diff --git a/DEPS b/DEPS index 9012adbf..60b5743 100644 --- a/DEPS +++ b/DEPS
@@ -182,11 +182,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': '93f1a38fb5b9bb359c98e96350de1e0a5607a212', + 'skia_revision': '64c8b811b55aeb3c077dac0e32a12a3b40b1c128', # 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': 'd77fdbe06bbdba723b8d84ce6a6afc24497ee515', + 'v8_revision': 'e02ac97561412ebf74a1b3b59b0ae0d3402ec882', # 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. @@ -194,7 +194,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': '086a04058cba6557742a7239b2fba15c9fd6e379', + 'angle_revision': 'ebc6d0a4b9ecfb11275afa22f687378ab6a79e02', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -253,7 +253,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'b6a8b828fd50207129c51ddd177eb8bc1cebd388', + 'devtools_frontend_revision': 'b711c4303271b22b26ca982f6317c8297e39daee', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -305,11 +305,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'adbf9153d909de0ac57141e0812ab88fe0ca5770', + 'dawn_revision': '0395ca9b6683367397ccf5c6d884720557279bd4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '6dfe58d86e8094f8a3277e05809b967c44662717', + 'quiche_revision': '4026f6e15a63e637df2a3c67ff9f7e1dc2cd2036', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -528,7 +528,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'be3c97421b9466ad0228dbace95dc9c15c752c04', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'da469c7660721d69f187f56db73ca76bc8868102', 'condition': 'checkout_ios', }, @@ -931,7 +931,7 @@ Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'bf190c43e5c7cc81751867c917a81bc2920be079', 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '78a3c915a1d70cf236588cc3c88f4db0566494a4', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '232ba0d848d19e385d719422435a041f6e08bb74', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1124,7 +1124,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + 'f80e888723942e821d7f89735ab71d96662f6aa2', + Var('chromium_git') + '/webm/libvpx.git' + '@' + 'c1765573149e2c0fe2acabc224c0f9085b9e7f2b', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + '51ca718c3adf0ddedacd7df25fe45f67dc5a9ce1', @@ -1207,7 +1207,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'a5473711f3e20c6bd1c33d81b6c7b9a0618aa18f', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + '724a60fb10c7042a3e00eb4f1cf25b41b88b0c8b', + Var('chromium_git') + '/openscreen' + '@' + 'c9201dd611b0aa8d66fe7ef2749c7ce0c157f0a1', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '9e97b73e7dd2bfc07745489d728f6a36665c648f', @@ -1224,7 +1224,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '890735b8c86dde8a30b2c0db1d2fe3d1d9c6ee1e', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '3d920083ed23e730aece1252ce18ef25bbe10256', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1452,7 +1452,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '43ccfecdb7681f8bfc160b70462f70c532a62269', + Var('webrtc_git') + '/src.git' + '@' + 'a4dfe24d7696145051c6929f778a100e6516d39c', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1524,7 +1524,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8278fd0af1066b278bc178a08c5afc5bc96ec7e1', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@91a2d1d0265380b7d984c9d759f01390d11ba262', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/AwDataDirLock.java b/android_webview/java/src/org/chromium/android_webview/AwDataDirLock.java index 3910ed2..d881df72 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwDataDirLock.java +++ b/android_webview/java/src/org/chromium/android_webview/AwDataDirLock.java
@@ -33,7 +33,9 @@ private static final String TAG = "AwDataDirLock"; private static final String EXCLUSIVE_LOCK_FILE = "webview_data.lock"; - private static final int LOCK_RETRIES = 5; + + // This results in a maximum wait time of 1.5s + private static final int LOCK_RETRIES = 16; private static final int LOCK_SLEEP_MS = 100; private static RandomAccessFile sLockFile; @@ -75,7 +77,7 @@ throw new RuntimeException("Failed to create lock file " + lockFile, e); } - // Some Android versions may have a race where a new instance of an app process can + // Android versions before 11 have edge cases where a new instance of an app process can // be started while an existing one is still in the process of being killed. Retry // the lock a few times to give the old process time to fully go away. for (int attempts = 1; attempts <= LOCK_RETRIES; ++attempts) {
diff --git a/ash/app_list/views/assistant/assistant_page_view.cc b/ash/app_list/views/assistant/assistant_page_view.cc index afbf7af..5e60ec5 100644 --- a/ash/app_list/views/assistant/assistant_page_view.cc +++ b/ash/app_list/views/assistant/assistant_page_view.cc
@@ -184,7 +184,12 @@ void AssistantPageView::OnShown() { // The preferred size might be different from the previous time, so updating // to the correct size here. - SetSize(CalculatePreferredSize()); + const gfx::Size size = CalculatePreferredSize(); + SetSize(size); + + // Our |size| may require a change in app list state in order to ensure that + // the AssistantPageView renders fully on screen w/o being clipped. + MaybeUpdateAppListState(size.height()); } void AssistantPageView::OnAnimationStarted(AppListState from_state, @@ -301,13 +306,14 @@ void AssistantPageView::MaybeUpdateAppListState(int child_height) { auto* app_list_view = contents_view_->app_list_view(); auto* widget = app_list_view->GetWidget(); + // |app_list_view| may not be initialized. if (!widget || !widget->IsVisible()) return; // Update app list view state for |assistant_page_view_|. - // Embedded Assistant Ui only has two sizes. The only states change is from - // kPeeking to kHalf state. + // Embedded Assistant Ui only has two sizes. The only state change is from + // |kPeeking| to |kHalf| state. if (app_list_view->app_list_state() != AppListViewState::kPeeking) return;
diff --git a/ash/app_list/views/assistant/assistant_page_view_unittest.cc b/ash/app_list/views/assistant/assistant_page_view_unittest.cc index f3a541c..2cd7e5f1 100644 --- a/ash/app_list/views/assistant/assistant_page_view_unittest.cc +++ b/ash/app_list/views/assistant/assistant_page_view_unittest.cc
@@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ash/app_list/views/app_list_view.h" #include "ash/assistant/model/assistant_ui_model.h" #include "ash/assistant/test/assistant_ash_test_base.h" #include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/main_stage/suggestion_chip_view.h" +#include "ash/public/cpp/app_list/app_list_types.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" @@ -234,6 +236,26 @@ } // namespace +TEST_F(AssistantPageViewTest, ShouldStartInPeekingState) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + chromeos::assistant::features::kAssistantBetterOnboarding); + + ShowAssistantUi(); + + EXPECT_EQ(AppListViewState::kPeeking, app_list_view()->app_list_state()); +} + +TEST_F(AssistantPageViewTest, ShouldStartInHalfState) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + chromeos::assistant::features::kAssistantBetterOnboarding); + + ShowAssistantUi(); + + EXPECT_EQ(AppListViewState::kHalf, app_list_view()->app_list_state()); +} + TEST_F(AssistantPageViewTest, ShouldStartAtMinimumHeight) { ShowAssistantUi();
diff --git a/ash/app_list/views/assistant/assistant_test_api_impl.cc b/ash/app_list/views/assistant/assistant_test_api_impl.cc index 14fb114..a6829f7 100644 --- a/ash/app_list/views/assistant/assistant_test_api_impl.cc +++ b/ash/app_list/views/assistant/assistant_test_api_impl.cc
@@ -108,8 +108,8 @@ return main_view()->GetWidget()->GetNativeWindow(); } -views::View* AssistantTestApiImpl::app_list_view() { - return static_cast<views::View*>(contents_view()->app_list_view()); +AppListView* AssistantTestApiImpl::app_list_view() { + return contents_view()->app_list_view(); } aura::Window* AssistantTestApiImpl::root_window() {
diff --git a/ash/app_list/views/assistant/assistant_test_api_impl.h b/ash/app_list/views/assistant/assistant_test_api_impl.h index aedb263..3eb1ee6 100644 --- a/ash/app_list/views/assistant/assistant_test_api_impl.h +++ b/ash/app_list/views/assistant/assistant_test_api_impl.h
@@ -49,7 +49,7 @@ views::View* onboarding_view() override; views::View* opt_in_view() override; aura::Window* window() override; - views::View* app_list_view() override; + AppListView* app_list_view() override; aura::Window* root_window() override; private:
diff --git a/ash/app_menu/app_menu_model_adapter.cc b/ash/app_menu/app_menu_model_adapter.cc index aa84b06f2..3a440161 100644 --- a/ash/app_menu/app_menu_model_adapter.cc +++ b/ash/app_menu/app_menu_model_adapter.cc
@@ -5,12 +5,12 @@ #include "ash/app_menu/app_menu_model_adapter.h" #include "ash/app_menu/notification_menu_controller.h" +#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/shelf_model.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/base/models/simple_menu_model.h" -#include "ui/base/ui_base_features.h" #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/controls/menu/menu_model_adapter.h" #include "ui/views/controls/menu/menu_runner.h" @@ -65,7 +65,7 @@ menu_open_time_ = base::TimeTicks::Now(); root_ = CreateMenu(); - if (features::IsNotificationIndicatorEnabled()) { + if (ash::features::IsNotificationsInContextMenuEnabled()) { notification_menu_controller_ = std::make_unique<NotificationMenuController>(app_id_, root_, this); }
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index cb94dd1..f6764b6 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1682,6 +1682,9 @@ <message name="IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLED" desc="The message to display in the network list when mobile data is turned off."> Mobile data is turned off. </message> + <message name="IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLING" desc="The message to display in the network list when mobile data is turning off (disabling)."> + Mobile data is turning off... + </message> <message name="IDS_ASH_STATUS_TRAY_VPN_DISCONNECTED" desc="The label used in system tray bubble to display vpn is disconnected."> VPN disconnected </message>
diff --git a/ash/assistant/test/assistant_ash_test_base.cc b/ash/assistant/test/assistant_ash_test_base.cc index 513a0ad88..7980034 100644 --- a/ash/assistant/test/assistant_ash_test_base.cc +++ b/ash/assistant/test/assistant_ash_test_base.cc
@@ -195,7 +195,7 @@ return test_api_->page_view(); } -views::View* AssistantAshTestBase::app_list_view() { +AppListView* AssistantAshTestBase::app_list_view() { return test_api_->app_list_view(); }
diff --git a/ash/assistant/test/assistant_ash_test_base.h b/ash/assistant/test/assistant_ash_test_base.h index b146fec..3218ec48 100644 --- a/ash/assistant/test/assistant_ash_test_base.h +++ b/ash/assistant/test/assistant_ash_test_base.h
@@ -27,6 +27,7 @@ namespace ash { +class AppListView; class AssistantTestApi; class SuggestionChipView; class TestAssistantClient; @@ -87,7 +88,7 @@ // Return the app list view hosting the Assistant page view. // Can only be used after |ShowAssistantUi| has been called. - views::View* app_list_view(); + AppListView* app_list_view(); // Return the root view hosting the Assistant page view. // Can only be used after |ShowAssistantUi| has been called.
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index f1ed855e..0729f86 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -130,6 +130,9 @@ const base::Feature kShelfAppScaling{"ShelfAppScaling", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kNotificationsInContextMenu{ + "NotificationsInContextMenu", base::FEATURE_DISABLED_BY_DEFAULT}; + bool IsAllowAmbientEQEnabled() { return base::FeatureList::IsEnabled(kAllowAmbientEQ); } @@ -277,6 +280,10 @@ chromeos::switches::ShouldShowShelfHotseat(); } +bool IsNotificationsInContextMenuEnabled() { + return base::FeatureList::IsEnabled(kNotificationsInContextMenu); +} + namespace { // The boolean flag indicating if "WebUITabStrip" feature is enabled in Chrome.
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index df82054..0cfa7e5 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -166,6 +166,9 @@ // right now since it is under development. ASH_PUBLIC_EXPORT extern const base::Feature kWebUITabStripTabDragIntegration; +// Enables notifications to be shown within context menus. +ASH_PUBLIC_EXPORT extern const base::Feature kNotificationsInContextMenu; + ASH_PUBLIC_EXPORT bool IsAllowAmbientEQEnabled(); ASH_PUBLIC_EXPORT bool IsAltTabLimitedToActiveDesk(); @@ -230,6 +233,8 @@ ASH_PUBLIC_EXPORT bool IsAppScalingEnabled(); +ASH_PUBLIC_EXPORT bool IsNotificationsInContextMenuEnabled(); + // These two functions are supposed to be temporary functions to set or get // whether "WebUITabStrip" feature is enabled from Chrome. ASH_PUBLIC_EXPORT void SetWebUITabStripEnabled(bool enabled);
diff --git a/ash/public/cpp/test/assistant_test_api.h b/ash/public/cpp/test/assistant_test_api.h index e531317..89c10cf 100644 --- a/ash/public/cpp/test/assistant_test_api.h +++ b/ash/public/cpp/test/assistant_test_api.h
@@ -22,6 +22,7 @@ namespace ash { +class AppListView; class AssistantState; // Public test API for the Assistant UI. @@ -120,7 +121,7 @@ // Returns the app list view hosting the Assistant UI. // Can only be used after the Assistant UI has been shown at least once. - virtual views::View* app_list_view() = 0; + virtual AppListView* app_list_view() = 0; // Returns the root window containing the Assistant UI (and the Ash shell). // This can be used even when the Assistant UI has never been shown.
diff --git a/ash/quick_answers/quick_answers_controller_impl.cc b/ash/quick_answers/quick_answers_controller_impl.cc index 8b006e7..189c35c7 100644 --- a/ash/quick_answers/quick_answers_controller_impl.cc +++ b/ash/quick_answers/quick_answers_controller_impl.cc
@@ -117,6 +117,9 @@ kNoResult)); quick_answers_ui_controller_->RenderQuickAnswersViewWithResult( anchor_bounds_, quick_answer_with_no_result); + // Fallback query to title if no result is available. + query_ = title_; + quick_answers_ui_controller_->SetActiveQuery(query_); } quick_answer_ = std::move(quick_answer);
diff --git a/ash/strings/ash_strings_ar.xtb b/ash/strings/ash_strings_ar.xtb index 014e9551..6a2ed86 100644 --- a/ash/strings/ash_strings_ar.xtb +++ b/ash/strings/ash_strings_ar.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">بدء طلب بحث صوتي</translation> <translation id="1658406695958299976">عذرًا، لا يمكن التحقق من كلمة المرور حتى الآن. ملاحظة: في حال تغيير كلمة المرور مؤخرًا، سيتم تطبيق كلمة المرور الجديدة بعد تسجيل الخروج، يُرجى استخدام كلمة المرور القديمة هنا.</translation> <translation id="1677472565718498478">الوقت المتبقي <ph name="TIME" /></translation> +<translation id="1698080062160024910">مؤقت <ph name="TOTAL_TIME" /> <ph name="LABEL" /></translation> <translation id="1698760176351776263">عنوان IPv6: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">إعدادات الشبكة</translation> <translation id="1743570585616704562">لم يتم التعرف عليها</translation> @@ -335,6 +336,7 @@ <translation id="4924411785043111640">إعادة التشغيل وإعادة الضبط</translation> <translation id="495046168593986294">التمرير لأعلى</translation> <translation id="4961318399572185831">إرسال الشاشة</translation> +<translation id="4969092041573468113"><ph name="HOURS" /> س <ph name="MINUTES" /> د <ph name="SECONDS" /> ث</translation> <translation id="5030687792513154421">انتهى الوقت</translation> <translation id="5035236842988137213">الجهاز <ph name="DEVICE_NAME" /> متصل بهاتف جديد</translation> <translation id="5035389544768382859">تأكيد ضبط شاشة العرض</translation> @@ -620,10 +622,12 @@ <translation id="8517041960877371778">قد يتعذر شحن <ph name="DEVICE_TYPE" /> أثناء التشغيل.</translation> <translation id="8563862697512465947">إعدادات الاشعارات</translation> <translation id="857201607579416096">تم نقل القائمة إلى أسفل يسار الشاشة.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455">تم الاتصال بجهاز <ph name="DEVICE_NAME" /></translation> <translation id="8631727435199967028">إعدادات "سهولة الاستخدام"</translation> <translation id="8637598503828012618">حالة الاتصال <ph name="CONNECTION_STATUS" />، قوة الإشارة <ph name="SIGNAL_STRENGTH" />، يديرها المشرف</translation> <translation id="8639760480004882931">يتبقى <ph name="PERCENTAGE" /></translation> +<translation id="8646417893960517480">موقّت <ph name="TOTAL_TIME" /></translation> <translation id="8649101189709089199">الاختيار والاستماع</translation> <translation id="8652175077544655965">غلق الإعدادات</translation> <translation id="8653151467777939995">عرض إعدادات الإشعارات. تم تفعيل الإشعارات</translation>
diff --git a/ash/strings/ash_strings_az.xtb b/ash/strings/ash_strings_az.xtb index 02b5dcef3..a509396 100644 --- a/ash/strings/ash_strings_az.xtb +++ b/ash/strings/ash_strings_az.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">Səsli sorğuya başlayın</translation> <translation id="1658406695958299976">Parolunuz hələ də doğrulanmayıb. Qeyd: əgər parolunuzu son vaxtlar dəyişmisinizsə, hesabdan çıxan kimi yeni parolunuz tətbiq olunacaq, köhnə parolu burada işlədin.</translation> <translation id="1677472565718498478"><ph name="TIME" /> qaldı</translation> +<translation id="1698080062160024910"><ph name="TOTAL_TIME" /> taymeri · <ph name="LABEL" /></translation> <translation id="1698760176351776263">IPv6 ünvanı: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">Şəbəkə Ayarları</translation> <translation id="1743570585616704562">Tanınmır</translation> @@ -262,6 +263,7 @@ <translation id="4017989525502048489">Lazer göstəricisi</translation> <translation id="4021716437419160885">Aşağı sürüşdürün</translation> <translation id="4028481283645788203">Əlavə təhlükəsizlik üçün parol tələb olunur</translation> +<translation id="4032485810211612751"><ph name="HOURS" />:<ph name="MINUTES" />:<ph name="SECONDS" /></translation> <translation id="4042660782729322247">Ekranı paylaşırsınız</translation> <translation id="4065525899979931964">{NUM_APPS,plural, =1{Tətbiqdə deaktivdir}other{# tətbiqdə deaktivdir}}</translation> <translation id="4072264167173457037">Ortaq siqnal</translation> @@ -334,6 +336,7 @@ <translation id="4924411785043111640">Yenidən başlayın və sıfırlayın</translation> <translation id="495046168593986294">Yuxarı sürüşdürün</translation> <translation id="4961318399572185831">Cast ekran</translation> +<translation id="4969092041573468113"><ph name="HOURS" />s <ph name="MINUTES" />dəq <ph name="SECONDS" />san</translation> <translation id="5030687792513154421">Vaxt bitdi</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> yeni telefona qoşuldu</translation> <translation id="5035389544768382859">Displey Konfiqurasiyasını təsdiq edin</translation> @@ -618,10 +621,12 @@ <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> cihazınız aktiv olan zaman elektrik yığmaya bilər.</translation> <translation id="8563862697512465947">Bildiriş Ayarları</translation> <translation id="857201607579416096">Menyu ekranın aşağı sağ küncünə köçürülüb.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455"><ph name="DEVICE_NAME" /> şəbəkəsinə qoşuldunuz</translation> <translation id="8631727435199967028">Əlçatımlılıq Ayarları</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, Siqnal Gücü <ph name="SIGNAL_STRENGTH" />, Administratorunuz tərəfindən idarə olunur</translation> <translation id="8639760480004882931"><ph name="PERCENTAGE" /> qalıb</translation> +<translation id="8646417893960517480"><ph name="TOTAL_TIME" /> taymeri</translation> <translation id="8649101189709089199">Səsləndirmək üçün seçim</translation> <translation id="8652175077544655965">Ayarları bağlayın</translation> <translation id="8653151467777939995">Bildiriş ayarlarını göstərin. Bildirişlər aktivdir</translation>
diff --git a/ash/strings/ash_strings_hi.xtb b/ash/strings/ash_strings_hi.xtb index eb949fc7..fcf95bf 100644 --- a/ash/strings/ash_strings_hi.xtb +++ b/ash/strings/ash_strings_hi.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">बोलकर खोजना शुरू करें</translation> <translation id="1658406695958299976">माफ़ करें, आपके पासवर्ड की अब भी पुष्टि नहीं हो पाई है. नोट: अगर आपने हाल ही में अपना पासवर्ड बदला है, तो आपके साइन आउट होते ही आपका नया पासवर्ड लागू हो जाएगा, कृपया यहां पुराने पासवर्ड का इस्तेमाल करें.</translation> <translation id="1677472565718498478"><ph name="TIME" /> बाकी</translation> +<translation id="1698080062160024910"><ph name="TOTAL_TIME" /> टाइमर · <ph name="LABEL" /></translation> <translation id="1698760176351776263">IPv6 पता: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">नेटवर्क सेटिंग</translation> <translation id="1743570585616704562">उंगली की पहचान नहीं हो सकी</translation> @@ -336,6 +337,7 @@ <translation id="4924411785043111640">रीस्टार्ट करें और रीसेट करें</translation> <translation id="495046168593986294">ऊपर स्क्रोल करें</translation> <translation id="4961318399572185831">स्क्रीन कास्ट करें</translation> +<translation id="4969092041573468113"><ph name="HOURS" />घं॰ <ph name="MINUTES" />मि॰ <ph name="SECONDS" />से॰</translation> <translation id="5030687792513154421">समय पूरा हो गया</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> एक नए फ़ोन से कनेक्ट हो गया है</translation> <translation id="5035389544768382859">डिसप्ले के कॉन्फ़िगरेशन की पुष्टि करें</translation> @@ -620,10 +622,12 @@ <translation id="8517041960877371778">हो सकता है आपका <ph name="DEVICE_TYPE" /> चालू होने पर चार्ज नहीं होता हो.</translation> <translation id="8563862697512465947">सूचना सेटिंग</translation> <translation id="857201607579416096">मेन्यू, स्क्रीन के सबसे नीचे दाएं कोने में चला गया है.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455"><ph name="DEVICE_NAME" /> से कनेक्ट है</translation> <translation id="8631727435199967028">सुलभता सेटिंग</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, सिग्नल की क्षमता <ph name="SIGNAL_STRENGTH" />, आपका एडमिन प्रबंधित करता है</translation> <translation id="8639760480004882931"><ph name="PERCENTAGE" /> बाकी</translation> +<translation id="8646417893960517480"><ph name="TOTAL_TIME" /> टाइमर</translation> <translation id="8649101189709089199">चुनें और सुनें</translation> <translation id="8652175077544655965">सेटिंग बंद करें</translation> <translation id="8653151467777939995">सूचना सेटिंग दिखाएं. सूचनाएं चालू हैं</translation>
diff --git a/ash/strings/ash_strings_iw.xtb b/ash/strings/ash_strings_iw.xtb index f073052..bb2bdf2 100644 --- a/ash/strings/ash_strings_iw.xtb +++ b/ash/strings/ash_strings_iw.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">הפעלה של שאילתה קולית</translation> <translation id="1658406695958299976">מצטערים, עדיין אי אפשר לאמת את הסיסמה שלך. חשוב לדעת: אם שינית לאחרונה את הסיסמה, הסיסמה החדשה תיכנס לתוקף רק אחרי יציאה מהחשבון. צריך להשתמש כאן בסיסמה הישנה.</translation> <translation id="1677472565718498478">זמן נותר - <ph name="TIME" /></translation> +<translation id="1698080062160024910">טיימר של <ph name="TOTAL_TIME" /> · <ph name="LABEL" /></translation> <translation id="1698760176351776263">כתובת IPv6: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">הגדרות רשת</translation> <translation id="1743570585616704562">לא מזוהה</translation> @@ -335,6 +336,7 @@ <translation id="4924411785043111640">הפעלה מחדש ואתחול</translation> <translation id="495046168593986294">גלילה למעלה</translation> <translation id="4961318399572185831">העברת מסך</translation> +<translation id="4969092041573468113"><ph name="HOURS" /> שעות <ph name="MINUTES" /> דקות <ph name="SECONDS" /> שניות</translation> <translation id="5030687792513154421">נגמר הזמן</translation> <translation id="5035236842988137213">מכשיר <ph name="DEVICE_NAME" /> התחבר לטלפון חדש</translation> <translation id="5035389544768382859">אישור הגדרת המסך</translation> @@ -621,10 +623,12 @@ <translation id="8517041960877371778">ייתכן שה-<ph name="DEVICE_TYPE" /> לא ייטען כשהוא פועל.</translation> <translation id="8563862697512465947">הגדרות התראה</translation> <translation id="857201607579416096">התפריט הועבר לפינה השמאלית התחתונה של המסך.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455">יש חיבור אל <ph name="DEVICE_NAME" /></translation> <translation id="8631727435199967028">הגדרות נגישות</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, עוצמת האות: <ph name="SIGNAL_STRENGTH" />, הרשת מנוהלת על ידי מנהל המערכת</translation> <translation id="8639760480004882931">שיעור טעינה נותר - <ph name="PERCENTAGE" /></translation> +<translation id="8646417893960517480">טיימר של <ph name="TOTAL_TIME" /></translation> <translation id="8649101189709089199">הקראה</translation> <translation id="8652175077544655965">סגירת ההגדרות</translation> <translation id="8653151467777939995">צפייה בהגדרות של הודעות. ההודעות מופעלות</translation>
diff --git a/ash/strings/ash_strings_kk.xtb b/ash/strings/ash_strings_kk.xtb index 80a1ac9..1861d110 100644 --- a/ash/strings/ash_strings_kk.xtb +++ b/ash/strings/ash_strings_kk.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">Дауыстық сұрауды бастау</translation> <translation id="1658406695958299976">Өкінішке орай, құпия сөзіңіз расталмады. Ескерту: жақында құпия сөзіңізді өзгерткен болсаңыз, жаңа құпия сөзіңіз жүйеден шыққаннан кейін қолданылады, бұл жерде ескі құпия сөзіңізді пайдаланыңыз.</translation> <translation id="1677472565718498478"><ph name="TIME" /> қалды</translation> +<translation id="1698080062160024910"><ph name="TOTAL_TIME" /> таймер · <ph name="LABEL" /></translation> <translation id="1698760176351776263">IPv6 мекенжайы: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">Желі параметрлері</translation> <translation id="1743570585616704562">Анықталмады</translation> @@ -262,6 +263,7 @@ <translation id="4017989525502048489">Лазер меңзер</translation> <translation id="4021716437419160885">Төменге айналдыру</translation> <translation id="4028481283645788203">Қауіпсіздікті күшейту үшін құпия сөзді енгізу қажет.</translation> +<translation id="4032485810211612751"><ph name="HOURS" />:<ph name="MINUTES" />:<ph name="SECONDS" /></translation> <translation id="4042660782729322247">Экранды бөлісудесіз</translation> <translation id="4065525899979931964">{NUM_APPS,plural, =1{Қолданба үшін өшірулі}other{# қолданба үшін өшірулі}}</translation> <translation id="4072264167173457037">Орташа сигнал</translation> @@ -334,6 +336,7 @@ <translation id="4924411785043111640">Қайта қосу және бастапқы күйге қайтару</translation> <translation id="495046168593986294">Жоғарыға айналдыру</translation> <translation id="4961318399572185831">Экран трансляциясы</translation> +<translation id="4969092041573468113"><ph name="HOURS" />с <ph name="MINUTES" />м <ph name="SECONDS" />с</translation> <translation id="5030687792513154421">Уақыт бітті</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> жаңа телефонға жалғанды</translation> <translation id="5035389544768382859">Дисплей конфигурациясын растау</translation> @@ -618,10 +621,12 @@ <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> іске қосылғанда зарядталмауы мүмкін.</translation> <translation id="8563862697512465947">Хабарландыру параметрлері</translation> <translation id="857201607579416096">Мәзір экранның төменгі оң жақ бұрышына жылжытылды.</translation> +<translation id="8594115950068821369">–<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455"><ph name="DEVICE_NAME" /> құрылғысына жалғанған</translation> <translation id="8631727435199967028">Арнайы мүмкіндіктер параметрлері</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, сигнал күші: <ph name="SIGNAL_STRENGTH" />, әкімші басқарады</translation> <translation id="8639760480004882931"><ph name="PERCENTAGE" /> қалды</translation> +<translation id="8646417893960517480"><ph name="TOTAL_TIME" /> таймер</translation> <translation id="8649101189709089199">Select-to-Speak</translation> <translation id="8652175077544655965">Параметрлерді жабу</translation> <translation id="8653151467777939995">Хабарландыру параметрлерін көрсету. Хабарландырулар қосулы</translation>
diff --git a/ash/strings/ash_strings_ky.xtb b/ash/strings/ash_strings_ky.xtb index 444e24c..acc800d 100644 --- a/ash/strings/ash_strings_ky.xtb +++ b/ash/strings/ash_strings_ky.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">Айтып издеп баштоо</translation> <translation id="1658406695958299976">Кечиресиз, сырсөзүңүздү текшерүү дагы эле мүмкүн болбой жатат. Эскертүү: эгер сырсөзүңүздү жакында өзгөрткөн болсоңуз, жаңы сырсөзүңүз чыгып кайра киргениңизден кийин гана колдонулат, андыктан бул жерде эски сырсөздү колдонуңуз.</translation> <translation id="1677472565718498478"><ph name="TIME" /> калды</translation> +<translation id="1698080062160024910"><ph name="TOTAL_TIME" /> таймер · <ph name="LABEL" /></translation> <translation id="1698760176351776263">IPv6 дареги: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">Тармак жөндөөлөрү</translation> <translation id="1743570585616704562">Таанылган жок</translation> @@ -335,6 +336,7 @@ <translation id="4924411785043111640">Өчүрүп-күйгүзүү жана баштапкы абалга келтирүү</translation> <translation id="495046168593986294">Өйдө сыдыруу</translation> <translation id="4961318399572185831">Экранды тышкы экранга чыгаруу</translation> +<translation id="4969092041573468113"><ph name="HOURS" /> с. <ph name="MINUTES" /> мүн. <ph name="SECONDS" /> сек.</translation> <translation id="5030687792513154421">Убакыт бүттү</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> жаңы телефонго туташты</translation> <translation id="5035389544768382859">Дисплейдин конфигурациясын ырастоо</translation> @@ -619,10 +621,12 @@ <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> түзмөгүңүз өчүп турганда кубатталбай калышы мүмкүн.</translation> <translation id="8563862697512465947">Билдирмелердин жөндөөлөрү</translation> <translation id="857201607579416096">Меню экрандын төмөнкү оң бурчуна жылдырылды.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455"><ph name="DEVICE_NAME" /> менен туташты</translation> <translation id="8631727435199967028">Атайын мүмкүнчүлүктөрдүн жөндөөлөрү</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, Сигналдын күчү <ph name="SIGNAL_STRENGTH" />, Администраторуңуз башкарат</translation> <translation id="8639760480004882931"><ph name="PERCENTAGE" /> калды</translation> +<translation id="8646417893960517480"><ph name="TOTAL_TIME" /> таймер</translation> <translation id="8649101189709089199">Басып туруп угуңуз</translation> <translation id="8652175077544655965">Жөндөөлөрдү жабуу</translation> <translation id="8653151467777939995">Билдирмелердин жөндөөлөрүн көрсөтүү. Билдирмелер күйүк</translation>
diff --git a/ash/strings/ash_strings_lo.xtb b/ash/strings/ash_strings_lo.xtb index 2ca886d1..9e5a5b6 100644 --- a/ash/strings/ash_strings_lo.xtb +++ b/ash/strings/ash_strings_lo.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">ເລີ່ມຄຳຊອກຫາດ້ວຍສຽງ</translation> <translation id="1658406695958299976">ຂໍອະໄພ, ຍັງບໍ່ສາມາດພິສູດຢືນຢັນລະຫັດຜ່ານຂອງທ່ານໄດ້. ໝາຍເຫດ: ຖ້າທ່ານປ່ຽນລະຫັດຜ່ານຂອງທ່ານເມື່ອບໍ່ດົນມານີ້, ຈະນຳໃຊ້ລະຫັດຜ່ານໃໝ່ຂອງທ່ານເມື່ອທ່ານອອກຈາກລະບົບແລ້ວ, ກະລຸນາໃຊ້ລະຫັດເກົ່າຢູ່ບ່ອນນີ້.</translation> <translation id="1677472565718498478">ຍັງເຫຼືອ <ph name="TIME" /></translation> +<translation id="1698080062160024910">ໂມງນັບຖອຍຫຼັງ <ph name="TOTAL_TIME" /> · <ph name="LABEL" /></translation> <translation id="1698760176351776263">ທີ່ຢູ່ IPv6: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">ການຕັ້ງຄ່າເຄືອຂ່າຍ</translation> <translation id="1743570585616704562">ບໍ່ຮັບຮູ້</translation> @@ -335,6 +336,7 @@ <translation id="4924411785043111640">ປິດເປີດຄືນໃໝ່ ແລະ ຣິເຊັດ</translation> <translation id="495046168593986294">ເລື່ອນຂຶ້ນ</translation> <translation id="4961318399572185831">ຄາສທ໌ໜ້າຈໍ</translation> +<translation id="4969092041573468113"><ph name="HOURS" />ຊມ <ph name="MINUTES" />ນທ <ph name="SECONDS" />ວິ</translation> <translation id="5030687792513154421">ໝົດເວລາແລ້ວ</translation> <translation id="5035236842988137213">ເຊື່ອມຕໍ່ <ph name="DEVICE_NAME" />ກັບໂທລະສັບໃໝ່ແລ້ວ</translation> <translation id="5035389544768382859">ຢືນຢັນການຕັ້ງຄ່າຈໍສະແດງຜົນ</translation> @@ -619,10 +621,12 @@ <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> ຂອງທ່ານບໍ່ອາດສາກໄດ້ໃນຂະນະທີ່ມັນເປີດ.</translation> <translation id="8563862697512465947">ການຕັ້ງຄ່າການແຈ້ງເຕືອນ</translation> <translation id="857201607579416096">ຍ້າຍເມນູໄປແຈລຸ່ມສຸດເບື້ອງຂວາຂອງໜ້າຈໍ.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455">ເຊື່ອມຕໍ່ກັບ <ph name="DEVICE_NAME" /> ແລ້ວ</translation> <translation id="8631727435199967028">ການຕັ້ງຄ່າການຊ່ວຍເຂົ້າເຖິງ</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, ຄວາມແຮງສັນຍານ <ph name="SIGNAL_STRENGTH" />, ຈັດການໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ</translation> <translation id="8639760480004882931">ຍັງເຫຼືອ <ph name="PERCENTAGE" /></translation> +<translation id="8646417893960517480">ໂມງນັບຖອຍຫຼັງ <ph name="TOTAL_TIME" /></translation> <translation id="8649101189709089199">ເລືອກເພື່ອເວົ້າ</translation> <translation id="8652175077544655965">ປິດການຕັ້ງຄ່າ</translation> <translation id="8653151467777939995">ສະແດງການຕັ້ງຄ່າການແຈ້ງເຕືອນ. ການແຈ້ງເຕືອນເປີດຢູ່</translation>
diff --git a/ash/strings/ash_strings_mk.xtb b/ash/strings/ash_strings_mk.xtb index aa47cb7..ddf5307 100644 --- a/ash/strings/ash_strings_mk.xtb +++ b/ash/strings/ash_strings_mk.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">Започнете гласовно барање</translation> <translation id="1658406695958299976">За жал, вашата лозинка сепак не можеше да се потврди. Белешка: ако сте ја промениле лозинката неодамна, новата лозинка ќе се примени откако ќе се одјавите. Користете ја старата лозинка тука.</translation> <translation id="1677472565718498478">Уште <ph name="TIME" /></translation> +<translation id="1698080062160024910">Тајмер за <ph name="TOTAL_TIME" /> · <ph name="LABEL" /></translation> <translation id="1698760176351776263">IPv6 адреса: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">Поставки за мрежата</translation> <translation id="1743570585616704562">Не е препознаен</translation> @@ -336,6 +337,7 @@ <translation id="4924411785043111640">Рестартирај и ресетирај</translation> <translation id="495046168593986294">Оди нагоре</translation> <translation id="4961318399572185831">Емитувај го екранот</translation> +<translation id="4969092041573468113"><ph name="HOURS" /> ч. <ph name="MINUTES" /> м. <ph name="SECONDS" /> с.</translation> <translation id="5030687792513154421">Времето истече</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> е поврзан со нов телефон</translation> <translation id="5035389544768382859">Потврдете ја конфигурацијата на екранот</translation> @@ -620,10 +622,12 @@ <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> може да не се полни додека е вклучен.</translation> <translation id="8563862697512465947">Поставки за известувања</translation> <translation id="857201607579416096">Менито е преместено во долниот десен агол на екранот.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455">Поврзан со <ph name="DEVICE_NAME" /></translation> <translation id="8631727435199967028">Поставки за пристапност</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, јачина на сигналот: <ph name="SIGNAL_STRENGTH" />, управувана од администраторот</translation> <translation id="8639760480004882931">Преостануваат <ph name="PERCENTAGE" /></translation> +<translation id="8646417893960517480">Тајмер за <ph name="TOTAL_TIME" /></translation> <translation id="8649101189709089199">Изберете за говор</translation> <translation id="8652175077544655965">Затворете ги поставките</translation> <translation id="8653151467777939995">Прикажи ги поставките за известувања. Известувањата се вклучени</translation>
diff --git a/ash/strings/ash_strings_ta.xtb b/ash/strings/ash_strings_ta.xtb index 9f74420..8ad3103 100644 --- a/ash/strings/ash_strings_ta.xtb +++ b/ash/strings/ash_strings_ta.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">குரல் வினவலைத் தொடங்கு</translation> <translation id="1658406695958299976">மன்னிக்கவும், உங்கள் கடவுச்சொல் இன்னும் சரிபார்க்கப்படவில்லை. குறிப்பு: உங்கள் கடவுச்சொல்லைச் சமீபத்தில் மாற்றியிருந்தால், நீங்கள் வெளியேறியவுடன் புதிய கடவுச்சொல் பயன்படுத்தப்படும், இங்கு பழைய கடவுச்சொல்லைப் பயன்படுத்தவும்.</translation> <translation id="1677472565718498478"><ph name="TIME" /> மணி நேரம்</translation> +<translation id="1698080062160024910"><ph name="TOTAL_TIME" /> டைமர் · <ph name="LABEL" /></translation> <translation id="1698760176351776263">IPv6 முகவரி: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">நெட்வொர்க் அமைப்புகள்</translation> <translation id="1743570585616704562">அடையாளங்காண முடியவில்லை</translation> @@ -335,6 +336,7 @@ <translation id="4924411785043111640">மீண்டும் தொடங்கி, மீட்டமை</translation> <translation id="495046168593986294">மேலே நகர்த்து</translation> <translation id="4961318399572185831">திரையை அலைபரப்பு</translation> +<translation id="4969092041573468113"><ph name="HOURS" />ம <ph name="MINUTES" />நி <ph name="SECONDS" />வி</translation> <translation id="5030687792513154421">நேரம் முடிந்தது</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ஒரு புதிய ஃபோனுடன் இணைக்கப்பட்டுள்ளது</translation> <translation id="5035389544768382859">திரை உள்ளமைவை உறுதிசெய்யுங்கள்</translation> @@ -619,10 +621,12 @@ <translation id="8517041960877371778">இயக்கப்பட்டிருக்கும் போது உங்கள் <ph name="DEVICE_TYPE" /> இல் சார்ஜ் ஏறாது.</translation> <translation id="8563862697512465947">அறிவிப்பு அமைப்புகள்</translation> <translation id="857201607579416096">திரையின் கீழ் வலது மூலைக்கு மெனு நகர்த்தப்பட்டது.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455"><ph name="DEVICE_NAME" /> உடன் இணைக்கப்பட்டுள்ளது</translation> <translation id="8631727435199967028">அணுகல்தன்மை அமைப்புகள்</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, சிக்னல் வலிமை: <ph name="SIGNAL_STRENGTH" />, உங்கள் நிர்வாகி நிர்வகிக்கிறார்</translation> <translation id="8639760480004882931"><ph name="PERCENTAGE" /> மீதமுள்ளது</translation> +<translation id="8646417893960517480"><ph name="TOTAL_TIME" /> டைமர்</translation> <translation id="8649101189709089199">பேசும் திரை</translation> <translation id="8652175077544655965">அமைப்புகளை மூடும்</translation> <translation id="8653151467777939995">அறிவிப்பு அமைப்புகளைக் காண்பிக்கும். அறிவிப்புகள் இயக்கப்பட்டுள்ளன</translation>
diff --git a/ash/strings/ash_strings_te.xtb b/ash/strings/ash_strings_te.xtb index 245858d..7e316bd 100644 --- a/ash/strings/ash_strings_te.xtb +++ b/ash/strings/ash_strings_te.xtb
@@ -63,6 +63,7 @@ <translation id="1654477262762802994">వాయిస్ ప్రశ్నను ప్రారంభించు</translation> <translation id="1658406695958299976">క్షమించండి, మీ పాస్వర్డ్ ఇప్పటికీ ధృవీకరించబడలేదు. గమనిక: మీరు మీ పాస్వర్డ్ను ఇటీవల మార్చి ఉంటే, మీరు సైన్ అవుట్ చేసిన తర్వాత మీ కొత్త పాస్వర్డ్ వర్తించబడుతుంది, దయచేసి పాత పాస్వర్డ్ను ఇక్కడ ఉపయోగించండి.</translation> <translation id="1677472565718498478"><ph name="TIME" /> మిగిలి ఉంది</translation> +<translation id="1698080062160024910"><ph name="TOTAL_TIME" /> టైమర్ · <ph name="LABEL" /></translation> <translation id="1698760176351776263">IPv6 చిరునామా: <ph name="ADDRESS" /></translation> <translation id="1709762881904163296">నెట్వర్క్ సెట్టింగ్లు</translation> <translation id="1743570585616704562">గుర్తించలేదు</translation> @@ -336,6 +337,7 @@ <translation id="4924411785043111640">మళ్లీ ప్రారంభించి, రీసెట్ చేయండి</translation> <translation id="495046168593986294">పైకి స్క్రోల్ చేయి</translation> <translation id="4961318399572185831">స్క్రీన్ ప్రసారం చేయండి</translation> +<translation id="4969092041573468113"><ph name="HOURS" />గం <ph name="MINUTES" />ని <ph name="SECONDS" />సె</translation> <translation id="5030687792513154421">సమయం ముగిసింది</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ఒక కొత్త ఫోన్కి కనెక్ట్ చేయబడింది</translation> <translation id="5035389544768382859">డిస్ప్లే కాన్ఫిగరేషన్ను నిర్ధారించండి</translation> @@ -620,10 +622,12 @@ <translation id="8517041960877371778">మీ <ph name="DEVICE_TYPE" /> ఆన్లో ఉన్నప్పుడు ఛార్జ్ కాకపోవచ్చు.</translation> <translation id="8563862697512465947">నోటిఫికేషన్ సెట్టింగ్లు</translation> <translation id="857201607579416096">స్క్రీన్లో కింద కుడి వైపు మూలకు మెనూ తరలించబడింది.</translation> +<translation id="8594115950068821369">-<ph name="FORMATTED_TIME" /></translation> <translation id="8627191004499078455"><ph name="DEVICE_NAME" />కి కనెక్ట్ చేయబడింది</translation> <translation id="8631727435199967028">యాక్సెసిబిలిటీ సెట్టింగ్లు</translation> <translation id="8637598503828012618"><ph name="CONNECTION_STATUS" />, సిగ్నల్ సామర్థ్యం <ph name="SIGNAL_STRENGTH" />, మీ అడ్మినిస్ట్రేటర్ ద్వారా నిర్వహించబడుతోంది</translation> <translation id="8639760480004882931"><ph name="PERCENTAGE" /> మిగిలి ఉంది</translation> +<translation id="8646417893960517480"><ph name="TOTAL_TIME" /> టైమర్</translation> <translation id="8649101189709089199">వినడానికి ఎంచుకోండి</translation> <translation id="8652175077544655965">సెట్టింగ్లను మూసివేయండి</translation> <translation id="8653151467777939995">నోటిఫికేషన్ సెట్టింగ్లను చూపుతుంది. నోటిఫికేషన్లు ఆన్ చేయబడి ఉన్నాయి</translation>
diff --git a/ash/system/network/network_section_header_view.cc b/ash/system/network/network_section_header_view.cc index 6625442..c5443bd 100644 --- a/ash/system/network/network_section_header_view.cc +++ b/ash/system/network/network_section_header_view.cc
@@ -165,10 +165,15 @@ SetToggleVisibility(false); return IDS_ASH_STATUS_TRAY_SIM_CARD_MISSING; } - + bool toggle_enabled = default_toggle_enabled && + (cellular_state == DeviceStateType::kEnabled || + cellular_state == DeviceStateType::kDisabled); bool cellular_enabled = cellular_state == DeviceStateType::kEnabled; SetToggleVisibility(true); - SetToggleState(default_toggle_enabled, cellular_enabled); + SetToggleState(toggle_enabled, cellular_enabled); + if (cellular_state == DeviceStateType::kDisabling) { + return IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLING; + } if (cellular_device->sim_lock_status && !cellular_device->sim_lock_status->lock_type.empty()) {
diff --git a/ash/wm/desks/desk_mini_view_animations.cc b/ash/wm/desks/desk_mini_view_animations.cc index ac4f558..811fab8 100644 --- a/ash/wm/desks/desk_mini_view_animations.cc +++ b/ash/wm/desks/desk_mini_view_animations.cc
@@ -55,16 +55,15 @@ } } -// A self-deleting object that takes ownership of the |removed_mini_view| and -// performs a fade out animation on its layer by changing its opacity from 1 to -// 0, and deleting it and itself when the animation is complete. +// A self-deleting object that performs a fade out animation on +// |removed_mini_view|'s layer by changing its opacity from 1 to 0, +// and deleting |removed_mini_view| and itself when the animation is complete. // TODO(afakhry): Consider generalizing HidingWindowAnimationObserverBase to be // reusable for the mini_view removal animation. class RemovedMiniViewFadeOutAnimation : public ui::ImplicitAnimationObserver { public: - RemovedMiniViewFadeOutAnimation( - std::unique_ptr<DeskMiniView> removed_mini_view) - : removed_mini_view_(std::move(removed_mini_view)) { + RemovedMiniViewFadeOutAnimation(DeskMiniView* removed_mini_view) + : removed_mini_view_(removed_mini_view) { ui::Layer* layer = removed_mini_view_->layer(); ui::ScopedLayerAnimationSettings settings{layer->GetAnimator()}; InitScopedAnimationSettings(&settings, kRemovedMiniViewsFadeOutDuration); @@ -73,11 +72,16 @@ layer->SetOpacity(0); } + ~RemovedMiniViewFadeOutAnimation() override { + DCHECK(removed_mini_view_->parent()); + removed_mini_view_->parent()->RemoveChildViewT(removed_mini_view_); + } + // ui::ImplicitAnimationObserver: void OnImplicitAnimationsCompleted() override { delete this; } private: - std::unique_ptr<DeskMiniView> removed_mini_view_; + DeskMiniView* removed_mini_view_; DISALLOW_COPY_AND_ASSIGN(RemovedMiniViewFadeOutAnimation); }; @@ -108,8 +112,8 @@ gfx::Transform begin_transform; begin_transform.Translate(shift_x, 0); - for (const auto& mini_view : bar_view->mini_views()) { - const bool is_new = base::Contains(new_mini_views, mini_view.get()); + for (auto* mini_view : bar_view->mini_views()) { + const bool is_new = base::Contains(new_mini_views, mini_view); ui::Layer* layer = mini_view->layer(); if (is_new) @@ -128,7 +132,7 @@ } void PerformRemoveDeskMiniViewAnimation( - std::unique_ptr<DeskMiniView> removed_mini_view, + DeskMiniView* removed_mini_view, std::vector<DeskMiniView*> mini_views_left, std::vector<DeskMiniView*> mini_views_right, int shift_x) { @@ -137,7 +141,7 @@ gfx::Transform mini_views_right_begin_transform; mini_views_right_begin_transform.Translate(-shift_x, 0); - new RemovedMiniViewFadeOutAnimation(std::move(removed_mini_view)); + new RemovedMiniViewFadeOutAnimation(removed_mini_view); AnimateMiniViews(mini_views_left, mini_views_left_begin_transform); AnimateMiniViews(mini_views_right, mini_views_right_begin_transform);
diff --git a/ash/wm/desks/desk_mini_view_animations.h b/ash/wm/desks/desk_mini_view_animations.h index ac11fd23..aa5bbf1 100644 --- a/ash/wm/desks/desk_mini_view_animations.h +++ b/ash/wm/desks/desk_mini_view_animations.h
@@ -35,17 +35,17 @@ int shift_x, bool first_time_mini_views); -// Performs the mini_view removal animation. It takes ownership of the -// |removed_mini_view|. |mini_views_left|, and |mini_views_right| are lists of -// the remaining mini_views to left and to the right of the removed mini_view -// respectively. Either list can be empty (e.g. if the removed mini_view is the -// last one on the right). |shift_x| is the amount by which the remaining -// mini_views will be moved horizontally to occupy the space that the removed -// mini_view used to occupy. -// It assumes that the remiaing mini_views have been laid out in their final -// positions as if the removed mini_view no longer exits. +// Performs the mini_view removal animation. It is in charge of removing the +// |removed_mini_view| from the views hierarchy and deleting it. +// |mini_views_left|, and |mini_views_right| are lists of the remaining +// mini_views to left and to the right of the removed mini_view respectively. +// Either list can be empty (e.g. if the removed mini_view is the last one on +// the right). |shift_x| is the amount by which the remaining mini_views will be +// moved horizontally to occupy the space that the removed mini_view used to +// occupy. It assumes that the remiaing mini_views have been laid out in their +// final positions as if the removed mini_view no longer exits. void PerformRemoveDeskMiniViewAnimation( - std::unique_ptr<DeskMiniView> removed_mini_view, + DeskMiniView* removed_mini_view, std::vector<DeskMiniView*> mini_views_left, std::vector<DeskMiniView*> mini_views_right, int shift_x);
diff --git a/ash/wm/desks/desks_bar_view.cc b/ash/wm/desks/desks_bar_view.cc index dd3191e..5ac3a41 100644 --- a/ash/wm/desks/desks_bar_view.cc +++ b/ash/wm/desks/desks_bar_view.cc
@@ -209,7 +209,7 @@ if (!GetWidget()->IsActive()) return false; - for (const auto& mini_view : mini_views_) { + for (auto* mini_view : mini_views_) { if (mini_view->IsDeskNameBeingModified()) return true; } @@ -221,13 +221,13 @@ } void DesksBarView::OnHoverStateMayHaveChanged() { - for (auto& mini_view : mini_views_) + for (auto* mini_view : mini_views_) mini_view->OnHoverStateMayHaveChanged(); } void DesksBarView::OnGestureTap(const gfx::Rect& screen_rect, bool is_long_gesture) { - for (auto& mini_view : mini_views_) + for (auto* mini_view : mini_views_) mini_view->OnWidgetGestureTap(screen_rect, is_long_gesture); } @@ -240,7 +240,7 @@ if (!old_dragged_item_over_bar && !dragged_item_over_bar) return; - for (auto& mini_view : mini_views_) + for (auto* mini_view : mini_views_) mini_view->UpdateBorderColor(); } @@ -278,7 +278,7 @@ int x = (width() - total_width) / 2; const int y = compact ? kMiniViewsYCompact : kMiniViewsY; - for (auto& mini_view : mini_views_) { + for (auto* mini_view : mini_views_) { mini_view->SetBoundsRect(gfx::Rect(gfx::Point(x, y), mini_view_size)); x += (mini_view_size.width() + kMiniViewsSpacing); } @@ -321,11 +321,9 @@ void DesksBarView::OnDeskRemoved(const Desk* desk) { DeskNameView::CommitChanges(GetWidget()); - auto iter = - std::find_if(mini_views_.begin(), mini_views_.end(), - [desk](const std::unique_ptr<DeskMiniView>& mini_view) { - return desk == mini_view->desk(); - }); + auto iter = std::find_if( + mini_views_.begin(), mini_views_.end(), + [desk](DeskMiniView* mini_view) { return desk == mini_view->desk(); }); DCHECK(iter != mini_views_.end()); @@ -338,36 +336,28 @@ // comes later in the highlight order (See documentation of // OnViewDestroyingOrDisabling()). highlight_controller->OnViewDestroyingOrDisabling((*iter)->desk_name_view()); - highlight_controller->OnViewDestroyingOrDisabling(iter->get()); + highlight_controller->OnViewDestroyingOrDisabling(*iter); const int begin_x = GetFirstMiniViewXOffset(); - std::unique_ptr<DeskMiniView> removed_mini_view = std::move(*iter); + // Remove the mini view from the list now. And remove it from its parent + // after the animation is done. + DeskMiniView* mini_view = *iter; auto partition_iter = mini_views_.erase(iter); UpdateMinimumWidthToFitContents(); overview_grid_->OnDesksChanged(); new_desk_button_->UpdateButtonState(); - std::vector<DeskMiniView*> mini_views_before; - std::vector<DeskMiniView*> mini_views_after; - const auto transform_lambda = - [](const std::unique_ptr<DeskMiniView>& mini_view) { - return mini_view.get(); - }; - - std::transform(mini_views_.begin(), partition_iter, - std::back_inserter(mini_views_before), transform_lambda); - std::transform(partition_iter, mini_views_.end(), - std::back_inserter(mini_views_after), transform_lambda); - - PerformRemoveDeskMiniViewAnimation(std::move(removed_mini_view), - mini_views_before, mini_views_after, - begin_x - GetFirstMiniViewXOffset()); + PerformRemoveDeskMiniViewAnimation( + mini_view, + std::vector<DeskMiniView*>(mini_views_.begin(), partition_iter), + std::vector<DeskMiniView*>(partition_iter, mini_views_.end()), + begin_x - GetFirstMiniViewXOffset()); } void DesksBarView::OnDeskActivationChanged(const Desk* activated, const Desk* deactivated) { - for (auto& mini_view : mini_views_) { + for (auto* mini_view : mini_views_) { const Desk* desk = mini_view->desk(); if (desk == activated || desk == deactivated) mini_view->UpdateBorderColor(); @@ -404,12 +394,10 @@ DCHECK(root_window); for (const auto& desk : desks) { if (!FindMiniViewForDesk(desk.get())) { - mini_views_.push_back( + DeskMiniView* mini_view = AddChildView( std::make_unique<DeskMiniView>(this, root_window, desk.get())); - DeskMiniView* mini_view = mini_views_.back().get(); - mini_view->set_owned_by_client(); - new_mini_views.emplace_back(mini_view); - AddChildView(mini_view); + mini_views_.push_back(mini_view); + new_mini_views.push_back(mini_view); } } @@ -425,9 +413,9 @@ } DeskMiniView* DesksBarView::FindMiniViewForDesk(const Desk* desk) const { - for (auto& mini_view : mini_views_) { + for (auto* mini_view : mini_views_) { if (mini_view->desk() == desk) - return mini_view.get(); + return mini_view; } return nullptr;
diff --git a/ash/wm/desks/desks_bar_view.h b/ash/wm/desks/desks_bar_view.h index a4420eb..7082c066 100644 --- a/ash/wm/desks/desks_bar_view.h +++ b/ash/wm/desks/desks_bar_view.h
@@ -50,9 +50,7 @@ NewDeskButton* new_desk_button() const { return new_desk_button_; } - const std::vector<std::unique_ptr<DeskMiniView>>& mini_views() const { - return mini_views_; - } + const std::vector<DeskMiniView*>& mini_views() const { return mini_views_; } const gfx::Point& last_dragged_item_screen_location() const { return last_dragged_item_screen_location_; @@ -133,9 +131,8 @@ NewDeskButton* new_desk_button_; - // The views representing desks mini_views. They're owned by this DeskBarView - // (i.e. `owned_by_client_` is true). - std::vector<std::unique_ptr<DeskMiniView>> mini_views_; + // The views representing desks mini_views. They're owned by views hierarchy. + std::vector<DeskMiniView*> mini_views_; // Observes mouse events on the desks bar widget and updates the states of the // mini_views accordingly.
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc index ee60e19..5e899daa 100644 --- a/ash/wm/desks/desks_unittests.cc +++ b/ash/wm/desks/desks_unittests.cc
@@ -242,7 +242,7 @@ const NewDeskButton* button = desks_bar_view->new_desk_button(); EXPECT_EQ(button->IsLabelVisibleForTesting(), !use_compact_layout); - for (const auto& mini_view : desks_bar_view->mini_views()) { + for (auto* mini_view : desks_bar_view->mini_views()) { EXPECT_EQ(mini_view->GetDeskPreviewForTesting()->height(), DeskPreviewView::GetHeight(root_window, use_compact_layout)); EXPECT_EQ(mini_view->IsDeskNameViewVisibleForTesting(), @@ -425,7 +425,7 @@ // Hover over one of the mini_views, and expect that the close button becomes // visible. - const auto* mini_view = desks_bar_view->mini_views().back().get(); + const auto* mini_view = desks_bar_view->mini_views().back(); EXPECT_FALSE(mini_view->close_desk_button()->GetVisible()); const gfx::Point mini_view_center = mini_view->GetBoundsInScreen().CenterPoint(); @@ -858,7 +858,7 @@ // Activate desk_4 (last one on the right) by clicking on its mini view. const Desk* desk_4 = controller->desks()[3].get(); EXPECT_FALSE(desk_4->is_active()); - auto* mini_view = desks_bar_view->mini_views().back().get(); + auto* mini_view = desks_bar_view->mini_views().back(); EXPECT_EQ(desk_4, mini_view->desk()); EXPECT_FALSE(mini_view->close_desk_button()->GetVisible()); const gfx::Point mini_view_center = @@ -927,7 +927,7 @@ // Activate desk_4 (last one on the right) by clicking on its mini view. const Desk* desk_4 = controller->desks()[3].get(); EXPECT_FALSE(desk_4->is_active()); - const auto* mini_view = desks_bar_view->mini_views().back().get(); + const auto* mini_view = desks_bar_view->mini_views().back(); const gfx::Point mini_view_center = mini_view->GetBoundsInScreen().CenterPoint(); auto* event_generator = GetEventGenerator(); @@ -980,7 +980,7 @@ ASSERT_TRUE(desks_bar_view); ASSERT_EQ(4u, desks_bar_view->mini_views().size()); Desk* desk_1 = controller->desks()[0].get(); - auto* mini_view = desks_bar_view->mini_views().front().get(); + auto* mini_view = desks_bar_view->mini_views().front(); EXPECT_EQ(desk_1, mini_view->desk()); // Setup observers of both the active and inactive desks to make sure @@ -1019,7 +1019,7 @@ // Removing a desk with no windows should not result in any new mini_views // updates. - mini_view = desks_bar_view->mini_views().front().get(); + mini_view = desks_bar_view->mini_views().front(); EXPECT_TRUE(mini_view->desk()->windows().empty()); CloseDeskFromMiniView(mini_view, GetEventGenerator()); EXPECT_EQ(1, desk_4_observer.notify_counts()); @@ -1080,7 +1080,7 @@ const auto* desks_bar_view = overview_grid->desks_bar_view(); ASSERT_TRUE(desks_bar_view); ASSERT_EQ(2u, desks_bar_view->mini_views().size()); - auto* mini_view = desks_bar_view->mini_views().back().get(); + auto* mini_view = desks_bar_view->mini_views().back(); EXPECT_EQ(desk_2, mini_view->desk()); // Setup observers of both the active and inactive desks to make sure @@ -1157,7 +1157,7 @@ GetOverviewGridForRoot(Shell::GetPrimaryRootWindow()); const auto* desks_bar_view = overview_grid->desks_bar_view(); const Desk* desk_1 = controller->desks()[0].get(); - const auto* mini_view = desks_bar_view->mini_views().front().get(); + const auto* mini_view = desks_bar_view->mini_views().front(); ClickOnMiniView(mini_view, GetEventGenerator()); EXPECT_FALSE(overview_controller->InOverviewSession()); EXPECT_TRUE(desk_1->is_active()); @@ -1234,7 +1234,7 @@ const auto* desks_bar_view = overview_grid->desks_bar_view(); ASSERT_TRUE(desks_bar_view); ASSERT_EQ(2u, desks_bar_view->mini_views().size()); - auto* desk_1_mini_view = desks_bar_view->mini_views()[0].get(); + auto* desk_1_mini_view = desks_bar_view->mini_views()[0]; EXPECT_EQ(desk_1, desk_1_mini_view->desk()); // Drag it and drop it on its same desk's mini_view. Nothing happens, it // should be returned back to its original target bounds. @@ -1250,7 +1250,7 @@ // Now drag it to desk_2's mini_view. The overview grid should now have only // `win2`, and `win1` should move to desk_2. - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; EXPECT_EQ(desk_2, desk_2_mini_view->desk()); DragItemToPoint(overview_item, desk_2_mini_view->GetBoundsInScreen().CenterPoint(), @@ -1318,7 +1318,7 @@ // Drag the window to desk_2's mini_view and activate desk_2. Expect that the // window will be in an unminimized state and all its visibility and layer // opacity attributes are correct. - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; EXPECT_EQ(desk_2, desk_2_mini_view->desk()); DragItemToPoint(overview_item, desk_2_mini_view->GetBoundsInScreen().CenterPoint(), @@ -1609,7 +1609,7 @@ const auto* desks_bar_view = grid2->desks_bar_view(); ASSERT_TRUE(desks_bar_view); ASSERT_EQ(2u, desks_bar_view->mini_views().size()); - auto* desk_1_mini_view = desks_bar_view->mini_views()[0].get(); + auto* desk_1_mini_view = desks_bar_view->mini_views()[0]; auto* event_generator = GetEventGenerator(); DragItemToPoint(overview_item, desk_1_mini_view->GetBoundsInScreen().CenterPoint(), @@ -1650,7 +1650,7 @@ const auto* desks_bar_view = grid2->desks_bar_view(); ASSERT_TRUE(desks_bar_view); ASSERT_EQ(2u, desks_bar_view->mini_views().size()); - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; auto* event_generator = GetEventGenerator(); DragItemToPoint(overview_item, desk_2_mini_view->GetBoundsInScreen().CenterPoint(), @@ -1884,8 +1884,7 @@ // Deleting a desk commits the changes. ClickOnDeskNameViewAtIndex(0); EXPECT_TRUE(desk_name_view->HasFocus()); - CloseDeskFromMiniView(desks_bar_view()->mini_views()[2].get(), - event_generator); + CloseDeskFromMiniView(desks_bar_view()->mini_views()[2], event_generator); ASSERT_EQ(2u, controller()->desks().size()); EXPECT_FALSE(desk_name_view->HasFocus()); @@ -2004,7 +2003,7 @@ // Now drag it to desk_2's mini_view, so that it moves to desk_2. Expect that // desk_1's backdrop is destroyed, while created (but still hidden) for // desk_2. - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; EXPECT_EQ(desk_2, desk_2_mini_view->desk()); DragItemToPoint(overview_item, desk_2_mini_view->GetBoundsInScreen().CenterPoint(), @@ -2071,7 +2070,7 @@ ASSERT_TRUE(overview_item); const auto* desks_bar_view = overview_grid->desks_bar_view(); ASSERT_TRUE(desks_bar_view); - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; // Observe how many times a drag and drop operation updates the mini views. TestDeskObserver observer1; @@ -2240,7 +2239,7 @@ EXPECT_TRUE(overview_controller->InOverviewSession()); auto* overview_grid = GetOverviewGridForRoot(Shell::GetPrimaryRootWindow()); auto* desks_bar_view = overview_grid->desks_bar_view(); - auto* mini_view = desks_bar_view->mini_views()[1].get(); + auto* mini_view = desks_bar_view->mini_views()[1]; Desk* desk_2 = desks_controller->desks()[1].get(); EXPECT_EQ(desk_2, mini_view->desk()); { @@ -2265,7 +2264,7 @@ EXPECT_TRUE(overview_controller->InOverviewSession()); overview_grid = GetOverviewGridForRoot(Shell::GetPrimaryRootWindow()); desks_bar_view = overview_grid->desks_bar_view(); - mini_view = desks_bar_view->mini_views()[0].get(); + mini_view = desks_bar_view->mini_views()[0]; Desk* desk_1 = desks_controller->desks()[0].get(); EXPECT_EQ(desk_1, mini_view->desk()); { @@ -2312,7 +2311,7 @@ ASSERT_TRUE(overview_controller->InOverviewSession()); auto* overview_grid = GetOverviewGridForRoot(Shell::GetPrimaryRootWindow()); auto* desks_bar_view = overview_grid->desks_bar_view(); - auto* mini_view = desks_bar_view->mini_views()[1].get(); + auto* mini_view = desks_bar_view->mini_views()[1]; Desk* desk_2 = desks_controller->desks()[1].get(); EXPECT_EQ(desk_2, mini_view->desk()); { @@ -2330,7 +2329,7 @@ ASSERT_TRUE(overview_controller->InOverviewSession()); overview_grid = GetOverviewGridForRoot(Shell::GetPrimaryRootWindow()); desks_bar_view = overview_grid->desks_bar_view(); - mini_view = desks_bar_view->mini_views()[0].get(); + mini_view = desks_bar_view->mini_views()[0]; Desk* desk_1 = desks_controller->desks()[0].get(); EXPECT_EQ(desk_1, mini_view->desk()); { @@ -2511,7 +2510,7 @@ const auto* desks_bar_view = overview_grid->desks_bar_view(); ASSERT_TRUE(desks_bar_view); ASSERT_EQ(2u, desks_bar_view->mini_views().size()); - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; auto* desk_2 = controller->desks()[1].get(); EXPECT_EQ(desk_2, desk_2_mini_view->desk()); auto* event_generator = GetEventGenerator(); @@ -2619,9 +2618,9 @@ const auto* desks_bar_view = overview_grid->desks_bar_view(); ASSERT_TRUE(desks_bar_view); ASSERT_EQ(3u, desks_bar_view->mini_views().size()); - auto* desk_1_mini_view = desks_bar_view->mini_views()[0].get(); - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); - auto* desk_3_mini_view = desks_bar_view->mini_views()[2].get(); + auto* desk_1_mini_view = desks_bar_view->mini_views()[0]; + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; + auto* desk_3_mini_view = desks_bar_view->mini_views()[2]; // Long gesture tapping on one mini_view shows its close button, and hides // those of other mini_views. @@ -2777,7 +2776,7 @@ // Drag it to desk_2's mini_view. The overview grid should now show the // "no-windows" widget, and the window should move to desk_2. - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; DragItemToPoint(overview_item, desk_2_mini_view->GetBoundsInScreen().CenterPoint(), GetEventGenerator(),
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 1bc9db2..d300848 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -1396,7 +1396,7 @@ } auto* desks_controller = DesksController::Get(); - for (auto& mini_view : desks_bar_view_->mini_views()) { + for (auto* mini_view : desks_bar_view_->mini_views()) { if (!mini_view->IsPointOnMiniView(screen_location)) continue;
diff --git a/ash/wm/overview/overview_highlight_controller.cc b/ash/wm/overview/overview_highlight_controller.cc index 4ea1615..82d4d83 100644 --- a/ash/wm/overview/overview_highlight_controller.cc +++ b/ash/wm/overview/overview_highlight_controller.cc
@@ -196,8 +196,8 @@ if (bar_view) { // The desk items are always traversable from left to right, even in RTL // languages. - for (const auto& mini_view : bar_view->mini_views()) { - traversable_views.push_back(mini_view.get()); + for (auto* mini_view : bar_view->mini_views()) { + traversable_views.push_back(mini_view); traversable_views.push_back(mini_view->desk_name_view()); }
diff --git a/ash/wm/overview/overview_highlight_controller_unittest.cc b/ash/wm/overview/overview_highlight_controller_unittest.cc index b394307a..42f1c93 100644 --- a/ash/wm/overview/overview_highlight_controller_unittest.cc +++ b/ash/wm/overview/overview_highlight_controller_unittest.cc
@@ -389,7 +389,7 @@ // Tests that the first highlighted item is the first mini view. SendKey(ui::VKEY_TAB); - EXPECT_EQ(desk_bar_view->mini_views()[0].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view->mini_views()[0], GetHighlightedView()); CheckDeskBarViewSize(desk_bar_view, "first mini view"); // Test that one more tab highlights the desks name view. @@ -415,7 +415,7 @@ // first mini view. SendKey(ui::VKEY_TAB); SendKey(ui::VKEY_TAB); - EXPECT_EQ(desk_bar_view->mini_views()[0].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view->mini_views()[0], GetHighlightedView()); CheckDeskBarViewSize(desk_bar_view, "go back to first"); } @@ -448,12 +448,12 @@ EXPECT_EQ(desk_bar_view->mini_views()[1]->desk_name_view(), GetHighlightedView()); SendKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN); - EXPECT_EQ(desk_bar_view->mini_views()[1].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view->mini_views()[1], GetHighlightedView()); SendKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN); EXPECT_EQ(desk_bar_view->mini_views()[0]->desk_name_view(), GetHighlightedView()); SendKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN); - EXPECT_EQ(desk_bar_view->mini_views()[0].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view->mini_views()[0], GetHighlightedView()); // Tests that we return to the last overview item after reverse tabbing from // the first mini view. @@ -487,12 +487,12 @@ // Tests that tabbing initially will go through the desk mini views and their // desk name views, then the new desk button on the first display. SendKey(ui::VKEY_TAB); - EXPECT_EQ(desk_bar_view1->mini_views()[0].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view1->mini_views()[0], GetHighlightedView()); SendKey(ui::VKEY_TAB); EXPECT_EQ(desk_bar_view1->mini_views()[0]->desk_name_view(), GetHighlightedView()); SendKey(ui::VKEY_TAB); - EXPECT_EQ(desk_bar_view1->mini_views()[1].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view1->mini_views()[1], GetHighlightedView()); SendKey(ui::VKEY_TAB); EXPECT_EQ(desk_bar_view1->mini_views()[1]->desk_name_view(), GetHighlightedView()); @@ -512,7 +512,7 @@ // second display. SendKey(ui::VKEY_TAB); const auto* desk_bar_view2 = GetDesksBarViewForRoot(roots[1]); - EXPECT_EQ(desk_bar_view2->mini_views()[0].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view2->mini_views()[0], GetHighlightedView()); // Tab through all items on the second display. SendKey(ui::VKEY_TAB); @@ -528,7 +528,7 @@ // next tab will bring us to the first mini view on the third display. SendKey(ui::VKEY_TAB); const auto* desk_bar_view3 = GetDesksBarViewForRoot(roots[2]); - EXPECT_EQ(desk_bar_view3->mini_views()[0].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view3->mini_views()[0], GetHighlightedView()); // Tab through all items on the third display. SendKey(ui::VKEY_TAB); @@ -543,7 +543,7 @@ // Tests that after tabbing through the items on the third display, the next // tab will bring us to the first mini view on the first display. SendKey(ui::VKEY_TAB); - EXPECT_EQ(desk_bar_view1->mini_views()[0].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view1->mini_views()[0], GetHighlightedView()); } TEST_F(DesksOverviewHighlightControllerTest, @@ -597,7 +597,7 @@ SendKey(ui::VKEY_TAB); SendKey(ui::VKEY_TAB); SendKey(ui::VKEY_TAB); - ASSERT_EQ(desk_bar_view->mini_views()[1].get(), GetHighlightedView()); + ASSERT_EQ(desk_bar_view->mini_views()[1], GetHighlightedView()); // Tests that after hitting the return key on the highlighted mini view // associated with desk 2, we switch to desk 2. @@ -617,8 +617,8 @@ ToggleOverview(); const auto* desk_bar_view = GetDesksBarViewForRoot(Shell::GetPrimaryRootWindow()); - auto* mini_view1 = desk_bar_view->mini_views()[0].get(); - auto* mini_view2 = desk_bar_view->mini_views()[1].get(); + auto* mini_view1 = desk_bar_view->mini_views()[0]; + auto* mini_view2 = desk_bar_view->mini_views()[1]; // Use keyboard to navigate to the miniview associated with desk 2. SendKey(ui::VKEY_TAB); @@ -707,7 +707,7 @@ // Tabbing again should cause no crashes. EXPECT_EQ(nullptr, GetHighlightedView()); SendKey(ui::VKEY_TAB); - EXPECT_EQ(desk_bar_view->mini_views()[0].get(), GetHighlightedView()); + EXPECT_EQ(desk_bar_view->mini_views()[0], GetHighlightedView()); } } // namespace ash
diff --git a/ash/wm/overview/overview_window_drag_controller_unittest.cc b/ash/wm/overview/overview_window_drag_controller_unittest.cc index 9fec5c3..b124f6d 100644 --- a/ash/wm/overview/overview_window_drag_controller_unittest.cc +++ b/ash/wm/overview/overview_window_drag_controller_unittest.cc
@@ -267,7 +267,7 @@ EXPECT_EQ(OverviewWindowDragController::DragBehavior::kNormalDrag, drag_controller->current_drag_behavior()); // Now it's possible to drop it on desk_2's mini_view. - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; ASSERT_TRUE(desk_2_mini_view); event_generator->MoveTouch( desk_2_mini_view->GetBoundsInScreen().CenterPoint()); @@ -458,7 +458,7 @@ // progress, the desks bar remains shifted. const auto* desks_bar_view = overview_grid()->desks_bar_view(); ASSERT_TRUE(desks_bar_view); - auto* desk_2_mini_view = desks_bar_view->mini_views()[1].get(); + auto* desk_2_mini_view = desks_bar_view->mini_views()[1]; ASSERT_TRUE(desk_2_mini_view); const auto mini_view_location = desk_2_mini_view->GetBoundsInScreen().CenterPoint();
diff --git a/base/message_loop/message_loop_current.cc b/base/message_loop/message_loop_current.cc index 6b76b74..d2b0790 100644 --- a/base/message_loop/message_loop_current.cc +++ b/base/message_loop/message_loop_current.cc
@@ -81,15 +81,6 @@ current_->SetAddQueueTimeToTasks(enable); } -void MessageLoopCurrent::SetNestableTasksAllowed(bool allowed) { - DCHECK(current_->IsBoundToCurrentThread()); - current_->SetTaskExecutionAllowed(allowed); -} - -bool MessageLoopCurrent::NestableTasksAllowed() const { - return current_->IsTaskExecutionAllowed(); -} - MessageLoopCurrent::ScopedNestableTaskAllower::ScopedNestableTaskAllower() : sequence_manager_(GetCurrentSequenceManagerImpl()), old_state_(sequence_manager_->IsTaskExecutionAllowed()) { @@ -102,6 +93,10 @@ TRACE_EVENT_END0("base", "ScopedNestableTaskAllower"); } +bool MessageLoopCurrent::NestableTasksAllowed() const { + return current_->IsTaskExecutionAllowed(); +} + bool MessageLoopCurrent::operator==(const MessageLoopCurrent& other) const { return current_ == other.current_; }
diff --git a/base/message_loop/message_loop_current.h b/base/message_loop/message_loop_current.h index 61b8c6fc..63314a4 100644 --- a/base/message_loop/message_loop_current.h +++ b/base/message_loop/message_loop_current.h
@@ -117,39 +117,29 @@ // posted tasks. void SetAddQueueTimeToTasks(bool enable); - // Enables or disables the recursive task processing. This happens in the case - // of recursive message loops. Some unwanted message loops may occur when - // using common controls or printer functions. By default, recursive task - // processing is disabled. + // Enables nested task processing in scope of an upcoming native message loop. + // Some unwanted message loops may occur when using common controls or printer + // functions. Hence, nested task processing is disabled by default to avoid + // unplanned reentrancy. This re-enables it in cases where the stack is + // reentrancy safe and processing nestable tasks is explicitly safe. // - // Please use |ScopedNestableTaskAllower| instead of calling these methods - // directly. In general, nestable message loops are to be avoided. They are - // dangerous and difficult to get right, so please use with extreme caution. - // - // The specific case where tasks get queued is: - // - The thread is running a message loop. + // For instance, + // - The current thread is running a message loop. // - It receives a task #1 and executes it. - // - The task #1 implicitly starts a message loop, like a MessageBox in the - // unit test. This can also be StartDoc or GetSaveFileName. + // - The task #1 implicitly starts a nested message loop, like a MessageBox in + // the unit test. This can also be StartDoc or GetSaveFileName. // - The thread receives a task #2 before or while in this second message // loop. // - With NestableTasksAllowed set to true, the task #2 will run right away. // Otherwise, it will get executed right after task #1 completes at "thread // message loop level". // - // DEPRECATED(https://crbug.com/750779): Use RunLoop::Type on the relevant - // RunLoop instead of these methods. - // TODO(gab): Migrate usage and delete these methods. - void SetNestableTasksAllowed(bool allowed); - bool NestableTasksAllowed() const; - - // Enables nestable tasks on the current MessageLoop while in scope. - // DEPRECATED(https://crbug.com/750779): This should not be used when the - // nested loop is driven by RunLoop (use RunLoop::Type::kNestableTasksAllowed - // instead). It can however still be useful in a few scenarios where re- - // entrancy is caused by a native message loop. - // TODO(gab): Remove usage of this class alongside RunLoop and rename it to - // ScopedApplicationTasksAllowedInNativeNestedLoop(?) for remaining use cases. + // Prefer RunLoop::Type::kNestableTasksAllowed when nesting is requested by + // the application. + // + // TODO(https://crbug.com/781352): Remove usage of this class alongside + // RunLoop and rename it to ScopedApplicationTasksAllowedInNativeNestedLoop(?) + // for remaining use cases. class BASE_EXPORT ScopedNestableTaskAllower { public: ScopedNestableTaskAllower(); @@ -160,6 +150,11 @@ const bool old_state_; }; + // Returns true if nestable tasks are allowed on the current loop at this time + // (i.e. if a nested loop would start from the callee's point in the stack, + // would it be allowed to run application tasks). + bool NestableTasksAllowed() const; + // Returns true if this is the active MessageLoop for the current thread. bool IsBoundToCurrentThread() const;
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc index 1d0ed42..5a86f4b9 100644 --- a/base/message_loop/message_loop_unittest.cc +++ b/base/message_loop/message_loop_unittest.cc
@@ -245,14 +245,12 @@ DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver); }; -void RecursiveFunc(TaskList* order, int cookie, int depth, bool is_reentrant) { +// A method which reposts itself |depth| times. +void RecursiveFunc(TaskList* order, int cookie, int depth) { order->RecordStart(RECURSIVE, cookie); if (depth > 0) { - if (is_reentrant) - MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - BindOnce(&RecursiveFunc, order, cookie, depth - 1, is_reentrant)); + FROM_HERE, BindOnce(&RecursiveFunc, order, cookie, depth - 1)); } order->RecordEnd(RECURSIVE, cookie); } @@ -291,9 +289,10 @@ // implicit message loops. void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) { order->RecordStart(MESSAGEBOX, cookie); + Optional<MessageLoopCurrent::ScopedNestableTaskAllower> maybe_allow_nesting; if (is_reentrant) - MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); - MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK); + maybe_allow_nesting.emplace(); + ::MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK); order->RecordEnd(MESSAGEBOX, cookie); } @@ -302,28 +301,28 @@ order->RecordStart(ENDDIALOG, cookie); HWND window = GetActiveWindow(); if (window != NULL) { - EXPECT_NE(EndDialog(window, IDCONTINUE), 0); + EXPECT_NE(::EndDialog(window, IDCONTINUE), 0); // Cheap way to signal that the window wasn't found if RunEnd() isn't // called. order->RecordEnd(ENDDIALOG, cookie); } } +// A method which posts a RecursiveFunc that will want to run while +// ::MessageBox() is active. void RecursiveFuncWin(scoped_refptr<SingleThreadTaskRunner> task_runner, HANDLE event, bool expect_window, TaskList* order, - bool is_reentrant) { - task_runner->PostTask(FROM_HERE, - BindOnce(&RecursiveFunc, order, 1, 2, is_reentrant)); - task_runner->PostTask(FROM_HERE, - BindOnce(&MessageBoxFunc, order, 2, is_reentrant)); - task_runner->PostTask(FROM_HERE, - BindOnce(&RecursiveFunc, order, 3, 2, is_reentrant)); - // The trick here is that for recursive task processing, this task will be + bool message_box_is_reentrant) { + task_runner->PostTask(FROM_HERE, BindOnce(&RecursiveFunc, order, 1, 2)); + task_runner->PostTask( + FROM_HERE, BindOnce(&MessageBoxFunc, order, 2, message_box_is_reentrant)); + task_runner->PostTask(FROM_HERE, BindOnce(&RecursiveFunc, order, 3, 2)); + // The trick here is that for nested task processing, this task will be // ran _inside_ the MessageBox message loop, dismissing the MessageBox // without a chance. - // For non-recursive task processing, this will be executed _after_ the + // For non-nested task processing, this will be executed _after_ the // MessageBox will have been dismissed by the code below, where // expect_window_ is true. task_runner->PostTask(FROM_HERE, BindOnce(&EndDialogFunc, order, 4)); @@ -336,14 +335,14 @@ // Poll for the MessageBox. Don't do this at home! At the speed we do it, // you will never realize one MessageBox was shown. for (; expect_window;) { - HWND window = FindWindow(L"#32770", kMessageBoxTitle); + HWND window = ::FindWindow(L"#32770", kMessageBoxTitle); if (window) { // Dismiss it. for (;;) { - HWND button = FindWindowEx(window, NULL, L"Button", NULL); + HWND button = ::FindWindowEx(window, NULL, L"Button", NULL); if (button != NULL) { - EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0)); - EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0)); + EXPECT_EQ(0, ::SendMessage(button, WM_LBUTTONDOWN, 0, 0)); + EXPECT_EQ(0, ::SendMessage(button, WM_LBUTTONUP, 0, 0)); break; } } @@ -817,8 +816,7 @@ ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, BindOnce(&NestingFunc, depth)); - MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); - RunLoop().Run(); + RunLoop(RunLoop::Type::kNestableTasksAllowed).Run(); } base::RunLoop::QuitCurrentWhenIdleDeprecated(); } @@ -835,15 +833,14 @@ EXPECT_EQ(depth, 0); } -TEST_P(MessageLoopTypedTest, RecursiveDenial1) { +TEST_P(MessageLoopTypedTest, Recursive) { auto loop = CreateMessageLoop(); - EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed()); TaskList order; ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2, false)); + FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2)); ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, BindOnce(&RecursiveFunc, &order, 2, 2, false)); + FROM_HERE, BindOnce(&RecursiveFunc, &order, 2, 2)); ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, BindOnce(&QuitFunc, &order, 3)); @@ -876,37 +873,6 @@ } // namespace -TEST_P(MessageLoopTypedTest, RecursiveSupport1) { - auto loop = CreateMessageLoop(); - - TaskList order; - ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2, true)); - ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, BindOnce(&RecursiveFunc, &order, 2, 2, true)); - ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - BindOnce(&QuitFunc, &order, 3)); - - RunLoop().Run(); - - // FIFO order. - ASSERT_EQ(14U, order.Size()); - EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); - EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true)); - EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false)); - EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true)); - EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false)); - EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false)); - EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true)); - EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false)); - EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false)); - EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true)); - EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false)); -} - // Tests that non nestable tasks run in FIFO if there are no nested loops. TEST_P(MessageLoopTypedTest, NonNestableWithNoNesting) { auto loop = CreateMessageLoop(); @@ -1413,24 +1379,6 @@ run_loop.Run(); } -TEST_P(MessageLoopTypedTest, NestableTasksAllowedManually) { - auto loop = CreateMessageLoop(); - RunLoop run_loop; - loop->task_runner()->PostTask( - FROM_HERE, - BindOnce( - [](RunLoop* run_loop) { - EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed()); - MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); - EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed()); - MessageLoopCurrent::Get()->SetNestableTasksAllowed(false); - EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed()); - run_loop->Quit(); - }, - Unretained(&run_loop))); - run_loop.Run(); -} - TEST_P(MessageLoopTypedTest, IsIdleForTesting) { auto loop = CreateMessageLoop(); EXPECT_TRUE(loop->IsIdleForTesting()); @@ -1808,10 +1756,10 @@ namespace { // A side effect of this test is the generation a beep. Sorry. -void RunTest_RecursiveDenial2(MessagePumpType message_pump_type) { +void RunTest_NestingDenial2(MessagePumpType message_pump_type) { MessageLoop loop(message_pump_type); - Thread worker("RecursiveDenial2_worker"); + Thread worker("NestingDenial2_worker"); Thread::Options options; options.message_pump_type = message_pump_type; ASSERT_EQ(true, worker.StartWithOptions(options)); @@ -1848,19 +1796,20 @@ } // namespace -// This test occasionally hangs. See http://crbug.com/44567. -TEST_F(MessageLoopTest, DISABLED_RecursiveDenial2) { - RunTest_RecursiveDenial2(MessagePumpType::DEFAULT); - RunTest_RecursiveDenial2(MessagePumpType::UI); - RunTest_RecursiveDenial2(MessagePumpType::IO); +// This test occasionally hangs, would need to be turned into an +// interactive_ui_test, see http://crbug.com/44567. +TEST_F(MessageLoopTest, DISABLED_NestingDenial2) { + RunTest_NestingDenial2(MessagePumpType::DEFAULT); + RunTest_NestingDenial2(MessagePumpType::UI); + RunTest_NestingDenial2(MessagePumpType::IO); } // A side effect of this test is the generation a beep. Sorry. This test also // needs to process windows messages on the current thread. -TEST_F(MessageLoopTest, RecursiveSupport2) { +TEST_F(MessageLoopTest, NestingSupport2) { MessageLoop loop(MessagePumpType::UI); - Thread worker("RecursiveSupport2_worker"); + Thread worker("NestingSupport2_worker"); Thread::Options options; options.message_pump_type = MessagePumpType::UI; ASSERT_EQ(true, worker.StartWithOptions(options)); @@ -2116,7 +2065,7 @@ case 2: // Since we're about to enter a modal loop, tell the message loop that we // intend to nest tasks. - MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); + MessageLoopCurrent::ScopedNestableTaskAllower allow_nestable_tasks; bool did_run = false; ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&EndTest, &did_run, hwnd));
diff --git a/base/message_loop/message_pump_glib_unittest.cc b/base/message_loop/message_pump_glib_unittest.cc index 54fa300..626a81f4 100644 --- a/base/message_loop/message_pump_glib_unittest.cc +++ b/base/message_loop/message_pump_glib_unittest.cc
@@ -447,8 +447,6 @@ }; void TestGLibLoopInternal(EventInjector* injector, OnceClosure done) { - // Allow tasks to be processed from 'native' event loops. - MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner(); int task_count = 0; @@ -472,7 +470,10 @@ TimeDelta::FromMilliseconds(40)); // Run a nested, straight GLib message loop. - runner->RunGLib(); + { + MessageLoopCurrent::ScopedNestableTaskAllower allow_nestable_tasks; + runner->RunGLib(); + } ASSERT_EQ(3, task_count); EXPECT_EQ(4, injector->processed_events()); @@ -480,8 +481,6 @@ } void TestGtkLoopInternal(EventInjector* injector, OnceClosure done) { - // Allow tasks to be processed from 'native' event loops. - MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner(); int task_count = 0; @@ -505,7 +504,10 @@ TimeDelta::FromMilliseconds(40)); // Run a nested, straight Gtk message loop. - runner->RunLoop(); + { + MessageLoopCurrent::ScopedNestableTaskAllower allow_nestable_tasks; + runner->RunLoop(); + } ASSERT_EQ(3, task_count); EXPECT_EQ(4, injector->processed_events());
diff --git a/base/task/sequence_manager/thread_controller_power_monitor.cc b/base/task/sequence_manager/thread_controller_power_monitor.cc index 4c10744..12dcb12 100644 --- a/base/task/sequence_manager/thread_controller_power_monitor.cc +++ b/base/task/sequence_manager/thread_controller_power_monitor.cc
@@ -30,13 +30,15 @@ } void ThreadControllerPowerMonitor::BindToCurrentThread() { -#if DCHECK_IS_ON() - DCHECK(!is_observer_registered_); - is_observer_registered_ = true; -#endif + // Occasionally registration happens twice (i.e. when the deprecated + // ThreadController::SetDefaultTaskRunner() re-initializes the + // ThreadController). + if (is_observer_registered_) + PowerMonitor::RemoveObserver(this); // Register the observer to deliver notifications on the current thread. PowerMonitor::AddObserver(this); + is_observer_registered_ = true; } bool ThreadControllerPowerMonitor::IsProcessInPowerSuspendState() {
diff --git a/base/task/sequence_manager/thread_controller_power_monitor.h b/base/task/sequence_manager/thread_controller_power_monitor.h index a8032d9..46b44c8 100644 --- a/base/task/sequence_manager/thread_controller_power_monitor.h +++ b/base/task/sequence_manager/thread_controller_power_monitor.h
@@ -5,8 +5,6 @@ #ifndef BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_POWER_MONITOR_H_ #define BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_POWER_MONITOR_H_ -#include "base/check.h" -#include "base/macros.h" #include "base/power_monitor/power_observer.h" namespace base { @@ -47,10 +45,8 @@ // Power state based on notifications delivered to this observer. bool is_power_suspended_ = false; -#if DCHECK_IS_ON() // Whether PowerMonitor observer is registered. bool is_observer_registered_ = false; -#endif }; } // namespace internal
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc index a4a79575..7d7e20cf 100644 --- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc +++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
@@ -100,7 +100,6 @@ ShouldScheduleWork::kScheduleImmediate) { pump_->ScheduleWork(); } - power_monitor_.BindToCurrentThread(); } void ThreadControllerWithMessagePumpImpl::SetWorkBatchSize( @@ -179,6 +178,9 @@ main_thread_only().thread_task_runner_handle.reset(); main_thread_only().thread_task_runner_handle = std::make_unique<ThreadTaskRunnerHandle>(task_runner_); + // When the task runner is known, bind the power manager. Power notifications + // are received through that sequence. + power_monitor_.BindToCurrentThread(); } scoped_refptr<SingleThreadTaskRunner>
diff --git a/base/test/with_feature_override.h b/base/test/with_feature_override.h index 9a88253c..deafd18 100644 --- a/base/test/with_feature_override.h +++ b/base/test/with_feature_override.h
@@ -16,15 +16,18 @@ #define INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(test_name) \ INSTANTIATE_TEST_SUITE_P(All, test_name, testing::Values(false, true)) -// Base class for a test fixture that must run with a feature enabled and -// disabled. Must be the first base class of the test fixture to take effect -// during the construction of the test fixture itself. +// Base class for a test fixture that enables running tests twice, once with a +// feature enabled and once with it disabled. Must be the first base class of +// the test fixture to take effect during its construction. If +// WithFeatureOverride is added as a parent to an existing test fixture +// all of its existing tests need to be migrated to TEST_P. // // Example usage: // -// class MyTest : public base::WithFeatureOverride, public testing::Test { +// class MyTest : public base::test::WithFeatureOverride, public testing::Test +// { // public: -// MyTest() : WithFeatureOverride(kMyFeature){} +// MyTest() : base::test::WithFeatureOverride(kMyFeature){} // }; // // TEST_P(MyTest, FooBar) { @@ -41,8 +44,8 @@ WithFeatureOverride(const WithFeatureOverride&) = delete; WithFeatureOverride& operator=(const WithFeatureOverride&) = delete; - // Use to know if the configured feature provided in the ctor is enabled or - // not. + // Use to know if the configured feature provided in the constructor is + // enabled or not. bool IsParamFeatureEnabled(); private:
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 83715bc..db86606ed 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -45,12 +45,8 @@ "*_bundle_module", ] -# Targets that match _java_target_patterns but are not actually java targets. -_java_target_exceptions = [ "*:*_unpack_aar" ] - # These targets match _java_lib_patterns but do not use java_library_impl. -_java_lib_exceptions = - _java_target_patterns - _java_lib_patterns + _java_target_exceptions +_java_lib_exceptions = _java_target_patterns - _java_lib_patterns _r8_path = "//third_party/r8/lib/r8.jar" _desugar_jdk_libs_json = "//third_party/r8/desugar_jdk_libs.json" @@ -127,8 +123,7 @@ if (_type != "android_apk" && _type != "java_binary" && _type != "dist_jar" && _type != "java_annotation_processor" && _type != "dist_aar" && _type != "android_app_bundle") { - if (filter_exclude([ _target_label ], _java_target_patterns) != [] && - filter_exclude([ _target_label ], _java_target_exceptions) != []) { + if (filter_exclude([ _target_label ], _java_target_patterns) != []) { assert(false, "Invalid java target name: $_target_label") } } @@ -159,8 +154,7 @@ if (defined(invoker.possible_config_deps)) { foreach(_possible_dep, invoker.possible_config_deps) { _dep_label = get_label_info(_possible_dep, "label_no_toolchain") - if (filter_exclude([ _dep_label ], _java_target_patterns) == [] && - filter_exclude([ _dep_label ], _java_target_exceptions) != []) { + if (filter_exclude([ _dep_label ], _java_target_patterns) == []) { # Put the bug number in the target name so that false-positives # have a hint in the error message about non-existent dependencies. deps += [ "$_dep_label$build_config_target_suffix" ]
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 050c86a..a9ded47 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -4147,7 +4147,13 @@ _info_path = invoker.info_path } _output_path = "${target_out_dir}/${target_name}" - _unpack_target_name = "${target_name}__unpack_aar" + _target_name_without_java_or_junit = + string_replace(string_replace(target_name, "_java", ""), "_junit", "") + + # This unpack target is a python action, not a valid java target. Since the + # java targets below depend on it, its name must not match the java patterns + # in internal_rules.gni. + _unpack_target_name = "${_target_name_without_java_or_junit}__unpack_aar" _ignore_aidl = defined(invoker.ignore_aidl) && invoker.ignore_aidl _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets _ignore_manifest =
diff --git a/build/config/compiler/pgo/BUILD.gn b/build/config/compiler/pgo/BUILD.gn index 2382e3f..213ca19b 100644 --- a/build/config/compiler/pgo/BUILD.gn +++ b/build/config/compiler/pgo/BUILD.gn
@@ -15,15 +15,15 @@ # are not required to be defined when we're not actually using PGO. if (chrome_pgo_phase == 1 && is_clang && !is_nacl && is_a_target_toolchain) { # TODO(sebmarchand): Add a GN flag that allows setting the PGO profile - # name or find a way to remove use {target_name} in the filename? + # name or find a way to use {target_name} in the filename? # This uses the "%m" specifier to allow concurrent runs of the # instrumented image. - cflags = [ "-fprofile-instr-generate=%m.profraw" ] + cflags = [ "-fprofile-generate=%m.profraw" ] if (!is_win) { # Windows directly calls link.exe instead of the compiler driver when # linking, and embeds the path to the profile runtime library as # dependent library into each object file. - ldflags = [ "-fprofile-instr-generate" ] + ldflags = [ "-fprofile-generate" ] } } } @@ -75,6 +75,13 @@ # out of date, so make sure we don't error for those cases. "-Wno-profile-instr-unprofiled", "-Wno-profile-instr-out-of-date", + + # Some hashing conflict results in a lot of warning like this when doing + # a PGO build: + # warning: foo.cc: Function control flow change detected (hash mismatch) + # [-Wbackend-plugin] + # See https://crbug.com/978401 + "-Wno-backend-plugin", ] } }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 1d327045..18196df 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200603.1.1 +0.20200603.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 1d327045..18196df 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200603.1.1 +0.20200603.2.1
diff --git a/buildtools/third_party/libunwind/BUILD.gn b/buildtools/third_party/libunwind/BUILD.gn index 1e4fbcb8..923f928f 100644 --- a/buildtools/third_party/libunwind/BUILD.gn +++ b/buildtools/third_party/libunwind/BUILD.gn
@@ -11,7 +11,18 @@ # ValueAsBitPattern in Unwind-EHABI.cpp is only used on Debug builds. "-Wno-unused-function", + + # libunwind expects to be compiled with unwind tables so it can + # unwind its own frames. + "-funwind-tables", ] + + if (is_fuchsia) { + # Workaround for https://bugs.llvm.org/show_bug.cgi?id=45875: + # compiling the C code with -fexceptions ensures that accurate + # unwinding information is generated for _Unwind_RaiseException. + cflags_c = [ "-fexceptions" ] + } } source_set("libunwind") {
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 1f6714f..be2fa72f 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h
@@ -10,6 +10,7 @@ #include "base/threading/thread.h" #include "build/build_config.h" #include "cc/animation/animation_delegate.h" +#include "cc/base/features.h" #include "cc/test/property_tree_test_utils.h" #include "cc/test/test_hooks.h" #include "cc/test/test_task_graph_runner.h" @@ -313,10 +314,15 @@ // a specific test name. eg. // // TODO(crbug.com/abcd): Disabled for some reasons stated here. // // SINGLE_AND_MULTI_THREAD_TEST_F(SomeRandomTest) -#define SINGLE_THREAD_TEST_F(TEST_FIXTURE_NAME) \ - TEST_F(TEST_FIXTURE_NAME, RunSingleThread_DelegatingRenderer) { \ - RunTest(CompositorMode::SINGLE_THREADED); \ - } \ +#define SINGLE_THREAD_TEST_F(TEST_FIXTURE_NAME) \ + TEST_F(TEST_FIXTURE_NAME, RunSingleThread_DelegatingRenderer) { \ + RunTest(CompositorMode::SINGLE_THREADED); \ + } \ + TEST_F(TEST_FIXTURE_NAME, RunSingleThread_DelegatingRendererUnifiedScroll) { \ + base::test::ScopedFeatureList scoped_feature_list; \ + scoped_feature_list.InitAndEnableFeature(features::kScrollUnification); \ + RunTest(CompositorMode::SINGLE_THREADED); \ + } \ class SingleThreadDelegatingImplNeedsSemicolon##TEST_FIXTURE_NAME {} // Do not change this macro to disable a test, it will disable half of @@ -324,10 +330,15 @@ // a specific test name. eg. // // TODO(crbug.com/abcd): Disabled for some reasons stated here. // // SINGLE_AND_MULTI_THREAD_TEST_F(SomeRandomTest) -#define MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) \ - TEST_F(TEST_FIXTURE_NAME, RunMultiThread_DelegatingRenderer) { \ - RunTest(CompositorMode::THREADED); \ - } \ +#define MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) \ + TEST_F(TEST_FIXTURE_NAME, RunMultiThread_DelegatingRenderer) { \ + RunTest(CompositorMode::THREADED); \ + } \ + TEST_F(TEST_FIXTURE_NAME, RunMultiThread_DelegatingRendererUnifiedScroll) { \ + base::test::ScopedFeatureList scoped_feature_list; \ + scoped_feature_list.InitAndEnableFeature(features::kScrollUnification); \ + RunTest(CompositorMode::THREADED); \ + } \ class MultiThreadDelegatingImplNeedsSemicolon##TEST_FIXTURE_NAME {} // Do not change this macro to disable a test, it will disable half of
diff --git a/cc/trees/draw_properties_unittest.cc b/cc/trees/draw_properties_unittest.cc index dab4da7..b19a402d 100644 --- a/cc/trees/draw_properties_unittest.cc +++ b/cc/trees/draw_properties_unittest.cc
@@ -12,6 +12,7 @@ #include "base/memory/ptr_util.h" #include "base/stl_util.h" +#include "base/test/scoped_feature_list.h" #include "cc/animation/animation.h" #include "cc/animation/animation_host.h" #include "cc/animation/animation_id_provider.h" @@ -3575,6 +3576,74 @@ active_child->effect_tree_index())); } +class TransformInteropTest : public DrawPropertiesTestBase, + public testing::Test { + public: + TransformInteropTest() : DrawPropertiesTestBase(TransformInteropSettings()) {} + + protected: + LayerTreeSettings TransformInteropSettings() { + LayerListSettings settings; + + settings.enable_transform_interop = true; + return settings; + } +}; + +TEST_F(TransformInteropTest, BackfaceInvisibleTransform) { + LayerImpl* root = root_layer(); + root->SetDrawsContent(true); + LayerImpl* back_facing = AddLayer<LayerImpl>(); + LayerImpl* back_facing_double_sided = AddLayer<LayerImpl>(); + LayerImpl* front_facing = AddLayer<LayerImpl>(); + back_facing->SetDrawsContent(true); + back_facing_double_sided->SetDrawsContent(true); + front_facing->SetDrawsContent(true); + + root->SetBounds(gfx::Size(50, 50)); + back_facing->SetBounds(gfx::Size(50, 50)); + back_facing_double_sided->SetBounds(gfx::Size(50, 50)); + front_facing->SetBounds(gfx::Size(50, 50)); + CopyProperties(root, back_facing); + CopyProperties(root, front_facing); + + back_facing->SetShouldCheckBackfaceVisibility(true); + back_facing_double_sided->SetShouldCheckBackfaceVisibility(false); + front_facing->SetShouldCheckBackfaceVisibility(true); + + auto& back_facing_transform_node = CreateTransformNode(back_facing); + back_facing_transform_node.flattens_inherited_transform = false; + back_facing_transform_node.sorting_context_id = 1; + gfx::Transform rotate_about_y; + rotate_about_y.RotateAboutYAxis(180.0); + back_facing_transform_node.local = rotate_about_y; + + CopyProperties(back_facing, back_facing_double_sided); + + UpdateActiveTreeDrawProperties(); + + EXPECT_TRUE(draw_property_utils::IsLayerBackFaceVisible( + back_facing, back_facing->transform_tree_index(), + host_impl()->active_tree()->property_trees())); + EXPECT_TRUE(draw_property_utils::IsLayerBackFaceVisible( + back_facing, back_facing_double_sided->transform_tree_index(), + host_impl()->active_tree()->property_trees())); + EXPECT_FALSE(draw_property_utils::IsLayerBackFaceVisible( + front_facing, front_facing->transform_tree_index(), + host_impl()->active_tree()->property_trees())); + + EXPECT_TRUE( + draw_property_utils::LayerShouldBeSkippedForDrawPropertiesComputation( + back_facing, host_impl()->active_tree()->property_trees())); + EXPECT_FALSE( + draw_property_utils::LayerShouldBeSkippedForDrawPropertiesComputation( + back_facing_double_sided, + host_impl()->active_tree()->property_trees())); + EXPECT_FALSE( + draw_property_utils::LayerShouldBeSkippedForDrawPropertiesComputation( + front_facing, host_impl()->active_tree()->property_trees())); +} + using LCDTextTestParam = std::tuple<bool, bool>; class LCDTextTest : public DrawPropertiesTestBase, public testing::TestWithParam<LCDTextTestParam> {
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index 2f701674..a748f34 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -388,12 +388,34 @@ return to_target.IsBackFaceVisible(); } -template <typename LayerType> -bool IsLayerBackFaceVisible(LayerType* layer, - int transform_tree_index, - const PropertyTrees* property_trees) { - return IsTargetSpaceTransformBackFaceVisible(layer, transform_tree_index, - property_trees); +bool IsTransformToRootOf3DRenderingContextVisible( + Layer* layer, + int transform_tree_index, + const PropertyTrees* property_trees) { + return true; +} + +bool IsTransformToRootOf3DRenderingContextVisible( + LayerImpl* layer, + int transform_tree_index, + const PropertyTrees* property_trees) { + const TransformTree& transform_tree = property_trees->transform_tree; + int root_id = transform_tree_index; + int sorting_context_id = + transform_tree.Node(transform_tree_index)->sorting_context_id; + while (root_id > 0 && transform_tree.Node(root_id - 1)->sorting_context_id == + sorting_context_id) + root_id--; + + // TODO(chrishtr): cache this on the transform trees if needed, similar to + // |to_target| and |to_screen|. + gfx::Transform to_3d_root; + if (transform_tree_index != root_id) + property_trees->transform_tree.CombineTransformsBetween( + transform_tree_index, root_id, &to_3d_root); + to_3d_root.PreconcatTransform( + property_trees->transform_tree.Node(root_id)->to_parent); + return to_3d_root.IsBackFaceVisible(); } inline bool TransformToScreenIsKnown(Layer* layer, @@ -445,7 +467,8 @@ // backface is not visible. if (TransformToScreenIsKnown(layer, backface_transform_id, tree) && !HasSingularTransform(backface_transform_id, tree) && - IsLayerBackFaceVisible(layer, backface_transform_id, property_trees)) { + draw_property_utils::IsLayerBackFaceVisible( + layer, backface_transform_id, property_trees)) { UMA_HISTOGRAM_BOOLEAN( "Compositing.Renderer.LayerUpdateSkippedDueToBackface", true); return false; @@ -474,35 +497,6 @@ !effect_node->is_drawn; } -inline bool LayerShouldBeSkippedForDrawPropertiesComputation( - LayerImpl* layer, - const TransformTree& transform_tree, - const EffectTree& effect_tree) { - const EffectNode* effect_node = effect_tree.Node(layer->effect_tree_index()); - - if (effect_node->HasRenderSurface() && effect_node->subtree_has_copy_request) - return false; - - // Skip if the node's subtree is hidden and no need to cache. - if (effect_node->subtree_hidden && !effect_node->cache_render_surface) - return true; - - // If the layer transform is not invertible, it should be skipped. In case the - // transform is animating and singular, we should not skip it. - const TransformNode* transform_node = - transform_tree.Node(layer->transform_tree_index()); - - if (!transform_node->node_and_ancestors_are_animated_or_invertible || - !effect_node->is_drawn) - return true; - - UMA_HISTOGRAM_BOOLEAN( - "Compositing.Renderer.LayerSkippedForDrawPropertiesDueToBackface", - effect_node->hidden_by_backface_visibility); - - return effect_node->hidden_by_backface_visibility; -} - gfx::Rect LayerDrawableContentRect( const LayerImpl* layer, const gfx::Rect& layer_bounds_in_target_space, @@ -922,8 +916,8 @@ bool is_root = layer_tree_impl->IsRootLayer(layer); bool skip_draw_properties_computation = - LayerShouldBeSkippedForDrawPropertiesComputation( - layer, property_trees->transform_tree, property_trees->effect_tree); + draw_property_utils::LayerShouldBeSkippedForDrawPropertiesComputation( + layer, property_trees); bool skip_for_invertibility = SkipForInvertibility(layer, property_trees); @@ -1172,6 +1166,61 @@ } // namespace +bool CC_EXPORT LayerShouldBeSkippedForDrawPropertiesComputation( + LayerImpl* layer, + const PropertyTrees* property_trees) { + const TransformTree& transform_tree = property_trees->transform_tree; + const EffectTree& effect_tree = property_trees->effect_tree; + const EffectNode* effect_node = effect_tree.Node(layer->effect_tree_index()); + + if (effect_node->HasRenderSurface() && effect_node->subtree_has_copy_request) + return false; + + // Skip if the node's subtree is hidden and no need to cache. + if (effect_node->subtree_hidden && !effect_node->cache_render_surface) + return true; + + // If the layer transform is not invertible, it should be skipped. In case the + // transform is animating and singular, we should not skip it. + const TransformNode* transform_node = + transform_tree.Node(layer->transform_tree_index()); + + if (!transform_node->node_and_ancestors_are_animated_or_invertible || + !effect_node->is_drawn) + return true; + if (layer->layer_tree_impl()->settings().enable_transform_interop) { + return layer->should_check_backface_visibility() && + IsLayerBackFaceVisible(layer, layer->transform_tree_index(), + property_trees); + } else { + return effect_node->hidden_by_backface_visibility; + } +} + +bool CC_EXPORT IsLayerBackFaceVisible(LayerImpl* layer, + int transform_tree_index, + const PropertyTrees* property_trees) { + if (layer->layer_tree_impl()->settings().enable_transform_interop) { + return IsTransformToRootOf3DRenderingContextVisible( + layer, transform_tree_index, property_trees); + } else { + return IsTargetSpaceTransformBackFaceVisible(layer, transform_tree_index, + property_trees); + } +} + +bool CC_EXPORT IsLayerBackFaceVisible(Layer* layer, + int transform_tree_index, + const PropertyTrees* property_trees) { + if (layer->layer_tree_host()->GetSettings().enable_transform_interop) { + return IsTransformToRootOf3DRenderingContextVisible( + layer, transform_tree_index, property_trees); + } else { + return IsTargetSpaceTransformBackFaceVisible(layer, transform_tree_index, + property_trees); + } +} + void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, gfx::Transform* transform) { DCHECK(effect_node->HasRenderSurface()); @@ -1203,7 +1252,6 @@ void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, std::vector<LayerImpl*>* visible_layer_list) { const PropertyTrees* property_trees = layer_tree_impl->property_trees(); - const TransformTree& transform_tree = property_trees->transform_tree; const EffectTree& effect_tree = property_trees->effect_tree; for (auto* layer_impl : *layer_tree_impl) { @@ -1212,8 +1260,8 @@ layer_impl->EnsureValidPropertyTreeIndices(); if (!IsRootLayer(layer_impl) && - LayerShouldBeSkippedForDrawPropertiesComputation( - layer_impl, transform_tree, effect_tree)) + LayerShouldBeSkippedForDrawPropertiesComputation(layer_impl, + property_trees)) continue; bool layer_is_drawn =
diff --git a/cc/trees/draw_property_utils.h b/cc/trees/draw_property_utils.h index c42684ee..b80b38e3 100644 --- a/cc/trees/draw_property_utils.h +++ b/cc/trees/draw_property_utils.h
@@ -68,6 +68,18 @@ RenderSurfaceList* output_render_surface_list, LayerImplList* output_update_layer_list_for_testing = nullptr); +bool CC_EXPORT LayerShouldBeSkippedForDrawPropertiesComputation( + LayerImpl* layer, + const PropertyTrees* property_trees); + +bool CC_EXPORT IsLayerBackFaceVisible(LayerImpl* layer, + int transform_tree_index, + const PropertyTrees* property_trees); + +bool CC_EXPORT IsLayerBackFaceVisible(Layer* layer, + int transform_tree_index, + const PropertyTrees* property_trees); + #if DCHECK_IS_ON() // Checks and logs if double background blur exists in any layers. Returns // true if no double background blur is detected, false otherwise.
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 970a4be..16f4096 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -797,16 +797,6 @@ : task_runner_provider_->MainThreadTaskRunner(); } - // Determines whether the given scroll node can scroll on the compositor - // thread or if there are any reasons it must be scrolled on the main thread - // or not at all. Note: in general, this is not sufficient to determine if a - // scroll can occur on the compositor thread. If hit testing to a scroll - // node, the caller must also check whether the hit point intersects a - // non-fast-scrolling-region of any ancestor scrolling layers. Can be removed - // after scroll unification https://crbug.com/476553. - InputHandler::ScrollStatus TryScroll(const ScrollTree& scroll_tree, - ScrollNode* scroll_node) const; - // Return all ScrollNode indices that have an associated layer with a non-fast // region that intersects the point. base::flat_set<int> NonFastScrollableNodes( @@ -915,6 +905,16 @@ // scroll chaining rules. ScrollNode* GetNodeToScroll(ScrollNode* node) const; + // Determines whether the given scroll node can scroll on the compositor + // thread or if there are any reasons it must be scrolled on the main thread + // or not at all. Note: in general, this is not sufficient to determine if a + // scroll can occur on the compositor thread. If hit testing to a scroll + // node, the caller must also check whether the hit point intersects a + // non-fast-scrolling-region of any ancestor scrolling layers. Can be removed + // after scroll unification https://crbug.com/476553. + InputHandler::ScrollStatus TryScroll(const ScrollTree& scroll_tree, + ScrollNode* scroll_node) const; + // Transforms viewport start point and scroll delta to local start point and // local delta, respectively. If the transformation of either the start or end // point of a scroll is clipped, the function returns false.
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index d01de18..3a95b18 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -1471,12 +1471,13 @@ void SetupTree() override { LayerTreeHostScrollTest::SetupTree(); - // Add a sub-scroller to test TryScroll against. The outer viewport scroll + // Add a sub-scroller to test ScrollBegin against. The outer viewport scroll // will be latched to for scrolling even if it doesn't have any scroll // extent in the given direction to support overscroll actions. scroller_ = Layer::Create(); scroller_->SetIsDrawable(true); scroller_->SetHitTestable(true); + scroller_->SetBounds(gfx::Size(200, 200)); scroller_->SetElementId(LayerIdToElementIdForTesting(scroller_->id())); CopyProperties(layer_tree_host()->OuterViewportScrollLayerForTesting(), scroller_.get()); @@ -1486,61 +1487,91 @@ layer_tree_host()->root_layer()->AddChild(scroller_.get()); } - void BeginTest() override { PostSetNeedsCommitToMainThread(); } + void BeginTest() override { NextStep(); } - void UpdateLayerTreeHost() override { + void NextStep() { + if (TestEnded()) + return; + + ++cur_step_; + ScrollTree& scroll_tree = layer_tree_host()->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.Node(scroller_->scroll_tree_index()); - switch (layer_tree_host()->SourceFrameNumber()) { - case 0: + switch (cur_step_) { + case 1: // Set max_scroll_offset = (100, 100). scroll_node->bounds = scroll_node->container_bounds; scroll_node->bounds.Enlarge(100, 100); break; - case 1: + case 2: // Set max_scroll_offset = (0, 0). scroll_node->bounds = scroll_node->container_bounds; break; - case 2: + case 3: // Set max_scroll_offset = (-1, -1). scroll_node->bounds = gfx::Size(); break; } + + layer_tree_host()->SetNeedsCommit(); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { + if (TestEnded()) + return; + ScrollTree& scroll_tree = impl->active_tree()->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.Node(scroller_->scroll_tree_index()); + + ScrollStateData scroll_state_data; + scroll_state_data.is_beginning = true; + // The position has to be at (0, 0) since the viewport in this test has + // bounds (1, 1). + scroll_state_data.position_x = 0; + scroll_state_data.position_y = 0; + scroll_state_data.delta_x_hint = 10; + scroll_state_data.delta_y_hint = 10; + scroll_state_data.is_direct_manipulation = true; + + ScrollState scroll_state(scroll_state_data); InputHandler::ScrollStatus status = - impl->TryScroll(scroll_tree, scroll_node); - switch (impl->active_tree()->source_frame_number()) { - case 0: - EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread) - << "In Frame 0"; - EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, - status.main_thread_scrolling_reasons) - << "In Frame 0"; - PostSetNeedsCommitToMainThread(); - break; + impl->ScrollBegin(&scroll_state, ui::ScrollInputType::kTouchscreen); + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread) + << "In Frame " << impl->active_tree()->source_frame_number(); + + switch (cur_step_) { case 1: - EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread) << "In Frame 1"; - EXPECT_EQ(MainThreadScrollingReason::kNotScrollable, - status.main_thread_scrolling_reasons) - << "In Frame 1"; - PostSetNeedsCommitToMainThread(); + // Since the scroller has scroll extend and is scrollable, we should + // have targeted it. + EXPECT_EQ(scroll_node, impl->CurrentlyScrollingNode()) << "In Frame 0"; break; case 2: - EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread) << "In Frame 2"; - EXPECT_EQ(MainThreadScrollingReason::kNotScrollable, - status.main_thread_scrolling_reasons) + // Since the max_scroll_offset is (0, 0) - we shouldn't target it and + // we should instead bubble up to the viewport. + EXPECT_EQ(impl->OuterViewportScrollNode(), + impl->CurrentlyScrollingNode()) + << "In Frame 1"; + break; + case 3: + // Since the max_scroll_offset is (-1, -1) - we shouldn't target it and + // we should instead bubble up to the viewport. + EXPECT_EQ(impl->OuterViewportScrollNode(), + impl->CurrentlyScrollingNode()) << "In Frame 2"; EndTest(); break; } + impl->ScrollEnd(); + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce( + &LayerTreeHostScrollTestScrollZeroMaxScrollOffset::NextStep, + base::Unretained(this))); } private: + int cur_step_ = 0; scoped_refptr<Layer> scroller_; }; @@ -1572,14 +1603,21 @@ InputHandler::ScrollStatus status = impl->ScrollBegin( BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 1)).get(), ui::ScrollInputType::kTouchscreen); - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, - status.main_thread_scrolling_reasons); + if (base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_TRUE(status.needs_main_thread_hit_test); + impl->ScrollEnd(); + } else { + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, + status.main_thread_scrolling_reasons); + } status = impl->ScrollBegin( BeginState(gfx::Point(21, 21), gfx::Vector2dF(0, 1)).get(), ui::ScrollInputType::kTouchscreen); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_FALSE(status.needs_main_thread_hit_test); EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); @@ -1600,36 +1638,88 @@ void SetupTree() override { LayerTreeHostScrollTest::SetupTree(); - GetScrollNode(layer_tree_host()->InnerViewportScrollLayerForTesting()) + GetScrollNode(layer_tree_host()->OuterViewportScrollLayerForTesting()) ->main_thread_scrolling_reasons = - MainThreadScrollingReason::kScrollbarScrolling; + MainThreadScrollingReason::kThreadedScrollingDisabled; + + scroller_ = Layer::Create(); + scroller_->SetIsDrawable(true); + scroller_->SetHitTestable(true); + scroller_->SetBounds(gfx::Size(200, 200)); + scroller_->SetElementId(LayerIdToElementIdForTesting(scroller_->id())); + CopyProperties(layer_tree_host()->OuterViewportScrollLayerForTesting(), + scroller_.get()); + CreateTransformNode(scroller_.get()); + CreateScrollNode(scroller_.get(), + layer_tree_host()->root_layer()->bounds()); + layer_tree_host()->root_layer()->AddChild(scroller_.get()); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - LayerImpl* inner_scroll_layer = - impl->active_tree()->InnerViewportScrollLayerForTesting(); - LayerImpl* outer_scroll_layer = - impl->active_tree()->OuterViewportScrollLayerForTesting(); - ScrollTree& scroll_tree = impl->active_tree()->property_trees()->scroll_tree; - ScrollNode* inner_scroll_node = - scroll_tree.Node(inner_scroll_layer->scroll_tree_index()); - ScrollNode* outer_scroll_node = - scroll_tree.Node(outer_scroll_layer->scroll_tree_index()); + ScrollNode* scroller_scroll_node = + scroll_tree.Node(scroller_->scroll_tree_index()); - InputHandler::ScrollStatus status = - impl->TryScroll(scroll_tree, inner_scroll_node); - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling, - status.main_thread_scrolling_reasons); + ScrollStateData scroll_state_data; + scroll_state_data.is_beginning = true; + // To hit the scroller, the position has to be at (0, 0) since the viewport + // in this test has bounds (1, 1) and would otherwise clip the hit test. + scroll_state_data.position_x = 0; + scroll_state_data.position_y = 0; + scroll_state_data.delta_x_hint = 10; + scroll_state_data.delta_y_hint = 10; + scroll_state_data.is_direct_manipulation = true; + ScrollState scroll_state(scroll_state_data); - status = impl->TryScroll(scroll_tree, outer_scroll_node); - EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, - status.main_thread_scrolling_reasons); + // Scroll hitting the scroller layer. + { + InputHandler::ScrollStatus status = + impl->ScrollBegin(&scroll_state, ui::ScrollInputType::kTouchscreen); + if (base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_EQ(impl->CurrentlyScrollingNode(), scroller_scroll_node); + EXPECT_FALSE(status.needs_main_thread_hit_test); + } else { + // Despite the fact that we hit the scroller, which has no main thread + // scrolling reason, we still must fallback to main thread scrolling due + // to the fact that it has a main thread scrolling ancestor. + EXPECT_EQ(impl->CurrentlyScrollingNode(), nullptr); + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kThreadedScrollingDisabled, + status.main_thread_scrolling_reasons); + } + impl->ScrollEnd(); + } + + // Scroll hitting the viewport layer. + { + // A hit test outside the viewport should fallback to scrolling the + // viewport. + scroll_state.data()->position_y = 1000; + + InputHandler::ScrollStatus status = + impl->ScrollBegin(&scroll_state, ui::ScrollInputType::kTouchscreen); + if (base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_FALSE(status.needs_main_thread_hit_test); + EXPECT_EQ(impl->CurrentlyScrollingNode(), + impl->OuterViewportScrollNode()); + } else { + // Since the viewport has a main thread scrolling reason, this + // too should fallback to the main thread. + EXPECT_EQ(impl->CurrentlyScrollingNode(), nullptr); + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kThreadedScrollingDisabled, + status.main_thread_scrolling_reasons); + } + impl->ScrollEnd(); + } + EndTest(); } + + private: + scoped_refptr<Layer> scroller_; }; SINGLE_AND_MULTI_THREAD_TEST_F( @@ -2541,27 +2631,28 @@ void SetupTree() override { SetInitialRootBounds(gfx::Size(800, 600)); LayerTreeHostScrollTest::SetupTree(); - Layer* root = layer_tree_host()->root_layer(); - fake_content_layer_client_.set_bounds(root->bounds()); + Layer* outer_scroll = + layer_tree_host()->OuterViewportScrollLayerForTesting(); + fake_content_layer_client_.set_bounds(outer_scroll->bounds()); bottom_ = FakePictureLayer::Create(&fake_content_layer_client_); bottom_->SetElementId(LayerIdToElementIdForTesting(bottom_->id())); bottom_->SetBounds(gfx::Size(100, 100)); bottom_->SetNonFastScrollableRegion(Region(gfx::Rect(50, 50, 50, 50))); bottom_->SetHitTestable(true); - CopyProperties(root, bottom_.get()); - root->AddChild(bottom_); + CopyProperties(outer_scroll, bottom_.get()); + outer_scroll->AddChild(bottom_); middle_scrollable_ = FakePictureLayer::Create(&fake_content_layer_client_); middle_scrollable_->SetElementId( LayerIdToElementIdForTesting(middle_scrollable_->id())); - middle_scrollable_->SetBounds(gfx::Size(100, 100)); + middle_scrollable_->SetBounds(gfx::Size(100, 200)); middle_scrollable_->SetIsDrawable(true); middle_scrollable_->SetHitTestable(true); CopyProperties(bottom_.get(), middle_scrollable_.get()); CreateTransformNode(middle_scrollable_.get()); - CreateScrollNode(middle_scrollable_.get(), gfx::Size(100, 200)); - root->AddChild(middle_scrollable_); + CreateScrollNode(middle_scrollable_.get(), gfx::Size(100, 100)); + outer_scroll->AddChild(middle_scrollable_); top_ = FakePictureLayer::Create(&fake_content_layer_client_); top_->SetElementId(LayerIdToElementIdForTesting(top_->id())); @@ -2569,7 +2660,7 @@ top_->SetNonFastScrollableRegion(Region(gfx::Rect(0, 0, 50, 50))); top_->SetHitTestable(true); CopyProperties(middle_scrollable_.get(), top_.get()); - root->AddChild(top_); + outer_scroll->AddChild(top_); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -2578,35 +2669,70 @@ if (TestEnded()) return; - // The top-left hit should immediately hit the top layer's non-fast region - // which forces main-thread scrolling. - auto top_left_status = impl->ScrollBegin( - BeginState(gfx::Point(20, 20), gfx::Vector2dF(0, 1)).get(), - ui::ScrollInputType::kTouchscreen); - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, top_left_status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, - top_left_status.main_thread_scrolling_reasons); + ScrollNode* scroll_node = + impl->active_tree()->property_trees()->scroll_tree.Node( + middle_scrollable_->scroll_tree_index()); - // The top-right hit should hit the top layer but not the non-fast region so - // the scroll should continue to scroll on the impl. - InputHandler::ScrollStatus top_right_status = impl->ScrollBegin( - BeginState(gfx::Point(80, 20), gfx::Vector2dF(0, 1)).get(), - ui::ScrollInputType::kTouchscreen); - EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, top_right_status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, - top_right_status.main_thread_scrolling_reasons); - impl->ScrollEnd(); + // The top-left hit should immediately hit the top layer's non-fast region. + { + auto status = impl->ScrollBegin( + BeginState(gfx::Point(20, 20), gfx::Vector2dF(0, 1)).get(), + ui::ScrollInputType::kTouchscreen); + if (base::FeatureList::IsEnabled(features::kScrollUnification)) { + // Hitting a non fast region should request a hit test from the main + // thread. + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_TRUE(status.needs_main_thread_hit_test); + impl->ScrollEnd(); + } else { + // Prior to scroll unification, this forces scrolling to the main + // thread. + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, + status.main_thread_scrolling_reasons); + } + } - // The bottom-right should hit the bottom layer's non-fast region. Though - // the middle layer is a composited scroller and is hit first, we cannot do - // a fast scroll because an ancestor on the scroll chain has hit a non-fast - // region. - InputHandler::ScrollStatus bottom_right_status = impl->ScrollBegin( - BeginState(gfx::Point(80, 80), gfx::Vector2dF(0, 1)).get(), - ui::ScrollInputType::kTouchscreen); - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, bottom_right_status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, - bottom_right_status.main_thread_scrolling_reasons); + // The top-right hit should hit the top layer but not the non-fast region + // so the scroll can be handled without involving the main thread. + { + InputHandler::ScrollStatus status = impl->ScrollBegin( + BeginState(gfx::Point(80, 20), gfx::Vector2dF(0, 1)).get(), + ui::ScrollInputType::kTouchscreen); + if (base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_FALSE(status.needs_main_thread_hit_test); + } else { + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, + status.main_thread_scrolling_reasons); + } + EXPECT_EQ(scroll_node, impl->CurrentlyScrollingNode()); + impl->ScrollEnd(); + } + + // The bottom-right should hit the bottom layer's non-fast region. + { + InputHandler::ScrollStatus status = impl->ScrollBegin( + BeginState(gfx::Point(80, 80), gfx::Vector2dF(0, 1)).get(), + ui::ScrollInputType::kTouchscreen); + if (base::FeatureList::IsEnabled(features::kScrollUnification)) { + // Even though the point intersects a non-fast region, the first hit + // layer is scrollable from the compositor thread so no need to involve + // the main thread. + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_FALSE(status.needs_main_thread_hit_test); + EXPECT_EQ(scroll_node, impl->CurrentlyScrollingNode()); + impl->ScrollEnd(); + } else { + // Though the middle layer is a composited scroller and is hit first, we + // cannot do a fast scroll because an ancestor on the scroll chain has + // hit a non-fast region. + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, + status.main_thread_scrolling_reasons); + } + } EndTest(); }
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h index c268464..446d467 100644 --- a/cc/trees/layer_tree_settings.h +++ b/cc/trees/layer_tree_settings.h
@@ -187,14 +187,18 @@ // Whether experimental de-jelly effect is allowed. bool allow_de_jelly_effect = false; - // Whether the compositor should attempt to sync with the scroll handlers before submitting a - // frame. + // Whether the compositor should attempt to sync with the scroll handlers + // before submitting a frame. bool enable_synchronized_scrolling = true; #if DCHECK_IS_ON() // Whether to check if any double blur exists. bool log_on_ui_double_background_blur = false; #endif + + // When enabled, enforces new interoperable semantics for 3D transforms. + // See crbug.com/1008483. + bool enable_transform_interop = false; }; class CC_EXPORT LayerListSettings : public LayerTreeSettings {
diff --git a/cc/trees/render_frame_metadata.h b/cc/trees/render_frame_metadata.h index 43af953..ddb416fe 100644 --- a/cc/trees/render_frame_metadata.h +++ b/cc/trees/render_frame_metadata.h
@@ -41,8 +41,7 @@ // specified. SkColor root_background_color = SK_ColorWHITE; - // Scroll offset of the root layer. This optional parameter is only valid - // during tests. + // Scroll offset of the root layer. base::Optional<gfx::Vector2dF> root_scroll_offset; // Selection region relative to the current viewport. If the selection is
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index f57983a..461caf14 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -370,10 +370,6 @@ data_deps = [ ":chrome_app" ] - if (debug_devtools) { - deps += [ ":devtools_debug_resources" ] - } - if (verify_dynamic_libraries) { deps += [ ":verify_libraries_chrome_app" ] } @@ -772,44 +768,6 @@ } } - # When debug_devtools is enabled, symlink the inspector resources into the - # framework bundle. The resources go into the final output directory for the - # framework in the app bundle, rather than the framework bundle in - # root_out_dir, since copy_bundle_data copies the contents of the link - # rather than the link itself. - if (debug_devtools) { - action("devtools_debug_resources") { - _stamp = "$target_out_dir/run_${target_name}.stamp" - - outputs = [ _stamp ] - - script = "//build/symlink.py" - - args = [ - "-f", - "--touch", - rebase_path(_stamp, root_out_dir), - - # Convert the symlink source and destination to an absolute paths, which - # makes symlinking easier (now pwd manipulation). - rebase_path("$root_out_dir/resources/inspector"), - rebase_path( - "$root_out_dir/$chrome_product_full_name.app/Contents/Frameworks/$chrome_framework_name.framework/Versions/$chrome_version_full/Resources/inspector"), - ] - - deps = [ - # Depend on :chrome_app to ensure that the bundle is produced before - # creating or destroying the symlink. - ":chrome_app", - "//third_party/blink/public:blink_devtools_frontend_resources", - "//third_party/blink/public:blink_devtools_inspector_resources", - ] - } - } else { - group("devtools_debug_resources") { - } - } - if (enable_nacl) { bundle_data("chrome_framework_plugins") { sources = []
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index 1ad84a6..2960d10 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -331,8 +331,6 @@ "java/res/drawable-sw600dp-xxxhdpi/google_logo.png", "java/res/drawable-sw600dp/toolbar_shadow.xml", "java/res/drawable-sw600dp/window_background.xml", - "java/res/drawable-sw720dp-v19/window_background.xml", - "java/res/drawable-sw720dp/window_background.xml", "java/res/drawable-v19/action_bar_activity_bg.xml", "java/res/drawable-v19/navigation_bubble_shadow.xml", "java/res/drawable-v21/button_borderless_compat.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 0edaa2a..abe57fa 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1348,7 +1348,6 @@ "java/src/org/chromium/chrome/browser/provider/ChromeBrowserProviderSuggestionsCursor.java", "java/src/org/chromium/chrome/browser/provider/SearchColumns.java", "java/src/org/chromium/chrome/browser/push_messaging/PushMessagingServiceObserver.java", - "java/src/org/chromium/chrome/browser/query_tiles/FakeTileProvider.java", "java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java", "java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java", "java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 1162a36a..c51a9a5 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -167,6 +167,7 @@ "javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java", "javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java", "javatests/src/org/chromium/chrome/browser/download/TestDownloadDirectoryProvider.java", + "javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogTest.java", "javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java", "javatests/src/org/chromium/chrome/browser/download/home/StubbedOfflineContentProvider.java", "javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java",
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java index 1c995d4..5d4a3cd 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java
@@ -85,7 +85,7 @@ } @Override - public void fetchGif(String url, String clientName, Callback<BaseGifImage> callback) { + public void fetchGif(final ImageFetcher.Params params, Callback<BaseGifImage> callback) { callback.onResult(mGifToFetch); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java index 121fbbfc..9fbc7d52 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -46,6 +46,7 @@ import org.chromium.chrome.tab_ui.R; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.modelutil.PropertyModel; import java.util.ArrayList; @@ -108,13 +109,13 @@ private final TabGridDialogMediator.DialogController mTabGridDialogController; private final ThemeColorProvider.ThemeColorObserver mThemeColorObserver; private final ThemeColorProvider.TintObserver mTintObserver; - private final TabModelSelectorTabObserver mTabModelSelectorTabObserver; private final TabModelSelectorObserver mTabModelSelectorObserver; private final ActivityLifecycleDispatcher mActivityLifecycleDispatcher; private final SnackbarManager.SnackbarManageable mSnackbarManageable; private final Snackbar mUndoClosureSnackBar; private TabGroupModelFilter.Observer mTabGroupModelFilterObserver; private PauseResumeWithNativeObserver mPauseResumeWithNativeObserver; + private TabModelSelectorTabObserver mTabModelSelectorTabObserver; private boolean mIsTabGroupUiVisible; private boolean mIsShowingOverViewMode; private boolean mActivatedButNotShown; @@ -261,6 +262,16 @@ if (!mIsTabGroupUiVisible || numTabs == 1) numTabs = 0; RecordHistogram.recordCountHistogram("TabStrip.TabCountOnPageLoad", numTabs); } + + @Override + public void onActivityAttachmentChanged(Tab tab, WindowAndroid window) { + // Remove this when tab is detached since the TabModelSelectorTabObserver is not + // properly destroyed when there is a normal/night mode switch. + if (window == null) { + this.destroy(); + mTabModelSelectorTabObserver = null; + } + } }; mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() { @@ -488,10 +499,12 @@ if (mPauseResumeWithNativeObserver != null) { mActivityLifecycleDispatcher.unregister(mPauseResumeWithNativeObserver); } + if (mTabModelSelectorTabObserver != null) { + mTabModelSelectorTabObserver.destroy(); + } mOverviewModeBehavior.removeOverviewModeObserver(mOverviewModeObserver); mThemeColorProvider.removeThemeColorObserver(mThemeColorObserver); mThemeColorProvider.removeTintObserver(mTintObserver); - mTabModelSelectorTabObserver.destroy(); } private void maybeActivateConditionalTabStrip(@ReasonToShow int reason) {
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_as.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_as.xtb index 9b7bda6..ad0494c 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_as.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_as.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">এক গোট কৰিবলৈ টেববোৰ টানি আনি এৰক</translation> <translation id="6040143037577758943">বন্ধ কৰক</translation> <translation id="6193448654517602979">টেবসমূহ বাছনি কৰক</translation> +<translation id="6510648526783655549">টেবৰ ষ্ট্রিপ বন্ধ কৰক</translation> <translation id="6562820390860419811">টেবটো বাওঁফাললৈ নিয়ক</translation> <translation id="6615455863669487791">মোক দেখুৱাওক</translation> <translation id="6840760312327750441">টেববোৰ একগোট কৰিবলৈ, এটা টেবত স্পৰ্শ কৰি ধৰি ৰাখক। তাৰপাছত, এইটো অন্য এটা টেবলৈ টানি আনি এৰক।</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_bn.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_bn.xtb index 54316e3..4aa64e4 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_bn.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_bn.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">ট্যাবগুলি গ্রুপ করতে ড্র্যাগ করুন</translation> <translation id="6040143037577758943">বন্ধ</translation> <translation id="6193448654517602979">ট্যাব বেছে নিন</translation> +<translation id="6510648526783655549">ট্যাব বার বন্ধ করুন</translation> <translation id="6562820390860419811">বাঁদিকে ট্যাব সরান</translation> <translation id="6615455863669487791">আমাকে দেখান</translation> <translation id="6840760312327750441">ট্যাব গ্রুপ করতে সেটি টাচ করে ধরে থাকুন। তারপর, সেটি টেনে অন্য ট্যাবে নিয়ে আসুন।</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_bs.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_bs.xtb index f99b5d2c0..e7ad91f 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_bs.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_bs.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">Prevucite kartice da ih grupirate</translation> <translation id="6040143037577758943">Zatvori</translation> <translation id="6193448654517602979">Odaberite kartice</translation> +<translation id="6510648526783655549">Zatvori traku kartice</translation> <translation id="6562820390860419811">Pomjeranje kartice ulijevo</translation> <translation id="6615455863669487791">Pokaži mi</translation> <translation id="6840760312327750441">Da grupirate kartice, dodirnite i zadržite jednu karticu. Nakon toga je prevucite na drugu karticu.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_et.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_et.xtb index 75f5c05..97d9bd1 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_et.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_et.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">Lohistage vahelehti, et neid rühmitata</translation> <translation id="6040143037577758943">Sulge</translation> <translation id="6193448654517602979">Valige vahelehed</translation> +<translation id="6510648526783655549">Sule vahelehtede riba</translation> <translation id="6562820390860419811">Teisalda vaheleht vasakule</translation> <translation id="6615455863669487791">Kuva mulle</translation> <translation id="6840760312327750441">Vahelehtede rühmitamiseks puudutage vahelehte pikalt. Seejärel lohistage see teise vahelehe peale.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_hr.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_hr.xtb index 91765660..91ed932 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_hr.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_hr.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">Povucite kartice da biste ih grupirali</translation> <translation id="6040143037577758943">Zatvori</translation> <translation id="6193448654517602979">Odaberite kartice</translation> +<translation id="6510648526783655549">Zatvorite vrpcu kartica</translation> <translation id="6562820390860419811">Pomakni karticu ulijevo</translation> <translation id="6615455863669487791">Pokaži mi</translation> <translation id="6840760312327750441">Da biste grupirali kartice, dodirnite i držite karticu. Zatim je povucite na drugu karticu.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_iw.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_iw.xtb index e419445..cdfd82d 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_iw.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_iw.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">ניתן לגרור כרטיסיות כדי לקבץ אותן</translation> <translation id="6040143037577758943">סגור</translation> <translation id="6193448654517602979">בחירת כרטיסיות</translation> +<translation id="6510648526783655549">סגירת שורת הכרטיסיות</translation> <translation id="6562820390860419811">העברת הכרטיסיה ימינה</translation> <translation id="6615455863669487791">הראה לי</translation> <translation id="6840760312327750441">כדי לקבץ כרטיסיות, יש ללחוץ לחיצה ארוכה על כרטיסייה. בזמן הלחיצה, יש לגרור אותה אל כרטיסייה אחרת.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ko.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ko.xtb index 9e4e91e..8e98313 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ko.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ko.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">탭을 드래그하여 그룹화하세요.</translation> <translation id="6040143037577758943">닫기</translation> <translation id="6193448654517602979">탭 선택</translation> +<translation id="6510648526783655549">탭 표시줄 닫기</translation> <translation id="6562820390860419811">탭을 왼쪽으로 이동</translation> <translation id="6615455863669487791">표시</translation> <translation id="6840760312327750441">탭을 그룹화하려면 탭을 길게 터치한 다음 다른 탭으로 드래그하세요.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_lo.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_lo.xtb index da0dbf6..650da5f 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_lo.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_lo.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">ລາກແຖບເພື່ອຈັດກຸ່ມພວກມັນ</translation> <translation id="6040143037577758943">ປິດ</translation> <translation id="6193448654517602979">ເລືອກແຖບ</translation> +<translation id="6510648526783655549">ປິດລາຍແຖບ</translation> <translation id="6562820390860419811">ຍ້າຍແຖບໄປຊ້າຍ</translation> <translation id="6615455863669487791">ສະແດງຂ້ອຍ</translation> <translation id="6840760312327750441">ເພື່ອຈັດກຸ່ມແຖບ, ແຕະແຖບໃດໜຶ່ງຄ້າງໄວ້. ຈາກນັ້ນ, ລາກມັນໄປໃສ່ແຖບອື່ນ.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_lt.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_lt.xtb index afe7c69..d8abb98 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_lt.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_lt.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">Vilkite skirtukus, kad juos sugrupuotumėte</translation> <translation id="6040143037577758943">Uždaryti</translation> <translation id="6193448654517602979">Pasirinkti skirtukus</translation> +<translation id="6510648526783655549">Uždaryti skirtuko juostelę</translation> <translation id="6562820390860419811">Perkelti skirtuką į kairę</translation> <translation id="6615455863669487791">Rodyti</translation> <translation id="6840760312327750441">Norėdami grupuoti skirtukus, palieskite ir palaikykite skirtuką. Tada nuvilkite jį į kitą skirtuką.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ml.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ml.xtb index 814b811..ce22ede 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ml.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ml.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">ടാബുകൾ ഗ്രൂപ്പ് ചെയ്യാൻ അവ വലിച്ചിടുക</translation> <translation id="6040143037577758943">അടയ്ക്കുക</translation> <translation id="6193448654517602979">ടാബുകൾ തിരഞ്ഞെടുക്കുക</translation> +<translation id="6510648526783655549">തുറന്ന് വച്ചിട്ടുള്ള ടാബുകൾ അടയ്ക്കുക</translation> <translation id="6562820390860419811">ടാബ് ഇടത്തേക്ക് നീക്കുക</translation> <translation id="6615455863669487791">എന്നെ കാണിക്കുക</translation> <translation id="6840760312327750441">ടാബുകൾ ഗ്രൂപ്പ് ചെയ്യാൻ, ഒരു ടാബിൽ സ്പർശിച്ച് പിടിക്കുക. തുടർന്ന്, അത് മറ്റൊരു ടാബിലേക്ക് വലിച്ചിടുക.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_sl.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_sl.xtb index 1c27cdbd..06111439 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_sl.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_sl.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">Povlecite zavihke, če jih želite združiti v skupino</translation> <translation id="6040143037577758943">Zapri</translation> <translation id="6193448654517602979">Izberite zavihke</translation> +<translation id="6510648526783655549">Zapri trak z zavihki</translation> <translation id="6562820390860419811">Premakni zavihek v levo</translation> <translation id="6615455863669487791">Pokaži mi</translation> <translation id="6840760312327750441">Če želite združiti zavihke v skupino, pridržite zavihek. Nato ga povlecite na drug zavihek.</translation>
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ta.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ta.xtb index 02da002..ab93e59 100644 --- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ta.xtb +++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ta.xtb
@@ -24,6 +24,7 @@ <translation id="58326064309361797">தாவல்களை இழுப்பதன் மூலம் அவற்றைக் குழுவாக்கலாம்</translation> <translation id="6040143037577758943">மூடு</translation> <translation id="6193448654517602979">தாவல்களைத் தேர்ந்தெடுக்கவும்</translation> +<translation id="6510648526783655549">தாவல் பட்டையை மூடும்</translation> <translation id="6562820390860419811">தாவலை இடப்புறம் நகர்த்து</translation> <translation id="6615455863669487791">எனக்கு காண்பி</translation> <translation id="6840760312327750441">தாவல்களைக் குழுவாக்க தாவலைத் தொட்டுப் பிடித்திருக்கவும். பிறகு அதை மற்றொரு தாவலுக்கு இழுத்துச்சென்று விடவும்.</translation>
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java index f45f30c81..2646672 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -50,6 +50,7 @@ import org.chromium.chrome.browser.tab.TabCreationState; import org.chromium.chrome.browser.tab.TabImpl; import org.chromium.chrome.browser.tab.TabLaunchType; +import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; import org.chromium.chrome.browser.tabmodel.TabModel; @@ -142,6 +143,8 @@ ArgumentCaptor<TabGroupModelFilter.Observer> mTabGroupModelFilterObserverArgumentCaptor; @Captor ArgumentCaptor<PauseResumeWithNativeObserver> mPauseResumeWithNativeObserverArgumentCaptor; + @Captor + ArgumentCaptor<TabObserver> mTabObserverCaptor; private TabImpl mTab1; private TabImpl mTab2; @@ -260,6 +263,9 @@ doReturn(POSITION1).when(mTabModel).indexOf(mTab1); doReturn(POSITION2).when(mTabModel).indexOf(mTab2); doReturn(POSITION3).when(mTabModel).indexOf(mTab3); + doNothing().when(mTab1).addObserver(mTabObserverCaptor.capture()); + doNothing().when(mTab2).addObserver(mTabObserverCaptor.capture()); + doNothing().when(mTab3).addObserver(mTabObserverCaptor.capture()); if (TabUiFeatureUtilities.isConditionalTabStripEnabled()) { doReturn(false).when(mTabModelFilter).isIncognito(); @@ -1287,4 +1293,19 @@ assertThat( mModel.get(TabGroupUiProperties.LEFT_BUTTON_ON_CLICK_LISTENER), equalTo(listener)); } + + @Test + public void testTabModelSelectorTabObserverDestroyWhenDetach() { + InOrder tabObserverDestroyInOrder = inOrder(mTab1); + initAndAssertProperties(mTab1); + + mTabObserverCaptor.getValue().onActivityAttachmentChanged(mTab1, null); + + tabObserverDestroyInOrder.verify(mTab1).removeObserver(mTabObserverCaptor.capture()); + + mTabGroupUiMediator.destroy(); + + tabObserverDestroyInOrder.verify(mTab1, never()) + .removeObserver(mTabObserverCaptor.capture()); + } }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java index 65a61907..85f6e47 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java
@@ -113,7 +113,6 @@ if (!canActivate()) return; mStreamState = StreamState.ACTIVE; - mStream.onActive(); } /** Calls {@link Stream#onInactive()}. */ @@ -121,7 +120,6 @@ if (mStreamState != StreamState.ACTIVE) return; mStreamState = StreamState.INACTIVE; - mStream.onInactive(); } /** Calls {@link Stream#onHide()}. */
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStream.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStream.java index ee13d31c..757af8ca 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStream.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStream.java
@@ -10,7 +10,6 @@ import android.content.Context; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; -import android.os.Bundle; import android.util.Base64; import android.view.ContextThemeWrapper; import android.view.View; @@ -95,8 +94,6 @@ public class BasicStream implements Stream, ModelProviderObserver, OnLayoutChangeListener { private static final String TAG = "BasicStream"; - @VisibleForTesting - static final String KEY_STREAM_STATE = "stream-state"; private static final long DEFAULT_LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS = 1000L; private static final long DEFAULT_MINIMUM_SPINNER_SHOW_TIME_MS = 500L; private static final long DEFAULT_SPINNER_DELAY_TIME_MS = 500L; @@ -228,16 +225,6 @@ } @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - onCreate((String) null); - return; - } - - onCreate(savedInstanceState.getString(KEY_STREAM_STATE)); - } - - @Override public void onCreate(@Nullable String savedInstanceState) { checkState(mRecyclerView == null, "Can't call onCreate() multiple times."); setupRecyclerView(); @@ -285,12 +272,6 @@ } @Override - public void onActive() {} - - @Override - public void onInactive() {} - - @Override public void onHide() { mAdapter.setShown(false); mContextMenuManager.dismissPopup(); @@ -319,13 +300,6 @@ } @Override - public Bundle getSavedInstanceState() { - Bundle bundle = new Bundle(); - bundle.putString(KEY_STREAM_STATE, getSavedInstanceStateString()); - return bundle; - } - - @Override public String getSavedInstanceStateString() { StreamSavedInstanceState.Builder builder = StreamSavedInstanceState.newBuilder(); if (mModelProvider != null && mModelProvider.getSessionId() != null) {
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/stream/Stream.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/stream/Stream.java index 75a0582..a28fc5e 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/stream/Stream.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/stream/Stream.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.feed.shared.stream; -import android.os.Bundle; import android.view.View; import androidx.annotation.IntDef; @@ -18,22 +17,8 @@ int POSITION_NOT_KNOWN = Integer.MIN_VALUE; /** - * Called when the Stream is being created. This method should only be called once. {@code - * savedInstanceState} should be a previous bundle returned from {@link - * #getSavedInstanceState()}. The Stream will restore from this bundle as it starts up. This - * maps similarly to {@link android.app.Activity#onCreate(Bundle)}. - * - * @param savedInstanceState state to restore to. - * @throws IllegalStateException if method is called multiple times. - */ - void onCreate(@Nullable Bundle savedInstanceState); - - /** - * Called when the Stream is being created. This method functions identically to {@link - * #onCreate(Bundle)} but allows a host to provide a String instead of a Bundle. This method - * should only be called once. If this method is used, {@link #onCreate(Bundle)} should not be - * used. {@code savedInstanceState} should be a previous string returned from {@link - * #getSavedInstanceStateString()}. + * Called when the Stream is being created. {@code savedInstanceState} should be a previous + * string returned from {@link #getSavedInstanceStateString()}. * * @param savedInstanceState state to restore to. * @throws IllegalStateException if method is called multiple times. @@ -49,19 +34,6 @@ void onShow(); /** - * Called when the Stream's view is completely visible and may be acted on by a user. This maps - * similarly to {@link android.app.Activity#onResume()}. - */ - void onActive(); - /** - * Called when the Stream view may not be acted on by a user. Generally when the Stream is no - * longer fully visible. Should also be called when the Activity hosting the Stream is not the - * active activity even though Stream may be fully visible. This maps similarly to {@link - * android.app.Activity#onPause()}. - */ - void onInactive(); - - /** * Called when the Stream is no longer visible on screen. This should act similarly to {@link * android.app.Activity#onStop()}. */ @@ -74,25 +46,17 @@ void onDestroy(); /** - * Called during {@link android.app.Activity#onSaveInstanceState(Bundle)}. The returned bundle - * should be passed to {@link #onCreate(Bundle)} when the activity is recreated and the stream - * needs to be recreated. - */ - Bundle getSavedInstanceState(); - - /** - * Call during {@link android.app.Activity#onSaveInstanceState(Bundle)}. The returned string - * should be passed to {@link #onCreate(String)} when the activity is recreated and the stream - * needs to be recreated. + * The returned string should be passed to {@link #onCreate(String)} when the activity is + * recreated and the stream needs to be recreated. */ String getSavedInstanceStateString(); /** * Return the root view which holds all card stream views. The Feed library builds Views when * this method is called (caches as needed). This must be called after {@link - * #onCreate(Bundle)}. Multiple calls to this method will return the same View. + * #onCreate()}. Multiple calls to this method will return the same View. * - * @throws IllegalStateException when called before {@link #onCreate(Bundle)}. + * @throws IllegalStateException when called before {@link #onCreate()}. */ View getView();
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java index 59841524..e9dc9b0 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.feed.v2; import android.content.Context; -import android.os.Bundle; import android.view.ContextThemeWrapper; import android.view.View; @@ -45,11 +44,6 @@ } @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - // TODO(jianli): TO be removed from Stream API since it is never used. - } - - @Override public void onCreate(@Nullable String savedInstanceState) { setupRecyclerView(); // TODO(jianli): Restore scroll state. @@ -59,12 +53,6 @@ public void onShow() {} @Override - public void onActive() {} - - @Override - public void onInactive() {} - - @Override public void onHide() {} @Override @@ -73,12 +61,6 @@ } @Override - public Bundle getSavedInstanceState() { - // TODO(jianli): TO be removed from Stream API since it is never used. - return new Bundle(); - } - - @Override public String getSavedInstanceStateString() { // TODO(jianli): Return saved scroll state as serializedf string; return "";
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java index c890562a..5604faad 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
@@ -70,10 +70,10 @@ import org.chromium.chrome.test.util.ViewUtils; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.RecyclerViewTestUtils; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule; import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites; import org.chromium.components.embedder_support.util.UrlConstants; -import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.EmbeddedTestServer;
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStreamTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStreamTest.java index 351d027..b3d0e6e3 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStreamTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStreamTest.java
@@ -17,7 +17,6 @@ import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import static org.chromium.chrome.browser.feed.library.basicstream.BasicStream.KEY_STREAM_STATE; import static org.chromium.chrome.browser.feed.library.common.testing.RunnableSubject.assertThatRunnable; import static org.chromium.chrome.browser.feed.shared.stream.Stream.POSITION_NOT_KNOWN; @@ -26,7 +25,6 @@ import android.app.Activity; import android.content.Context; import android.os.Build.VERSION_CODES; -import android.os.Bundle; import android.util.Base64; import android.view.View; import android.widget.FrameLayout; @@ -221,7 +219,7 @@ mLayoutManager = new LinearLayoutManagerWithFakePositioning(mContext); mBasicStream = createBasicStream(mLayoutManager); - mBasicStream.onCreate((Bundle) null); + mBasicStream.onCreate(null); } @Test @@ -481,13 +479,6 @@ } @Test - public void testLifecycle_onCreateWithBundleCalledOnlyOnce() { - // onCreate is called once in setup - assertThatRunnable(() -> mBasicStream.onCreate(new Bundle())) - .throwsAnExceptionOfType(IllegalStateException.class); - } - - @Test public void testLifecycle_onCreateWithStringCalledOnlyOnce() { // onCreate is called once in setup assertThatRunnable(() -> mBasicStream.onCreate("")) @@ -566,16 +557,6 @@ } @Test - public void testGetSavedInstanceState() { - mBasicStream.onShow(); - - Bundle bundle = mBasicStream.getSavedInstanceState(); - assertThat(bundle.getString(KEY_STREAM_STATE)) - .isEqualTo( - Base64.encodeToString(SAVED_INSTANCE_STATE.toByteArray(), Base64.DEFAULT)); - } - - @Test public void testGetSavedInstanceStateString_beforeShow() throws InvalidProtocolBufferException { StreamSavedInstanceState savedInstanceState = StreamSavedInstanceState.parseFrom( decodeSavedInstanceStateString(mBasicStream.getSavedInstanceStateString())); @@ -622,7 +603,7 @@ public void testRestore() { mBasicStream.onShow(); - Bundle bundle = mBasicStream.getSavedInstanceState(); + String savedInstanceState = mBasicStream.getSavedInstanceStateString(); mBasicStream.onHide(); mBasicStream.onDestroy(); @@ -631,7 +612,7 @@ .thenReturn(mRestoredModelProvider); mBasicStream = createBasicStream(new LinearLayoutManagerWithFakePositioning(mContext)); - mBasicStream.onCreate(bundle); + mBasicStream.onCreate(savedInstanceState); mBasicStream.onShow(); @@ -662,7 +643,7 @@ public void testRestore_doesNotShowZeroState() { mBasicStream.onShow(); - Bundle bundle = mBasicStream.getSavedInstanceState(); + String savedInstanceState = mBasicStream.getSavedInstanceStateString(); mBasicStream.onHide(); mBasicStream.onDestroy(); @@ -672,7 +653,7 @@ reset(mStreamDriver); mBasicStream = createBasicStream(new LinearLayoutManagerWithFakePositioning(mContext)); - mBasicStream.onCreate(bundle); + mBasicStream.onCreate(savedInstanceState); mBasicStream.onShow(); @@ -683,7 +664,7 @@ @Test public void testRestore_showsZeroStateIfNoSessionToRestore() { mBasicStream = createBasicStream(new LinearLayoutManagerWithFakePositioning(mContext)); - mBasicStream.onCreate(Bundle.EMPTY); + mBasicStream.onCreate(""); mBasicStream.onShow(); @@ -698,13 +679,13 @@ public void testRestore_invalidSession() { mBasicStream.onShow(); - Bundle bundle = mBasicStream.getSavedInstanceState(); + String savedInstanceState = mBasicStream.getSavedInstanceStateString(); mBasicStream.onHide(); mBasicStream.onDestroy(); mBasicStream = createBasicStream(new LinearLayoutManagerWithFakePositioning(mContext)); - mBasicStream.onCreate(bundle); + mBasicStream.onCreate(savedInstanceState); mBasicStream.onShow(); verify(mModelProvider).registerObserver(mBasicStream); @@ -714,14 +695,11 @@ public void testRestore_invalidBase64Encoding() { mBasicStream.onShow(); - Bundle bundle = new Bundle(); - bundle.putString(KEY_STREAM_STATE, "=invalid"); - mBasicStream.onHide(); mBasicStream.onDestroy(); mBasicStream = createBasicStream(new LinearLayoutManagerWithFakePositioning(mContext)); - assertThatRunnable(() -> mBasicStream.onCreate(bundle)) + assertThatRunnable(() -> mBasicStream.onCreate("=invalid")) .throwsAnExceptionOfType(RuntimeException.class); } @@ -729,15 +707,13 @@ public void testRestore_invalidProtocolBuffer() { mBasicStream.onShow(); - Bundle bundle = new Bundle(); - bundle.putString( - KEY_STREAM_STATE, Base64.encodeToString("invalid".getBytes(UTF_8), Base64.DEFAULT)); - mBasicStream.onHide(); mBasicStream.onDestroy(); mBasicStream = createBasicStream(new LinearLayoutManagerWithFakePositioning(mContext)); - assertThatRunnable(() -> mBasicStream.onCreate(bundle)) + assertThatRunnable(() + -> mBasicStream.onCreate(Base64.encodeToString( + "invalid".getBytes(UTF_8), Base64.DEFAULT))) .throwsAnExceptionOfType(RuntimeException.class); } @@ -745,7 +721,7 @@ public void testRestore_createsStreamDriver() { mBasicStream.onShow(); - Bundle bundle = mBasicStream.getSavedInstanceState(); + String savedInstanceState = mBasicStream.getSavedInstanceStateString(); mBasicStream.onHide(); mBasicStream.onDestroy(); @@ -754,7 +730,7 @@ .thenReturn(mRestoredModelProvider); mBasicStream = createBasicStream(new LinearLayoutManagerWithFakePositioning(mContext)); - mBasicStream.onCreate(bundle); + mBasicStream.onCreate(savedInstanceState); mBasicStream.onShow(); @@ -765,7 +741,7 @@ public void testRestore_createsStreamDriver_afterFailure() { mBasicStream.onShow(); - Bundle bundle = mBasicStream.getSavedInstanceState(); + String savedInstanceState = mBasicStream.getSavedInstanceStateString(); mBasicStream.onHide(); mBasicStream.onDestroy(); @@ -774,7 +750,7 @@ .thenReturn(mRestoredModelProvider); mBasicStream = createBasicStream(new LinearLayoutManagerWithFakePositioning(mContext)); - mBasicStream.onCreate(bundle); + mBasicStream.onCreate(savedInstanceState); // onSessionFinish indicates the restore has failed. mBasicStream.onSessionFinished(UiContext.getDefaultInstance());
diff --git a/chrome/android/java/res/drawable-sw720dp-v19/window_background.xml b/chrome/android/java/res/drawable-sw720dp-v19/window_background.xml deleted file mode 100644 index 527afabec..0000000 --- a/chrome/android/java/res/drawable-sw720dp-v19/window_background.xml +++ /dev/null
@@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2015 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. --> - -<!-- Tablets from api 19 and up have the top notification bar --> -<layer-list - xmlns:android="http://schemas.android.com/apk/res/android" > - <item> - <shape android:shape="rectangle"> - <solid android:color="@android:color/black" /> - </shape> - </item> - <item - android:top="25dp" - android:bottom="0px"> - <nine-patch android:src="@drawable/toolbar_background" /> - </item> -</layer-list>
diff --git a/chrome/android/java/res/drawable-sw720dp/window_background.xml b/chrome/android/java/res/drawable-sw720dp/window_background.xml deleted file mode 100644 index d1940b8..0000000 --- a/chrome/android/java/res/drawable-sw720dp/window_background.xml +++ /dev/null
@@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2015 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. --> - -<!-- Tablets from api 18 and below didn't have the top notification bar --> -<layer-list - xmlns:android="http://schemas.android.com/apk/res/android" > - <item> - <nine-patch android:src="@drawable/toolbar_background" /> - </item> -</layer-list>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoDelegateImpl.java index acd75d7..b6330b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoDelegateImpl.java
@@ -77,7 +77,8 @@ if (!isAnimatedLogoShowing && mAnimatedLogoUrl != null) { RecordHistogram.recordSparseHistogram(LOGO_CLICK_UMA_NAME, CTA_IMAGE_CLICKED); mLogoView.showLoadingView(); - mImageFetcher.fetchGif(mAnimatedLogoUrl, ImageFetcher.NTP_ANIMATED_LOGO_UMA_CLIENT_NAME, + mImageFetcher.fetchGif(ImageFetcher.Params.create(mAnimatedLogoUrl, + ImageFetcher.NTP_ANIMATED_LOGO_UMA_CLIENT_NAME), (BaseGifImage animatedLogoImage) -> { if (mIsDestroyed || animatedLogoImage == null) return; mLogoView.playAnimatedLogo(animatedLogoImage);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java index 92d53ce..2a09d6ec4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java
@@ -56,7 +56,7 @@ /** Called to set the list of query tiles to be displayed in the suggestion. */ public void setTiles(List<QueryTile> tiles) { - getTileCoordinator().setTiles(new ArrayList<>(tiles)); + getTileCoordinator().setTiles(tiles == null ? new ArrayList<>() : new ArrayList<>(tiles)); } /** Called to clean up resources used by this class. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java index 6e371209..e123130 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java
@@ -72,7 +72,7 @@ List<QueryTile> tiles = suggestion.getQueryTiles(); if (mLastProcessedTiles != null && mLastProcessedTiles.equals(tiles)) return; - mLastProcessedTiles = new ArrayList<>(tiles); + mLastProcessedTiles = tiles == null ? null : new ArrayList<>(tiles); mQueryTileSuggestionCallback.onResult(tiles); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/FakeTileProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/FakeTileProvider.java deleted file mode 100644 index af2a5b6b..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/FakeTileProvider.java +++ /dev/null
@@ -1,201 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.query_tiles; - -import org.chromium.base.Callback; -import org.chromium.chrome.browser.GlobalDiscardableReferencePool; -import org.chromium.chrome.browser.image_fetcher.ImageFetcher; -import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig; -import org.chromium.chrome.browser.image_fetcher.ImageFetcherFactory; -import org.chromium.components.query_tiles.QueryTile; -import org.chromium.components.query_tiles.TileProvider; - -import java.util.ArrayList; -import java.util.List; - -/** - * A test tile provider class that fakes the backend and provides example data. - */ -public class FakeTileProvider implements TileProvider { - private List<QueryTile> mTiles = new ArrayList<>(); - - public FakeTileProvider() { - FakeTile tile = null; - List<QueryTile> children = new ArrayList<>(); - - children.clear(); - children.add(new FakeTile("tile1_1", "India", - "http://t2.gstatic.com/images?q=tbn:ANd9GcTCr5Ene2snzAE_tOxcZ6AlKrH8CLA4aYQYYLRepngj5oh5bwHagRF0ootjfRDlM1k", - null)); - children.add(new FakeTile("tile1_2", "Latest news", - "http://t1.gstatic.com/images?q=tbn:ANd9GcQZIopJYcA7KFGcpA2ye385iiEEtkOfZn6uDQrDvTlRD_S-e9-KOkKNh9oE2V2K_Uk", - null)); - children.add(new FakeTile("tile1_3", "Video", - "http://t1.gstatic.com/images?q=tbn:ANd9GcSSUTrzE2L7LWwsvqevSwwj-CJYmhzYsXER-Qy9jCUAF9Ncu6VJcSymtksFq6EbAZU", - null)); - children.add(new FakeTile("tile1_4", "News live", - "http://t0.gstatic.com/images?q=tbn:ANd9GcRjuMvz4MlWifrdoKEv9Ysjx9TL_Q6p9PZQf1nmnmqcz4OUgpU9gf3WMkKB9_JQK-U", - null)); - children.add(new FakeTile("tile1_5", "Entertainment", - "http://t1.gstatic.com/images?q=tbn:ANd9GcQ1DgiH1n3zwD9M6fGlvXjUc1q7Vviod8kE3Ak4gqPG6sfEnJB3Ek0Ag_WekvBc1c0", - null)); - tile = new FakeTile("1", "News", - "http://t0.gstatic.com/images?q=tbn:ANd9GcTFlesDfqnMIxCvcotuKHBR-U4cSOG1ceOcoitEOWuiRq9MqNn05e6agwcQHVXiQ3A", - new ArrayList<>(children)); - mTiles.add(tile); - - children.clear(); - children.add(new FakeTile("tile2_1", "New releases", - "http://t3.gstatic.com/images?q=tbn:ANd9GcT0TXKxHnR-ZsSgGoZQU-q3p3IJinh04R7_-ApKqvU5dG08GeEI_tBrposmeXBj_sM", - null)); - children.add(new FakeTile("tile2_2", "Best 2019", - "http://t2.gstatic.com/images?q=tbn:ANd9GcQj0bEH217cUI5_RZIFu70U6HyxHjQAJjr_cRE_90KUzitct9UmmbiPIth64NVmBbw", - null)); - children.add(new FakeTile("tile2_3", "Action", - "http://t2.gstatic.com/images?q=tbn:ANd9GcRRfln9zLxGtoxSNm7A5aZONaU0UKItu-QMCPFBB3vB278uJzzx0-DyCnEFJbWrFd4", - null)); - children.add(new FakeTile("tile2_4", "Romantic", - "http://t0.gstatic.com/images?q=tbn:ANd9GcRtP-cfkS_wTEiLoJWzhqTPsS_K3ibnMEPis3Mc4VFSyKKKhFjrpLzr5HqGIxgd8Xk", - null)); - children.add(new FakeTile("tile2_5", "Video", - "http://t2.gstatic.com/images?q=tbn:ANd9GcTzYvuKtm_0lZlf2gJiY7NAFARzFmM8CdsZsRlUw5v86bZCHBDATZ_meercGPrPiiA", - null)); - tile = new FakeTile("2", "Films", - "http://t1.gstatic.com/images?q=tbn:ANd9GcRuSbDebh0CCLeMEr2Wh8qmHpWSKdbqrZFWZsndsu7TMtPeeNDYIKrQqexISQ4Bk0U", - new ArrayList<>(children)); - mTiles.add(tile); - - children.clear(); - children.add(new FakeTile("tile3_1", "Sports News", - "http://t0.gstatic.com/images?q=tbn:ANd9GcTPE3E_bwbTfnnbncoJWr0nVGjYq5Xo1KVzsd1RjVzYzQ7bDmkIfiJq5YICMO5oOC0", - null)); - children.add(new FakeTile("tile3_2", "Cricket", - "http://t1.gstatic.com/images?q=tbn:ANd9GcSKpIPKbz3xQNTAFcj0RjvAMy4VkQQ59UB9MHbrWv18UnWMwzziQ0gDf31bBGCWW84", - null)); - children.add(new FakeTile("tile3_3", "Live Scores", - "http://t2.gstatic.com/images?q=tbn:ANd9GcTNe2t7j38aebbbrDhrPWqVoSxJontlVju_wpoMF1RPZC8tdTFhTsVJM_Ax7miNQnA", - null)); - children.add(new FakeTile("tile3_4", "India national cricket team", - "http://t1.gstatic.com/images?q=tbn:ANd9GcTdAED2AVXWGbch4xSJdjAsQVjMN-g2COE38eCxuJ-g3NoAFFtXsZY-OEvHNj3o1qU", - null)); - children.add(new FakeTile("tile3_5", "Shikhar Dhawan", - "http://t0.gstatic.com/images?q=tbn:ANd9GcRM7ciJIz1xCbj7Yoo0IwagKAmZ9w6bcyoPAb0aGiAIDPFtW6uGyZgqsoeqspfZGjk", - null)); - tile = new FakeTile("3", "Sports", - "http://t0.gstatic.com/images?q=tbn:ANd9GcTPOt9GGURBjUQxg-U5-cVt8lJqmvsO6xV1utP--yyHt_YVfAbi3c4c6JPG3mQyYXA", - new ArrayList<>(children)); - mTiles.add(tile); - - children.clear(); - children.add(new FakeTile("tile4_1", "Stock market", - "http://t1.gstatic.com/images?q=tbn:ANd9GcQx19VxfDCoQB6ju0ar378vNq8Wvkjkbw9rdEYD4f5JlpEFMIJBJj93yonFoEKPD4E", - null)); - children.add(new FakeTile("tile4_2", "Financial news", - "http://t1.gstatic.com/images?q=tbn:ANd9GcSUAGi0zETa0LKs8mddhIRQd1kzLvm8JLcsOpDWnaBqmH8gu-Ildf5GO0mkW_xIrNY", - null)); - children.add(new FakeTile("tile4_3", "Real estate", - "http://t0.gstatic.com/images?q=tbn:ANd9GcTFlesDfqnMIxCvcotuKHBR-U4cSOG1ceOcoitEOWuiRq9MqNn05e6agwcQHVXiQ3A", - null)); - children.add(new FakeTile("tile4_4", "Mutual fund", - "http://t0.gstatic.com/images?q=tbn:ANd9GcRM7ciJIz1xCbj7Yoo0IwagKAmZ9w6bcyoPAb0aGiAIDPFtW6uGyZgqsoeqspfZGjk", - null)); - children.add(new FakeTile("tile4_5", "Gold", - "http://t3.gstatic.com/images?q=tbn:ANd9GcRarq7ZX7nv7RWjWl7NvmWp83XO6NgPpkU3eY_FzjfBsoOLBGBBNZK5UvRl4KhK6tc", - null)); - tile = new FakeTile("4", "Investment", - "http://t1.gstatic.com/images?q=tbn:ANd9GcSUAGi0zETa0LKs8mddhIRQd1kzLvm8JLcsOpDWnaBqmH8gu-Ildf5GO0mkW_xIrNY", - new ArrayList<>(children)); - mTiles.add(tile); - - children.clear(); - children.add(new FakeTile("tile5_1", "Food", - "http://t2.gstatic.com/images?q=tbn:ANd9GcR4QAsqpRFDC1bXNGrhSOEOZR-nD-jr7wIuV_p-BCRy6o2f_iWbvD8-5Ay8govJfao", - null)); - children.add(new FakeTile("tile5_2", "Diet", - "http://t2.gstatic.com/images?q=tbn:ANd9GcR4QAsqpRFDC1bXNGrhSOEOZR-nD-jr7wIuV_p-BCRy6o2f_iWbvD8-5Ay8govJfao", - null)); - children.add(new FakeTile("tile5_3", "Women", - "http://t2.gstatic.com/images?q=tbn:ANd9GcR4QAsqpRFDC1bXNGrhSOEOZR-nD-jr7wIuV_p-BCRy6o2f_iWbvD8-5Ay8govJfao", - null)); - children.add(new FakeTile("tile5_4", "Kids", - "http://t2.gstatic.com/images?q=tbn:ANd9GcR4QAsqpRFDC1bXNGrhSOEOZR-nD-jr7wIuV_p-BCRy6o2f_iWbvD8-5Ay8govJfao", - null)); - children.add(new FakeTile("tile5_5", "Exercise", - "http://t2.gstatic.com/images?q=tbn:ANd9GcR4QAsqpRFDC1bXNGrhSOEOZR-nD-jr7wIuV_p-BCRy6o2f_iWbvD8-5Ay8govJfao", - null)); - tile = new FakeTile("5", "Health", - "http://t2.gstatic.com/images?q=tbn:ANd9GcR4QAsqpRFDC1bXNGrhSOEOZR-nD-jr7wIuV_p-BCRy6o2f_iWbvD8-5Ay8govJfao", - new ArrayList<>(children)); - mTiles.add(tile); - - children.clear(); - children.add(new FakeTile("tile6_1", "New Releases", - "http://t0.gstatic.com/images?q=tbn:ANd9GcSb3yVUlA_2p1hnTB-iAWHiHbamV7WXWuTtF7ph8UMVypPZtNcWijS9iJanH_Tph0M", - null)); - children.add(new FakeTile("tile6_2", "Best 2019", - "http://t0.gstatic.com/images?q=tbn:ANd9GcSb3yVUlA_2p1hnTB-iAWHiHbamV7WXWuTtF7ph8UMVypPZtNcWijS9iJanH_Tph0M", - null)); - children.add(new FakeTile("tile6_3", "Hindi", - "http://t0.gstatic.com/images?q=tbn:ANd9GcSb3yVUlA_2p1hnTB-iAWHiHbamV7WXWuTtF7ph8UMVypPZtNcWijS9iJanH_Tph0M", - null)); - children.add(new FakeTile("tile6_4", "Music Download", - "http://t0.gstatic.com/images?q=tbn:ANd9GcSb3yVUlA_2p1hnTB-iAWHiHbamV7WXWuTtF7ph8UMVypPZtNcWijS9iJanH_Tph0M", - null)); - children.add(new FakeTile("tile6_5", "Live streaming", - "http://t0.gstatic.com/images?q=tbn:ANd9GcSb3yVUlA_2p1hnTB-iAWHiHbamV7WXWuTtF7ph8UMVypPZtNcWijS9iJanH_Tph0M", - null)); - tile = new FakeTile("6", "Music", - "http://t0.gstatic.com/images?q=tbn:ANd9GcSb3yVUlA_2p1hnTB-iAWHiHbamV7WXWuTtF7ph8UMVypPZtNcWijS9iJanH_Tph0M", - new ArrayList<>(children)); - mTiles.add(tile); - - children.clear(); - children.add(new FakeTile("tile7_1", "Subtopic", "", null)); - children.add(new FakeTile("tile7_2", "Subtopic", "", null)); - tile = new FakeTile("7", "Tile 7", "", children); - mTiles.add(tile); - tile = new FakeTile("8", "Tile 8", "", children); - mTiles.add(tile); - tile = new FakeTile("9", "Tile 9", "", children); - mTiles.add(tile); - tile = new FakeTile("10", "Tile 10", "", children); - mTiles.add(tile); - tile = new FakeTile("11", "Tile 11", "", children); - mTiles.add(tile); - tile = new FakeTile("12", "Tile 12", "", children); - mTiles.add(tile); - } - - @Override - public void getQueryTiles(Callback<List<QueryTile>> callback) { - callback.onResult(mTiles); - } - - private QueryTile findTile(String id) { - if (id == null) return null; - for (QueryTile tile : mTiles) { - if (tile.id.equals(id)) return tile; - for (QueryTile subtile : tile.children) { - if (subtile.id.equals(id)) return subtile; - } - } - return null; - } - - private ImageFetcher getImageFetcher() { - return ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.IN_MEMORY_WITH_DISK_CACHE, - GlobalDiscardableReferencePool.getReferencePool()); - } - - private static class FakeTile extends QueryTile { - public String url; - - public FakeTile(String id, String displayTitle, String url, List<QueryTile> children) { - super(id, displayTitle, displayTitle, displayTitle, new String[] {url}, new String[0], - children); - this.url = url; - } - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java index a345bb54..9ff7c66 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java
@@ -46,7 +46,9 @@ "most_visited_max_rows_small_screen"; private static final String MOST_VISITED_MAX_ROWS_NORMAL_SCREEN = "most_visited_max_rows_normal_screen"; - private static final int SMALL_SCREEN_HEIGHT_THRESHOLD_DP = 750; + private static final String VARIATION_SMALL_SCREEN_HEIGHT_THRESHOLD_DP = + "small_screen_height_threshold_dp"; + private static final int DEFAULT_SMALL_SCREEN_HEIGHT_THRESHOLD_DP = 750; private static final String UMA_PREFIX = "QueryTiles.NTP"; private final ViewGroup mQueryTileSectionView; @@ -196,7 +198,10 @@ DisplayAndroid display = DisplayAndroid.getNonMultiDisplay(mQueryTileSectionView.getContext()); int screenHeightDp = DisplayUtil.pxToDp(display, display.getDisplayHeight()); - boolean isSmallScreen = screenHeightDp < SMALL_SCREEN_HEIGHT_THRESHOLD_DP; + int smallScreenHeightThresholdDp = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( + ChromeFeatureList.QUERY_TILES, VARIATION_SMALL_SCREEN_HEIGHT_THRESHOLD_DP, + DEFAULT_SMALL_SCREEN_HEIGHT_THRESHOLD_DP); + boolean isSmallScreen = screenHeightDp < smallScreenHeightThresholdDp; return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(ChromeFeatureList.QUERY_TILES, isSmallScreen ? MOST_VISITED_MAX_ROWS_SMALL_SCREEN : MOST_VISITED_MAX_ROWS_NORMAL_SCREEN,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java index f399798e..895c3ef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java
@@ -13,33 +13,24 @@ * natively to the given {@link Profile}. */ public class TileProviderFactory { - private static TileProvider sTileProvider; + private static TileProvider sTileProviderForTesting; /** * Used to get access to the tile provider backend. * @return An {@link TileProvider} instance. */ public static TileProvider getForProfile(Profile profile) { - if (sTileProvider == null) { - sTileProvider = TileProviderFactoryJni.get().getForProfile(profile); - } - - return sTileProvider; + if (sTileProviderForTesting != null) return sTileProviderForTesting; + return TileProviderFactoryJni.get().getForProfile(profile); } /** For testing only. */ public static void setTileProviderForTesting(TileProvider provider) { - sTileProvider = provider; - } - - // TODO(shaktisahu): Remove this function once we have the real provider. - public static void setFakeTileProvider(FakeTileProvider provider) { - if (sTileProvider != null) return; - sTileProvider = provider; + sTileProviderForTesting = provider; } @NativeMethods interface Natives { TileProvider getForProfile(Profile profile); } -} +} \ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/BackgroundSyncTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/BackgroundSyncTest.java index 7e1db76..28231a3a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/BackgroundSyncTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/BackgroundSyncTest.java
@@ -26,7 +26,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.TabTitleObserver; -import org.chromium.components.signin.test.util.AccountManagerTestRule; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.content_public.browser.test.NativeLibraryTestRule; import org.chromium.content_public.browser.test.util.BackgroundSyncNetworkUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java index 037ad05..dd871e0e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java
@@ -28,7 +28,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.TabTitleObserver; -import org.chromium.components.signin.test.util.AccountManagerTestRule; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.content_public.browser.test.NativeLibraryTestRule; import org.chromium.content_public.browser.test.util.BackgroundSyncNetworkUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogTest.java new file mode 100644 index 0000000..454d2473 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogTest.java
@@ -0,0 +1,70 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.download.dialogs; + +import android.support.test.filters.MediumTest; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.modaldialog.DialogDismissalCause; +import org.chromium.ui.modaldialog.ModalDialogProperties; + +/** + * Test to verify download later dialog. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class DownloadLaterDialogTest { + @Rule + public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + + private DownloadLaterDialogCoordinator mDialogCoordinator; + + @Mock + private ModalDialogProperties.Controller mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mActivityTestRule.startMainActivityOnBlankPage(); + TestThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertNotNull("controller should not be null", mController); + mDialogCoordinator = new DownloadLaterDialogCoordinator(mActivityTestRule.getActivity(), + mActivityTestRule.getActivity().getModalDialogManager(), mController); + }); + } + + @Test + @MediumTest + public void testShowDialogThenDismiss() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + mDialogCoordinator.showDialog(); + Assert.assertTrue(mActivityTestRule.getActivity().getModalDialogManager().isShowing()); + mDialogCoordinator.dismissDialog(DialogDismissalCause.UNKNOWN); + Assert.assertFalse(mActivityTestRule.getActivity().getModalDialogManager().isShowing()); + }); + } + + @Test + @MediumTest + public void testShowDialogThenDestroy() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + mDialogCoordinator.showDialog(); + Assert.assertTrue(mActivityTestRule.getActivity().getModalDialogManager().isShowing()); + mDialogCoordinator.destroy(); + }); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityScrollingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityScrollingTest.java index b56da773..dd9f867 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityScrollingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityScrollingTest.java
@@ -31,9 +31,9 @@ import org.chromium.chrome.browser.widget.DateDividedAdapter.TimedItem; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.util.browser.RecyclerViewTestUtils; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.components.browser_ui.widget.MoreProgressButton; import org.chromium.components.browser_ui.widget.MoreProgressButton.State; -import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.UiRestriction;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java index 8bf0df6..72a49700 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java
@@ -28,8 +28,8 @@ import org.chromium.chrome.test.omaha.MockRequestGenerator; import org.chromium.chrome.test.omaha.MockRequestGenerator.DeviceType; import org.chromium.chrome.test.omaha.MockRequestGenerator.SignedInStatus; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.components.signin.identitymanager.IdentityManager; -import org.chromium.components.signin.test.util.AccountManagerTestRule; /** * Unit tests for the RequestGenerator class.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordViewingTypeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordViewingTypeTest.java index 3c7c94b..6ac68c8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordViewingTypeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordViewingTypeTest.java
@@ -27,8 +27,8 @@ import org.chromium.chrome.browser.settings.SettingsLauncherImpl; import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.chrome.test.util.ApplicationTestUtils; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.components.browser_ui.settings.ChromeBasePreference; -import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.components.sync.AndroidSyncSettings; import org.chromium.components.sync.test.util.MockSyncContentResolverDelegate; import org.chromium.content_public.browser.test.NativeLibraryTestRule;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java index 2623eaa..996e295 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java
@@ -34,8 +34,8 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.components.signin.ProfileDataSource; -import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.components.signin.test.util.FakeProfileDataSource; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DummyUiActivityTestCase;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java index 2524e5ae..3b41ab6a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java
@@ -13,8 +13,8 @@ import org.junit.runner.RunWith; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.chrome.test.util.browser.signin.MockChangeEventChecker; -import org.chromium.components.signin.test.util.AccountManagerTestRule; /** * Instrumentation tests for {@link SigninHelper}.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java index 44c9ce8..0aa4135 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
@@ -6,6 +6,7 @@ import static org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge.SITE_WILDCARD; +import android.content.Context; import android.content.Intent; import android.os.Build; import android.support.test.InstrumentationRegistry; @@ -46,6 +47,7 @@ import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.site_settings.FourStateCookieSettingsPreference; import org.chromium.components.browser_ui.site_settings.FourStateCookieSettingsPreference.CookieSettingsState; +import org.chromium.components.browser_ui.site_settings.R; import org.chromium.components.browser_ui.site_settings.SingleCategorySettings; import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings; import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; @@ -1213,8 +1215,9 @@ } SettingsLauncher settingsLauncher = new SettingsLauncherImpl(); - Intent intent = settingsLauncher.createSettingsActivityIntent( - InstrumentationRegistry.getTargetContext(), SingleWebsiteSettings.class.getName(), + Context context = InstrumentationRegistry.getTargetContext(); + Intent intent = settingsLauncher.createSettingsActivityIntent(context, + SingleWebsiteSettings.class.getName(), SingleWebsiteSettings.createFragmentArgsForSite(url)); final SettingsActivity settingsActivity = (SettingsActivity) InstrumentationRegistry.getInstrumentation().startActivitySync( @@ -1227,6 +1230,9 @@ final Preference notificationPreference = websitePreferences.findPreference("push_notifications_list"); + Assert.assertEquals(context.getString(R.string.automatically_blocked), + notificationPreference.getSummary()); + websitePreferences.launchOsChannelSettingsFromPreference(notificationPreference); // Ensure that a proper separate channel has indeed been created to allow the user to
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/NtpStreamLifecycleManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/NtpStreamLifecycleManagerTest.java index 380fe15..a5b81ee0 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/NtpStreamLifecycleManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/NtpStreamLifecycleManagerTest.java
@@ -123,125 +123,19 @@ @Test @SmallTest - public void testActivate() { - // Verify that stream is not active before activity resumed. - when((mTab).isHidden()).thenReturn(false); - when(mTab.isUserInteractable()).thenReturn(true); - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED); - verify(mStream, times(1)).onShow(); - verify(mStream, times(0)).onActive(); - - // Verify that stream is not active before tab is user interactable. - when(mTab.isUserInteractable()).thenReturn(false); - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); - verify(mStream, times(1)).onShow(); - verify(mStream, times(0)).onActive(); - - // Verify that stream is active when tab is user interactable and activity is resumed. - when(mTab.isUserInteractable()).thenReturn(true); - mNtpStreamLifecycleManager.getTabObserverForTesting().onInteractabilityChanged(mTab, true); - verify(mStream, times(1)).onShow(); - verify(mStream, times(1)).onActive(); - - // When the Stream is active, it won't call Stream#onShow() again. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED); - verify(mStream, times(1)).onShow(); - - // When the Stream is active, it won't call Stream#onActive() again. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); - verify(mStream, times(1)).onActive(); - } - - @Test - @SmallTest - public void testActivateAfterCreateAndHideAfterActivate() { - // Activate the stream from created state. - InOrder inOrder = Mockito.inOrder(mStream); - when((mTab).isHidden()).thenReturn(false); - when(mTab.isUserInteractable()).thenReturn(true); - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); - inOrder.verify(mStream).onShow(); - inOrder.verify(mStream).onActive(); - verify(mStream, times(1)).onShow(); - verify(mStream, times(1)).onActive(); - - // Verify that the stream is deactivated before hidden. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STOPPED); - inOrder.verify(mStream).onInactive(); - inOrder.verify(mStream).onHide(); - verify(mStream, times(1)).onShow(); - verify(mStream, times(1)).onActive(); - verify(mStream, times(1)).onInactive(); - verify(mStream, times(1)).onHide(); - } - - @Test - @SmallTest - public void testDeactivate() { - // Verify that the Stream cannot be set inactive from created. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED); - verify(mStream, times(0)).onInactive(); - - // Show the stream. - when((mTab).isHidden()).thenReturn(false); - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED); - verify(mStream, times(1)).onShow(); - - // Verify that the Stream cannot be set inactive from shown. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED); - verify(mStream, times(0)).onInactive(); - - // Activate the stream. - when(mTab.isUserInteractable()).thenReturn(true); - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); - verify(mStream, times(1)).onActive(); - - // Verify that the Stream can be set inactive from active on activity paused. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED); - verify(mStream, times(1)).onInactive(); - - // When the Stream is inactive, it won't call Stream#onInactive() again. - mNtpStreamLifecycleManager.getTabObserverForTesting().onInteractabilityChanged(mTab, false); - verify(mStream, times(1)).onInactive(); - - // Verify that the Stream cannot be set shown from inactive. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED); - verify(mStream, times(1)).onShow(); - - // Verify that the Stream can be set active from inactive. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); - verify(mStream, times(2)).onActive(); - - // Verify that the Stream can be set inactive from active on tab interactability changed. - mNtpStreamLifecycleManager.getTabObserverForTesting().onInteractabilityChanged(mTab, false); - verify(mStream, times(2)).onInactive(); - } - - @Test - @SmallTest public void testHideFromActivityStopped() { // Activate the Stream. when((mTab).isHidden()).thenReturn(false); when(mTab.isUserInteractable()).thenReturn(true); ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); verify(mStream, times(1)).onShow(); - verify(mStream, times(1)).onActive(); // Deactivate the Stream. ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED); - verify(mStream, times(1)).onInactive(); // Verify that the Stream can be set hidden from inactive. ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STOPPED); verify(mStream, times(1)).onHide(); - - // Verify that the Stream cannot be set inactive from hidden. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED); - verify(mStream, times(1)).onInactive(); - - // When the Stream is hidden, it won't call Stream#onHide() again. - ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STOPPED); - verify(mStream, times(1)).onHide(); } @Test @@ -252,12 +146,10 @@ ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED); verify(mStream, times(1)).onShow(); - // Verify that onActive and onInactive are skipped when Stream is set hidden from shown. + // Hide the stream. mNtpStreamLifecycleManager.getTabObserverForTesting().onHidden( mTab, TabHidingType.CHANGED_TABS); verify(mStream, times(1)).onShow(); - verify(mStream, times(0)).onActive(); - verify(mStream, times(0)).onInactive(); verify(mStream, times(1)).onHide(); } @@ -284,8 +176,6 @@ ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STOPPED); ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.DESTROYED); verify(mStream, times(0)).onShow(); - verify(mStream, times(0)).onActive(); - verify(mStream, times(0)).onInactive(); verify(mStream, times(0)).onHide(); verify(mStream, times(1)).onDestroy(); } @@ -300,16 +190,12 @@ // Activate the Stream. ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); inOrder.verify(mStream).onShow(); - inOrder.verify(mStream).onActive(); verify(mStream, times(1)).onShow(); - verify(mStream, times(1)).onActive(); // Verify that onInactive and onHide is called before onDestroy. ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.DESTROYED); - inOrder.verify(mStream).onInactive(); inOrder.verify(mStream).onHide(); inOrder.verify(mStream).onDestroy(); - verify(mStream, times(1)).onInactive(); verify(mStream, times(1)).onHide(); verify(mStream, times(1)).onDestroy(); } @@ -325,42 +211,30 @@ ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED); ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); inOrder.verify(mStream).onShow(); - inOrder.verify(mStream).onActive(); verify(mStream, times(1)).onShow(); - verify(mStream, times(1)).onActive(); // On activity pause and then resume (simulates multi-window mode). ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED); ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); - inOrder.verify(mStream).onInactive(); - inOrder.verify(mStream).onActive(); - verify(mStream, times(1)).onInactive(); - verify(mStream, times(2)).onActive(); // On activity stop (simulates app switched to background). ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED); ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STOPPED); - inOrder.verify(mStream).onInactive(); inOrder.verify(mStream).onHide(); - verify(mStream, times(2)).onInactive(); verify(mStream, times(1)).onHide(); // On activity start (simulates app switched back to foreground). ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED); ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED); inOrder.verify(mStream).onShow(); - inOrder.verify(mStream).onActive(); verify(mStream, times(2)).onShow(); - verify(mStream, times(3)).onActive(); // On activity pause, stop, and destroy (simulates app removed from Android recents). ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED); ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STOPPED); ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.DESTROYED); - inOrder.verify(mStream).onInactive(); inOrder.verify(mStream).onHide(); inOrder.verify(mStream).onDestroy(); - verify(mStream, times(3)).onInactive(); verify(mStream, times(2)).onHide(); verify(mStream, times(1)).onDestroy(); } @@ -386,29 +260,21 @@ // On tab interactable. when(mTab.isUserInteractable()).thenReturn(true); mNtpStreamLifecycleManager.getTabObserverForTesting().onInteractabilityChanged(mTab, true); - inOrder.verify(mStream).onActive(); - verify(mStream, times(1)).onActive(); // On tab un-interactable (simulates user enter the tab switcher). when(mTab.isUserInteractable()).thenReturn(false); mNtpStreamLifecycleManager.getTabObserverForTesting().onInteractabilityChanged(mTab, false); - inOrder.verify(mStream).onInactive(); - verify(mStream, times(1)).onInactive(); // On tab interactable (simulates user exit the tab switcher). when(mTab.isUserInteractable()).thenReturn(true); mNtpStreamLifecycleManager.getTabObserverForTesting().onInteractabilityChanged(mTab, true); - inOrder.verify(mStream).onActive(); - verify(mStream, times(2)).onActive(); // On tab un-interactable and hidden (simulates user switch to another tab). when((mTab).isHidden()).thenReturn(true); when(mTab.isUserInteractable()).thenReturn(false); mNtpStreamLifecycleManager.getTabObserverForTesting().onInteractabilityChanged(mTab, false); mNtpStreamLifecycleManager.getTabObserverForTesting().onHidden(mTab, CHANGED_TABS); - inOrder.verify(mStream).onInactive(); inOrder.verify(mStream).onHide(); - verify(mStream, times(2)).onInactive(); verify(mStream, times(1)).onHide(); // On tab shown (simulates user switch back to this tab).
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiverTest.java index af19776f..0b705fb2 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiverTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiverTest.java
@@ -21,7 +21,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; -import org.chromium.components.signin.test.util.AccountManagerTestRule; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import java.util.HashSet; import java.util.Set;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcherTest.java index 430a640..7bf34af5 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcherTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcherTest.java
@@ -90,7 +90,8 @@ return null; }) .when(mBridge) - .fetchGif(anyInt(), eq(URL), eq(UMA_CLIENT_NAME), gifCallbackCaptor.capture()); + .fetchGif(anyInt(), eq(ImageFetcher.Params.create(URL, UMA_CLIENT_NAME)), + gifCallbackCaptor.capture()); } @Test @@ -145,29 +146,29 @@ public void testFetchGif_fileNotFoundOnDisk() { doReturn(null).when(mImageLoader).tryToLoadGifFromDisk(PATH); - mCachedImageFetcher.fetchGif(URL, UMA_CLIENT_NAME, mGifCallback); + ImageFetcher.Params params = ImageFetcher.Params.create(URL, UMA_CLIENT_NAME); + mCachedImageFetcher.fetchGif(params, mGifCallback); ArgumentCaptor<BaseGifImage> gifCaptor = ArgumentCaptor.forClass(BaseGifImage.class); verify(mGifCallback).onResult(gifCaptor.capture()); Assert.assertEquals(mGif, gifCaptor.getValue()); - verify(mBridge).fetchGif( - eq(ImageFetcherConfig.DISK_CACHE_ONLY), eq(URL), eq(UMA_CLIENT_NAME), any()); + verify(mBridge).fetchGif(eq(ImageFetcherConfig.DISK_CACHE_ONLY), eq(params), any()); } @Test public void testFetchGif_fileFoundOnDisk() { doReturn(mGif).when(mImageLoader).tryToLoadGifFromDisk(PATH); - mCachedImageFetcher.fetchGif(URL, UMA_CLIENT_NAME, mGifCallback); + ImageFetcher.Params params = ImageFetcher.Params.create(URL, UMA_CLIENT_NAME); + mCachedImageFetcher.fetchGif(params, mGifCallback); ArgumentCaptor<BaseGifImage> gifCaptor = ArgumentCaptor.forClass(BaseGifImage.class); verify(mGifCallback).onResult(gifCaptor.capture()); Assert.assertEquals(mGif, gifCaptor.getValue()); verify(mBridge, never()) - .fetchGif(eq(ImageFetcherConfig.DISK_CACHE_ONLY), eq(URL), eq(UMA_CLIENT_NAME), - any()); + .fetchGif(eq(ImageFetcherConfig.DISK_CACHE_ONLY), eq(params), any()); verify(mBridge).reportEvent(UMA_CLIENT_NAME, ImageFetcherEvent.JAVA_DISK_CACHE_HIT); verify(mBridge).reportCacheHitTime(eq(UMA_CLIENT_NAME), anyLong()); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridgeTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridgeTest.java index 4e9b4c4d..54bf5c9 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridgeTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridgeTest.java
@@ -77,7 +77,7 @@ mExpectedException.expectMessage("getFilePath called after destroy"); mBridge.getFilePath(""); mExpectedException.expectMessage("fetchGif called after destroy"); - mBridge.fetchGif(-1, "", "", null); + mBridge.fetchGif(-1, ImageFetcher.Params.create("", ""), null); mExpectedException.expectMessage("fetchImage called after destroy"); mBridge.fetchImage(-1, ImageFetcher.Params.create("", "", 100, 100), null); mExpectedException.expectMessage("fetchImage called after destroy"); @@ -158,9 +158,9 @@ }) .when(mNatives) .fetchImageData(eq(sNativePointer), eq(mBridge), anyInt(), anyString(), anyString(), - callbackCaptor.capture()); + eq(0), callbackCaptor.capture()); - mBridge.fetchGif(-1, "", "", mGifCallback); + mBridge.fetchGif(-1, ImageFetcher.Params.create("", ""), mGifCallback); ArgumentCaptor<BaseGifImage> gifCaptor = ArgumentCaptor.forClass(BaseGifImage.class); verify(mGifCallback).onResult(gifCaptor.capture()); @@ -176,9 +176,9 @@ }) .when(mNatives) .fetchImageData(eq(sNativePointer), eq(mBridge), anyInt(), anyString(), anyString(), - callbackCaptor.capture()); + eq(0), callbackCaptor.capture()); - mBridge.fetchGif(-1, "", "", mGifCallback); + mBridge.fetchGif(-1, ImageFetcher.Params.create("", ""), mGifCallback); verify(mGifCallback).onResult(null); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java index c218d72..6ba069b4 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java
@@ -48,10 +48,10 @@ } @Override - public void fetchGif(String url, String clientName, Callback<BaseGifImage> callback) {} + public void fetchGif(final Params params, Callback<BaseGifImage> callback) {} @Override - public void fetchImage(Params params, Callback<Bitmap> callback) {} + public void fetchImage(final Params params, Callback<Bitmap> callback) {} @Override public void clear() {}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcherTest.java index 0098076..131d6c2 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcherTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcherTest.java
@@ -159,8 +159,9 @@ @Test public void testFetchGif() { - mInMemoryCachedImageFetcher.fetchGif(URL, UMA_CLIENT_NAME, (BaseGifImage gif) -> {}); - verify(mMockImageFetcher).fetchGif(eq(URL), eq(UMA_CLIENT_NAME), any()); + ImageFetcher.Params params = ImageFetcher.Params.create(URL, UMA_CLIENT_NAME); + mInMemoryCachedImageFetcher.fetchGif(params, (BaseGifImage gif) -> {}); + verify(mMockImageFetcher).fetchGif(eq(params), any()); } @Test @@ -182,7 +183,7 @@ // Check that calling methods after destroy throw AssertionErrors. mExpectedException.expect(AssertionError.class); mExpectedException.expectMessage("fetchGif called after destroy"); - mInMemoryCachedImageFetcher.fetchGif("", "", null); + mInMemoryCachedImageFetcher.fetchGif(ImageFetcher.Params.create("", ""), null); mExpectedException.expectMessage("fetchImage called after destroy"); mInMemoryCachedImageFetcher.fetchImage(ImageFetcher.Params.create("", "", 100, 100), null); mExpectedException.expectMessage("clear called after destroy");
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcherTest.java index 6f0e0d15..ed4ef80 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcherTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcherTest.java
@@ -76,7 +76,8 @@ return null; }) .when(mBridge) - .fetchGif(anyInt(), eq(URL), eq(UMA_CLIENT_NAME), gifCallbackCaptor.capture()); + .fetchGif(anyInt(), eq(ImageFetcher.Params.create(URL, UMA_CLIENT_NAME)), + gifCallbackCaptor.capture()); } @Test @@ -91,10 +92,10 @@ @Test public void test_fetchGif() { - mImageFetcher.fetchGif(URL, UMA_CLIENT_NAME, mGifCallback); + ImageFetcher.Params params = ImageFetcher.Params.create(URL, UMA_CLIENT_NAME); + mImageFetcher.fetchGif(params, mGifCallback); verify(mGifCallback).onResult(mGif); - verify(mBridge).fetchGif( - ImageFetcherConfig.NETWORK_ONLY, URL, UMA_CLIENT_NAME, mGifCallback); + verify(mBridge).fetchGif(ImageFetcherConfig.NETWORK_ONLY, params, mGifCallback); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerMediatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerMediatorTest.java index 35a5f7a..435cdd0 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerMediatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerMediatorTest.java
@@ -20,8 +20,8 @@ import org.chromium.chrome.browser.signin.DisplayableProfileData; import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.AddAccountRowProperties; import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.ExistingAccountRowProperties; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.components.signin.ProfileDataSource; -import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.components.signin.test.util.FakeProfileDataSource; import org.chromium.ui.modelutil.MVCListAdapter; import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 64f8a12..cfbbc46e 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -820,6 +820,9 @@ <message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_TITLE" desc="The title of the dialog that welcomes the user on the first log in, and explains Chrome Sync and privacy options."> You're signed in! </message> + <message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE" desc="The subtitle of the dialog that explains Chrome Sync and privacy options on first login."> + By continuing, Google will sync data from <ph name="EMAIL">$1<ex>user@example.com</ex></ph> with this device. + </message> <message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_OS_SYNC_NAME" desc="Title of the 'Settings sync' section of the sync confirmation dialog that is displayed on the first user log in."> Chrome OS settings sync </message> @@ -850,6 +853,12 @@ <message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE" desc="The label on the button that closes dialog while accepting the selected settings."> Accept and continue </message> + <message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT" desc="The label on the button that closes the dialog while agreeing to sync."> + Yes, I'm in + </message> + <message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_DECLINE" desc="The label on the button that closes the dialog while not agreeing to sync."> + No, thanks + </message> <message name="IDS_LOGIN_RECOMMEND_APPS_SCREEN_TITLE" desc="The title of the dialog that recommend apps which user has installed in other devices"> Install apps from your other devices
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT.png.sha1 new file mode 100644 index 0000000..3e44c96 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT.png.sha1
@@ -0,0 +1 @@ +3684b2d06490ff527f1895ab0d9f5e9bca3706d1 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_DECLINE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_DECLINE.png.sha1 new file mode 100644 index 0000000..3e44c96 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_DECLINE.png.sha1
@@ -0,0 +1 @@ +3684b2d06490ff527f1895ab0d9f5e9bca3706d1 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE.png.sha1 new file mode 100644 index 0000000..3e44c96 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +3684b2d06490ff527f1895ab0d9f5e9bca3706d1 \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index c0b46ca..5a41f86 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -4399,9 +4399,6 @@ <message name="IDS_EXTENSIONS_LOCKED_SUPERVISED_USER" desc="The error message (either shown in the extensions UI or logged) informing a supervised user that extensions cannot be changed."> Apps and extensions can only be modified by the manager (<ph name="CUSTODIAN_NAME">$1<ex>Jane Doe</ex></ph>). </message> - <message name="IDS_EXTENSIONS_INSTALLED_BY_SUPERVISED_USER_CUSTODIAN" desc="The text in the extensions UI informing a supervised user that an extension was installed by their custodian and cannot be changed"> - Installed by your custodian. - </message> <message name="IDS_EXTENSION_LOAD_FROM_DIRECTORY" desc="Title of directory browse dialog when user wants to load an extension from a directory."> Select the extension directory. </message> @@ -4624,6 +4621,9 @@ <message name="IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_TITLE_GENERIC" desc="The title of the dialog informing the user that the new tab page has been overridden by an extension."> Did you mean to change this page? </message> + <message name="IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_TITLE_BACK_TO_GOOGLE" desc="The title of the dialog informing the user that the new tab page has been overridden by an extension, and asking if they want to change back to Google."> + Change back to Google? + </message> <message name="IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_BODY_GENERIC" desc="The body of the dialog informing the user that the new tab page has been overridden by an extension, indicating which extension now controls it."> This page was changed by the <ph name="EXTENSION_NAME">$1<ex>Google Arts and Culture</ex></ph> extension </message>
diff --git a/chrome/app/generated_resources_grd/IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_TITLE_BACK_TO_GOOGLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_TITLE_BACK_TO_GOOGLE.png.sha1 new file mode 100644 index 0000000..34d72dd --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_TITLE_BACK_TO_GOOGLE.png.sha1
@@ -0,0 +1 @@ +04a94597ba2933769a78c70dac6b45880fbc7f5b \ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings.grdp b/chrome/app/os_settings_search_tag_strings.grdp index b592f7eec..740998f 100644 --- a/chrome/app/os_settings_search_tag_strings.grdp +++ b/chrome/app/os_settings_search_tag_strings.grdp
@@ -257,8 +257,11 @@ <message name="IDS_OS_SETTINGS_TAG_LOCK_SCREEN_WHEN_WAKING_ALT1" desc="Text for search result item which, when clicked, navigates the user to lock screen settings. Alternate phrase for: 'Lock screen settings'"> Login screen </message> - <message name="IDS_OS_SETTINGS_TAG_LOCK_SCREEN_PIN_OR_PASSWORD" desc="Text for search result item which, when clicked, navigates the user to lock screen settings, with an option to determine whether the device can be unlocked with a PIN."> - PIN lock screen settings + <message name="IDS_OS_SETTINGS_TAG_LOCK_SCREEN_PIN_OR_PASSWORD" desc="Text for search result item which, when clicked, navigates the user to lock screen settings, with an option to determine whether the device can be unlocked with a PIN or a password. Alternate phrase for: 'Screen lock password'"> + Screen lock PIN + </message> + <message name="IDS_OS_SETTINGS_TAG_LOCK_SCREEN_PIN_OR_PASSWORD_ALT1" desc="Text for search result item which, when clicked, navigates the user to lock screen settings, with an option to determine whether the device can be unlocked with a PIN or a password. Alternate phrase for: 'Screen lock PIN'"> + Screen lock password </message> <message name="IDS_OS_SETTINGS_TAG_GUEST_BROWSING" desc="Text for search result item which, when clicked, navigates the user to account settings, with a toggle to enable/disable guest browsing."> Guest browsing @@ -394,11 +397,17 @@ <message name="IDS_OS_SETTINGS_TAG_POWER" desc="Text for search result item which, when clicked, navigates the user to power settings."> Power </message> - <message name="IDS_OS_SETTINGS_TAG_POWER_IDLE" desc="Text for search result item which, when clicked, navigates the user to power settings, with an option to set the idle (i.e., sleep) behavior. Alternate phrase for: 'Sleep settings'"> - Idle power + <message name="IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_CHARGING" desc="Text for search result item which, when clicked, navigates the user to power settings, with an option to set the idle (i.e., sleep) behavior while charging. Alternate phrase for: 'Sleep while charging'"> + Idle power while charging </message> - <message name="IDS_OS_SETTINGS_TAG_POWER_IDLE_ALT1" desc="Text for search result item which, when clicked, navigates the user to power settings, with an option to set the idle (i.e., sleep) behavior. Alternate phrase for: 'Idle power settings'"> - Sleep settings + <message name="IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_CHARGING_ALT1" desc="Text for search result item which, when clicked, navigates the user to power settings, with an option to set the idle (i.e., sleep) behavior while charging. Alternate phrase for: 'Idle power while charging'"> + Sleep while charging + </message> + <message name="IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_ON_BATTERY" desc="Text for search result item which, when clicked, navigates the user to power settings, with an option to set the idle (i.e., sleep) behavior while on the device is being powered by its battery. Alternate phrase for: 'Sleep while on battery'"> + Idle power on battery + </message> + <message name="IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_ON_BATTERY_ALT1" desc="Text for search result item which, when clicked, navigates the user to power settings, with an option to set the idle (i.e., sleep) behavior while on the device is being powered by its battery. Alternate phrase for: 'Idle power on battery'"> + Sleep while on battery </message> <message name="IDS_OS_SETTINGS_TAG_TOUCHPAD" desc="Text for search result item which, when clicked, navigates the user to touchpad settings. Alternate phrase for: 'Trackpad'"> Touchpad @@ -478,14 +487,26 @@ <message name="IDS_OS_SETTINGS_TAG_DISPLAY_ARRANGEMENT_ALT2" desc="Text for search result item which, when clicked, navigates the user to display settings, with the ability to rearrange screen positioning. Alternate phrase for: 'Display arrangement', 'Monitor arrangement'"> Screen arrangement </message> - <message name="IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen orientation. Alternate phrase for: 'Monitor orientation', 'Screen orientation'"> + <message name="IDS_OS_SETTINGS_TAG_MIRRORING" desc="Text for search result item which, when clicked, navigates the user to display settings, with a checkbox to enable/disable display mirroring."> + Display mirroring + </message> + <message name="IDS_OS_SETTINGS_TAG_UNIFIED_DESKTOP" desc="Text for search result item which, when clicked, navigates the user to display settings, with a toggle to enable/disable Unified Desktop mode, which allows windows to span multiple displays."> + Allow windows to span displays + </message> + <message name="IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select display orientation (normal, or rotated 90/180/270 degrees). Alternate phrase for 'Display orientation'"> Display orientation </message> - <message name="IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT1" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen orientation. Alternate phrase for: 'Display orientation', 'Screen orientation'"> - Monitor orientation + <message name="IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT1" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select display orientation (normal, or rotated 90/180/270 degrees). Alternate phrase for 'Display rotation'."> + Display rotation </message> - <message name="IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT2" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen orientation. Alternate phrase for: 'Display orientation', 'Monitor orientation'"> - Screen orientation + <message name="IDS_OS_SETTINGS_TAG_DISPLAY_AMBIENT_COLORS" desc="Text for search result item which, when clicked, navigates the user to display settings, with a toggle to enable/disable ambient colors, which adapts the screen color to match the environment."> + Ambient colors + </message> + <message name="IDS_OS_SETTINGS_TAG_DISPLAY_TOUCHSCREEN_CALIBRATION" desc="Text for search result item which, when clicked, navigates the user to display settings, with a link to open the touchscreen calibration UI."> + Touchscreen calibration + </message> + <message name="IDS_OS_SETTINGS_TAG_NIGHT_LIGHT_COLOR_TEMPERATURE" desc="Text for search result item which, when clicked, navigates the user to display settings, with a slider to increase/decrease the 'color temperature' for Night Light, which makes it easier to look at the screen in dim light."> + Night Light color temperature </message> <message name="IDS_OS_SETTINGS_TAG_DOWNLOADED_CONTENT" desc="Text for search result item which, when clicked, navigates the user to downloaded content. Alternate phrase for: 'DLC'"> Downloaded Content @@ -526,7 +547,7 @@ <message name="IDS_OS_SETTINGS_TAG_POWER_SLEEP_COVER_CLOSED_ALT2" desc="Text for search result item which, when clicked, navigates the user to power settings, with an option to set whether the device sleeps when the lid is closed. Alternate phrase for: 'Sleep when cover is closed', 'Sleep when laptop is closed'"> Sleep when lid is closed </message> - <message name="IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen orientation. Alternate phrase for: 'Monitor orientation', 'Screen orientation'"> + <message name="IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen resolution. Alternate phrase for: 'Monitor resolution', 'Screen resolution'"> Display resolution </message> <message name="IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION_ALT1" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen resolution. Alternate phrase for: 'Display resolution', 'Screen resolution'"> @@ -535,7 +556,7 @@ <message name="IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION_ALT2" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen resolution. Alternate phrase for: 'Display resolution', 'Monitor resolution'"> Screen resolution </message> - <message name="IDS_OS_SETTINGS_TAG_DISPLAY_REFRESH_RATE" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen orientation. Alternate phrase for: 'Monitor orientation', 'Screen orientation'"> + <message name="IDS_OS_SETTINGS_TAG_DISPLAY_REFRESH_RATE" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen refresh rate. Alternate phrase for: 'Monitor refresh rate', 'Screen refresh rate'"> Display refresh rate </message> <message name="IDS_OS_SETTINGS_TAG_DISPLAY_REFRESH_RATE_ALT1" desc="Text for search result item which, when clicked, navigates the user to display settings, with a dropdown to select screen refresh rate. Alternate phrase for: 'Display refresh rate', 'Screen refresh rate'">
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index b1e0298..2a79ffc 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -1686,6 +1686,9 @@ <message name="IDS_SETTINGS_INTERNET_DEVICE_ENABLING" desc="Settings > Internet > Message when a device (e.g a Cellular modem) is enabling."> Enabling </message> + <message name="IDS_SETTINGS_INTERNET_DEVICE_DISABLING" desc="Settings > Internet > Message when a Cellular modem is turning off (disabling)."> + Turning off + </message> <message name="IDS_SETTINGS_INTERNET_DEVICE_INITIALIZING" desc="Settings > Internet > Message when a device (e.g a Cellular modem) is initializing."> Initializing </message>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb index 8cf72ef..a1531f3 100644 --- a/chrome/app/resources/generated_resources_ar.xtb +++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -2130,6 +2130,7 @@ <translation id="3677106374019847299">إدخال مزوّد مخصّص</translation> <translation id="3677657024345889897">المستوى الأدنى</translation> <translation id="3677911431265050325">طلب موقع إلكتروني متوافق مع الأجهزة الجوَالة</translation> +<translation id="3677959414150797585">يتضمن المحتوى المُقترح التطبيقات وصفحات الويب والمزيد. لا يرسل هذا الإجراء إحصاءات لتحسين المحتوى المُقترح إلا إذا اختَرت مشاركة بيانات الاستخدام.</translation> <translation id="3678156199662914018">الإضافة: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">صوت "تحويل النص إلى كلام"</translation> <translation id="3681311097828166361">شكرًا على تعليقاتك. أنت غير متصل الآن، وسيتم إرسال تقريرك لاحقًا.</translation> @@ -3780,6 +3781,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> - تسجيل الكاميرا أو الميكروفون</translation> <translation id="5841270259333717135">ضبط إعدادات إيثرنت</translation> <translation id="5842497610951477805">تفعيل البلوتوث</translation> +<translation id="5844574845205796324">اقتراح محتوى جديد لاستكشافه</translation> <translation id="5846200638699387931">خطأ في بنية العلاقة: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">تثبيت التحديثات والتطبيقات تعني متابعتك أنك توافق على منح هذا الجهاز إذنًا لتنزيل التحديثات والتطبيقات وتثبيتها تلقائيًا من Google ومشغّل شبكة الجوّال والشركة المصنّعة لجهازك، مع احتمالية استخدام بيانات شبكة الجوّال. قد تتيح بعض هذه التطبيقات عمليات شراء داخل التطبيق.</translation> <translation id="5849212445710944278">تمت إضافتها سابقًا.</translation>
diff --git a/chrome/app/resources/generated_resources_az.xtb b/chrome/app/resources/generated_resources_az.xtb index 6fd2347..0dc54400 100644 --- a/chrome/app/resources/generated_resources_az.xtb +++ b/chrome/app/resources/generated_resources_az.xtb
@@ -2125,6 +2125,7 @@ <translation id="3677106374019847299">Fərdi təminatçı daxil edin</translation> <translation id="3677657024345889897">Ən səssiz</translation> <translation id="3677911431265050325">Mobil saytı tələb edin</translation> +<translation id="3677959414150797585">Tətbiqlər, veb səhifələr və daha çoxu daxildir. Yalnız istifadə datasını paylaşmağı seçdiyiniz zaman təklifləri yaxşılaşdırmaq üçün statistika göndərir.</translation> <translation id="3678156199662914018">Artırma: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">Mətndən-nitqə səsi</translation> <translation id="3681311097828166361">Əks əlaqə üçün təşəkkür edirik. Hazırda oflaynsınız, hesabınız sonra göndəriləcək.</translation> @@ -3775,6 +3776,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> - Kamera və ya mikrofon qeydə alması</translation> <translation id="5841270259333717135">Ethernet şəbəkəsini konfiqurasiya edin</translation> <translation id="5842497610951477805">Bluetooth'un aktiv edilməsi</translation> +<translation id="5844574845205796324">Araşdırmaq üçün yeni məzmun təklif edin</translation> <translation id="5846200638699387931">Əlaqə sintaksis xətası: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">Yeniləmələri və tətbiqləri quraşdırın. Davam edərək razılaşırsınız ki, bu cihaz Google, operatorunuz və cihaz istehsalçınızdan avtomatik olaraq yeniləmələri və tətbiqləri endirə və quraşdıra bilər, bu zaman mobil datadan istifadə edilə bilər. Bu tətbiqlərin bəzilərində tətbiqdaxili satınalmalar təklif edilə bilər.</translation> <translation id="5849212445710944278">Artıq əlavə edilib</translation>
diff --git a/chrome/app/resources/generated_resources_gl.xtb b/chrome/app/resources/generated_resources_gl.xtb index 53635f0..28321eab 100644 --- a/chrome/app/resources/generated_resources_gl.xtb +++ b/chrome/app/resources/generated_resources_gl.xtb
@@ -2885,7 +2885,7 @@ <translation id="4645676300727003670">&Continuar</translation> <translation id="4646675363240786305">Portos</translation> <translation id="4647090755847581616">&Pechar pestana</translation> -<translation id="4647420311443994946">{0,select, tablet{Iniciar aplicación ao iniciar sesión na tableta}computer{Iniciar aplicación ao iniciar sesión no ordenador}other{Iniciar aplicación ao iniciar sesión no dispositivo}}</translation> +<translation id="4647420311443994946">{0,select, tablet{Abrir aplicación ao iniciar sesión na tableta}computer{Abrir aplicación ao iniciar sesión no ordenador}other{Abrir aplicación ao iniciar sesión no dispositivo}}</translation> <translation id="4647697156028544508">Introduce o PIN de "<ph name="DEVICE_NAME" />":</translation> <translation id="4648491805942548247">Permisos insuficientes</translation> <translation id="4648499713050786492">Desbloquea o teu perfil antes de engadir unha persoa.</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb index 3cce72d..eed08805 100644 --- a/chrome/app/resources/generated_resources_hi.xtb +++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -2130,6 +2130,7 @@ <translation id="3677106374019847299">डीएनएस सेवा देने वाली कंपनी का नाम अपने हिसाब से डालें</translation> <translation id="3677657024345889897">सबसे कम</translation> <translation id="3677911431265050325">मोबाइल साइट के लिए अनुरोध करें</translation> +<translation id="3677959414150797585">इसमें ऐप्लिकेशन, वेबपेज वगैरह शामिल हैं. यह सुझावों को बेहतर बनाने के लिए आंकड़े सिर्फ़ तब भेजता है, जब आपने इस्तेमाल के बारे में जानकारी देने वाला डेटा शेयर करने का विकल्प चुना हो.</translation> <translation id="3678156199662914018">एक्सटेंशन: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">लिखाई को बोली में बदलने के लिए आवाज़ की सेटिंग</translation> <translation id="3681311097828166361">आपके फ़ीडबैक के लिए धन्यवाद. आप अब ऑफ़लाइन हैं और आपकी रिपोर्ट बाद में भेज दी जाएगी.</translation> @@ -3781,6 +3782,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> - कैमरा या माइक्रोफ़ोन रिकॉर्डिंग</translation> <translation id="5841270259333717135">ईथरनेट कॉन्फ़िगर करें</translation> <translation id="5842497610951477805">ब्लूटूथ चालू है</translation> +<translation id="5844574845205796324">एक्सप्लोर करने के लिए नया कॉन्टेंट सुझाएं</translation> <translation id="5846200638699387931">रिलेशन सिंटैक्स गड़बड़ी: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">अपडेट और ऐप्लिकेशन इंस्टॉल करें. जारी रखकर, आप इस बात की इजाज़त देते हैं कि यह डिवाइस Google, आपको मोबाइल और इंटरनेट सेवा देने वाली कंपनी, और आपका डिवाइस बनाने वाली कंपनी से अपने-आप अपडेट और ऐप्लिकेशन डाउनलोड और उन्हें इंस्टॉल कर सकता है. इसके लिए, शायद आपके मोबाइल डेटा का इस्तेमाल किया जाए. इनमें से कुछ ऐप्लिकेशन में इन-ऐप्लिकेशन खरीदारी की सुविधा भी हो सकती है.</translation> <translation id="5849212445710944278">पहले ही जोड़ा जा चुका है</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb index 86f8d6d..a547d3d 100644 --- a/chrome/app/resources/generated_resources_iw.xtb +++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -2128,6 +2128,7 @@ <translation id="3677106374019847299">יש להזין ספק בהתאמה אישית</translation> <translation id="3677657024345889897">עוצמת הקול הנמוכה ביותר</translation> <translation id="3677911431265050325">בקשת אתר לנייד</translation> +<translation id="3677959414150797585">כולל אפליקציות, דפי אינטרנט ועוד. המערכת שולחת נתונים סטטיסטיים כדי לשפר את ההצעות רק אם בחרת לשתף נתוני שימוש במכשיר.</translation> <translation id="3678156199662914018">תוסף: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">קול של המרת טקסט לדיבור (TTS)</translation> <translation id="3681311097828166361">תודה על המשוב. כרגע אינך מחובר לאינטרנט, כך שהדוח שלך יישלח מאוחר יותר.</translation> @@ -3780,6 +3781,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> - הקלטה במצלמה או במיקרופון</translation> <translation id="5841270259333717135">הגדרת Ethernet</translation> <translation id="5842497610951477805">הפעלה של Bluetooth</translation> +<translation id="5844574845205796324">קבלת הצעות לתוכן חדש שיכול לעניין אותך</translation> <translation id="5846200638699387931">שגיאה בתחביר המציין את הקשר: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">התקנה של עדכונים ואפליקציות. המשך מהווה את הסכמתך לכך שהמכשיר הזה עשוי גם להוריד ולהתקין באופן אוטומטי עדכונים ואפליקציות מ-Google, מהספק שלך ומיצרן המכשיר, וייתכן שהדבר יתבצע תוך שימוש בחבילת הגלישה. חלק מהאפליקציות האלו עשויות לכלול רכישות מהאפליקציה.</translation> <translation id="5849212445710944278">כבר נוספה</translation>
diff --git a/chrome/app/resources/generated_resources_kk.xtb b/chrome/app/resources/generated_resources_kk.xtb index 09dcc10..c45ea213 100644 --- a/chrome/app/resources/generated_resources_kk.xtb +++ b/chrome/app/resources/generated_resources_kk.xtb
@@ -2127,6 +2127,7 @@ <translation id="3677106374019847299">Арнаулы провайдерді енгізу</translation> <translation id="3677657024345889897">Ең бәсең</translation> <translation id="3677911431265050325">Сайттың мобильдік нұсқасын сұрау</translation> +<translation id="3677959414150797585">Оған қолданбалар, веб-беттер және тағы басқалар жатады. Пайдаланылуы туралы деректерді бөлісуді таңдасаңыз, ұсыныстарды жақсарту үшін статистиканы жібереді.</translation> <translation id="3678156199662914018">Кеңейтім: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">Мәтінді дыбыстау дауысы</translation> <translation id="3681311097828166361">Пікіріңіз үшін рақмет. Қазір желіге қосылмағансыз, есебіңіз кейінірек жіберіледі.</translation> @@ -3779,6 +3780,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> – камерадан не микрофоннан жазу</translation> <translation id="5841270259333717135">Ethernet желісін конфигурациялау</translation> <translation id="5842497610951477805">Bluetooth қосу</translation> +<translation id="5844574845205796324">Жаңа мазмұн ұсыну</translation> <translation id="5846200638699387931">Қатынас синтаксисінің қатесі: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">Жаңа нұсқалар мен қолданбаларды орнату. Жалғастыру арқылы бұл құрылғының Google қызметінен, оператордан және құрылғы өндірушісінен жаңа нұсқалар мен қолданбаларды автоматты түрде жүктеп алуына және орнатуына келісім бересіз (ұялы деректер пайдаланылуы мүмкін). Бұл қолданбалардың кейбірінде қолданба арқылы сатып алу ұсынылуы мүмкін.</translation> <translation id="5849212445710944278">Бұрыннан бар</translation>
diff --git a/chrome/app/resources/generated_resources_ky.xtb b/chrome/app/resources/generated_resources_ky.xtb index 7f4b768..6e1c161 100644 --- a/chrome/app/resources/generated_resources_ky.xtb +++ b/chrome/app/resources/generated_resources_ky.xtb
@@ -2130,6 +2130,7 @@ <translation id="3677106374019847299">Жеке кызмат көрсөтүүчүнү киргизиңиз</translation> <translation id="3677657024345889897">Эң акырын</translation> <translation id="3677911431265050325">Мобилдик версиясы керек</translation> +<translation id="3677959414150797585">Колдонмолор, веб-баракчалар жана башкалар сунушталат. Сунуштарды жакшыртуу максатында колдонуу статистикаңыз жөнөтүлөт (статистиканы бөлүшүүнү тандаган болсоңуз гана).</translation> <translation id="3678156199662914018">Кеңейтүү: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">Кеп синтезаторунун үнү</translation> <translation id="3681311097828166361">Ой пикириңиз үчүн чоң рахмат! Отчет Интернетке туташаарыңыз менен жөнөтүлөт.</translation> @@ -3782,6 +3783,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> – Видео же аудио жаздырылууда</translation> <translation id="5841270259333717135">Ethernet'ти конфигурациялоо</translation> <translation id="5842497610951477805">Bluetooth'ду иштетүү</translation> +<translation id="5844574845205796324">Изилдөө үчүн жаңы мазмун сунушталсын</translation> <translation id="5846200638699387931">Катнаштын синтаксис катасы: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">Жаңыртууларды жана колдонмолорду орнотуу. Улантуу менен, түзмөккө Google'дан, байланыш операторуңуздан жана түзмөгүңүздү иштеп чыккандардан жаңыртууларды жана колдомолорду автоматтык түрдө жүктөп алып орнотушуна уруксат бересиз. Айрым колдонмолор кандайдыр бир кошумча нерселерди сатып алууну сунуштайт.</translation> <translation id="5849212445710944278">Мурунтан эле кошулган</translation>
diff --git a/chrome/app/resources/generated_resources_lo.xtb b/chrome/app/resources/generated_resources_lo.xtb index 09684dd8..41ca04e 100644 --- a/chrome/app/resources/generated_resources_lo.xtb +++ b/chrome/app/resources/generated_resources_lo.xtb
@@ -2128,6 +2128,7 @@ <translation id="3677106374019847299">ປ້ອນຜູ້ໃຫ້ບໍລິການທີ່ກຳນົດເອງ</translation> <translation id="3677657024345889897">ງຽບທີ່ສຸດ</translation> <translation id="3677911431265050325">ຮ້ອງຂໍເວັບໄຊມືຖື</translation> +<translation id="3677959414150797585">ຮວມມີແອັບ, ໜ້າເວັບ ແລະ ອື່ນໆອີກ. ສົ່ງສະຖິຕິເພື່ອປັບປຸງການແນະນຳພຽງແຕ່ຖ້າທ່ານໄດ້ເລືອກແບ່ງປັນຂໍ້ມູນການນຳໃຊ້ເທົ່ານັ້ນ.</translation> <translation id="3678156199662914018">ສ່ວນຂະຫຍາຍ: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">ສຽງຂອງການປ່ຽນຂໍ້ຄວາມເປັນສຽງເວົ້າ</translation> <translation id="3681311097828166361">ຂໍຂອບໃຈສຳລັບຄຳຕິຊົມຂອງທ່ານ. ທ່ານອອບລາຍຢູ່ຕອນນີ້ ແລະ ລາຍງານຂອງທ່ານຈະຖືກສົ່ງໃນພາຍຫຼັງ.</translation> @@ -3780,6 +3781,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> - ການບັນທຶກກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນ</translation> <translation id="5841270259333717135">ຕັ້ງຄ່າອີເທີເນັດ</translation> <translation id="5842497610951477805">ເປີດນຳໃຊ້ Bluetooth</translation> +<translation id="5844574845205796324">ແນະນຳເນື້ອຫາໃໝ່ເພື່ອໃຫ້ສຳຫຼວດເບິ່ງ</translation> <translation id="5846200638699387931">ຂໍ້ຜິດພາດທາງໄວຍະກອນທີ່ກ່ຽວຂ້ອງ: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">ຕິດຕັ້ງການອັບເດດ ແລະ ແອັບ. ໂດຍການສືບຕໍ່, ແມ່ນຖືວ່າທ່ານເຫັນດີວ່າອຸປະກອນນີ້ສາມາດດາວໂຫຼດ ແລະ ຕິດຕັ້ງການອັບເດດ ແລະ ແອັບໄດ້ໂດຍອັດຕະໂນມັດຈາກ Google, ຜູ້ໃຫ້ບໍລິການຂອງທ່ານ ແລະ ຜູ້ຜະລິດອຸປະກອນຂອງທ່ານ, ໂດຍເປັນໄປໄດ້ວ່າອາດຈະໃຊ້ຂໍ້ມູນມືຖື. ບາງແອັບເຫຼົ່ານີ້ອາດຈະໃຫ້ການຊື້ໃນແອັບ.</translation> <translation id="5849212445710944278">ເພີ່ມເຂົ້າແລ້ວ</translation>
diff --git a/chrome/app/resources/generated_resources_mk.xtb b/chrome/app/resources/generated_resources_mk.xtb index 34eb7ab..9e67b1c2b 100644 --- a/chrome/app/resources/generated_resources_mk.xtb +++ b/chrome/app/resources/generated_resources_mk.xtb
@@ -2130,6 +2130,7 @@ <translation id="3677106374019847299">Внесете приспособен оператор</translation> <translation id="3677657024345889897">Најтивко</translation> <translation id="3677911431265050325">Побарај мобилна верзија на сајтот</translation> +<translation id="3677959414150797585">Вклучува апликации, веб-страници, и друго. Статистики за подобрување на предлозите се испраќаат само ако сте одбрале споделување на податоците за користење</translation> <translation id="3678156199662914018">Наставка: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">Глас за „Од текст во говор“</translation> <translation id="3681311097828166361">Благодариме за повратните информации. Во моментов сте офлајн, па вашиот извештај ќе се испрати подоцна.</translation> @@ -3782,6 +3783,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> - камерата или микрофонот снима</translation> <translation id="5841270259333717135">Конфигурирајте етернет</translation> <translation id="5842497610951477805">Овозможете Bluetooth</translation> +<translation id="5844574845205796324">Предложете нови содржини за истражување</translation> <translation id="5846200638699387931">Синтаксичка грешка во односот: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">Инсталирање ажурирања и апликации. Ако продолжите, се согласувате дека уредов може и автоматски да презема и инсталира ажурирања и апликации од Google, од вашиот оператор и производителот на уредот, веројатно преку мобилен интернет. Некои од овие апликации може да нудат купувања во апликации.</translation> <translation id="5849212445710944278">Додаден претходно</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb index 7955a579..e56b5909 100644 --- a/chrome/app/resources/generated_resources_ta.xtb +++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -2130,6 +2130,7 @@ <translation id="3677106374019847299">பிரத்தியேக வழங்குநரை உள்ளிடுக</translation> <translation id="3677657024345889897">குறைவு</translation> <translation id="3677911431265050325">மொபைல் தளத்தைக் கோரு</translation> +<translation id="3677959414150797585">ஆப்ஸ், இணையப் பக்கங்கள் மற்றும் பல அடங்கும். உபயோகத் தரவுப் பகிர்வை தேர்வுசெய்திருந்தால் மட்டுமே பரிந்துரைகளை மேம்படுத்துவதற்காகப் புள்ளிவிவரங்களை அனுப்பும்.</translation> <translation id="3678156199662914018">நீட்டிப்பு: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">’உரையிலிருந்து பேச்சு’ செயல்முறைக்கான குரல்</translation> <translation id="3681311097828166361">உங்கள் கருத்திற்கு நன்றி. இப்போது ஆஃப்லைனில் உள்ளீர்கள், உங்கள் அறிக்கை பின்னர் அனுப்பப்படும்.</translation> @@ -3783,6 +3784,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> - கேமரா அல்லது மைக்ரோஃபோன் ரெக்கார்டு செய்கிறது</translation> <translation id="5841270259333717135">ஈத்தர்நெட்டை உள்ளமை</translation> <translation id="5842497610951477805">புளூடூத்தை இயக்கு</translation> +<translation id="5844574845205796324">பயன்படுத்திப் பார்க்க புதிய உள்ளடக்கத்தைப் பரிந்துரை</translation> <translation id="5846200638699387931">ரிலேஷன் சின்டாக்ஸ் பிழை: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">புதுப்பிப்புகளையும் ஆப்ஸையும் நிறுவுதல். தொடர்வதன் மூலம் இந்தச் சாதனமானது Google, உங்கள் தொலைத்தொடர்பு நிறுவனம் மற்றும் இந்தச் சாதனத்தின் உற்பத்தியாளர் ஆகியோரிடமிருந்து வரும் புதுப்பிப்புகளையும் ஆப்ஸையும் மொபைல் டேட்டா வழியே தானாகவே பதிவிறக்கி, நிறுவக்கூடும் என்பதை ஏற்கிறீர்கள். இதில் சில ஆப்ஸ், ஆப்ஸில் வாங்குதல்களை வழங்கக்கூடும்.</translation> <translation id="5849212445710944278">ஏற்கனவே சேர்க்கப்பட்டுள்ளது</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb index 30fe991..dcf4775f 100644 --- a/chrome/app/resources/generated_resources_te.xtb +++ b/chrome/app/resources/generated_resources_te.xtb
@@ -2130,6 +2130,7 @@ <translation id="3677106374019847299">అనుకూల ప్రొవైడర్ను ఎంటర్ చేయండి</translation> <translation id="3677657024345889897">అత్యంత నిశబ్దం</translation> <translation id="3677911431265050325">మొబైల్ సైట్ను అభ్యర్థించండి</translation> +<translation id="3677959414150797585">యాప్లు, వెబ్పేజీలు, మరిన్ని ఇందులో ఉంటాయి. మీరు డేటా వినియోగాన్ని షేర్ చేయడాన్ని ఎంచుకుంటే మాత్రమే సూచనలు మెరుగుపరచడానికి గణాంకాలను పంపుతుంది.</translation> <translation id="3678156199662914018">పొడిగింపు: <ph name="EXTENSION_NAME" /></translation> <translation id="3680683624079082902">టెక్ట్స్-టు-స్పీచ్ వాయిస్</translation> <translation id="3681311097828166361">మీ అభిప్రాయం తెలియజేసినందుకు ధన్యవాదాలు. మీరు ప్రస్తుతం ఆఫ్లైన్లో ఉన్నారు, మీ నివేదిక తర్వాత పంపబడుతుంది.</translation> @@ -3782,6 +3783,7 @@ <translation id="5835486486592033703"><ph name="WINDOW_TITLE" /> - కెమెరా లేదా మైక్రోఫోన్ రికార్డ్ చేస్తోంది</translation> <translation id="5841270259333717135">ఈథర్నెట్ను కాన్ఫిగర్ చేయండి</translation> <translation id="5842497610951477805">బ్లూటూత్ను ప్రారంభించు</translation> +<translation id="5844574845205796324">అన్వేషించడానికి కొత్త కంటెంట్ను సూచించండి</translation> <translation id="5846200638699387931">రిలేషన్ సింటాక్స్ ఎర్రర్: <ph name="ERROR_LINE" /></translation> <translation id="5846807460505171493">అప్డేట్లను, యాప్లను ఇన్స్టాల్ చేయండి. మీరు కొనసాగడం ద్వారా ఈ పరికరం ఆటోమేటిక్గా Google, మీ క్యారియర్, మీ పరికర తయారీదారు నుండి సెల్యులార్ డేటాతో కూడా అప్డేట్లు, యాప్లను డౌన్లోడ్ చేసి, ఇన్స్టాల్ చేయవచ్చని మీరు అంగీకరిస్తున్నారు. ఈ యాప్లలో కొన్ని, యాప్లోని కొనుగోళ్లను ఆఫర్ చేయవచ్చు.</translation> <translation id="5849212445710944278">ఇప్పటికే జోడించబడింది</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 3272b9b..4b2c8db 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1360,6 +1360,8 @@ "prerender/isolated/isolated_prerender_service_factory.h", "prerender/isolated/isolated_prerender_service_workers_observer.cc", "prerender/isolated/isolated_prerender_service_workers_observer.h", + "prerender/isolated/isolated_prerender_subresource_manager.cc", + "prerender/isolated/isolated_prerender_subresource_manager.h", "prerender/isolated/isolated_prerender_tab_helper.cc", "prerender/isolated/isolated_prerender_tab_helper.h", "prerender/isolated/isolated_prerender_url_loader.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 52500bb..dd684058 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2798,6 +2798,9 @@ {"webxr-incubations", flag_descriptions::kWebXrIncubationsName, flag_descriptions::kWebXrIncubationsDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWebXrIncubations)}, + {"webxr-multi-gpu", flag_descriptions::kWebXrMultiGpuName, + flag_descriptions::kWebXrMultiGpuDescription, kOsDesktop, + FEATURE_VALUE_TYPE(blink::features::kWebXrMultiGpu)}, {"webxr-runtime", flag_descriptions::kWebXrForceRuntimeName, flag_descriptions::kWebXrForceRuntimeDescription, kOsDesktop, MULTI_VALUE_TYPE(kWebXrForceRuntimeChoices)},
diff --git a/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc b/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc index e900fe7a..5135ade 100644 --- a/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc +++ b/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
@@ -106,6 +106,7 @@ const jint j_image_fetcher_config, const JavaRef<jstring>& j_url, const JavaRef<jstring>& j_client_name, + const jint j_expiration_interval_mins, const JavaRef<jobject>& j_callback) { ScopedJavaGlobalRef<jobject> callback(j_callback); ImageFetcherConfig config = @@ -115,6 +116,10 @@ base::android::ConvertJavaStringToUTF8(j_client_name); image_fetcher::ImageFetcherParams params(kTrafficAnnotation, client_name); + if (j_expiration_interval_mins > 0) { + params.set_hold_for_expiration_interval( + base::TimeDelta::FromMinutes(j_expiration_interval_mins)); + } // We can skip transcoding here because this method is used in java as // ImageFetcher.fetchGif, which decodes the data in a Java-only library.
diff --git a/chrome/browser/android/image_fetcher/image_fetcher_bridge.h b/chrome/browser/android/image_fetcher/image_fetcher_bridge.h index 89e6281..45b1cfb 100644 --- a/chrome/browser/android/image_fetcher/image_fetcher_bridge.h +++ b/chrome/browser/android/image_fetcher/image_fetcher_bridge.h
@@ -37,6 +37,7 @@ const jint j_image_fetcher_config, const base::android::JavaRef<jstring>& j_url, const base::android::JavaRef<jstring>& j_client_name, + const jint j_expiration_interval_mins, const base::android::JavaRef<jobject>& j_callback); void FetchImage(JNIEnv* j_env,
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc index b847fa73..d3e7681 100644 --- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc +++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
@@ -427,9 +427,6 @@ ukm::builders::BackgroundFetchDeletingRegistration(*source_id) .SetUserInitiatedAbort(user_initiated_abort) .Record(ukm::UkmRecorder::Get()); - - if (ukm_event_recorded_for_testing_) - std::move(ukm_event_recorded_for_testing_).Run(); } void BackgroundFetchDelegateImpl::MarkJobComplete(
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.h b/chrome/browser/background_fetch/background_fetch_delegate_impl.h index bf87b87d..b7c4fae 100644 --- a/chrome/browser/background_fetch/background_fetch_delegate_impl.h +++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
@@ -131,10 +131,6 @@ void GetUploadData(const std::string& download_guid, download::GetUploadDataCallback callback); - void set_ukm_event_recorded_for_testing(base::OnceClosure closure) { - ukm_event_recorded_for_testing_ = std::move(closure); - } - base::WeakPtr<BackgroundFetchDelegateImpl> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } @@ -289,9 +285,6 @@ // Set of Observers to be notified of any changes to the shown notifications. std::set<Observer*> observers_; - // Testing-only closure to inform tests when a UKM event has been recorded. - base::OnceClosure ukm_event_recorded_for_testing_; - base::WeakPtrFactory<BackgroundFetchDelegateImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDelegateImpl);
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl_unittest.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl_unittest.cc index 8a77cc8..6bae1a0 100644 --- a/chrome/browser/background_fetch/background_fetch_delegate_impl_unittest.cc +++ b/chrome/browser/background_fetch/background_fetch_delegate_impl_unittest.cc
@@ -46,12 +46,6 @@ history::SOURCE_BROWSED); } - void WaitForUkmEvent() { - base::RunLoop run_loop; - delegate_->set_ukm_event_recorded_for_testing(run_loop.QuitClosure()); - run_loop.Run(); - } - protected: // This is used to specify the main thread type of the tests as the UI // thread. @@ -72,9 +66,13 @@ EXPECT_EQ(entries.size(), 0u); } + base::RunLoop run_loop; + recorder_->SetOnAddEntryCallback( + ukm::builders::BackgroundFetchDeletingRegistration::kEntryName, + run_loop.QuitClosure()); delegate_->RecordBackgroundFetchDeletingRegistrationUkmEvent( origin, /* user_initiated_abort= */ true); - WaitForUkmEvent(); + run_loop.Run(); { std::vector<const ukm::mojom::UkmEntry*> entries =
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 20a96d2..9a847c16 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -1357,7 +1357,9 @@ // Windows platform spellcheck dictionary language tags used to populate the // context menu for editable content. if (spellcheck::UseWinHybridSpellChecker() && - profile_->GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable)) { + profile_->GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable) && + !base::FeatureList::IsEnabled( + spellcheck::kWinDelaySpellcheckServiceInit)) { SpellcheckServiceFactory::GetForContext(profile_); } #endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc index 2ff11de1..af1d0b3 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
@@ -709,8 +709,8 @@ RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName, ""); } -// Disabled: https://crbug.com/1044417 -IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, RemoveApp) { +// Flaky https://crbug.com/1090937 (previous bug: https://crbug.com/1044417) +IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, DISABLED_RemoveApp) { // Add a new app. RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName, ""); KioskAppManager::AppList apps;
diff --git a/chrome/browser/chromeos/arc/session/arc_service_launcher.cc b/chrome/browser/chromeos/arc/session/arc_service_launcher.cc index 945b7df6..56e9a9c 100644 --- a/chrome/browser/chromeos/arc/session/arc_service_launcher.cc +++ b/chrome/browser/chromeos/arc/session/arc_service_launcher.cc
@@ -10,8 +10,6 @@ #include "base/bind.h" #include "base/check_op.h" #include "base/files/file_util.h" -#include "base/task/post_task.h" -#include "base/task/thread_pool.h" #include "chrome/browser/apps/app_service/arc_apps_factory.h" #include "chrome/browser/chromeos/apps/apk_web_app_service.h" #include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h" @@ -87,10 +85,6 @@ namespace arc { namespace { -// The file that specifies if the environment is ARCVM or ARC. It contains 1 in -// ARCVM and 0 in ARC. -constexpr base::FilePath::CharType kIsArcVm[] = "/run/chrome/is_arcvm"; - // ChromeBrowserMainPartsChromeos owns. ArcServiceLauncher* g_arc_service_launcher = nullptr; @@ -110,14 +104,6 @@ scheduler_configuration_manager_(scheduler_configuration_manager) { DCHECK(g_arc_service_launcher == nullptr); g_arc_service_launcher = this; - - // Write kIsArcVm file to be 1 or 0. - base::ThreadPool::PostTask( - FROM_HERE, {base::MayBlock()}, - base::BindOnce([](const base::FilePath& filename, const char* data, - int size) { base::WriteFile(filename, data, size); }, - base::FilePath(kIsArcVm), - arc::IsArcVmEnabled() ? "1" : "0", 1)); } ArcServiceLauncher::~ArcServiceLauncher() {
diff --git a/chrome/browser/chromeos/input_method/emoji_suggester.cc b/chrome/browser/chromeos/input_method/emoji_suggester.cc index ffe4534..a732f56 100644 --- a/chrome/browser/chromeos/input_method/emoji_suggester.cc +++ b/chrome/browser/chromeos/input_method/emoji_suggester.cc
@@ -6,6 +6,7 @@ #include "base/files/file_util.h" #include "base/i18n/number_formatting.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -24,6 +25,8 @@ const char kDefaultEngine[] = "default_engine"; const base::FilePath::CharType kEmojiMapFilePath[] = FILE_PATH_LITERAL("/emoji/emoji-map.csv"); +const int kMaxSuggestionIndex = 31; +const int kMaxSuggestionSize = kMaxSuggestionIndex + 1; std::string ReadEmojiDataFromFile() { if (!base::DirectoryExists(base::FilePath(ime::kBundledInputMethodsDirPath))) @@ -99,9 +102,16 @@ std::string emojis = line.substr(comma_pos + 1); // Build emoji_map_ from splitting the string of emojis. emoji_map_[word] = SplitString(emojis, ";"); + DCHECK_LE(static_cast<int>(emoji_map_[word].size()), kMaxSuggestionSize); } } +void EmojiSuggester::RecordAcceptanceIndex(int index) { + base::UmaHistogramExactLinear( + "InputMethod.Assistive.EmojiSuggestAddition.AcceptancePosition", index, + kMaxSuggestionIndex); +} + void EmojiSuggester::OnFocus(int context_id) { context_id_ = context_id; } @@ -121,6 +131,7 @@ engine_->CommitText(context_id_, candidates_[candidate_id_].value.c_str(), &error); engine_->SetCandidateWindowVisible(false, &error); + RecordAcceptanceIndex(candidate_id_); status = SuggestionStatus::kAccept; } else if (event.key == "Down") { candidate_id_ < static_cast<int>(candidates_.size()) - 1
diff --git a/chrome/browser/chromeos/input_method/emoji_suggester.h b/chrome/browser/chromeos/input_method/emoji_suggester.h index 6ae4057..ca842bcf 100644 --- a/chrome/browser/chromeos/input_method/emoji_suggester.h +++ b/chrome/browser/chromeos/input_method/emoji_suggester.h
@@ -35,9 +35,9 @@ private: void ShowSuggestion(const std::string& text); - void LoadEmojiMap(); void OnEmojiDataLoaded(const std::string& emoji_data); + void RecordAcceptanceIndex(int index); InputMethodEngine* const engine_;
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc index 963b3de5..a0d13ee 100644 --- a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
@@ -51,6 +51,8 @@ #include "ui/base/l10n/l10n_util.h" using testing::Contains; +using testing::Eq; +using testing::UnorderedElementsAreArray; namespace chromeos { namespace { @@ -113,7 +115,9 @@ class SyncConsentTest : public OobeBaseTest { public: - SyncConsentTest() { + SyncConsentTest() + : force_branded_build_( + SyncConsentScreen::ForceBrandedBuildForTesting(true)) { // To reuse existing wizard controller in the flow. feature_list_.InitAndEnableFeature( chromeos::features::kOobeScreensPriority); @@ -131,7 +135,8 @@ IDS_LOGIN_SYNC_CONSENT_SCREEN_CHROME_SYNC_DESCRIPTION, IDS_LOGIN_SYNC_CONSENT_SCREEN_PERSONALIZE_GOOGLE_SERVICES_NAME, IDS_LOGIN_SYNC_CONSENT_SCREEN_PERSONALIZE_GOOGLE_SERVICES_DESCRIPTION, - IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE, + IDS_LOGIN_SYNC_CONSENT_SCREEN_DECLINE, + IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT, }; } else { expected_consent_ids_ = { @@ -189,61 +194,17 @@ // No need to explicitly show the screen as it is the first one after login. } + protected: base::Optional<SyncConsentScreen::Result> screen_result_; base::HistogramTester histogram_tester_; + std::vector<int> expected_consent_ids_; - protected: static SyncConsentScreen* GetSyncConsentScreen() { return static_cast<SyncConsentScreen*>( WizardController::default_controller()->GetScreen( SyncConsentScreenView::kScreenId)); } - void SyncConsentRecorderTestImpl( - const std::vector<std::string>& expected_consent_strings, - const std::string expected_consent_confirmation_string) { - SyncConsentScreen* screen = GetSyncConsentScreen(); - ConsentRecordedWaiter consent_recorded_waiter; - screen->SetDelegateForTesting(&consent_recorded_waiter); - - test::OobeJS().CreateVisibilityWaiter(true, {"sync-consent-impl"})->Wait(); - - if (features::IsSplitSettingsSyncEnabled()) { - test::OobeJS().ExpectVisiblePath( - {"sync-consent-impl", "splitSettingsSyncConsentDialog"}); - test::OobeJS().TapOnPath( - {"sync-consent-impl", "settingsAcceptAndContinueButton"}); - } else { - test::OobeJS().ExpectVisiblePath( - {"sync-consent-impl", "syncConsentOverviewDialog"}); - test::OobeJS().TapOnPath( - {"sync-consent-impl", "settingsSaveAndContinueButton"}); - } - consent_recorded_waiter.Wait(); - screen->SetDelegateForTesting(nullptr); // cleanup - - const int expected_consent_confirmation_id = - IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE; - - EXPECT_EQ(SyncConsentScreen::CONSENT_GIVEN, - consent_recorded_waiter.consent_given_); - EXPECT_EQ(expected_consent_strings, - consent_recorded_waiter.consent_description_strings_); - EXPECT_EQ(expected_consent_confirmation_string, - consent_recorded_waiter.consent_confirmation_string_); - EXPECT_EQ(expected_consent_ids_, - consent_recorded_waiter.consent_description_ids_); - EXPECT_EQ(expected_consent_confirmation_id, - consent_recorded_waiter.consent_confirmation_id_); - - WaitForScreenExit(); - EXPECT_EQ(screen_result_.value(), SyncConsentScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount( - "OOBE.StepCompletionTimeByExitReason.Sync-consent.Next", 1); - histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Sync-consent", - 1); - } - std::vector<std::string> GetLocalizedExpectedConsentStrings() const { std::vector<std::string> result; for (const int& id : expected_consent_ids_) { @@ -275,9 +236,9 @@ base::RepeatingClosure screen_exit_callback_; SyncConsentScreen::ScreenExitCallback original_callback_; - std::vector<int> expected_consent_ids_; LoginManagerMixin login_manager_mixin_{&mixin_host_}; + std::unique_ptr<base::AutoReset<bool>> force_branded_build_; base::test::ScopedFeatureList feature_list_; DISALLOW_COPY_AND_ASSIGN(SyncConsentTest); }; @@ -308,48 +269,55 @@ histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Sync-consent", 0); } -IN_PROC_BROWSER_TEST_F(SyncConsentTest, SyncConsentRecorder) { - auto autoreset = SyncConsentScreen::ForceBrandedBuildForTesting(true); +// Tests of the consent recorder with SplitSettingsSync disabled. The +// SplitSettingsSync suite below has its own consent recorder tests. +class SyncConsentRecorderTest : public SyncConsentTest { + public: + SyncConsentRecorderTest() { + features_.InitAndDisableFeature(chromeos::features::kSplitSettingsSync); + } + ~SyncConsentRecorderTest() override = default; + + base::test::ScopedFeatureList features_; +}; + +IN_PROC_BROWSER_TEST_F(SyncConsentRecorderTest, SyncConsentRecorder) { EXPECT_EQ(g_browser_process->GetApplicationLocale(), "en-US"); LoginToSyncConsentScreen(); WaitForScreenShown(); - // For En-US we hardcode strings here to catch string issues too. - std::vector<std::string> expected_consent_strings; - if (features::IsSplitSettingsSyncEnabled()) { - expected_consent_strings = { - "You're signed in!", - "Chrome OS settings sync", - "Your apps, settings, and other customizations will sync across all " - "Chrome OS devices signed in with your Google Account.", - "Chrome browser sync", - "Your bookmarks, history, passwords, and other settings will be synced " - "to your Google Account so you can use them on all your devices.", - "Personalize Google services", - "Google may use your browsing history to personalize Search, ads, and " - "other Google services. You can change this anytime at " - "myaccount.google.com/activitycontrols/search", - "Accept and continue"}; - } else { - expected_consent_strings = { - "You're signed in!", - "Chrome sync", - "Your bookmarks, history, passwords, and other settings will be synced " - "to your Google Account so you can use them on all your devices.", - "Personalize Google services", - "Google may use your browsing history to personalize Search, ads, and " - "other Google services. You can change this anytime at " - "myaccount.google.com/activitycontrols/search", - "Review sync options following setup", - "Accept and continue"}; - } - const std::string expected_consent_confirmation_string = - "Accept and continue"; - SyncConsentRecorderTestImpl(expected_consent_strings, - expected_consent_confirmation_string); + + SyncConsentScreen* screen = GetSyncConsentScreen(); + ConsentRecordedWaiter consent_recorded_waiter; + screen->SetDelegateForTesting(&consent_recorded_waiter); + + test::OobeJS().CreateVisibilityWaiter(true, {"sync-consent-impl"})->Wait(); + test::OobeJS().ExpectVisiblePath( + {"sync-consent-impl", "syncConsentOverviewDialog"}); + test::OobeJS().TapOnPath( + {"sync-consent-impl", "settingsSaveAndContinueButton"}); + consent_recorded_waiter.Wait(); + screen->SetDelegateForTesting(nullptr); // cleanup + + EXPECT_EQ(SyncConsentScreen::CONSENT_GIVEN, + consent_recorded_waiter.consent_given_); + EXPECT_THAT(consent_recorded_waiter.consent_description_strings_, + UnorderedElementsAreArray(GetLocalizedExpectedConsentStrings())); + EXPECT_EQ("Accept and continue", + consent_recorded_waiter.consent_confirmation_string_); + EXPECT_THAT(consent_recorded_waiter.consent_description_ids_, + UnorderedElementsAreArray(expected_consent_ids_)); + EXPECT_EQ(IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE, + consent_recorded_waiter.consent_confirmation_id_); + + WaitForScreenExit(); + EXPECT_EQ(screen_result_.value(), SyncConsentScreen::Result::NEXT); + histogram_tester_.ExpectTotalCount( + "OOBE.StepCompletionTimeByExitReason.Sync-consent.Next", 1); + histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Sync-consent", 1); } class SyncConsentTestWithParams - : public SyncConsentTest, + : public SyncConsentRecorderTest, public ::testing::WithParamInterface<std::string> { public: SyncConsentTestWithParams() = default; @@ -360,19 +328,25 @@ }; IN_PROC_BROWSER_TEST_P(SyncConsentTestWithParams, SyncConsentTestWithLocale) { - LOG(INFO) << "SyncConsentTestWithParams() started with param='" << GetParam() - << "'"; - auto autoreset = SyncConsentScreen::ForceBrandedBuildForTesting(true); EXPECT_EQ(g_browser_process->GetApplicationLocale(), "en-US"); SwitchLanguage(GetParam()); LoginToSyncConsentScreen(); - const std::vector<std::string> expected_consent_strings = - GetLocalizedExpectedConsentStrings(); - const std::string expected_consent_confirmation_string = - GetLocalizedConsentString( - IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE); - SyncConsentRecorderTestImpl(expected_consent_strings, - expected_consent_confirmation_string); + + SyncConsentScreen* screen = GetSyncConsentScreen(); + ConsentRecordedWaiter consent_recorded_waiter; + screen->SetDelegateForTesting(&consent_recorded_waiter); + + test::OobeJS().CreateVisibilityWaiter(true, {"sync-consent-impl"})->Wait(); + test::OobeJS().TapOnPath( + {"sync-consent-impl", "settingsSaveAndContinueButton"}); + consent_recorded_waiter.Wait(); + screen->SetDelegateForTesting(nullptr); + + EXPECT_THAT(consent_recorded_waiter.consent_description_strings_, + UnorderedElementsAreArray(GetLocalizedExpectedConsentStrings())); + EXPECT_THAT(consent_recorded_waiter.consent_confirmation_string_, + Eq(GetLocalizedConsentString( + IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE))); } // "es" tests language switching, "en-GB" checks switching to language varants. @@ -392,7 +366,6 @@ IN_PROC_BROWSER_TEST_P(SyncConsentPolicyDisabledTest, SyncConsentPolicyDisabled) { - auto autoreset = SyncConsentScreen::ForceBrandedBuildForTesting(true); LoginToSyncConsentScreen(); SyncConsentScreen* screen = GetSyncConsentScreen(); @@ -431,7 +404,6 @@ #define MAYBE_DefaultFlow DefaultFlow #endif IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest, MAYBE_DefaultFlow) { - auto autoreset = SyncConsentScreen::ForceBrandedBuildForTesting(true); LoginToSyncConsentScreen(); // OS sync is disabled by default. @@ -455,44 +427,46 @@ test::OobeJS().ExpectVisiblePath( {"sync-consent-impl", "splitSettingsSyncConsentDialog"}); - // Click the continue button and wait for the JS to C++ callback. - test::OobeJS().ClickOnPath( - {"sync-consent-impl", "settingsAcceptAndContinueButton"}); + // Click the accept button and wait for the JS to C++ callback. + test::OobeJS().ClickOnPath({"sync-consent-impl", "acceptButton"}); consent_recorded_waiter.Wait(); screen->SetDelegateForTesting(nullptr); // Consent was recorded for the confirmation button. EXPECT_EQ(SyncConsentScreen::CONSENT_GIVEN, consent_recorded_waiter.consent_given_); - EXPECT_EQ("Accept and continue", + EXPECT_EQ("Yes, I'm in", consent_recorded_waiter.consent_confirmation_string_); - EXPECT_EQ(IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE, + EXPECT_EQ(IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT, consent_recorded_waiter.consent_confirmation_id_); // Consent was recorded for all descriptions, including the confirmation // button label. std::vector<int> expected_ids = { IDS_LOGIN_SYNC_CONSENT_SCREEN_TITLE, + IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE, IDS_LOGIN_SYNC_CONSENT_SCREEN_OS_SYNC_NAME, IDS_LOGIN_SYNC_CONSENT_SCREEN_OS_SYNC_DESCRIPTION, IDS_LOGIN_SYNC_CONSENT_SCREEN_CHROME_BROWSER_SYNC_NAME, IDS_LOGIN_SYNC_CONSENT_SCREEN_CHROME_SYNC_DESCRIPTION, IDS_LOGIN_SYNC_CONSENT_SCREEN_PERSONALIZE_GOOGLE_SERVICES_NAME, IDS_LOGIN_SYNC_CONSENT_SCREEN_PERSONALIZE_GOOGLE_SERVICES_DESCRIPTION, - IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE, + IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT, + IDS_LOGIN_SYNC_CONSENT_SCREEN_DECLINE, }; EXPECT_THAT(consent_recorded_waiter.consent_description_ids_, testing::UnorderedElementsAreArray(expected_ids)); - // Toggle button is on-by-default, so OS sync should be on. + // OS sync is on. EXPECT_TRUE(prefs->GetBoolean(syncer::prefs::kOsSyncFeatureEnabled)); - // Browser sync is on-by-default. + // Browser sync is on. auto* identity_manager = IdentityManagerFactory::GetForProfile(profile); EXPECT_TRUE(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); - auto* service = ProfileSyncServiceFactory::GetForProfile(profile); - EXPECT_TRUE(service->GetUserSettings()->IsSyncRequested()); - EXPECT_TRUE(service->GetUserSettings()->IsFirstSetupComplete()); + syncer::SyncUserSettings* settings = GetSyncUserSettings(); + EXPECT_TRUE(settings->IsSyncRequested()); + EXPECT_TRUE(settings->IsFirstSetupComplete()); + EXPECT_TRUE(settings->IsSyncEverythingEnabled()); WaitForScreenExit(); EXPECT_EQ(screen_result_.value(), SyncConsentScreen::Result::NEXT); @@ -506,12 +480,11 @@ // Flaky failures on sanitizer builds. https://crbug.com/1054377 #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) -#define MAYBE_DisableOsSync DISABLED_DisableOsSync +#define MAYBE_DisableSync DISABLED_DisableSync #else -#define MAYBE_DisableOsSync DisableOsSync +#define MAYBE_DisableSync DisableSync #endif -IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest, MAYBE_DisableOsSync) { - auto autoreset = SyncConsentScreen::ForceBrandedBuildForTesting(true); +IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest, MAYBE_DisableSync) { LoginToSyncConsentScreen(); // Wait for content to load. @@ -523,48 +496,14 @@ screen->OnStateChanged(nullptr); test::OobeJS().CreateVisibilityWaiter(true, {"sync-consent-impl"})->Wait(); - // Turn off the toggle. - test::OobeJS().ClickOnPath({"sync-consent-impl", "osSyncToggle"}); - - // Click the continue button and wait for the JS to C++ callback. - test::OobeJS().ClickOnPath( - {"sync-consent-impl", "settingsAcceptAndContinueButton"}); + // Click the decline button and wait for the JS to C++ callback. + test::OobeJS().ClickOnPath({"sync-consent-impl", "declineButton"}); consent_recorded_waiter.Wait(); screen->SetDelegateForTesting(nullptr); // OS sync is off. PrefService* prefs = ProfileManager::GetPrimaryUserProfile()->GetPrefs(); EXPECT_FALSE(prefs->GetBoolean(syncer::prefs::kOsSyncFeatureEnabled)); -} - -// Flaky failures on sanitizer builds. https://crbug.com/1054377 -#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) -#define MAYBE_DisableBrowserSync DISABLED_DisableBrowserSync -#else -#define MAYBE_DisableBrowserSync DisableBrowserSync -#endif -IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest, - MAYBE_DisableBrowserSync) { - auto autoreset = SyncConsentScreen::ForceBrandedBuildForTesting(true); - LoginToSyncConsentScreen(); - - // Wait for content to load. - SyncConsentScreen* screen = GetSyncConsentScreen(); - ConsentRecordedWaiter consent_recorded_waiter; - screen->SetDelegateForTesting(&consent_recorded_waiter); - screen->SetProfileSyncDisabledByPolicyForTesting(false); - screen->SetProfileSyncEngineInitializedForTesting(true); - screen->OnStateChanged(nullptr); - test::OobeJS().CreateVisibilityWaiter(true, {"sync-consent-impl"})->Wait(); - - // Turn off the toggle. - test::OobeJS().ClickOnPath({"sync-consent-impl", "browserSyncToggle"}); - - // Click the continue button and wait for the JS to C++ callback. - test::OobeJS().ClickOnPath( - {"sync-consent-impl", "settingsAcceptAndContinueButton"}); - consent_recorded_waiter.Wait(); - screen->SetDelegateForTesting(nullptr); // For historical reasons, browser sync is still on. However, all data types // are disabled. @@ -573,6 +512,49 @@ EXPECT_TRUE(settings->IsFirstSetupComplete()); EXPECT_FALSE(settings->IsSyncEverythingEnabled()); EXPECT_TRUE(settings->GetSelectedTypes().Empty()); + + // Dialog is completed. + EXPECT_TRUE(prefs->GetBoolean(chromeos::prefs::kSyncOobeCompleted)); +} + +IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest, LanguageSwitch) { + SwitchLanguage("es"); + LoginToSyncConsentScreen(); + + SyncConsentScreen* screen = GetSyncConsentScreen(); + ConsentRecordedWaiter consent_recorded_waiter; + screen->SetDelegateForTesting(&consent_recorded_waiter); + + test::OobeJS().CreateVisibilityWaiter(true, {"sync-consent-impl"})->Wait(); + test::OobeJS().TapOnPath({"sync-consent-impl", "acceptButton"}); + consent_recorded_waiter.Wait(); + screen->SetDelegateForTesting(nullptr); + + EXPECT_THAT(consent_recorded_waiter.consent_description_strings_, + UnorderedElementsAreArray(GetLocalizedExpectedConsentStrings())); + EXPECT_THAT( + consent_recorded_waiter.consent_confirmation_string_, + Eq(GetLocalizedConsentString(IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT))); +} + +IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest, LanguageVariant) { + SwitchLanguage("en-GB"); + LoginToSyncConsentScreen(); + + SyncConsentScreen* screen = GetSyncConsentScreen(); + ConsentRecordedWaiter consent_recorded_waiter; + screen->SetDelegateForTesting(&consent_recorded_waiter); + + test::OobeJS().CreateVisibilityWaiter(true, {"sync-consent-impl"})->Wait(); + test::OobeJS().TapOnPath({"sync-consent-impl", "acceptButton"}); + consent_recorded_waiter.Wait(); + screen->SetDelegateForTesting(nullptr); + + EXPECT_THAT(consent_recorded_waiter.consent_description_strings_, + UnorderedElementsAreArray(GetLocalizedExpectedConsentStrings())); + EXPECT_THAT( + consent_recorded_waiter.consent_confirmation_string_, + Eq(GetLocalizedConsentString(IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT))); } IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest, @@ -597,7 +579,6 @@ IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest, SkippedSyncDisabledByPolicy) { - auto autoreset = SyncConsentScreen::ForceBrandedBuildForTesting(true); SyncConsentScreen* screen = GetSyncConsentScreen(); screen->SetProfileSyncDisabledByPolicyForTesting(true); LoginToSyncConsentScreen(); @@ -674,7 +655,6 @@ }; IN_PROC_BROWSER_TEST_F(SyncConsentTimezoneOverride, MakesTimezoneRequest) { - auto autoreset = SyncConsentScreen::ForceBrandedBuildForTesting(true); LoginToSyncConsentScreen(); EXPECT_EQ("TimezeonPropagationTest", g_browser_process->local_state()->GetString(
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_screen.cc b/chrome/browser/chromeos/login/screens/sync_consent_screen.cc index 2e5705f..ad647b01 100644 --- a/chrome/browser/chromeos/login/screens/sync_consent_screen.cc +++ b/chrome/browser/chromeos/login/screens/sync_consent_screen.cc
@@ -183,20 +183,18 @@ void SyncConsentScreen::OnAcceptAndContinue( const std::vector<int>& consent_description, int consent_confirmation, - bool enable_os_sync, - bool enable_browser_sync) { + bool enable_sync) { DCHECK(chromeos::features::IsSplitSettingsSyncEnabled()); if (is_hidden()) return; // Record that the user saw the consent text, regardless of which features // they chose to enable. RecordConsent(CONSENT_GIVEN, consent_description, consent_confirmation); - UpdateSyncSettings(enable_os_sync, enable_browser_sync); + UpdateSyncSettings(enable_sync); Finish(Result::NEXT); } -void SyncConsentScreen::UpdateSyncSettings(bool enable_os_sync, - bool enable_browser_sync) { +void SyncConsentScreen::UpdateSyncSettings(bool enable_sync) { DCHECK(chromeos::features::IsSplitSettingsSyncEnabled()); // For historical reasons, Chrome OS always has a "sync-consented" primary // account in IdentityManager and always has browser sync "enabled". If the @@ -210,8 +208,8 @@ syncer::SyncService* sync_service = GetSyncService(profile_); if (sync_service) { syncer::SyncUserSettings* sync_settings = sync_service->GetUserSettings(); - sync_settings->SetOsSyncFeatureEnabled(enable_os_sync); - if (!enable_browser_sync) { + sync_settings->SetOsSyncFeatureEnabled(enable_sync); + if (!enable_sync) { syncer::UserSelectableTypeSet empty_set; sync_settings->SetSelectedTypes(/*sync_everything=*/false, empty_set); } @@ -227,7 +225,7 @@ identity_manager->GetPrimaryAccountMutator()->SetPrimaryAccount(account_id); // Only enable URL-keyed metrics if the user turned on browser sync. - if (enable_browser_sync) { + if (enable_sync) { unified_consent::UnifiedConsentService* consent_service = UnifiedConsentServiceFactory::GetForProfile(profile_); if (consent_service) @@ -245,7 +243,7 @@ return; if (behavior_ == SyncScreenBehavior::kSkipAndEnableSync) - UpdateSyncSettings(/*enable_os_sync=*/true, /*enable_browser_sync=*/true); + UpdateSyncSettings(/*enable_sync=*/true); } // static
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_screen.h b/chrome/browser/chromeos/login/screens/sync_consent_screen.h index 65dccc2..18deaf9 100644 --- a/chrome/browser/chromeos/login/screens/sync_consent_screen.h +++ b/chrome/browser/chromeos/login/screens/sync_consent_screen.h
@@ -86,14 +86,13 @@ void OnContinueWithDefaults(const std::vector<int>& consent_description, const int consent_confirmation); - // Reacts to "Accept and Continue". + // Reacts to "Yes, I'm in" and "No, thanks". void OnAcceptAndContinue(const std::vector<int>& consent_description, int consent_confirmation, - bool enable_os_sync, - bool enable_browser_sync); + bool enable_sync); // Configures OS sync and browser sync. - void UpdateSyncSettings(bool enable_os_sync, bool enable_browser_sync); + void UpdateSyncSettings(bool enable_sync); // Enables sync if required when skipping the dialog. void MaybeEnableSyncForSkip();
diff --git a/chrome/browser/chromeos/net/mojom/network_health.mojom b/chrome/browser/chromeos/net/mojom/network_health.mojom index 791258e..34a77f9 100644 --- a/chrome/browser/chromeos/net/mojom/network_health.mojom +++ b/chrome/browser/chromeos/net/mojom/network_health.mojom
@@ -13,14 +13,12 @@ enum NetworkState { // The network type is available but not yet initialized. kUninitialized, - // The network type is available but disabled. + // The network type is available but disabled or disabling. kDisabled, - // The network type is available and enabling. - kEnabling, // The network type is prohibited by policy. kProhibited, - // The network type is available and enabled, but no network connection has - // been established. + // The network type is available and enabled or enabling, but no network + // connection has been established. kNotConnected, // The network type is available and enabled, and a network connection is // in progress.
diff --git a/chrome/browser/chromeos/net/network_health.cc b/chrome/browser/chromeos/net/network_health.cc index 34ffd94..53409be 100644 --- a/chrome/browser/chromeos/net/network_health.cc +++ b/chrome/browser/chromeos/net/network_health.cc
@@ -22,9 +22,11 @@ case network_config::mojom::DeviceStateType::kUninitialized: return mojom::NetworkState::kUninitialized; case network_config::mojom::DeviceStateType::kDisabled: - return mojom::NetworkState::kDisabled; + case network_config::mojom::DeviceStateType::kDisabling: case network_config::mojom::DeviceStateType::kEnabling: - return mojom::NetworkState::kEnabling; + // Disabling and Enabling are intermediate state that we care about in the + // UI, but not for purposes of network health, we can treat as Disabled. + return mojom::NetworkState::kDisabled; case network_config::mojom::DeviceStateType::kEnabled: return mojom::NetworkState::kNotConnected; case network_config::mojom::DeviceStateType::kProhibited:
diff --git a/chrome/browser/chromeos/net/network_health_unittest.cc b/chrome/browser/chromeos/net/network_health_unittest.cc index b3a3e49..d01e95d 100644 --- a/chrome/browser/chromeos/net/network_health_unittest.cc +++ b/chrome/browser/chromeos/net/network_health_unittest.cc
@@ -105,8 +105,6 @@ ValidateState(network_health::mojom::NetworkState::kDisabled); } -// TODO(crbug/1081488): implement test for kEnabling state. - TEST_F(NetworkHealthTest, NetworkStateProhibited) { cros_network_config_test_helper_.network_state_helper() .manager_test()
diff --git a/chrome/browser/chromeos/policy/system_proxy_manager.cc b/chrome/browser/chromeos/policy/system_proxy_manager.cc index 4242597..5fef546 100644 --- a/chrome/browser/chromeos/policy/system_proxy_manager.cc +++ b/chrome/browser/chromeos/policy/system_proxy_manager.cc
@@ -83,14 +83,17 @@ return; } - system_proxy::SetSystemTrafficCredentialsRequest request; - request.set_system_services_username(*username); - request.set_system_services_password(*password); + system_proxy::Credentials credentials; + credentials.set_username(*username); + credentials.set_password(*password); - chromeos::SystemProxyClient::Get()->SetSystemTrafficCredentials( - request, - base::BindOnce(&SystemProxyManager::OnSetSystemTrafficCredentials, - weak_factory_.GetWeakPtr())); + system_proxy::SetAuthenticationDetailsRequest request; + request.set_traffic_type(system_proxy::TrafficOrigin::SYSTEM); + *request.mutable_credentials() = credentials; + + chromeos::SystemProxyClient::Get()->SetAuthenticationDetails( + request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails, + weak_factory_.GetWeakPtr())); } void SystemProxyManager::SetSystemServicesProxyUrlForTest( @@ -99,8 +102,8 @@ system_services_address_ = local_proxy_url; } -void SystemProxyManager::OnSetSystemTrafficCredentials( - const system_proxy::SetSystemTrafficCredentialsResponse& response) { +void SystemProxyManager::OnSetAuthenticationDetails( + const system_proxy::SetAuthenticationDetailsResponse& response) { if (response.has_error_message()) { NET_LOG(ERROR) << "Failed to set system traffic credentials for system proxy: "
diff --git a/chrome/browser/chromeos/policy/system_proxy_manager.h b/chrome/browser/chromeos/policy/system_proxy_manager.h index f7291a6d..b2c4e53 100644 --- a/chrome/browser/chromeos/policy/system_proxy_manager.h +++ b/chrome/browser/chromeos/policy/system_proxy_manager.h
@@ -12,7 +12,7 @@ #include "chromeos/dbus/system_proxy/system_proxy_service.pb.h" namespace system_proxy { -class SetSystemTrafficCredentialsResponse; +class SetAuthenticationDetailsResponse; class ShutDownResponse; } // namespace system_proxy @@ -42,8 +42,8 @@ void SetSystemServicesProxyUrlForTest(const std::string& local_proxy_url); private: - void OnSetSystemTrafficCredentials( - const system_proxy::SetSystemTrafficCredentialsResponse& response); + void OnSetAuthenticationDetails( + const system_proxy::SetAuthenticationDetailsResponse& response); void OnDaemonShutDown(const system_proxy::ShutDownResponse& response); // Once a trusted set of policies is established, this function calls
diff --git a/chrome/browser/chromeos/policy/system_proxy_manager_unittest.cc b/chrome/browser/chromeos/policy/system_proxy_manager_unittest.cc index 75cd1da..a5add30 100644 --- a/chrome/browser/chromeos/policy/system_proxy_manager_unittest.cc +++ b/chrome/browser/chromeos/policy/system_proxy_manager_unittest.cc
@@ -48,24 +48,21 @@ // Verifies that System-proxy is configured with the system traffic credentials // set by |kSystemProxySettings| policy. -TEST_F(SystemProxyManagerTest, SetSystemTrafficCredentials) { +TEST_F(SystemProxyManagerTest, SetAuthenticationDetails) { SystemProxyManager system_proxy_manager(chromeos::CrosSettings::Get()); - EXPECT_EQ(0, - client_test_interface()->GetSetSystemTrafficCredentialsCallCount()); + EXPECT_EQ(0, client_test_interface()->GetSetAuthenticationDetailsCallCount()); SetPolicy(true /* system_proxy_enabled */, "" /* system_services_username */, "" /* system_services_password */); task_environment_.RunUntilIdle(); // Don't send empty credentials. - EXPECT_EQ(0, - client_test_interface()->GetSetSystemTrafficCredentialsCallCount()); + EXPECT_EQ(0, client_test_interface()->GetSetAuthenticationDetailsCallCount()); SetPolicy(true /* system_proxy_enabled */, "test" /* system_services_username */, "test" /* system_services_password */); task_environment_.RunUntilIdle(); - EXPECT_EQ(1, - client_test_interface()->GetSetSystemTrafficCredentialsCallCount()); + EXPECT_EQ(1, client_test_interface()->GetSetAuthenticationDetailsCallCount()); } // Verifies requests to shut down are sent to System-proxy according to the
diff --git a/chrome/browser/download/android/BUILD.gn b/chrome/browser/download/android/BUILD.gn index eed1a8a9..e6d547d 100644 --- a/chrome/browser/download/android/BUILD.gn +++ b/chrome/browser/download/android/BUILD.gn
@@ -22,6 +22,9 @@ "java/src/org/chromium/chrome/browser/download/MediaStoreHelper.java", "java/src/org/chromium/chrome/browser/download/MimeUtils.java", "java/src/org/chromium/chrome/browser/download/StringUtils.java", + "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogCoordinator.java", + "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogProperties.java", + "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java", "java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinator.java", "java/src/org/chromium/chrome/browser/download/home/DownloadManagerUiConfig.java", "java/src/org/chromium/chrome/browser/download/home/FaviconProvider.java", @@ -134,6 +137,7 @@ "java/res/layout/confirm_oma_download.xml", "java/res/layout/download_home_tabs.xml", "java/res/layout/download_home_toolbar.xml", + "java/res/layout/download_later_dialog.xml", "java/res/layout/download_location_dialog.xml", "java/res/layout/download_location_preference.xml", "java/res/layout/download_location_preference_item.xml",
diff --git a/chrome/browser/download/android/java/res/layout/download_later_dialog.xml b/chrome/browser/download/android/java/res/layout/download_later_dialog.xml new file mode 100644 index 0000000..3ec5755d --- /dev/null +++ b/chrome/browser/download/android/java/res/layout/download_later_dialog.xml
@@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> + +<org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + style="@style/AlertDialogContent"> + + <TextView + android:id="@+id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="3dp" + android:textAppearance="@style/TextAppearance.DownloadLaterTitle" + android:text="@string/download_later_dialog_title" /> + + <TextView + android:id="@+id/subtitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="10dp" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" + android:text="@string/download_later_dialog_subtitle" /> + + <org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout + android:id="@+id/radio_button_layout" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <!-- TODO(xingliu): Use 0 paddingStart for RadioButtonWithDescription. See crbug.com/1090062 --> + <!-- TODO(xingliu): Adjust margin between RadioButtonWithDescription. See crbug.com/1090155 --> + <org.chromium.components.browser_ui.widget.RadioButtonWithDescription + android:id="@+id/download_now" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="1dp" + app:primaryText="@string/download_later_download_now_text" /> + + <org.chromium.components.browser_ui.widget.RadioButtonWithDescription + android:id="@+id/on_wifi" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="1dp" + app:primaryText="@string/download_later_on_wifi_text" /> + + <org.chromium.components.browser_ui.widget.RadioButtonWithDescription + android:id="@+id/choose_date_time" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="1dp" + app:primaryText="@string/download_later_pick_time_text" /> + + </org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout> + + <CheckBox + android:id="@+id/show_again_checkbox" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="11dp" + android:layout_marginBottom="11dp" + android:layout_marginStart="-5dp" + android:text="@string/download_location_dialog_checkbox" + style="@style/TextAppearance.TextMedium.Tertiary" /> + + </LinearLayout> +</org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogView>
diff --git a/chrome/browser/download/android/java/res/values-v17/styles.xml b/chrome/browser/download/android/java/res/values-v17/styles.xml index b944c2b..4056d99 100644 --- a/chrome/browser/download/android/java/res/values-v17/styles.xml +++ b/chrome/browser/download/android/java/res/values-v17/styles.xml
@@ -82,4 +82,9 @@ <item name="android:src">@drawable/ic_play_arrow_white_36dp</item> <item name="android:tint">@color/modern_grey_800</item> </style> + + <!-- Download Later Styles --> + <style name="TextAppearance.DownloadLaterTitle" parent="TextAppearance.AlertDialogTitleStyle"> + <item name="android:textSize">20sp</item> + </style> </resources>
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogCoordinator.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogCoordinator.java new file mode 100644 index 0000000..564a3b6 --- /dev/null +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogCoordinator.java
@@ -0,0 +1,85 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.download.dialogs; + +import android.app.Activity; +import android.content.Context; +import android.view.LayoutInflater; + +import org.chromium.chrome.browser.download.R; +import org.chromium.ui.modaldialog.DialogDismissalCause; +import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.modaldialog.ModalDialogProperties; +import org.chromium.ui.modelutil.PropertyKey; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModelChangeProcessor; + +/** + * Coordinator to construct the download later dialog. + */ +public class DownloadLaterDialogCoordinator { + private final PropertyModel mDownloadLaterDialogModel; + private final DownloadLaterDialogView mCustomView; + private final ModalDialogManager mModalDialogManager; + private final PropertyModel mDialogModel; + private final ModalDialogProperties.Controller mController; + private final PropertyModelChangeProcessor<PropertyModel, DownloadLaterDialogView, PropertyKey> + mPropertyModelChangeProcessor; + + /** + * The coordinator that bridges the download later diaog view logic to multiple data models. + * @param activity The activity mainly to provide the {@link ModalDialogManager}. + */ + public DownloadLaterDialogCoordinator(Activity activity, ModalDialogManager modalDialogManager, + ModalDialogProperties.Controller controller) { + // Set up the download later UI MVC. + mDownloadLaterDialogModel = new PropertyModel(DownloadLaterDialogProperties.ALL_KEYS); + mCustomView = (DownloadLaterDialogView) LayoutInflater.from(activity).inflate( + R.layout.download_later_dialog, null); + mPropertyModelChangeProcessor = + PropertyModelChangeProcessor.create(mDownloadLaterDialogModel, mCustomView, + DownloadLaterDialogView.Binder::bind, true /*performInitialBind*/); + + // Set up the modal dialog. + mModalDialogManager = modalDialogManager; + mController = controller; + mDialogModel = getModalDialogModel(activity); + } + + /** + * Shows the download later dialog. + */ + public void showDialog() { + mModalDialogManager.showDialog(mDialogModel, ModalDialogManager.ModalDialogType.APP); + } + + /** + * Dismisses the download later dialog. + * @param dismissalCause The reason to dismiss the dialog, used in metrics tracking. + */ + public void dismissDialog(@DialogDismissalCause int dismissalCause) { + mModalDialogManager.dismissDialog(mDialogModel, dismissalCause); + } + + /** + * Destroy the download later dialog. + */ + public void destroy() { + mPropertyModelChangeProcessor.destroy(); + } + + private PropertyModel getModalDialogModel(Context context) { + assert mController != null; + assert mCustomView != null; + return new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) + .with(ModalDialogProperties.CONTROLLER, mController) + .with(ModalDialogProperties.CUSTOM_VIEW, mCustomView) + .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, context.getResources(), + R.string.duplicate_download_infobar_download_button) + .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, context.getResources(), + R.string.cancel) + .build(); + } +}
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogProperties.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogProperties.java new file mode 100644 index 0000000..33c2be8f --- /dev/null +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogProperties.java
@@ -0,0 +1,19 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.download.dialogs; + +import org.chromium.ui.modelutil.PropertyKey; +import org.chromium.ui.modelutil.PropertyModel; + +/** + * Contains all the properties for the download later dialog {@link PropertyModel}. + */ +public class DownloadLaterDialogProperties { + /** The selection to define when to start the download. */ + public static final PropertyModel.WritableIntPropertyKey DOWNLOAD_TIME_SELECTION = + new PropertyModel.WritableIntPropertyKey(); + + public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {DOWNLOAD_TIME_SELECTION}; +}
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java new file mode 100644 index 0000000..2a063fc9 --- /dev/null +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java
@@ -0,0 +1,31 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.download.dialogs; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +import androidx.annotation.Nullable; + +import org.chromium.ui.modelutil.PropertyKey; +import org.chromium.ui.modelutil.PropertyModel; + +/** + * The custom view in the download later dialog. + */ +public class DownloadLaterDialogView extends LinearLayout { + /** + * The view binder to propagate events from model to view. + */ + public static class Binder { + public static void bind( + PropertyModel model, DownloadLaterDialogView view, PropertyKey propertyKey) {} + } + + public DownloadLaterDialogView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } +}
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc index 8941666..7d4467e 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -348,7 +348,6 @@ } // TODO(crbug.com/1063426): Log nickname management via settings page. - // TODO(crbug.com/1063426): add corresponding nickname autofill_private test. if (card->nickname) { credit_card.SetNickname(base::UTF8ToUTF16(*card->nickname)); }
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc index 6c4f2b9..cd201d1 100644 --- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc +++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -522,17 +522,10 @@ // ControlledInfo. bool is_policy_location = Manifest::IsPolicyLocation(extension.location()); if (is_policy_location) { - info->controlled_info.reset(new developer::ControlledInfo()); - if (is_policy_location) { - info->controlled_info->type = developer::CONTROLLER_TYPE_POLICY; - info->controlled_info->text = - l10n_util::GetStringUTF8(IDS_EXTENSIONS_INSTALL_LOCATION_ENTERPRISE); - } else { - info->controlled_info->type = - developer::CONTROLLER_TYPE_SUPERVISED_USER_CUSTODIAN; - info->controlled_info->text = l10n_util::GetStringUTF8( - IDS_EXTENSIONS_INSTALLED_BY_SUPERVISED_USER_CUSTODIAN); - } + info->controlled_info = std::make_unique<developer::ControlledInfo>(); + info->controlled_info->type = developer::CONTROLLER_TYPE_POLICY; + info->controlled_info->text = + l10n_util::GetStringUTF8(IDS_EXTENSIONS_INSTALL_LOCATION_ENTERPRISE); } bool is_enabled = state == developer::EXTENSION_STATE_ENABLED;
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index ad8c1c5..ee1f90c 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -1048,16 +1048,10 @@ return function; } -// https://crbug.com/678967 -#if defined(OS_WIN) || defined(OS_LINUX) -#define MAYBE_DownloadExtensionTest_FileIcon_Active DISABLED_DownloadExtensionTest_FileIcon_Active -#else -#define MAYBE_DownloadExtensionTest_FileIcon_Active DownloadExtensionTest_FileIcon_Active -#endif // Test downloads.getFileIcon() on in-progress, finished, cancelled and deleted // download items. IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, - MAYBE_DownloadExtensionTest_FileIcon_Active) { + DownloadExtensionTest_FileIcon_Active) { DownloadItem* download_item = CreateFirstSlowTestDownload(); ASSERT_TRUE(download_item); ASSERT_FALSE(download_item->GetTargetFilePath().empty());
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc index 624ac0b3..4bee70b 100644 --- a/chrome/browser/extensions/extension_web_ui.cc +++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include <iterator> #include <set> #include <utility> #include <vector> @@ -342,6 +343,81 @@ } } +// A helper method to retrieve active overrides for the given |url|, if any. If +// |get_all| is true, this will retrieve all active overrides; otherwise it will +// return the highest-priority one (potentially early-out-ing). The resulting +// vector is ordered by priority. +std::vector<GURL> GetOverridesForChromeURL( + const GURL& url, + content::BrowserContext* browser_context, + bool get_all) { + // Only chrome: URLs can be overridden like this. + DCHECK(url.SchemeIs(content::kChromeUIScheme)); + + Profile* profile = Profile::FromBrowserContext(browser_context); + const base::DictionaryValue* overrides = profile->GetPrefs()->GetDictionary( + ExtensionWebUI::kExtensionURLOverrides); + + const base::ListValue* url_list = nullptr; + if (!overrides || !overrides->GetList(url.host_piece(), &url_list)) + return {}; // No overrides present for this host. + + extensions::ExtensionRegistry* registry = + extensions::ExtensionRegistry::Get(browser_context); + const extensions::ExtensionSet& extensions = registry->enabled_extensions(); + + // Separate out overrides from non-component extensions (higher priority). + std::vector<GURL> override_urls; + std::vector<GURL> component_overrides; + + // Iterate over the URL list looking for suitable overrides. + for (const auto& value : *url_list) { + GURL override_url; + const Extension* extension = nullptr; + if (!ValidateOverrideURL(&value, url, extensions, &override_url, + &extension)) { + // Invalid overrides are cleaned up on startup. + continue; + } + + // We can't handle chrome-extension URLs in incognito mode unless the + // extension uses split mode. + bool incognito_override_allowed = + extensions::IncognitoInfo::IsSplitMode(extension) && + extensions::util::IsIncognitoEnabled(extension->id(), profile); + if (profile->IsOffTheRecord() && !incognito_override_allowed) { + continue; + } + + if (extensions::Manifest::IsComponentLocation(extension->location())) { + component_overrides.push_back(override_url); + } else { + override_urls.push_back(override_url); + if (!get_all) { // Early out, since the highest-priority was found. + DCHECK_EQ(1u, override_urls.size()); + return override_urls; + } + } + } + + if (!get_all) { + // Since component overrides are lower priority, we should only get here if + // there are no non-component overrides. + DCHECK(override_urls.empty()); + // Return the highest-priority component override, if any. + if (component_overrides.size() > 1u) { + component_overrides.erase(component_overrides.begin() + 1, + component_overrides.end()); + } + return component_overrides; + } + + override_urls.insert(override_urls.end(), + std::make_move_iterator(component_overrides.begin()), + std::make_move_iterator(component_overrides.end())); + return override_urls; +} + } // namespace const char ExtensionWebUI::kExtensionURLOverrides[] = @@ -360,64 +436,13 @@ if (!url->SchemeIs(content::kChromeUIScheme)) return false; - Profile* profile = Profile::FromBrowserContext(browser_context); - const base::DictionaryValue* overrides = - profile->GetPrefs()->GetDictionary(kExtensionURLOverrides); - - std::string url_host = url->host(); - const base::ListValue* url_list = NULL; - if (!overrides || !overrides->GetList(url_host, &url_list)) + std::vector<GURL> overrides = + GetOverridesForChromeURL(*url, browser_context, /*get_all=*/false); + if (overrides.empty()) return false; - extensions::ExtensionRegistry* registry = - extensions::ExtensionRegistry::Get(browser_context); - const extensions::ExtensionSet& extensions = registry->enabled_extensions(); - - GURL component_url; - bool found_component_override = false; - - // Iterate over the URL list looking for a suitable override. If a - // valid non-component override is encountered it is chosen immediately. - for (size_t i = 0; i < url_list->GetSize(); ++i) { - const base::Value* val = NULL; - url_list->Get(i, &val); - - GURL override_url; - const Extension* extension; - if (!ValidateOverrideURL( - val, *url, extensions, &override_url, &extension)) { - // Invalid overrides are cleaned up on startup. - continue; - } - - // We can't handle chrome-extension URLs in incognito mode unless the - // extension uses split mode. - bool incognito_override_allowed = - extensions::IncognitoInfo::IsSplitMode(extension) && - extensions::util::IsIncognitoEnabled(extension->id(), profile); - if (profile->IsOffTheRecord() && !incognito_override_allowed) { - continue; - } - - if (!extensions::Manifest::IsComponentLocation(extension->location())) { - *url = override_url; - return true; - } - - if (!found_component_override) { - found_component_override = true; - component_url = override_url; - } - } - - // If no other non-component overrides were found, use the first known - // component override, if any. - if (found_component_override) { - *url = component_url; - return true; - } - - return false; + *url = overrides[0]; + return true; } // static @@ -482,6 +507,17 @@ } // static +size_t ExtensionWebUI::GetNumberOfExtensionsOverridingURL( + const GURL& url, + content::BrowserContext* browser_context) { + if (!url.SchemeIs(content::kChromeUIScheme)) + return 0; + + return GetOverridesForChromeURL(url, browser_context, /*get_all=*/true) + .size(); +} + +// static void ExtensionWebUI::InitializeChromeURLOverrides(Profile* profile) { ForEachOverrideList(profile, base::Bind(&InitializeOverridesList)); }
diff --git a/chrome/browser/extensions/extension_web_ui.h b/chrome/browser/extensions/extension_web_ui.h index e63d7e5..30e1372 100644 --- a/chrome/browser/extensions/extension_web_ui.h +++ b/chrome/browser/extensions/extension_web_ui.h
@@ -44,6 +44,13 @@ const GURL& url, content::BrowserContext* browser_context); + // Returns the number of extensions that are overriding the given |url|. Note + // that only one is *actively* overriding it; the others would take over if + // that one were to be disabled or removed. + static size_t GetNumberOfExtensionsOverridingURL( + const GURL& url, + content::BrowserContext* browser_context); + // Initialize the Chrome URL overrides. This must happen *before* any further // calls for URL overrides! static void InitializeChromeURLOverrides(Profile* profile);
diff --git a/chrome/browser/extensions/extension_web_ui_unittest.cc b/chrome/browser/extensions/extension_web_ui_unittest.cc index 713ebf5..127a7624 100644 --- a/chrome/browser/extensions/extension_web_ui_unittest.cc +++ b/chrome/browser/extensions/extension_web_ui_unittest.cc
@@ -16,6 +16,7 @@ #include "components/favicon_base/favicon_callback.h" #include "components/favicon_base/favicon_types.h" #include "content/public/test/browser_task_environment.h" +#include "extensions/browser/disable_reason.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" @@ -257,4 +258,47 @@ } } +TEST_F(ExtensionWebUITest, TestNumExtensionsOverridingURL) { + auto load_extension_overriding_newtab = [this](const char* name) { + std::unique_ptr<base::Value> chrome_url_overrides = + DictionaryBuilder().Set("newtab", "newtab.html").Build(); + scoped_refptr<const Extension> extension = + ExtensionBuilder(name) + .SetLocation(Manifest::INTERNAL) + .SetManifestKey("chrome_url_overrides", + std::move(chrome_url_overrides)) + .Build(); + + extension_service_->AddExtension(extension.get()); + EXPECT_EQ(extension, ExtensionWebUI::GetExtensionControllingURL( + GURL(chrome::kChromeUINewTabURL), profile_.get())); + + return extension.get(); + }; + + const GURL ntp_url(chrome::kChromeUINewTabURL); + + // Load a series of extensions that override the new tab page. + const Extension* extension1 = load_extension_overriding_newtab("one"); + ASSERT_TRUE(extension1); + EXPECT_EQ(1u, ExtensionWebUI::GetNumberOfExtensionsOverridingURL( + ntp_url, profile_.get())); + + const Extension* extension2 = load_extension_overriding_newtab("two"); + ASSERT_TRUE(extension2); + EXPECT_EQ(2u, ExtensionWebUI::GetNumberOfExtensionsOverridingURL( + ntp_url, profile_.get())); + + const Extension* extension3 = load_extension_overriding_newtab("three"); + ASSERT_TRUE(extension3); + EXPECT_EQ(3u, ExtensionWebUI::GetNumberOfExtensionsOverridingURL( + ntp_url, profile_.get())); + + // Disabling an extension should remove it from the override count. + extension_service_->DisableExtension(extension2->id(), + disable_reason::DISABLE_USER_ACTION); + EXPECT_EQ(2u, ExtensionWebUI::GetNumberOfExtensionsOverridingURL( + ntp_url, profile_.get())); +} + } // namespace extensions
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 112ee1cf..3183e56 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -4452,6 +4452,11 @@ "expiry_milestone": 85 }, { + "name": "webxr-multi-gpu", + "owners": [ "//third_party/blink/renderer/modules/xr/OWNERS", "xr-dev@chromium.org" ], + "expiry_milestone": 88 + }, + { "name": "webxr-runtime", "owners": [ "//third_party/blink/renderer/modules/xr/OWNERS", "xr-dev@chromium.org" ], // This flag allows QA and Developers to force running on a particular
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 7a1a593..2e12b4c 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1275,9 +1275,8 @@ const char kNotificationIndicatorName[] = "Notification Indicators"; const char kNotificationIndicatorDescription[] = - "Enable notification indicators, which appear on app icons when a " - "notification is active. This will also enable notifications in context " - "menus."; + "Enable notification indicators, which appear on shelf app icons when a " + "notification is active."; const char kNotificationSchedulerDebugOptionName[] = "Notification scheduler debug options"; @@ -2283,6 +2282,10 @@ const char kWebXrIncubationsDescription[] = "Enables experimental features for WebXR."; +const char kWebXrMultiGpuName[] = "WebXR Multi GPU Support"; +const char kWebXrMultiGpuDescription[] = + "Improves WebXR support for computers with more than one GPU."; + const char kZeroCopyName[] = "Zero-copy rasterizer"; const char kZeroCopyDescription[] = "Raster threads write directly to GPU memory associated with tiles.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index d4a5487c..c750d615 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1324,6 +1324,9 @@ extern const char kWebXrIncubationsName[]; extern const char kWebXrIncubationsDescription[]; +extern const char kWebXrMultiGpuName[]; +extern const char kWebXrMultiGpuDescription[]; + extern const char kZeroCopyName[]; extern const char kZeroCopyDescription[];
diff --git a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java index 20cc5e0..6db5652f 100644 --- a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java +++ b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
@@ -87,32 +87,31 @@ * Tries to load the gif from disk, if not it falls back to the bridge. */ @Override - public void fetchGif(String url, String clientName, Callback<BaseGifImage> callback) { + public void fetchGif(final ImageFetcher.Params params, Callback<BaseGifImage> callback) { long startTimeMillis = System.currentTimeMillis(); PostTask.postTask(TaskTraits.USER_VISIBLE, () -> { // Try to read the gif from disk, then post back to the ui thread. - String filePath = getImageFetcherBridge().getFilePath(url); + String filePath = getImageFetcherBridge().getFilePath(params.url); BaseGifImage cachedGif = mImageLoader.tryToLoadGifFromDisk(filePath); PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE, () -> { - continueFetchGifAfterDisk(url, clientName, callback, cachedGif, startTimeMillis); + continueFetchGifAfterDisk(params, callback, cachedGif, startTimeMillis); }); }); } @VisibleForTesting - void continueFetchGifAfterDisk(String url, String clientName, Callback<BaseGifImage> callback, - BaseGifImage cachedGif, long startTimeMillis) { + void continueFetchGifAfterDisk(final ImageFetcher.Params params, + Callback<BaseGifImage> callback, BaseGifImage cachedGif, long startTimeMillis) { if (cachedGif != null) { callback.onResult(cachedGif); - reportEvent(clientName, ImageFetcherEvent.JAVA_DISK_CACHE_HIT); - getImageFetcherBridge().reportCacheHitTime(clientName, startTimeMillis); + reportEvent(params.clientName, ImageFetcherEvent.JAVA_DISK_CACHE_HIT); + getImageFetcherBridge().reportCacheHitTime(params.clientName, startTimeMillis); } else { - getImageFetcherBridge().fetchGif( - getConfig(), url, clientName, (BaseGifImage gifFromNative) -> { - callback.onResult(gifFromNative); - getImageFetcherBridge().reportTotalFetchTimeFromNative( - clientName, startTimeMillis); - }); + getImageFetcherBridge().fetchGif(getConfig(), params, (BaseGifImage gifFromNative) -> { + callback.onResult(gifFromNative); + getImageFetcherBridge().reportTotalFetchTimeFromNative( + params.clientName, startTimeMillis); + }); } }
diff --git a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java index 07dc531..ca5e525 100644 --- a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java +++ b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
@@ -192,13 +192,13 @@ /** * Fetch the gif for the given url. * - * @param url The url to fetch the image from. - * @param clientName The UMA client name to report the metrics to. If using CachedImageFetcher - * to fetch images and gifs, use separate clientNames for them. + * @param params The parameters to specify image fetching details. If using CachedImageFetcher + * to fetch images and gifs, use separate {@link Params#clientName} for them. * @param callback The function which will be called when the image is ready; will be called * with null result if fetching fails. */ - public abstract void fetchGif(String url, String clientName, Callback<BaseGifImage> callback); + public abstract void fetchGif( + final ImageFetcher.Params params, Callback<BaseGifImage> callback); /** * Fetches the image based on customized parameters specified.
diff --git a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java index 3ded770..322b2d6 100644 --- a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java +++ b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java
@@ -67,16 +67,16 @@ /** * Fetch a gif from native or null if the gif can't be fetched or decoded. * - * @param url The url to fetch. - * @param clientName The UMA client name to report the metrics to. + * @param params The parameters to specify image fetching details. * @param callback The callback to call when the gif is ready. The callback will be invoked on * the same thread it was called on. */ - public void fetchGif(@ImageFetcherConfig int config, String url, String clientName, + public void fetchGif(@ImageFetcherConfig int config, final ImageFetcher.Params params, Callback<BaseGifImage> callback) { assert mNativeImageFetcherBridge != 0 : "fetchGif called after destroy"; ImageFetcherBridgeJni.get().fetchImageData(mNativeImageFetcherBridge, - ImageFetcherBridge.this, config, url, clientName, (byte[] data) -> { + ImageFetcherBridge.this, config, params.url, params.clientName, + params.expirationIntervalMinutes, (byte[] data) -> { if (data == null || data.length == 0) { callback.onResult(null); return; @@ -161,7 +161,7 @@ String getFilePath(long nativeImageFetcherBridge, ImageFetcherBridge caller, String url); void fetchImageData(long nativeImageFetcherBridge, ImageFetcherBridge caller, @ImageFetcherConfig int config, String url, String clientName, - Callback<byte[]> callback); + int expirationIntervalMinutes, Callback<byte[]> callback); void fetchImage(long nativeImageFetcherBridge, ImageFetcherBridge caller, @ImageFetcherConfig int config, String url, String clientName, int expirationIntervalMinutes, Callback<Bitmap> callback);
diff --git a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java index 8543529..ed33c76 100644 --- a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java +++ b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java
@@ -86,9 +86,9 @@ } @Override - public void fetchGif(String url, String clientName, Callback<BaseGifImage> callback) { + public void fetchGif(final Params params, Callback<BaseGifImage> callback) { assert mBitmapCache != null && mImageFetcher != null : "fetchGif called after destroy"; - mImageFetcher.fetchGif(url, clientName, callback); + mImageFetcher.fetchGif(params, callback); } @Override
diff --git a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java index 2439ccf..3d3f3d3 100644 --- a/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java +++ b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
@@ -29,8 +29,8 @@ } @Override - public void fetchGif(String url, String clientName, Callback<BaseGifImage> callback) { - getImageFetcherBridge().fetchGif(getConfig(), url, clientName, callback); + public void fetchGif(final ImageFetcher.Params params, Callback<BaseGifImage> callback) { + getImageFetcherBridge().fetchGif(getConfig(), params, callback); } @Override
diff --git a/chrome/browser/performance_manager/policies/policy_features.cc b/chrome/browser/performance_manager/policies/policy_features.cc index c27ca928..7818bda 100644 --- a/chrome/browser/performance_manager/policies/policy_features.cc +++ b/chrome/browser/performance_manager/policies/policy_features.cc
@@ -88,6 +88,22 @@ "UrgentDiscardingFromPerformanceManager", base::FEATURE_DISABLED_BY_DEFAULT}; +UrgentDiscardingParams::UrgentDiscardingParams() = default; +UrgentDiscardingParams::UrgentDiscardingParams( + const UrgentDiscardingParams& rhs) = default; +UrgentDiscardingParams::~UrgentDiscardingParams() = default; + +constexpr base::FeatureParam<int> UrgentDiscardingParams::kDiscardStrategy; + +// static +UrgentDiscardingParams UrgentDiscardingParams::GetParams() { + UrgentDiscardingParams params = {}; + params.discard_strategy_ = + static_cast<UrgentDiscardingParams::DiscardStrategy>( + UrgentDiscardingParams::kDiscardStrategy.Get()); + return params; +} + const base::Feature kBackgroundTabLoadingFromPerformanceManager{ "BackgroundTabLoadingFromPerformanceManager", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/performance_manager/policies/policy_features.h b/chrome/browser/performance_manager/policies/policy_features.h index 6f0a004..5415246 100644 --- a/chrome/browser/performance_manager/policies/policy_features.h +++ b/chrome/browser/performance_manager/policies/policy_features.h
@@ -85,6 +85,35 @@ // than via TabManager. extern const base::Feature kUrgentDiscardingFromPerformanceManager; +class UrgentDiscardingParams { + public: + ~UrgentDiscardingParams(); + + static UrgentDiscardingParams GetParams(); + + // The discard strategy to use. + // Integer values are specified to allow conversion from the integer value in + // the DiscardStrategy feature param. + enum class DiscardStrategy : int { + // Discards the least recently used tab among the eligible ones. + LRU = 0, + // Discard the tab with the biggest resident set among the eligible ones. + BIGGEST_RSS = 1, + }; + + DiscardStrategy discard_strategy() const { return discard_strategy_; } + + static constexpr base::FeatureParam<int> kDiscardStrategy{ + &features::kUrgentDiscardingFromPerformanceManager, "DiscardStrategy", + static_cast<int>(DiscardStrategy::BIGGEST_RSS)}; + + private: + UrgentDiscardingParams(); + UrgentDiscardingParams(const UrgentDiscardingParams& rhs); + + DiscardStrategy discard_strategy_; +}; + // Enable background tab loading of pages (restored via session restore) // directly from Performance Manager rather than via TabLoader. extern const base::Feature kBackgroundTabLoadingFromPerformanceManager;
diff --git a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc index f7f0f4fb9c..9233a9ce 100644 --- a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc +++ b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc
@@ -240,6 +240,7 @@ base::flat_map<const PageNode*, uint64_t> discardable_pages; base::TimeDelta oldest_bg_time; const PageNode* oldest_bg_discardable_page_node = nullptr; + const PageNode* discard_candidate = nullptr; // Find all the pages that could be discarded. for (const auto* page_node : graph_->GetAllPageNodes()) { if (!CanUrgentlyDiscard(page_node)) @@ -261,56 +262,64 @@ return; } - // List all the processes associated with these page nodes. - base::flat_set<const ProcessNode*> process_nodes; - for (const auto& iter : discardable_pages) { - auto processes = GraphOperations::GetAssociatedProcessNodes(iter.first); - process_nodes.insert(processes.begin(), processes.end()); - } + auto discard_strategy = + features::UrgentDiscardingParams::GetParams().discard_strategy(); + if (discard_strategy == + features::UrgentDiscardingParams::DiscardStrategy::LRU) { + discard_candidate = oldest_bg_discardable_page_node; + } else if (discard_strategy == + features::UrgentDiscardingParams::DiscardStrategy::BIGGEST_RSS) { + // List all the processes associated with these page nodes. + base::flat_set<const ProcessNode*> process_nodes; + for (const auto& iter : discardable_pages) { + auto processes = GraphOperations::GetAssociatedProcessNodes(iter.first); + process_nodes.insert(processes.begin(), processes.end()); + } - uint64_t largest_resident_set_kb = 0; - const PageNode* largest_page_node = nullptr; - // Compute the resident set of each page by simply summing up the estimated - // resident set of all its frames, find the largest one. - for (const ProcessNode* process_node : process_nodes) { - auto process_frames = process_node->GetFrameNodes(); - uint64_t frame_rss_kb = 0; - // Get the resident set of the process and split it equally across its - // frames. - if (process_frames.size()) - frame_rss_kb = process_node->GetResidentSetKb() / process_frames.size(); - for (const FrameNode* frame_node : process_frames) { - // Check if the frame belongs to a discardable page, if so update the - // resident set of the page. - auto iter = discardable_pages.find(frame_node->GetPageNode()); - if (iter == discardable_pages.end()) - continue; - iter->second += frame_rss_kb; - if (iter->second > largest_resident_set_kb) { - largest_resident_set_kb = iter->second; - largest_page_node = iter->first; + uint64_t largest_resident_set_kb = 0; + const PageNode* largest_page_node = nullptr; + // Compute the resident set of each page by simply summing up the estimated + // resident set of all its frames, find the largest one. + for (const ProcessNode* process_node : process_nodes) { + auto process_frames = process_node->GetFrameNodes(); + uint64_t frame_rss_kb = 0; + // Get the resident set of the process and split it equally across its + // frames. + if (process_frames.size()) + frame_rss_kb = process_node->GetResidentSetKb() / process_frames.size(); + for (const FrameNode* frame_node : process_frames) { + // Check if the frame belongs to a discardable page, if so update the + // resident set of the page. + auto iter = discardable_pages.find(frame_node->GetPageNode()); + if (iter == discardable_pages.end()) + continue; + iter->second += frame_rss_kb; + if (iter->second > largest_resident_set_kb) { + largest_resident_set_kb = iter->second; + largest_page_node = iter->first; + } } } - } - - if (largest_page_node) { - // Only report the memory usage metrics if we can compare them. - UMA_HISTOGRAM_COUNTS_1000("Discarding.LargestTabFootprint", - discardable_pages[largest_page_node] / 1024); - UMA_HISTOGRAM_COUNTS_1000( - "Discarding.OldestTabFootprint", - discardable_pages[oldest_bg_discardable_page_node] / 1024); - } else { - largest_page_node = oldest_bg_discardable_page_node; + if (largest_page_node) { + // Only report the memory usage metrics if we can compare them. + UMA_HISTOGRAM_COUNTS_1000("Discarding.LargestTabFootprint", + discardable_pages[largest_page_node] / 1024); + UMA_HISTOGRAM_COUNTS_1000( + "Discarding.OldestTabFootprint", + discardable_pages[oldest_bg_discardable_page_node] / 1024); + discard_candidate = largest_page_node; + } else { + discard_candidate = oldest_bg_discardable_page_node; + } } // Adorns the PageNode with a discard attempt marker to make sure that we // don't try to discard it multiple times if it fails to be discarded. In // practice this should only happen to prerenderers. - DiscardAttemptMarker::GetOrCreate(PageNodeImpl::FromNode(largest_page_node)); + DiscardAttemptMarker::GetOrCreate(PageNodeImpl::FromNode(discard_candidate)); page_discarder_->DiscardPageNode( - largest_page_node, + discard_candidate, base::BindOnce(&UrgentPageDiscardingPolicy::PostDiscardAttemptCallback, weak_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h index 8a962c8..98eb41f 100644 --- a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h +++ b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h
@@ -24,8 +24,9 @@ namespace policies { -// Urgently discard a tab when receiving a memory pressure signal. The discarded -// tab will be the eligible tab with the largest resident set. +// Urgently discard a tab when receiving a memory pressure signal. The discard +// strategy used by this policy is based on a feature flag, see +// UrgentDiscardingParams for more details. class UrgentPageDiscardingPolicy : public GraphOwned, public PageNode::ObserverDefaultImpl, public NodeDataDescriberDefaultImpl {
diff --git a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc index 0d147b5..de52518 100644 --- a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc +++ b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc
@@ -7,11 +7,14 @@ #include <memory> #include "base/memory/memory_pressure_listener.h" +#include "base/strings/string_number_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "base/util/memory_pressure/fake_memory_pressure_monitor.h" #include "chrome/browser/performance_manager/decorators/page_aggregator.h" #include "chrome/browser/performance_manager/mechanisms/page_discarder.h" +#include "chrome/browser/performance_manager/policies/policy_features.h" #include "components/performance_manager/graph/frame_node_impl.h" #include "components/performance_manager/graph/graph_impl.h" #include "components/performance_manager/graph/node_attached_data_impl.h" @@ -308,7 +311,30 @@ EXPECT_FALSE(policy()->CanUrgentlyDiscardForTesting(page_node())); } -TEST_F(UrgentPageDiscardingPolicyTest, UrgentlyDiscardAPageNoCandidate) { +class ParameterizedUrgentPageDiscardingPolicyTest + : public UrgentPageDiscardingPolicyTest, + public ::testing::WithParamInterface< + features::UrgentDiscardingParams::DiscardStrategy> { + public: + ParameterizedUrgentPageDiscardingPolicyTest() { + base::FieldTrialParams params; + params[features::UrgentDiscardingParams::kDiscardStrategy.name] = + base::NumberToString(static_cast<int>(GetParam())); + feature_list_.InitAndEnableFeatureWithParameters( + features::kUrgentDiscardingFromPerformanceManager, params); + } + ~ParameterizedUrgentPageDiscardingPolicyTest() override = default; + ParameterizedUrgentPageDiscardingPolicyTest( + const ParameterizedUrgentPageDiscardingPolicyTest& other) = delete; + ParameterizedUrgentPageDiscardingPolicyTest& operator=( + const ParameterizedUrgentPageDiscardingPolicyTest&) = delete; + + protected: + base::test::ScopedFeatureList feature_list_; +}; + +TEST_P(ParameterizedUrgentPageDiscardingPolicyTest, + UrgentlyDiscardAPageNoCandidate) { page_node()->SetIsVisible(true); SimulateMemoryPressure(); testing::Mock::VerifyAndClearExpectations(discarder()); @@ -316,7 +342,8 @@ 1); } -TEST_F(UrgentPageDiscardingPolicyTest, UrgentlyDiscardAPageSingleCandidate) { +TEST_P(ParameterizedUrgentPageDiscardingPolicyTest, + UrgentlyDiscardAPageSingleCandidate) { EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node())) .WillOnce(Return(true)); SimulateMemoryPressure(); @@ -325,7 +352,7 @@ 1); } -TEST_F(UrgentPageDiscardingPolicyTest, +TEST_P(ParameterizedUrgentPageDiscardingPolicyTest, UrgentlyDiscardAPageSingleCandidateFails) { EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node())) .WillOnce(Return(false)); @@ -341,7 +368,8 @@ 1); } -TEST_F(UrgentPageDiscardingPolicyTest, UrgentlyDiscardAPageTwoCandidates) { +TEST_P(ParameterizedUrgentPageDiscardingPolicyTest, + UrgentlyDiscardAPageTwoCandidates) { auto process_node2 = CreateNode<performance_manager::ProcessNodeImpl>(); auto page_node2 = CreateNode<performance_manager::PageNodeImpl>(); auto main_frame_node2 = @@ -361,21 +389,29 @@ process_node()->set_resident_set_kb(1024); process_node2->set_resident_set_kb(2048); - // |page_node2| should be discarded despite being the most recently visible - // page as it has a bigger footprint. - EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get())) - .WillOnce(Return(true)); - SimulateMemoryPressure(); - testing::Mock::VerifyAndClearExpectations(discarder()); + if (GetParam() == + features::UrgentDiscardingParams::DiscardStrategy::BIGGEST_RSS) { + // |page_node2| should be discarded despite being the most recently visible + // page as it has a bigger footprint. + EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get())) + .WillOnce(Return(true)); + SimulateMemoryPressure(); + testing::Mock::VerifyAndClearExpectations(discarder()); + histogram_tester()->ExpectUniqueSample("Discarding.LargestTabFootprint", + 2048 / 1024, 1); + histogram_tester()->ExpectUniqueSample("Discarding.OldestTabFootprint", + 1024 / 1024, 1); + } else { + EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node())) + .WillOnce(Return(true)); + SimulateMemoryPressure(); + testing::Mock::VerifyAndClearExpectations(discarder()); + } histogram_tester()->ExpectBucketCount("Discarding.DiscardCandidatesCount", 2, 1); - histogram_tester()->ExpectUniqueSample("Discarding.LargestTabFootprint", - 2048 / 1024, 1); - histogram_tester()->ExpectUniqueSample("Discarding.OldestTabFootprint", - 1024 / 1024, 1); } -TEST_F(UrgentPageDiscardingPolicyTest, +TEST_P(ParameterizedUrgentPageDiscardingPolicyTest, UrgentlyDiscardAPageTwoCandidatesFirstFails) { auto process_node2 = CreateNode<performance_manager::ProcessNodeImpl>(); auto page_node2 = CreateNode<performance_manager::PageNodeImpl>(); @@ -389,15 +425,27 @@ // Pretends that the first discardable page hasn't been discarded // successfully, the other one should be discarded in this case. - EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get())) - .WillOnce(Return(false)); - EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node())) - .WillOnce(Return(true)); + if (GetParam() == + features::UrgentDiscardingParams::DiscardStrategy::BIGGEST_RSS) { + ::testing::InSequence in_sequence; + // The first candidate is the tab with the biggest RSS. + EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get())) + .WillOnce(Return(false)); + EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node())) + .WillOnce(Return(true)); + } else { + ::testing::InSequence in_sequence; + // The first candidate is the least recently used tab. + EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node())) + .WillOnce(Return(false)); + EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get())) + .WillOnce(Return(true)); + } SimulateMemoryPressure(); testing::Mock::VerifyAndClearExpectations(discarder()); } -TEST_F(UrgentPageDiscardingPolicyTest, +TEST_P(ParameterizedUrgentPageDiscardingPolicyTest, UrgentlyDiscardAPageTwoCandidatesMultipleFrames) { auto process_node2 = CreateNode<performance_manager::ProcessNodeImpl>(); auto page_node2 = CreateNode<performance_manager::PageNodeImpl>(); @@ -421,7 +469,7 @@ testing::Mock::VerifyAndClearExpectations(discarder()); } -TEST_F(UrgentPageDiscardingPolicyTest, +TEST_P(ParameterizedUrgentPageDiscardingPolicyTest, UrgentlyDiscardAPageTwoCandidatesNoRSSData) { auto process_node2 = CreateNode<performance_manager::ProcessNodeImpl>(); auto page_node2 = CreateNode<performance_manager::PageNodeImpl>(); @@ -447,7 +495,8 @@ testing::Mock::VerifyAndClearExpectations(discarder()); } -TEST_F(UrgentPageDiscardingPolicyTest, NoDiscardOnModeratePressure) { +TEST_P(ParameterizedUrgentPageDiscardingPolicyTest, + NoDiscardOnModeratePressure) { // No tab should be discarded on moderate pressure. mem_pressure_monitor()->SetAndNotifyMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel:: @@ -456,5 +505,12 @@ testing::Mock::VerifyAndClearExpectations(discarder()); } +INSTANTIATE_TEST_CASE_P( + UrgentPageDiscardingPolicyWithParamTest, + ParameterizedUrgentPageDiscardingPolicyTest, + ::testing::Values( + features::UrgentDiscardingParams::DiscardStrategy::LRU, + features::UrgentDiscardingParams::DiscardStrategy::BIGGEST_RSS)); + } // namespace policies } // namespace performance_manager
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_service.cc b/chrome/browser/prerender/isolated/isolated_prerender_service.cc index 9c9fc12..be42ee8 100644 --- a/chrome/browser/prerender/isolated/isolated_prerender_service.cc +++ b/chrome/browser/prerender/isolated/isolated_prerender_service.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/prerender/isolated/isolated_prerender_params.h" #include "chrome/browser/prerender/isolated/isolated_prerender_proxy_configurator.h" #include "chrome/browser/prerender/isolated/isolated_prerender_service_workers_observer.h" +#include "chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.h" #include "chrome/browser/prerender/isolated/prefetched_mainframe_response_container.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_task_traits.h" @@ -36,40 +37,32 @@ drp_settings->RemoveDataReductionProxySettingsObserver(this); } -void IsolatedPrerenderService::OnAboutToNoStatePrefetch( +IsolatedPrerenderSubresourceManager* +IsolatedPrerenderService::OnAboutToNoStatePrefetch( const GURL& url, std::unique_ptr<PrefetchedMainframeResponseContainer> response) { - no_state_prefetch_responses_.emplace(url, std::move(response)); - - // Schedule a cleanup in just a short time so that any edge case that causes a - // response not to be used (like the user navigating away inside of a narrow - // window between the response being copied here and taken) doesn't cause a - // memory leak. - content::GetUIThreadTaskRunner({})->PostDelayedTask( - FROM_HERE, - base::BindOnce(&IsolatedPrerenderService::CleanupNoStatePrefetchResponse, - weak_factory_.GetWeakPtr(), url), - // 30s is ample time since the mainframe can always be anonymously - // re-fetched if the NSP fails to start the renderer in this time. - base::TimeDelta::FromSeconds(30)); + std::unique_ptr<IsolatedPrerenderSubresourceManager> manager = + std::make_unique<IsolatedPrerenderSubresourceManager>( + url, std::move(response)); + IsolatedPrerenderSubresourceManager* manager_ptr = manager.get(); + subresource_managers_.emplace(url, std::move(manager)); + return manager_ptr; } -std::unique_ptr<PrefetchedMainframeResponseContainer> -IsolatedPrerenderService::TakeResponseForNoStatePrefetch(const GURL& url) { - auto iter = no_state_prefetch_responses_.find(url); - if (iter == no_state_prefetch_responses_.end()) { +IsolatedPrerenderSubresourceManager* +IsolatedPrerenderService::GetSubresourceManagerForURL(const GURL& url) const { + auto iter = subresource_managers_.find(url); + if (iter == subresource_managers_.end()) return nullptr; - } - - std::unique_ptr<PrefetchedMainframeResponseContainer> resp = - std::move(iter->second); - no_state_prefetch_responses_.erase(iter); - - return resp; + return iter->second.get(); } -void IsolatedPrerenderService::CleanupNoStatePrefetchResponse(const GURL& url) { - TakeResponseForNoStatePrefetch(url); +void IsolatedPrerenderService::DestroySubresourceManagerForURL( + const GURL& url) { + auto iter = subresource_managers_.find(url); + if (iter != subresource_managers_.end()) { + subresource_managers_.erase(iter); + } } void IsolatedPrerenderService::OnProxyRequestHeadersChanged(
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_service.h b/chrome/browser/prerender/isolated/isolated_prerender_service.h index 87026ee..c4c8637 100644 --- a/chrome/browser/prerender/isolated/isolated_prerender_service.h +++ b/chrome/browser/prerender/isolated/isolated_prerender_service.h
@@ -17,6 +17,7 @@ class Profile; class IsolatedPrerenderProxyConfigurator; class IsolatedPrerenderServiceWorkersObserver; +class IsolatedPrerenderSubresourceManager; class PrefetchedMainframeResponseContainer; // This service owns browser-level objects used in Isolated Prerenders. @@ -35,12 +36,19 @@ return service_workers_observer_.get(); } - void OnAboutToNoStatePrefetch( + // Creates an |IsolatedPrerenderSubresourceManager| for the given |url|. + IsolatedPrerenderSubresourceManager* OnAboutToNoStatePrefetch( const GURL& url, std::unique_ptr<PrefetchedMainframeResponseContainer> response); - std::unique_ptr<PrefetchedMainframeResponseContainer> - TakeResponseForNoStatePrefetch(const GURL& url); + // Returns a pointer to an |IsolatedPrerenderSubresourceManager| for the given + // URL, if one exists and hasn't been destroyed. Do not hold on to the + // returned pointer since it may be deleted without notice. + IsolatedPrerenderSubresourceManager* GetSubresourceManagerForURL( + const GURL& url) const; + + // Destroys the subresource manager for the given url if one exists. + void DestroySubresourceManagerForURL(const GURL& url); IsolatedPrerenderService(const IsolatedPrerenderService&) = delete; IsolatedPrerenderService& operator=(const IsolatedPrerenderService&) = delete; @@ -70,11 +78,10 @@ std::unique_ptr<IsolatedPrerenderServiceWorkersObserver> service_workers_observer_; - // The cached mainframe responses that will be used in an upcoming - // NoStatePrefetch. Kept at the browser level because the NSP happens in a - // different WebContents than the one that initiated it. - std::map<GURL, std::unique_ptr<PrefetchedMainframeResponseContainer>> - no_state_prefetch_responses_; + // Map of prerender URL to its manager. Kept at the browser level since NSPs + // are done in a separate WebContents from the one they are created in. + std::map<GURL, std::unique_ptr<IsolatedPrerenderSubresourceManager>> + subresource_managers_; base::WeakPtrFactory<IsolatedPrerenderService> weak_factory_{this}; };
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.cc b/chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.cc new file mode 100644 index 0000000..0552a95 --- /dev/null +++ b/chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.cc
@@ -0,0 +1,52 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.h" + +#include "chrome/browser/prerender/isolated/prefetched_mainframe_response_container.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/render_frame_host.h" + +IsolatedPrerenderSubresourceManager::IsolatedPrerenderSubresourceManager( + const GURL& url, + std::unique_ptr<PrefetchedMainframeResponseContainer> mainframe_response) + : url_(url), mainframe_response_(std::move(mainframe_response)) {} + +IsolatedPrerenderSubresourceManager::~IsolatedPrerenderSubresourceManager() { + if (nsp_handle_) { + nsp_handle_->OnCancel(); + nsp_handle_->SetObserver(nullptr); + } +} + +void IsolatedPrerenderSubresourceManager::ManageNoStatePrefetch( + std::unique_ptr<prerender::PrerenderHandle> handle, + base::OnceClosure on_nsp_done_callback) { + on_nsp_done_callback_ = std::move(on_nsp_done_callback); + nsp_handle_ = std::move(handle); + nsp_handle_->SetObserver(this); +} + +std::unique_ptr<PrefetchedMainframeResponseContainer> +IsolatedPrerenderSubresourceManager::TakeMainframeResponse() { + return std::move(mainframe_response_); +} + +void IsolatedPrerenderSubresourceManager::SetIsolatedURLLoaderFactory( + scoped_refptr<network::SharedURLLoaderFactory> isolated_loader_factory) { + isolated_loader_factory_ = isolated_loader_factory; +} + +void IsolatedPrerenderSubresourceManager::OnPrerenderStop( + prerender::PrerenderHandle* handle) { + DCHECK_EQ(nsp_handle_.get(), handle); + + if (on_nsp_done_callback_) { + std::move(on_nsp_done_callback_).Run(); + } + + // The handle must be canceled before it can be destroyed. + nsp_handle_->OnCancel(); + nsp_handle_.reset(); +}
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.h b/chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.h new file mode 100644 index 0000000..0ea7ad91 --- /dev/null +++ b/chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.h
@@ -0,0 +1,82 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PRERENDER_ISOLATED_ISOLATED_PRERENDER_SUBRESOURCE_MANAGER_H_ +#define CHROME_BROWSER_PRERENDER_ISOLATED_ISOLATED_PRERENDER_SUBRESOURCE_MANAGER_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/memory/scoped_refptr.h" +#include "base/optional.h" +#include "chrome/browser/prerender/prerender_handle.h" +#include "content/public/browser/content_browser_client.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/mojom/network_context.mojom.h" +#include "url/gurl.h" +#include "url/origin.h" + +namespace prerender { +class PrerenderHandle; +} + +class PrefetchedMainframeResponseContainer; + +// This class manages the isolated prerender of a page and its subresources. +class IsolatedPrerenderSubresourceManager + : public prerender::PrerenderHandle::Observer { + public: + explicit IsolatedPrerenderSubresourceManager( + const GURL& url, + std::unique_ptr<PrefetchedMainframeResponseContainer> mainframe_response); + ~IsolatedPrerenderSubresourceManager() override; + + // Passes ownership of |handle| to |this|, calling |on_nsp_done_callback| when + // the NSP is done. + void ManageNoStatePrefetch(std::unique_ptr<prerender::PrerenderHandle> handle, + base::OnceClosure on_nsp_done_callback); + + bool has_nsp_handle() const { return !!nsp_handle_; } + + // Takes ownership of |mainframe_response_|. + std::unique_ptr<PrefetchedMainframeResponseContainer> TakeMainframeResponse(); + + // Gives |this| a reference to the isolated URL Loader factory to use for + // Isolated Prerenders. + void SetIsolatedURLLoaderFactory( + scoped_refptr<network::SharedURLLoaderFactory> isolated_loader_factory); + + // prerender::PrerenderHandle::Observer: + void OnPrerenderStart(prerender::PrerenderHandle* handle) override {} + void OnPrerenderStopLoading(prerender::PrerenderHandle* handle) override {} + void OnPrerenderDomContentLoaded( + prerender::PrerenderHandle* handle) override {} + void OnPrerenderStop(prerender::PrerenderHandle* handle) override; + void OnPrerenderNetworkBytesChanged( + prerender::PrerenderHandle* handle) override {} + + IsolatedPrerenderSubresourceManager( + const IsolatedPrerenderSubresourceManager&) = delete; + IsolatedPrerenderSubresourceManager& operator=( + const IsolatedPrerenderSubresourceManager&) = delete; + + private: + // The page that is being prerendered. + const GURL url_; + + // The mainframe response headers and body. + std::unique_ptr<PrefetchedMainframeResponseContainer> mainframe_response_; + + // State for managing the NoStatePrerender when it is running. If + // |nsp_handle_| is set, then |on_nsp_done_callback_| is also set and vise + // versa. + std::unique_ptr<prerender::PrerenderHandle> nsp_handle_; + base::OnceClosure on_nsp_done_callback_; + + // The isolated URL Loader Factory (with proxy) to use during NSP. + scoped_refptr<network::SharedURLLoaderFactory> isolated_loader_factory_; +}; + +#endif // CHROME_BROWSER_PRERENDER_ISOLATED_ISOLATED_PRERENDER_SUBRESOURCE_MANAGER_H_
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc b/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc index 9cfd8e9..d733f08 100644 --- a/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc +++ b/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/prerender/isolated/isolated_prerender_service.h" #include "chrome/browser/prerender/isolated/isolated_prerender_service_factory.h" #include "chrome/browser/prerender/isolated/isolated_prerender_service_workers_observer.h" +#include "chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/profiles/profile.h" @@ -48,6 +49,7 @@ #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" +#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_service.mojom.h" @@ -106,13 +108,29 @@ IsolatedPrerenderTabHelper::CurrentPageLoad::CurrentPageLoad( content::NavigationHandle* handle) - : navigation_start_(handle ? handle->NavigationStart() : base::TimeTicks()), + : profile_(handle ? Profile::FromBrowserContext( + handle->GetWebContents()->GetBrowserContext()) + : nullptr), + navigation_start_(handle ? handle->NavigationStart() : base::TimeTicks()), srp_metrics_( base::MakeRefCounted<IsolatedPrerenderTabHelper::PrefetchMetrics>()) { } + IsolatedPrerenderTabHelper::CurrentPageLoad::~CurrentPageLoad() { - if (no_state_prefetch_handle_) { - no_state_prefetch_handle_->OnNavigateAway(); + if (!profile_) + return; + + IsolatedPrerenderService* service = + IsolatedPrerenderServiceFactory::GetForProfile(profile_); + if (!service) { + return; + } + + for (const GURL& url : no_state_prefetched_urls_) { + service->DestroySubresourceManagerForURL(url); + } + for (const GURL& url : urls_to_no_state_prefetch_) { + service->DestroySubresourceManagerForURL(url); } } @@ -526,11 +544,6 @@ void IsolatedPrerenderTabHelper::DoNoStatePrefetch() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Don't start another NSP until the previous one finishes. - if (page_->no_state_prefetch_handle_) { - return; - } - if (page_->urls_to_no_state_prefetch_.empty()) { return; } @@ -553,30 +566,42 @@ return; } - GURL url = page_->urls_to_no_state_prefetch_[0]; - - // Forward a copy of the mainframe response to the browser-level service. This - // way the IsolatedPrerenderURLLoaderInterceptor in the PrerenderContents can - // use the cached response without having to geta reference to |this|. IsolatedPrerenderService* service = IsolatedPrerenderServiceFactory::GetForProfile(profile_); if (!service) { return; } - service->OnAboutToNoStatePrefetch(url, CopyPrefetchResponseForNSP(url)); + GURL url = page_->urls_to_no_state_prefetch_[0]; + + // Don't start another NSP until the previous one finishes. + { + IsolatedPrerenderSubresourceManager* manager = + service->GetSubresourceManagerForURL(url); + if (manager && manager->has_nsp_handle()) { + return; + } + } + + // The manager must be created here so that the mainframe response can be + // given to the URLLoaderInterceptor in this call stack, but may be destroyed + // before the end of the method if the handle is not created. + IsolatedPrerenderSubresourceManager* manager = + service->OnAboutToNoStatePrefetch(url, CopyPrefetchResponseForNSP(url)); + manager->SetIsolatedURLLoaderFactory(page_->isolated_url_loader_factory_); content::SessionStorageNamespace* session_storage_namespace = web_contents()->GetController().GetDefaultSessionStorageNamespace(); gfx::Size size = web_contents()->GetContainerBounds().size(); - page_->no_state_prefetch_handle_ = + std::unique_ptr<prerender::PrerenderHandle> handle = prerender_manager->AddPrerenderFromNavigationPredictor( url, session_storage_namespace, size); - if (!page_->no_state_prefetch_handle_) { + if (!handle) { // Clean up the prefetch response in |service| since it wasn't used. - service->TakeResponseForNoStatePrefetch(url); + service->DestroySubresourceManagerForURL(url); + // Don't use |manager| again! // Try the next URL. page_->urls_to_no_state_prefetch_.erase( @@ -585,13 +610,17 @@ return; } - page_->no_state_prefetch_handle_->SetObserver(this); + manager->ManageNoStatePrefetch( + std::move(handle), + base::BindOnce(&IsolatedPrerenderTabHelper::OnPrerenderDone, + weak_factory_.GetWeakPtr(), url)); + page_->number_of_no_state_prefetch_attempts_++; } -void IsolatedPrerenderTabHelper::OnPrerenderStop( - prerender::PrerenderHandle* handle) { +void IsolatedPrerenderTabHelper::OnPrerenderDone(const GURL& url) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!page_->urls_to_no_state_prefetch_.empty()); + DCHECK_EQ(url, page_->urls_to_no_state_prefetch_[0]); page_->no_state_prefetched_urls_.push_back( page_->urls_to_no_state_prefetch_[0]); @@ -600,9 +629,6 @@ observer.OnNoStatePrefetchFinished(); } - page_->no_state_prefetch_handle_.reset(); - // |handle| is now invalid! - page_->urls_to_no_state_prefetch_.erase( page_->urls_to_no_state_prefetch_.begin()); @@ -816,9 +842,15 @@ factory_params->is_trusted = true; factory_params->is_corb_enabled = false; + mojo::PendingRemote<network::mojom::URLLoaderFactory> isolated_factory_remote; + page_->isolated_network_context_->CreateURLLoaderFactory( - page_->isolated_url_loader_factory_.BindNewPipeAndPassReceiver(), + isolated_factory_remote.InitWithNewPipeAndPassReceiver(), std::move(factory_params)); + + page_->isolated_url_loader_factory_ = network::SharedURLLoaderFactory::Create( + std::make_unique<network::WrapperPendingSharedURLLoaderFactory>( + std::move(isolated_factory_remote))); } WEB_CONTENTS_USER_DATA_KEY_IMPL(IsolatedPrerenderTabHelper)
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.h b/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.h index ff548aa..1f7584f 100644 --- a/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.h +++ b/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.h
@@ -18,7 +18,6 @@ #include "base/time/time.h" #include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h" #include "chrome/browser/prerender/isolated/prefetched_mainframe_response_container.h" -#include "chrome/browser/prerender/prerender_handle.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "mojo/public/cpp/bindings/remote.h" @@ -43,8 +42,7 @@ class IsolatedPrerenderTabHelper : public content::WebContentsObserver, public content::WebContentsUserData<IsolatedPrerenderTabHelper>, - public NavigationPredictorKeyedService::Observer, - public prerender::PrerenderHandle::Observer { + public NavigationPredictorKeyedService::Observer { public: ~IsolatedPrerenderTabHelper() override; @@ -214,14 +212,8 @@ content::NavigationHandle* navigation_handle) override; void OnVisibilityChanged(content::Visibility visibility) override; - // prerender::PrerenderHandle::Observer: - void OnPrerenderStart(prerender::PrerenderHandle* handle) override {} - void OnPrerenderStopLoading(prerender::PrerenderHandle* handle) override {} - void OnPrerenderDomContentLoaded( - prerender::PrerenderHandle* handle) override {} - void OnPrerenderStop(prerender::PrerenderHandle* handle) override; - void OnPrerenderNetworkBytesChanged( - prerender::PrerenderHandle* handle) override {} + // Notifies |this| that the NSP for |url| is done. + void OnPrerenderDone(const GURL& url); // Takes ownership of a prefetched response by URL, if one if available. std::unique_ptr<PrefetchedMainframeResponseContainer> TakePrefetchResponse( @@ -252,6 +244,8 @@ explicit CurrentPageLoad(content::NavigationHandle* handle); ~CurrentPageLoad(); + Profile* profile_; + // The start time of the current navigation. const base::TimeTicks navigation_start_; @@ -284,11 +278,6 @@ std::map<GURL, std::unique_ptr<PrefetchedMainframeResponseContainer>> prefetched_responses_; - // The handle for any currently active no state prefetch. Its url is always - // the first element in |urls_to_no_state_prefetch_|. nullptr when there is - // no pending no state prefetch. - std::unique_ptr<prerender::PrerenderHandle> no_state_prefetch_handle_; - // The number of no state prefetch requests that have been made. size_t number_of_no_state_prefetch_attempts_ = 0; @@ -304,7 +293,7 @@ // The network context and url loader factory that will be used for // prefetches. A separate network context is used so that the prefetch proxy // can be used via a custom proxy configuration. - mojo::Remote<network::mojom::URLLoaderFactory> isolated_url_loader_factory_; + scoped_refptr<network::SharedURLLoaderFactory> isolated_url_loader_factory_; mojo::Remote<network::mojom::NetworkContext> isolated_network_context_; };
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_url_loader_interceptor.cc b/chrome/browser/prerender/isolated/isolated_prerender_url_loader_interceptor.cc index 41cd165..980e937 100644 --- a/chrome/browser/prerender/isolated/isolated_prerender_url_loader_interceptor.cc +++ b/chrome/browser/prerender/isolated/isolated_prerender_url_loader_interceptor.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/prerender/isolated/isolated_prerender_params.h" #include "chrome/browser/prerender/isolated/isolated_prerender_service.h" #include "chrome/browser/prerender/isolated/isolated_prerender_service_factory.h" +#include "chrome/browser/prerender/isolated/isolated_prerender_subresource_manager.h" #include "chrome/browser/prerender/isolated/isolated_prerender_url_loader.h" #include "chrome/browser/prerender/isolated/prefetched_mainframe_response_container.h" #include "chrome/browser/prerender/prerender_manager.h" @@ -77,13 +78,18 @@ if (!service) return false; - std::unique_ptr<PrefetchedMainframeResponseContainer> prefetch = - service->TakeResponseForNoStatePrefetch(url_); - if (!prefetch) + IsolatedPrerenderSubresourceManager* manager = + service->GetSubresourceManagerForURL(url_); + if (!manager) + return false; + + std::unique_ptr<PrefetchedMainframeResponseContainer> mainframe_response = + manager->TakeMainframeResponse(); + if (!mainframe_response) return false; InterceptPrefetchedNavigation(tentative_resource_request, - std::move(prefetch)); + std::move(mainframe_response)); return true; }
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc index 1b95e6f..1854940 100644 --- a/chrome/browser/prerender/prerender_contents.cc +++ b/chrome/browser/prerender/prerender_contents.cc
@@ -27,10 +27,10 @@ #include "chrome/browser/ui/tab_helpers.h" #include "chrome/browser/ui/web_contents_sizer.h" #include "chrome/common/prerender_messages.h" -#include "chrome/common/prerender_types.h" #include "chrome/common/prerender_util.h" #include "components/history/core/browser/history_types.h" #include "components/prerender/prerender_final_status.h" +#include "components/prerender/prerender_types.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h index d1bb49a..7aeb5d6 100644 --- a/chrome/browser/prerender/prerender_contents.h +++ b/chrome/browser/prerender/prerender_contents.h
@@ -19,9 +19,9 @@ #include "base/time/time.h" #include "base/values.h" #include "chrome/common/prerender_canceler.mojom.h" -#include "chrome/common/prerender_types.h" #include "components/prerender/prerender_final_status.h" #include "components/prerender/prerender_origin.h" +#include "components/prerender/prerender_types.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/prerender/prerender_link_manager.cc b/chrome/browser/prerender/prerender_link_manager.cc index 94c051f..bda27ad9 100644 --- a/chrome/browser/prerender/prerender_link_manager.cc +++ b/chrome/browser/prerender/prerender_link_manager.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" -#include "chrome/common/prerender_types.h" +#include "components/prerender/prerender_types.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/session_storage_namespace.h"
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index 95890472..87486be7 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc
@@ -48,9 +48,9 @@ #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h" #include "chrome/common/chrome_features.h" -#include "chrome/common/prerender_types.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/prerender/prerender_final_status.h" +#include "components/prerender/prerender_types.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/render_frame_host.h"
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc index c196e08..433b3a0 100644 --- a/chrome/browser/prerender/prerender_unittest.cc +++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -36,13 +36,13 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" -#include "chrome/common/prerender_types.h" #include "chrome/common/prerender_util.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/content_settings/core/common/pref_names.h" #include "components/prefs/pref_service.h" #include "components/prerender/prerender_origin.h" +#include "components/prerender/prerender_types.h" #include "content/public/browser/render_view_host.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/renderer_host/chrome_navigation_ui_data.h b/chrome/browser/renderer_host/chrome_navigation_ui_data.h index f7c2f9f..3a21d237 100644 --- a/chrome/browser/renderer_host/chrome_navigation_ui_data.h +++ b/chrome/browser/renderer_host/chrome_navigation_ui_data.h
@@ -8,9 +8,9 @@ #include <memory> #include "base/macros.h" -#include "chrome/common/prerender_types.h" #include "components/offline_pages/buildflags/buildflags.h" #include "components/offline_pages/core/request_header/offline_page_navigation_ui_data.h" +#include "components/prerender/prerender_types.h" #include "content/public/browser/navigation_ui_data.h" #include "extensions/browser/extension_navigation_ui_data.h" #include "extensions/buildflags/buildflags.h"
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js index 0d5f0a6..8f23163 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -202,7 +202,7 @@ case 'reportIssue': let url = 'https://code.google.com/p/chromium/issues/entry?' + 'labels=Type-Bug,Pri-2,OS-Chrome&' + - 'components=UI>accessibility>ChromeVox&' + + 'components=OS>Accessibility>ChromeVox&' + 'description='; const description = {};
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js index 26918f68..64f03c9 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
@@ -26,7 +26,7 @@ this.wordHighlight_ = true; /** @const {string} */ - this.color_ = '#f73a98'; + this.color_ = '#da36e8'; /** @private {string} */ this.highlightColor_ = '#5e9bff';
diff --git a/chrome/browser/resources/chromeos/edu_login/edu_login_parent_info.html b/chrome/browser/resources/chromeos/edu_login/edu_login_parent_info.html index 4d82aa3..86d4683 100644 --- a/chrome/browser/resources/chromeos/edu_login/edu_login_parent_info.html +++ b/chrome/browser/resources/chromeos/edu_login/edu_login_parent_info.html
@@ -67,6 +67,8 @@ </div> </span> <span slot="buttons"> + <edu-login-button button-type="back"> + </edu-login-button> <edu-login-button button-type="next"> </edu-login-button> </span>
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_icons.html b/chrome/browser/resources/chromeos/login/components/oobe_icons.html index 4d256fc..c91d800 100644 --- a/chrome/browser/resources/chromeos/login/components/oobe_icons.html +++ b/chrome/browser/resources/chromeos/login/components/oobe_icons.html
@@ -73,6 +73,10 @@ <path fill="#5BB974" fill-rule="nonzero" d="M 16,2.6667 C 8.6400184,2.6667 2.6667,8.640018 2.6667,16 2.6667,23.359982 8.6400184,29.3333 16,29.3333 23.359982,29.3333 29.3333,23.359982 29.3333,16 29.3333,8.640018 23.359982,2.6667 16,2.6667 Z m 0,23.99994 C 10.120015,26.66664 5.33336,21.879985 5.33336,16 5.33336,10.120015 10.120015,5.33336 16,5.33336 c 5.879985,0 10.66664,4.786655 10.66664,10.66664 0,5.879985 -4.786655,10.66664 -10.66664,10.66664 z M 13.33334,18.933326 9.866682,15.466668 8.00002,17.33333 13.33334,22.66665 23.99998,12.00001 22.133318,10.133348 Z"></path> <path d="M 0,8 H 24 V 32 H 0 Z"></path> </g> + <g id="avatar" fill="none" fill-rule="evenodd"> + <path fill="#fff" d="M0 0h32v32H0z"></path> + <path fill-rule="evenodd" clip-rule="evenodd" d="M16 2.667C8.64 2.667 2.667 8.64 2.667 16S8.64 29.333 16 29.333 29.333 23.36 29.333 16 23.36 2.667 16 2.667zm8.48 19.773c-1.907-2.32-6.533-3.107-8.48-3.107s-6.573.787-8.48 3.107A10.6 10.6 0 015.333 16C5.333 10.12 10.12 5.333 16 5.333S26.667 10.12 26.667 16a10.6 10.6 0 01-2.187 6.44zM16 8a4.655 4.655 0 00-4.667 4.667A4.655 4.655 0 0016 17.333a4.655 4.655 0 004.667-4.666A4.655 4.655 0 0016 8z" fill="#1A73E8"></path> + </g> </defs> </svg> </iron-iconset-svg> @@ -145,6 +149,10 @@ <path fill="#5BB974" fill-rule="nonzero" d="M 32,5.3334 C 17.280037,5.3334 5.3334,17.280036 5.3334,32 5.3334,46.719964 17.280037,58.6666 32,58.6666 46.719964,58.6666 58.6666,46.719964 58.6666,32 58.6666,17.280036 46.719964,5.3334 32,5.3334 Z m 0,47.99988 C 20.24003,53.33328 10.66672,43.75997 10.66672,32 10.66672,20.24003 20.24003,10.66672 32,10.66672 43.75997,10.66672 53.33328,20.24003 53.33328,32 53.33328,43.75997 43.75997,53.33328 32,53.33328 Z M 26.66668,37.866652 19.733364,30.933336 16.00004,34.66666 26.66668,45.3333 47.99996,24.00002 44.266636,20.266696 Z"></path> <path d="m -14.66665,30.66665 h 48 v 48 h -48 z"></path> </g> + <g id="avatar" fill="none" fill-rule="evenodd"> + <path fill="#fff" d="M0 0h64v64H0z"></path> + <path fill-rule="evenodd" clip-rule="evenodd" d="M32 5.333C17.28 5.333 5.333 17.28 5.333 32 5.333 46.72 17.28 58.667 32 58.667c14.72 0 26.667-11.947 26.667-26.667C58.667 17.28 46.72 5.333 32 5.333zM48.96 44.88c-3.813-4.64-13.067-6.213-16.96-6.213-3.893 0-13.147 1.573-16.96 6.213-2.72-3.573-4.373-8.027-4.373-12.88 0-11.76 9.573-21.333 21.333-21.333 11.76 0 21.333 9.573 21.333 21.333 0 4.853-1.653 9.307-4.373 12.88zM32 16a9.31 9.31 0 00-9.333 9.333A9.31 9.31 0 0032 34.667a9.31 9.31 0 009.333-9.334A9.31 9.31 0 0032 16z" fill="#1A73E8"></path> + </g> </defs> </svg> </iron-iconset-svg>
diff --git a/chrome/browser/resources/chromeos/login/screen_sync_consent.js b/chrome/browser/resources/chromeos/login/screen_sync_consent.js index 9106dfb..6b16e4d7 100644 --- a/chrome/browser/resources/chromeos/login/screen_sync_consent.js +++ b/chrome/browser/resources/chromeos/login/screen_sync_consent.js
@@ -28,6 +28,7 @@ */ onBeforeShow(data) { $('sync-consent-impl').setIsChildAccount(data['isChildAccount']); + $('sync-consent-impl').setUserEmail(data['userEmail']); cr.ui.login.invokePolymerMethod($('sync-loading'), 'onBeforeShow'); cr.ui.login.invokePolymerMethod($('sync-consent-impl'), 'onBeforeShow'); },
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.css b/chrome/browser/resources/chromeos/login/sync_consent.css index 8f0c8544..385c52c 100644 --- a/chrome/browser/resources/chromeos/login/sync_consent.css +++ b/chrome/browser/resources/chromeos/login/sync_consent.css
@@ -57,13 +57,3 @@ padding-inline-end: 16px; } -#splitSettingsSyncConsentDialog cr-checkbox { - align-self: start; /* Prevent label from spanning the whole width. */ - margin-top: 16px; - --cr-checkbox-label-padding-start: 12px; -} - -#splitSettingsSyncConsentDialog cr-toggle { - margin-top: 8px; -} -
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.html b/chrome/browser/resources/chromeos/login/sync_consent.html index 2a2c4db..89e1e9a 100644 --- a/chrome/browser/resources/chromeos/login/sync_consent.html +++ b/chrome/browser/resources/chromeos/login/sync_consent.html
@@ -3,7 +3,6 @@ found in the LICENSE file. --> <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <if expr="_google_chrome"> <link rel="import" href="chrome://oobe/sync-consent-icons.html"> @@ -72,12 +71,17 @@ <!-- Dialog used with the SplitSettingsSync feature. --> <oobe-dialog id="splitSettingsSyncConsentDialog" role="dialog" has-buttons - aria-label$="[[i18nDynamic(locale, 'syncConsentScreenTitle')]]" hidden> + aria-label$="[[i18nDynamic(locale, 'syncConsentScreenTitle')]]" hidden> <hd-iron-icon slot="oobe-icon" icon1x="sync-consent-32:googleg" icon2x="sync-consent-64:googleg"> </hd-iron-icon> <h1 slot="title" consent-description> [[i18nDynamic(locale, 'syncConsentScreenTitle')]] </h1> + <!-- The string contains a substitution, so consent is recorded directly + by SyncConsentScreenHandler instead of using consent-description. --> + <div slot="subtitle"> + [[i18nDynamic(locale, 'syncConsentScreenSubtitle', userEmail_)]] + </div> <div slot="footer" class="layout vertical flex"> <!-- "Chrome OS settings sync" --> @@ -91,8 +95,6 @@ [[i18nDynamic(locale, 'syncConsentScreenOsSyncDescription')]] </div> </div> - <cr-toggle id="osSyncToggle" checked aria-labelledby="osSyncName"> - </cr-toggle> </div> <!-- "Chrome browser sync" --> @@ -107,9 +109,6 @@ [[i18nDynamic(locale, 'syncConsentScreenChromeSyncDescription')]] </div> </div> - <cr-toggle id="browserSyncToggle" checked - aria-labelledby="browserSyncName"> - </cr-toggle> </div> <!-- Personalize Google services --> @@ -134,10 +133,15 @@ </div> </div> <div slot="bottom-buttons" class="layout horizontal end-justified"> - <oobe-text-button id="settingsAcceptAndContinueButton" on-tap="onSettingsAcceptAndContinue_" + <oobe-text-button id="declineButton" on-tap="onDeclineTap_"> + <div slot="text" consent-description consent-confirmation> + [[i18nDynamic(locale, 'syncConsentScreenDecline')]] + </div> + </oobe-text-button> + <oobe-text-button id="acceptButton" on-tap="onAcceptTap_" class="focus-on-show" inverse> <div slot="text" consent-description consent-confirmation> - [[i18nDynamic(locale, 'syncConsentAcceptAndContinue')]] + [[i18nDynamic(locale, 'syncConsentScreenAccept')]] </div> </oobe-text-button> </div>
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.js b/chrome/browser/resources/chromeos/login/sync_consent.js index 38e66d3..121d260 100644 --- a/chrome/browser/resources/chromeos/login/sync_consent.js +++ b/chrome/browser/resources/chromeos/login/sync_consent.js
@@ -16,16 +16,22 @@ /** * Flag that determines whether current account type is supervised or not. */ - isChildAccount_: { type: Boolean }, + isChildAccount_: Boolean, + /** @private */ splitSettingsSyncEnabled_: { type: Boolean, - value: function () { + value: function() { return loadTimeData.getBoolean('splitSettingsSyncEnabled'); }, readOnly: true, }, + /** + * The display email address of the current user. + * @private + */ + userEmail_: String, }, /** @@ -36,6 +42,13 @@ this.isChildAccount_ = is_child_account; }, + /** + * @param userEmail {string} The display email address of the current user. + */ + setUserEmail(userEmail) { + this.userEmail_ = userEmail; + }, + /** @override */ ready() { this.updateLocalizedContent(); @@ -118,18 +131,28 @@ }, /** - * Continue button handler for SplitSettingsSync. + * Accept button handler for SplitSettingsSync. * @param {!Event} event * @private */ - onSettingsAcceptAndContinue_(event) { + onAcceptTap_(event) { assert(loadTimeData.getBoolean('splitSettingsSyncEnabled')); assert(event.path); - const enableOsSync = !!this.$.osSyncToggle.checked; - const enableBrowserSync = !!this.$.browserSyncToggle.checked; chrome.send('login.SyncConsentScreen.acceptAndContinue', [ - this.getConsentDescription_(), this.getConsentConfirmation_(event.path), - enableOsSync, enableBrowserSync + this.getConsentDescription_(), this.getConsentConfirmation_(event.path) + ]); + }, + + /** + * Decline button handler for SplitSettingsSync. + * @param {!Event} event + * @private + */ + onDeclineTap_(event) { + assert(loadTimeData.getBoolean('splitSettingsSyncEnabled')); + assert(event.path); + chrome.send('login.SyncConsentScreen.declineAndContinue', [ + this.getConsentDescription_(), this.getConsentConfirmation_(event.path) ]); },
diff --git a/chrome/browser/resources/extensions/detail_view.js b/chrome/browser/resources/extensions/detail_view.js index eb33794..a45ebd87 100644 --- a/chrome/browser/resources/extensions/detail_view.js +++ b/chrome/browser/resources/extensions/detail_view.js
@@ -321,8 +321,6 @@ switch (type) { case 'POLICY': return 'cr20:domain'; - case 'SUPERVISED_USER_CUSTODIAN': - return 'cr:supervisor-account'; default: return ''; }
diff --git a/chrome/browser/resources/invalidations/about_invalidations.html b/chrome/browser/resources/invalidations/about_invalidations.html index d49aa98..e15459fd 100644 --- a/chrome/browser/resources/invalidations/about_invalidations.html +++ b/chrome/browser/resources/invalidations/about_invalidations.html
@@ -4,7 +4,6 @@ <meta charset="utf-8"> <title>Invalidations</title> <script src="chrome://resources/js/cr.js"></script> - <script src="chrome://resources/js/parse_html_subset.js"></script> <script src="chrome://resources/js/util.js"></script> <script src="chrome://invalidations/about_invalidations.js"></script> <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html index 56f50557..cf44da3 100644 --- a/chrome/browser/resources/net_internals/index.html +++ b/chrome/browser/resources/net_internals/index.html
@@ -30,6 +30,5 @@ <include src="chromeos_view.html"> </div> - <script src="chrome://resources/js/jstemplate_compiled.js"></script> </body> </html>
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html index 5b273b3..7dac652e 100644 --- a/chrome/browser/resources/new_tab_page/app.html +++ b/chrome/browser/resources/new_tab_page/app.html
@@ -312,8 +312,6 @@ <div id="oneGoogleBarOverlayBackdrop"></div> <svg> <defs> - <clipPath id="oneGoogleBarClipPath"> - <rect x="0" y="0" width="100vw" height="56"></rect> - </clipPath> + <clipPath id="oneGoogleBarClipPath"></clipPath> </defs> </svg>
diff --git a/chrome/browser/resources/new_tab_page/app.js b/chrome/browser/resources/new_tab_page/app.js index 96015fa..ce15678 100644 --- a/chrome/browser/resources/new_tab_page/app.js +++ b/chrome/browser/resources/new_tab_page/app.js
@@ -618,10 +618,9 @@ BrowserProxy.getInstance().handler.onOneGoogleBarRendered( BrowserProxy.getInstance().now()); } else if (data.messageType === 'overlaysUpdated') { - this.$.oneGoogleBarClipPath.querySelectorAll('rect:not(:first-child)') - .forEach(el => { - el.remove(); - }); + this.$.oneGoogleBarClipPath.querySelectorAll('rect').forEach(el => { + el.remove(); + }); const overlayRects = /** @type {!Array<!DOMRect>} */ (data.data); overlayRects.forEach(({x, y, width, height}) => { const rectElement =
diff --git a/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js b/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js index cd660e25..ffd1e58 100644 --- a/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js +++ b/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js
@@ -2,29 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -const oneGoogleBarHeightInPixels = 64; -let modalOverlays = false; -let darkThemeEnabled = false; -let shouldUndoDarkTheme = false; - -/** - * @param {boolean} enabled - * @return {!Promise} - */ -async function enableDarkTheme(enabled) { - if (!window.gbar) { - return; - } - darkThemeEnabled = enabled; - const ogb = await window.gbar.a.bf(); - ogb.pc.call(ogb, enabled ? 1 : 0); -} - /** * The following |messageType|'s are sent to the parent frame: * - loaded: sent on initial load. * - overlaysUpdated: sent when an overlay is updated. The overlay bounding - * rects are included in the |data|. + * rects are included in the |data|. * - activate/deactivate: When an overlay is open, 'activate' is sent to the * to ntp-app so it can layer the OneGoogleBar over the NTP content. When * no overlays are open, 'deactivate' is sent to ntp-app so the NTP @@ -42,114 +24,158 @@ 'chrome://new-tab-page'); } -const overlays = new Set(); +// Object that exposes: +// - |getEnabled()|: returns whether dark theme is enabled. +// - |setEnabled(value)|: updates whether dark theme is enabled using the +// OneGoogleBar API. +const darkTheme = (() => { + let enabled = false; -function sendOverlayUpdate() { - // Remove overlays detached from DOM or elements in a parent overlay. - Array.from(overlays).forEach(overlay => { - if (!overlay.parentElement) { - overlays.delete(overlay); + /** @return {boolean} */ + const getEnabled = () => enabled; + + /** + * @param {boolean} value + * @return {!Promise} + */ + const setEnabled = async value => { + if (!window.gbar) { return; } - let parent = overlay.parentElement; - while (parent) { - if (overlays.has(parent)) { + enabled = value; + const ogb = await window.gbar.a.bf(); + ogb.pc.call(ogb, enabled ? 1 : 0); + }; + + return {getEnabled, setEnabled}; +})(); + +// Object that exposes: +// - |track()|: sets up MutationObserver to track element visibility changes. +// - |update(potentialNewOverlays)|: determines visibility of tracked elements +// and sends an update to the top frame about element visibility. +const overlayUpdater = (() => { + const modalOverlays = document.documentElement.hasAttribute('modal-overlays'); + let shouldUndoDarkTheme = false; + + /** @type {!Set<!Element>} */ + const overlays = new Set(); + + /** @param {!Array<!Element>} potentialNewOverlays */ + const update = (potentialNewOverlays) => { + Array.from(potentialNewOverlays).forEach(overlay => { + if (overlay.getBoundingClientRect().width > 0) { + overlays.add(overlay); + } + }); + // Remove overlays detached from DOM. + Array.from(overlays).forEach(overlay => { + if (!overlay.parentElement) { overlays.delete(overlay); return; } - parent = parent.parentElement; - } - }); - // Check if an overlay and its parents are visible. - const overlayRects = - Array.from(overlays) - .filter(overlay => { - if (window.getComputedStyle(overlay).visibility === 'hidden') { - return false; - } - let current = overlay; - while (current) { - if (window.getComputedStyle(current).display === 'none') { + }); + const barHeight = document.body.querySelector('#gb').offsetHeight; + // Check if an overlay and its parents are visible. + const overlayRects = + Array.from(overlays) + .filter(overlay => { + if (window.getComputedStyle(overlay).visibility === 'hidden') { return false; } - current = current.parentElement; - } - return true; - }) - .map(el => el.getBoundingClientRect()); - if (!modalOverlays) { - postMessage('overlaysUpdated', overlayRects); - return; - } - const overlayShown = overlayRects.length > 0; - postMessage(overlayShown ? 'activate' : 'deactivate'); - // If the overlays are modal, a dark backdrop is displayed below the - // OneGoogleBar iframe. The dark theme for the OneGoogleBar is then enabled - // for better visibility. - if (overlayShown) { - if (!darkThemeEnabled) { - shouldUndoDarkTheme = true; - enableDarkTheme(true); + let current = overlay; + while (current) { + if (window.getComputedStyle(current).display === 'none') { + return false; + } + current = current.parentElement; + } + return true; + }) + .map(el => el.getBoundingClientRect()) + .filter(rect => !modalOverlays || rect.bottom > barHeight); + if (!modalOverlays) { + postMessage('overlaysUpdated', overlayRects); + return; } - } else if (shouldUndoDarkTheme) { - shouldUndoDarkTheme = false; - enableDarkTheme(false); - } -} + const overlayShown = overlayRects.length > 0; + postMessage(overlayShown ? 'activate' : 'deactivate'); + // If the overlays are modal, a dark backdrop is displayed below the + // OneGoogleBar iframe. The dark theme for the OneGoogleBar is then enabled + // for better visibility. + if (overlayShown) { + if (!darkTheme.getEnabled()) { + shouldUndoDarkTheme = true; + darkTheme.setEnabled(true); + } + } else if (shouldUndoDarkTheme) { + shouldUndoDarkTheme = false; + darkTheme.setEnabled(false); + } + }; -function trackOverlayState() { - const observer = new MutationObserver(mutations => { - // After loaded, there could exist overlays that are shown, but not mutated. - // Add all elements that could be an overlay. The children of the actual - // overlay element are removed before sending any overlay update message. - if (overlays.size === 0) { - Array.from(document.body.querySelectorAll('*')).forEach(el => { - if (el.offsetTop + el.offsetHeight > oneGoogleBarHeightInPixels) { - overlays.add(el); - } - }); - } - // Add any mutated element that is an overlay to |overlays|. - mutations.forEach(({target}) => { - if (target.id === 'gb' || target.tagName === 'BODY' || - overlays.has(target)) { - return; - } - // When overlays are modal, the tooltips should not be treated like an - // overlay. - if (modalOverlays && target.parentElement && - target.parentElement.tagName === 'BODY') { - return; - } - if (target.offsetTop + target.offsetHeight > oneGoogleBarHeightInPixels) { - overlays.add(target); - } - // Update links that are loaded dynamically to ensure target is "_blank" - // or "_top". - // TODO(crbug.com/1039913): remove after OneGoogleBar links are updated. - if (target.parentElement) { - target.parentElement.querySelectorAll('a').forEach(el => { - if (el.target !== '_blank' && el.target !== '_top') { - el.target = '_top'; - } + const track = () => { + const observer = new MutationObserver(mutations => { + const potentialNewOverlays = []; + // After loaded, there could exist overlays that are shown, but not + // mutated. Add all elements that could be an overlay. The children of the + // actual overlay element are removed before sending any overlay update + // message. + if (!modalOverlays && overlays.size === 0) { + Array.from(document.body.querySelectorAll('*')).forEach(el => { + potentialNewOverlays.push(el); }); } + // Add any mutated element that is an overlay to |overlays|. + mutations.forEach(({target}) => { + if (target.id === 'gb' || target.tagName === 'BODY' || + overlays.has(target)) { + return; + } + // When overlays are modal, the tooltips should not be treated like an + // overlay. + if (modalOverlays && target.parentElement && + target.parentElement.tagName === 'BODY') { + return; + } + potentialNewOverlays.push(target); + // Update links that are loaded dynamically to ensure target is "_blank" + // or "_top". + // TODO(crbug.com/1039913): remove after OneGoogleBar links are updated. + if (target.parentElement) { + target.parentElement.querySelectorAll('a').forEach(el => { + if (el.target !== '_blank' && el.target !== '_top') { + el.target = '_top'; + } + }); + } + }); + update(potentialNewOverlays); }); - sendOverlayUpdate(); - }); - observer.observe( - document, {attributes: true, childList: true, subtree: true}); -} + observer.observe(document, { + attributes: true, + childList: true, + subtree: true, + }); + if (!modalOverlays) { + update([document.body.querySelector('#gb')]); + } + }; + + return {track, update}; +})(); window.addEventListener('message', ({data}) => { if (data.type === 'enableDarkTheme') { - enableDarkTheme(data.enabled); + darkTheme.setEnabled(data.enabled); } }); // Need to send overlay updates on resize because overlay bounding rects are // absolutely positioned. -window.addEventListener('resize', sendOverlayUpdate); +window.addEventListener('resize', () => { + overlayUpdater.update([]); +}); // When the account overlay is shown, it does not close on blur. It does close // when clicking the body. @@ -167,5 +193,5 @@ }); modalOverlays = document.documentElement.hasAttribute('modal-overlays'); postMessage('loaded'); - trackOverlayState(); + overlayUpdater.track(); });
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html index 9cfa848..4b7f700 100644 --- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html +++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html
@@ -98,7 +98,12 @@ } </style> <cr-input id="dropdownInput" on-keydown="onKeyDown_" - value="[[value.displayName]]" readonly> + value="[[value.displayName]]" disabled="[[disabled]]"> + <div id="pre-input-overlay" slot="prefix"> + <div id="pre-input-box"> + <iron-icon icon="[[destinationIcon]]"></iron-icon> + </div> + </div> <div id="input-overlay" slot="suffix"> <div id="input-box"> <iron-icon id="dropdown-icon" icon="cr:arrow-drop-down"></iron-icon> @@ -115,6 +120,22 @@ [[item.displayName]] </button> </template> + <button class="list-item" on-click="onSelect_" tabindex="-1" + value="[[pdfDestinationKey]]" hidden$="[[pdfPrinterDisabled]]"> + $i18n{printToPDF} + </button> + <button class="list-item" on-click="onSelect_" tabindex="-1" + value="[[driveDestinationKey]]" hidden$="[[!driveDestinationKey]]"> + $i18n{printToGoogleDrive} + </button> + <button class="list-item" on-click="onSelect_" tabindex="-1" + value="noDestinations" hidden$="[[!noDestinations]]"> + $i18n{noDestinationsMessage} + </button> + <button class="list-item" on-click="onSelect_" tabindex="-1" + value="seeMore" aria-label$="[[i18n(seeMoreDestinationsLabel)]]"> + $i18n{seeMore} + </button> </div> </iron-dropdown> </div>
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js index e0a6706..0e3f430 100644 --- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js +++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js
@@ -28,6 +28,22 @@ type: Array, observer: 'enqueueDropdownRefit_', }, + + /** @type {boolean} */ + disabled: { + type: Boolean, + value: false, + }, + + driveDestinationKey: String, + + noDestinations: Boolean, + + pdfPrinterDisabled: Boolean, + + pdfDestinationKey: String, + + destinationIcon: String, }, listeners: { @@ -62,6 +78,10 @@ /** @private */ openDropdown_() { + if (this.disabled) { + return; + } + this.$$('iron-dropdown').open(); this.opened_ = true; },
diff --git a/chrome/browser/resources/print_preview/ui/destination_select_cros.html b/chrome/browser/resources/print_preview/ui/destination_select_cros.html index 7ff9ad7..9ef6b08 100644 --- a/chrome/browser/resources/print_preview/ui/destination_select_cros.html +++ b/chrome/browser/resources/print_preview/ui/destination_select_cros.html
@@ -34,7 +34,13 @@ </template> <template is="dom-if" if="[[printerStatusFlagEnabled_]]"> <print-preview-destination-dropdown-cros id="dropdown" - value="[[destination]]" item-list="[[recentDestinationList]]" + value="[[destination]]" hidden$="[[!loaded]]" + item-list="[[recentDestinationList]]" + pdf-destination-key="[[pdfDestinationKey_]]" + drive-destination-key="[[driveDestinationKey]]" + no-destinations="[[noDestinations]]" + pdf-printer-disabled="[[pdfPrinterDisabled]]" + destination-icon="[[destinationIcon_]]" disabled="[[disabled]]" on-dropdown-value-selected="onDropdownValueSelected_"> </print-preview-destination-dropdown-cros> </template>
diff --git a/chrome/browser/resources/print_preview/ui/destination_select_cros.js b/chrome/browser/resources/print_preview/ui/destination_select_cros.js index cd89056..b300c54 100644 --- a/chrome/browser/resources/print_preview/ui/destination_select_cros.js +++ b/chrome/browser/resources/print_preview/ui/destination_select_cros.js
@@ -75,7 +75,13 @@ backgroundImages_: { type: String, computed: - 'computeBackgroundImages_(selectedValue, destination, noDestinations, dark)', + 'computeBackgroundImages_(destinationIcon_, dark, noDestinations)', + }, + + /** @private {string} */ + destinationIcon_: { + type: String, + computed: 'computeDestinationIcon_(selectedValue, destination)', }, /** @private */ @@ -126,7 +132,7 @@ * @return {string} The iconset and icon for the current selection. * @private */ - getDestinationIcon_() { + computeDestinationIcon_() { if (!this.selectedValue) { return ''; } @@ -166,8 +172,7 @@ * @private */ computeBackgroundImages_() { - const icon = this.getDestinationIcon_(); - if (!icon) { + if (!this.destinationIcon_) { return ''; } @@ -175,7 +180,7 @@ if (this.noDestinations) { iconSetAndIcon = ['cr', 'error']; } - iconSetAndIcon = iconSetAndIcon || icon.split(':'); + iconSetAndIcon = iconSetAndIcon || this.destinationIcon_.split(':'); const iconset = /** @type {!IronIconsetSvgElement} */ ( this.meta_.byKey(iconSetAndIcon[0])); return getSelectDropdownBackground(iconset, iconSetAndIcon[1], this);
diff --git a/chrome/browser/resources/settings/autofill_page/BUILD.gn b/chrome/browser/resources/settings/autofill_page/BUILD.gn index 668104df..8a430e0 100644 --- a/chrome/browser/resources/settings/autofill_page/BUILD.gn +++ b/chrome/browser/resources/settings/autofill_page/BUILD.gn
@@ -16,6 +16,7 @@ ":blocking_request_manager", ":credit_card_edit_dialog", ":credit_card_list_entry", + ":merge_passwords_store_copies_behavior", ":multi_store_id_handler", ":multi_store_password_ui_entry", ":password_check", @@ -228,6 +229,7 @@ js_library("passwords_section") { deps = [ + ":merge_passwords_store_copies_behavior", ":multi_store_password_ui_entry", ":password_list_item", ":password_manager_proxy", @@ -241,7 +243,6 @@ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:i18n_behavior.m", - "//ui/webui/resources/js:list_property_update_behavior.m", "//ui/webui/resources/js:util.m", "//ui/webui/resources/js:web_ui_listener_behavior.m", "//ui/webui/resources/js/cr/ui:focus_without_ink.m", @@ -288,6 +289,14 @@ externs_list = [ "$externs_path/passwords_private.js" ] } +js_library("merge_passwords_store_copies_behavior") { + deps = [ + ":multi_store_password_ui_entry", + ":password_manager_proxy", + "//ui/webui/resources/js:list_property_update_behavior.m", + ] +} + js_library("remove_password_behavior") { deps = [ ":multi_store_password_ui_entry",
diff --git a/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js b/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js new file mode 100644 index 0000000..30080fed --- /dev/null +++ b/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js
@@ -0,0 +1,97 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview This behavior bundles the functionality for retrieving + * saved passwords from the password manager and deduplicating eventual copies + * existing stored both on the device and in the account. + */ + +import {assert} from 'chrome://resources/js/assert.m.js'; +import {ListPropertyUpdateBehavior} from 'chrome://resources/js/list_property_update_behavior.m.js'; + +import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js'; +import {PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js'; + +/** + * @polymerBehavior + */ +const MergePasswordsStoreCopiesBehaviorImpl = { + + properties: { + /** + * Saved passwords after deduplicating versions that are repeated in the + * account and on the device. + * @type {!Array<!MultiStorePasswordUiEntry>} + */ + savedPasswords: { + type: Array, + value: () => [], + }, + + /** + * @type {?function(!Array<PasswordManagerProxy.PasswordUiEntry>):void} + * @private + */ + setSavedPasswordsListener_: { + type: Object, + value: null, + }, + + }, + + /** @override */ + attached() { + this.setSavedPasswordsListener_ = passwordList => { + const mergedPasswordList = + this.mergePasswordsStoreDuplicates_(passwordList); + + // getCombinedId() is unique for each |entry|. If both copies are removed, + // updateList() will consider this a removal. If only one copy is removed, + // this will be treated as a removal plus an insertion. + const getCombinedId = + entry => [entry.deviceId, entry.accountId].join('_'); + this.updateList('savedPasswords', getCombinedId, mergedPasswordList); + }; + + PasswordManagerImpl.getInstance().getSavedPasswordList( + this.setSavedPasswordsListener_); + PasswordManagerImpl.getInstance().addSavedPasswordListChangedListener( + this.setSavedPasswordsListener_); + this.notifySplices('savedPasswords', []); + }, + + detached() { + PasswordManagerImpl.getInstance().removeSavedPasswordListChangedListener( + assert(this.setSavedPasswordsListener_)); + }, + + /** + * @param {!Array<!PasswordManagerProxy.PasswordUiEntry>} passwordList + * @return {!Array<!MultiStorePasswordUiEntry>} + * @private + */ + mergePasswordsStoreDuplicates_(passwordList) { + /** @type {!Array<!MultiStorePasswordUiEntry>} */ + const multiStoreEntries = []; + /** @type {!Map<number, !MultiStorePasswordUiEntry>} */ + const frontendIdToMergedEntry = new Map(); + for (const entry of passwordList) { + if (frontendIdToMergedEntry.has(entry.frontendId)) { + frontendIdToMergedEntry.get(entry.frontendId).merge(entry); + } else { + const multiStoreEntry = new MultiStorePasswordUiEntry(entry); + frontendIdToMergedEntry.set(entry.frontendId, multiStoreEntry); + multiStoreEntries.push(multiStoreEntry); + } + } + return multiStoreEntries; + }, +}; + +/** + * @polymerBehavior + */ +export const MergePasswordsStoreCopiesBehavior = + [ListPropertyUpdateBehavior, MergePasswordsStoreCopiesBehaviorImpl];
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.js b/chrome/browser/resources/settings/autofill_page/passwords_section.js index e43e20f..a6747c36 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.js
@@ -24,7 +24,6 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; -import {ListPropertyUpdateBehavior} from 'chrome://resources/js/list_property_update_behavior.m.js'; import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js'; @@ -39,6 +38,7 @@ import '../prefs/prefs.m.js'; import {PrefsBehavior} from '../prefs/prefs_behavior.m.js'; import {routes} from '../route.js'; +import {MergePasswordsStoreCopiesBehavior} from './merge_passwords_store_copies_behavior.js'; import {Router} from '../router.m.js'; import '../settings_shared_css.m.js'; import '../site_favicon.js'; @@ -75,7 +75,7 @@ behaviors: [ I18nBehavior, WebUIListenerBehavior, - ListPropertyUpdateBehavior, + MergePasswordsStoreCopiesBehavior, PasswordCheckBehavior, IronA11yKeysBehavior, GlobalScrollTargetBehavior, @@ -95,16 +95,6 @@ }, /** - * Saved passwords after deduplicating versions that are repeated in the - * account and on the device. - * @type {!Array<!MultiStorePasswordUiEntry>} - */ - savedPasswords: { - type: Array, - value: () => [], - }, - - /** * An array of sites to display. * @type {!Array<!PasswordManagerProxy.ExceptionEntry>} */ @@ -271,12 +261,6 @@ setIsOptedInForAccountStorageListener_: null, /** - * @type {?function(!Array<PasswordManagerProxy.PasswordUiEntry>):void} - * @private - */ - setSavedPasswordsListener_: null, - - /** * @type {?function(!Array<PasswordManagerProxy.ExceptionEntry>):void} * @private */ @@ -289,26 +273,12 @@ this.isOptedInForAccountStorage_ = optedIn; }; - const setSavedPasswordsListener = passwordList => { - const mergedPasswordList = - this.mergePasswordsStoreDuplicates_(passwordList); - - // getCombinedId() is unique for each |entry|. If both copies are removed, - // updateList() will consider this a removal. If only one copy is removed, - // this will be treated as a removal plus an insertion. - const getCombinedId = - entry => [entry.deviceId, entry.accountId].join('_'); - this.updateList('savedPasswords', getCombinedId, mergedPasswordList); - this.hasStoredPasswords_ = passwordList.length > 0; - }; - const setPasswordExceptionsListener = list => { this.passwordExceptions = list; }; this.setIsOptedInForAccountStorageListener_ = setIsOptedInForAccountStorageListener; - this.setSavedPasswordsListener_ = setSavedPasswordsListener; this.setPasswordExceptionsListener_ = setPasswordExceptionsListener; // Set the manager. These can be overridden by tests. @@ -330,19 +300,14 @@ // Request initial data. this.passwordManager_.isOptedInForAccountStorage().then( setIsOptedInForAccountStorageListener); - this.passwordManager_.getSavedPasswordList(setSavedPasswordsListener); this.passwordManager_.getExceptionList(setPasswordExceptionsListener); // Listen for changes. this.passwordManager_.addAccountStorageOptInStateListener( setIsOptedInForAccountStorageListener); - this.passwordManager_.addSavedPasswordListChangedListener( - setSavedPasswordsListener); this.passwordManager_.addExceptionListChangedListener( setPasswordExceptionsListener); - this.notifySplices('savedPasswords', []); - const syncBrowserProxy = SyncBrowserProxyImpl.getInstance(); const syncStatusChanged = syncStatus => this.syncStatus_ = syncStatus; @@ -367,8 +332,6 @@ /** @override */ detached() { - this.passwordManager_.removeSavedPasswordListChangedListener( - assert(this.setSavedPasswordsListener_)); this.passwordManager_.removeExceptionListChangedListener( assert(this.setPasswordExceptionsListener_)); this.passwordManager_.removeAccountStorageOptInStateListener( @@ -429,28 +392,6 @@ }, /** - * @param {!Array<!PasswordManagerProxy.PasswordUiEntry>} passwordList - * @return {!Array<!MultiStorePasswordUiEntry>} - * @private - */ - mergePasswordsStoreDuplicates_(passwordList) { - /** @type {!Array<!MultiStorePasswordUiEntry>} */ - const multiStoreEntries = []; - /** @type {!Map<number, !MultiStorePasswordUiEntry>} */ - const frontendIdToMergedEntry = new Map(); - for (const entry of passwordList) { - if (frontendIdToMergedEntry.has(entry.frontendId)) { - frontendIdToMergedEntry.get(entry.frontendId).merge(entry); - } else { - const multiStoreEntry = new MultiStorePasswordUiEntry(entry); - frontendIdToMergedEntry.set(entry.frontendId, multiStoreEntry); - multiStoreEntries.push(multiStoreEntry); - } - } - return multiStoreEntries; - }, - - /** * @return {boolean} * @private */
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_subpage.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_subpage.js index 11d3d67..2844258 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_subpage.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_subpage.js
@@ -439,7 +439,8 @@ enableToggleIsEnabled_(deviceState) { return !!deviceState && deviceState.deviceState != - chromeos.networkConfig.mojom.DeviceStateType.kProhibited; + chromeos.networkConfig.mojom.DeviceStateType.kProhibited && + !OncMojo.deviceStateIsIntermediate(deviceState.deviceState); }, /**
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.html b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.html index 6cf33ef..10e846c 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.html +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.html
@@ -52,7 +52,7 @@ [[getTitleText_(activeNetworkState)]] </div> <div id="networkState"> - [[getNetworkStateText_(activeNetworkState, deviceState)]] + [[getNetworkStateText_(activeNetworkState, deviceState.*)]] </div> </div> </div>
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js index 44c7c9d4..6795523 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js
@@ -77,18 +77,17 @@ }, /** - * @param {!OncMojo.NetworkStateProperties} activeNetworkState - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState * @return {string} * @private */ - getNetworkStateText_(activeNetworkState, deviceState) { + getNetworkStateText_() { const stateText = - this.getConnectionStateText_(activeNetworkState, deviceState); + this.getConnectionStateText_(this.activeNetworkState, this.deviceState); if (stateText) { return stateText; } // No network state, use device state. + const deviceState = this.deviceState; if (deviceState) { // Type specific scanning or initialization states. if (deviceState.type == mojom.NetworkType.kCellular) { @@ -98,6 +97,9 @@ if (deviceState.deviceState == mojom.DeviceStateType.kUninitialized) { return this.i18n('internetDeviceInitializing'); } + if (deviceState.deviceState == mojom.DeviceStateType.kDisabling) { + return this.i18n('internetDeviceDisabling'); + } } else if (deviceState.type == mojom.NetworkType.kTether) { if (deviceState.deviceState == mojom.DeviceStateType.kUninitialized) { return this.i18n('tetherEnableBluetooth'); @@ -119,7 +121,7 @@ }, /** - * @param {!OncMojo.NetworkStateProperties} networkState + * @param {!OncMojo.NetworkStateProperties|undefined} networkState * @param {!OncMojo.DeviceStateProperties|undefined} deviceState * @return {string} * @private @@ -236,7 +238,7 @@ enableToggleIsEnabled_(deviceState) { return this.enableToggleIsVisible_(deviceState) && deviceState.deviceState != mojom.DeviceStateType.kProhibited && - deviceState.deviceState != mojom.DeviceStateType.kUninitialized; + !OncMojo.deviceStateIsIntermediate(deviceState.deviceState); }, /** @@ -359,6 +361,10 @@ this.fire( 'device-enabled-toggled', {enabled: !deviceIsEnabled, type: this.deviceState.type}); + // Set the device state to enabling or disabling until updated. + this.deviceState.deviceState = deviceIsEnabled ? + mojom.DeviceStateType.kDisabling : + mojom.DeviceStateType.kEnabling; }, /**
diff --git a/chrome/browser/resources/settings/settings_resources_v3.grdp b/chrome/browser/resources/settings/settings_resources_v3.grdp index 3ce51d67..839760a 100644 --- a/chrome/browser/resources/settings/settings_resources_v3.grdp +++ b/chrome/browser/resources/settings/settings_resources_v3.grdp
@@ -86,6 +86,10 @@ file="autofill_page/blocking_request_manager.js" compress="false" type="BINDATA" /> </if> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_MERGE_PASSWORDS_STORE_COPIES_BEHAVIOR_JS" + file="autofill_page/merge_passwords_store_copies_behavior.js" + compress="false" type="BINDATA" + preprocess="true" /> <include name="IDR_SETTINGS_AUTOFILL_PAGE_MULTI_STORE_EXCEPTION_ENTRY_JS" file="autofill_page/multi_store_exception_entry.js" compress="false" type="BINDATA" />
diff --git a/chrome/browser/signin/signin_features.cc b/chrome/browser/signin/signin_features.cc index 04c9c495..34a745b 100644 --- a/chrome/browser/signin/signin_features.cc +++ b/chrome/browser/signin/signin_features.cc
@@ -8,3 +8,6 @@ const base::Feature kDiceWebSigninInterceptionFeature{ "DiceWebSigninInterception", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // ENABLE_DICE_SUPPORT + +const base::Feature kSigninReauthPrompt = {"SigninReauthPrompt", + base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/signin/signin_features.h b/chrome/browser/signin/signin_features.h index 6b258b77..258cb70c 100644 --- a/chrome/browser/signin/signin_features.h +++ b/chrome/browser/signin/signin_features.h
@@ -12,4 +12,6 @@ extern const base::Feature kDiceWebSigninInterceptionFeature; #endif // ENABLE_DICE_SUPPORT +extern const base::Feature kSigninReauthPrompt; + #endif // CHROME_BROWSER_SIGNIN_SIGNIN_FEATURES_H_
diff --git a/chrome/browser/spellchecker/spellcheck_factory.h b/chrome/browser/spellchecker/spellcheck_factory.h index 0a2c469..66e05d4 100644 --- a/chrome/browser/spellchecker/spellcheck_factory.h +++ b/chrome/browser/spellchecker/spellcheck_factory.h
@@ -43,6 +43,8 @@ #if defined(OS_WIN) FRIEND_TEST_ALL_PREFIXES(SpellcheckServiceWindowsHybridBrowserTest, WindowsHybridSpellcheck); + FRIEND_TEST_ALL_PREFIXES(SpellcheckServiceWindowsHybridBrowserTestDelayInit, + WindowsHybridSpellcheckDelayInit); #endif // defined(OS_WIN) DISALLOW_COPY_AND_ASSIGN(SpellcheckServiceFactory);
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc index 0b7520ec..83c5408 100644 --- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc +++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -666,4 +666,36 @@ // include Windows spellcheck languages that lack Hunspell support. ASSERT_FALSE(service->windows_spellcheck_dictionary_map_.empty()); } + +class SpellcheckServiceWindowsHybridBrowserTestDelayInit + : public SpellcheckServiceBrowserTest { + public: + SpellcheckServiceWindowsHybridBrowserTestDelayInit() = default; + + void SetUp() override { + // Don't initialize the SpellcheckService on browser launch. + feature_list_.InitWithFeatures( + /*enabled_features=*/{spellcheck::kWinUseBrowserSpellChecker, + spellcheck::kWinDelaySpellcheckServiceInit}, + /*disabled_features=*/{}); + InProcessBrowserTest::SetUp(); + } +}; + +IN_PROC_BROWSER_TEST_F(SpellcheckServiceWindowsHybridBrowserTestDelayInit, + WindowsHybridSpellcheckDelayInit) { + if (!spellcheck::WindowsVersionSupportsSpellchecker()) + return; + + ASSERT_TRUE(spellcheck::UseBrowserSpellChecker()); + + // Note that the base class forces dictionary sync to not be performed, and + // the kWinDelaySpellcheckServiceInit flag is set, which together should + // prevent creation of a SpellcheckService object on browser startup. So + // testing here that this is indeed the case. + SpellcheckService* service = static_cast<SpellcheckService*>( + SpellcheckServiceFactory::GetInstance()->GetServiceForBrowserContext( + GetContext(), /* create */ false)); + ASSERT_EQ(nullptr, service); +} #endif // defined(OS_WIN)
diff --git a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc index 4d98bd4..d85bb5e 100644 --- a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
@@ -207,16 +207,11 @@ ASSERT_THAT(GetPrefs(1)->GetString(pref_name), Eq(string_value)); // Start sync and await until they sync mutually. - base::HistogramTester histogram_tester; ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; // Verify that neither of the clients got updated, because of type mismatch. EXPECT_THAT(GetPrefs(0)->GetBoolean(pref_name), Eq(true)); EXPECT_THAT(GetPrefs(1)->GetString(pref_name), Eq(string_value)); - - // Only one of the two clients sees the mismatch, the one sync-ing last. - histogram_tester.ExpectTotalCount("Sync.Preferences.RemotePrefTypeMismatch", - 1); } // Verifies that priority synced preferences and regular sycned preferences are
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 28702b3..87a50bd 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1006,6 +1006,23 @@ Chrome has saved you <ph name="gigabytes">%1$d<ex>10</ex></ph> GB </message> + <!-- Download later --> + <message name="IDS_DOWNLOAD_LATER_DIALOG_TITLE" desc="Title of the download later dialog that let the user to choose the time to download."> + Choose when to download + </message> + <message name="IDS_DOWNLOAD_LATER_DIALOG_SUBTITLE" desc="Subtitle of the download later dialog that let the user to choose the time to download."> + You'll see a notification when this file is ready + </message> + <message name="IDS_DOWNLOAD_LATER_DOWNLOAD_NOW_TEXT" desc="The text for the radio button to trigger the download now in download later dialog."> + Now + </message> + <message name="IDS_DOWNLOAD_LATER_ON_WIFI_TEXT" desc="The text for the radio button to trigger the download on WIFI in download later dialog."> + On Wi-Fi + </message> + <message name="IDS_DOWNLOAD_LATER_PICK_TIME_TEXT" desc="The text for the radio button to select the download time in download later dialog."> + Pick date & time + </message> + <!-- Downloads location --> <message name="IDS_DOWNLOADS_LOCATION_SELECTOR_TITLE" desc="Title of the preference that allows the user to select which of the folders they would like to make the default location to save their downloads."> Download location
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.cc index 2f52beaa..2e75d20 100644 --- a/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.cc +++ b/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.cc
@@ -171,9 +171,17 @@ auto windows = GetWindows(extension_misc::kChromeAppId); for (auto* window : windows) { if (!chrome::FindBrowserWithWindow(window)) { - // The tabs in the browser should be closed, and tab windows have been - // removed from |browser_window_to_tab_window_|. - DCHECK(!base::Contains(browser_window_to_tab_window_, window)); + // Remove windows from |browser_window_to_tab_window_| and + // |tab_window_to_browser_window_|, because OnTabClosing could be not + // called for tabs in the browser, when the browser is removed. + if (base::Contains(browser_window_to_tab_window_, window)) { + for (auto* w : browser_window_to_tab_window_[window]) { + tab_window_to_browser_window_.erase(w); + OnInstances(GetAppId(w), w, std::string(), + apps::InstanceState::kDestroyed); + } + browser_window_to_tab_window_.erase(window); + } // The browser is removed if the window can't be found, so update the // Chrome window instance as destroyed.
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc index 15df712b..7c2fbb9 100644 --- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc
@@ -495,6 +495,11 @@ pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), GetSecurityLevel(), GetSyncState()); + + if (base::FeatureList::IsEnabled( + features::kAutofillEnableFixedPaymentsBubbleLogging)) { + AutofillMetrics::LogCreditCardUploadLegalMessageLinkClicked(); + } } void SaveCardBubbleControllerImpl::OnManageCardsClicked() {
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc index 55f92785..2dd4ba6 100644 --- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/metrics/user_action_tester.h" #include "base/test/scoped_feature_list.h" #include "base/values.h" #include "chrome/browser/ui/autofill/payments/save_card_bubble_view.h" @@ -809,89 +810,6 @@ AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_HIDDEN, 1); } -TEST_F(SaveCardBubbleControllerImplTest, - Metrics_Upload_FirstShow_LegalMessageLink) { - ShowUploadBubble(); - - base::HistogramTester histogram_tester; - controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com")); - - histogram_tester.ExpectUniqueSample( - "Autofill.SaveCreditCardPrompt.Upload.FirstShow", - AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1); -} - -TEST_F(SaveCardBubbleControllerImplTest, - Metrics_Upload_FirstShow_RequestingCardholderName_LegalMessageLink) { - ShowUploadBubble(AutofillClient::SaveCreditCardOptions() - .with_should_request_name_from_user(true) - .with_show_prompt()); - - base::HistogramTester histogram_tester; - controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com")); - - histogram_tester.ExpectUniqueSample( - "Autofill.SaveCreditCardPrompt.Upload.FirstShow.RequestingCardholderName", - AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1); -} - -TEST_F(SaveCardBubbleControllerImplTest, - Metrics_Upload_FirstShow_RequestingExpirationDate_LegalMessageLink) { - ShowUploadBubble(AutofillClient::SaveCreditCardOptions() - .with_should_request_expiration_date_from_user(true) - .with_show_prompt()); - - base::HistogramTester histogram_tester; - controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com")); - - histogram_tester.ExpectUniqueSample( - "Autofill.SaveCreditCardPrompt.Upload.FirstShow.RequestingExpirationDate", - AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1); -} - -TEST_F(SaveCardBubbleControllerImplTest, - Metrics_Upload_Reshows_LegalMessageLink) { - ShowUploadBubble(); - CloseAndReshowBubble(); - - base::HistogramTester histogram_tester; - controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com")); - - histogram_tester.ExpectUniqueSample( - "Autofill.SaveCreditCardPrompt.Upload.Reshows", - AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1); -} - -TEST_F(SaveCardBubbleControllerImplTest, - Metrics_Upload_Reshows_RequestingCardholderName_LegalMessageLink) { - ShowUploadBubble(AutofillClient::SaveCreditCardOptions() - .with_should_request_name_from_user(true) - .with_show_prompt()); - CloseAndReshowBubble(); - - base::HistogramTester histogram_tester; - controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com")); - - histogram_tester.ExpectUniqueSample( - "Autofill.SaveCreditCardPrompt.Upload.Reshows.RequestingCardholderName", - AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1); -} - -TEST_F(SaveCardBubbleControllerImplTest, - Metrics_Upload_Reshows_RequestingExpirationDate_LegalMessageLink) { - ShowUploadBubble(AutofillClient::SaveCreditCardOptions() - .with_should_request_expiration_date_from_user(true) - .with_show_prompt()); - CloseAndReshowBubble(); - - base::HistogramTester histogram_tester; - controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com")); - - histogram_tester.ExpectUniqueSample( - "Autofill.SaveCreditCardPrompt.Upload.Reshows.RequestingExpirationDate", - AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1); -} - // Param of the SaveCardBubbleSingletonTestData: // -- bool metrics_revamp_experiment_enabled; // -- bool first_shown_is_local; @@ -1233,14 +1151,39 @@ "Autofill.SaveCreditCardPromptOffer." + destination_ + ".SECURE", AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, expected_count); } else { - EXPECT_THAT( - histogram_tester.GetAllSamples("Autofill.SaveCreditCardPrompt." + - destination_ + ".SECURE"), - ElementsAre(Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOW_REQUESTED, - expected_count), - Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOWN_DEPRECATED, - expected_count))); + histogram_tester.ExpectTotalCount( + "Autofill.SaveCreditCardPromptOffer." + destination_ + ".SECURE", 0); } + + EXPECT_THAT( + histogram_tester.GetAllSamples("Autofill.SaveCreditCardPrompt." + + destination_ + ".SECURE"), + ElementsAre(Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOW_REQUESTED, + expected_count), + Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOWN_DEPRECATED, + expected_count))); +} + +TEST_P(SaveCardBubbleLoggingTest, Metrics_LegalMessageLinkedClicked) { + if (destination_ == "Local") + return; + + TriggerFlow(); + base::HistogramTester histogram_tester; + base::UserActionTester user_action_tester; + controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com")); + + if (metrics_revamp_experiment_enabled_) { + EXPECT_EQ(1, user_action_tester.GetActionCount( + "Autofill_CreditCardUpload_LegalMessageLinkClicked")); + } else { + EXPECT_EQ(0, user_action_tester.GetActionCount( + "Autofill_CreditCardUpload_LegalMessageLinkClicked")); + } + + histogram_tester.ExpectUniqueSample( + "Autofill.SaveCreditCardPrompt." + destination_ + "." + show_, + AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1); } // TODO(crbug.com/932818): Delete (manage card) or move (sign in promo) below
diff --git a/chrome/browser/ui/extensions/extension_settings_overridden_dialog.cc b/chrome/browser/ui/extensions/extension_settings_overridden_dialog.cc index f31d4292..628875c 100644 --- a/chrome/browser/ui/extensions/extension_settings_overridden_dialog.cc +++ b/chrome/browser/ui/extensions/extension_settings_overridden_dialog.cc
@@ -121,7 +121,7 @@ DCHECK(extension); - return {params_.dialog_title, params_.dialog_message}; + return {params_.dialog_title, params_.dialog_message, params_.icon}; } void ExtensionSettingsOverriddenDialog::OnDialogShown() {
diff --git a/chrome/browser/ui/extensions/settings_overridden_params_providers.cc b/chrome/browser/ui/extensions/settings_overridden_params_providers.cc index 8efc5d4..bae7ae6 100644 --- a/chrome/browser/ui/extensions/settings_overridden_params_providers.cc +++ b/chrome/browser/ui/extensions/settings_overridden_params_providers.cc
@@ -5,26 +5,52 @@ #include "chrome/browser/ui/extensions/settings_overridden_params_providers.h" #include "base/strings/utf_string_conversions.h" +#include "build/branding_buildflags.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/extensions/extension_web_ui.h" #include "chrome/browser/extensions/ntp_overridden_bubble_delegate.h" #include "chrome/browser/extensions/settings_api_bubble_delegate.h" #include "chrome/browser/extensions/settings_api_helpers.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" +#include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" +#include "components/google/core/common/google_util.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_service.h" #include "components/url_formatter/url_formatter.h" +#include "content/public/browser/browser_url_handler.h" #include "ui/base/l10n/l10n_util.h" namespace settings_overridden_params { +namespace { + +// Returns true if Google is the default search provider. +bool GoogleIsDefaultSearchProvider(Profile* profile) { + TemplateURLService* template_url_service = + TemplateURLServiceFactory::GetForProfile(profile); + const TemplateURL* const default_search = + template_url_service->GetDefaultSearchProvider(); + if (!default_search) { + // According to TemplateURLService, |default_search| can be null if the + // default search engine is disabled by policy. + return false; + } + + GURL search_url = default_search->GenerateSearchURL( + template_url_service->search_terms_data()); + return google_util::IsGoogleSearchUrl(search_url); +} + +} // namespace + base::Optional<ExtensionSettingsOverriddenDialog::Params> GetNtpOverriddenParams(Profile* profile) { + const GURL ntp_url(chrome::kChromeUINewTabURL); const extensions::Extension* extension = - ExtensionWebUI::GetExtensionControllingURL( - GURL(chrome::kChromeUINewTabURL), profile); + ExtensionWebUI::GetExtensionControllingURL(ntp_url, profile); if (!extension) return base::nullopt; @@ -34,19 +60,65 @@ const char* preference_name = extensions::NtpOverriddenBubbleDelegate::kNtpBubbleAcknowledged; - constexpr char kHistogramName[] = - "Extensions.SettingsOverridden.GenericNtpOverriddenDialogResult"; + std::vector<GURL> possible_rewrites = + content::BrowserURLHandler::GetInstance()->GetPossibleRewrites(ntp_url, + profile); + // We already know that the extension is the primary NTP controller. + DCHECK(!possible_rewrites.empty()); + DCHECK_EQ(extension->url().host_piece(), possible_rewrites[0].host_piece()) + << "Unexpected NTP URL: " << possible_rewrites[0]; - // TODO(devlin): Adjust these messages based on the previous NTP. - base::string16 dialog_title = l10n_util::GetStringUTF16( - IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_TITLE_GENERIC); + // Find whether the default NTP would take over if the extension were to be + // removed. This might not be the case if, e.g. an enterprise policy set the + // NTP or the default search provided its own. + bool default_ntp_is_secondary = true; + if (possible_rewrites.size() > 1) { + default_ntp_is_secondary = + possible_rewrites[1] == ntp_url || + possible_rewrites[1] == GURL(chrome::kChromeSearchLocalNtpUrl) || + possible_rewrites[1] == GURL(chrome::kChromeUINewTabPageURL); + } + // Check if there's another extension that would take over (this isn't + // included in BrowserURLHandler::GetPossibleRewrites(), which only takes the + // highest-priority from each source). + default_ntp_is_secondary &= + ExtensionWebUI::GetNumberOfExtensionsOverridingURL(ntp_url, profile) == 1; + + // We show different dialogs based on whether the NTP would return to the + // default Chrome NTP with Google search. + bool use_back_to_google_messaging = + default_ntp_is_secondary && GoogleIsDefaultSearchProvider(profile); + + constexpr char kGenericDialogHistogramName[] = + "Extensions.SettingsOverridden.GenericNtpOverriddenDialogResult"; + constexpr char kBackToGoogleDialogHistogramName[] = + "Extensions.SettingsOverridden.BackToGoogleNtpOverriddenDialogResult"; + + base::string16 dialog_title; + const char* histogram_name = nullptr; + const gfx::VectorIcon* icon = nullptr; + if (use_back_to_google_messaging) { + dialog_title = l10n_util::GetStringUTF16( + IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_TITLE_BACK_TO_GOOGLE); + histogram_name = kBackToGoogleDialogHistogramName; +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + icon = &kGoogleGLogoIcon; +#endif + } else { + dialog_title = l10n_util::GetStringUTF16( + IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_TITLE_GENERIC); + histogram_name = kGenericDialogHistogramName; + } + DCHECK(!dialog_title.empty()); + DCHECK(histogram_name); + base::string16 dialog_message = l10n_util::GetStringFUTF16( IDS_EXTENSION_NTP_OVERRIDDEN_DIALOG_BODY_GENERIC, base::UTF8ToUTF16(extension->name().c_str())); return ExtensionSettingsOverriddenDialog::Params( - extension->id(), preference_name, kHistogramName, std::move(dialog_title), - std::move(dialog_message), nullptr); + extension->id(), preference_name, histogram_name, std::move(dialog_title), + std::move(dialog_message), icon); } base::Optional<ExtensionSettingsOverriddenDialog::Params>
diff --git a/chrome/browser/ui/extensions/settings_overridden_params_providers_browsertest.cc b/chrome/browser/ui/extensions/settings_overridden_params_providers_browsertest.cc index 1075cd8..ebf06de1 100644 --- a/chrome/browser/ui/extensions/settings_overridden_params_providers_browsertest.cc +++ b/chrome/browser/ui/extensions/settings_overridden_params_providers_browsertest.cc
@@ -10,7 +10,10 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/settings_api_helpers.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/ui/browser.h" +#include "components/search_engines/template_url.h" +#include "components/search_engines/template_url_service.h" #include "content/public/test/browser_test.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension_builder.h" @@ -28,6 +31,16 @@ extensions::GetExtensionOverridingSearchEngine(profile())); return extension; } + + // Installs a new extension that controls the new tab page. + const extensions::Extension* AddExtensionControllingNewTab() { + const extensions::Extension* extension = + InstallExtensionWithPermissionsGranted( + test_data_dir_.AppendASCII("api_test/override/newtab"), 1); + EXPECT_EQ(extension, + extensions::GetExtensionOverridingNewTabPage(profile())); + return extension; + } }; // The chrome_settings_overrides API that allows extensions to override the @@ -67,3 +80,35 @@ } #endif // defined(OS_WIN) || defined(OS_MACOSX) + +// Tests the dialog display when the default search engine has changed; in this +// case, we should display the generic dialog. +IN_PROC_BROWSER_TEST_F(SettingsOverriddenParamsProvidersBrowserTest, + DialogParamsWithNonDefaultSearch) { + // Find a search provider that isn't Google, and set it as the default. + TemplateURLService* const template_url_service = + TemplateURLServiceFactory::GetForProfile(profile()); + TemplateURLService::TemplateURLVector template_urls = + template_url_service->GetTemplateURLs(); + auto iter = std::find_if(template_urls.begin(), template_urls.end(), + [template_url_service](const TemplateURL* turl) { + // For the test, we can be a bit lazier and just + // use HasGoogleBaseURLs() instead of getting the + // full search URL. + return !turl->HasGoogleBaseURLs( + template_url_service->search_terms_data()); + }); + ASSERT_TRUE(iter != template_urls.end()); + template_url_service->SetUserSelectedDefaultSearchProvider(*iter); + + const extensions::Extension* extension = AddExtensionControllingNewTab(); + + // The dialog should be the generic version, rather than prompting to go back + // to the default. + base::Optional<ExtensionSettingsOverriddenDialog::Params> params = + settings_overridden_params::GetNtpOverriddenParams(profile()); + ASSERT_TRUE(params); + EXPECT_EQ(extension->id(), params->controlling_extension_id); + EXPECT_EQ("Did you mean to change this page?", + base::UTF16ToUTF8(params->dialog_title)); +}
diff --git a/chrome/browser/ui/extensions/settings_overridden_params_providers_unittest.cc b/chrome/browser/ui/extensions/settings_overridden_params_providers_unittest.cc index 9e78b60..22690af7 100644 --- a/chrome/browser/ui/extensions/settings_overridden_params_providers_unittest.cc +++ b/chrome/browser/ui/extensions/settings_overridden_params_providers_unittest.cc
@@ -4,11 +4,15 @@ #include "chrome/browser/ui/extensions/settings_overridden_params_providers.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service_test_base.h" #include "chrome/browser/extensions/extension_web_ui.h" #include "chrome/browser/extensions/extension_web_ui_override_registrar.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/common/webui_url_constants.h" +#include "chrome/test/base/search_test_utils.h" +#include "components/search_engines/template_url_service.h" #include "extensions/common/extension_builder.h" #include "extensions/common/value_builder.h" @@ -28,14 +32,20 @@ return std::make_unique< extensions::ExtensionWebUIOverrideRegistrar>(context); })); + auto* template_url_service = static_cast<TemplateURLService*>( + TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( + profile(), + base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor))); + search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service); } // Adds a new extension that overrides the NTP. - const extensions::Extension* AddExtensionControllingNewTab() { + const extensions::Extension* AddExtensionControllingNewTab( + const char* name = "ntp override") { std::unique_ptr<base::Value> chrome_url_overrides = extensions::DictionaryBuilder().Set("newtab", "newtab.html").Build(); scoped_refptr<const extensions::Extension> extension = - extensions::ExtensionBuilder("ntp override") + extensions::ExtensionBuilder(name) .SetLocation(extensions::Manifest::INTERNAL) .SetManifestKey("chrome_url_overrides", std::move(chrome_url_overrides)) @@ -70,4 +80,27 @@ settings_overridden_params::GetNtpOverriddenParams(profile()); ASSERT_TRUE(params); EXPECT_EQ(ntp_extension->id(), params->controlling_extension_id); + + // In this case, disabling the extension would go back to the default NTP, so + // a specific message should show. + EXPECT_EQ("Change back to Google?", base::UTF16ToUTF8(params->dialog_title)); +} + +TEST_F(SettingsOverriddenParamsProvidersUnitTest, + DialogStringsWhenMultipleNtpOverrides_MultipleExtensions) { + const extensions::Extension* extension1 = + AddExtensionControllingNewTab("uno"); + const extensions::Extension* extension2 = + AddExtensionControllingNewTab("dos"); + EXPECT_NE(extension1->id(), extension2->id()); + + // When there are multiple extensions that could override the NTP, we should + // show a generic dialog (rather than prompting to go back to the default + // NTP), because the other extension would just take over. + base::Optional<ExtensionSettingsOverriddenDialog::Params> params = + settings_overridden_params::GetNtpOverriddenParams(profile()); + ASSERT_TRUE(params); + EXPECT_EQ(extension2->id(), params->controlling_extension_id); + EXPECT_EQ("Did you mean to change this page?", + base::UTF16ToUTF8(params->dialog_title)); }
diff --git a/chrome/browser/ui/qrcode_generator/OWNERS b/chrome/browser/ui/qrcode_generator/OWNERS new file mode 100644 index 0000000..e58f618d --- /dev/null +++ b/chrome/browser/ui/qrcode_generator/OWNERS
@@ -0,0 +1,3 @@ +file://components/send_tab_to_self/OWNERS + +# COMPONENT: UI>Browser>Sharing
diff --git a/chrome/browser/ui/signin_reauth_view_controller.cc b/chrome/browser/ui/signin_reauth_view_controller.cc index fe7a615..65d30b1 100644 --- a/chrome/browser/ui/signin_reauth_view_controller.cc +++ b/chrome/browser/ui/signin_reauth_view_controller.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/reauth_result.h" #include "chrome/browser/signin/reauth_tab_helper.h" +#include "chrome/browser/signin/signin_features.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "content/public/browser/browser_task_traits.h" @@ -24,9 +25,6 @@ namespace { -const base::Feature kSigninReauthPrompt = {"SigninReauthPrompt", - base::FEATURE_DISABLED_BY_DEFAULT}; - class ReauthWebContentsObserver : public content::WebContentsObserver { public: ReauthWebContentsObserver(content::WebContents* web_contents, @@ -125,6 +123,10 @@ OnStateChanged(); } +void SigninReauthViewController::OnReauthDismissed() { + CompleteReauth(signin::ReauthResult::kDismissedByUser); +} + void SigninReauthViewController::OnGaiaReauthPageNavigated() { if (gaia_reauth_page_state_ >= GaiaReauthPageState::kNavigated) return;
diff --git a/chrome/browser/ui/signin_reauth_view_controller.h b/chrome/browser/ui/signin_reauth_view_controller.h index f039a3a..289c8457 100644 --- a/chrome/browser/ui/signin_reauth_view_controller.h +++ b/chrome/browser/ui/signin_reauth_view_controller.h
@@ -70,6 +70,10 @@ // dialog. // This happens before the Gaia reauth page is shown. void OnReauthConfirmed(); + // Called when the user clicks the cancel button in the reauth confirmation + // dialog. + // This happens before the Gaia reauth page is shown. + void OnReauthDismissed(); // Called when the Gaia reauth page has navigated. void OnGaiaReauthPageNavigated();
diff --git a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc new file mode 100644 index 0000000..a740293 --- /dev/null +++ b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
@@ -0,0 +1,240 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/notreached.h" +#include "base/optional.h" +#include "base/run_loop.h" +#include "base/test/bind_test_util.h" +#include "base/test/mock_callback.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/signin/reauth_result.h" +#include "chrome/browser/signin/signin_features.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/signin_reauth_view_controller.h" +#include "chrome/browser/ui/signin_view_controller.h" +#include "chrome/browser/ui/webui/signin/login_ui_test_utils.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/signin/public/identity_manager/consent_level.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/identity_test_utils.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_navigation_observer.h" +#include "google_apis/gaia/core_account_id.h" +#include "google_apis/gaia/gaia_switches.h" +#include "net/base/escape.h" +#include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/controllable_http_response.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_response.h" +#include "net/test/embedded_test_server/request_handler_util.h" + +namespace { + +const base::TimeDelta kReauthDialogTimeout = base::TimeDelta::FromSeconds(30); +const char kReauthDonePath[] = "/embedded/xreauth/chrome?done"; +const char kReauthPath[] = "/embedded/xreauth/chrome"; +const char kChallengePath[] = "/challenge"; + +std::unique_ptr<net::test_server::BasicHttpResponse> CreateRedirectResponse( + const GURL& redirect_url) { + auto http_response = std::make_unique<net::test_server::BasicHttpResponse>(); + http_response->set_code(net::HTTP_TEMPORARY_REDIRECT); + http_response->AddCustomHeader("Location", redirect_url.spec()); + http_response->AddCustomHeader("Access-Control-Allow-Origin", "*"); + return http_response; +} + +std::unique_ptr<net::test_server::HttpResponse> HandleReauthURL( + const GURL& base_url, + const net::test_server::HttpRequest& request) { + if (!net::test_server::ShouldHandle(request, kReauthPath)) { + return nullptr; + } + + GURL request_url = request.GetURL(); + std::string parameter = + net::UnescapeBinaryURLComponent(request_url.query_piece()); + + if (parameter.empty()) { + // Parameterless request redirects to the fake challenge page. + return CreateRedirectResponse(base_url.Resolve(kChallengePath)); + } + + if (parameter == "done") { + // On success, the reauth returns HTTP_NO_CONTENT response. + auto http_response = + std::make_unique<net::test_server::BasicHttpResponse>(); + http_response->set_code(net::HTTP_NO_CONTENT); + return http_response; + } + + NOTREACHED(); + return nullptr; +} + +} // namespace + +// Browser tests for SigninReauthViewController. +class SigninReauthViewControllerBrowserTest : public InProcessBrowserTest { + public: + SigninReauthViewControllerBrowserTest() + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { + scoped_feature_list_.InitAndEnableFeature(kSigninReauthPrompt); + } + + void SetUp() override { + ASSERT_TRUE(https_server()->InitializeAndListen()); + InProcessBrowserTest::SetUp(); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII(switches::kGaiaUrl, base_url().spec()); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + + https_server()->RegisterRequestHandler( + base::BindRepeating(&HandleReauthURL, base_url())); + reauth_challenge_response_ = + std::make_unique<net::test_server::ControllableHttpResponse>( + https_server(), kChallengePath); + https_server()->StartAcceptingConnections(); + + account_id_ = signin::SetUnconsentedPrimaryAccount(identity_manager(), + "alice@gmail.com") + .account_id; + + reauth_result_loop_ = std::make_unique<base::RunLoop>(); + } + + void ShowReauthPrompt() { + abort_handle_ = browser()->signin_view_controller()->ShowReauthPrompt( + account_id_, + base::BindOnce(&SigninReauthViewControllerBrowserTest::OnReauthResult, + base::Unretained(this))); + } + + // This method must be called only after the reauth dialog has been opened. + void RedirectGaiaChallengeTo(const GURL& redirect_url) { + reauth_challenge_response_->WaitForRequest(); + auto redirect_response = CreateRedirectResponse(redirect_url); + reauth_challenge_response_->Send(redirect_response->ToResponseString()); + reauth_challenge_response_->Done(); + } + + void OnReauthResult(signin::ReauthResult reauth_result) { + reauth_result_ = reauth_result; + reauth_result_loop_->Quit(); + } + + base::Optional<signin::ReauthResult> WaitForReauthResult() { + reauth_result_loop_->Run(); + return reauth_result_; + } + + void ResetAbortHandle() { abort_handle_.reset(); } + + net::EmbeddedTestServer* https_server() { return &https_server_; } + + GURL base_url() { return https_server()->base_url(); } + + signin::IdentityManager* identity_manager() { + return IdentityManagerFactory::GetForProfile(browser()->profile()); + } + + SigninReauthViewController* signin_reauth_view_controller() { + SigninViewController* signin_view_controller = + browser()->signin_view_controller(); + DCHECK(signin_view_controller->ShowsModalDialog()); + return static_cast<SigninReauthViewController*>( + signin_view_controller->GetModalDialogDelegateForTesting()); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + net::EmbeddedTestServer https_server_; + std::unique_ptr<net::test_server::ControllableHttpResponse> + reauth_challenge_response_; + CoreAccountId account_id_; + std::unique_ptr<SigninViewController::ReauthAbortHandle> abort_handle_; + + std::unique_ptr<base::RunLoop> reauth_result_loop_; + base::Optional<signin::ReauthResult> reauth_result_; +}; + +// Tests that the abort handle cancels an ongoing reauth flow. +IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, + AbortReauthDialog_AbortHandle) { + ShowReauthPrompt(); + ResetAbortHandle(); + EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kCancelled); +} + +// Tests canceling the reauth dialog through CloseModalSignin(). +IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, + AbortReauthDialog_CloseModalSignin) { + ShowReauthPrompt(); + browser()->signin_view_controller()->CloseModalSignin(); + EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kCancelled); +} + +// Tests closing the reauth dialog through by clicking on the close button (the +// X). +IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, + CloseReauthDialog) { + ShowReauthPrompt(); + // The test cannot depend on Views implementation so it simulates clicking on + // the close button through calling the close event. + signin_reauth_view_controller()->OnModalSigninClosed(); + EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kDismissedByUser); +} + +// Tests clicking on the cancel button in the reauth dialog. +IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, + CancelReauthDialog) { + ShowReauthPrompt(); + ASSERT_TRUE(login_ui_test_utils::CancelReauthConfirmationDialog( + browser(), kReauthDialogTimeout)); + EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kDismissedByUser); +} + +// Tests the reauth result in case Gaia page failed to load. +IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, + GaiaChallengeLoadFailed) { + ShowReauthPrompt(); + ASSERT_TRUE(login_ui_test_utils::ConfirmReauthConfirmationDialog( + browser(), kReauthDialogTimeout)); + RedirectGaiaChallengeTo(https_server()->GetURL("/close-socket")); + EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kLoadFailed); +} + +// Tests clicking on the confirm button in the reauth dialog. Reauth completes +// before the confirmation. +IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, + ConfirmReauthDialog_AfterReauthSuccess) { + ShowReauthPrompt(); + RedirectGaiaChallengeTo(https_server()->GetURL(kReauthDonePath)); + ASSERT_TRUE(login_ui_test_utils::ConfirmReauthConfirmationDialog( + browser(), kReauthDialogTimeout)); + EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kSuccess); +} + +// Tests clicking on the confirm button in the reauth dialog. Reauth completes +// after the confirmation. +IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, + ConfirmReauthDialog_BeforeReauthSuccess) { + ShowReauthPrompt(); + ASSERT_TRUE(login_ui_test_utils::ConfirmReauthConfirmationDialog( + browser(), kReauthDialogTimeout)); + RedirectGaiaChallengeTo(https_server()->GetURL(kReauthDonePath)); + EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kSuccess); +}
diff --git a/chrome/browser/ui/signin_view_controller.cc b/chrome/browser/ui/signin_view_controller.cc index 670406f..d696c4b 100644 --- a/chrome/browser/ui/signin_view_controller.cc +++ b/chrome/browser/ui/signin_view_controller.cc
@@ -272,6 +272,11 @@ reauth_controller_->OnReauthConfirmed(); } +void SigninViewController::OnReauthDismissed() { + if (reauth_controller_) + reauth_controller_->OnReauthDismissed(); +} + #if BUILDFLAG(ENABLE_DICE_SUPPORT) void SigninViewController::ShowDiceSigninTab( signin_metrics::Reason signin_reason, @@ -435,3 +440,9 @@ DCHECK(delegate_); return delegate_->GetWebContents(); } + +SigninViewControllerDelegate* +SigninViewController::GetModalDialogDelegateForTesting() { + DCHECK(delegate_); + return delegate_; +}
diff --git a/chrome/browser/ui/signin_view_controller.h b/chrome/browser/ui/signin_view_controller.h index d7d9687..b79939b 100644 --- a/chrome/browser/ui/signin_view_controller.h +++ b/chrome/browser/ui/signin_view_controller.h
@@ -142,8 +142,12 @@ // Notifies that the user confirmed the reauth dialog. void OnReauthConfirmed(); + // Notifies that the user dismissed the reauth dialog. + void OnReauthDismissed(); + private: friend class login_ui_test_utils::SigninViewControllerTestUtil; + friend class SigninReauthViewControllerBrowserTest; #if BUILDFLAG(ENABLE_DICE_SUPPORT) // Shows the DICE-specific sign-in flow: opens a Gaia sign-in webpage in a new @@ -158,6 +162,9 @@ // Returns the web contents of the modal dialog. content::WebContents* GetModalDialogWebContentsForTesting(); + // Returns the modal dialog delegate. + SigninViewControllerDelegate* GetModalDialogDelegateForTesting(); + // Browser owning this controller. Browser* browser_;
diff --git a/chrome/browser/ui/signin_view_controller_interactive_uitest.cc b/chrome/browser/ui/signin_view_controller_interactive_uitest.cc index 7d8385d..c71c9b4b 100644 --- a/chrome/browser/ui/signin_view_controller_interactive_uitest.cc +++ b/chrome/browser/ui/signin_view_controller_interactive_uitest.cc
@@ -7,7 +7,6 @@ #include "base/callback.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" -#include "base/test/mock_callback.h" #include "build/build_config.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/reauth_result.h" @@ -68,19 +67,6 @@ EXPECT_EQ(2, browser()->tab_strip_model()->count()); } -IN_PROC_BROWSER_TEST_F(SignInViewControllerBrowserTest, AbortOngoingReauth) { - CoreAccountId account_id = signin::SetUnconsentedPrimaryAccount( - GetIdentityManager(), "alice@gmail.com") - .account_id; - base::MockCallback<base::OnceCallback<void(signin::ReauthResult)>> - reauth_callback; - std::unique_ptr<SigninViewController::ReauthAbortHandle> abort_handle = - browser()->signin_view_controller()->ShowReauthPrompt( - account_id, reauth_callback.Get()); - EXPECT_CALL(reauth_callback, Run(signin::ReauthResult::kCancelled)); - abort_handle.reset(); -} - // Tests that the confirm button is focused by default in the reauth dialog. IN_PROC_BROWSER_TEST_F(SignInViewControllerBrowserTest, ReauthDefaultFocus) { CoreAccountId account_id = signin::SetUnconsentedPrimaryAccount(
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc index 31494f3..29e808f 100644 --- a/chrome/browser/ui/views/download/download_shelf_view.cc +++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -105,12 +105,9 @@ // and return to chrome with the download shelf still open. mouse_watcher_.set_notify_on_exit_time(base::TimeDelta::FromSeconds(5)); SetID(VIEW_ID_DOWNLOAD_SHELF); - parent->AddChildView(this); } -DownloadShelfView::~DownloadShelfView() { - parent_->RemoveChildView(this); -} +DownloadShelfView::~DownloadShelfView() = default; void DownloadShelfView::AddDownloadView(DownloadItemView* view) { mouse_watcher_.Stop();
diff --git a/chrome/browser/ui/views/extensions/settings_overridden_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/settings_overridden_dialog_view_browsertest.cc index dc198338..b756a8e5 100644 --- a/chrome/browser/ui/views/extensions/settings_overridden_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/settings_overridden_dialog_view_browsertest.cc
@@ -12,6 +12,7 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/extensions/settings_api_bubble_helpers.h" @@ -22,6 +23,8 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/search_engines/template_url.h" +#include "components/search_engines/template_url_service.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "ui/views/test/widget_test.h" @@ -72,8 +75,10 @@ ShowSimpleDialog(false, browser()); else if (name == "SimpleDialogWithIcon") ShowSimpleDialog(true, browser()); - else if (name == "NtpOverriddenDialog") - ShowNtpOverriddenDialog(); + else if (name == "NtpOverriddenDialog_BackToDefault") + ShowNtpOverriddenDefaultDialog(); + else if (name == "NtpOverriddenDialog_Generic") + ShowNtpOverriddenGenericDialog(); else if (name == "SearchOverriddenDialog") ShowSearchOverriddenDialog(); else @@ -99,22 +104,17 @@ return dialog; } - void ShowNtpOverriddenDialog() { - base::FilePath test_root_path; - ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_root_path)); + void ShowNtpOverriddenDefaultDialog() { + // Load an extension overriding the NTP and open a new tab to trigger the + // dialog. + LoadExtensionOverridingNewTab(); + NavigateToNewTab(); + } - // Load up an extension that overrides the NTP. - Profile* const profile = browser()->profile(); - scoped_refptr<const extensions::Extension> extension = - extensions::ChromeTestExtensionLoader(profile).LoadExtension( - test_root_path.AppendASCII("extensions/api_test/override/newtab")); - ASSERT_TRUE(extension); - - // Opening up a new tab should trigger the dialog. - ui_test_utils::NavigateToURLWithDisposition( - browser(), GURL(chrome::kChromeUINewTabURL), - WindowOpenDisposition::NEW_FOREGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + void ShowNtpOverriddenGenericDialog() { + SetNonDefaultSearchProvider(); + LoadExtensionOverridingNewTab(); + NavigateToNewTab(); } void ShowSearchOverriddenDialog() { @@ -159,6 +159,42 @@ } private: + void LoadExtensionOverridingNewTab() { + base::FilePath test_root_path; + ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_root_path)); + + Profile* const profile = browser()->profile(); + scoped_refptr<const extensions::Extension> extension = + extensions::ChromeTestExtensionLoader(profile).LoadExtension( + test_root_path.AppendASCII("extensions/api_test/override/newtab")); + ASSERT_TRUE(extension); + } + + void NavigateToNewTab() { + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(chrome::kChromeUINewTabURL), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + } + + void SetNonDefaultSearchProvider() { + TemplateURLService* const template_url_service = + TemplateURLServiceFactory::GetForProfile(browser()->profile()); + TemplateURLService::TemplateURLVector template_urls = + template_url_service->GetTemplateURLs(); + auto iter = std::find_if(template_urls.begin(), template_urls.end(), + [template_url_service](const TemplateURL* turl) { + // For the test, we can be a bit lazier and just + // use HasGoogleBaseURLs() instead of getting the + // full search URL. + return !turl->HasGoogleBaseURLs( + template_url_service->search_terms_data()); + }); + ASSERT_TRUE(iter != template_urls.end()); + + template_url_service->SetUserSelectedDefaultSearchProvider(*iter); + } + std::string test_name_; base::Optional<SettingsOverriddenDialogController::DialogResult> @@ -181,7 +217,16 @@ } IN_PROC_BROWSER_TEST_F(SettingsOverriddenDialogViewBrowserTest, - InvokeUi_NtpOverriddenDialog) { + InvokeUi_NtpOverriddenDialog_BackToDefault) { + // Force the post-install NTP UI to be enabled, so that we can test on all + // platforms. + extensions::SetNtpPostInstallUiEnabledForTesting(true); + ShowAndVerifyUi(); + extensions::SetNtpPostInstallUiEnabledForTesting(false); +} + +IN_PROC_BROWSER_TEST_F(SettingsOverriddenDialogViewBrowserTest, + InvokeUi_NtpOverriddenDialog_Generic) { // Force the post-install NTP UI to be enabled, so that we can test on all // platforms. extensions::SetNtpPostInstallUiEnabledForTesting(true);
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 21c9d54..c8402aae 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -399,15 +399,6 @@ : browser_view_(browser_view) {} ~BrowserViewLayoutDelegateImpl() override {} - // BrowserViewLayoutDelegate overrides: - bool DownloadShelfNeedsLayout() const override { - DownloadShelfView* download_shelf = browser_view_->download_shelf_.get(); - // Re-layout the shelf either if it is visible or if its close animation - // is currently running. - return download_shelf && - (download_shelf->IsShowing() || download_shelf->IsClosing()); - } - bool IsTabStripVisible() const override { return browser_view_->IsTabStripVisible(); } @@ -588,34 +579,20 @@ // child views and it is an observer for avatar toolbar button if any. autofill_bubble_handler_.reset(); - extensions::ExtensionCommandsGlobalRegistry* global_registry = + auto* global_registry = extensions::ExtensionCommandsGlobalRegistry::Get(browser_->profile()); if (global_registry->registry_for_active_window() == extension_keybinding_registry_.get()) global_registry->set_registry_for_active_window(nullptr); - // We destroy the download shelf before |browser_| to remove its child - // download views from the set of download observers (since the observed - // downloads can be destroyed along with |browser_| and the observer - // notifications will call back into deleted objects). - BrowserViewLayout* browser_view_layout = GetBrowserViewLayout(); - if (browser_view_layout) - browser_view_layout->set_download_shelf(nullptr); - download_shelf_.reset(); - // The TabStrip attaches a listener to the model. Make sure we shut down the // TabStrip first so that it can cleanly remove the listener. - if (tabstrip_) { - tabstrip_->parent()->RemoveChildView(tabstrip_); - if (browser_view_layout) - browser_view_layout->set_tab_strip(nullptr); - delete tabstrip_; - tabstrip_ = nullptr; - } + if (tabstrip_) + tabstrip_->parent()->RemoveChildViewT(tabstrip_); + // Child views maintain PrefMember attributes that point to // OffTheRecordProfile's PrefService which gets deleted by ~Browser. RemoveAllChildViews(true); - toolbar_ = nullptr; } // static @@ -1694,16 +1671,16 @@ } bool BrowserView::IsDownloadShelfVisible() const { - return download_shelf_.get() && download_shelf_->IsShowing(); + return download_shelf_ && download_shelf_->IsShowing(); } DownloadShelf* BrowserView::GetDownloadShelf() { - if (!download_shelf_.get()) { - download_shelf_ = std::make_unique<DownloadShelfView>(browser_.get(), this); - download_shelf_->set_owned_by_client(); - GetBrowserViewLayout()->set_download_shelf(download_shelf_.get()); + if (!download_shelf_) { + download_shelf_ = + AddChildView(std::make_unique<DownloadShelfView>(browser_.get(), this)); + GetBrowserViewLayout()->set_download_shelf(download_shelf_); } - return download_shelf_.get(); + return download_shelf_; } void BrowserView::ConfirmBrowserCloseWithPendingDownloads( @@ -2244,7 +2221,7 @@ // focus order, but makes it easily accessible by using SHIFT-TAB (reverse // focus traversal) from the toolbar/omnibox. if (download_shelf_ && contents_container_) - InsertIntoFocusOrderAfter(contents_container_, download_shelf_.get()); + InsertIntoFocusOrderAfter(contents_container_, download_shelf_); #if DCHECK_IS_ON() // Make sure we didn't create any cycles in the focus order. @@ -2559,8 +2536,8 @@ panes->push_back(bookmark_bar_view_.get()); if (infobar_container_) panes->push_back(infobar_container_); - if (download_shelf_.get()) - panes->push_back(download_shelf_.get()); + if (download_shelf_) + panes->push_back(download_shelf_); // TODO(crbug.com/1055150): Implement for mac. #if !defined(OS_MACOSX) // See if there is a caption bubble present.
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 7d3583c..4c2c03f 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -770,7 +770,7 @@ View* find_bar_host_view_ = nullptr; // The download shelf view (view at the bottom of the page). - std::unique_ptr<DownloadShelfView> download_shelf_; + DownloadShelfView* download_shelf_ = nullptr; // The InfoBarContainerView that contains InfoBars for the current tab. InfoBarContainerView* infobar_container_ = nullptr;
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc index f103429..18f1dff 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout.cc +++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -529,13 +529,10 @@ int BrowserViewLayout::LayoutDownloadShelf(int bottom) { TRACE_EVENT0("ui", "BrowserViewLayout::LayoutDownloadShelf"); - if (delegate_->DownloadShelfNeedsLayout()) { - DCHECK(download_shelf_); + if (download_shelf_ && download_shelf_->GetVisible()) { const int height = download_shelf_->GetPreferredSize().height(); - SetViewVisibility(download_shelf_, true); download_shelf_->SetBounds(vertical_layout_rect_.x(), bottom - height, vertical_layout_rect_.width(), height); - download_shelf_->Layout(); bottom -= height; } return bottom;
diff --git a/chrome/browser/ui/views/frame/browser_view_layout_delegate.h b/chrome/browser/ui/views/frame/browser_view_layout_delegate.h index c3861e9..65a57e5 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout_delegate.h +++ b/chrome/browser/ui/views/frame/browser_view_layout_delegate.h
@@ -26,7 +26,6 @@ virtual bool IsToolbarVisible() const = 0; virtual bool IsBookmarkBarVisible() const = 0; virtual bool IsContentsSeparatorEnabled() const = 0; - virtual bool DownloadShelfNeedsLayout() const = 0; virtual ExclusiveAccessBubbleViews* GetExclusiveAccessBubble() const = 0; virtual bool IsTopControlsSlideBehaviorEnabled() const = 0; virtual float GetTopControlsSlideBehaviorShownRatio() const = 0;
diff --git a/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc b/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc index 8637119..e8916b13 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/frame/browser_view_layout.h" +#include <memory> + #include "base/containers/flat_set.h" #include "base/macros.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -29,9 +31,6 @@ MockBrowserViewLayoutDelegate() = default; ~MockBrowserViewLayoutDelegate() override = default; - void set_download_shelf_needs_layout(bool layout) { - download_shelf_needs_layout_ = layout; - } void set_tab_strip_visible(bool visible) { tab_strip_visible_ = visible; } @@ -63,10 +62,6 @@ bool IsContentsSeparatorEnabled() const override { return content_separator_enabled_; } - bool DownloadShelfNeedsLayout() const override { - return download_shelf_needs_layout_; - } - ExclusiveAccessBubbleViews* GetExclusiveAccessBubble() const override { return nullptr; } @@ -97,7 +92,6 @@ bool toolbar_visible_ = true; bool bookmark_bar_visible_ = true; bool content_separator_enabled_ = true; - bool download_shelf_needs_layout_ = false; bool top_controls_slide_enabled_ = false; float top_controls_shown_ratio_ = 1.f; @@ -106,8 +100,8 @@ /////////////////////////////////////////////////////////////////////////////// -views::View* CreateFixedSizeView(const gfx::Size& size) { - auto* view = new views::View; +std::unique_ptr<views::View> CreateFixedSizeView(const gfx::Size& size) { + auto view = std::make_unique<views::View>(); view->SetPreferredSize(size); view->SizeToPreferredSize(); return view; @@ -168,45 +162,44 @@ void SetUp() override { ChromeViewsTestBase::SetUp(); - root_view_.reset(CreateFixedSizeView(gfx::Size(800, 600))); + root_view_ = CreateFixedSizeView(gfx::Size(800, 600)); immersive_mode_controller_ = std::make_unique<MockImmersiveModeController>(); - top_container_ = CreateFixedSizeView(gfx::Size(800, 60)); - views::View* tab_strip_region_view = new TabStripRegionView(); - tab_strip_ = new TabStrip(std::make_unique<FakeBaseTabStripController>()); - top_container_->AddChildView(tab_strip_region_view); - tab_strip_region_view->AddChildView(tab_strip_); - webui_tab_strip_ = CreateFixedSizeView(gfx::Size(800, 200)); + top_container_ = + root_view_->AddChildView(CreateFixedSizeView(gfx::Size(800, 60))); + views::View* tab_strip_region_view = + top_container_->AddChildView(std::make_unique<TabStripRegionView>()); + tab_strip_ = tab_strip_region_view->AddChildView(std::make_unique<TabStrip>( + std::make_unique<FakeBaseTabStripController>())); + webui_tab_strip_ = + top_container_->AddChildView(CreateFixedSizeView(gfx::Size(800, 200))); webui_tab_strip_->SetVisible(false); - top_container_->AddChildView(webui_tab_strip_); - toolbar_ = CreateFixedSizeView(gfx::Size(800, kToolbarHeight)); - top_container_->AddChildView(toolbar_); + toolbar_ = top_container_->AddChildView( + CreateFixedSizeView(gfx::Size(800, kToolbarHeight))); separator_ = top_container_->AddChildView(std::make_unique<views::Separator>()); - root_view_->AddChildView(top_container_); - infobar_container_ = new InfoBarContainerView(nullptr); - root_view_->AddChildView(infobar_container_); + infobar_container_ = root_view_->AddChildView( + std::make_unique<InfoBarContainerView>(nullptr)); - contents_web_view_ = CreateFixedSizeView(gfx::Size(800, 600)); - devtools_web_view_ = CreateFixedSizeView(gfx::Size(800, 600)); + contents_container_ = + root_view_->AddChildView(CreateFixedSizeView(gfx::Size(800, 600))); + devtools_web_view_ = contents_container_->AddChildView( + CreateFixedSizeView(gfx::Size(800, 600))); devtools_web_view_->SetVisible(false); - - contents_container_ = CreateFixedSizeView(gfx::Size(800, 600)); - contents_container_->AddChildView(devtools_web_view_); - contents_container_->AddChildView(contents_web_view_); + contents_web_view_ = contents_container_->AddChildView( + CreateFixedSizeView(gfx::Size(800, 600))); contents_container_->SetLayoutManager( std::make_unique<ContentsLayoutManager>(devtools_web_view_, contents_web_view_)); - root_view_->AddChildView(contents_container_); - // TODO(jamescook): Attach |layout_| to |root_view_|? - delegate_ = new MockBrowserViewLayoutDelegate(); + auto delegate = std::make_unique<MockBrowserViewLayoutDelegate>(); + delegate_ = delegate.get(); layout_ = std::make_unique<BrowserViewLayout>( - std::unique_ptr<BrowserViewLayoutDelegate>(delegate_), + std::move(delegate), nullptr, // NativeView. nullptr, // BrowserView. top_container_, tab_strip_region_view, tab_strip_, toolbar_, @@ -284,21 +277,21 @@ } TEST_F(BrowserViewLayoutTest, LayoutDownloadShelf) { - std::unique_ptr<views::View> download_shelf( - CreateFixedSizeView(gfx::Size(800, 50))); + constexpr int kHeight = 50; + std::unique_ptr<views::View> download_shelf = + CreateFixedSizeView(gfx::Size(800, kHeight)); layout()->set_download_shelf(download_shelf.get()); - // If download shelf doesn't need layout, it doesn't move the bottom edge. - delegate()->set_download_shelf_needs_layout(false); - const int kBottom = 500; + // If the download shelf isn't visible, it doesn't move the bottom edge. + download_shelf->SetVisible(false); + constexpr int kBottom = 500; EXPECT_EQ(kBottom, layout()->LayoutDownloadShelf(kBottom)); - // Download shelf layout moves up the bottom edge and sets visibility. - delegate()->set_download_shelf_needs_layout(true); - download_shelf->SetVisible(false); - EXPECT_EQ(450, layout()->LayoutDownloadShelf(kBottom)); - EXPECT_TRUE(download_shelf->GetVisible()); - EXPECT_EQ(gfx::Rect(0, 450, 0, 50), download_shelf->bounds()); + // A visible download shelf moves the bottom edge up. + download_shelf->SetVisible(true); + constexpr int kTop = kBottom - kHeight; + EXPECT_EQ(kTop, layout()->LayoutDownloadShelf(kBottom)); + EXPECT_EQ(gfx::Rect(0, kTop, 0, kHeight), download_shelf->bounds()); } TEST_F(BrowserViewLayoutTest, LayoutContentsWithTopControlsSlideBehavior) {
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 index 1799598..a9625eda 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -390,6 +390,10 @@ title_label_->SetVerticalAlignment(gfx::ALIGN_TOP); title_label_->SetMultiLine(true); title_label_->SetMaxLines(kTitleMaxLines); + title_label_->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred, + views::MaximumFlexSizeRule::kPreferred, true)); title_fade_label_ = AddChildView(std::make_unique<FadeLabel>( base::string16(), CONTEXT_TAB_HOVER_CARD_TITLE, @@ -441,11 +445,6 @@ views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum, views::MaximumFlexSizeRule::kPreferred)); domain_label_->SetVisible(tab->controller()->ShowDomainInHoverCard(tab)); - if (preview_image_) { - // Always want a nonzero margin above the preview image if present. - preview_image_->SetProperty( - views::kMarginsKey, gfx::Insets(kVerticalMargin, kHorizontalMargin)); - } widget_ = views::BubbleDialogDelegateView::CreateBubble(this); set_adjust_if_offscreen(true);
diff --git a/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc b/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc index 3e05aa8..0da4836 100644 --- a/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc +++ b/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
@@ -214,7 +214,7 @@ void UpdateColors(); void MaybeStartThrobber(TabStripModel* tab_strip_model, const TabStripModelChange& change); - void MaybeStopThrobber(); + void StopThrobber(); void Init(); // views::Button: @@ -323,27 +323,29 @@ const auto& contents = change.GetInsert()->contents; if (contents.size() > 1 || tab_strip_model->GetActiveWebContents() != contents[0].contents) { - throbber_->Start(); + // If the throbber is already showing, just reset the timer so that the + // animation continues smoothly for tabs created in quick succession. + if (throbber_timer_.IsRunning()) { + throbber_timer_.Reset(); + } else { + throbber_->Start(); - // Automatically stop the throbber after 1 second. Currently we do not - // check the real loading state of the new tab(s), as that adds - // unnecessary complexity. The purpose of the throbber is just to indicate - // to the user that some activity has happened in the background, which - // may not otherwise have been obvious because the tab strip is hidden in - // this mode. - throbber_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(1000), - this, &WebUITabCounterButton::MaybeStopThrobber); + // Automatically stop the throbber after 1 second. Currently we do not + // check the real loading state of the new tab(s), as that adds + // unnecessary complexity. The purpose of the throbber is just to + // indicate to the user that some activity has happened in the + // background, which may not otherwise have been obvious because the tab + // strip is hidden in this mode. + throbber_timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(1000), this, + &WebUITabCounterButton::StopThrobber); + } } } } -void WebUITabCounterButton::MaybeStopThrobber() { - // Stop the throbber if no other background tabs have been created. Otherwise, - // reset the timer to keep the throbber running smoothly. - if (throbber_timer_.IsRunning()) - throbber_timer_.Reset(); - else - throbber_->Stop(); +void WebUITabCounterButton::StopThrobber() { + throbber_->Stop(); } void WebUITabCounterButton::Init() {
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index 5391a38..2ea62e956 100644 --- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -406,3 +406,10 @@ NoTrustedTypesViolationInWebrtcInternals) { CheckTrustedTypesViolation("chrome://webrtc-internals"); } + +// Verify that there's no Trusted Types violation in chrome://crashes +IN_PROC_BROWSER_TEST_F( + ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, + NoTrustedTypesViolationInCrashes) { + CheckTrustedTypesViolation("chrome://crashes"); +}
diff --git a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc index 2e83bfb..8d99eb5 100644 --- a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
@@ -111,6 +111,8 @@ builder); // SplitSettingsSync strings. + RememberLocalizedValue("syncConsentScreenSubtitle", + IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE, builder); RememberLocalizedValue("syncConsentScreenOsSyncName", IDS_LOGIN_SYNC_CONSENT_SCREEN_OS_SYNC_NAME, builder); RememberLocalizedValue("syncConsentScreenOsSyncDescription", @@ -119,6 +121,10 @@ RememberLocalizedValue("syncConsentScreenChromeBrowserSyncName", IDS_LOGIN_SYNC_CONSENT_SCREEN_CHROME_BROWSER_SYNC_NAME, builder); + RememberLocalizedValue("syncConsentScreenAccept", + IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT, builder); + RememberLocalizedValue("syncConsentScreenDecline", + IDS_LOGIN_SYNC_CONSENT_SCREEN_DECLINE, builder); } void SyncConsentScreenHandler::Bind(SyncConsentScreen* screen) { @@ -127,10 +133,10 @@ } void SyncConsentScreenHandler::Show() { - bool is_child_account_ = - user_manager::UserManager::Get()->IsLoggedInAsChildUser(); + auto* user_manager = user_manager::UserManager::Get(); base::DictionaryValue data; - data.SetBoolean("isChildAccount", is_child_account_); + data.SetBoolean("isChildAccount", user_manager->IsLoggedInAsChildUser()); + data.SetString("userEmail", user_manager->GetActiveUser()->GetDisplayEmail()); ShowScreenWithData(kScreenId, &data); } @@ -149,6 +155,8 @@ &SyncConsentScreenHandler::HandleContinueWithDefaults); AddCallback("login.SyncConsentScreen.acceptAndContinue", &SyncConsentScreenHandler::HandleAcceptAndContinue); + AddCallback("login.SyncConsentScreen.declineAndContinue", + &SyncConsentScreenHandler::HandleDeclineAndContinue); } void SyncConsentScreenHandler::GetAdditionalParameters( @@ -198,16 +206,30 @@ void SyncConsentScreenHandler::HandleAcceptAndContinue( const login::StringList& consent_description, + const std::string& consent_confirmation) { + Continue(consent_description, consent_confirmation, /*enable_sync=*/true); +} + +void SyncConsentScreenHandler::HandleDeclineAndContinue( + const login::StringList& consent_description, + const std::string& consent_confirmation) { + Continue(consent_description, consent_confirmation, /*enable_sync=*/false); +} + +void SyncConsentScreenHandler::Continue( + const login::StringList& consent_description, const std::string& consent_confirmation, - bool enable_os_sync, - bool enable_browser_sync) { + bool enable_sync) { DCHECK(chromeos::features::IsSplitSettingsSyncEnabled()); std::vector<int> consent_description_ids; int consent_confirmation_id; GetConsentIDs(known_string_ids_, consent_description, consent_confirmation, &consent_description_ids, &consent_confirmation_id); + // Manually add this ID because the string contains a runtime substitution, + // so it's not included in GetConsentIDs(). + consent_description_ids.push_back(IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE); screen_->OnAcceptAndContinue(consent_description_ids, consent_confirmation_id, - enable_os_sync, enable_browser_sync); + enable_sync); SyncConsentScreen::SyncConsentScreenTestDelegate* test_delegate = screen_->GetDelegateForTesting();
diff --git a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h index af58bff..dfb8a054 100644 --- a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h
@@ -67,10 +67,17 @@ void HandleContinueWithDefaults( const ::login::StringList& consent_description, const std::string& consent_confirmation); + + // WebUI message handlers for SplitSettingsSync. void HandleAcceptAndContinue(const ::login::StringList& consent_description, - const std::string& consent_confirmation, - bool enable_os_sync, - bool enable_browser_sync); + const std::string& consent_confirmation); + void HandleDeclineAndContinue(const ::login::StringList& consent_description, + const std::string& consent_confirmation); + + // Helper for the accept and decline cases. + void Continue(const ::login::StringList& consent_description, + const std::string& consent_confirmation, + bool enable_sync); // Adds resource |resource_id| both to |builder| and to |known_string_ids_|. void RememberLocalizedValue(const std::string& name,
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom index 3ce9a17e..9d0c643 100644 --- a/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom +++ b/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
@@ -91,12 +91,18 @@ kStylusLatestNoteOnLockScreen = 419, kDisplayOrientation = 420, kDisplayArrangement = 421, - kPowerIdleBehavior = 422, + kPowerIdleBehaviorWhileCharging = 422, kPowerSource = 423, kSleepWhenLaptopLidClosed = 424, kDisplayResolution = 425, kDisplayRefreshRate = 426, kRemoveDlc = 427, + kDisplayMirroring = 428, + kAllowWindowsToSpanDisplays = 429, + kAmbientColors = 430, + kTouchscreenCalibration = 431, + kNightLightColorTemperature = 432, + kPowerIdleBehaviorWhileOnBattery = 433, // Personalization section. kOpenWallpaper = 500,
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_section.cc b/chrome/browser/ui/webui/settings/chromeos/device_section.cc index 1385cb8..60a36a19 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_section.cc
@@ -121,13 +121,22 @@ mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kKeyboardFunctionKeys}}, - {IDS_OS_SETTINGS_TAG_POWER_IDLE, + {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_CHARGING, mojom::kPowerSubpagePath, mojom::SearchResultIcon::kPower, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kPowerIdleBehavior}, - {IDS_OS_SETTINGS_TAG_POWER_IDLE_ALT1, SearchConcept::kAltTagEnd}}, + {.setting = mojom::Setting::kPowerIdleBehaviorWhileCharging}, + {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_CHARGING_ALT1, + SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_ON_BATTERY, + mojom::kPowerSubpagePath, + mojom::SearchResultIcon::kPower, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kPowerIdleBehaviorWhileOnBattery}, + {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_ON_BATTERY_ALT1, + SearchConcept::kAltTagEnd}}, }); return *tags; } @@ -281,36 +290,30 @@ const std::vector<SearchConcept>& GetDisplayMirrorSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display mirror" search concepts. + {IDS_OS_SETTINGS_TAG_MIRRORING, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDisplayMirroring}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayUnifiedDesktopSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display with Unified Desktop" search concepts. - }); - return *tags; -} - -const std::vector<SearchConcept>& GetDisplayMultipleSearchConcepts() { - static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display multiple" search concepts. + {IDS_OS_SETTINGS_TAG_UNIFIED_DESKTOP, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kAllowWindowsToSpanDisplays}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayExternalSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION, - mojom::kDisplaySubpagePath, - mojom::SearchResultIcon::kDisplay, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kDisplayOrientation}, - {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT1, - IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT2, - SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION, mojom::kDisplaySubpagePath, mojom::SearchResultIcon::kDisplay, @@ -342,28 +345,50 @@ const std::vector<SearchConcept>& GetDisplayOrientationSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display orientation" search concepts. + {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDisplayOrientation}, + {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT1, + SearchConcept::kAltTagEnd}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayAmbientSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display ambient" search concepts. + {IDS_OS_SETTINGS_TAG_DISPLAY_AMBIENT_COLORS, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kAmbientColors}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayTouchCalibrationSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display touch calibration" search concepts. + {IDS_OS_SETTINGS_TAG_DISPLAY_TOUCHSCREEN_CALIBRATION, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kTouchscreenCalibration}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayNightLightOnSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display Night Light on" search concepts. + {IDS_OS_SETTINGS_TAG_NIGHT_LIGHT_COLOR_TEMPERATURE, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kNightLightColorTemperature}}, }); return *tags; } @@ -904,9 +929,17 @@ mojom::SearchResultIcon::kDisplay, mojom::SearchResultDefaultRank::kMedium, mojom::kDisplaySubpagePath); static constexpr mojom::Setting kDisplaySettings[] = { - mojom::Setting::kDisplaySize, mojom::Setting::kNightLight, - mojom::Setting::kDisplayOrientation, mojom::Setting::kDisplayArrangement, - mojom::Setting::kDisplayResolution, mojom::Setting::kDisplayRefreshRate, + mojom::Setting::kDisplaySize, + mojom::Setting::kNightLight, + mojom::Setting::kDisplayOrientation, + mojom::Setting::kDisplayArrangement, + mojom::Setting::kDisplayResolution, + mojom::Setting::kDisplayRefreshRate, + mojom::Setting::kDisplayMirroring, + mojom::Setting::kAllowWindowsToSpanDisplays, + mojom::Setting::kAmbientColors, + mojom::Setting::kTouchscreenCalibration, + mojom::Setting::kNightLightColorTemperature, }; RegisterNestedSettingBulk(mojom::Subpage::kDisplay, kDisplaySettings, generator); @@ -934,7 +967,8 @@ mojom::SearchResultIcon::kPower, mojom::SearchResultDefaultRank::kMedium, mojom::kPowerSubpagePath); static constexpr mojom::Setting kPowerSettings[] = { - mojom::Setting::kPowerIdleBehavior, + mojom::Setting::kPowerIdleBehaviorWhileCharging, + mojom::Setting::kPowerIdleBehaviorWhileOnBattery, mojom::Setting::kPowerSource, mojom::Setting::kSleepWhenLaptopLidClosed, }; @@ -1043,12 +1077,6 @@ registry()->RemoveSearchTags(GetDisplayUnifiedDesktopSearchConcepts()); } - // Multiple displays UI. - if (has_multiple_displays) - registry()->AddSearchTags(GetDisplayMultipleSearchConcepts()); - else - registry()->RemoveSearchTags(GetDisplayMultipleSearchConcepts()); - // External display settings. if (has_external_display) registry()->AddSearchTags(GetDisplayExternalSearchConcepts());
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_section.cc b/chrome/browser/ui/webui/settings/chromeos/internet_section.cc index f0cfa28..1b06d0d5 100644 --- a/chrome/browser/ui/webui/settings/chromeos/internet_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/internet_section.cc
@@ -485,6 +485,7 @@ {"internetConfigName", IDS_SETTINGS_INTERNET_CONFIG_NAME}, {"internetDetailPageTitle", IDS_SETTINGS_INTERNET_DETAIL}, {"internetDeviceEnabling", IDS_SETTINGS_INTERNET_DEVICE_ENABLING}, + {"internetDeviceDisabling", IDS_SETTINGS_INTERNET_DEVICE_DISABLING}, {"internetDeviceInitializing", IDS_SETTINGS_INTERNET_DEVICE_INITIALIZING}, {"internetJoinType", IDS_SETTINGS_INTERNET_JOIN_TYPE}, {"internetKnownNetworksPageTitle", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS},
diff --git a/chrome/browser/ui/webui/settings/chromeos/people_section.cc b/chrome/browser/ui/webui/settings/chromeos/people_section.cc index bab56c2..dd3fe2f 100644 --- a/chrome/browser/ui/webui/settings/chromeos/people_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/people_section.cc
@@ -68,7 +68,9 @@ mojom::SearchResultIcon::kLock, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kChangeAuthPin}}, + {.setting = mojom::Setting::kChangeAuthPin}, + {IDS_OS_SETTINGS_TAG_LOCK_SCREEN_PIN_OR_PASSWORD_ALT1, + SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_USERNAMES_AND_PHOTOS, mojom::kManageOtherPeopleSubpagePath, mojom::SearchResultIcon::kAvatar,
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc index ed8186be..22713f6 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/signin/login_ui_test_utils.h" #include "base/bind.h" +#include "base/notreached.h" #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/strings/stringprintf.h" @@ -192,6 +193,8 @@ enum class SyncConfirmationDialogAction { kConfirm, kCancel }; +enum class ReauthDialogAction { kConfirm, kCancel }; + #if !defined(OS_CHROMEOS) std::string GetButtonIdForSyncConfirmationDialogAction( SyncConfirmationDialogAction action) { @@ -225,6 +228,16 @@ } } +std::string GetButtonIdForReauthConfirmationDialogAction( + ReauthDialogAction action) { + switch (action) { + case ReauthDialogAction::kConfirm: + return "confirmButton"; + case ReauthDialogAction::kCancel: + return "cancelButton"; + } +} + std::string GetButtonSelectorForApp(const std::string& app, const std::string& button_id) { return base::StringPrintf( @@ -332,11 +345,41 @@ content::WebContents* dialog_web_contents = signin_view_controller->GetModalDialogWebContentsForTesting(); DCHECK(dialog_web_contents); - const std::string button_selector = - GetButtonSelectorForApp("signin-reauth-app", "confirmButton"); + const std::string button_selector = GetButtonSelectorForApp( + "signin-reauth-app", GetButtonIdForReauthConfirmationDialogAction( + ReauthDialogAction::kConfirm)); return IsElementReady(dialog_web_contents, button_selector); #endif } + + static bool TryCompleteReauthConfirmationDialog(Browser* browser, + ReauthDialogAction action) { +#if defined(OS_CHROMEOS) + NOTREACHED(); + return false; +#else + SigninViewController* signin_view_controller = + browser->signin_view_controller(); + DCHECK(signin_view_controller); + if (!signin_view_controller->ShowsModalDialog()) + return false; + + content::WebContents* dialog_web_contents = + signin_view_controller->GetModalDialogWebContentsForTesting(); + DCHECK(dialog_web_contents); + std::string button_selector = GetButtonSelectorForApp( + "signin-reauth-app", + GetButtonIdForReauthConfirmationDialogAction(action)); + if (!IsElementReady(dialog_web_contents, button_selector)) + return false; + + // This cannot be a synchronous call, because it closes the window as a side + // effect, which may cause the javascript execution to never finish. + content::ExecuteScriptAsync(dialog_web_contents, + button_selector + ".click();"); + return true; +#endif + } }; void WaitUntilUIReady(Browser* browser) { @@ -491,4 +534,28 @@ "Could not find reauth confirm button"); } +bool CompleteReauthConfirmationDialog(Browser* browser, + base::TimeDelta timeout, + ReauthDialogAction action) { + const base::Time expire_time = base::Time::Now() + timeout; + while (base::Time::Now() <= expire_time) { + if (SigninViewControllerTestUtil::TryCompleteReauthConfirmationDialog( + browser, action)) + return true; + RunLoopFor(base::TimeDelta::FromMilliseconds(1000)); + } + return false; +} + +bool ConfirmReauthConfirmationDialog(Browser* browser, + base::TimeDelta timeout) { + return CompleteReauthConfirmationDialog(browser, timeout, + ReauthDialogAction::kConfirm); +} + +bool CancelReauthConfirmationDialog(Browser* browser, base::TimeDelta timeout) { + return CompleteReauthConfirmationDialog(browser, timeout, + ReauthDialogAction::kCancel); +} + } // namespace login_ui_test_utils
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.h b/chrome/browser/ui/webui/signin/login_ui_test_utils.h index f57e8ba..1e91ad7f 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.h +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.h
@@ -63,6 +63,16 @@ // Waits for the reauth confirmation dialog to get displayed. void WaitUntilReauthUIIsReady(Browser* browser); +// Waits for the reauth confirmation dialog to get displayed, then executes +// javascript to click on confirm button. Returns false if dialog wasn't +// dismissed before |timeout|. +bool ConfirmReauthConfirmationDialog(Browser* browser, base::TimeDelta timeout); + +// Waits for the reauth confirmation dialog to get displayed, then executes +// javascript to click on cancel button. Returns false if dialog wasn't +// dismissed before |timeout|. +bool CancelReauthConfirmationDialog(Browser* browser, base::TimeDelta timeout); + } // namespace login_ui_test_utils #endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_LOGIN_UI_TEST_UTILS_H_
diff --git a/chrome/browser/ui/webui/signin/signin_reauth_handler.cc b/chrome/browser/ui/webui/signin/signin_reauth_handler.cc index fc037ca5..229169f 100644 --- a/chrome/browser/ui/webui/signin/signin_reauth_handler.cc +++ b/chrome/browser/ui/webui/signin/signin_reauth_handler.cc
@@ -29,5 +29,5 @@ } void SigninReauthHandler::HandleCancel(const base::ListValue* args) { - browser_->signin_view_controller()->CloseModalSignin(); + browser_->signin_view_controller()->OnReauthDismissed(); }
diff --git a/chrome/browser/virtual_keyboard_policy_uitest_win.cc b/chrome/browser/virtual_keyboard_policy_uitest_win.cc index 35580c8..63f1b45 100644 --- a/chrome/browser/virtual_keyboard_policy_uitest_win.cc +++ b/chrome/browser/virtual_keyboard_policy_uitest_win.cc
@@ -7,7 +7,6 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/post_task.h" #include "base/win/windows_version.h" #include "build/build_config.h" #include "chrome/browser/ui/browser.h" @@ -61,7 +60,7 @@ void OnSuccess() { success_ = true; - base::PostTask(FROM_HERE, run_loop.QuitClosure()); + run_loop.Quit(); // By deleting |tester_| we make sure that the internal observer used in // content/ is removed from the observer list of TextInputManager.
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index fa10cb4..902cf5e 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1591170216-219e7bf40eeb405c9bdb366afea32eceddcbc16f.profdata +chrome-mac-master-1591199990-53a8f554cee1144b8cf9ac7f99b06fbe1ec5521a.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 8aa61ce..d0b4a75 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1591142315-92a136d405d944eb0ad6a14d1cc0d834f3d533a1.profdata +chrome-win64-master-1591184865-5178b7a96ecfc255ba5ba33ed0277fd9a93edec8.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 25f5f64..f157249f 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -139,7 +139,6 @@ "pref_names_util.cc", "pref_names_util.h", "prerender_messages.h", - "prerender_types.h", "prerender_url_loader_throttle.cc", "prerender_url_loader_throttle.h", "prerender_util.cc", @@ -263,6 +262,7 @@ "//components/google/core/common", "//components/metrics:call_stack_profile_builder", "//components/page_load_metrics/common:common", + "//components/prerender", ] if (enable_plugins) {
diff --git a/chrome/common/DEPS b/chrome/common/DEPS index 7073404c..2c35b3b 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS
@@ -34,6 +34,7 @@ "+components/password_manager/core/common", "+components/policy/core/common", "+components/prefs", + "+components/prerender", "+components/printing/common", "+components/safe_browsing/buildflags.h", "+components/safe_browsing/core/proto/csd.pb.h",
diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl index b8029a0..2a58e11 100644 --- a/chrome/common/extensions/api/developer_private.idl +++ b/chrome/common/extensions/api/developer_private.idl
@@ -162,8 +162,7 @@ }; enum ControllerType { - POLICY, - SUPERVISED_USER_CUSTODIAN + POLICY }; enum HostAccess {
diff --git a/chrome/common/prerender_messages.h b/chrome/common/prerender_messages.h index a6e9000..2d22e25 100644 --- a/chrome/common/prerender_messages.h +++ b/chrome/common/prerender_messages.h
@@ -5,7 +5,7 @@ #ifndef CHROME_COMMON_PRERENDER_MESSAGES_H_ #define CHROME_COMMON_PRERENDER_MESSAGES_H_ -#include "chrome/common/prerender_types.h" +#include "components/prerender/prerender_types.h" #include "ipc/ipc_message.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_param_traits.h"
diff --git a/chrome/common/prerender_url_loader_throttle.h b/chrome/common/prerender_url_loader_throttle.h index c76ad12..b238e4b 100644 --- a/chrome/common/prerender_url_loader_throttle.h +++ b/chrome/common/prerender_url_loader_throttle.h
@@ -11,7 +11,7 @@ #include "base/sequenced_task_runner.h" #include "base/timer/timer.h" #include "chrome/common/prerender_canceler.mojom.h" -#include "chrome/common/prerender_types.h" +#include "components/prerender/prerender_types.h" #include "net/base/request_priority.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
diff --git a/chrome/common/prerender_util.h b/chrome/common/prerender_util.h index 4fa1436..9b2d00e 100644 --- a/chrome/common/prerender_util.h +++ b/chrome/common/prerender_util.h
@@ -7,7 +7,7 @@ #include <string> -#include "chrome/common/prerender_types.h" +#include "components/prerender/prerender_types.h" class GURL;
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS index b0736240..76e46eb 100644 --- a/chrome/renderer/DEPS +++ b/chrome/renderer/DEPS
@@ -34,6 +34,7 @@ "+components/password_manager/core/common", "+components/pdf/renderer", "+components/plugins/renderer", + "+components/prerender", "+components/printing/common", "+components/printing/renderer", "+components/rappor/public/mojom",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 86c0ba4..51f7952 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -34,7 +34,6 @@ #include "chrome/common/crash_keys.h" #include "chrome/common/pdf_util.h" #include "chrome/common/pepper_permission_util.h" -#include "chrome/common/prerender_types.h" #include "chrome/common/prerender_url_loader_throttle.h" #include "chrome/common/profiler/thread_profiler.h" #include "chrome/common/render_messages.h" @@ -87,6 +86,7 @@ #include "components/page_load_metrics/renderer/metrics_render_frame_observer.h" #include "components/paint_preview/buildflags/buildflags.h" #include "components/pdf/renderer/pepper_pdf_host.h" +#include "components/prerender/prerender_types.h" #include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/content/renderer/threat_dom_details.h" #include "components/spellcheck/spellcheck_buildflags.h"
diff --git a/chrome/renderer/chrome_render_frame_observer.h b/chrome/renderer/chrome_render_frame_observer.h index a7257c75..cf3c336 100644 --- a/chrome/renderer/chrome_render_frame_observer.h +++ b/chrome/renderer/chrome_render_frame_observer.h
@@ -12,7 +12,7 @@ #include "base/timer/timer.h" #include "build/build_config.h" #include "chrome/common/chrome_render_frame.mojom.h" -#include "chrome/common/prerender_types.h" +#include "components/prerender/prerender_types.h" #include "components/safe_browsing/buildflags.h" #include "content/public/renderer/render_frame_observer.h" #include "mojo/public/cpp/bindings/associated_receiver_set.h"
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.h b/chrome/renderer/plugins/chrome_plugin_placeholder.h index 738a37a..a01632cc 100644 --- a/chrome/renderer/plugins/chrome_plugin_placeholder.h +++ b/chrome/renderer/plugins/chrome_plugin_placeholder.h
@@ -11,9 +11,9 @@ #include "base/macros.h" #include "chrome/common/buildflags.h" #include "chrome/common/plugin.mojom.h" -#include "chrome/common/prerender_types.h" #include "chrome/renderer/plugins/power_saver_info.h" #include "components/plugins/renderer/loadable_plugin_placeholder.h" +#include "components/prerender/prerender_types.h" #include "content/public/renderer/context_menu_client.h" #include "content/public/renderer/render_thread_observer.h" #include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chrome/renderer/prerender/prerender_helper.h b/chrome/renderer/prerender/prerender_helper.h index 6bd8cbc..2d9ebe65 100644 --- a/chrome/renderer/prerender/prerender_helper.h +++ b/chrome/renderer/prerender/prerender_helper.h
@@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "chrome/common/prerender_types.h" +#include "components/prerender/prerender_types.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 4cb9aa1..4f4c508 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1545,6 +1545,7 @@ sources += [ "../browser/external_protocol/external_protocol_handler_browsertest.cc", "../browser/lifetime/application_lifetime_browsertest.cc", + "../browser/ui/signin_reauth_view_controller_browsertest.cc", ] }
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index e4fce678..443c1ce 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -222,6 +222,7 @@ "javatests/src/org/chromium/chrome/test/util/browser/contextmenu/ContextMenuUtils.java", "javatests/src/org/chromium/chrome/test/util/browser/contextmenu/RevampedContextMenuUtils.java", "javatests/src/org/chromium/chrome/test/util/browser/offlinepages/FakeOfflinePageBridge.java", + "javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java", "javatests/src/org/chromium/chrome/test/util/browser/signin/MockChangeEventChecker.java", "javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java", "javatests/src/org/chromium/chrome/test/util/browser/suggestions/SuggestionsDependenciesRule.java",
diff --git a/chrome/test/android/DEPS b/chrome/test/android/DEPS index 203da726..00e27e3 100644 --- a/chrome/test/android/DEPS +++ b/chrome/test/android/DEPS
@@ -5,5 +5,6 @@ "+components/sync/android/java/src/org/chromium/components/sync/signin", "+components/sync/test/android/javatests/src/org/chromium/components/sync/test/util", "+components/signin/core/browser/android/java/src/org/chromium/components/signin", + "+components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util", ]
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java similarity index 92% rename from components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java rename to chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java index ad2eece..df15c95 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.components.signin.test.util; +package org.chromium.chrome.test.util.browser.signin; import android.accounts.Account; @@ -15,6 +15,8 @@ import org.chromium.components.signin.AccountManagerFacadeProvider; import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ProfileDataSource; +import org.chromium.components.signin.test.util.FakeAccountManagerFacade; +import org.chromium.components.signin.test.util.FakeProfileDataSource; /** * JUnit4 rule for overriding behaviour of {@link AccountManagerFacade} for tests.
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc index 65cf981..1a6ee9a 100644 --- a/chrome/test/chromedriver/commands.cc +++ b/chrome/test/chromedriver/commands.cc
@@ -128,7 +128,7 @@ return; } - base::RunLoop run_loop; + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); for (auto iter = session_thread_map->begin(); iter != session_thread_map->end(); ++iter) { @@ -142,7 +142,6 @@ } base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(10)); - base::MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); run_loop.Run(); callback.Run(Status(kOk), std::move(session_list), session_id, false); @@ -180,7 +179,7 @@ session_id, false); return; } - base::RunLoop run_loop; + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); for (auto iter = session_thread_map->begin(); iter != session_thread_map->end(); ++iter) { quit_command.Run(params, @@ -193,7 +192,6 @@ FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(10)); // Uses a nested run loop to block this thread until all the quit // commands have executed, or the timeout expires. - base::MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); run_loop.Run(); callback.Run(Status(kOk), std::unique_ptr<base::Value>(), session_id, false);
diff --git a/chrome/test/data/extensions/api_test/autofill_private/test.js b/chrome/test/data/extensions/api_test/autofill_private/test.js index 50ba8b3..4a26385 100644 --- a/chrome/test/data/extensions/api_test/autofill_private/test.js +++ b/chrome/test/data/extensions/api_test/autofill_private/test.js
@@ -185,8 +185,8 @@ function filterCardProperties(cards) { return cards.map(cards => { var filteredCards = {}; - ['name', 'cardNumber', 'expirationMonth', 'expirationYear'].forEach( - property => { + ['name', 'cardNumber', 'expirationMonth', 'expirationYear', 'nickname'] + .forEach(property => { filteredCards[property] = cards[property]; }); return filteredCards; @@ -206,7 +206,8 @@ name: CARD_NAME, cardNumber: NUMBER, expirationMonth: EXP_MONTH, - expirationYear: EXP_YEAR + expirationYear: EXP_YEAR, + nickname: undefined }], filterCardProperties(cardList)); })); @@ -223,11 +224,13 @@ function updateExistingCreditCard() { var UPDATED_CARD_NAME = 'UpdatedCardName'; var UPDATED_EXP_YEAR = '2888'; + var UPDATED_NICKNAME = 'New nickname'; function filterCardProperties(cards) { return cards.map(cards => { var filteredCards = {}; - ['guid', 'name', 'cardNumber', 'expirationMonth', 'expirationYear'] + ['guid', 'name', 'cardNumber', 'expirationMonth', 'expirationYear', + 'nickname'] .forEach(property => { filteredCards[property] = cards[property]; }); @@ -252,7 +255,8 @@ name: UPDATED_CARD_NAME, cardNumber: NUMBER, expirationMonth: EXP_MONTH, - expirationYear: UPDATED_EXP_YEAR + expirationYear: UPDATED_EXP_YEAR, + nickname: UPDATED_NICKNAME }], filterCardProperties(cardList)); })); @@ -262,7 +266,8 @@ chrome.autofillPrivate.saveCreditCard({ guid: cardGuid, name: UPDATED_CARD_NAME, - expirationYear: UPDATED_EXP_YEAR + expirationYear: UPDATED_EXP_YEAR, + nickname: UPDATED_NICKNAME }); })); },
diff --git a/chrome/test/data/webui/cr_elements/BUILD.gn b/chrome/test/data/webui/cr_elements/BUILD.gn index 664c4572..9aa25d8 100644 --- a/chrome/test/data/webui/cr_elements/BUILD.gn +++ b/chrome/test/data/webui/cr_elements/BUILD.gn
@@ -77,11 +77,11 @@ ":cr_radio_button_test.m", ":cr_radio_group_test.m", ":cr_scrollable_behavior_tests.m", + ":cr_search_field_tests.m", + ":cr_slider_test.m", + ":cr_splitter_test", + ":cr_tabs_test.m", - #":cr_search_field_tests", - #":cr_slider_test", - #":cr_splitter_test", - #":cr_tabs_test", #":cr_toast_manager_test", #":cr_toast_test", #":cr_toggle_test", @@ -374,3 +374,51 @@ externs_list = [ "$externs_path/mocha-2.5.js" ] extra_deps = [ ":modulize" ] } + +js_library("cr_search_field_tests.m") { + sources = [ "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_search_field_tests.m.js" ] + deps = [ + "..:chai_assert", + "..:test_util.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field.m", + ] + externs_list = [ "$externs_path/mocha-2.5.js" ] + extra_deps = [ ":modulize" ] +} + +js_library("cr_slider_test.m") { + sources = + [ "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_slider_test.m.js" ] + deps = [ + "..:chai_assert", + "..:test_util.m", + "//third_party/polymer/v3_0/components-chromium/iron-test-helpers:mock-interactions", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_slider:cr_slider.m", + ] + externs_list = [ "$externs_path/mocha-2.5.js" ] + extra_deps = [ ":modulize" ] +} + +js_library("cr_splitter_test") { + deps = [ + "..:chai_assert", + "//ui/webui/resources/cr_elements/cr_splitter:cr_splitter", + ] + externs_list = [ "$externs_path/mocha-2.5.js" ] +} + +js_library("cr_tabs_test.m") { + sources = + [ "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_tabs_test.m.js" ] + deps = [ + "..:chai_assert", + "..:test_util.m", + "//third_party/polymer/v3_0/components-chromium/iron-test-helpers:mock-interactions", + "//ui/webui/resources/cr_elements/cr_tabs:cr_tabs.m", + "//ui/webui/resources/js:util.m", + ] + externs_list = [ "$externs_path/mocha-2.5.js" ] + extra_deps = [ ":modulize" ] +}
diff --git a/chrome/test/data/webui/cr_elements/cr_search_field_tests.js b/chrome/test/data/webui/cr_elements/cr_search_field_tests.js index 82ca405..13e7fa7 100644 --- a/chrome/test/data/webui/cr_elements/cr_search_field_tests.js +++ b/chrome/test/data/webui/cr_elements/cr_search_field_tests.js
@@ -7,31 +7,33 @@ // // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; // #import {flushTasks} from '../test_util.m.js'; +// #import {assertEquals, assertDeepEquals, assertNotReached, assertFalse, assertNotEquals, assertTrue} from '../chai_assert.js'; // clang-format on /** @fileoverview Suite of tests for cr-search-field. */ suite('cr-search-field', function() { - /** @type {?CrSearchFieldElement} */ - let field = null; + /** @type {!CrSearchFieldElement} */ + let field; /** @type {?Array<string>} */ let searches = null; /** @param {string} term */ function simulateSearch(term) { - field.$.searchInput.value = term; + field.$$('#searchInput').value = term; field.onSearchTermInput(); field.onSearchTermSearch(); } setup(function() { - PolymerTest.clearBody(); + document.body.innerHTML = ''; // Ensure svg, which is referred to by a relative URL, is loaded from // chrome://resources and not chrome://test const base = document.createElement('base'); base.href = 'chrome://resources/cr_elements/'; document.head.appendChild(base); - field = document.createElement('cr-search-field'); + field = /** @type {!CrSearchFieldElement} */ ( + document.createElement('cr-search-field')); searches = []; field.addEventListener('search-changed', function(event) { searches.push(event.detail); @@ -40,8 +42,6 @@ }); teardown(function() { - field.remove(); - field = null; searches = null; }); @@ -70,7 +70,7 @@ field.$$('#clearSearch').click(); assertEquals('', field.getValue()); await test_util.flushTasks(); - assertEquals(field.$.searchInput, field.root.activeElement); + assertEquals(field.$$('#searchInput'), field.root.activeElement); assertFalse(field.hasSearchText); }); @@ -84,7 +84,7 @@ field.$$('#clearSearch').click(); assertEquals('', field.getValue()); await test_util.flushTasks(); - assertEquals(field.$.searchInput, field.root.activeElement); + assertEquals(field.$$('#searchInput'), field.root.activeElement); assertFalse(field.hasSearchText); });
diff --git a/chrome/test/data/webui/cr_elements/cr_slider_test.js b/chrome/test/data/webui/cr_elements/cr_slider_test.js index 9ee0da3..f69622e 100644 --- a/chrome/test/data/webui/cr_elements/cr_slider_test.js +++ b/chrome/test/data/webui/cr_elements/cr_slider_test.js
@@ -7,13 +7,14 @@ // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; // #import {flushTasks, eventToPromise} from '../test_util.m.js'; // #import {pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; +// #import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js'; // clang-format on suite('cr-slider', function() { + /** @type {!CrSliderElement} */ let crSlider; setup(function() { - PolymerTest.clearBody(); document.body.innerHTML = ` <style> #wrapper { @@ -25,7 +26,8 @@ </div> `; - crSlider = document.body.querySelector('cr-slider'); + crSlider = /** @type {!CrSliderElement} */ ( + document.body.querySelector('cr-slider')); crSlider.value = 0; return test_util.flushTasks(); }); @@ -72,7 +74,7 @@ } function pointerEvent(eventType, ratio) { - const rect = crSlider.$.container.getBoundingClientRect(); + const rect = crSlider.$$('#container').getBoundingClientRect(); crSlider.dispatchEvent(new PointerEvent(eventType, { buttons: 1, pointerId: 1, @@ -140,11 +142,12 @@ }); test('mouse events', () => { + assertFalse(crSlider.dragging); pointerMove(.25); assertEquals(0, crSlider.value); pointerDown(.5); + assertTrue(crSlider.dragging); assertEquals(50, crSlider.value); - assertEquals(5, crSlider.draggingEventTracker_.listeners_.length); pointerMove(.75); assertEquals(75, crSlider.value); pointerMove(-1); @@ -153,7 +156,7 @@ assertEquals(100, crSlider.value); pointerUp(); assertEquals(100, crSlider.value); - assertEquals(0, crSlider.draggingEventTracker_.listeners_.length); + assertFalse(crSlider.dragging); pointerMove(.25); assertEquals(100, crSlider.value); }); @@ -185,9 +188,9 @@ }); test('markers', () => { - assertTrue(crSlider.$.markers.hidden); + assertTrue(crSlider.$$('#markers').hidden); crSlider.markerCount = 10; - assertFalse(crSlider.$.markers.hidden); + assertFalse(crSlider.$$('#markers').hidden); Polymer.dom.flush(); const markers = Array.from(crSlider.root.querySelectorAll('#markers div')); assertEquals(9, markers.length); @@ -214,13 +217,13 @@ assertEquals('8', crSlider.getAttribute('aria-valuemax')); assertEquals('4', crSlider.getAttribute('aria-valuetext')); assertEquals('4', crSlider.getAttribute('aria-valuenow')); - assertEquals('', crSlider.$.label.innerHTML.trim()); + assertEquals('', crSlider.$$('#label').innerHTML.trim()); assertEquals(2, crSlider.value); pressArrowRight(); assertEquals(3, crSlider.value); assertEquals('8', crSlider.getAttribute('aria-valuetext')); assertEquals('8', crSlider.getAttribute('aria-valuenow')); - assertEquals('', crSlider.$.label.innerHTML.trim()); + assertEquals('', crSlider.$$('#label').innerHTML.trim()); crSlider.value = 2; crSlider.ticks = [ { @@ -241,12 +244,12 @@ assertEquals('1', crSlider.getAttribute('aria-valuemin')); assertEquals('3', crSlider.getAttribute('aria-valuemax')); assertEquals('Third', crSlider.getAttribute('aria-valuetext')); - assertEquals('Third', crSlider.$.label.innerHTML.trim()); + assertEquals('Third', crSlider.$$('#label').innerHTML.trim()); assertEquals('3', crSlider.getAttribute('aria-valuenow')); pressArrowLeft(); assertEquals('Second', crSlider.getAttribute('aria-valuetext')); assertEquals('20', crSlider.getAttribute('aria-valuenow')); - assertEquals('Second', crSlider.$.label.innerHTML.trim()); + assertEquals('Second', crSlider.$$('#label').innerHTML.trim()); }); test('disabled whenever public |disabled| is true', () => { @@ -324,22 +327,26 @@ const assertNoTransition = () => { const expected = 'all 0s ease 0s'; assertEquals( - expected, getComputedStyle(crSlider.$.knobAndLabel).transition); - assertEquals(expected, getComputedStyle(crSlider.$.bar).transition); + expected, getComputedStyle(crSlider.$$('#knobAndLabel')).transition); + assertEquals(expected, getComputedStyle(crSlider.$$('#bar')).transition); }; const assertTransition = () => { const getValue = propName => `${propName} 0.08s ease 0s`; assertEquals( getValue('margin-inline-start'), - getComputedStyle(crSlider.$.knobAndLabel).transition); + getComputedStyle(crSlider.$$('#knobAndLabel')).transition); assertEquals( - getValue('width'), getComputedStyle(crSlider.$.bar).transition); + getValue('width'), getComputedStyle(crSlider.$$('#bar')).transition); }; assertNoTransition(); pointerDown(.5); assertTransition(); - await test_util.eventToPromise('transitionend', crSlider.$.knobAndLabel); + + const knobAndLabel = + /** @type {!HTMLElement} */ (crSlider.$$('#knobAndLabel')); + + await test_util.eventToPromise('transitionend', knobAndLabel); assertNoTransition(); // Other operations that change the value do not have transitions. pointerMove(0); @@ -357,7 +364,7 @@ crSlider.value = 0; pointerDown(0); assertTransition(); - await test_util.eventToPromise('transitionend', crSlider.$.knobAndLabel); + await test_util.eventToPromise('transitionend', knobAndLabel); assertNoTransition(); }); @@ -402,9 +409,10 @@ test('container hidden until value set', () => { document.body.innerHTML = '<cr-slider></cr-slider>'; - crSlider = document.body.querySelector('cr-slider'); - assertTrue(crSlider.$.container.hidden); + crSlider = /** @type {!CrSliderElement} */ ( + document.body.querySelector('cr-slider')); + assertTrue(crSlider.$$('#container').hidden); crSlider.value = 0; - assertFalse(crSlider.$.container.hidden); + assertFalse(crSlider.$$('#container').hidden); }); });
diff --git a/chrome/test/data/webui/cr_elements/cr_splitter_test.js b/chrome/test/data/webui/cr_elements/cr_splitter_test.js index 7c8d7cd..21731d5 100644 --- a/chrome/test/data/webui/cr_elements/cr_splitter_test.js +++ b/chrome/test/data/webui/cr_elements/cr_splitter_test.js
@@ -4,18 +4,20 @@ import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.js'; +import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js'; + suite('cr-splitter', function() { + /** @type {!CrSplitterElement} */ let crSplitter; setup(function() { - PolymerTest.clearBody(); - document.body.innerHTML = ` <div id="previous"></div> <cr-splitter id="splitter"></cr-splitter> <div id="next"></div>`; - crSplitter = document.querySelector('#splitter'); + crSplitter = + /** @type {!CrSplitterElement} */ (document.querySelector('#splitter')); }); test('ignores right mouse', function() {
diff --git a/chrome/test/data/webui/cr_elements/cr_tabs_test.js b/chrome/test/data/webui/cr_elements/cr_tabs_test.js index 0ea7cb2..12cb8f6 100644 --- a/chrome/test/data/webui/cr_elements/cr_tabs_test.js +++ b/chrome/test/data/webui/cr_elements/cr_tabs_test.js
@@ -7,26 +7,28 @@ // #import {eventToPromise, flushTasks} from '../test_util.m.js'; // #import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; // #import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; +// #import {assertEquals, assertNotEquals, assertTrue} from '../chai_assert.js'; // clang-format on suite('cr_tabs_test', function() { - /** @type {?CrTabsElement} */ - let tabs = null; + /** @type {!CrTabsElement} */ + let tabs; setup(() => { - PolymerTest.clearBody(); - document.body.innerHTML = `<cr-tabs></cr-tabs>`; - tabs = document.querySelector('cr-tabs'); + document.body.innerHTML = ''; + tabs = /** @type {!CrTabsElement} */ (document.createElement('cr-tabs')); tabs.tabNames = ['tab1', 'tab2', 'tab3']; + document.body.appendChild(tabs); return test_util.flushTasks(); }); /** * @param {number} index - * @return {HTMLElement} + * @return {!HTMLElement} */ function getTabElement(index) { - return tabs.$$(`.tab:nth-of-type(${index + 1})`); + return /** @type {!HTMLElement} */ ( + tabs.$$(`.tab:nth-of-type(${index + 1})`)); } /** @@ -57,13 +59,13 @@ } /** - * @param {string} string + * @param {string} key * @param {number} initialSelection * @param {number} expectedSelection */ async function checkKey(key, initialSelection, expectedSelection) { await checkUiChange( - () => MockInteractions.keyDownOn(tabs, null, [], key), initialSelection, + () => MockInteractions.keyDownOn(tabs, 0, [], key), initialSelection, expectedSelection); } @@ -125,7 +127,7 @@ }); test('selection underline does not freeze with two tabs', async () => { - const underline = tabs.$.selectionBar; + const underline = tabs.$$('#selectionBar'); const fullyExpanded = 'translateX(0%) scaleX(1)'; tabs.tabNames = ['tab1', 'tab2']; assertEquals(undefined, tabs.selected);
diff --git a/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js b/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js index d2bc2b0..3c345985 100644 --- a/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js +++ b/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js
@@ -21,6 +21,7 @@ SelectedAfterUpDown: 'selected after keyboard press up and down', EnterOpensCloses: 'enter opens and closes dropdown', SelectedFollowsMouse: 'selected follows mouse', + Disabled: 'disabled', }; suite(destination_dropdown_cros_test.suiteName, function() { @@ -92,6 +93,7 @@ /** @type {!PrintPreviewDestinationDropdownCrosElement} */ (document.createElement('print-preview-destination-dropdown-cros')); document.body.appendChild(dropdown); + dropdown.noDestinations = false; }); test( @@ -103,7 +105,7 @@ ]); const itemList = getList(); - assertEquals(3, itemList.length); + assertEquals(7, itemList.length); assertEquals('One', itemList[0].textContent.trim()); assertEquals('Two', itemList[1].textContent.trim()); assertEquals('Three', itemList[2].textContent.trim()); @@ -155,30 +157,29 @@ test( assert(destination_dropdown_cros_test.TestNames.SelectedAfterUpDown), function() { - setItemList([ - createDestination('One'), createDestination('Two'), - createDestination('Three') - ]); + setItemList([createDestination('One')]); pointerDown(dropdown.$$('#dropdownInput')); down(); assertEquals('One', getSelectedElementText()); down(); - assertEquals('Two', getSelectedElementText()); + assertEquals('Save as PDF', getSelectedElementText()); down(); - assertEquals('Three', getSelectedElementText()); + assertEquals('Save to Google Drive', getSelectedElementText()); + down(); + assertEquals('See more…', getSelectedElementText()); down(); assertEquals('One', getSelectedElementText()); up(); - assertEquals('Three', getSelectedElementText()); + assertEquals('See more…', getSelectedElementText()); up(); - assertEquals('Two', getSelectedElementText()); + assertEquals('Save to Google Drive', getSelectedElementText()); + up(); + assertEquals('Save as PDF', getSelectedElementText()); up(); assertEquals('One', getSelectedElementText()); - up(); - assertEquals('Three', getSelectedElementText()); }); test( @@ -217,4 +218,16 @@ move(getList()[0], {x: 0, y: 0}, {x: 0, y: 0}, 1); assertEquals('One', getSelectedElementText()); }); + + test(assert(destination_dropdown_cros_test.TestNames.Disabled), function() { + setItemList([createDestination('One')]); + dropdown.disabled = true; + + pointerDown(dropdown.$$('#dropdownInput')); + assertFalse(dropdown.$$('iron-dropdown').opened); + + dropdown.disabled = false; + pointerDown(dropdown.$$('#dropdownInput')); + assertTrue(dropdown.$$('iron-dropdown').opened); + }); });
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js index 3c13f7a..d56ebb1 100644 --- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -1172,6 +1172,10 @@ destination_dropdown_cros_test.TestNames.SelectedFollowsMouse); }); +TEST_F('PrintPreviewDestinationDropdownCrosTest', 'Disabled', function() { + this.runMochaTest(destination_dropdown_cros_test.TestNames.Disabled); +}); + GEN('#else'); // eslint-disable-next-line no-var var PrintPreviewDestinationSelectTest = class extends PrintPreviewTest {
diff --git a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js index 6865492..0c8371e 100644 --- a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
@@ -117,14 +117,14 @@ assertFalse(toggle.disabled); assertFalse(toggle.checked); - // Tap the enable toggle button and ensure the state becomes enabled. + // Tap the enable toggle button and ensure the state becomes enabling. toggle.click(); return flushAsync().then(() => { assertTrue(toggle.checked); const wifiDevice = mojoApi_.getDeviceStateForTest(mojom.NetworkType.kWiFi); assertTrue(!!wifiDevice); - assertEquals(mojom.DeviceStateType.kEnabled, wifiDevice.deviceState); + assertEquals(mojom.DeviceStateType.kEnabling, wifiDevice.deviceState); }); }); });
diff --git a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js index 7ef8063..46d11972 100644 --- a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
@@ -214,9 +214,16 @@ } }; -TEST_F('CrSettingsPasswordsSectionV3Test', 'All', function() { +// Flaky on Mac https://crbug.com/1090931 +GEN('#if defined(OS_MACOSX)'); +GEN('#define MAYBE_All DISABLED_All'); +GEN('#else'); +GEN('#define MAYBE_All All'); +GEN('#endif'); +TEST_F('CrSettingsPasswordsSectionV3Test', 'MAYBE_All', function() { mocha.run(); }); +GEN('#undef MAYBE_All'); // eslint-disable-next-line no-var var CrSettingsMultiStorePasswordUiEntryV3Test = @@ -501,7 +508,6 @@ ['SearchPage', 'search_page_test.js'], ['Search', 'search_settings_test.js'], ['SecurityKeysSubpage', 'security_keys_subpage_test.js'], - ['SecurityPage', 'security_page_test.js'], ['SecureDns', 'secure_dns_test.js'], // Copied from P2 test: Disabled for flakiness, see https://crbug.com/1061249 ['SiteData', 'site_data_test.js', 'DISABLED_All'], @@ -530,6 +536,8 @@ GEN('#if !defined(OS_MACOSX)'); [['EditDictionaryPage', 'edit_dictionary_page_test.js'], + // TODO(https://crbug.com/1081908): Flaky on Mac. Fix and re-enable. + ['SecurityPage', 'security_page_test.js'], ].forEach(test => registerTest(...test)); GEN('#endif //!defined(OS_MACOSX)');
diff --git a/chrome/test/nacl/nacl_browsertest_uma.cc b/chrome/test/nacl/nacl_browsertest_uma.cc index 9b0439f..459935f 100644 --- a/chrome/test/nacl/nacl_browsertest_uma.cc +++ b/chrome/test/nacl/nacl_browsertest_uma.cc
@@ -259,6 +259,13 @@ // Test that validation for the 2 (or 3) PNaCl translator nexes can be cached. // This includes pnacl-llc.nexe, pnacl-ld.nexe, and possibly pnacl-sz.nexe. +// Flaky on Windows https://crbug.com/1059468#c18 +#if defined(OS_WIN) +#define MAYBE_ValidationCacheOfTranslatorNexes \ + DISABLED_ValidationCacheOfTranslatorNexes +#else +#define MAYBE_ValidationCacheOfTranslatorNexes ValidationCacheOfTranslatorNexes +#endif IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnacl, ValidationCacheOfTranslatorNexes) { const bool uses_subzero_with_o0 = IsSubzeroSupportedForArch();
diff --git a/chrome/updater/mac/setup/setup.h b/chrome/updater/mac/setup/setup.h index da743a4..4bfd8dad 100644 --- a/chrome/updater/mac/setup/setup.h +++ b/chrome/updater/mac/setup/setup.h
@@ -7,6 +7,46 @@ namespace updater { +namespace setup_exit_codes { + +// Success. +constexpr int kSuccess = 0; + +// Failed to copy the updater's bundle. +constexpr int kFailedToCopyBundle = 10; + +// Failed to delete the updater's install folder. +constexpr int kFailedToDeleteFolder = 11; + +// Failed to remove the active(unversioned) update service job from Launchd. +constexpr int kFailedToRemoveActiveUpdateServiceJobFromLaunchd = 20; + +// Failed to remove versioned update service job from Launchd. +constexpr int kFailedToRemoveCandidateUpdateServiceJobFromLaunchd = 21; + +// Failed to remove versioned administration job from Launchd. +constexpr int kFailedToRemoveAdministrationJobFromLaunchd = 22; + +// Failed to create the active(unversioned) update service Launchd plist. +constexpr int kFailedToCreateUpdateServiceLaunchdJobPlist = 30; + +// Failed to create the versioned update service Launchd plist. +constexpr int kFailedToCreateVersionedUpdateServiceLaunchdJobPlist = 31; + +// Failed to create the versioned administration Launchd plist. +constexpr int kFailedToCreateAdministrationLaunchdJobPlist = 32; + +// Failed to start the active(unversioned) update service job. +constexpr int kFailedToStartLaunchdActiveServiceJob = 40; + +// Failed to start the versioned update service job. +constexpr int kFailedToStartLaunchdVersionedServiceJob = 41; + +// Failed to start the administration job. +constexpr int kFailedToStartLaunchdAdministrationJob = 42; + +} // namespace setup_exit_codes + // Sets up the candidate updater by copying the bundle, creating launchd plists // for administration service and XPC service tasks, and start the corresponding // launchd jobs.
diff --git a/chrome/updater/mac/setup/setup.mm b/chrome/updater/mac/setup/setup.mm index 2aba62b..35f3938 100644 --- a/chrome/updater/mac/setup/setup.mm +++ b/chrome/updater/mac/setup/setup.mm
@@ -250,7 +250,7 @@ info_plist->UpdaterVersionedFolderPath(GetUpdaterFolderPath()); if (!CopyBundle(dest_path)) - return -1; + return setup_exit_codes::kFailedToCopyBundle; base::FilePath updater_executable_path = info_plist->UpdaterExecutablePath( GetLibraryFolderPath(), GetUpdateFolderName(), GetUpdaterAppName(), @@ -259,26 +259,27 @@ if (!CreateUpdateServiceLaunchdJobPlist( info_plist->GoogleUpdateServiceLaunchdNameVersioned(), updater_executable_path)) { - return -2; + return setup_exit_codes:: + kFailedToCreateVersionedUpdateServiceLaunchdJobPlist; } if (!CreateUpdateAdministrationLaunchdJobPlist( info_plist->GoogleUpdateAdministrationLaunchdNameVersioned(), updater_executable_path)) { - return -3; + return setup_exit_codes::kFailedToCreateAdministrationLaunchdJobPlist; } if (!StartUpdateServiceVersionedLaunchdJob( info_plist->GoogleUpdateServiceLaunchdNameVersioned())) { - return -4; + return setup_exit_codes::kFailedToStartLaunchdVersionedServiceJob; } if (!StartUpdateAdministrationVersionedLaunchdJob( info_plist->GoogleUpdateAdministrationLaunchdNameVersioned())) { - return -5; + return setup_exit_codes::kFailedToStartLaunchdAdministrationJob; } - return 0; + return setup_exit_codes::kSuccess; } int UninstallCandidate() { @@ -293,7 +294,7 @@ DeleteInstallFolder( info_plist->UpdaterVersionedFolderPath(GetUpdaterFolderPath())); - return 0; + return setup_exit_codes::kSuccess; } int PromoteCandidate() { @@ -310,14 +311,14 @@ if (!CreateUpdateServiceLaunchdJobPlist(CopyGoogleUpdateServiceLaunchDName(), updater_executable_path)) { - return -1; + return setup_exit_codes::kFailedToCreateUpdateServiceLaunchdJobPlist; } if (!StartLaunchdServiceJob()) { - return -2; + return setup_exit_codes::kFailedToStartLaunchdActiveServiceJob; } - return 0; + return setup_exit_codes::kSuccess; } #pragma mark Uninstall @@ -330,20 +331,21 @@ if (!RemoveUpdateServiceJobFromLaunchd( info_plist->GoogleUpdateServiceLaunchdNameVersioned())) { - return -1; + return setup_exit_codes:: + kFailedToRemoveCandidateUpdateServiceJobFromLaunchd; } if (!RemoveUpdateAdministrationJobFromLaunchd( info_plist->GoogleUpdateAdministrationLaunchdNameVersioned())) - return -2; + return setup_exit_codes::kFailedToRemoveAdministrationJobFromLaunchd; if (!RemoveUpdateServiceJobFromLaunchd()) - return -3; + return setup_exit_codes::kFailedToRemoveActiveUpdateServiceJobFromLaunchd; if (!DeleteInstallFolder()) - return -4; + return setup_exit_codes::kFailedToDeleteFolder; - return 0; + return setup_exit_codes::kSuccess; } } // namespace updater
diff --git a/chrome/updater/mac/update_service_out_of_process.mm b/chrome/updater/mac/update_service_out_of_process.mm index ecdea2f..193537f 100644 --- a/chrome/updater/mac/update_service_out_of_process.mm +++ b/chrome/updater/mac/update_service_out_of_process.mm
@@ -141,7 +141,7 @@ } - (void)haltForUpdateToVersion:(NSString* _Nonnull)version - reply:(void (^_Nonnull)(bool shouldUpdate))reply { + reply:(void (^_Nonnull)(BOOL shouldUpdate))reply { auto errorHandler = ^(NSError* xpcError) { LOG(ERROR) << "XPC connection failed: " << base::SysNSStringToUTF8([xpcError description]);
diff --git a/chrome/updater/server/mac/service_delegate.mm b/chrome/updater/server/mac/service_delegate.mm index fc1c62e..052584f2 100644 --- a/chrome/updater/server/mac/service_delegate.mm +++ b/chrome/updater/server/mac/service_delegate.mm
@@ -11,7 +11,9 @@ #include "base/command_line.h" #include "base/mac/scoped_block.h" #include "base/mac/scoped_nsobject.h" +#include "base/no_destructor.h" #include "base/strings/sys_string_conversions.h" +#include "base/synchronization/waitable_event.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/version.h" #include "chrome/updater/mac/setup/setup.h" @@ -21,6 +23,14 @@ #include "chrome/updater/update_service.h" #include "chrome/updater/updater_version.h" +const NSInteger kMaxRedialAttempts = 3; + +const base::Version& GetSelfVersion() { + static base::NoDestructor<base::Version> self_version( + base::Version(UPDATER_VERSION_STRING)); + return *self_version; +} + @interface CRUUpdateCheckXPCServiceImpl : NSObject <CRUUpdateChecking, CRUAdministering> @@ -28,46 +38,63 @@ // Designated initializers. - (instancetype)initWithUpdateService:(updater::UpdateService*)service - - callbackRunner:(scoped_refptr<base::SequencedTaskRunner>) - callbackRunner; -- (instancetype)initWithUpdateService:(updater::UpdateService*)service callbackRunner:(scoped_refptr<base::SequencedTaskRunner>) callbackRunner - updateCheckXPCConnection:(base::scoped_nsobject<NSXPCConnection>) - updateCheckXPCConnection NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithUpdateService:(updater::UpdateService*)service + updaterConnectionOptions:(NSXPCConnectionOptions)options + callbackRunner:(scoped_refptr<base::SequencedTaskRunner>) + callbackRunner; + @end @implementation CRUUpdateCheckXPCServiceImpl { updater::UpdateService* _service; scoped_refptr<base::SequencedTaskRunner> _callbackRunner; + NSXPCConnectionOptions _updateCheckXPCConnectionOptions; base::scoped_nsobject<NSXPCConnection> _updateCheckXPCConnection; + NSInteger _redialAttempts; } - (instancetype)initWithUpdateService:(updater::UpdateService*)service callbackRunner:(scoped_refptr<base::SequencedTaskRunner>) callbackRunner { - [self initWithUpdateService:service - callbackRunner:callbackRunner - updateCheckXPCConnection:base::scoped_nsobject<NSXPCConnection>(nil)]; + if (self = [super init]) { + _service = service; + _callbackRunner = callbackRunner; + } return self; } - (instancetype)initWithUpdateService:(updater::UpdateService*)service + updaterConnectionOptions:(NSXPCConnectionOptions)options callbackRunner:(scoped_refptr<base::SequencedTaskRunner>) - callbackRunner - updateCheckXPCConnection:(base::scoped_nsobject<NSXPCConnection>) - updateCheckXPCConnection { - if (self = [super init]) { - _service = service; - _callbackRunner = callbackRunner; - _updateCheckXPCConnection = updateCheckXPCConnection; - } + callbackRunner { + [self initWithUpdateService:service callbackRunner:callbackRunner]; + _updateCheckXPCConnectionOptions = options; + [self dialUpdateCheckXPCConnection]; return self; } +- (void)dialUpdateCheckXPCConnection { + _updateCheckXPCConnection.reset([[NSXPCConnection alloc] + initWithMachServiceName:updater::GetGoogleUpdateServiceMachName().get() + options:_updateCheckXPCConnectionOptions]); + + _updateCheckXPCConnection.get().remoteObjectInterface = + updater::GetXPCUpdateCheckingInterface(); + + _updateCheckXPCConnection.get().interruptionHandler = ^{ + LOG(WARNING) << "CRUUpdateCheckingService: XPC connection interrupted."; + }; + + _updateCheckXPCConnection.get().invalidationHandler = ^{ + LOG(WARNING) << "CRUUpdateCheckingService: XPC connection invalidated."; + }; + [_updateCheckXPCConnection resume]; +} + #pragma mark CRUUpdateChecking - (void)checkForUpdatesWithUpdateState:(id<CRUUpdateStateObserving>)updateState reply:(void (^_Nonnull)(int rc))reply { @@ -181,8 +208,7 @@ } - (BOOL)isUpdaterVersionLowerThanCandidateVersion:(NSString* _Nonnull)version { - const base::Version selfVersion = - base::Version(base::SysNSStringToUTF8(@UPDATER_VERSION_STRING)); + const base::Version selfVersion = GetSelfVersion(); CHECK(selfVersion.IsValid()); const base::Version candidateVersion = base::Version(base::SysNSStringToUTF8(version)); @@ -193,7 +219,7 @@ } - (void)haltForUpdateToVersion:(NSString* _Nonnull)candidateVersion - reply:(void (^_Nonnull)(bool shouldUpdate))reply { + reply:(void (^_Nonnull)(BOOL shouldUpdate))reply { if (reply) { if ([self isUpdaterVersionLowerThanCandidateVersion:candidateVersion]) { // Halt the service for a long time, so that the update to the candidate @@ -208,56 +234,108 @@ } #pragma mark CRUAdministering -- (void)performAdminTasks { - // Get the version of the active service. - auto errorHandler = ^(NSError* xpcError) { + +- (void)promoteCandidate { + // TODO: crbug 1072061 + // Actually do the self test. For now assume it passes. + BOOL selfTestPassed = YES; + + if (!selfTestPassed) { + LOG(ERROR) << "Candidate versioned: '" + << UPDATER_VERSION_STRING "' failed self test."; + return; + } + + auto haltErrorHandler = ^(NSError* haltError) { LOG(ERROR) << "XPC connection failed: " - << base::SysNSStringToUTF8([xpcError description]); + << base::SysNSStringToUTF8([haltError description]); + // Try to redial the connection + if (++_redialAttempts <= kMaxRedialAttempts) { + [self dialUpdateCheckXPCConnection]; + [self promoteCandidate]; + return; + } else { + LOG(ERROR) << "XPC connection redialed maximum number of times."; + } }; - auto reply = ^(NSString* _Nullable activeServiceVersionString) { + auto haltReply = ^(BOOL halted) { + VLOG(0) << "Response from haltForUpdateToVersion:reply: = " << halted; + if (halted) { + updater::PromoteCandidate(); + } else { + LOG(ERROR) << "The active service refused to halt for update to version: " + << UPDATER_VERSION_STRING; + } + }; + + [[_updateCheckXPCConnection.get() + remoteObjectProxyWithErrorHandler:haltErrorHandler] + haltForUpdateToVersion:@UPDATER_VERSION_STRING + reply:haltReply]; +} + +- (void)performAdminTasks { + base::scoped_nsobject<NSError> versionError; + + if (!_updateCheckXPCConnection) { + [self promoteCandidate]; + return; + } + + auto versionErrorHandler = ^(NSError* versionError) { + LOG(ERROR) << "XPC connection failed: " + << base::SysNSStringToUTF8([versionError description]); + }; + + auto versionReply = ^(NSString* _Nullable activeServiceVersionString) { if (activeServiceVersionString) { const base::Version activeServiceVersion = base::Version(base::SysNSStringToUTF8(activeServiceVersionString)); - CHECK(activeServiceVersion.IsValid()); - const base::Version selfVersion = - base::Version(base::SysNSStringToUTF8(@UPDATER_VERSION_STRING)); - CHECK(selfVersion.IsValid()); - int versionComparisonResult = selfVersion.CompareTo(activeServiceVersion); + const base::Version selfVersion = GetSelfVersion(); - if (versionComparisonResult > 0) { - // If the versioned service is a higher version than the active service, - // activate the versioned service. - updater::PromoteCandidate(); - } else if (versionComparisonResult < 0) { - // If the versioned service is a lower version than the active service, - // remove the versioned service. + if (!selfVersion.IsValid()) { updater::UninstallCandidate(); + } else if (!activeServiceVersion.IsValid()) { + [self promoteCandidate]; } else { - // If the versioned service is the same version as the active service, - // check for updates. - auto updateCheckErrorHandler = ^(NSError* xpcError) { - LOG(ERROR) << "XPC connection failed: " - << base::SysNSStringToUTF8([xpcError description]); - }; + int versionComparisonResult = + selfVersion.CompareTo(activeServiceVersion); - auto updateCheckReply = ^(int error) { - VLOG(0) << "UpdateAll complete: exit_code = " << error; - }; + if (versionComparisonResult > 0) { + // If the versioned service is a higher version than the active + // service, run a self test and activate the versioned service. + [self promoteCandidate]; + } else if (versionComparisonResult < 0) { + // If the versioned service is a lower version than the active + // service, remove the versioned service. + updater::UninstallCandidate(); + } else { + // If the versioned service is the same version as the active + // service, check for updates. + base::scoped_nsobject<NSError> updateCheckError; - base::scoped_nsprotocol<id<CRUUpdateStateObserving>> stateObserver( - [[CRUUpdateStateObserver alloc] - initWithRepeatingCallback: - base::BindRepeating( - [](updater::UpdateService::UpdateState) {}) - callbackRunner:_callbackRunner]); + base::scoped_nsprotocol<id<CRUUpdateStateObserving>> stateObserver( + [[CRUUpdateStateObserver alloc] + initWithRepeatingCallback: + base::BindRepeating( + [](updater::UpdateService::UpdateState) {}) + callbackRunner:_callbackRunner]); - // TODO: crbug 1072061 - // Need to wait for the async reply? - [[_updateCheckXPCConnection.get() - remoteObjectProxyWithErrorHandler:updateCheckErrorHandler] - checkForUpdatesWithUpdateState:stateObserver.get() - reply:updateCheckReply]; + auto updateCheckErrorHandler = ^(NSError* updateCheckError) { + LOG(ERROR) << "XPC connection failed: " + << base::SysNSStringToUTF8( + [updateCheckError description]); + }; + auto updateCheckReply = ^(int error) { + VLOG(0) << "UpdateAll complete: exit_code = " << error; + }; + + [[_updateCheckXPCConnection.get() + remoteObjectProxyWithErrorHandler:updateCheckErrorHandler] + checkForUpdatesWithUpdateState:stateObserver + reply:updateCheckReply]; + } } } else { // Active service version is nil. @@ -265,16 +343,9 @@ } }; - if (!_updateCheckXPCConnection) { - // Activate the service. - updater::PromoteCandidate(); - } else { - // TODO: crbug 1072061 - // Need to wait for the async reply? - [[_updateCheckXPCConnection.get() - remoteObjectProxyWithErrorHandler:errorHandler] - getUpdaterVersionWithReply:reply]; - } + [[_updateCheckXPCConnection.get() + remoteObjectProxyWithErrorHandler:versionErrorHandler] + getUpdaterVersionWithReply:versionReply]; } @end @@ -330,36 +401,18 @@ // Check to see if the other side of the connection is "okay"; // if not, invalidate newConnection and return NO. - base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - NSXPCConnectionOptions options = cmdline->HasSwitch(updater::kSystemSwitch) + base::CommandLine* cmdLine = base::CommandLine::ForCurrentProcess(); + NSXPCConnectionOptions options = cmdLine->HasSwitch(updater::kSystemSwitch) ? NSXPCConnectionPrivileged : 0; - base::scoped_nsobject<NSXPCConnection> updateCheckXPCConnection( - [[NSXPCConnection alloc] - initWithMachServiceName:updater::GetGoogleUpdateServiceMachName() - .get() - options:options]); - - updateCheckXPCConnection.get().remoteObjectInterface = - updater::GetXPCUpdateCheckingInterface(); - - updateCheckXPCConnection.get().interruptionHandler = ^{ - LOG(WARNING) << "CRUUpdateCheckingService: XPC connection interrupted."; - }; - - updateCheckXPCConnection.get().invalidationHandler = ^{ - LOG(WARNING) << "CRUUpdateCheckingService: XPC connection invalidated."; - }; - [updateCheckXPCConnection resume]; - newConnection.exportedInterface = updater::GetXPCAdministeringInterface(); base::scoped_nsobject<CRUUpdateCheckXPCServiceImpl> object( [[CRUUpdateCheckXPCServiceImpl alloc] initWithUpdateService:_service.get() - callbackRunner:_callbackRunner.get() - updateCheckXPCConnection:updateCheckXPCConnection]); + updaterConnectionOptions:options + callbackRunner:_callbackRunner.get()]); newConnection.exportedObject = object.get(); [newConnection resume]; return YES;
diff --git a/chrome/updater/server/mac/service_protocol.h b/chrome/updater/server/mac/service_protocol.h index ff39190..28204822c 100644 --- a/chrome/updater/server/mac/service_protocol.h +++ b/chrome/updater/server/mac/service_protocol.h
@@ -51,7 +51,7 @@ // Checks if |version| is newer. Returns the result in the reply block. - (void)haltForUpdateToVersion:(NSString* _Nonnull)version - reply:(void (^_Nonnull)(bool shouldUpdate))reply; + reply:(void (^_Nonnull)(BOOL shouldUpdate))reply; @end
diff --git a/chrome/updater/test/test_app/update_client_mac.mm b/chrome/updater/test/test_app/update_client_mac.mm index ac2cebb5..70ce34a4 100644 --- a/chrome/updater/test/test_app/update_client_mac.mm +++ b/chrome/updater/test/test_app/update_client_mac.mm
@@ -127,7 +127,7 @@ } - (void)haltForUpdateToVersion:(NSString* _Nonnull)version - reply:(void (^_Nonnull)(bool shouldUpdate))reply { + reply:(void (^_Nonnull)(BOOL shouldUpdate))reply { auto errorHandler = ^(NSError* xpcError) { LOG(ERROR) << "XPC connection failed: " << base::SysNSStringToUTF8([xpcError description]);
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn index 713a31bc1..f50b3f857 100644 --- a/chromeos/dbus/BUILD.gn +++ b/chromeos/dbus/BUILD.gn
@@ -26,6 +26,7 @@ ":anomaly_detector_proto", ":cicerone_proto", ":concierge_proto", + ":lorgnette_proto", ":metrics_event_proto", ":oobe_config_proto", ":plugin_vm_service_proto", @@ -266,6 +267,13 @@ proto_out_dir = "chromeos/dbus/concierge" } +proto_library("lorgnette_proto") { + sources = + [ "//third_party/cros_system_api/dbus/lorgnette/lorgnette_service.proto" ] + + proto_out_dir = "chromeos/dbus/lorgnette" +} + proto_library("metrics_event_proto") { sources = [ "//third_party/cros_system_api/dbus/metrics_event/metrics_event.proto" ]
diff --git a/chromeos/dbus/fake_lorgnette_manager_client.cc b/chromeos/dbus/fake_lorgnette_manager_client.cc index f8682da..c1d91f2 100644 --- a/chromeos/dbus/fake_lorgnette_manager_client.cc +++ b/chromeos/dbus/fake_lorgnette_manager_client.cc
@@ -21,12 +21,9 @@ void FakeLorgnetteManagerClient::Init(dbus::Bus* bus) {} void FakeLorgnetteManagerClient::ListScanners( - DBusMethodCallback<ScannerTable> callback) { + DBusMethodCallback<lorgnette::ListScannersResponse> callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - scanner_table_.empty() - ? base::nullopt - : base::make_optional(scanner_table_))); + FROM_HERE, base::BindOnce(std::move(callback), list_scanners_response_)); } void FakeLorgnetteManagerClient::ScanImageToString( @@ -41,12 +38,6 @@ FROM_HERE, base::BindOnce(std::move(callback), std::move(data))); } -void FakeLorgnetteManagerClient::AddScannerTableEntry( - const std::string& device_name, - const ScannerTableEntry& entry) { - scanner_table_[device_name] = entry; -} - void FakeLorgnetteManagerClient::AddScanData(const std::string& device_name, const ScanProperties& properties, const std::string& data) { @@ -54,4 +45,9 @@ properties.resolution_dpi)] = data; } +void FakeLorgnetteManagerClient::SetListScannersResponse( + const lorgnette::ListScannersResponse& list_scanners_response) { + list_scanners_response_ = list_scanners_response; +} + } // namespace chromeos
diff --git a/chromeos/dbus/fake_lorgnette_manager_client.h b/chromeos/dbus/fake_lorgnette_manager_client.h index 67b9c6e..ab61307d 100644 --- a/chromeos/dbus/fake_lorgnette_manager_client.h +++ b/chromeos/dbus/fake_lorgnette_manager_client.h
@@ -10,6 +10,7 @@ #include <tuple> #include "base/macros.h" +#include "chromeos/dbus/lorgnette/lorgnette_service.pb.h" #include "chromeos/dbus/lorgnette_manager_client.h" namespace chromeos { @@ -24,23 +25,24 @@ void Init(dbus::Bus* bus) override; - void ListScanners(DBusMethodCallback<ScannerTable> callback) override; + void ListScanners( + DBusMethodCallback<lorgnette::ListScannersResponse> callback) override; void ScanImageToString(std::string device_name, const ScanProperties& properties, DBusMethodCallback<std::string> callback) override; - // Adds a fake scanner table entry, which will be returned by ListScanners(). - void AddScannerTableEntry(const std::string& device_name, - const ScannerTableEntry& entry); - // Adds a fake scan data, which will be returned by ScanImageToString(), // if |device_name| and |properties| are matched. void AddScanData(const std::string& device_name, const ScanProperties& properties, const std::string& data); + // Sets the response returned by ListScanners(). + void SetListScannersResponse( + const lorgnette::ListScannersResponse& list_scanners_response); + private: - ScannerTable scanner_table_; + lorgnette::ListScannersResponse list_scanners_response_; // Use tuple for a map below, which has pre-defined "less", for convenience. using ScanDataKey = std::tuple<std::string /* device_name */,
diff --git a/chromeos/dbus/lorgnette_manager_client.cc b/chromeos/dbus/lorgnette_manager_client.cc index 6f2cb75..87e2766 100644 --- a/chromeos/dbus/lorgnette_manager_client.cc +++ b/chromeos/dbus/lorgnette_manager_client.cc
@@ -32,9 +32,10 @@ LorgnetteManagerClientImpl() = default; ~LorgnetteManagerClientImpl() override = default; - void ListScanners(DBusMethodCallback<ScannerTable> callback) override { + void ListScanners( + DBusMethodCallback<lorgnette::ListScannersResponse> callback) override { dbus::MethodCall method_call(lorgnette::kManagerServiceInterface, - lorgnette::kListScannersMethod); + lorgnette::kListScannersProtoMethod); lorgnette_daemon_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&LorgnetteManagerClientImpl::OnListScanners, @@ -153,46 +154,24 @@ }; // Called when ListScanners completes. - void OnListScanners(DBusMethodCallback<ScannerTable> callback, - dbus::Response* response) { - dbus::MessageReader table_reader(nullptr); - if (!response || !dbus::MessageReader(response).PopArray(&table_reader)) { + void OnListScanners( + DBusMethodCallback<lorgnette::ListScannersResponse> callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to obtain ListScannersResponse"; std::move(callback).Run(base::nullopt); return; } - ScannerTable scanners; - while (table_reader.HasMoreData()) { - std::string device_name; - dbus::MessageReader device_entry_reader(nullptr); - dbus::MessageReader device_element_reader(nullptr); - if (!table_reader.PopDictEntry(&device_entry_reader) || - !device_entry_reader.PopString(&device_name) || - !device_entry_reader.PopArray(&device_element_reader)) { - LOG(ERROR) << "Failed to decode response from ListScanners"; - std::move(callback).Run(base::nullopt); - return; - } - - ScannerTableEntry scanner_entry; - while (device_element_reader.HasMoreData()) { - std::string attribute; - std::string value; - dbus::MessageReader device_attribute_reader(nullptr); - if (!device_element_reader.PopDictEntry(&device_attribute_reader) || - !device_attribute_reader.PopString(&attribute) || - !device_attribute_reader.PopString(&value)) { - LOG(ERROR) << "Failed to decode response from ListScanners"; - std::move(callback).Run(base::nullopt); - return; - } - scanner_entry.emplace(std::move(attribute), std::move(value)); - } - - scanners.emplace(std::move(device_name), std::move(scanner_entry)); + lorgnette::ListScannersResponse response_proto; + dbus::MessageReader reader(response); + if (!reader.PopArrayOfBytesAsProto(&response_proto)) { + LOG(ERROR) << "Failed to read ListScannersResponse"; + std::move(callback).Run(base::nullopt); + return; } - std::move(callback).Run(std::move(scanners)); + std::move(callback).Run(std::move(response_proto)); } // Called when a response for ScanImage() is received.
diff --git a/chromeos/dbus/lorgnette_manager_client.h b/chromeos/dbus/lorgnette_manager_client.h index db6ca4e..5b6b351 100644 --- a/chromeos/dbus/lorgnette_manager_client.h +++ b/chromeos/dbus/lorgnette_manager_client.h
@@ -14,6 +14,7 @@ #include "base/macros.h" #include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/dbus_method_call_status.h" +#include "chromeos/dbus/lorgnette/lorgnette_service.pb.h" namespace chromeos { @@ -22,10 +23,6 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS) LorgnetteManagerClient : public DBusClient { public: - // The property information for each scanner retured by ListScanners. - using ScannerTableEntry = std::map<std::string, std::string>; - using ScannerTable = std::map<std::string, ScannerTableEntry>; - // Attributes provided to a scan request. struct ScanProperties { std::string mode; // Can be "Color", "Gray", or "Lineart". @@ -35,7 +32,8 @@ ~LorgnetteManagerClient() override; // Gets a list of scanners from the lorgnette manager. - virtual void ListScanners(DBusMethodCallback<ScannerTable> callback) = 0; + virtual void ListScanners( + DBusMethodCallback<lorgnette::ListScannersResponse> callback) = 0; // Request a scanned image and calls |callback| when completed with a string // pointing at the scanned image data. Image data will be stored in the .png
diff --git a/chromeos/dbus/system_proxy/fake_system_proxy_client.cc b/chromeos/dbus/system_proxy/fake_system_proxy_client.cc index 37d82e6..1829c4d 100644 --- a/chromeos/dbus/system_proxy/fake_system_proxy_client.cc +++ b/chromeos/dbus/system_proxy/fake_system_proxy_client.cc
@@ -14,11 +14,11 @@ FakeSystemProxyClient::~FakeSystemProxyClient() = default; -void FakeSystemProxyClient::SetSystemTrafficCredentials( - const system_proxy::SetSystemTrafficCredentialsRequest& request, - SetSystemTrafficCredentialsCallback callback) { +void FakeSystemProxyClient::SetAuthenticationDetails( + const system_proxy::SetAuthenticationDetailsRequest& request, + SetAuthenticationDetailsCallback callback) { ++set_credentials_call_count_; - system_proxy::SetSystemTrafficCredentialsResponse response; + system_proxy::SetAuthenticationDetailsResponse response; base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), response)); } @@ -41,7 +41,7 @@ return this; } -int FakeSystemProxyClient::GetSetSystemTrafficCredentialsCallCount() const { +int FakeSystemProxyClient::GetSetAuthenticationDetailsCallCount() const { return set_credentials_call_count_; }
diff --git a/chromeos/dbus/system_proxy/fake_system_proxy_client.h b/chromeos/dbus/system_proxy/fake_system_proxy_client.h index 8b20211..7fe9b116 100644 --- a/chromeos/dbus/system_proxy/fake_system_proxy_client.h +++ b/chromeos/dbus/system_proxy/fake_system_proxy_client.h
@@ -21,16 +21,16 @@ ~FakeSystemProxyClient() override; // SystemProxyClient implementation. - void SetSystemTrafficCredentials( - const system_proxy::SetSystemTrafficCredentialsRequest& request, - SetSystemTrafficCredentialsCallback callback) override; + void SetAuthenticationDetails( + const system_proxy::SetAuthenticationDetailsRequest& request, + SetAuthenticationDetailsCallback callback) override; void ShutDownDaemon(ShutDownDaemonCallback callback) override; void ConnectToWorkerActiveSignal(WorkerActiveCallback callback) override; SystemProxyClient::TestInterface* GetTestInterface() override; // SystemProxyClient::TestInterface implementation. - int GetSetSystemTrafficCredentialsCallCount() const override; + int GetSetAuthenticationDetailsCallCount() const override; int GetShutDownCallCount() const override; private:
diff --git a/chromeos/dbus/system_proxy/system_proxy_client.cc b/chromeos/dbus/system_proxy/system_proxy_client.cc index 59df213..cc5bccc9 100644 --- a/chromeos/dbus/system_proxy/system_proxy_client.cc +++ b/chromeos/dbus/system_proxy/system_proxy_client.cc
@@ -59,10 +59,10 @@ ~SystemProxyClientImpl() override = default; // SystemProxyClient overrides: - void SetSystemTrafficCredentials( - const system_proxy::SetSystemTrafficCredentialsRequest& request, - SetSystemTrafficCredentialsCallback callback) override { - CallProtoMethodWithRequest(system_proxy::kSetSystemTrafficCredentialsMethod, + void SetAuthenticationDetails( + const system_proxy::SetAuthenticationDetailsRequest& request, + SetAuthenticationDetailsCallback callback) override { + CallProtoMethodWithRequest(system_proxy::kSetAuthenticationDetailsMethod, request, std::move(callback)); }
diff --git a/chromeos/dbus/system_proxy/system_proxy_client.h b/chromeos/dbus/system_proxy/system_proxy_client.h index 58d5b6d..d010662 100644 --- a/chromeos/dbus/system_proxy/system_proxy_client.h +++ b/chromeos/dbus/system_proxy/system_proxy_client.h
@@ -21,8 +21,8 @@ // initializes the DBusThreadManager instance. class COMPONENT_EXPORT(SYSTEM_PROXY) SystemProxyClient { public: - using SetSystemTrafficCredentialsCallback = base::OnceCallback<void( - const system_proxy::SetSystemTrafficCredentialsResponse& response)>; + using SetAuthenticationDetailsCallback = base::OnceCallback<void( + const system_proxy::SetAuthenticationDetailsResponse& response)>; using ShutDownDaemonCallback = base::OnceCallback<void(const system_proxy::ShutDownResponse& response)>; using WorkerActiveCallback = base::RepeatingCallback<void( @@ -32,8 +32,8 @@ // only implemented in the fake implementation. class TestInterface { public: - // Returns how many times |SetSystemTrafficCredentials| was called. - virtual int GetSetSystemTrafficCredentialsCallCount() const = 0; + // Returns how many times |SetAuthenticationDetails| was called. + virtual int GetSetAuthenticationDetailsCallCount() const = 0; // Returns how many times |ShutDownDaemon| was called. virtual int GetShutDownCallCount() const = 0; @@ -59,9 +59,9 @@ // SystemProxy daemon D-Bus method calls. See org.chromium.SystemProxy.xml and // system_proxy_service.proto in Chromium OS code for the documentation of the // methods and request/response messages. - virtual void SetSystemTrafficCredentials( - const system_proxy::SetSystemTrafficCredentialsRequest& request, - SetSystemTrafficCredentialsCallback callback) = 0; + virtual void SetAuthenticationDetails( + const system_proxy::SetAuthenticationDetailsRequest& request, + SetAuthenticationDetailsCallback callback) = 0; // When receiving a shut-down call, System-proxy will schedule a shut-down // task and reply. |callback| is called when the daemon starts to shut-down.
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index 4dcf443..34fda40 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -207,8 +207,7 @@ case NetworkStateHandler::TECHNOLOGY_AVAILABLE: return mojom::DeviceStateType::kDisabled; case NetworkStateHandler::TECHNOLOGY_DISABLING: - // TODO(jonmann): Add a DeviceStateType::kDisabling. - return mojom::DeviceStateType::kDisabled; + return mojom::DeviceStateType::kDisabling; case NetworkStateHandler::TECHNOLOGY_ENABLING: return mojom::DeviceStateType::kEnabling; case NetworkStateHandler::TECHNOLOGY_ENABLED:
diff --git a/chromeos/services/network_config/public/mojom/network_types.mojom b/chromeos/services/network_config/public/mojom/network_types.mojom index 6274e0ee..f193fb2d 100644 --- a/chromeos/services/network_config/public/mojom/network_types.mojom +++ b/chromeos/services/network_config/public/mojom/network_types.mojom
@@ -19,6 +19,7 @@ enum DeviceStateType { kUninitialized, kDisabled, + kDisabling, kEnabling, kEnabled, kProhibited,
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc index 902a0ae7..96ea44b 100644 --- a/components/autofill/core/browser/autofill_metrics.cc +++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -876,6 +876,12 @@ } // static +void AutofillMetrics::LogCreditCardUploadLegalMessageLinkClicked() { + base::RecordAction(base::UserMetricsAction( + "Autofill_CreditCardUpload_LegalMessageLinkClicked")); +} + +// static void AutofillMetrics::LogCreditCardUploadFeedbackMetric( CreditCardUploadFeedbackMetric metric) { DCHECK_LT(metric, NUM_CREDIT_CARD_UPLOAD_FEEDBACK_METRICS);
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h index 6295097..6043081e 100644 --- a/components/autofill/core/browser/autofill_metrics.h +++ b/components/autofill/core/browser/autofill_metrics.h
@@ -1159,6 +1159,7 @@ SaveCardPromptMetric metric, bool is_uploading, security_state::SecurityLevel security_level); + static void LogCreditCardUploadLegalMessageLinkClicked(); static void LogCreditCardUploadFeedbackMetric( CreditCardUploadFeedbackMetric metric); static void LogManageCardsPromptMetric(ManageCardsPromptMetric metric,
diff --git a/components/autofill_assistant/browser/actions/use_address_action.cc b/components/autofill_assistant/browser/actions/use_address_action.cc index a6cd5cc..5455a1b 100644 --- a/components/autofill_assistant/browser/actions/use_address_action.cc +++ b/components/autofill_assistant/browser/actions/use_address_action.cc
@@ -127,6 +127,36 @@ } void UseAddressAction::FillFormWithData() { + if (selector_.empty()) { + DCHECK(proto_.use_address().skip_autofill()); + OnWaitForElement(OkClientStatus()); + return; + } + + delegate_->ShortWaitForElement( + selector_, base::BindOnce(&UseAddressAction::OnWaitForElement, + weak_ptr_factory_.GetWeakPtr())); +} + +void UseAddressAction::OnWaitForElement(const ClientStatus& element_status) { + if (!element_status.ok()) { + EndAction(element_status); + return; + } + + if (proto_.use_address().skip_autofill()) { + ExecuteFallback(OkClientStatus()); + return; + } + + DCHECK(!selector_.empty()); + DCHECK(profile_ != nullptr); + delegate_->FillAddressForm(profile_.get(), selector_, + base::BindOnce(&UseAddressAction::ExecuteFallback, + weak_ptr_factory_.GetWeakPtr())); +} + +void UseAddressAction::ExecuteFallback(const ClientStatus& status) { DCHECK(profile_ != nullptr); std::vector<RequiredField> required_fields; for (const auto& required_field_proto : @@ -147,32 +177,6 @@ /* locale = */ "en-US"), delegate_); - if (proto_.use_address().skip_autofill()) { - fallback_handler_->CheckAndFallbackRequiredFields( - OkClientStatus(), base::BindOnce(&UseAddressAction::EndAction, - weak_ptr_factory_.GetWeakPtr())); - return; - } - - delegate_->ShortWaitForElement( - selector_, base::BindOnce(&UseAddressAction::OnWaitForElement, - weak_ptr_factory_.GetWeakPtr())); -} - -void UseAddressAction::OnWaitForElement(const ClientStatus& element_status) { - if (!element_status.ok()) { - EndAction(element_status); - return; - } - - DCHECK(!selector_.empty()); - delegate_->FillAddressForm(profile_.get(), selector_, - base::BindOnce(&UseAddressAction::OnFormFilled, - weak_ptr_factory_.GetWeakPtr())); -} - -void UseAddressAction::OnFormFilled(const ClientStatus& status) { - DCHECK(fallback_handler_ != nullptr); fallback_handler_->CheckAndFallbackRequiredFields( status, base::BindOnce(&UseAddressAction::EndAction, weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/autofill_assistant/browser/actions/use_address_action.h b/components/autofill_assistant/browser/actions/use_address_action.h index 4af42cf9..01c5c53 100644 --- a/components/autofill_assistant/browser/actions/use_address_action.h +++ b/components/autofill_assistant/browser/actions/use_address_action.h
@@ -44,7 +44,7 @@ void OnWaitForElement(const ClientStatus& element_status); // Called when the address has been filled. - void OnFormFilled(const ClientStatus& status); + void ExecuteFallback(const ClientStatus& status); // Note: |fallback_handler_| must be a member, because checking for fallbacks // is asynchronous and the existence of the handler must be ensured.
diff --git a/components/autofill_assistant/browser/actions/use_address_action_unittest.cc b/components/autofill_assistant/browser/actions/use_address_action_unittest.cc index 11a142b..dab28fdf6 100644 --- a/components/autofill_assistant/browser/actions/use_address_action_unittest.cc +++ b/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
@@ -516,6 +516,7 @@ "#first_name"); action_proto.mutable_use_address()->set_skip_autofill(true); + EXPECT_CALL(mock_action_delegate_, OnShortWaitForElement(_, _)).Times(0); EXPECT_CALL(mock_action_delegate_, OnFillAddressForm(_, _, _)).Times(0); // First validation fails.
diff --git a/components/autofill_assistant/browser/actions/use_credit_card_action.cc b/components/autofill_assistant/browser/actions/use_credit_card_action.cc index 44f3cc2..c79ffdb 100644 --- a/components/autofill_assistant/browser/actions/use_credit_card_action.cc +++ b/components/autofill_assistant/browser/actions/use_credit_card_action.cc
@@ -108,11 +108,9 @@ } void UseCreditCardAction::FillFormWithData() { - if (proto_.use_card().skip_autofill()) { - DCHECK(credit_card_ != nullptr); - delegate_->GetFullCard(credit_card_.get(), - base::BindOnce(&UseCreditCardAction::OnGetFullCard, - weak_ptr_factory_.GetWeakPtr())); + if (selector_.empty()) { + DCHECK(proto_.use_card().skip_autofill()); + OnWaitForElement(OkClientStatus()); return; } @@ -167,18 +165,17 @@ required_fields, fallback_values, delegate_); if (proto_.use_card().skip_autofill()) { - fallback_handler_->CheckAndFallbackRequiredFields( - OkClientStatus(), base::BindOnce(&UseCreditCardAction::EndAction, - weak_ptr_factory_.GetWeakPtr())); + ExecuteFallback(OkClientStatus()); return; } + DCHECK(!selector_.empty()); delegate_->FillCardForm(std::move(card), cvc, selector_, - base::BindOnce(&UseCreditCardAction::OnFormFilled, + base::BindOnce(&UseCreditCardAction::ExecuteFallback, weak_ptr_factory_.GetWeakPtr())); } -void UseCreditCardAction::OnFormFilled(const ClientStatus& status) { +void UseCreditCardAction::ExecuteFallback(const ClientStatus& status) { DCHECK(fallback_handler_ != nullptr); fallback_handler_->CheckAndFallbackRequiredFields( status, base::BindOnce(&UseCreditCardAction::EndAction,
diff --git a/components/autofill_assistant/browser/actions/use_credit_card_action.h b/components/autofill_assistant/browser/actions/use_credit_card_action.h index 9f10684..7bf36ff 100644 --- a/components/autofill_assistant/browser/actions/use_credit_card_action.h +++ b/components/autofill_assistant/browser/actions/use_credit_card_action.h
@@ -48,7 +48,7 @@ const base::string16& cvc); // Called when the form credit card has been filled. - void OnFormFilled(const ClientStatus& status); + void ExecuteFallback(const ClientStatus& status); // Note: |fallback_handler_| must be a member, because checking for fallbacks // is asynchronous and the existence of the handler must be ensured.
diff --git a/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc b/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc index 06d285a..8905e8c6 100644 --- a/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc +++ b/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
@@ -392,13 +392,14 @@ ON_CALL(mock_action_delegate_, GetElementTag(_, _)) .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT")); - ActionProto action = CreateUseCreditCardAction(); + ActionProto action; AddRequiredField(&action, base::NumberToString(static_cast<int>( AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE)), "#cvc"); action.mutable_use_card()->set_skip_autofill(true); + EXPECT_CALL(mock_action_delegate_, OnShortWaitForElement(_, _)).Times(0); EXPECT_CALL(mock_action_delegate_, OnFillCardForm(_, _, _, _)).Times(0); // First validation fails.
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/PermissionInfo.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/PermissionInfo.java index 488c062d..5629548 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/PermissionInfo.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/PermissionInfo.java
@@ -45,15 +45,22 @@ } private final boolean mIsIncognito; + private final boolean mIsEmbargoed; private final String mEmbedder; private final String mOrigin; private final @Type int mType; public PermissionInfo(@Type int type, String origin, String embedder, boolean isIncognito) { + this(type, origin, embedder, isIncognito, false); + } + + public PermissionInfo(@Type int type, String origin, String embedder, boolean isIncognito, + boolean isEmbargoed) { mOrigin = origin; mEmbedder = embedder; mIsIncognito = isIncognito; mType = type; + mIsEmbargoed = isEmbargoed; } public @Type int getType() { @@ -76,6 +83,10 @@ return mEmbedder != null ? mEmbedder : mOrigin; } + public boolean isEmbargoed() { + return mIsEmbargoed; + } + /** * Returns the ContentSetting value for this origin. */
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java index edcf1a9e..b57a117ed 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -350,7 +350,9 @@ } else if (i == ContentSettingException.Type.JAVASCRIPT) { setUpJavascriptPreference(preference); } else { - setUpListPreference(preference, mSite.getContentSettingPermission(i)); + // ContentSettingException can not be embargoed. + setUpListPreference(preference, mSite.getContentSettingPermission(i), + false /* isEmbargoed */); } return; } @@ -362,17 +364,23 @@ if (i == PermissionInfo.Type.GEOLOCATION) { setUpLocationPreference(preference); } else if (i == PermissionInfo.Type.NOTIFICATION) { - setUpNotificationsPreference(preference); + setUpNotificationsPreference( + preference, isPermissionEmbargoed(PermissionInfo.Type.NOTIFICATION)); } else { setUpListPreference(preference, mSite.getPermission( - getSiteSettingsClient().getBrowserContextHandle(), i)); + getSiteSettingsClient().getBrowserContextHandle(), i), + isPermissionEmbargoed(i)); } return; } } } + private boolean isPermissionEmbargoed(@PermissionInfo.Type int type) { + return mSite.getPermissionInfo(type) != null && mSite.getPermissionInfo(type).isEmbargoed(); + } + private void setUpClearDataPreference(ClearWebsiteStorage preference) { long usage = mSite.getTotalUsage(); if (usage > 0) { @@ -452,7 +460,7 @@ }); } - private void setUpNotificationsPreference(Preference preference) { + private void setUpNotificationsPreference(Preference preference, boolean isEmbargoed) { WebappSettingsClient client = getSiteSettingsClient().getWebappSettingsClient(); Origin origin = Origin.create(mSite.getAddress().getOrigin()); if (origin != null) { @@ -482,14 +490,15 @@ getPreferenceScreen().removePreference(preference); return; } - String overrideSummary; if (isPermissionControlledByDSE(ContentSettingsType.NOTIFICATIONS)) { overrideSummary = getString(value != null && value == ContentSettingValues.ALLOW ? R.string.website_settings_permissions_allow_dse : R.string.website_settings_permissions_block_dse); } else { - overrideSummary = getString(ContentSettingsResources.getSiteSummary(value)); + overrideSummary = isEmbargoed + ? getString(R.string.automatically_blocked) + : getString(ContentSettingsResources.getSiteSummary(value)); } // On Android O this preference is read-only, so we replace the existing pref with a @@ -503,7 +512,6 @@ return true; }); } else { - setUpListPreference(preference, value); if (isPermissionControlledByDSE(ContentSettingsType.NOTIFICATIONS) && value != null) { updatePreferenceForDSESetting(preference); } @@ -512,14 +520,9 @@ // This is implemented as a public utility function to better facilitate testing. public void launchOsChannelSettingsFromPreference(Preference preference) { - final boolean blockedByEmbargo = - (WebsitePreferenceBridgeJni.get().isNotificationEmbargoedForOrigin( - getSiteSettingsClient().getBrowserContextHandle(), - mSite.getAddress().getOrigin())); - // There is no notification channel if the origin is merely embargoed. Create it // just-in-time if the user tries to change to setting. - if (blockedByEmbargo) { + if (isPermissionEmbargoed(PermissionInfo.Type.NOTIFICATION)) { mSite.setPermission(getSiteSettingsClient().getBrowserContextHandle(), PermissionInfo.Type.NOTIFICATION, ContentSettingValues.BLOCK); } @@ -567,7 +570,7 @@ findPreference(PERMISSION_PREFERENCE_KEYS[PermissionInfo.Type.NOTIFICATION + ContentSettingException.Type.NUM_ENTRIES]); if (notificationsPreference != null) { - setUpNotificationsPreference(notificationsPreference); + setUpNotificationsPreference(notificationsPreference, false /* isEmbargoed */); } // To ensure UMA receives notification revocations, we detect if the setting has changed @@ -745,8 +748,8 @@ * @param preference The ListPreference to initialize. * @param value The value to initialize it to. */ - private void setUpListPreference( - Preference preference, @ContentSettingValues @Nullable Integer value) { + private void setUpListPreference(Preference preference, + @ContentSettingValues @Nullable Integer value, boolean isEmbargoed) { if (value == null) { getPreferenceScreen().removePreference(preference); return; @@ -764,12 +767,12 @@ getString(ContentSettingsResources.getSiteSummary(ContentSettingValues.BLOCK)); listPreference.setEntryValues(keys); listPreference.setEntries(descriptions); + listPreference.setOnPreferenceChangeListener(this); + listPreference.setSummary(isEmbargoed ? getString(R.string.automatically_blocked) : "%s"); // TODO(crbug.com/735110): Figure out if this is the correct thing to do - here we are // effectively treating non-ALLOW values as BLOCK. int index = (value == ContentSettingValues.ALLOW ? 0 : 1); listPreference.setValueIndex(index); - listPreference.setOnPreferenceChangeListener(this); - listPreference.setSummary("%s"); } /** @@ -803,7 +806,8 @@ @Nullable Integer permission = mSite.getPermission( getSiteSettingsClient().getBrowserContextHandle(), PermissionInfo.Type.GEOLOCATION); - setUpListPreference(preference, permission); + setUpListPreference( + preference, permission, isPermissionEmbargoed(PermissionInfo.Type.GEOLOCATION)); if (isPermissionControlledByDSE(ContentSettingsType.GEOLOCATION) && permission != null) { updatePreferenceForDSESetting(preference); } @@ -823,7 +827,8 @@ ? ContentSettingValues.ALLOW : ContentSettingValues.BLOCK; } - setUpListPreference(preference, currentValue); + // Not possible to embargo SOUND. + setUpListPreference(preference, currentValue, false /* isEmbargoed */); } private void setUpJavascriptPreference(Preference preference) { @@ -839,7 +844,8 @@ ContentSettingsType.JAVASCRIPT)) { currentValue = ContentSettingValues.BLOCK; } - setUpListPreference(preference, currentValue); + // Not possible to embargo JAVASCRIPT. + setUpListPreference(preference, currentValue, false /* isEmbargoed */); } /** @@ -852,7 +858,7 @@ private void setUpAdsPreference(Preference preference) { // Do not show the setting if the category is not enabled. if (!SiteSettingsCategory.adsCategoryEnabled()) { - setUpListPreference(preference, null); + setUpListPreference(preference, null, false); return; } // If the ad blocker is activated, then this site will have ads blocked unless there is an @@ -867,7 +873,7 @@ // If the site is not considered a candidate for blocking, do the standard thing and remove // the preference. if (permission == null && !activated) { - setUpListPreference(preference, null); + setUpListPreference(preference, null, false); return; } @@ -880,7 +886,8 @@ ? ContentSettingValues.ALLOW : ContentSettingValues.BLOCK; } - setUpListPreference(preference, permission); + // Not possible to embargo ADS. + setUpListPreference(preference, permission, false /* isEmbargoed */); // The subresource filter permission has a custom BLOCK string. ListPreference listPreference = (ListPreference) preference; @@ -935,6 +942,8 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { @ContentSettingValues int permission = ContentSetting.fromString((String) newValue); + // Embargoed permission preserves summary. Refresh it manually. + preference.setSummary("%s"); BrowserContextHandle browserContextHandle = getSiteSettingsClient().getBrowserContextHandle(); for (int i = 0; i < PERMISSION_PREFERENCE_KEYS.length; i++) {
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java index f8c47092..493edc29 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java
@@ -77,7 +77,7 @@ } private static void insertInfoIntoList(@PermissionInfo.Type int type, - ArrayList<PermissionInfo> list, String origin, String embedder) { + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { if (type == PermissionInfo.Type.CAMERA || type == PermissionInfo.Type.MICROPHONE) { for (PermissionInfo info : list) { if (info.getOrigin().equals(origin) && info.getEmbedder().equals(embedder)) { @@ -85,67 +85,69 @@ } } } - list.add(new PermissionInfo(type, origin, embedder, false)); + list.add(new PermissionInfo(type, origin, embedder, false, isEmbargoed)); } @CalledByNative private static void insertArInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.AUGMENTED_REALITY, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList( + PermissionInfo.Type.AUGMENTED_REALITY, list, origin, embedder, isEmbargoed); } @CalledByNative private static void insertCameraInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.CAMERA, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.CAMERA, list, origin, embedder, isEmbargoed); } @CalledByNative private static void insertClipboardInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.CLIPBOARD, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.CLIPBOARD, list, origin, embedder, isEmbargoed); } @CalledByNative private static void insertGeolocationInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.GEOLOCATION, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.GEOLOCATION, list, origin, embedder, isEmbargoed); } @CalledByNative private static void insertMicrophoneInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.MICROPHONE, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.MICROPHONE, list, origin, embedder, isEmbargoed); } @CalledByNative private static void insertMidiInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.MIDI, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.MIDI, list, origin, embedder, isEmbargoed); } @CalledByNative private static void insertNfcInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.NFC, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.NFC, list, origin, embedder, isEmbargoed); } @CalledByNative private static void insertNotificationIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.NOTIFICATION, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.NOTIFICATION, list, origin, embedder, isEmbargoed); } @CalledByNative private static void insertProtectedMediaIdentifierInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.PROTECTED_MEDIA_IDENTIFIER, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.PROTECTED_MEDIA_IDENTIFIER, list, origin, embedder, + isEmbargoed); } @CalledByNative private static void insertSensorsInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.SENSORS, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList(PermissionInfo.Type.SENSORS, list, origin, embedder, isEmbargoed); } @CalledByNative @@ -156,8 +158,9 @@ @CalledByNative private static void insertVrInfoIntoList( - ArrayList<PermissionInfo> list, String origin, String embedder) { - insertInfoIntoList(PermissionInfo.Type.VIRTUAL_REALITY, list, origin, embedder); + ArrayList<PermissionInfo> list, String origin, String embedder, boolean isEmbargoed) { + insertInfoIntoList( + PermissionInfo.Type.VIRTUAL_REALITY, list, origin, embedder, isEmbargoed); } @CalledByNative
diff --git a/components/browser_ui/site_settings/android/website_preference_bridge.cc b/components/browser_ui/site_settings/android/website_preference_bridge.cc index 8f279ee..b76af68 100644 --- a/components/browser_ui/site_settings/android/website_preference_bridge.cc +++ b/components/browser_ui/site_settings/android/website_preference_bridge.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <jni.h> #include <algorithm> #include <string> #include <vector> @@ -125,7 +126,8 @@ JNIEnv*, const base::android::JavaRef<jobject>&, const base::android::JavaRef<jstring>&, - const base::android::JavaRef<jstring>&); + const base::android::JavaRef<jstring>&, + jboolean); void GetOrigins(JNIEnv* env, const JavaParamRef<jobject>& jbrowser_context_handle, @@ -166,7 +168,8 @@ jembedder = ConvertUTF8ToJavaString(env, embedder); seen_origins.push_back(origin); - insertionFunc(env, list, ConvertOriginToJavaString(env, origin), jembedder); + insertionFunc(env, list, ConvertOriginToJavaString(env, origin), jembedder, + /*is_embargoed=*/false); } // Add any origins which have a default content setting value (thus skipped @@ -188,7 +191,7 @@ .content_setting == CONTENT_SETTING_BLOCK) { seen_origins.push_back(origin); insertionFunc(env, list, ConvertOriginToJavaString(env, origin), - jembedder); + jembedder, /*is_embargoed=*/true); } } }
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd index 259cad5..40fb69d7 100644 --- a/components/browser_ui/strings/android/browser_ui_strings.grd +++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -378,6 +378,9 @@ <message name="IDS_MENU_HELP" desc="Menu item for opening the help page. [CHAR-LIMIT=27]"> Help & feedback </message> + <message name="IDS_AUTOMATICALLY_BLOCKED" desc="Description displayed next to an origin when it was placed under embargo by Chrome. This indicates to the user that the origin is blocked automatically instead of being the result of the user's decision."> + Automatically blocked + </message> <!-- Downloads UI --> <message name="IDS_DOWNLOAD_NOTIFICATION_CANCEL_BUTTON" desc="Text on the button that cancels a download.">
diff --git a/components/crash/core/browser/resources/crashes.html b/components/crash/core/browser/resources/crashes.html index d5bb4165..e04058e 100644 --- a/components/crash/core/browser/resources/crashes.html +++ b/components/crash/core/browser/resources/crashes.html
@@ -80,6 +80,5 @@ <p id="noCrashes" hidden>$i18n{noCrashesMessage}</p> </div> - <script src="chrome://resources/js/jstemplate_compiled.js"></script> </body> </html>
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc index b10349b..a27fec1 100644 --- a/components/cronet/url_request_context_config_unittest.cc +++ b/components/cronet/url_request_context_config_unittest.cc
@@ -71,7 +71,7 @@ {"QUIC", "set_quic_flags"}, base::Value( "FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count=5," - "FLAGS_quic_reloadable_flag_quic_enable_version_t050_v2=true," + "FLAGS_quic_reloadable_flag_quic_enable_version_draft_28=true," "FLAGS_quic_reloadable_flag_quic_enable_version_draft_27=true")); options.SetPath({"AsyncDNS", "enable"}, base::Value(true)); options.SetPath({"NetworkErrorLogging", "enable"}, base::Value(true)); @@ -145,7 +145,7 @@ // Initialize QUIC flags set by the config. FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count = 0; - FLAGS_quic_reloadable_flag_quic_enable_version_t050_v2 = false; + FLAGS_quic_reloadable_flag_quic_enable_version_draft_28 = false; FLAGS_quic_reloadable_flag_quic_enable_version_draft_27 = false; URLRequestContextConfig config( @@ -198,7 +198,7 @@ EXPECT_EQ(quic_connection_options, quic_params->connection_options); EXPECT_EQ(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count, 5); - EXPECT_TRUE(FLAGS_quic_reloadable_flag_quic_enable_version_t050_v2); + EXPECT_TRUE(FLAGS_quic_reloadable_flag_quic_enable_version_draft_28); EXPECT_TRUE(FLAGS_quic_reloadable_flag_quic_enable_version_draft_27); // Check Custom QUIC User Agent Id.
diff --git a/components/feed/core/v2/feed_network_impl.cc b/components/feed/core/v2/feed_network_impl.cc index d815289..8815bb7f7 100644 --- a/components/feed/core/v2/feed_network_impl.cc +++ b/components/feed/core/v2/feed_network_impl.cc
@@ -41,20 +41,48 @@ namespace feed { namespace { -constexpr char kAuthenticationScope[] = - "https://www.googleapis.com/auth/googlenow"; constexpr char kApplicationOctetStream[] = "application/octet-stream"; constexpr base::TimeDelta kNetworkTimeout = base::TimeDelta::FromSeconds(30); -// Add URLs for Bling when it is supported. -constexpr char kFeedQueryUrl[] = - "https://www.google.com/httpservice/retry/TrellisClankService/FeedQuery"; -constexpr char kNextPageQueryUrl[] = - "https://www.google.com/httpservice/retry/TrellisClankService/" - "NextPageQuery"; -constexpr char kBackgroundQueryUrl[] = - "https://www.google.com/httpservice/noretry/TrellisClankService/" - "FeedQuery"; +signin::ScopeSet GetAuthScopes() { + return {"https://www.googleapis.com/auth/googlenow"}; +} + +GURL GetFeedQueryURL(feedwire::FeedQuery::RequestReason reason) { + // Add URLs for Bling when it is supported. + switch (reason) { + case feedwire::FeedQuery::SCHEDULED_REFRESH: + case feedwire::FeedQuery::IN_PLACE_UPDATE: + return GURL( + "https://www.google.com/httpservice/noretry/TrellisClankService/" + "FeedQuery"); + case feedwire::FeedQuery::NEXT_PAGE_SCROLL: + return GURL( + "https://www.google.com/httpservice/retry/TrellisClankService/" + "NextPageQuery"); + case feedwire::FeedQuery::MANUAL_REFRESH: + return GURL( + "https://www.google.com/httpservice/retry/TrellisClankService/" + "FeedQuery"); + default: + return GURL(); + } +} + +GURL GetUploadActionURL(version_info::Channel channel) { + switch (channel) { + case version_info::Channel::BETA: + return GURL( + "https://staging-discover-pa.sandbox.googleapis.com/v1/" + "actions:upload"); + case version_info::Channel::STABLE: + return GURL("https://discover-pa.googleapis.com/v1/actions:upload"); + default: + return GURL( + "https://autopush-discover-pa.sandbox.googleapis.com/v1/" + "actions:upload"); + } +} GURL GetUrlWithoutQuery(const GURL& url) { GURL::Replacements replacements; @@ -102,12 +130,25 @@ void AddMothershipPayloadQueryParams(bool is_post, const std::string& payload, const std::string& language_tag, - GURL* url) { + GURL& url) { if (!is_post) - *url = net::AppendQueryParameter(*url, "reqpld", payload); - *url = net::AppendQueryParameter(*url, "fmt", "bin"); + url = net::AppendQueryParameter(url, "reqpld", payload); + url = net::AppendQueryParameter(url, "fmt", "bin"); if (!language_tag.empty()) - *url = net::AppendQueryParameter(*url, "hl", language_tag); + url = net::AppendQueryParameter(url, "hl", language_tag); +} + +// Compresses and attaches |request_body| for upload if it's not empty. +// Returns the compressed size of the request. +int PopulateRequestBody(const std::string& request_body, + network::SimpleURLLoader* loader) { + if (request_body.empty()) + return 0; + std::string compressed_request_body; + compression::GzipCompress(request_body, &compressed_request_body); + loader->AttachStringForUpload(compressed_request_body, + kApplicationOctetStream); + return compressed_request_body.size(); } } // namespace @@ -167,11 +208,10 @@ private: void StartAccessTokenFetch() { - signin::ScopeSet scopes{kAuthenticationScope}; // It's safe to pass base::Unretained(this) since deleting the token fetcher // will prevent the callback from being completed. token_fetcher_ = std::make_unique<signin::PrimaryAccountAccessTokenFetcher>( - "feed", identity_manager_, scopes, + "feed", identity_manager_, GetAuthScopes(), base::BindOnce(&NetworkFetch::AccessTokenFetchFinished, base::Unretained(this), tick_clock_->NowTicks()), signin::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable); @@ -250,53 +290,39 @@ resource_request->site_for_cookies = net::SiteForCookies::FromUrl(url); } - SetRequestHeaders(!request_body_.empty(), resource_request.get()); + SetRequestHeaders(!request_body_.empty(), *resource_request); auto simple_loader = network::SimpleURLLoader::Create( std::move(resource_request), traffic_annotation); simple_loader->SetAllowHttpErrorResults(true); simple_loader->SetTimeoutDuration(kNetworkTimeout); - PopulateRequestBody(simple_loader.get()); + + const int compressed_size = + PopulateRequestBody(request_body_, simple_loader.get()); + UMA_HISTOGRAM_COUNTS_1M( + "ContentSuggestions.Feed.Network.RequestSizeKB.Compressed", + compressed_size / 1024); return simple_loader; } void SetRequestHeaders(bool has_request_body, - network::ResourceRequest* request) const { + network::ResourceRequest& request) const { if (has_request_body) { - request->headers.SetHeader(net::HttpRequestHeaders::kContentType, - kApplicationOctetStream); - request->headers.SetHeader("Content-Encoding", "gzip"); + request.headers.SetHeader(net::HttpRequestHeaders::kContentType, + kApplicationOctetStream); + request.headers.SetHeader("Content-Encoding", "gzip"); } variations::SignedIn signed_in_status = variations::SignedIn::kNo; if (!access_token_.empty()) { - request->headers.SetHeader(net::HttpRequestHeaders::kAuthorization, - "Bearer " + access_token_); + request.headers.SetHeader(net::HttpRequestHeaders::kAuthorization, + "Bearer " + access_token_); signed_in_status = variations::SignedIn::kYes; } // Add X-Client-Data header with experiment IDs from field trials. variations::AppendVariationsHeader(url_, variations::InIncognito::kNo, - signed_in_status, request); - } - - void PopulateRequestBody(network::SimpleURLLoader* loader) { - std::string compressed_request_body; - if (!request_body_.empty()) { - std::string uncompressed_request_body( - reinterpret_cast<const char*>(request_body_.data()), - request_body_.size()); - - compression::GzipCompress(uncompressed_request_body, - &compressed_request_body); - - loader->AttachStringForUpload(compressed_request_body, - kApplicationOctetStream); - } - - UMA_HISTOGRAM_COUNTS_1M( - "ContentSuggestions.Feed.Network.RequestSizeKB.Compressed", - static_cast<int>(compressed_request_body.size() / 1024)); + signed_in_status, &request); } void OnSimpleLoaderComplete(std::unique_ptr<std::string> response) { @@ -334,11 +360,10 @@ response_body = std::move(*response); if (response_info.status_code == net::HTTP_UNAUTHORIZED) { - signin::ScopeSet scopes{kAuthenticationScope}; CoreAccountId account_id = identity_manager_->GetPrimaryAccountId(); if (!account_id.empty()) { - identity_manager_->RemoveAccessTokenFromCache(account_id, scopes, - access_token_); + identity_manager_->RemoveAccessTokenFromCache( + account_id, GetAuthScopes(), access_token_); } } } @@ -394,10 +419,12 @@ const std::string& api_key, scoped_refptr<network::SharedURLLoaderFactory> loader_factory, const base::TickClock* tick_clock, - PrefService* pref_service) + PrefService* pref_service, + version_info::Channel chrome_channel) : delegate_(delegate), identity_manager_(identity_manager), api_key_(api_key), + chrome_channel_(chrome_channel), loader_factory_(loader_factory), tick_clock_(tick_clock), pref_service_(pref_service) {} @@ -415,26 +442,13 @@ // TODO(harringtond): Decide how we want to override these URLs for testing. // Should probably add a command-line flag. - GURL url; - switch (request.feed_request().feed_query().reason()) { - case feedwire::FeedQuery::SCHEDULED_REFRESH: - case feedwire::FeedQuery::IN_PLACE_UPDATE: - url = GURL(kBackgroundQueryUrl); - break; - case feedwire::FeedQuery::NEXT_PAGE_SCROLL: - url = GURL(kNextPageQueryUrl); - break; - case feedwire::FeedQuery::MANUAL_REFRESH: - url = GURL(kFeedQueryUrl); - break; - default: - std::move(callback).Run({}); - return; - } + GURL url = GetFeedQueryURL(request.feed_request().feed_query().reason()); + if (url.is_empty()) + return std::move(callback).Run({}); AddMothershipPayloadQueryParams(/*is_post=*/false, base64proto, - delegate_->GetLanguageTag(), &url); - Send(url, "GET", /*request_body=*/std::string(), + delegate_->GetLanguageTag(), url); + Send(url, "GET", /*request_body=*/{}, base::BindOnce(&ParseAndForwardResponse<QueryRequestResult, NetworkRequestType::kFeedQuery>, std::move(callback))); @@ -446,11 +460,10 @@ std::string binary_proto; request.SerializeToString(&binary_proto); - GURL url( - "https://www.google.com/httpservice/retry/ClankActionUploadService/" - "ClankActionUpload"); - AddMothershipPayloadQueryParams(/*is_post=*/true, /*payload=*/std::string(), - delegate_->GetLanguageTag(), &url); + GURL url = GetUploadActionURL(chrome_channel_); + AddMothershipPayloadQueryParams(/*is_post=*/true, + /*payload=*/{}, delegate_->GetLanguageTag(), + url); Send(url, "POST", std::move(binary_proto), base::BindOnce( &ParseAndForwardResponse<ActionRequestResult,
diff --git a/components/feed/core/v2/feed_network_impl.h b/components/feed/core/v2/feed_network_impl.h index ba6e4dcb..2dc8e438 100644 --- a/components/feed/core/v2/feed_network_impl.h +++ b/components/feed/core/v2/feed_network_impl.h
@@ -11,6 +11,7 @@ #include "base/containers/unique_ptr_adapters.h" #include "base/memory/scoped_refptr.h" #include "components/feed/core/v2/feed_network.h" +#include "components/version_info/channel.h" #include "url/gurl.h" class PrefService; @@ -43,7 +44,8 @@ const std::string& api_key, scoped_refptr<network::SharedURLLoaderFactory> loader_factory, const base::TickClock* tick_clock, - PrefService* pref_service); + PrefService* pref_service, + version_info::Channel chrome_channel); ~FeedNetworkImpl() override; FeedNetworkImpl(const FeedNetworkImpl&) = delete; FeedNetworkImpl& operator=(FeedNetworkImpl&) = delete; @@ -79,6 +81,7 @@ Delegate* delegate_; signin::IdentityManager* identity_manager_; const std::string api_key_; + const version_info::Channel chrome_channel_; scoped_refptr<network::SharedURLLoaderFactory> loader_factory_; const base::TickClock* tick_clock_; PrefService* pref_service_;
diff --git a/components/feed/core/v2/feed_network_impl_unittest.cc b/components/feed/core/v2/feed_network_impl_unittest.cc index c931576a..990f791 100644 --- a/components/feed/core/v2/feed_network_impl_unittest.cc +++ b/components/feed/core/v2/feed_network_impl_unittest.cc
@@ -94,7 +94,7 @@ feed_network_ = std::make_unique<FeedNetworkImpl>( &delegate_, identity_test_env_.identity_manager(), "dummy_api_key", shared_url_loader_factory_, task_environment_.GetMockTickClock(), - &profile_prefs_); + &profile_prefs_, version_info::Channel::STABLE); } FeedNetwork* feed_network() { return feed_network_.get(); } @@ -410,8 +410,8 @@ RespondToActionRequest(GetTestActionResponse(), net::HTTP_OK); EXPECT_EQ( - GURL("https://www.google.com/httpservice/retry/ClankActionUploadService/" - "ClankActionUpload?fmt=bin&hl=en"), + GURL( + "https://discover-pa.googleapis.com/v1/actions:upload?fmt=bin&hl=en"), resource_request.url); EXPECT_EQ("POST", resource_request.method);
diff --git a/components/feed/core/v2/public/feed_service.cc b/components/feed/core/v2/public/feed_service.cc index 4c6dcef..1f87c64 100644 --- a/components/feed/core/v2/public/feed_service.cc +++ b/components/feed/core/v2/public/feed_service.cc
@@ -145,7 +145,8 @@ base::DefaultTickClock::GetInstance(), profile_prefs); feed_network_ = std::make_unique<FeedNetworkImpl>( network_delegate_.get(), identity_manager, api_key, url_loader_factory, - base::DefaultTickClock::GetInstance(), profile_prefs); + base::DefaultTickClock::GetInstance(), profile_prefs, + chrome_info.channel); store_ = std::make_unique<FeedStore>(std::move(database)); stream_ = std::make_unique<FeedStream>(
diff --git a/components/metal_util/BUILD.gn b/components/metal_util/BUILD.gn index 7a716ec..86b8df4 100644 --- a/components/metal_util/BUILD.gn +++ b/components/metal_util/BUILD.gn
@@ -4,15 +4,6 @@ import("//testing/test.gni") -config("metal_weak_framework") { - ldflags = [ - "-weak_framework", - "Metal", - "-weak_framework", - "MetalKit", - ] -} - component("metal_util") { output_name = "metal" @@ -38,11 +29,14 @@ "//components/crash/core/common:crash_key", ] - libs = [ + frameworks = [ "Cocoa.framework", "IOSurface.framework", "QuartzCore.framework", ] - configs += [ ":metal_weak_framework" ] + weak_frameworks = [ + "Metal.framework", + "MetalKit.framework", + ] }
diff --git a/components/metrics/net/net_metrics_log_uploader.cc b/components/metrics/net/net_metrics_log_uploader.cc index 641e119..3c0562bb 100644 --- a/components/metrics/net/net_metrics_log_uploader.cc +++ b/components/metrics/net/net_metrics_log_uploader.cc
@@ -4,12 +4,17 @@ #include "components/metrics/net/net_metrics_log_uploader.h" +#include <sstream> + #include "base/base64.h" #include "base/bind.h" #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" +#include "base/metrics/statistics_recorder.h" #include "base/rand_util.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/task/post_task.h" #include "base/threading/sequenced_task_runner_handle.h" #include "components/encrypted_messages/encrypted_message.pb.h" @@ -21,7 +26,9 @@ #include "net/url_request/url_fetcher.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" +#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h" #include "third_party/metrics_proto/reporting_info.pb.h" +#include "third_party/zlib/google/compression_utils.h" #include "url/gurl.h" namespace { @@ -182,6 +189,52 @@ return true; } +#ifndef NDEBUG +void LogUploadingHistograms(const std::string& compressed_log_data) { + if (!VLOG_IS_ON(2)) + return; + + std::string uncompressed; + if (!compression::GzipUncompress(compressed_log_data, &uncompressed)) { + DVLOG(2) << "failed to uncompress log"; + return; + } + metrics::ChromeUserMetricsExtension proto; + if (!proto.ParseFromString(uncompressed)) { + DVLOG(2) << "failed to parse uncompressed log"; + return; + }; + DVLOG(2) << "Uploading histograms..."; + + const base::StatisticsRecorder::Histograms histograms = + base::StatisticsRecorder::GetHistograms(); + auto get_histogram_name = [&](uint64_t name_hash) -> std::string { + for (base::HistogramBase* histogram : histograms) { + if (histogram->name_hash() == name_hash) + return histogram->histogram_name(); + } + return base::StrCat({"unnamed ", base::NumberToString(name_hash)}); + }; + + for (int i = 0; i < proto.histogram_event_size(); i++) { + const metrics::HistogramEventProto& event = proto.histogram_event(i); + + std::stringstream summary; + summary << " sum=" << event.sum(); + for (int j = 0; j < event.bucket_size(); j++) { + const metrics::HistogramEventProto::Bucket& b = event.bucket(j); + // Empty fields have a specific meaning, see + // third_party/metrics_proto/histogram_event.proto. + summary << " bucket[" + << (b.has_min() ? base::NumberToString(b.min()) : "..") << '-' + << (b.has_max() ? base::NumberToString(b.max()) : "..") << ")=" + << (b.has_count() ? base::NumberToString(b.count()) : "(1)"); + } + DVLOG(2) << get_histogram_name(event.name_hash()) << summary.str(); + } +} +#endif + } // namespace namespace metrics { @@ -243,6 +296,13 @@ const GURL& url) { DCHECK(!log_hash.empty()); +#ifndef NDEBUG + // For debug builds, you can use -vmodule=net_metrics_log_uploader=2 + // to enable logging of uploaded histograms. You probably also want to use + // --force-enable-metrics-reporting, or metrics reporting may not be enabled. + LogUploadingHistograms(compressed_log_data); +#endif + auto resource_request = std::make_unique<network::ResourceRequest>(); resource_request->url = url; // Drop cookies and auth data.
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc index ee93a25..fa3e981b 100644 --- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -603,18 +603,18 @@ } TEST_F(NetworkSessionConfiguratorTest, QuicFlags) { - FLAGS_quic_reloadable_flag_quic_enable_version_t050_v2 = false; + FLAGS_quic_reloadable_flag_quic_enable_version_draft_28 = false; FLAGS_quic_reloadable_flag_quic_enable_version_draft_27 = false; std::map<std::string, std::string> field_trial_params; field_trial_params["set_quic_flags"] = - "FLAGS_quic_reloadable_flag_quic_enable_version_t050_v2=true," + "FLAGS_quic_reloadable_flag_quic_enable_version_draft_28=true," "FLAGS_quic_reloadable_flag_quic_enable_version_draft_27=true"; variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); ParseFieldTrials(); - EXPECT_TRUE(FLAGS_quic_reloadable_flag_quic_enable_version_t050_v2); + EXPECT_TRUE(FLAGS_quic_reloadable_flag_quic_enable_version_draft_28); EXPECT_TRUE(FLAGS_quic_reloadable_flag_quic_enable_version_draft_27); }
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index 977870ef..66ad080 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -1764,7 +1764,15 @@ void LoginDatabase::DeleteAllSyncMetadata() { TRACE_EVENT0("passwords", "LoginDatabase::DeleteAllSyncMetadata"); + bool had_unsynced_deletions = HasUnsyncedDeletions(); ClearAllSyncMetadata(&db_); + if (had_unsynced_deletions && deletions_have_synced_callback_) { + // Note: At this point we can't be fully sure whether the deletions actually + // reached the server yet. We might have sent a commit, but haven't received + // the commit confirmation. Let's be conservative and assume they haven't + // been successfully deleted. + deletions_have_synced_callback_.Run(/*success=*/false); + } } bool LoginDatabase::UpdateSyncMetadata( @@ -1796,7 +1804,13 @@ s.BindInt(0, storage_key_int); s.BindString(1, encrypted_metadata); - return s.Run(); + bool had_unsynced_deletions = HasUnsyncedDeletions(); + bool result = s.Run(); + if (result && had_unsynced_deletions && !HasUnsyncedDeletions() && + deletions_have_synced_callback_) { + deletions_have_synced_callback_.Run(/*success=*/true); + } + return result; } bool LoginDatabase::ClearSyncMetadata(syncer::ModelType model_type, @@ -1817,7 +1831,13 @@ "storage_key=?")); s.BindInt(0, storage_key_int); - return s.Run(); + bool had_unsynced_deletions = HasUnsyncedDeletions(); + bool result = s.Run(); + if (result && had_unsynced_deletions && !HasUnsyncedDeletions() && + deletions_have_synced_callback_) { + deletions_have_synced_callback_.Run(/*success=*/true); + } + return result; } bool LoginDatabase::UpdateModelTypeState( @@ -1847,6 +1867,24 @@ return s.Run(); } +void LoginDatabase::SetDeletionsHaveSyncedCallback( + base::RepeatingCallback<void(bool)> callback) { + deletions_have_synced_callback_ = std::move(callback); +} + +bool LoginDatabase::HasUnsyncedDeletions() { + TRACE_EVENT0("passwords", "LoginDatabase::HasUnsyncedDeletions"); + + std::unique_ptr<syncer::MetadataBatch> batch = GetAllSyncEntityMetadata(); + for (const auto& metadata_entry : batch->GetAllMetadata()) { + // Note: No need for an explicit "is unsynced" check: Once the deletion is + // committed, the metadata entry is removed. + if (metadata_entry.second->is_deleted()) + return true; + } + return false; +} + bool LoginDatabase::BeginTransaction() { TRACE_EVENT0("passwords", "LoginDatabase::BeginTransaction"); return db_.BeginTransaction();
diff --git a/components/password_manager/core/browser/login_database.h b/components/password_manager/core/browser/login_database.h index afacb23..88fa8f9 100644 --- a/components/password_manager/core/browser/login_database.h +++ b/components/password_manager/core/browser/login_database.h
@@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/macros.h" @@ -187,6 +188,9 @@ syncer::ModelType model_type, const sync_pb::ModelTypeState& model_type_state) override; bool ClearModelTypeState(syncer::ModelType model_type) override; + void SetDeletionsHaveSyncedCallback( + base::RepeatingCallback<void(bool)> callback) override; + bool HasUnsyncedDeletions() override; // Callers that requires transaction support should call these methods to // begin, rollback and commit transactions. They delegate to the transaction @@ -362,6 +366,12 @@ bool use_encryption_ = true; #endif // defined(OS_POSIX) + // A callback to be invoked whenever all pending deletions have been processed + // by Sync - see + // PasswordStoreSync::MetadataStore::SetDeletionsHaveSyncedCallback for more + // details. + base::RepeatingCallback<void(bool)> deletions_have_synced_callback_; + DISALLOW_COPY_AND_ASSIGN(LoginDatabase); };
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 0f5487f3..8da420d 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -136,9 +136,7 @@ } PasswordStore::PasswordStore() - : observers_(new base::ObserverListThreadSafe<Observer>()), - shutdown_called_(false), - init_status_(InitStatus::kUnknown) {} + : observers_(new base::ObserverListThreadSafe<Observer>()) {} bool PasswordStore::Init(PrefService* prefs, base::RepeatingClosure sync_enabled_or_disabled_cb) { @@ -195,11 +193,13 @@ const base::RepeatingCallback<bool(const GURL&)>& url_filter, base::Time delete_begin, base::Time delete_end, - base::OnceClosure completion) { + base::OnceClosure completion, + base::OnceCallback<void(bool)> sync_completion) { DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); ScheduleTask(base::BindOnce(&PasswordStore::RemoveLoginsByURLAndTimeInternal, this, url_filter, delete_begin, delete_end, - std::move(completion))); + std::move(completion), + std::move(sync_completion))); } void PasswordStore::RemoveLoginsCreatedBetween(base::Time delete_begin, @@ -745,6 +745,24 @@ } } +void PasswordStore::NotifyDeletionsHaveSynced(bool success) { + DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); + // Either all deletions have been committed to the Sync server, or Sync is + // telling us that it won't commit them (because Sync was turned off + // permanently). In either case, run the corresponding callbacks now (on the + // main task runner). + DCHECK(!GetMetadataStore()->HasUnsyncedDeletions()); + for (base::OnceCallback<void(bool)>& callback : + deletions_have_synced_callbacks_) { + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce([](base::OnceCallback<void(bool)> callback, + bool success) { std::move(callback).Run(success); }, + std::move(callback), success)); + } + deletions_have_synced_callbacks_.clear(); +} + void PasswordStore::InvokeAndNotifyAboutCompromisedPasswordsChange( base::OnceCallback<bool()> callback) { DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); @@ -954,7 +972,8 @@ const base::RepeatingCallback<bool(const GURL&)>& url_filter, base::Time delete_begin, base::Time delete_end, - base::OnceClosure completion) { + base::OnceClosure completion, + base::OnceCallback<void(bool)> sync_completion) { DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("passwords", "PasswordStore::RemoveLoginsByURLAndTimeInternal"); BeginTransaction(); @@ -966,8 +985,18 @@ // sync codebase needs to update metadata atomically together with the login // data. CommitTransaction(); + if (completion) main_task_runner_->PostTask(FROM_HERE, std::move(completion)); + + if (sync_completion) { + deletions_have_synced_callbacks_.push_back(std::move(sync_completion)); + + // Do an immediate check for the case where there are already no unsynced + // deletions. + if (!GetMetadataStore()->HasUnsyncedDeletions()) + NotifyDeletionsHaveSynced(/*success=*/true); + } } void PasswordStore::RemoveLoginsCreatedBetweenInternal(
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 25128aa..23a543c 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -172,15 +172,19 @@ virtual void RemoveLogin(const autofill::PasswordForm& form); // Remove all logins whose origins match the given filter and that were - // created - // in the given date range. |completion| will be posted to the - // |main_task_runner_| after deletions have been completed and notification - // have been sent out. + // created in the given date range. |completion| will be posted to the + // |main_task_runner_| after deletions have been completed and notifications + // have been sent out. |sync_completion| will be posted to + // |main_task_runner_| once the deletions have also been propagated to the + // server (or, in rare cases, if the user permanently disables Sync). This is + // only relevant for Sync users and for account store users - for other users, + // |sync_completion| will be run immediately after |completion|. void RemoveLoginsByURLAndTime( const base::RepeatingCallback<bool(const GURL&)>& url_filter, base::Time delete_begin, base::Time delete_end, - base::OnceClosure completion); + base::OnceClosure completion, + base::OnceCallback<void(bool)> sync_completion = base::NullCallback()); // Removes all logins created in the given date range. If |completion| is not // null, it will be posted to the |main_task_runner_| after deletions have @@ -573,6 +577,8 @@ // been changed. void NotifyLoginsChanged(const PasswordStoreChangeList& changes) override; + void NotifyDeletionsHaveSynced(bool success) override; + void NotifyUnsyncedCredentialsWillBeDeleted( const std::vector<autofill::PasswordForm>& unsynced_credentials) override; @@ -700,7 +706,8 @@ const base::RepeatingCallback<bool(const GURL&)>& url_filter, base::Time delete_begin, base::Time delete_end, - base::OnceClosure completion); + base::OnceClosure completion, + base::OnceCallback<void(bool)> sync_completion); void RemoveLoginsCreatedBetweenInternal(base::Time delete_begin, base::Time delete_end, base::OnceClosure completion); @@ -860,9 +867,14 @@ std::unique_ptr<UnsyncedCredentialsDeletionNotifier> deletion_notifier_; - bool shutdown_called_; + // A list of callbacks that should be run once all pending deletions have been + // sent to the Sync server. Note that the vector itself lives on the + // background thread, but the callbacks must be run on the main thread! + std::vector<base::OnceCallback<void(bool)>> deletions_have_synced_callbacks_; - InitStatus init_status_; + bool shutdown_called_ = false; + + InitStatus init_status_ = InitStatus::kUnknown; DISALLOW_COPY_AND_ASSIGN(PasswordStore); };
diff --git a/components/password_manager/core/browser/password_store_default.cc b/components/password_manager/core/browser/password_store_default.cc index 33377d3e..bd79718 100644 --- a/components/password_manager/core/browser/password_store_default.cc +++ b/components/password_manager/core/browser/password_store_default.cc
@@ -40,6 +40,11 @@ success = false; LOG(ERROR) << "Could not create/open login database."; } + if (success) { + login_db_->SetDeletionsHaveSyncedCallback( + base::BindRepeating(&PasswordStoreDefault::NotifyDeletionsHaveSynced, + base::Unretained(this))); + } return PasswordStore::InitOnBackgroundSequence() && success; }
diff --git a/components/password_manager/core/browser/password_store_sync.h b/components/password_manager/core/browser/password_store_sync.h index ac9361a..277bfa5 100644 --- a/components/password_manager/core/browser/password_store_sync.h +++ b/components/password_manager/core/browser/password_store_sync.h
@@ -102,6 +102,20 @@ // Deletes all the stored sync metadata for passwords. virtual void DeleteAllSyncMetadata() = 0; + + // Registers a callback that will be invoked whenever all pending (unsynced) + // deletions are gone. If they were committed to the server (or, rarely, the + // entity was undeleted), the |callback| will be run with "true". If the + // deletions are gone because Sync was permanently turned off, it'll be run + // with "false" instead. + // Note that there can be only one such callback; if one was already + // registered, it'll be overridden by the new |callback|. + virtual void SetDeletionsHaveSyncedCallback( + base::RepeatingCallback<void(bool)> callback) = 0; + + // Returns whether there are any pending deletions that have not been sent + // to the Sync server yet. + virtual bool HasUnsyncedDeletions() = 0; }; PasswordStoreSync(); @@ -149,6 +163,11 @@ // Notifies observers that password store data may have been changed. virtual void NotifyLoginsChanged(const PasswordStoreChangeList& changes) = 0; + // Notifies any waiting callback that all pending deletions have been + // committed to the Sync server now, or that Sync definitely won't commit + // them (because Sync was turned off permanently). + virtual void NotifyDeletionsHaveSynced(bool success) = 0; + // Notifies the UI that some unsynced credentials will be deleted on sign-out // in order to offer the user the option of saving them in the profile store. // Should only be called for the account store.
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc index 04b4384..e7ffa948e 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -185,6 +185,9 @@ MOCK_METHOD2(UpdateModelTypeState, bool(syncer::ModelType, const sync_pb::ModelTypeState&)); MOCK_METHOD1(ClearModelTypeState, bool(syncer::ModelType)); + MOCK_METHOD1(SetDeletionsHaveSyncedCallback, + void(base::RepeatingCallback<void(bool)>)); + MOCK_METHOD0(HasUnsyncedDeletions, bool()); }; class MockPasswordStoreSync : public PasswordStoreSync { @@ -205,6 +208,8 @@ MOCK_METHOD1(RemoveLoginSync, PasswordStoreChangeList(const autofill::PasswordForm&)); MOCK_METHOD1(NotifyLoginsChanged, void(const PasswordStoreChangeList&)); + MOCK_METHOD1(NotifyDeletionsHaveSynced, void(bool)); + MOCK_METHOD1( NotifyUnsyncedCredentialsWillBeDeleted, void(const std::vector<autofill::PasswordForm>& unsynced_credentials));
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc index f534b7d..2ee5b02 100644 --- a/components/password_manager/core/browser/test_password_store.cc +++ b/components/password_manager/core/browser/test_password_store.cc
@@ -42,6 +42,9 @@ bool ClearModelTypeState(syncer::ModelType model_type) override; std::unique_ptr<syncer::MetadataBatch> GetAllSyncMetadata() override; void DeleteAllSyncMetadata() override; + void SetDeletionsHaveSyncedCallback( + base::RepeatingCallback<void(bool)> callback) override; + bool HasUnsyncedDeletions() override; private: sync_pb::ModelTypeState sync_model_type_state_; @@ -60,7 +63,7 @@ bool TestPasswordSyncMetadataStore::ClearSyncMetadata( syncer::ModelType model_type, const std::string& storage_key) { - sync_metadata_.clear(); + sync_metadata_.erase(storage_key); return true; } @@ -96,6 +99,15 @@ sync_metadata_.clear(); } +void TestPasswordSyncMetadataStore::SetDeletionsHaveSyncedCallback( + base::RepeatingCallback<void(bool)> callback) { + NOTIMPLEMENTED(); +} + +bool TestPasswordSyncMetadataStore::HasUnsyncedDeletions() { + return false; +} + } // namespace TestPasswordStore::TestPasswordStore(bool is_account_store)
diff --git a/components/prerender/BUILD.gn b/components/prerender/BUILD.gn index c325e58..c58cfbb0 100644 --- a/components/prerender/BUILD.gn +++ b/components/prerender/BUILD.gn
@@ -8,6 +8,7 @@ "prerender_final_status.h", "prerender_origin.cc", "prerender_origin.h", + "prerender_types.h", ] deps = [ "//base" ] }
diff --git a/chrome/common/prerender_types.h b/components/prerender/prerender_types.h similarity index 74% rename from chrome/common/prerender_types.h rename to components/prerender/prerender_types.h index e6c98dc..ac81495 100644 --- a/chrome/common/prerender_types.h +++ b/components/prerender/prerender_types.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_COMMON_PRERENDER_TYPES_H_ -#define CHROME_COMMON_PRERENDER_TYPES_H_ +#ifndef COMPONENTS_PRERENDER_PRERENDER_TYPES_H_ +#define COMPONENTS_PRERENDER_PRERENDER_TYPES_H_ namespace prerender { @@ -22,4 +22,4 @@ } // namespace prerender -#endif // CHROME_COMMON_PRERENDER_TYPES_H_ +#endif // CHROME_COMMON_PRERCOMPONENTS_PRERENDER_PRERENDER_TYPES_H_ENDER_TYPES_H_
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn index be9992a2..30f2dbc 100644 --- a/components/signin/core/browser/android/BUILD.gn +++ b/components/signin/core/browser/android/BUILD.gn
@@ -109,7 +109,6 @@ sources = [ "javatests/src/org/chromium/components/signin/test/util/AccountHolder.java", - "javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java", "javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java", "javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java", "javatests/src/org/chromium/components/signin/test/util/FakeProfileDataSource.java",
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java index 15fcc7d..2d5571e 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java
@@ -121,13 +121,16 @@ /** * Sets the boolean for whether the account cache has already been populated. */ - void setIsCachePopulated(boolean isCachePopulated) { + public void setIsCachePopulated(boolean isCachePopulated) { synchronized (mLock) { mIsCachePopulated = isCachePopulated; } } - void addAccount(Account account) { + /** + * Adds an account to the fake AccountManagerFacade. + */ + public void addAccount(Account account) { AccountHolder accountHolder = AccountHolder.builder(account).alwaysAccept(true).build(); // As this class is accessed both from UI thread and worker threads, we lock the access // to account holders to avoid potential race condition. @@ -136,7 +139,11 @@ } } - void setProfileData(String accountId, @Nullable ProfileDataSource.ProfileData profileData) { + /** + * Sets profile data in the fake ProfileDataSource. + */ + public void setProfileData( + String accountId, @Nullable ProfileDataSource.ProfileData profileData) { assert mFakeProfileDataSource != null : "ProfileDataSource was disabled!"; ThreadUtils.runOnUiThreadBlocking( () -> mFakeProfileDataSource.setProfileData(accountId, profileData));
diff --git a/components/signin/public/identity_manager/identity_manager.cc b/components/signin/public/identity_manager/identity_manager.cc index 822e773..d4c36c6 100644 --- a/components/signin/public/identity_manager/identity_manager.cc +++ b/components/signin/public/identity_manager/identity_manager.cc
@@ -82,6 +82,10 @@ base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this), token_service_->GetDelegate()->GetJavaObject()); #endif + +#if defined(OS_CHROMEOS) + chromeos_account_manager_ = parameters.chromeos_account_manager; +#endif } IdentityManager::~IdentityManager() { @@ -434,26 +438,32 @@ } #endif -PrimaryAccountManager* IdentityManager::GetPrimaryAccountManager() { +PrimaryAccountManager* IdentityManager::GetPrimaryAccountManager() const { return primary_account_manager_.get(); } -ProfileOAuth2TokenService* IdentityManager::GetTokenService() { +ProfileOAuth2TokenService* IdentityManager::GetTokenService() const { return token_service_.get(); } -AccountTrackerService* IdentityManager::GetAccountTrackerService() { +AccountTrackerService* IdentityManager::GetAccountTrackerService() const { return account_tracker_service_.get(); } -AccountFetcherService* IdentityManager::GetAccountFetcherService() { +AccountFetcherService* IdentityManager::GetAccountFetcherService() const { return account_fetcher_service_.get(); } -GaiaCookieManagerService* IdentityManager::GetGaiaCookieManagerService() { +GaiaCookieManagerService* IdentityManager::GetGaiaCookieManagerService() const { return gaia_cookie_manager_service_.get(); } +#if defined(OS_CHROMEOS) +chromeos::AccountManager* IdentityManager::GetChromeOSAccountManager() const { + return chromeos_account_manager_; +} +#endif + AccountInfo IdentityManager::GetAccountInfoForAccountWithRefreshToken( const CoreAccountId& account_id) const { // TODO(https://crbug.com/919793): This invariant is not currently possible to
diff --git a/components/signin/public/identity_manager/identity_manager.h b/components/signin/public/identity_manager/identity_manager.h index fbd82f5..1603a2c6 100644 --- a/components/signin/public/identity_manager/identity_manager.h +++ b/components/signin/public/identity_manager/identity_manager.h
@@ -28,6 +28,12 @@ #include "base/android/jni_android.h" #endif +#if defined(OS_CHROMEOS) +namespace chromeos { +class AccountManager; +} // namespace chromeos +#endif + namespace gaia { class GaiaSource; struct ListedAccount; @@ -383,6 +389,9 @@ std::unique_ptr<AccountsMutator> accounts_mutator; std::unique_ptr<DeviceAccountsSynchronizer> device_accounts_synchronizer; std::unique_ptr<DiagnosticsProvider> diagnostics_provider; +#if defined(OS_CHROMEOS) + chromeos::AccountManager* chromeos_account_manager = nullptr; +#endif InitParameters(); InitParameters(InitParameters&&); @@ -594,11 +603,14 @@ ForceRefreshOfExtendedAccountInfo); // Private getters used for testing only (i.e. see identity_test_utils.h). - PrimaryAccountManager* GetPrimaryAccountManager(); - ProfileOAuth2TokenService* GetTokenService(); - AccountTrackerService* GetAccountTrackerService(); - AccountFetcherService* GetAccountFetcherService(); - GaiaCookieManagerService* GetGaiaCookieManagerService(); + PrimaryAccountManager* GetPrimaryAccountManager() const; + ProfileOAuth2TokenService* GetTokenService() const; + AccountTrackerService* GetAccountTrackerService() const; + AccountFetcherService* GetAccountFetcherService() const; + GaiaCookieManagerService* GetGaiaCookieManagerService() const; +#if defined(OS_CHROMEOS) + chromeos::AccountManager* GetChromeOSAccountManager() const; +#endif // Populates and returns an AccountInfo object corresponding to |account_id|, // which must be an account with a refresh token. @@ -694,6 +706,10 @@ base::android::ScopedJavaGlobalRef<jobject> java_identity_manager_; #endif +#if defined(OS_CHROMEOS) + chromeos::AccountManager* chromeos_account_manager_ = nullptr; +#endif + DISALLOW_COPY_AND_ASSIGN(IdentityManager); };
diff --git a/components/signin/public/identity_manager/identity_manager_builder.cc b/components/signin/public/identity_manager/identity_manager_builder.cc index 0169c7b..3f24bda 100644 --- a/components/signin/public/identity_manager/identity_manager_builder.cc +++ b/components/signin/public/identity_manager/identity_manager_builder.cc
@@ -171,6 +171,9 @@ std::move(gaia_cookie_manager_service); init_params.primary_account_manager = std::move(primary_account_manager); init_params.token_service = std::move(token_service); +#if defined(OS_CHROMEOS) + init_params.chromeos_account_manager = params->account_manager; +#endif return init_params; }
diff --git a/components/signin/public/identity_manager/identity_manager_builder_unittest.cc b/components/signin/public/identity_manager/identity_manager_builder_unittest.cc index 484aeda..4ee471a 100644 --- a/components/signin/public/identity_manager/identity_manager_builder_unittest.cc +++ b/components/signin/public/identity_manager/identity_manager_builder_unittest.cc
@@ -122,6 +122,9 @@ EXPECT_EQ(init_params.device_accounts_synchronizer, nullptr); EXPECT_NE(init_params.accounts_mutator, nullptr); #endif +#if defined(OS_CHROMEOS) + EXPECT_NE(init_params.chromeos_account_manager, nullptr); +#endif // Manually shut down AccountFetcherService to avoid DCHECK failure inside its // destructor.
diff --git a/components/signin/public/identity_manager/identity_manager_unittest.cc b/components/signin/public/identity_manager/identity_manager_unittest.cc index 76b86ed..a1a24d2 100644 --- a/components/signin/public/identity_manager/identity_manager_unittest.cc +++ b/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/containers/flat_set.h" +#include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/stl_util.h" @@ -57,6 +58,11 @@ #include "components/signin/internal/identity_manager/child_account_info_fetcher_android.h" #endif +#if defined(OS_CHROMEOS) +#include "chromeos/components/account_manager/account_manager.h" +#include "chromeos/components/account_manager/account_manager_factory.h" +#endif + namespace signin { namespace { @@ -313,6 +319,8 @@ identity_manager_diagnostics_observer_.reset(); identity_manager_.reset(); + ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir()); + auto token_service = std::make_unique<CustomFakeProfileOAuth2TokenService>(&pref_service_); @@ -321,7 +329,8 @@ &signin_client_); auto account_tracker_service = std::make_unique<AccountTrackerService>(); - account_tracker_service->Initialize(&pref_service_, base::FilePath()); + account_tracker_service->Initialize(&pref_service_, + temp_profile_dir_.GetPath()); auto account_fetcher_service = std::make_unique<AccountFetcherService>(); account_fetcher_service->Initialize( @@ -378,6 +387,11 @@ token_service.get(), account_tracker_service.get(), primary_account_manager.get(), &pref_service_); #endif +#if defined(OS_CHROMEOS) + init_params.chromeos_account_manager = + GetAccountManagerFactory()->GetAccountManager( + temp_profile_dir_.GetPath().value()); +#endif init_params.account_fetcher_service = std::move(account_fetcher_service); init_params.account_tracker_service = std::move(account_tracker_service); @@ -427,7 +441,14 @@ return &test_url_loader_factory_; } +#if defined(OS_CHROMEOS) + chromeos::AccountManagerFactory* GetAccountManagerFactory() { + return &account_manager_factory_; + } +#endif + private: + base::ScopedTempDir temp_profile_dir_; base::test::TaskEnvironment task_environment_; sync_preferences::TestingPrefServiceSyncable pref_service_; network::TestURLLoaderFactory test_url_loader_factory_; @@ -437,6 +458,9 @@ std::unique_ptr<TestIdentityManagerDiagnosticsObserver> identity_manager_diagnostics_observer_; CoreAccountId primary_account_id_; +#if defined(OS_CHROMEOS) + chromeos::AccountManagerFactory account_manager_factory_; +#endif DISALLOW_COPY_AND_ASSIGN(IdentityManagerTest); }; @@ -458,6 +482,9 @@ EXPECT_NE(identity_manager()->GetAccountsMutator(), nullptr); EXPECT_EQ(identity_manager()->GetDeviceAccountsSynchronizer(), nullptr); #endif +#if defined(OS_CHROMEOS) + EXPECT_NE(identity_manager()->GetChromeOSAccountManager(), nullptr); +#endif } // Test that IdentityManager starts off with the information in
diff --git a/components/spellcheck/common/spellcheck_features.cc b/components/spellcheck/common/spellcheck_features.cc index 29dad0e..266cf49 100644 --- a/components/spellcheck/common/spellcheck_features.cc +++ b/components/spellcheck/common/spellcheck_features.cc
@@ -33,6 +33,9 @@ const base::Feature kWinUseBrowserSpellChecker{ "WinUseBrowserSpellChecker", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kWinDelaySpellcheckServiceInit{ + "WinDelaySpellcheckServiceInit", base::FEATURE_DISABLED_BY_DEFAULT}; + bool WindowsVersionSupportsSpellchecker() { return base::win::GetVersion() > base::win::Version::WIN7 && base::win::GetVersion() < base::win::Version::WIN_LAST;
diff --git a/components/spellcheck/common/spellcheck_features.h b/components/spellcheck/common/spellcheck_features.h index ed2936f8..6a091c9 100644 --- a/components/spellcheck/common/spellcheck_features.h +++ b/components/spellcheck/common/spellcheck_features.h
@@ -22,6 +22,16 @@ #if defined(OS_WIN) extern const base::Feature kWinUseBrowserSpellChecker; +// If enabled, don't initialize the SpellcheckService on browser launch. +// Since Chromium already by default initializes the spellcheck service +// on startup for custom dictionary synchronization, the command line +// for launching the browser with Windows hybrid spellchecking enabled +// but no initialization of the spellcheck service is: +// chrome +// --enable-features=WinUseBrowserSpellChecker,WinDelaySpellcheckServiceInit +// --disable-sync-types="Dictionary" +extern const base::Feature kWinDelaySpellcheckServiceInit; + bool WindowsVersionSupportsSpellchecker(); bool UseWinHybridSpellChecker(); #endif // defined(OS_WIN)
diff --git a/components/sync_preferences/pref_model_associator.cc b/components/sync_preferences/pref_model_associator.cc index 4939689..e6ae5ba 100644 --- a/components/sync_preferences/pref_model_associator.cc +++ b/components/sync_preferences/pref_model_associator.cc
@@ -603,7 +603,6 @@ if (!local_value || local_value->type() == new_value.type()) return true; - UMA_HISTOGRAM_BOOLEAN("Sync.Preferences.RemotePrefTypeMismatch", true); DLOG(WARNING) << "Unexpected type mis-match for pref. " << "Synced value for " << pref_name << " is of type " << new_value.type() << " which doesn't match the locally "
diff --git a/components/sync_preferences/pref_service_syncable_unittest.cc b/components/sync_preferences/pref_service_syncable_unittest.cc index 9d83153a..a9060d4 100644 --- a/components/sync_preferences/pref_service_syncable_unittest.cc +++ b/components/sync_preferences/pref_service_syncable_unittest.cc
@@ -325,7 +325,6 @@ // Verifies that the implementation gracefully handles an initial remote sync // data of wrong type. The local version should not get modified in these cases. TEST_F(PrefServiceSyncableTest, ModelAssociationWithDataTypeMismatch) { - base::HistogramTester histogram_tester; prefs_.SetString(kStringPrefName, kExampleUrl0); syncer::SyncDataList in; @@ -334,8 +333,6 @@ syncer::SyncChangeList out; InitWithSyncDataTakeOutput(in, &out); EXPECT_THAT(out, IsEmpty()); - histogram_tester.ExpectBucketCount("Sync.Preferences.RemotePrefTypeMismatch", - true, 1); EXPECT_THAT(prefs_.GetString(kStringPrefName), Eq(kExampleUrl0)); } @@ -713,7 +710,6 @@ // Verifies that the implementation gracefully handles a remote update with the // wrong type. The local version should not get modified in these cases. TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionUpdateTypeMismatch) { - base::HistogramTester histogram_tester; GetPrefs()->SetString(kStringPrefName, kExampleUrl0); InitWithNoSyncData(); @@ -724,8 +720,6 @@ pref_sync_service_->ProcessSyncChanges(FROM_HERE, remote_changes); EXPECT_THAT(prefs_.GetString(kStringPrefName), Eq(kExampleUrl0)); - histogram_tester.ExpectBucketCount("Sync.Preferences.RemotePrefTypeMismatch", - true, 1); } TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionAdd) {
diff --git a/components/ukm/ukm_recorder_impl.cc b/components/ukm/ukm_recorder_impl.cc index 8ff2966..dd401ac 100644 --- a/components/ukm/ukm_recorder_impl.cc +++ b/components/ukm/ukm_recorder_impl.cc
@@ -108,6 +108,8 @@ } void RecordDroppedEntry(uint64_t event_hash, DroppedDataReason reason) { + // The enum for this histogram gets populated by the PopulateEnumWithUkmEvents + // function in populate_enums.py when producing the merged XML. base::UmaHistogramSparse("UKM.Entries.Dropped.ByEntryHash", // Truncate the unsigned 64-bit hash to 31 bits, to // make it a suitable histogram sample.
diff --git a/components/viz/host/hit_test/hit_test_query.cc b/components/viz/host/hit_test/hit_test_query.cc index 54cd565..9e81188 100644 --- a/components/viz/host/hit_test/hit_test_query.cc +++ b/components/viz/host/hit_test/hit_test_query.cc
@@ -224,8 +224,8 @@ // hit test data, e.g. overlapped by ShelfApp on ChromeOS. // The kHitTestAsk flag should be ignored in such a case because there is no // need to do async hit testing on the root merely because it was overlapped. - // TODO(yigu): Do not set the kHitTestAsk and kOverlappedRegion flags for - // root when building hit test data. + // TODO(crbug.com/1001238): Do not set the kHitTestAsk and kOverlappedRegion + // flags for root when building hit test data. bool root_view_overlapped = hit_test_data_[region_index].frame_sink_id == root_view_frame_sink_id && hit_test_data_[region_index].async_hit_test_reasons ==
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index b2ba22d8da..7a76ba1a 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -409,7 +409,7 @@ deps += [ "//ui/gfx/x" ] } - if (skia_use_dawn) { + if (skia_use_dawn && is_win) { sources += [ "display_embedder/skia_output_device_dawn.cc", "display_embedder/skia_output_device_dawn.h",
diff --git a/components/viz/service/display_embedder/skia_output_device_dawn.cc b/components/viz/service/display_embedder/skia_output_device_dawn.cc index a2ba674..9790a1b 100644 --- a/components/viz/service/display_embedder/skia_output_device_dawn.cc +++ b/components/viz/service/display_embedder/skia_output_device_dawn.cc
@@ -6,17 +6,11 @@ #include "base/check_op.h" #include "base/notreached.h" -#include "build/build_config.h" #include "components/viz/common/gpu/dawn_context_provider.h" +#include "third_party/dawn/src/include/dawn_native/D3D12Backend.h" #include "ui/gfx/presentation_feedback.h" #include "ui/gfx/vsync_provider.h" - -#if defined(OS_WIN) -#include "third_party/dawn/src/include/dawn_native/D3D12Backend.h" #include "ui/gl/vsync_provider_win.h" -#elif defined(OS_LINUX) -#include "third_party/dawn/src/include/dawn_native/VulkanBackend.h" -#endif namespace viz { @@ -41,7 +35,7 @@ DidSwapBufferCompleteCallback did_swap_buffer_complete_callback) : SkiaOutputDevice(memory_tracker, did_swap_buffer_complete_callback), context_provider_(context_provider), - widget_(widget) { + child_window_(widget) { capabilities_.output_surface_origin = origin; capabilities_.uses_default_gl_framebuffer = false; capabilities_.supports_post_sub_buffer = false; @@ -51,13 +45,16 @@ context_provider_->GetGrContext()->defaultBackendFormat( kSurfaceColorType, GrRenderable::kYes); -#if defined(OS_WIN) - vsync_provider_ = std::make_unique<gl::VSyncProviderWin>(widget_); -#endif + vsync_provider_ = std::make_unique<gl::VSyncProviderWin>(widget); + child_window_.Initialize(); } SkiaOutputDeviceDawn::~SkiaOutputDeviceDawn() = default; +gpu::SurfaceHandle SkiaOutputDeviceDawn::GetChildSurfaceHandle() const { + return child_window_.window(); +} + bool SkiaOutputDeviceDawn::Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, @@ -136,13 +133,8 @@ } void SkiaOutputDeviceDawn::CreateSwapChainImplementation() { -#if defined(OS_WIN) swap_chain_implementation_ = dawn_native::d3d12::CreateNativeSwapChainImpl( - context_provider_->GetDevice().Get(), widget_); -#else - NOTREACHED(); - ALLOW_UNUSED_LOCAL(widget_); -#endif + context_provider_->GetDevice().Get(), child_window_.window()); } } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_dawn.h b/components/viz/service/display_embedder/skia_output_device_dawn.h index 56ef86f..3d6bcf82 100644 --- a/components/viz/service/display_embedder/skia_output_device_dawn.h +++ b/components/viz/service/display_embedder/skia_output_device_dawn.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_DAWN_H_ #define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_DAWN_H_ +#include "build/build_config.h" #include "components/viz/service/display_embedder/skia_output_device.h" #include "third_party/dawn/src/include/dawn/dawn_wsi.h" #include "third_party/dawn/src/include/dawn/webgpu.h" @@ -13,6 +14,7 @@ #include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gl/child_window_win.h" namespace viz { @@ -28,6 +30,8 @@ DidSwapBufferCompleteCallback did_swap_buffer_complete_callback); ~SkiaOutputDeviceDawn() override; + gpu::SurfaceHandle GetChildSurfaceHandle() const; + // SkiaOutputDevice implementation: bool Reshape(const gfx::Size& size, float device_scale_factor, @@ -45,7 +49,6 @@ void CreateSwapChainImplementation(); DawnContextProvider* const context_provider_; - gfx::AcceleratedWidget widget_; DawnSwapChainImplementation swap_chain_implementation_; wgpu::SwapChain swap_chain_; wgpu::Texture texture_; @@ -56,6 +59,13 @@ sk_sp<SkColorSpace> sk_color_space_; GrBackendTexture backend_texture_; + // D3D12 requires that we use flip model swap chains. Flip swap chains + // require that the swap chain be connected with DWM. DWM requires that + // the rendering windows are owned by the process that's currently doing + // the rendering. gl::ChildWindowWin creates and owns a window which is + // reparented by the browser to be a child of its window. + gl::ChildWindowWin child_window_; + DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceDawn); };
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 4f769e5..9f66272 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -83,8 +83,10 @@ #if BUILDFLAG(SKIA_USE_DAWN) #include "components/viz/common/gpu/dawn_context_provider.h" +#if defined(OS_WIN) #include "components/viz/service/display_embedder/skia_output_device_dawn.h" #endif +#endif namespace viz { @@ -1626,11 +1628,20 @@ output_device_ = std::make_unique<SkiaOutputDeviceX11>( context_state_, dependency_->GetSurfaceHandle(), memory_tracker_.get(), did_swap_buffer_complete_callback_); +#elif defined(OS_WIN) + std::unique_ptr<SkiaOutputDeviceDawn> output_device = + std::make_unique<SkiaOutputDeviceDawn>( + dawn_context_provider_, dependency_->GetSurfaceHandle(), + gfx::SurfaceOrigin::kTopLeft, memory_tracker_.get(), + did_swap_buffer_complete_callback_); + const gpu::SurfaceHandle child_surface_handle = + output_device->GetChildSurfaceHandle(); + DidCreateAcceleratedSurfaceChildWindow(dependency_->GetSurfaceHandle(), + child_surface_handle); + output_device_ = std::move(output_device); #else - output_device_ = std::make_unique<SkiaOutputDeviceDawn>( - dawn_context_provider_, dependency_->GetSurfaceHandle(), - gfx::SurfaceOrigin::kTopLeft, memory_tracker_.get(), - did_swap_buffer_complete_callback_); + NOTREACHED(); + return false; #endif } #endif
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc index dc602776..896b036f 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -183,7 +183,7 @@ } void CompositorFrameSinkSupport::OnSurfaceProcessed(Surface* surface) { - DidReceiveCompositorFrameAck(); + DidReceiveCompositorFrameAck(/*early_ack*/ false); } void CompositorFrameSinkSupport::OnSurfaceAggregatedDamage( @@ -555,6 +555,35 @@ // Make sure we periodically check if the frame should activate. pending_surfaces_.insert(current_surface); UpdateNeedsBeginFramesInternal(); + // Ack a pending surface early the client's scheduler to schedule frames + // for future surface changes This case happens when screen rotation takes + // place while there is an active frame when this takes place it has a + // unique signature of 2 consecutive submit frame requests with + // clients_needs_begin_frame_ is set (high) and 1st frame is not a new + // surface and 2nd frame is a new surface. For only this sequence send an + // early ack to the client by using OnSurfaceProcessed. Setting the + // early_ack during the call to denote that an early ACK took place. This + // prevents sending a second ack for the frame when it is activated. To + // ensure only this sequence is early acked, the + // last_pending_frame_was_new_surface_ flag is used to ensure the sequence + // is correct using current_surface == prev_surface => NOT new_surface ID, + // to limit the when the early ack is sent. + // In some cases the 2 frame comes and require early ack before the + // surface sync work is completed add counter early_acked_count_ to make + // sure right ack get cleared + if (client_needs_begin_frame_) { + if ((current_surface == prev_surface) || + last_pending_frame_was_new_surface_) { + early_acked_count_++; + DidReceiveCompositorFrameAck(/*early_ack*/ true); + last_pending_frame_was_new_surface_ = + !last_pending_frame_was_new_surface_; + } else { + if (current_surface != prev_surface) { + last_pending_frame_was_new_surface_ = false; + } + } + } break; case Surface::QueueFrameResult::ACCEPTED_ACTIVE: // Nothing to do here. @@ -585,22 +614,39 @@ surface_returned_resources_.clear(); } -void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() { - DCHECK_GT(ack_pending_count_, 0); - ack_pending_count_--; - if (!client_) - return; +void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck(bool early_ack) { + // Only do early ack on frame that don't have callback + if (early_ack) { + DCHECK_GT(early_acked_count_, 0); + if (!client_ || compositor_frame_callback_) + return; + // early Ack client + client_->DidReceiveCompositorFrameAck(surface_returned_resources_); + // don't clear resources_ as it is still been used by surface_manager + } else { // actual ack + DCHECK_GT(ack_pending_count_, 0); + ack_pending_count_--; + if (!client_) + return; - // If we have a callback, we only return the resource on onBeginFrame. - if (compositor_frame_callback_) { - callback_received_receive_ack_ = true; - UpdateNeedsBeginFramesInternal(); - HandleCallback(); - return; + // If we have a callback, we only return the resource on onBeginFrame. + if (compositor_frame_callback_) { + if (early_acked_count_ > 0) // if there was an early ack decrement it. + early_acked_count_--; + callback_received_receive_ack_ = true; + UpdateNeedsBeginFramesInternal(); + HandleCallback(); + return; + } + + if (early_acked_count_ == 0) { // no early ACK has been sent, send an ACK + client_->DidReceiveCompositorFrameAck(surface_returned_resources_); + } else { // early count is bigger than zero, decrement it + early_acked_count_--; + } + // for any ack request, that is not early clear resources + surface_returned_resources_.clear(); } - - client_->DidReceiveCompositorFrameAck(surface_returned_resources_); - surface_returned_resources_.clear(); } void CompositorFrameSinkSupport::DidPresentCompositorFrame( @@ -639,15 +685,15 @@ std::vector<ui::LatencyInfo> latency_info) { TRACE_EVENT_INSTANT0("viz", "DidRejectCompositorFrame", TRACE_EVENT_SCOPE_THREAD); - // TODO(eseckler): Should these be stored and attached to the next successful - // frame submission instead? + // TODO(eseckler): Should these be stored and attached to the next + // successful frame submission instead? for (ui::LatencyInfo& info : latency_info) info.Terminate(); std::vector<ReturnedResource> resources = TransferableResource::ReturnResources(frame_resource_list); ReturnResources(resources); - DidReceiveCompositorFrameAck(); + DidReceiveCompositorFrameAck(/*early_ack*/ false); DidPresentCompositorFrame(frame_token, base::TimeTicks(), gfx::SwapTimings(), gfx::PresentationFeedback::Failure()); } @@ -834,8 +880,8 @@ return false; } - // We might throttle this OnBeginFrame() if it's been less than a second since - // the last one was sent. + // We might throttle this OnBeginFrame() if it's been less than a second + // since the last one was sent. bool can_throttle = (frame_time - last_frame_time_) < base::TimeDelta::FromSeconds(1); @@ -851,8 +897,8 @@ return true; } - // We should never throttle BeginFrames if there is another client waiting for - // this client to submit a frame. + // We should never throttle BeginFrames if there is another client waiting + // for this client to submit a frame. if (surface_manager_->HasBlockedEmbedder(frame_sink_id_)) { RecordShouldSendBeginFrame(SendBeginFrameResult::kSendBlockedEmbedded); return true;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h index fe2449d8b..ac53030 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -208,7 +208,7 @@ // Creates a surface reference from the top-level root to |surface_id|. SurfaceReference MakeTopLevelRootReference(const SurfaceId& surface_id); - void DidReceiveCompositorFrameAck(); + void DidReceiveCompositorFrameAck(bool early_ack); void DidPresentCompositorFrame(uint32_t frame_token, base::TimeTicks draw_start_timestamp, const gfx::SwapTimings& swap_timings, @@ -322,6 +322,8 @@ compositor_frame_callback_; bool callback_received_begin_frame_ = true; bool callback_received_receive_ack_ = true; + bool last_pending_frame_was_new_surface_ = false; + uint8_t early_acked_count_ = 0; uint32_t trace_sequence_ = 0; BeginFrameTracker begin_frame_tracker_;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc index 04968717..2f7b1a1 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -28,12 +28,12 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/khronos/GLES2/gl2.h" -using testing::UnorderedElementsAre; -using testing::IsEmpty; -using testing::SizeIs; -using testing::Invoke; using testing::_; using testing::Eq; +using testing::Invoke; +using testing::IsEmpty; +using testing::SizeIs; +using testing::UnorderedElementsAre; namespace viz { namespace { @@ -111,6 +111,7 @@ manager_.InvalidateFrameSinkId(kArbitraryFrameSinkId); manager_.surface_manager()->RemoveObserver(&surface_observer_); } + bool GetEarlyAckCount() const { return support_->early_acked_count_; } void AddResourcesToFrame(CompositorFrame* frame, ResourceId* resource_ids, @@ -1437,5 +1438,74 @@ support->SetNeedsBeginFrame(false); } +// Check CompositorFrame get an early ack if the surface id needs to have +// pending child needsBeginFrame = true, and NOT new surface ID, then followed +// by needsBeginFrame = true, and new Surface ID, other classes should not get +// an early ACK. crbug.com/1060058) +TEST_F(CompositorFrameSinkSupportTest, PassesEarlyAcks) { + SurfaceId id(support_->frame_sink_id(), local_surface_id_); + LocalSurfaceId child_local_surface_id(1, kAnotherArbitraryToken); + SurfaceId child_id(kAnotherArbitraryFrameSinkId, child_local_surface_id); + MockCompositorFrameSinkClient mock_client; + uint8_t EarlyAckCount; + support_->SetNeedsBeginFrame(true); + + // Submit a frame with size (5,5). + auto frame = CompositorFrameBuilder() + .AddRenderPass(gfx::Rect(5, 5), gfx::Rect()) + .SetActivationDependencies({child_id}) + .Build(); + auto result = support_->MaybeSubmitCompositorFrame( + local_surface_id_, std::move(frame), base::nullopt, 0, + mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback()); + // should get NOT early ACK, NeedsBeginFrame= true, and new surface ID (need + // to have a NOT new Surface ID) + EXPECT_EQ(GetEarlyAckCount(), 0); + + // send a same surface id with new dependencies. + LocalSurfaceId child_local_surface_id2(2, kAnotherArbitraryToken); + SurfaceId child_id2(kAnotherArbitraryFrameSinkId, child_local_surface_id2); + frame = CompositorFrameBuilder() + .AddRenderPass(gfx::Rect(5, 5), gfx::Rect()) + .SetActivationDependencies({child_id2}) + .Build(); + result = support_->MaybeSubmitCompositorFrame( + local_surface_id_, std::move(frame), base::nullopt, 0, + mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback()); + EXPECT_EQ(SubmitResult::ACCEPTED, result); + // should get early ACK, count should be 1, NeedsBeginFrame= true, and not new + // surface ID + EXPECT_EQ(GetEarlyAckCount(), 1); + EarlyAckCount = GetEarlyAckCount(); + + // send new surface id with dependencies. + LocalSurfaceId local_surface_id2(6, kArbitraryToken); + LocalSurfaceId child_local_surface_id3(2, kAnotherArbitraryToken); + SurfaceId child_id3(kAnotherArbitraryFrameSinkId, child_local_surface_id3); + + frame = CompositorFrameBuilder() + .AddRenderPass(gfx::Rect(5, 5), gfx::Rect()) + .SetActivationDependencies({child_id3}) + .Build(); + + result = support_->MaybeSubmitCompositorFrame( + local_surface_id2, std::move(frame), base::nullopt, 0, + mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback()); + // should get early ACK, NeedsBeginFrame= true, and 1st new surface ID + // hence the count should not drop, it be either 1 or 2 + EXPECT_GE(GetEarlyAckCount(), EarlyAckCount); + EarlyAckCount = GetEarlyAckCount(); + // set a surface with needbeginframe = false, should not get early ack + support_->SetNeedsBeginFrame(false); + frame = CompositorFrameBuilder() + .AddRenderPass(gfx::Rect(5, 5), gfx::Rect()) + .Build(); + result = support_->MaybeSubmitCompositorFrame( + local_surface_id2, std::move(frame), base::nullopt, 0, + mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback()); + // should get early NOT ACK, hence it the count should not increase, it could + // decrease + EXPECT_LE(GetEarlyAckCount(), EarlyAckCount); +} } // namespace viz
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc index 24770ba..08338b4 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -782,8 +782,11 @@ frame.get(), gfx::Rect(content_rect.origin(), AdjustSizeForPixelFormat(result->size()))); - if (content_version > content_version_in_marked_frame_) { + if (content_version > content_version_in_marked_frame_ || + (content_version == content_version_in_marked_frame_ && + frame->coded_size() != marked_frame_size_)) { frame_pool_.MarkFrame(*frame); + marked_frame_size_ = frame->coded_size(); content_version_in_marked_frame_ = content_version; } }
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h index 36db91ce..2f0e13f 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -299,6 +299,8 @@ int64_t content_version_in_marked_frame_ = -1; + gfx::Size marked_frame_size_; + // A queue of captured frames pending delivery. This queue is used to re-order // frames, if they should happen to be captured out-of-order. struct CapturedFrame {
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc index 1e99e7b9..11b9327 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -89,10 +89,11 @@ // The location of the letterboxed content within each VideoFrame. All pixels // outside of this region should be black. gfx::Rect expected_content_rect; -} kSizeSets[3] = { +} kSizeSets[4] = { {gfx::Size(100, 100), gfx::Size(32, 18), gfx::Rect(6, 0, 18, 18)}, {gfx::Size(64, 18), gfx::Size(32, 18), gfx::Rect(0, 4, 32, 8)}, - {gfx::Size(64, 18), gfx::Size(64, 18), gfx::Rect(0, 0, 64, 18)}}; + {gfx::Size(64, 18), gfx::Size(64, 18), gfx::Rect(0, 0, 64, 18)}, + {gfx::Size(100, 100), gfx::Size(16, 8), gfx::Rect(0, 0, 8, 8)}}; constexpr float kDefaultDeviceScaleFactor = 1.f; constexpr float kDefaultPageScaleFactor = 1.f; @@ -450,6 +451,14 @@ size_set_.capture_size, false); } + void ForceOracleSize(const SizeSet& size_set) { + size_set_ = size_set; + oracle_->set_forced_capture_size(size_set.capture_size); + frame_sink_.set_size_set(size_set); + // No call to capturer_, because this method simulates size change requested + // by the oracle, internal to the capturer. + } + const SizeSet& size_set() { return size_set_; } void NotifyFrameDamaged( @@ -962,6 +971,104 @@ StopCapture(); } +// Tests that full capture happens on capture resolution change due to oracle, +// but only once and resurrected frames are used after that. +TEST_F(FrameSinkVideoCapturerTest, + RessurectsFramesForChangingCaptureResolution) { + frame_sink_.SetCopyOutputColor(YUVColor{0x80, 0x80, 0x80}); + EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) + .WillRepeatedly(Return(&frame_sink_)); + + capturer_->ChangeTarget(kFrameSinkId); + + MockConsumer consumer; + constexpr int num_refresh_frames = 3; // Initial, plus two refreshes after + // downscale and upscale. + constexpr int num_update_frames = 3; + + int expected_frames_count = 0; + int expected_copy_results = 0; + + EXPECT_CALL(consumer, OnFrameCapturedMock()) + .Times(num_refresh_frames + num_update_frames); + EXPECT_CALL(consumer, OnStopped()).Times(1); + StartCapture(&consumer); + + // 1. The first frame captured automatically once the capture stats. + // It will be marked as the latest content in the buffer. + EXPECT_FALSE(IsRefreshRetryTimerRunning()); + ++expected_copy_results; + ++expected_frames_count; + frame_sink_.SendCopyOutputResult(expected_copy_results - 1); + ASSERT_EQ(expected_copy_results, frame_sink_.num_copy_results()); + EXPECT_EQ(expected_frames_count, consumer.num_frames_received()); + consumer.SendDoneNotification(expected_copy_results - 1); + + // 2. Another frame is captured, but there was no updates since the previous + // frame, therefore the marked frame should be resurrected, without making an + // actual request. + capturer_->RequestRefreshFrame(); + AdvanceClockForRefreshTimer(); + ++expected_frames_count; + EXPECT_EQ(expected_copy_results, frame_sink_.num_copy_results()); + EXPECT_EQ(expected_frames_count, consumer.num_frames_received()); + EXPECT_FALSE(IsRefreshRetryTimerRunning()); + // If we do not advance the clock, the oracle will reject capture due to + // frame rate limits. + AdvanceClockToNextVsync(); + + // 3. Simulate a change in the oracle imposed capture size (e.g. due to + // overuse). This frame is of a different size than the cached frame and will + // be captured with a CopyOutputRequest. + ForceOracleSize(kSizeSets[3]); + capturer_->RequestRefreshFrame(); + AdvanceClockForRefreshTimer(); + ++expected_copy_results; + ++expected_frames_count; + frame_sink_.SendCopyOutputResult(expected_copy_results - 1); + ASSERT_EQ(expected_copy_results, frame_sink_.num_copy_results()); + EXPECT_EQ(expected_frames_count, consumer.num_frames_received()); + consumer.SendDoneNotification(expected_copy_results - 1); + + // 4. Another frame is captured, but there was no updates since the previous + // frame, therefore the marked frame should be resurrected, without making an + // actual request. + capturer_->RequestRefreshFrame(); + AdvanceClockForRefreshTimer(); + ++expected_frames_count; + EXPECT_EQ(expected_copy_results, frame_sink_.num_copy_results()); + EXPECT_EQ(expected_frames_count, consumer.num_frames_received()); + EXPECT_FALSE(IsRefreshRetryTimerRunning()); + // If we do not advance the clock, the oracle will reject capture due to + // frame rate limits. + AdvanceClockToNextVsync(); + + // 5. Simulate a change in the oracle imposed capture size (e.g. due to + // overuse). This frame is of a different size than the cached frame and will + // be captured with a CopyOutputRequest. + ForceOracleSize(kSizeSets[0]); + capturer_->RequestRefreshFrame(); + AdvanceClockForRefreshTimer(); + ++expected_copy_results; + ++expected_frames_count; + frame_sink_.SendCopyOutputResult(expected_copy_results - 1); + ASSERT_EQ(expected_copy_results, frame_sink_.num_copy_results()); + EXPECT_EQ(expected_frames_count, consumer.num_frames_received()); + consumer.SendDoneNotification(expected_copy_results - 1); + + // 6. Another frame is captured, but there was no updates since the previous + // frame, therefore the marked frame should be resurrected, without making an + // actual request. + capturer_->RequestRefreshFrame(); + AdvanceClockForRefreshTimer(); + ++expected_frames_count; + EXPECT_EQ(expected_copy_results, frame_sink_.num_copy_results()); + EXPECT_EQ(expected_frames_count, consumer.num_frames_received()); + EXPECT_FALSE(IsRefreshRetryTimerRunning()); + + StopCapture(); +} + // Tests that CompositorFrameMetadata variables (|device_scale_factor|, // |page_scale_factor| and |root_scroll_offset|) are sent along with each frame, // and refreshes cause variables of the cached CompositorFrameMetadata
diff --git a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc index 39678e5..04d1652 100644 --- a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc +++ b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc
@@ -38,6 +38,10 @@ if (it->mapping.size() < bytes_required) { continue; } + // The buffer will possibly be rewritten, so the marked frame may be lost. + if (it->mapping.memory() == marked_frame_buffer_) { + ClearFrameMarking(); + } PooledBuffer taken = std::move(*it); available_buffers_.erase(it.base() - 1); return WrapBuffer(std::move(taken), format, size);
diff --git a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc index 86233d74..34b89c1 100644 --- a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc
@@ -293,6 +293,38 @@ ASSERT_FALSE(pool.HasMarkedFrameWithSize(kBiggerSize)); } +TEST(InterprocessFramePoolTest, FrameMarkingIsLostWhenBufferIsReused) { + InterprocessFramePool pool(2); + + // Reserve enough frames to hit capacity. + scoped_refptr<media::VideoFrame> frame1 = + pool.ReserveVideoFrame(kFormat, kSize); + scoped_refptr<media::VideoFrame> frame2 = + pool.ReserveVideoFrame(kFormat, kSize); + ASSERT_TRUE(frame1); + EXPECT_TRUE(frame2); + + // Mark one of them + pool.MarkFrame(*frame1); + EXPECT_TRUE(pool.HasMarkedFrameWithSize(kSize)); + + // Release all frames + frame1 = nullptr; + frame2 = nullptr; + + // Reserve all frames again but this time request a smaller size. + // This should lead to all buffers being reused and the marking being + // lost. + gfx::Size kSmallerSize(kSize.width() - 2, kSize.height() - 2); + frame1 = pool.ReserveVideoFrame(kFormat, kSmallerSize); + frame2 = pool.ReserveVideoFrame(kFormat, kSmallerSize); + EXPECT_TRUE(frame1); + EXPECT_TRUE(frame2); + + EXPECT_FALSE(pool.HasMarkedFrameWithSize(kSize)); + EXPECT_FALSE(pool.HasMarkedFrameWithSize(kSmallerSize)); +} + TEST(InterprocessFramePoolTest, ReportsCorrectUtilization) { InterprocessFramePool pool(2); ASSERT_EQ(0.0f, pool.GetUtilization());
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc index 7bf60d54..abc989b 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -170,6 +170,8 @@ AddPropertyFilter(property_filters, "protected"); AddPropertyFilter(property_filters, "required"); AddPropertyFilter(property_filters, "select*"); + AddPropertyFilter(property_filters, "selectedFromFocus=*", + PropertyFilter::DENY); AddPropertyFilter(property_filters, "visited"); // Other attributes AddPropertyFilter(property_filters, "busy=true");
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index 7f0fb603..aa7d4f1 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -917,11 +917,7 @@ if (!delegate_) return; - ui::AXActionData action_data; - action_data.action = ax::mojom::Action::kHitTest; - action_data.target_point = frame_point; - action_data.hit_test_event_to_fire = ax::mojom::Event::kHover; - delegate_->AccessibilityPerformAction(action_data); + delegate_->AccessibilityHitTest(frame_point, ax::mojom::Event::kHover, 0, {}); } gfx::Rect BrowserAccessibilityManager::GetViewBoundsInScreenCoordinates()
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h index 3b3a9c4..809ca3a 100644 --- a/content/browser/accessibility/browser_accessibility_manager.h +++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -96,6 +96,12 @@ virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessibleForWindow() = 0; virtual WebContents* AccessibilityWebContents() = 0; + virtual void AccessibilityHitTest( + const gfx::Point& point_in_frame_pixels, + ax::mojom::Event opt_event_to_fire, + int opt_request_id, + base::OnceCallback<void(BrowserAccessibilityManager* hit_manager, + int hit_node_id)> opt_callback) = 0; // Returns true if this delegate represents the main (topmost) frame in a // tree of frames.
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index bbc50be..c705311 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -211,6 +211,8 @@ AddPropertyFilter(property_filters, "layout-guess:*", PropertyFilter::ALLOW); AddPropertyFilter(property_filters, "select*"); + AddPropertyFilter(property_filters, "selectedFromFocus=*", + PropertyFilter::DENY); AddPropertyFilter(property_filters, "descript*"); AddPropertyFilter(property_filters, "check*"); AddPropertyFilter(property_filters, "horizontal"); @@ -2145,6 +2147,22 @@ RunHtmlTest(FILE_PATH_LITERAL("select.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilitySelectFollowsFocus) { + RunHtmlTest(FILE_PATH_LITERAL("select-follows-focus.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilitySelectFollowsFocusAriaSelectedFalse) { + RunHtmlTest( + FILE_PATH_LITERAL("select-follows-focus-aria-selected-false.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilitySelectFollowsFocusMultiselect) { + RunHtmlTest(FILE_PATH_LITERAL("select-follows-focus-multiselect.html")); +} + #if defined(OS_LINUX) #define MAYBE_AccessibilitySource DISABLED_AccessibilitySource #else
diff --git a/content/browser/accessibility/hit_testing_browsertest.cc b/content/browser/accessibility/hit_testing_browsertest.cc index 47120dc..26cbd045 100644 --- a/content/browser/accessibility/hit_testing_browsertest.cc +++ b/content/browser/accessibility/hit_testing_browsertest.cc
@@ -5,6 +5,7 @@ #include "content/browser/accessibility/hit_testing_browsertest.h" #include "base/check.h" +#include "base/test/bind_test_util.h" #include "build/build_config.h" #include "build/chromecast_buildflags.h" #include "content/browser/accessibility/accessibility_tree_formatter_blink.h" @@ -138,7 +139,8 @@ action_data.action = ax::mojom::Action::kHitTest; action_data.target_point = CSSToFramePoint(point); action_data.hit_test_event_to_fire = event_to_fire; - manager->delegate()->AccessibilityPerformAction(action_data); + manager->delegate()->AccessibilityHitTest(CSSToFramePoint(point), + event_to_fire, 0, {}); event_waiter.WaitForNotification(); RenderFrameHostImpl* target_frame = event_waiter.event_render_frame_host(); @@ -156,6 +158,30 @@ } BrowserAccessibility* +AccessibilityHitTestingBrowserTest::AsyncHitTestAndWaitForCallback( + const gfx::Point& point) { + BrowserAccessibilityManager* manager = GetRootBrowserAccessibilityManager(); + + gfx::Point target_point = CSSToFramePoint(point); + base::RunLoop run_loop; + BrowserAccessibilityManager* hit_manager = nullptr; + int hit_node_id = 0; + + auto callback = [&](BrowserAccessibilityManager* manager, int node_id) { + hit_manager = manager; + hit_node_id = node_id; + run_loop.QuitClosure().Run(); + }; + manager->delegate()->AccessibilityHitTest( + target_point, ax::mojom::Event::kNone, 0, + base::BindLambdaForTesting(callback)); + run_loop.Run(); + + BrowserAccessibility* hit_node = hit_manager->GetFromID(hit_node_id); + return hit_node; +} + +BrowserAccessibility* AccessibilityHitTestingBrowserTest::CallCachingAsyncHitTest( const gfx::Point& page_point) { gfx::Point screen_point = CSSToPhysicalPixelPoint(page_point); @@ -362,6 +388,10 @@ BrowserAccessibility* expected_node = FindNode(ax::mojom::Role::kGenericContainer, "rect2"); EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_2_point, expected_node, hit_node); + + // Try callback API. + hit_node = AsyncHitTestAndWaitForCallback(rect_2_point); + EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_2_point, expected_node, hit_node); } // Test a hit on a rect in the iframe. @@ -372,6 +402,10 @@ FindNode(ax::mojom::Role::kGenericContainer, "rectB"); EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_b_point, expected_node, hit_node); + // Try callback API. + hit_node = AsyncHitTestAndWaitForCallback(rect_b_point); + EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_b_point, expected_node, hit_node); + // Test with a different event. hit_node = HitTestAndWaitForResultWithEvent(rect_b_point, ax::mojom::Event::kAlert); @@ -400,7 +434,14 @@ EXPECT_TRUE(NavigateToURL(shell(), url)); waiter.WaitForNotification(); - BrowserAccessibility* hit_node = HitTestAndWaitForResult(gfx::Point(-1, -1)); + gfx::Point out_of_bounds_point(-1, -1); + + BrowserAccessibility* hit_node = HitTestAndWaitForResult(out_of_bounds_point); + ASSERT_TRUE(hit_node != nullptr); + ASSERT_EQ(ax::mojom::Role::kRootWebArea, hit_node->GetRole()); + + // Try callback API. + hit_node = AsyncHitTestAndWaitForCallback(out_of_bounds_point); ASSERT_TRUE(hit_node != nullptr); ASSERT_EQ(ax::mojom::Role::kRootWebArea, hit_node->GetRole()); } @@ -448,6 +489,10 @@ BrowserAccessibility* expected_node = FindNode(ax::mojom::Role::kGenericContainer, "rectB"); EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_b_point, expected_node, hit_node); + + // Try callback API. + hit_node = AsyncHitTestAndWaitForCallback(rect_b_point); + EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_b_point, expected_node, hit_node); } // Scroll div up 100px. @@ -468,6 +513,10 @@ BrowserAccessibility* expected_node = FindNode(ax::mojom::Role::kGenericContainer, "rectG"); EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_g_point, expected_node, hit_node); + + // Try callback API. + hit_node = AsyncHitTestAndWaitForCallback(rect_g_point); + EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_g_point, expected_node, hit_node); } } @@ -595,6 +644,10 @@ BrowserAccessibility* expected_node = FindNode(ax::mojom::Role::kGenericContainer, "rect2"); EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_2_point, expected_node, hit_node); + + // Try callback API. + hit_node = AsyncHitTestAndWaitForCallback(rect_2_point); + EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_2_point, expected_node, hit_node); } // Test a hit on a rect in the iframe. @@ -604,6 +657,10 @@ BrowserAccessibility* expected_node = FindNode(ax::mojom::Role::kGenericContainer, "rectB"); EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_b_point, expected_node, hit_node); + + // Try callback API. + hit_node = AsyncHitTestAndWaitForCallback(rect_b_point); + EXPECT_ACCESSIBILITY_HIT_TEST_RESULT(rect_b_point, expected_node, hit_node); } }
diff --git a/content/browser/accessibility/hit_testing_browsertest.h b/content/browser/accessibility/hit_testing_browsertest.h index 05b294c..418d3f9 100644 --- a/content/browser/accessibility/hit_testing_browsertest.h +++ b/content/browser/accessibility/hit_testing_browsertest.h
@@ -35,11 +35,19 @@ gfx::Rect GetViewBoundsInScreenCoordinates(); gfx::Point CSSToFramePoint(gfx::Point css_point); gfx::Point CSSToPhysicalPixelPoint(gfx::Point css_point); + + // Test the hit test action that fires an event. BrowserAccessibility* HitTestAndWaitForResultWithEvent( const gfx::Point& point, ax::mojom::Event event_to_fire); BrowserAccessibility* HitTestAndWaitForResult(const gfx::Point& point); + + // Test the hit test mojo RPC that calls a callback function. + BrowserAccessibility* AsyncHitTestAndWaitForCallback(const gfx::Point& point); + + // Test the caching async hit test. BrowserAccessibility* CallCachingAsyncHitTest(const gfx::Point& page_point); + BrowserAccessibility* CallNearestLeafNode(const gfx::Point& page_point); void SynchronizeThreads(); base::string16 FormatHitTestAccessibilityTree();
diff --git a/content/browser/accessibility/test_browser_accessibility_delegate.cc b/content/browser/accessibility/test_browser_accessibility_delegate.cc index 9e3fe4f..72d1d261 100644 --- a/content/browser/accessibility/test_browser_accessibility_delegate.cc +++ b/content/browser/accessibility/test_browser_accessibility_delegate.cc
@@ -55,6 +55,13 @@ return is_root_frame_; } +void TestBrowserAccessibilityDelegate::AccessibilityHitTest( + const gfx::Point& point_in_frame_pixels, + ax::mojom::Event opt_event_to_fire, + int opt_request_id, + base::OnceCallback<void(BrowserAccessibilityManager* hit_manager, + int hit_node_id)> opt_callback) {} + bool TestBrowserAccessibilityDelegate::got_fatal_error() const { return got_fatal_error_; }
diff --git a/content/browser/accessibility/test_browser_accessibility_delegate.h b/content/browser/accessibility/test_browser_accessibility_delegate.h index 818e827b..5b9b260 100644 --- a/content/browser/accessibility/test_browser_accessibility_delegate.h +++ b/content/browser/accessibility/test_browser_accessibility_delegate.h
@@ -25,6 +25,12 @@ override; WebContents* AccessibilityWebContents() override; bool AccessibilityIsMainFrame() override; + void AccessibilityHitTest( + const gfx::Point& point_in_frame_pixels, + ax::mojom::Event opt_event_to_fire, + int opt_request_id, + base::OnceCallback<void(BrowserAccessibilityManager* hit_manager, + int hit_node_id)> opt_callback) override; bool got_fatal_error() const; void reset_got_fatal_error();
diff --git a/content/browser/android/gesture_listener_manager.cc b/content/browser/android/gesture_listener_manager.cc index 3a0e3d7..97b1902 100644 --- a/content/browser/android/gesture_listener_manager.cc +++ b/content/browser/android/gesture_listener_manager.cc
@@ -137,6 +137,16 @@ rwhva_->SetMultiTouchZoomSupportEnabled(enabled); } +void GestureListenerManager::SetHasListenersAttached(JNIEnv* env, + jboolean enabled) { + if (has_listeners_attached_ == enabled) + return; + + has_listeners_attached_ = enabled; + if (rwhva_) + rwhva_->UpdateReportAllRootScrolls(); +} + void GestureListenerManager::GestureEventAck( const blink::WebGestureEvent& event, blink::mojom::InputEventResultState ack_result) { @@ -223,10 +233,9 @@ RenderWidgetHostViewAndroid* old_rwhva, RenderWidgetHostViewAndroid* new_rwhva) { if (old_rwhva) - old_rwhva->set_gesture_listener_manager(nullptr); - if (new_rwhva) { - new_rwhva->set_gesture_listener_manager(this); - } + old_rwhva->SetGestureListenerManager(nullptr); + if (new_rwhva) + new_rwhva->SetGestureListenerManager(this); rwhva_ = new_rwhva; }
diff --git a/content/browser/android/gesture_listener_manager.h b/content/browser/android/gesture_listener_manager.h index 12c831f..93413ab1 100644 --- a/content/browser/android/gesture_listener_manager.h +++ b/content/browser/android/gesture_listener_manager.h
@@ -43,6 +43,8 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, jboolean enabled); + bool has_listeners_attached() const { return has_listeners_attached_; } + void SetHasListenersAttached(JNIEnv* env, jboolean enabled); void GestureEventAck(const blink::WebGestureEvent& event, blink::mojom::InputEventResultState ack_result); void DidStopFlinging(); @@ -83,6 +85,9 @@ // A weak reference to the Java GestureListenerManager object. JavaObjectWeakGlobalRef java_ref_; + // True if there is at least one listener attached. + bool has_listeners_attached_ = false; + DISALLOW_COPY_AND_ASSIGN(GestureListenerManager); };
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc index 395dbad..9e9379113 100644 --- a/content/browser/back_forward_cache_browsertest.cc +++ b/content/browser/back_forward_cache_browsertest.cc
@@ -2027,6 +2027,66 @@ blink::scheduler::WebSchedulerTrackedFeature::kIdleManager, FROM_HERE); } +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, + DoesNotCachePaymentManager) { + ASSERT_TRUE(CreateHttpsServer()->Start()); + + // 1) Navigate to a page which includes PaymentManager functionality. Note + // that service workers are used, and therefore we use https server instead of + // embedded_server() + EXPECT_TRUE(NavigateToURL( + shell(), https_server()->GetURL( + "a.com", "/payments/payment_app_invocation.html"))); + RenderFrameHostImpl* rfh_a = current_frame_host(); + RenderFrameDeletedObserver rfh_a_deleted(rfh_a); + + // Execute functionality that calls PaymentManager. + EXPECT_TRUE(ExecJs(rfh_a, R"( + new Promise(async resolve => { + registerPaymentApp(); + resolve(); + }); + )")); + + // 2) Navigate away. + EXPECT_TRUE( + NavigateToURL(shell(), https_server()->GetURL("b.com", "/title1.html"))); + + // The page uses PaymentManager so it should be deleted. + rfh_a_deleted.WaitUntilDeleted(); + + // 3) Go back. + web_contents()->GetController().GoBack(); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + ExpectNotRestored( + {BackForwardCacheMetrics::NotRestoredReason::kBlocklistedFeatures}, + FROM_HERE); + + // Note that on Mac10.10, there is occasionally blocklisting for network + // requests (kOutstandingNetworkRequestOthers). This causes flakiness if we + // check against all blocklisted features. As a result, we only check for the + // blocklist we care about. + base::HistogramBase::Sample sample = base::HistogramBase::Sample( + blink::scheduler::WebSchedulerTrackedFeature::kPaymentManager); + std::vector<base::Bucket> blocklist_values = histogram_tester_.GetAllSamples( + "BackForwardCache.HistoryNavigationOutcome." + "BlocklistedFeature"); + auto it = std::find_if( + blocklist_values.begin(), blocklist_values.end(), + [sample](const base::Bucket& bucket) { return bucket.min == sample; }); + EXPECT_TRUE(it != blocklist_values.end()); + + std::vector<base::Bucket> all_sites_blocklist_values = + histogram_tester_.GetAllSamples( + "BackForwardCache.AllSites.HistoryNavigationOutcome." + "BlocklistedFeature"); + + auto all_sites_it = std::find_if( + all_sites_blocklist_values.begin(), all_sites_blocklist_values.end(), + [sample](const base::Bucket& bucket) { return bucket.min == sample; }); + EXPECT_TRUE(all_sites_it != all_sites_blocklist_values.end()); +} + class MockAppBannerService : public blink::mojom::AppBannerService { public: MockAppBannerService() = default;
diff --git a/content/browser/browser_url_handler_impl.cc b/content/browser/browser_url_handler_impl.cc index d0a943d..88bc53e9 100644 --- a/content/browser/browser_url_handler_impl.cc +++ b/content/browser/browser_url_handler_impl.cc
@@ -125,6 +125,23 @@ RewriteURLIfNecessary(url, browser_context, &ignored_reverse_on_redirect); } +std::vector<GURL> BrowserURLHandlerImpl::GetPossibleRewrites( + const GURL& url, + BrowserContext* browser_context) { + std::vector<GURL> rewrites; + for (const auto& it : url_handlers_) { + const URLHandler& handler = it.first; + if (!handler) + continue; + + GURL mutable_url(url); + if (handler(&mutable_url, browser_context)) + rewrites.push_back(std::move(mutable_url)); + } + + return rewrites; +} + void BrowserURLHandlerImpl::FixupURLBeforeRewrite( GURL* url, BrowserContext* browser_context) {
diff --git a/content/browser/browser_url_handler_impl.h b/content/browser/browser_url_handler_impl.h index 5d83a2ff..1823ec6 100644 --- a/content/browser/browser_url_handler_impl.h +++ b/content/browser/browser_url_handler_impl.h
@@ -26,6 +26,9 @@ // BrowserURLHandler implementation: void RewriteURLIfNecessary(GURL* url, BrowserContext* browser_context) override; + std::vector<GURL> GetPossibleRewrites( + const GURL& url, + BrowserContext* browser_context) override; void SetFixupHandler(URLHandler handler) override; void AddHandlerPair(URLHandler handler, URLHandler reverse_handler) override; @@ -63,6 +66,7 @@ FRIEND_TEST_ALL_PREFIXES(BrowserURLHandlerImplTest, BasicRewriteAndReverse); FRIEND_TEST_ALL_PREFIXES(BrowserURLHandlerImplTest, NullHandlerReverse); FRIEND_TEST_ALL_PREFIXES(BrowserURLHandlerImplTest, ViewSourceReverse); + FRIEND_TEST_ALL_PREFIXES(BrowserURLHandlerImplTest, GetPossibleRewrites); DISALLOW_COPY_AND_ASSIGN(BrowserURLHandlerImpl); };
diff --git a/content/browser/browser_url_handler_impl_unittest.cc b/content/browser/browser_url_handler_impl_unittest.cc index c55206c..0f7b9fd 100644 --- a/content/browser/browser_url_handler_impl_unittest.cc +++ b/content/browser/browser_url_handler_impl_unittest.cc
@@ -5,6 +5,7 @@ #include "content/browser/browser_url_handler_impl.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_browser_context.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -98,4 +99,32 @@ ASSERT_EQ("view-source:http://foo/?a=1", url.spec()); } +// Verify that GetPossibleRewrites retrieves the rewrites from all handlers that +// match, in order of priority. +TEST_F(BrowserURLHandlerImplTest, GetPossibleRewrites) { + BrowserTaskEnvironment task_environment; + TestBrowserContext browser_context; + BrowserURLHandlerImpl handler; + + auto rewriter1 = [](GURL* url, BrowserContext* context) { + *url = GURL("https://test1.example"); + return true; + }; + auto rewriter2 = [](GURL* url, BrowserContext* context) { return false; }; + auto rewriter3 = [](GURL* url, BrowserContext* context) { + *url = GURL("https://test3.example"); + return true; + }; + handler.AddHandlerPair(rewriter1, BrowserURLHandlerImpl::null_handler()); + handler.AddHandlerPair(rewriter2, BrowserURLHandlerImpl::null_handler()); + handler.AddHandlerPair(rewriter3, BrowserURLHandlerImpl::null_handler()); + + GURL url("https://example.com"); + std::vector<GURL> rewrites = + handler.GetPossibleRewrites(url, &browser_context); + + EXPECT_THAT(rewrites, testing::ElementsAre(GURL("https://test1.example"), + GURL("https://test3.example"))); +} + } // namespace content
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index 4cb2409..f653fa34 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -9,6 +9,7 @@ #include "content/browser/devtools/browser_devtools_agent_host.h" #include "content/browser/devtools/devtools_url_loader_interceptor.h" #include "content/browser/devtools/protocol/audits_handler.h" +#include "content/browser/devtools/protocol/browser_handler.h" #include "content/browser/devtools/protocol/emulation_handler.h" #include "content/browser/devtools/protocol/fetch_handler.h" #include "content/browser/devtools/protocol/log_handler.h" @@ -23,14 +24,17 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_package/signed_exchange_envelope.h" #include "content/common/navigation_params.mojom.h" +#include "content/public/browser/browser_context.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "net/base/load_flags.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_inclusion_status.h" #include "net/http/http_request_headers.h" +#include "net/proxy_resolution/proxy_config.h" #include "net/quic/quic_transport_error.h" #include "net/ssl/ssl_info.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h" @@ -827,6 +831,18 @@ DispatchToAgents(ftn, &protocol::LogHandler::EntryAdded, entry.get()); } +void ApplyNetworkContextParamsOverrides( + BrowserContext* browser_context, + network::mojom::NetworkContextParams* context_params) { + for (auto* agent_host : BrowserDevToolsAgentHost::Instances()) { + for (auto* target_handler : + protocol::TargetHandler::ForAgentHost(agent_host)) { + target_handler->ApplyNetworkContextParamsOverrides(browser_context, + context_params); + } + } +} + } // namespace devtools_instrumentation } // namespace content
diff --git a/content/browser/devtools/devtools_instrumentation.h b/content/browser/devtools/devtools_instrumentation.h index 55bf3c8f..2889921c 100644 --- a/content/browser/devtools/devtools_instrumentation.h +++ b/content/browser/devtools/devtools_instrumentation.h
@@ -43,13 +43,14 @@ } // namespace download namespace content { -class SignedExchangeEnvelope; +class BrowserContext; class FrameTreeNode; class NavigationHandle; class NavigationRequest; class NavigationThrottle; class RenderFrameHostImpl; class RenderProcessHost; +class SignedExchangeEnvelope; class WebContents; struct SignedExchangeError; @@ -202,6 +203,10 @@ const GURL& url, const base::Optional<net::QuicTransportError>& error); +void ApplyNetworkContextParamsOverrides( + BrowserContext* browser_context, + network::mojom::NetworkContextParams* network_context_params); + } // namespace devtools_instrumentation } // namespace content
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc index 4614ecae..96ddb37 100644 --- a/content/browser/devtools/protocol/target_handler.cc +++ b/content/browser/devtools/protocol/target_handler.cc
@@ -30,6 +30,35 @@ namespace { +constexpr net::NetworkTrafficAnnotationTag + kSettingsProxyConfigTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("devtools_proxy_config", R"( + semantics { + sender: "Proxy Configuration over Developer Tools" + description: + "Used to fetch HTTP/HTTPS/SOCKS5/PAC proxy configuration when " + "proxy is configured by DevTools. It is equivalent to the one " + "configured via the --proxy-server command line flag. " + "When proxy implies automatic configuration, it can send network " + "requests in the scope of this annotation." + trigger: + "Whenever a network request is made when the system proxy settings " + "are used, and they indicate to use a proxy server." + data: + "Proxy configuration." + destination: OTHER + destination_other: "The proxy server specified in the configuration." + } + policy { + cookies_allowed: NO + setting: + "This request cannot be disabled in settings. However it will never " + "be made if user does not run with '--remote-debugging-*' switches " + "and does not explicitly send this data over Chrome remote debugging." + policy_exception_justification: + "Not implemented, only used in DevTools and is behind a switch." + })"); + static const char kNotAllowedError[] = "Not allowed"; static const char kMethod[] = "method"; static const char kResumeMethod[] = "Runtime.runIfWaitingForDebugger"; @@ -560,6 +589,7 @@ } dispose_on_detach_context_ids_.clear(); } + contexts_with_overridden_proxy_.clear(); return Response::Success(); } @@ -950,6 +980,8 @@ protocol::Response TargetHandler::CreateBrowserContext( Maybe<bool> dispose_on_detach, + Maybe<std::string> proxy_server, + Maybe<std::string> proxy_bypass_list, std::string* out_context_id) { if (access_mode_ != AccessMode::kBrowser) return Response::ServerError(kNotAllowedError); @@ -961,6 +993,18 @@ BrowserContext* context = delegate->CreateBrowserContext(); if (!context) return Response::ServerError("Failed to create browser context."); + + if (proxy_server.isJust()) { + net::ProxyConfig proxy_config; + proxy_config.proxy_rules().ParseFromString(proxy_server.fromJust()); + if (proxy_bypass_list.isJust()) { + proxy_config.proxy_rules().bypass_rules.ParseFromString( + proxy_bypass_list.fromJust()); + } + contexts_with_overridden_proxy_[context->UniqueId()] = + std::move(proxy_config); + } + *out_context_id = context->UniqueId(); if (dispose_on_detach.fromMaybe(false)) dispose_on_detach_context_ids_.insert(*out_context_id); @@ -1024,5 +1068,15 @@ std::move(callback))); } +void TargetHandler::ApplyNetworkContextParamsOverrides( + BrowserContext* browser_context, + network::mojom::NetworkContextParams* context_params) { + auto it = contexts_with_overridden_proxy_.find(browser_context->UniqueId()); + if (it == contexts_with_overridden_proxy_.end()) + return; + context_params->initial_proxy_config = net::ProxyConfigWithAnnotation( + it->second, kSettingsProxyConfigTrafficAnnotation); +} + } // namespace protocol } // namespace content
diff --git a/content/browser/devtools/protocol/target_handler.h b/content/browser/devtools/protocol/target_handler.h index e410f6d9..bf7d2da 100644 --- a/content/browser/devtools/protocol/target_handler.h +++ b/content/browser/devtools/protocol/target_handler.h
@@ -8,12 +8,15 @@ #include <map> #include <set> +#include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/memory/weak_ptr.h" #include "content/browser/devtools/protocol/devtools_domain_handler.h" #include "content/browser/devtools/protocol/target.h" #include "content/browser/devtools/protocol/target_auto_attacher.h" #include "content/public/browser/devtools_agent_host_observer.h" +#include "net/proxy_resolution/proxy_config.h" +#include "services/network/public/mojom/network_context.mojom.h" namespace content { @@ -86,6 +89,8 @@ Response ExposeDevToolsProtocol(const std::string& target_id, Maybe<std::string> binding_name) override; Response CreateBrowserContext(Maybe<bool> dispose_on_detach, + Maybe<std::string> proxy_server, + Maybe<std::string> proxy_bypass_list, std::string* out_context_id) override; void DisposeBrowserContext( const std::string& context_id, @@ -104,6 +109,10 @@ std::unique_ptr<protocol::Array<Target::TargetInfo>>* target_infos) override; + void ApplyNetworkContextParamsOverrides( + BrowserContext* browser_context, + network::mojom::NetworkContextParams* network_context_params); + private: class Session; class Throttle; @@ -143,6 +152,7 @@ std::map<DevToolsAgentHost*, Session*> auto_attached_sessions_; std::set<DevToolsAgentHost*> reported_hosts_; base::flat_set<std::string> dispose_on_detach_context_ids_; + base::flat_map<std::string, net::ProxyConfig> contexts_with_overridden_proxy_; AccessMode access_mode_; std::string owner_target_id_; DevToolsSession* root_session_;
diff --git a/content/browser/frame_host/back_forward_cache_impl.cc b/content/browser/frame_host/back_forward_cache_impl.cc index b3bed97..e1f29e6 100644 --- a/content/browser/frame_host/back_forward_cache_impl.cc +++ b/content/browser/frame_host/back_forward_cache_impl.cc
@@ -156,7 +156,8 @@ FeatureToBit(WebSchedulerTrackedFeature::kPictureInPicture) | FeatureToBit(WebSchedulerTrackedFeature::kPortal) | FeatureToBit(WebSchedulerTrackedFeature::kSpeechRecognizer) | - FeatureToBit(WebSchedulerTrackedFeature::kIdleManager); + FeatureToBit(WebSchedulerTrackedFeature::kIdleManager) | + FeatureToBit(WebSchedulerTrackedFeature::kPaymentManager); uint64_t result = kAlwaysDisallowedFeatures;
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 588b104..7994201c 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -2747,8 +2747,11 @@ // - If the frame is in back-forward cache, it's not allowed to navigate as it // should remain frozen. Ignore the request and evict the document from // back-forward cache. + // + // If the frame is inactive, there's no need to recurse into subframes, which + // should all be inactive as well. if (frame->current_frame_host()->IsInactiveAndDisallowReactivation()) - return HistoryNavigationAction::kNone; + return HistoryNavigationAction::kStopLooking; // If there's no last committed entry, there is no previous history entry to // compare against, so fall back to a different-document load. Note that we @@ -2780,13 +2783,16 @@ // NavigationEntry, but we shouldn't delete or change what's loaded in // it. // + // Note that in this case, there is no need to keep looking for navigations + // in subframes, which would be missing FrameNavigationEntries as well. + // // It's important to check this before checking |old_item| below, since both // might be null, and in that case we still shouldn't change what's loaded in // this frame. Note that scheduling any loads assumes that |new_item| is // non-null. See https://crbug.com/1088354. FrameNavigationEntry* new_item = pending_entry_->GetFrameEntry(frame); if (!new_item) - return HistoryNavigationAction::kNone; + return HistoryNavigationAction::kStopLooking; // If there is no old FrameNavigationEntry, schedule a different-document // load. @@ -2830,10 +2836,10 @@ } // If the item sequence numbers match, there is no need to navigate this - // frame. + // frame. Keep looking for navigations in this frame's children. DCHECK_EQ(new_item->document_sequence_number(), old_item->document_sequence_number()); - return HistoryNavigationAction::kNone; + return HistoryNavigationAction::kKeepLooking; } void NavigationControllerImpl::FindFramesToNavigate( @@ -2886,6 +2892,8 @@ // For a different document, the subframes will be destroyed, so there's // no need to consider them. return; + } else if (action == HistoryNavigationAction::kStopLooking) { + return; } for (size_t i = 0; i < frame->child_count(); i++) {
diff --git a/content/browser/frame_host/navigation_controller_impl.h b/content/browser/frame_host/navigation_controller_impl.h index 57d8e75..fba67556 100644 --- a/content/browser/frame_host/navigation_controller_impl.h +++ b/content/browser/frame_host/navigation_controller_impl.h
@@ -339,7 +339,8 @@ // Defines possible actions that are returned by // DetermineActionForHistoryNavigation(). enum class HistoryNavigationAction { - kNone, + kStopLooking, + kKeepLooking, kSameDocument, kDifferentDocument, };
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 06bf07d..f576993 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -1192,6 +1192,7 @@ if (IsNavigationStarted()) { GetDelegate()->DidFinishNavigation(this); + ProcessOriginIsolationEndResult(); if (IsInMainFrame()) { TRACE_EVENT_NESTABLE_ASYNC_END2( "navigation", "Navigation StartToCommit", @@ -1849,6 +1850,77 @@ return OptInIsolationCheckResult::NONE; } +void NavigationRequest::DetermineOriginIsolationEndResult( + OptInIsolationCheckResult check_result) { + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + const url::Origin origin = url::Origin::Create(common_params_->url); + const IsolationContext& isolation_context = + render_frame_host_->GetSiteInstance()->GetIsolationContext(); + const bool got_isolated = + policy->ShouldOriginGetOptInIsolation(isolation_context, origin); + + switch (check_result) { + case OptInIsolationCheckResult::NONE: + origin_isolation_end_result_ = + got_isolated + ? OptInOriginIsolationEndResult::kNotRequestedButIsolated + : OptInOriginIsolationEndResult::kNotRequestedAndNotIsolated; + break; + case OptInIsolationCheckResult::ORIGIN_POLICY: + origin_isolation_end_result_ = + got_isolated ? OptInOriginIsolationEndResult:: + kRequestedViaOriginPolicyAndIsolated + : OptInOriginIsolationEndResult:: + kRequestedViaOriginPolicyButNotIsolated; + break; + case OptInIsolationCheckResult::HEADER: + origin_isolation_end_result_ = + got_isolated + ? OptInOriginIsolationEndResult::kRequestedViaHeaderAndIsolated + : OptInOriginIsolationEndResult:: + kRequestedViaHeaderButNotIsolated; + break; + } +} + +void NavigationRequest::ProcessOriginIsolationEndResult() { + if (!HasCommitted() || IsErrorPage() || IsSameDocument()) + return; + + if (origin_isolation_end_result_ == + OptInOriginIsolationEndResult::kRequestedViaHeaderAndIsolated || + origin_isolation_end_result_ == + OptInOriginIsolationEndResult::kRequestedViaHeaderButNotIsolated) + GetContentClient()->browser()->LogWebFeatureForCurrentPage( + render_frame_host_, blink::mojom::WebFeature::kOriginIsolationHeader); + + const url::Origin origin = url::Origin::Create(GetURL()); + + if (origin_isolation_end_result_ == + OptInOriginIsolationEndResult::kRequestedViaHeaderButNotIsolated || + origin_isolation_end_result_ == + OptInOriginIsolationEndResult:: + kRequestedViaOriginPolicyButNotIsolated) + render_frame_host_->AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kWarning, + base::StringPrintf( + "The page requested origin isolation, but could not be isolated " + "since the origin '%s' had previously been seen with no " + "isolation. Update your headers to uniformly isolate all pages " + "on the origin.", + origin.Serialize().c_str())); + + if (origin_isolation_end_result_ == + OptInOriginIsolationEndResult::kNotRequestedButIsolated) + render_frame_host_->AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kWarning, + base::StringPrintf("The page did not request origin isolation, but " + "was isolated anyway because the origin '%s' had " + "previously been isolated. Update your headers to " + "uniformly isolate all pages on the origin.", + origin.Serialize().c_str())); +} + void NavigationRequest::OnResponseStarted( network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, network::mojom::URLResponseHeadPtr response_head, @@ -2097,10 +2169,7 @@ DCHECK(render_frame_host_ || !response_should_be_rendered_); if (render_frame_host_) { - if (opt_in_isolation == OptInIsolationCheckResult::HEADER) { - GetContentClient()->browser()->LogWebFeatureForCurrentPage( - render_frame_host_, blink::mojom::WebFeature::kOriginIsolationHeader); - } + DetermineOriginIsolationEndResult(opt_in_isolation); // TODO(pmeuleman, ahemery): Only set COOP and COEP values on // RenderFrameHost when the navigation commits. In the meantime, keep them
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 305ac14..921da7c 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -218,6 +218,21 @@ }; OptInIsolationCheckResult IsOptInIsolationRequested(const GURL& url); + // The origin isolation end result is determined early in the lifecycle of a + // NavigationRequest, but used late. In particular, we want to trigger use + // counters and console warnings once navigation has committed. + enum class OptInOriginIsolationEndResult { + kNotRequestedAndNotIsolated, + kNotRequestedButIsolated, + kRequestedViaOriginPolicyButNotIsolated, + kRequestedViaOriginPolicyAndIsolated, + kRequestedViaHeaderButNotIsolated, + kRequestedViaHeaderAndIsolated + }; + void DetermineOriginIsolationEndResult( + OptInIsolationCheckResult check_result); + void ProcessOriginIsolationEndResult(); + // NavigationHandle implementation: int64_t GetNavigationId() override; const GURL& GetURL() override; @@ -1327,6 +1342,9 @@ // 'ReadyToCommit' time. base::Optional<network::mojom::WebSandboxFlags> sandbox_flags_to_commit_; + OptInOriginIsolationEndResult origin_isolation_end_result_ = + OptInOriginIsolationEndResult::kNotRequestedAndNotIsolated; + base::WeakPtrFactory<NavigationRequest> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(NavigationRequest);
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 48ef992c..111129f1 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1734,13 +1734,10 @@ if (IsInactiveAndDisallowReactivation() || !render_accessibility_) return; - // Use the dedicated HitTest method so that we can handle its response via - // mojo callback once it's been handled in the renderer process. if (action_data.action == ax::mojom::Action::kHitTest) { - render_accessibility_->HitTest( - action_data, - base::BindOnce(&RenderFrameHostImpl::RequestAXHitTestCallback, - weak_ptr_factory_.GetWeakPtr(), action_data.request_id)); + AccessibilityHitTest(action_data.target_point, + action_data.hit_test_event_to_fire, + action_data.request_id, {}); return; } @@ -1852,6 +1849,19 @@ return delegate()->GetAsWebContents(); } +void RenderFrameHostImpl::AccessibilityHitTest( + const gfx::Point& point_in_frame_pixels, + ax::mojom::Event opt_event_to_fire, + int opt_request_id, + base::OnceCallback<void(BrowserAccessibilityManager* hit_manager, + int hit_node_id)> opt_callback) { + render_accessibility_->HitTest( + point_in_frame_pixels, opt_event_to_fire, opt_request_id, + base::BindOnce(&RenderFrameHostImpl::AccessibilityHitTestCallback, + weak_ptr_factory_.GetWeakPtr(), opt_request_id, + opt_event_to_fire, std::move(opt_callback))); +} + bool RenderFrameHostImpl::AccessibilityIsMainFrame() { if (!is_active()) return false; @@ -6928,34 +6938,39 @@ dst->focused_tree_id = focused_frame->GetAXTreeID(); } -void RenderFrameHostImpl::RequestAXHitTestCallback( - int action_request_id, - mojom::ChildFrameHitTestInfoPtr child_frame_hit_test_info) { - // Not receiving a child_frame_hit_test_info means that the renderer has - // already handled this by emitting the requested event over the object found - // as the result of the hit testing process, so nothing to do. - if (!child_frame_hit_test_info) - return; - - // A child frame was found while hit testing on this frame, and so we need to - // request a new hit test over such child frame now. +void RenderFrameHostImpl::AccessibilityHitTestCallback( + int request_id, + ax::mojom::Event event_to_fire, + base::OnceCallback<void(BrowserAccessibilityManager* hit_manager, + int hit_node_id)> opt_callback, + mojom::HitTestResponsePtr hit_test_response) { auto frame_or_proxy = LookupRenderFrameHostOrProxy( - GetProcess()->GetID(), child_frame_hit_test_info->child_frame_routing_id); - RenderFrameHostImpl* child_frame = + GetProcess()->GetID(), hit_test_response->hit_frame_routing_id); + RenderFrameHostImpl* hit_frame = frame_or_proxy.proxy ? frame_or_proxy.proxy->frame_tree_node()->current_frame_host() : frame_or_proxy.frame; - if (!child_frame || child_frame->IsInactiveAndDisallowReactivation()) + if (!hit_frame || hit_frame->IsInactiveAndDisallowReactivation()) { + std::move(opt_callback).Run(nullptr, 0); return; + } - ui::AXActionData action_data; - action_data.request_id = action_request_id; - action_data.target_point = child_frame_hit_test_info->transformed_point; - action_data.action = ax::mojom::Action::kHitTest; - action_data.hit_test_event_to_fire = child_frame_hit_test_info->event_to_fire; + // If the hit node's routing ID is the same frame, we're done. If a + // callback was provided, call it with the information about the hit node. + if (hit_frame->GetRoutingID() == routing_id_) { + if (opt_callback) { + std::move(opt_callback) + .Run(hit_frame->browser_accessibility_manager(), + hit_test_response->hit_node_id); + } + return; + } - child_frame->AccessibilityPerformAction(action_data); + // The hit node has a child frame. Do a hit test in that frame's renderer. + hit_frame->AccessibilityHitTest( + hit_test_response->hit_frame_transformed_point, event_to_fire, request_id, + std::move(opt_callback)); } void RenderFrameHostImpl::RequestAXTreeSnapshotCallback( @@ -6983,6 +6998,12 @@ } GetProcess()->CreatePaymentManagerForOrigin(GetLastCommittedOrigin(), std::move(receiver)); + + // Blocklist PaymentManager from the back-forward cache as at the moment we + // don't cancel pending payment requests when the RenderFrameHost is stored + // in back-forward cache. + OnSchedulerTrackedFeatureUsed( + blink::scheduler::WebSchedulerTrackedFeature::kPaymentManager); } void RenderFrameHostImpl::CreateWebBluetoothService(
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index b75349e..d7d8fd7 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -439,6 +439,12 @@ gfx::NativeViewAccessible AccessibilityGetNativeViewAccessibleForWindow() override; WebContents* AccessibilityWebContents() override; + void AccessibilityHitTest( + const gfx::Point& point_in_frame_pixels, + ax::mojom::Event opt_event_to_fire, + int opt_request_id, + base::OnceCallback<void(BrowserAccessibilityManager* hit_manager, + int hit_node_id)> opt_callback) override; bool AccessibilityIsMainFrame() override; // RenderProcessHostObserver implementation. @@ -2053,11 +2059,14 @@ // AXTreeData structure. void AXContentTreeDataToAXTreeData(ui::AXTreeData* dst); - // Callback that will be called as a response to the request to perform a hit - // test over the accessibility object at given point. - void RequestAXHitTestCallback( + // Callback in response to an accessibility hit test triggered by + // AccessibilityHitTest. + void AccessibilityHitTestCallback( int action_request_id, - mojom::ChildFrameHitTestInfoPtr child_frame_hit_test_result); + ax::mojom::Event event_to_fire, + base::OnceCallback<void(BrowserAccessibilityManager* hit_manager, + int hit_node_id)> opt_callback, + mojom::HitTestResponsePtr hit_test_response); // Callback that will be called as a response to the call to the method // content::mojom::RenderAccessibility::SnapshotAccessibilityTree(). The
diff --git a/content/browser/isolated_origin_browsertest.cc b/content/browser/isolated_origin_browsertest.cc index b43036c..cf5127f 100644 --- a/content/browser/isolated_origin_browsertest.cc +++ b/content/browser/isolated_origin_browsertest.cc
@@ -511,7 +511,15 @@ // Change OriginPolicy manifest to stop isolating the sub-origin. It should // still be isolated, to remain consistent with the other frame. SetOriginPolicyManifest(R"({ })"); + + WebContentsConsoleObserver console_observer(shell()->web_contents()); + console_observer.SetPattern( + "The page did not request origin isolation, but was isolated anyway*"); + NavigateFrameToURL(child_frame_node1, isolated_suborigin_url); + + console_observer.Wait(); + EXPECT_NE(root->current_frame_host()->GetSiteInstance(), child_frame_node1->current_frame_host()->GetSiteInstance()); @@ -553,7 +561,15 @@ // Change OriginPolicy manifest to start isolating the sub-origin. It should // still be not-isolated, to remain consistent with the other frame. SetOriginPolicyManifest(R"({ "ids": ["my-policy"], "isolation": true })"); + + WebContentsConsoleObserver console_observer(shell()->web_contents()); + console_observer.SetPattern( + "The page requested origin isolation, but could not be isolated*"); + NavigateFrameToURL(child_frame_node1, isolated_suborigin_url); + + console_observer.Wait(); + EXPECT_EQ(root->current_frame_host()->GetSiteInstance(), child_frame_node1->current_frame_host()->GetSiteInstance());
diff --git a/content/browser/media/media_canplaytype_browsertest.cc b/content/browser/media/media_canplaytype_browsertest.cc index 3e8d10e..45a76bc 100644 --- a/content/browser/media/media_canplaytype_browsertest.cc +++ b/content/browser/media/media_canplaytype_browsertest.cc
@@ -596,7 +596,14 @@ } #endif // BUILDFLAG(ENABLE_AV1_DECODER) -IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_wav) { +// Flaky on Lollipop and Marshmallow. https://crbug.com/1090770 +#if defined(OS_ANDROID) +#define MAYBE_CodecSupportTest_wav DISABLED_CodecSupportTest_wav +#else +#define MAYBE_CodecSupportTest_wav CodecSupportTest_wav +#endif + +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_wav) { EXPECT_EQ(kMaybe, CanPlay("'audio/wav'")); EXPECT_EQ(kProbably, CanPlay("'audio/wav; codecs=\"1\"'")); @@ -608,7 +615,14 @@ TestWAVUnacceptableCombinations("audio/x-wav"); } -IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_webm) { +// Flaky on Lollipop and Marshmallow. https://crbug.com/1090770 +#if defined(OS_ANDROID) +#define MAYBE_CodecSupportTest_webm DISABLED_CodecSupportTest_webm +#else +#define MAYBE_CodecSupportTest_webm CodecSupportTest_webm +#endif + +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_webm) { EXPECT_EQ(kMaybe, CanPlay("'video/webm'")); EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8\"'")); @@ -652,7 +666,14 @@ TestWEBMUnacceptableCombinations("audio/webm"); } -IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) { +// Flaky on Lollipop and Marshmallow. https://crbug.com/1090770 +#if defined(OS_ANDROID) +#define MAYBE_CodecSupportTest_ogg DISABLED_CodecSupportTest_ogg +#else +#define MAYBE_CodecSupportTest_ogg CodecSupportTest_ogg +#endif + +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_ogg) { EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg'")); EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"theora\"'")); EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"theora, flac\"'")); @@ -727,7 +748,14 @@ EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.40.02\"'")); } -IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) { +// Flaky on Lollipop and Marshmallow. https://crbug.com/1090770 +#if defined(OS_ANDROID) +#define MAYBE_CodecSupportTest_mp3 DISABLED_CodecSupportTest_mp3 +#else +#define MAYBE_CodecSupportTest_mp3 CodecSupportTest_mp3 +#endif + +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_mp3) { EXPECT_EQ(kNot, CanPlay("'video/mp3'")); EXPECT_EQ(kNot, CanPlay("'video/mpeg'")); EXPECT_EQ(kNot, CanPlay("'video/x-mp3'")); @@ -803,7 +831,14 @@ EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp3\"'")); } -IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) { +// Flaky on Lollipop and Marshmallow. https://crbug.com/1090770 +#if defined(OS_ANDROID) +#define MAYBE_CodecSupportTest_mp4 DISABLED_CodecSupportTest_mp4 +#else +#define MAYBE_CodecSupportTest_mp4 CodecSupportTest_mp4 +#endif + +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_mp4) { EXPECT_EQ(kMaybe, CanPlay("'video/mp4'")); EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1\"'")); @@ -1344,11 +1379,20 @@ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42E052\"'")); } +// Flaky on Lollipop and Marshmallow. https://crbug.com/1090770 +#if defined(OS_ANDROID) +#define MAYBE_CodecSupportTest_Mp4aVariants \ + DISABLED_CodecSupportTest_Mp4aVariants +#else +#define MAYBE_CodecSupportTest_Mp4aVariants CodecSupportTest_Mp4aVariants +#endif + // All values that return positive results are tested. There are also // negative tests for values around or that could potentially be confused with // (e.g. case, truncation, hex <-> deciemal conversion) those values that return // positive results. -IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mp4aVariants) { +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, + MAYBE_CodecSupportTest_Mp4aVariants) { EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a\"'")); EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.\"'")); @@ -1444,7 +1488,14 @@ EXPECT_EQ(kXHE_AACProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.42\"'")); } -IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HLS) { +// Flaky on Lollipop and Marshmallow. https://crbug.com/1090770 +#if defined(OS_ANDROID) +#define MAYBE_CodecSupportTest_HLS DISABLED_CodecSupportTest_HLS +#else +#define MAYBE_CodecSupportTest_HLS CodecSupportTest_HLS +#endif + +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_HLS) { TestHLSCombinations("application/vnd.apple.mpegurl"); TestHLSCombinations("application/x-mpegurl"); TestHLSCombinations("audio/mpegurl"); @@ -1460,7 +1511,14 @@ EXPECT_EQ(kNot, CanPlay("'audio/aac; codecs=\"mp4a.40.2\"'")); } -IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mpeg2Ts) { +// Flaky on Lollipop and Marshmallow. https://crbug.com/1090770 +#if defined(OS_ANDROID) +#define MAYBE_CodecSupportTest_Mpeg2Ts DISABLED_CodecSupportTest_Mpeg2Ts +#else +#define MAYBE_CodecSupportTest_Mpeg2Ts CodecSupportTest_Mpeg2Ts +#endif + +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_Mpeg2Ts) { EXPECT_EQ(kMp2tsMaybe, CanPlay("'video/mp2t'")); // video/mp2t must support standard RFC 6381 compliant H.264 / AAC codec ids.
diff --git a/content/browser/renderer_host/render_frame_metadata_provider_impl.cc b/content/browser/renderer_host/render_frame_metadata_provider_impl.cc index 498d3330..eabfcfc 100644 --- a/content/browser/renderer_host/render_frame_metadata_provider_impl.cc +++ b/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
@@ -36,10 +36,9 @@ std::move(client_receiver), task_runner_); #if defined(OS_ANDROID) - if (pending_report_all_root_scrolls_for_accessibility_.has_value()) { - ReportAllRootScrollsForAccessibility( - *pending_report_all_root_scrolls_for_accessibility_); - pending_report_all_root_scrolls_for_accessibility_.reset(); + if (pending_report_all_root_scrolls_.has_value()) { + ReportAllRootScrolls(*pending_report_all_root_scrolls_); + pending_report_all_root_scrolls_.reset(); } #endif if (pending_report_all_frame_submission_for_testing_.has_value()) { @@ -50,15 +49,13 @@ } #if defined(OS_ANDROID) -void RenderFrameMetadataProviderImpl::ReportAllRootScrollsForAccessibility( - bool enabled) { +void RenderFrameMetadataProviderImpl::ReportAllRootScrolls(bool enabled) { if (!render_frame_metadata_observer_remote_) { - pending_report_all_root_scrolls_for_accessibility_ = enabled; + pending_report_all_root_scrolls_ = enabled; return; } - render_frame_metadata_observer_remote_->ReportAllRootScrollsForAccessibility( - enabled); + render_frame_metadata_observer_remote_->ReportAllRootScrolls(enabled); } #endif
diff --git a/content/browser/renderer_host/render_frame_metadata_provider_impl.h b/content/browser/renderer_host/render_frame_metadata_provider_impl.h index 9c0f9c8..4b92ea5 100644 --- a/content/browser/renderer_host/render_frame_metadata_provider_impl.h +++ b/content/browser/renderer_host/render_frame_metadata_provider_impl.h
@@ -47,8 +47,9 @@ #if defined(OS_ANDROID) // Notifies the renderer to begin sending a notification on all root scroll - // changes, which is needed for accessibility on Android. - void ReportAllRootScrollsForAccessibility(bool enabled); + // changes, which is needed for accessibility and GestureListenerManager on + // Android. + void ReportAllRootScrolls(bool enabled); #endif // Notifies the renderer to begin sending a notification on all frame @@ -94,7 +95,7 @@ render_frame_metadata_observer_remote_; #if defined(OS_ANDROID) - base::Optional<bool> pending_report_all_root_scrolls_for_accessibility_; + base::Optional<bool> pending_report_all_root_scrolls_; #endif base::Optional<bool> pending_report_all_frame_submission_for_testing_;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 82fba6d..bb749bb5 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -4907,6 +4907,8 @@ GetContentClient()->browser()->GetUserAgent()); GetRendererInterface()->SetUserAgentMetadata( GetContentClient()->browser()->GetUserAgentMetadata()); + GetRendererInterface()->SetCorsExemptHeaderList( + storage_partition_impl_->cors_exempt_header_list()); NotifyRendererIfLockedToSite(); // Send the initial system color info to the renderer.
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc index 879dd09..77af9ff8 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -471,10 +471,9 @@ // the OOPIF renderer. Instead of using the coordinate transformation in the // browser process process, use the cached coordinates that were determined // by the renderer process on the previous MouseDown. - // TODO(yigu): Currently there is a mismatch between the coordinate - // transforms from browser process and renderer process. We need to fix it - // so that we don't need to cache the transform from MouseDown. - // https://crbug.com/934434. + // TODO(crbug.com/989109): Currently there is a mismatch between the + // coordinate transforms from browser process and renderer process. We need + // to fix it so that we don't need to cache the transform from MouseDown. if (event.GetType() == blink::WebInputEvent::Type::kMouseUp && target == last_mouse_down_target_ && mouse_down_pre_transformed_coordinate_ == event.PositionInWidget()) {
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index 50d2541..24f17c6 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -274,7 +274,7 @@ ~FakeRenderFrameMetadataObserver() override {} #if defined(OS_ANDROID) - void ReportAllRootScrollsForAccessibility(bool enabled) override {} + void ReportAllRootScrolls(bool enabled) override {} #endif void ReportAllFrameSubmissionsForTesting(bool enabled) override {}
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 0dd5bbb4..b16ff35e 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -785,6 +785,20 @@ transformed_point); } +void RenderWidgetHostViewAndroid::SetGestureListenerManager( + GestureListenerManager* manager) { + gesture_listener_manager_ = manager; + UpdateReportAllRootScrolls(); +} + +void RenderWidgetHostViewAndroid::UpdateReportAllRootScrolls() { + if (!host()) + return; + + host()->render_frame_metadata_provider()->ReportAllRootScrolls( + ShouldReportAllRootScrolls()); +} + base::WeakPtr<RenderWidgetHostViewAndroid> RenderWidgetHostViewAndroid::GetWeakPtrAndroid() { return weak_ptr_factory_.GetWeakPtr(); @@ -1969,6 +1983,15 @@ CreateOverscrollControllerIfPossible(); } +bool RenderWidgetHostViewAndroid::ShouldReportAllRootScrolls() { + // In order to provide support for onScrollOffsetOrExtentChanged() + // GestureListenerManager needs root-scroll-offsets. This is only necessary + // if a GestureStateListenerWithScroll is added. + return web_contents_accessibility_ != nullptr || + (gesture_listener_manager_ && + gesture_listener_manager_->has_listeners_attached()); +} + MouseWheelPhaseHandler* RenderWidgetHostViewAndroid::GetMouseWheelPhaseHandler() { return &mouse_wheel_phase_handler_; @@ -2359,12 +2382,7 @@ void RenderWidgetHostViewAndroid::SetWebContentsAccessibility( WebContentsAccessibilityAndroid* web_contents_accessibility) { web_contents_accessibility_ = web_contents_accessibility; - - if (host()) { - host() - ->render_frame_metadata_provider() - ->ReportAllRootScrollsForAccessibility(!!web_contents_accessibility_); - } + UpdateReportAllRootScrolls(); } void RenderWidgetHostViewAndroid::SetNeedsBeginFrameForFlingProgress() {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index 86a35ef..def5f8e 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -248,9 +248,9 @@ TextSuggestionHostAndroid* text_suggestion_host() const { return text_suggestion_host_; } - void set_gesture_listener_manager(GestureListenerManager* manager) { - gesture_listener_manager_ = manager; - } + void SetGestureListenerManager(GestureListenerManager* manager); + + void UpdateReportAllRootScrolls(); base::WeakPtr<RenderWidgetHostViewAndroid> GetWeakPtrAndroid(); @@ -371,6 +371,8 @@ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, GestureManagerListensToChildFrames); + bool ShouldReportAllRootScrolls(); + MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override; void EvictDelegatedFrame();
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 62400b52..a0034ad 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -2371,6 +2371,8 @@ GetContentClient()->browser()->ConfigureNetworkContextParams( browser_context_, is_in_memory_, relative_partition_path_, context_params.get(), cert_verifier_creation_params.get()); + devtools_instrumentation::ApplyNetworkContextParamsOverrides( + browser_context_, context_params.get()); DCHECK(!context_params->cert_verifier_params) << "|cert_verifier_params| should not be set in the NetworkContextParams," "as they will be replaced with either the newly configured " @@ -2389,6 +2391,8 @@ kCorsExemptRequestedWithHeaderName); variations::UpdateCorsExemptHeaderForVariations(context_params.get()); + cors_exempt_header_list_ = context_params->cors_exempt_header_list; + network_context_.reset(); GetNetworkService()->CreateNetworkContext( network_context_.BindNewPipeAndPassReceiver(), std::move(context_params));
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 965ebe6..12c2184b 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -294,6 +294,10 @@ auto& dom_storage_receivers_for_testing() { return dom_storage_receivers_; } + std::vector<std::string> cors_exempt_header_list() const { + return cors_exempt_header_list_; + } + // When this StoragePartition is for guests (e.g., for a <webview> tag), this // is the site URL to use when creating a SiteInstance for a service worker. // Typically one would use the script URL of the service worker (e.g., @@ -336,6 +340,8 @@ mojo::PendingRemote<network::mojom::CookieAccessObserver> CreateCookieAccessObserverForServiceWorker(); + std::vector<std::string> GetCorsExemptHeaderList(); + private: class DataDeletionHelper; class QuotaManagedDataDeletionHelper; @@ -546,6 +552,10 @@ mojo::Remote<network::mojom::OriginPolicyManager> origin_policy_manager_for_browser_process_; + // The list of cors exempt headers that are set on |network_context_|. + // Initialized in InitNetworkContext() and never updated after then. + std::vector<std::string> cors_exempt_header_list_; + // See comments for site_for_guest_service_worker(). GURL site_for_guest_service_worker_;
diff --git a/content/browser/tracing/tracing_controller_impl_data_endpoint.cc b/content/browser/tracing/tracing_controller_impl_data_endpoint.cc index 84c68d7..9bc2eee7 100644 --- a/content/browser/tracing/tracing_controller_impl_data_endpoint.cc +++ b/content/browser/tracing/tracing_controller_impl_data_endpoint.cc
@@ -85,11 +85,14 @@ } bool OpenFileIfNeededOnBlockingThread() { - base::ScopedBlockingCall scoped_blocking_call( - FROM_HERE, base::BlockingType::MAY_BLOCK); if (file_ != nullptr) return true; - file_ = base::OpenFile(file_path_, "w"); + + // The temporary trace file is produced in the same folder since paths must + // be on the same volume. + file_ = FileToFILE(CreateAndOpenTemporaryFileInDir(file_path_.DirName(), + &pending_file_path_), + "w"); if (file_ == nullptr) { LOG(ERROR) << "Failed to open " << file_path_.value(); return false; @@ -103,6 +106,14 @@ file_ = nullptr; } + base::File::Error error; + if (!base::ReplaceFile(pending_file_path_, file_path_, &error)) { + LOG(ERROR) << "Cannot replace file '" << file_path_ + << "' : " << base::File::ErrorToString(error); + base::DeleteFile(pending_file_path_, false); + return; + } + GetUIThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&FileTraceDataEndpoint::FinalizeOnUIThread, this)); @@ -111,6 +122,7 @@ void FinalizeOnUIThread() { std::move(completion_callback_).Run(); } base::FilePath file_path_; + base::FilePath pending_file_path_; base::OnceClosure completion_callback_; FILE* file_ = nullptr; const scoped_refptr<base::SequencedTaskRunner> may_block_task_runner_;
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc index 1aff511..6a5570c 100644 --- a/content/browser/webauth/authenticator_common.cc +++ b/content/browser/webauth/authenticator_common.cc
@@ -540,13 +540,12 @@ void AuthenticatorCommon::StartMakeCredentialRequest( bool allow_skipping_pin_touch) { - discovery_factory_ = + device::FidoDiscoveryFactory* discovery_factory = AuthenticatorEnvironmentImpl::GetInstance()->GetDiscoveryFactoryOverride( static_cast<RenderFrameHostImpl*>(render_frame_host_) ->frame_tree_node()); - if (!discovery_factory_) { - discovery_factory_ = request_delegate_->GetDiscoveryFactory(); - } + if (!discovery_factory) + discovery_factory = request_delegate_->GetDiscoveryFactory(); if (base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) { std::vector<device::CableDiscoveryData> cable_pairings = @@ -558,15 +557,15 @@ if (request_delegate_->SetCableTransportInfo( /*cable_extension_provided=*/false, have_paired_phones, qr_generator_key)) { - discovery_factory_->set_cable_data(cable_pairings, - std::move(qr_generator_key)); + discovery_factory->set_cable_data(cable_pairings, + std::move(qr_generator_key)); } } make_credential_options_->allow_skipping_pin_touch = allow_skipping_pin_touch; request_ = std::make_unique<device::MakeCredentialRequestHandler>( - discovery_factory_, + discovery_factory, GetAvailableTransports(render_frame_host_, request_delegate_.get(), caller_origin_), *ctap_make_credential_request_, *authenticator_selection_criteria_, @@ -595,13 +594,12 @@ void AuthenticatorCommon::StartGetAssertionRequest( bool allow_skipping_pin_touch) { - discovery_factory_ = + device::FidoDiscoveryFactory* discovery_factory = AuthenticatorEnvironmentImpl::GetInstance()->GetDiscoveryFactoryOverride( static_cast<RenderFrameHostImpl*>(render_frame_host_) ->frame_tree_node()); - if (!discovery_factory_) { - discovery_factory_ = request_delegate_->GetDiscoveryFactory(); - } + if (!discovery_factory) + discovery_factory = request_delegate_->GetDiscoveryFactory(); std::vector<device::CableDiscoveryData> cable_pairings; bool have_cable_extension = false; @@ -625,12 +623,12 @@ if ((!cable_pairings.empty() || qr_generator_key.has_value()) && request_delegate_->SetCableTransportInfo( have_cable_extension, have_paired_phones, qr_generator_key)) { - discovery_factory_->set_cable_data(std::move(cable_pairings), - std::move(qr_generator_key)); + discovery_factory->set_cable_data(std::move(cable_pairings), + std::move(qr_generator_key)); } request_ = std::make_unique<device::GetAssertionRequestHandler>( - discovery_factory_, + discovery_factory, GetAvailableTransports(render_frame_host_, request_delegate_.get(), caller_origin_), *ctap_get_assertion_request_, allow_skipping_pin_touch, @@ -1487,15 +1485,6 @@ timer_->Stop(); request_.reset(); - if (discovery_factory_) { - // The FidoDiscoveryFactory instance may have been obtained via - // AuthenticatorEnvironmentImpl::GetDiscoveryFactoryOverride() (in unit - // tests or when WebDriver injected a virtual authenticator), in which case - // it may be long-lived and handle more than one request. Hence, we need to - // reset all per-request state before deleting its pointer. - discovery_factory_->ResetRequestState(); - discovery_factory_ = nullptr; - } ctap_make_credential_request_.reset(); make_credential_options_.reset(); request_delegate_.reset();
diff --git a/content/browser/webauth/authenticator_common.h b/content/browser/webauth/authenticator_common.h index 61631ac..a15c1136 100644 --- a/content/browser/webauth/authenticator_common.h +++ b/content/browser/webauth/authenticator_common.h
@@ -169,7 +169,6 @@ BrowserContext* browser_context() const; RenderFrameHost* const render_frame_host_; - device::FidoDiscoveryFactory* discovery_factory_ = nullptr; std::unique_ptr<device::FidoRequestHandlerBase> request_; blink::mojom::Authenticator::MakeCredentialCallback make_credential_response_callback_;
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 6ed02f5..2aaacff 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -59,8 +59,11 @@ WebRuntimeFeatures::EnableCompositedSelectionUpdate(true); #endif #if defined(OS_WIN) - if (base::win::GetVersion() >= base::win::Version::WIN10) + if (base::win::GetVersion() >= base::win::Version::WIN10) { WebRuntimeFeatures::EnableWebBluetooth(true); + WebRuntimeFeatures::EnableWebBluetoothRemoteCharacteristicNewWriteValue( + true); + } #endif #if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT) @@ -318,6 +321,8 @@ {wf::EnableInstalledApp, features::kInstalledApp, kDisableOnly}, {wf::EnableWebAuthenticationGetAssertionFeaturePolicy, device::kWebAuthGetAssertionFeaturePolicy, kUseFeatureState}, + {wf::EnableTransformInterop, blink::features::kTransformInterop, + kUseFeatureState}, }; for (const auto& mapping : blinkFeatureToBaseFeatureMapping) { @@ -362,6 +367,8 @@ {"LayoutNGFlexBox", blink::features::kFlexNG, kUseFeatureState}, {"LegacyWindowsDWriteFontFallback", features::kLegacyWindowsDWriteFontFallback, kUseFeatureState}, + {"LinkDisabledNewSpecBehavior", + blink::features::kLinkDisabledNewSpecBehavior, kUseFeatureState}, {"OriginPolicy", features::kOriginPolicy, kUseFeatureState}, {"OriginIsolationHeader", features::kOriginIsolationHeader, kUseFeatureState},
diff --git a/content/common/render_accessibility.mojom b/content/common/render_accessibility.mojom index 4bfa3ee..3065950 100644 --- a/content/common/render_accessibility.mojom +++ b/content/common/render_accessibility.mojom
@@ -19,16 +19,20 @@ ax.mojom.AXRelativeBounds new_location; }; -struct ChildFrameHitTestInfo { - // The routing ID of the child frame to request a hit test for. - int32 child_frame_routing_id; +struct HitTestResponse { + // The routing ID of the frame that got hit. If this is not equal to + // the frame that the original hit test was called on, the client should + // do another hit test on this frame. + int32 hit_frame_routing_id; // The coordinates that should be used for the hit test on the child frame - // indicated by |child_frame_routing_id|, accounting for the viewport. - gfx.mojom.Point transformed_point; + // indicated by |hit_frame_routing_id|, accounting for the viewport. This + // is only needed if |hit_frame_routing_id| is not the same as the + // current frame's routing ID. + gfx.mojom.Point hit_frame_transformed_point; - // The accessibility event that should be fired. - ax.mojom.Event event_to_fire; + // The AXID of the accessibility node that got hit. + int32 hit_node_id; }; // Interface for accessibility messages sent from the renderer to the browser, @@ -71,15 +75,18 @@ FatalError(); // Relays a request from assistive technology to perform a hit test over the - // accessibility object at the point passed via |action_data.target_point|. + // accessibility object at the point passed via |point| in frame pixels. // - // If the object hit doesn't have a child frame, the accessibility event - // indicated via |action_data.hit_test_event_to_fire| will be emitted by the - // renderer and no |child_frame_hit_test_info| should be returned. Otherwise, - // |child_frame_hit_test_info| will provide the necessary information for the - // browser process to request another hit test over the child frame found. - HitTest(ax.mojom.AXActionData action_data) - => (ChildFrameHitTestInfo? child_frame_hit_test_info); + // If the object hit doesn't have a child frame, and if |event_to_fire| is + // set, the accessibility event will be emitted on the hit node with the + // given request ID. + // + // Either way, the response contains the routing ID of the hit frame, + // and the transformed point if the hit frame is a child frame. + HitTest(gfx.mojom.Point point, + ax.mojom.Event event_to_fire, + int32 request_id) + => (HitTestResponse? hit_test_response); // Relay a request from assistive technology to perform an action, such as // focusing or clicking on a node.
diff --git a/content/common/render_frame_metadata.mojom b/content/common/render_frame_metadata.mojom index fccbceb..c384790 100644 --- a/content/common/render_frame_metadata.mojom +++ b/content/common/render_frame_metadata.mojom
@@ -100,9 +100,11 @@ interface RenderFrameMetadataObserver { // When |enabled| is set to true, this will send RenderFrameMetadata to // the RenderFrameMetadataObserverClient for any frame in which the root - // scroll changes. Used only on Android for accessibility cases. + // scroll changes. Used only on Android for acessibility or + // GestureListenerManager. [EnableIf=is_android] - ReportAllRootScrollsForAccessibility(bool enabled); + ReportAllRootScrolls(bool enabled); + // When |enabled| is set to true, this will send RenderFrameMetadata to // the RenderFrameMetadataObserverClient for all frames. Only used for // tests. @@ -113,7 +115,7 @@ // RenderFrameMetadata. It can be notified of all frame submissions, via // RenderFrameMetadataObserver::ReportAllFrameSubmissionsForTesting, or of // additional frames with root scroll offset changes via -// RenderFrameMetadataObserver::ReportAllRootScrollsForAccessibility. +// RenderFrameMetadataObserver::ReportAllRootScrolls. interface RenderFrameMetadataObserverClient { // Notified when RenderFrameMetadata has changed. OnRenderFrameMetadataChanged(uint32 frame_token, RenderFrameMetadata metadata);
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom index 3cc553f..5d3135b 100644 --- a/content/common/renderer.mojom +++ b/content/common/renderer.mojom
@@ -295,6 +295,9 @@ // decide to ship https://github.com/WICG/ua-client-hints. SetUserAgentMetadata(blink.mojom.UserAgentMetadata metadata); + // Sets the CORS exempt header list for sanity checking (e.g. DCHECKs). + SetCorsExemptHeaderList(array<string> list); + // Tells the renderer about a scrollbar appearance change. Only for use on // OS X. UpdateScrollbarTheme(UpdateScrollbarThemeParams params);
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 147ad29..a02d4e0 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -486,6 +486,7 @@ "javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java", "javatests/src/org/chromium/content/browser/EncodeHtmlDataUriTest.java", "javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java", + "javatests/src/org/chromium/content/browser/GestureListenerManagerTest.java", "javatests/src/org/chromium/content/browser/ImportantFileWriterAndroidTest.java", "javatests/src/org/chromium/content/browser/JavaBridgeActivityTestRule.java", "javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java index b8cd3c5..32664cc1 100644 --- a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
@@ -7,6 +7,8 @@ import android.view.HapticFeedbackConstants; import android.view.View; +import androidx.annotation.VisibleForTesting; + import org.chromium.base.ObserverList; import org.chromium.base.ObserverList.RewindableIterator; import org.chromium.base.TraceEvent; @@ -97,12 +99,30 @@ @Override public void addListener(GestureStateListener listener) { - mListeners.addObserver(listener); + final boolean didAdd = mListeners.addObserver(listener); + if (mNativeGestureListenerManager != 0 && didAdd + && listener instanceof GestureStateListenerWithScroll) { + GestureListenerManagerImplJni.get().setHasListenersAttached( + mNativeGestureListenerManager, true); + } } @Override public void removeListener(GestureStateListener listener) { - mListeners.removeObserver(listener); + final boolean didRemove = mListeners.removeObserver(listener); + if (mNativeGestureListenerManager != 0 && didRemove + && (listener instanceof GestureStateListenerWithScroll) + && !hasGestureStateListenerWithScroll()) { + GestureListenerManagerImplJni.get().setHasListenersAttached( + mNativeGestureListenerManager, false); + } + } + + private boolean hasGestureStateListenerWithScroll() { + for (GestureStateListener listener : mListeners) { + if (listener instanceof GestureStateListenerWithScroll) return true; + } + return false; } @Override @@ -131,6 +151,11 @@ return mHasActiveFlingScroll; } + @VisibleForTesting + public boolean shouldReportAllRootScrolls() { + return hasGestureStateListenerWithScroll(); + } + // WindowEventObserver @Override @@ -384,5 +409,6 @@ GestureListenerManagerImpl caller, boolean enabled); void setMultiTouchZoomSupportEnabled(long nativeGestureListenerManager, GestureListenerManagerImpl caller, boolean enabled); + void setHasListenersAttached(long nativeGestureListenerManager, boolean hasListeners); } }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/GestureListenerManager.java b/content/public/android/java/src/org/chromium/content_public/browser/GestureListenerManager.java index a6881f9..487428c0 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/GestureListenerManager.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/GestureListenerManager.java
@@ -22,6 +22,10 @@ /** * Add a listener that gets alerted on gesture state changes. + * + * WARNING: attaching a listener results in extra IPC that impacts rendering performance. Only + * attach listeners when absolutely necessary and remove as soon as possible. + * * @param listener Listener to add. */ void addListener(GestureStateListener listener);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/GestureListenerManagerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/GestureListenerManagerTest.java new file mode 100644 index 0000000..afc8612 --- /dev/null +++ b/content/public/android/javatests/src/org/chromium/content/browser/GestureListenerManagerTest.java
@@ -0,0 +1,121 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.browser; + +import android.support.test.filters.LargeTest; +import android.view.View; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.UrlUtils; +import org.chromium.content_public.browser.GestureListenerManager; +import org.chromium.content_public.browser.GestureStateListenerWithScroll; +import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.WebContents; +import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer; +import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.content_public.browser.test.util.TouchCommon; +import org.chromium.content_shell_apk.ContentShellActivityTestRule; + +/** + * Assertions for GestureListenerManager. + */ +@RunWith(BaseJUnit4ClassRunner.class) +public class GestureListenerManagerTest { + @Rule + public ContentShellActivityTestRule mActivityTestRule = new ContentShellActivityTestRule(); + + // The page should be large enough so that scrolling occurs. + private static final String TEST_URL = + UrlUtils.encodeHtmlDataUri("<html><body style='height: 10000px'>"); + + private static final class GestureStateListenerImpl implements GestureStateListenerWithScroll { + private int mNumOnScrollOffsetOrExtentChangedCalls; + public CallbackHelper mCallbackHelper = new CallbackHelper(); + private boolean mGotStarted; + private boolean mDidScrollOffsetChangeWhileScrolling; + private Integer mLastScrollOffsetY; + + @Override + public void onScrollStarted(int scrollOffsetY, int scrollExtentY) { + mGotStarted = true; + mLastScrollOffsetY = null; + } + @Override + public void onScrollOffsetOrExtentChanged(int scrollOffsetY, int scrollExtentY) { + if (mGotStarted + && (mLastScrollOffsetY == null || !mLastScrollOffsetY.equals(scrollOffsetY))) { + if (mLastScrollOffsetY != null) mDidScrollOffsetChangeWhileScrolling = true; + mLastScrollOffsetY = scrollOffsetY; + } + } + @Override + public void onScrollEnded(int scrollOffsetY, int scrollExtentY) { + // onScrollEnded() should be preceded by onScrollStarted(). + Assert.assertTrue(mGotStarted); + // onScrollOffsetOrExtentChanged() should be called at least twice. Once with an initial + // value, and then with a different value. + Assert.assertTrue(mDidScrollOffsetChangeWhileScrolling); + mCallbackHelper.notifyCalled(); + mGotStarted = false; + } + } + + private float mCurrentX; + private float mCurrentY; + + /** + * Assertions for GestureStateListener.onScrollOffsetOrExtentChanged. + */ + @Test + @LargeTest + @Feature({"Browser"}) + public void testOnScrollOffsetOrExtentChanged() throws Throwable { + mActivityTestRule.launchContentShellWithUrl("about:blank"); + WebContents webContents = mActivityTestRule.getWebContents(); + // This needs to wait for first-paint, otherwise scrolling doesn't happen. + TestCallbackHelperContainer callbackHelperContainer = + new TestCallbackHelperContainer(webContents); + CallbackHelper done = callbackHelperContainer.getOnFirstVisuallyNonEmptyPaintHelper(); + mActivityTestRule.loadUrl(webContents.getNavigationController(), callbackHelperContainer, + new LoadUrlParams(TEST_URL)); + done.waitForCallback(0); + + final GestureStateListenerImpl listener = new GestureStateListenerImpl(); + TestThreadUtils.runOnUiThreadBlocking(() -> { + GestureListenerManagerImpl manager = + (GestureListenerManagerImpl) GestureListenerManager.fromWebContents( + webContents); + // shouldReportAllRootScrolls() should initially be false (as there are no listeners). + Assert.assertFalse(manager.shouldReportAllRootScrolls()); + manager.addListener(listener); + // Adding a listener enables root-scrolls. + Assert.assertTrue(manager.shouldReportAllRootScrolls()); + View webContentsView = webContents.getViewAndroidDelegate().getContainerView(); + mCurrentX = webContentsView.getWidth() / 2; + mCurrentY = webContentsView.getHeight() / 2; + }); + + // Perform a scroll. + TouchCommon.performDrag(mActivityTestRule.getActivity(), mCurrentX, mCurrentX, mCurrentY, + mCurrentY - 50, /* stepCount*/ 3, /* duration in ms */ 250); + listener.mCallbackHelper.waitForCallback(0); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + GestureListenerManagerImpl manager = + (GestureListenerManagerImpl) GestureListenerManager.fromWebContents( + webContents); + manager.removeListener(listener); + // Removing the only listener disbles root-scrolls. + Assert.assertFalse(manager.shouldReportAllRootScrolls()); + }); + } +}
diff --git a/content/public/browser/browser_url_handler.h b/content/public/browser/browser_url_handler.h index 5f023ac..3757788 100644 --- a/content/public/browser/browser_url_handler.h +++ b/content/public/browser/browser_url_handler.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_PUBLIC_BROWSER_BROWSER_URL_HANDLER_H_ #define CONTENT_PUBLIC_BROWSER_BROWSER_URL_HANDLER_H_ +#include <vector> + #include "content/common/content_export.h" class GURL; @@ -40,6 +42,15 @@ virtual void RewriteURLIfNecessary(GURL* url, BrowserContext* browser_context) = 0; + // Returns the list of possible rewrites, in order of priority (i.e., index 0 + // is the rewrite that would be used in RewriteURLIfNecessary()). Note that + // this only allows for one rewrite per registered URLHandler (and each gets a + // fresh copy of |url|), so it is not necessarily the complete set of all + // possible rewrites. + virtual std::vector<GURL> GetPossibleRewrites( + const GURL& url, + BrowserContext* browser_context) = 0; + // Set the specified handler as a preliminary fixup phase to be done before // rewriting. This allows minor cleanup for the URL without having it affect // the virtual URL.
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index f9f5667d..a71c677a 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -298,44 +298,55 @@ } void RenderAccessibilityImpl::HitTest( - const ui::AXActionData& action_data, + const gfx::Point& point, + ax::mojom::Event event_to_fire, + int request_id, mojom::RenderAccessibility::HitTestCallback callback) { - // This method should be called exclusively for kHitTest actions. - DCHECK_EQ(action_data.action, ax::mojom::Action::kHitTest); - DCHECK_NE(action_data.hit_test_event_to_fire, ax::mojom::Event::kNone); - WebAXObject ax_object; const WebDocument& document = GetMainDocument(); if (!document.IsNull()) { auto root_obj = WebAXObject::FromWebDocument(document); if (root_obj.UpdateLayoutAndCheckValidity()) - ax_object = root_obj.HitTest(action_data.target_point); + ax_object = root_obj.HitTest(point); } // Return if no attached accessibility object was found for the main document. if (ax_object.IsDetached()) { - std::move(callback).Run(/*child_frame_hit_test_info=*/nullptr); + std::move(callback).Run(/*hit_test_response=*/nullptr); return; } - // If the object that was hit has a child frame, we have to send a message - // back to the browser to do the hit test in the child frame, recursively. + // If the result was in the same frame, return the result. AXContentNodeData data; ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); tree_source_.SerializeNode(ax_object, &data); if (data.child_routing_id == MSG_ROUTING_NONE) { - // Otherwise, send an event on the node that was hit. - const std::vector<ui::AXEventIntent> intents; - HandleAXEvent(ui::AXEvent( - ax_object.AxID(), action_data.hit_test_event_to_fire, - ax::mojom::EventFrom::kAction, intents, action_data.request_id)); + // Optionally fire an event, if requested to. This is a good fit for + // features like touch exploration on Android, Chrome OS, and + // possibly other platforms - if the user explore a particular point, + // we fire a hover event on the nearest object under the point. + // + // Avoid using this mechanism to fire a particular sentinel event + // and then listen for that event to associate it with the hit test + // request. Instead, the mojo reply should be used directly. + if (event_to_fire != ax::mojom::Event::kNone) { + const std::vector<ui::AXEventIntent> intents; + HandleAXEvent(ui::AXEvent(ax_object.AxID(), event_to_fire, + ax::mojom::EventFrom::kAction, intents, + request_id)); + } - // The mojo message still needs a reply. - std::move(callback).Run(/*child_frame_hit_test_info=*/nullptr); + // Reply with the result. + std::move(callback).Run(mojom::HitTestResponse::New( + render_frame_->GetRoutingID(), point, ax_object.AxID())); return; } - gfx::Point transformed_point = action_data.target_point; + // The result was in a child frame. Reply so that the + // client can do a hit test on the child frame recursively. + // If it's a remote frame, transform the point into the child frame's + // coordinate system. + gfx::Point transformed_point = point; bool is_remote_frame = RenderFrameProxy::FromRoutingID(data.child_routing_id); if (is_remote_frame) { // Remote frames don't have access to the information from the visual @@ -351,12 +362,8 @@ gfx::Vector2d(viewport_offset.x(), viewport_offset.y()) - gfx::Rect(rect).OffsetFromOrigin(); } - - // Signal to the caller that we haven't handled this hit test yet, and that - // a new one will need to be performed over the child frame found. - std::move(callback).Run(mojom::ChildFrameHitTestInfo::New( - data.child_routing_id, transformed_point, - action_data.hit_test_event_to_fire)); + std::move(callback).Run(mojom::HitTestResponse::New( + data.child_routing_id, transformed_point, ax_object.AxID())); return; }
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h index 00856a1..40945581 100644 --- a/content/renderer/accessibility/render_accessibility_impl.h +++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -123,7 +123,9 @@ ui::PageTransition transition) override; void AccessibilityModeChanged(const ui::AXMode& mode) override; - void HitTest(const ui::AXActionData& action_data, + void HitTest(const gfx::Point& point, + ax::mojom::Event event_to_fire, + int request_id, mojom::RenderAccessibility::HitTestCallback callback); void PerformAction(const ui::AXActionData& data); void Reset(int32_t reset_token);
diff --git a/content/renderer/accessibility/render_accessibility_manager.cc b/content/renderer/accessibility/render_accessibility_manager.cc index 2278b175..06eb5da 100644 --- a/content/renderer/accessibility/render_accessibility_manager.cc +++ b/content/renderer/accessibility/render_accessibility_manager.cc
@@ -69,10 +69,13 @@ } void RenderAccessibilityManager::HitTest( - const ui::AXActionData& action_data, + const gfx::Point& point, + ax::mojom::Event event_to_fire, + int request_id, mojom::RenderAccessibility::HitTestCallback callback) { DCHECK(render_accessibility_); - render_accessibility_->HitTest(action_data, std::move(callback)); + render_accessibility_->HitTest(point, event_to_fire, request_id, + std::move(callback)); } void RenderAccessibilityManager::PerformAction(const ui::AXActionData& data) {
diff --git a/content/renderer/accessibility/render_accessibility_manager.h b/content/renderer/accessibility/render_accessibility_manager.h index 57ebb7d..cbfe443 100644 --- a/content/renderer/accessibility/render_accessibility_manager.h +++ b/content/renderer/accessibility/render_accessibility_manager.h
@@ -60,7 +60,9 @@ // mojom::RenderAccessibility implementation. void SetMode(uint32_t ax_mode) override; void FatalError() override; - void HitTest(const ui::AXActionData& action_data, + void HitTest(const gfx::Point& point, + ax::mojom::Event event_to_fire, + int request_id, mojom::RenderAccessibility::HitTestCallback callback) override; void PerformAction(const ui::AXActionData& data) override; void Reset(int32_t reset_token) override;
diff --git a/content/renderer/browser_exposed_renderer_interfaces.cc b/content/renderer/browser_exposed_renderer_interfaces.cc index ac78340..b1a2d783 100644 --- a/content/renderer/browser_exposed_renderer_interfaces.cc +++ b/content/renderer/browser_exposed_renderer_interfaces.cc
@@ -22,6 +22,7 @@ #include "content/public/common/resource_usage_reporter.mojom.h" #include "content/public/common/resource_usage_reporter_type_converters.h" #include "content/public/renderer/content_renderer_client.h" +#include "content/renderer/loader/resource_dispatcher.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/service_worker/embedded_worker_instance_client_impl.h" @@ -181,6 +182,20 @@ std::move(receiver)); } +void CreateEmbeddedWorker( + scoped_refptr<base::SingleThreadTaskRunner> initiator_task_runner, + base::WeakPtr<RenderThreadImpl> render_thread, + mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> + receiver) { + initiator_task_runner->PostTask( + FROM_HERE, + base::BindOnce( + &EmbeddedWorkerInstanceClientImpl::CreateForRequest, + initiator_task_runner, + render_thread->resource_dispatcher()->cors_exempt_header_list(), + std::move(receiver))); +} + } // namespace void ExposeRendererInterfacesToBrowser( @@ -197,10 +212,10 @@ base::ThreadPool::CreateSingleThreadTaskRunner( {base::MayBlock(), base::TaskPriority::USER_BLOCKING, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); - binders->Add( - base::BindRepeating(&EmbeddedWorkerInstanceClientImpl::CreateForRequest, - task_runner_for_service_worker_startup), - task_runner_for_service_worker_startup); + binders->Add(base::BindRepeating(&CreateEmbeddedWorker, + task_runner_for_service_worker_startup, + render_thread), + base::ThreadTaskRunnerHandle::Get()); binders->Add(base::BindRepeating(&CreateFrameFactory), base::ThreadTaskRunnerHandle::Get());
diff --git a/content/renderer/input/main_thread_event_queue.cc b/content/renderer/input/main_thread_event_queue.cc index 1e0d698..7ad054ec 100644 --- a/content/renderer/input/main_thread_event_queue.cc +++ b/content/renderer/input/main_thread_event_queue.cc
@@ -63,15 +63,24 @@ ~QueuedWebInputEvent() override {} - bool ArePointerMoveEventTypes(QueuedWebInputEvent* other_event) { + bool AreCoalescablePointerRawUpdateEvents(QueuedWebInputEvent* other_event) { // There is no pointermove at this point in the queue. DCHECK(event_->Event().GetType() != WebInputEvent::Type::kPointerMove && other_event->event_->Event().GetType() != WebInputEvent::Type::kPointerMove); + // Events with modifiers differing by kRelativeMotionEvent should not be + // coalesced. In case of a pointer lock, kRelativeMotionEvent is sent + // when the cursor is recentered. Events post the recentered event have + // a big delta compared to the previous events and hence should not be + // coalesced. return event_->Event().GetType() == WebInputEvent::Type::kPointerRawUpdate && other_event->event_->Event().GetType() == - WebInputEvent::Type::kPointerRawUpdate; + WebInputEvent::Type::kPointerRawUpdate && + ((event_->Event().GetModifiers() & + blink::WebInputEvent::Modifiers::kRelativeMotionEvent) == + (other_event->event_->Event().GetModifiers() & + blink::WebInputEvent::Modifiers::kRelativeMotionEvent)); } FilterResult FilterNewEvent(MainThreadEventQueueTask* other_task) override { @@ -92,7 +101,7 @@ // Two pointerevents may not be able to coalesce but we should continue // looking further down the queue if both of them were rawupdate or move // events and only their pointer_type, id, or event_type was different. - if (ArePointerMoveEventTypes(other_event)) + if (AreCoalescablePointerRawUpdateEvents(other_event)) return FilterResult::KeepIterating; return FilterResult::StopIterating; }
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc index e4829b5..70b959e 100644 --- a/content/renderer/loader/resource_dispatcher.cc +++ b/content/renderer/loader/resource_dispatcher.cc
@@ -407,6 +407,11 @@ transfer_size_diff); } +void ResourceDispatcher::SetCorsExemptHeaderList( + const std::vector<std::string>& list) { + cors_exempt_header_list_ = list; +} + ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( std::unique_ptr<RequestPeer> peer, network::mojom::RequestDestination request_destination, @@ -460,14 +465,14 @@ base::ThreadPool::CreateSingleThreadTaskRunner({}); task_runner->PostTask( FROM_HERE, - base::BindOnce(&SyncLoadContext::StartAsyncWithWaitableEvent, - std::move(request), routing_id, task_runner, - traffic_annotation, loader_options, - std::move(pending_factory), std::move(throttles), - base::Unretained(response), - base::Unretained(&redirect_or_response_event), - base::Unretained(terminate_sync_load_event_), timeout, - std::move(download_to_blob_registry))); + base::BindOnce( + &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request), + routing_id, task_runner, traffic_annotation, loader_options, + std::move(pending_factory), std::move(throttles), + base::Unretained(response), + base::Unretained(&redirect_or_response_event), + base::Unretained(terminate_sync_load_event_), timeout, + std::move(download_to_blob_registry), cors_exempt_header_list_)); // redirect_or_response_event will signal when each redirect completes, and // when the final response is complete. @@ -561,7 +566,8 @@ blink::ThrottlingURLLoader::CreateLoaderAndStart( std::move(url_loader_factory), std::move(throttles), routing_id, request_id, loader_options, request.get(), client.get(), - traffic_annotation, std::move(loading_task_runner)); + traffic_annotation, std::move(loading_task_runner), + base::make_optional(cors_exempt_header_list_)); pending_request->url_loader = std::move(url_loader); pending_request->url_loader_client = std::move(client);
diff --git a/content/renderer/loader/resource_dispatcher.h b/content/renderer/loader/resource_dispatcher.h index 949cc1e..e7a86179 100644 --- a/content/renderer/loader/resource_dispatcher.h +++ b/content/renderer/loader/resource_dispatcher.h
@@ -159,6 +159,13 @@ void OnTransferSizeUpdated(int request_id, int32_t transfer_size_diff); + // Sets the CORS exempt header list for sanity checking. + void SetCorsExemptHeaderList(const std::vector<std::string>& list); + + std::vector<std::string> cors_exempt_header_list() const { + return cors_exempt_header_list_; + } + // This is used only when |this| is created for a worker thread. // Sets |terminate_sync_load_event_| which will be signaled from the main // thread when the worker thread is being terminated so that the sync requests @@ -253,6 +260,8 @@ base::WaitableEvent* terminate_sync_load_event_ = nullptr; + std::vector<std::string> cors_exempt_header_list_; + base::WeakPtrFactory<ResourceDispatcher> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ResourceDispatcher);
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc index ba16da6..b246fe3e 100644 --- a/content/renderer/loader/sync_load_context.cc +++ b/content/renderer/loader/sync_load_context.cc
@@ -101,11 +101,13 @@ base::WaitableEvent* redirect_or_response_event, base::WaitableEvent* abort_event, base::TimeDelta timeout, - mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry) { - auto* context = new SyncLoadContext( - request.get(), std::move(pending_url_loader_factory), response, - redirect_or_response_event, abort_event, timeout, - std::move(download_to_blob_registry), loading_task_runner); + mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, + const std::vector<std::string>& cors_exempt_header_list) { + auto* context = + new SyncLoadContext(request.get(), std::move(pending_url_loader_factory), + response, redirect_or_response_event, abort_event, + timeout, std::move(download_to_blob_registry), + loading_task_runner, cors_exempt_header_list); context->request_id_ = context->resource_dispatcher_->StartAsync( std::move(request), routing_id, std::move(loading_task_runner), traffic_annotation, loader_options, base::WrapUnique(context), @@ -121,7 +123,8 @@ base::WaitableEvent* abort_event, base::TimeDelta timeout, mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + const std::vector<std::string>& cors_exempt_header_list) : response_(response), body_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), download_to_blob_registry_(std::move(download_to_blob_registry)), @@ -138,6 +141,7 @@ // Constructs a new ResourceDispatcher specifically for this request. resource_dispatcher_ = std::make_unique<ResourceDispatcher>(); + resource_dispatcher_->SetCorsExemptHeaderList(cors_exempt_header_list); // Initialize the final URL with the original request URL. It will be // overwritten on redirects.
diff --git a/content/renderer/loader/sync_load_context.h b/content/renderer/loader/sync_load_context.h index f7565e5d..9ba341f04 100644 --- a/content/renderer/loader/sync_load_context.h +++ b/content/renderer/loader/sync_load_context.h
@@ -66,8 +66,8 @@ base::WaitableEvent* completed_event, base::WaitableEvent* abort_event, base::TimeDelta timeout, - mojo::PendingRemote<blink::mojom::BlobRegistry> - download_to_blob_registry); + mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, + const std::vector<std::string>& cors_exempt_header_list); ~SyncLoadContext() override; @@ -86,7 +86,8 @@ base::WaitableEvent* abort_event, base::TimeDelta timeout, mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + const std::vector<std::string>& cors_exempt_header_list); // RequestPeer implementation: void OnUploadProgress(uint64_t position, uint64_t size) override; bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
diff --git a/content/renderer/loader/sync_load_context_unittest.cc b/content/renderer/loader/sync_load_context_unittest.cc index d4d012d1a..3e30786 100644 --- a/content/renderer/loader/sync_load_context_unittest.cc +++ b/content/renderer/loader/sync_load_context_unittest.cc
@@ -104,16 +104,17 @@ base::WaitableEvent* redirect_or_response_event) { loading_thread_.task_runner()->PostTask( FROM_HERE, - base::BindOnce(&SyncLoadContext::StartAsyncWithWaitableEvent, - std::move(request), MSG_ROUTING_NONE, - loading_thread_.task_runner(), - TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* loader_options */, - std::move(pending_factory), - std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(), - out_response, redirect_or_response_event, - nullptr /* terminate_sync_load_event */, - base::TimeDelta::FromSeconds(60) /* timeout */, - mojo::NullRemote() /* download_to_blob_registry */)); + base::BindOnce( + &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request), + MSG_ROUTING_NONE, loading_thread_.task_runner(), + TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* loader_options */, + std::move(pending_factory), + std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(), + out_response, redirect_or_response_event, + nullptr /* terminate_sync_load_event */, + base::TimeDelta::FromSeconds(60) /* timeout */, + mojo::NullRemote() /* download_to_blob_registry */, + std::vector<std::string>() /* cors_exempt_header_list */)); } static void RunSyncLoadContextViaDataPipe( @@ -128,7 +129,8 @@ response, redirect_or_response_event, nullptr /* terminate_sync_load_event */, base::TimeDelta::FromSeconds(60) /* timeout */, - mojo::NullRemote() /* download_to_blob_registry */, task_runner); + mojo::NullRemote() /* download_to_blob_registry */, task_runner, + std::vector<std::string>() /* cors_exempt_header_list */); // Override |resource_dispatcher_| for testing. auto dispatcher = std::make_unique<MockResourceDispatcher>();
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.cc b/content/renderer/loader/web_worker_fetch_context_impl.cc index 5e7b8b3..ce1d1c8 100644 --- a/content/renderer/loader/web_worker_fetch_context_impl.cc +++ b/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -171,7 +171,8 @@ std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_fallback_factory, mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> - pending_subresource_loader_updater) { + pending_subresource_loader_updater, + const std::vector<std::string>& cors_exempt_header_list) { mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient> service_worker_client_receiver; mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry> @@ -209,7 +210,8 @@ ->renderer() ->CreateWebSocketHandshakeThrottleProvider(), ChildThreadImpl::current()->thread_safe_sender(), - ChildThreadImpl::current()->child_process_host())); + ChildThreadImpl::current()->child_process_host(), + cors_exempt_header_list)); if (provider_context) { worker_fetch_context->set_controller_service_worker_mode( provider_context->GetControllerServiceWorkerMode()); @@ -241,7 +243,8 @@ std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider, ThreadSafeSender* thread_safe_sender, - mojo::SharedRemote<mojom::ChildProcessHost> process_host) + mojo::SharedRemote<mojom::ChildProcessHost> process_host, + const std::vector<std::string>& cors_exempt_header_list) : service_worker_client_receiver_( std::move(service_worker_client_receiver)), pending_service_worker_worker_client_registry_( @@ -259,7 +262,8 @@ throttle_provider_(std::move(throttle_provider)), websocket_handshake_throttle_provider_( std::move(websocket_handshake_throttle_provider)), - process_host_(std::move(process_host)) {} + process_host_(std::move(process_host)), + cors_exempt_header_list_(cors_exempt_header_list) {} WebWorkerFetchContextImpl::~WebWorkerFetchContextImpl() {} @@ -373,6 +377,7 @@ DCHECK(!receiver_.is_bound()); DCHECK(!preference_watcher_receiver_.is_bound()); resource_dispatcher_ = std::make_unique<ResourceDispatcher>(); + resource_dispatcher_->SetCorsExemptHeaderList(cors_exempt_header_list_); resource_dispatcher_->set_terminate_sync_load_event( terminate_sync_load_event_); @@ -620,7 +625,7 @@ ? websocket_handshake_throttle_provider_->Clone( std::move(task_runner)) : nullptr, - thread_safe_sender_.get(), process_host_)); + thread_safe_sender_.get(), process_host_, cors_exempt_header_list_)); new_context->is_on_sub_frame_ = is_on_sub_frame_; new_context->ancestor_frame_id_ = ancestor_frame_id_; new_context->frame_request_blocker_ = frame_request_blocker_;
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.h b/content/renderer/loader/web_worker_fetch_context_impl.h index 6d08e2d..1ea853a 100644 --- a/content/renderer/loader/web_worker_fetch_context_impl.h +++ b/content/renderer/loader/web_worker_fetch_context_impl.h
@@ -85,7 +85,8 @@ std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_fallback_factory, mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> - pending_subresource_loader_updater); + pending_subresource_loader_updater, + const std::vector<std::string>& cors_exempt_header_list); // Clones this fetch context for a nested worker. // For non-PlzDedicatedWorker. This will be removed once PlzDedicatedWorker is @@ -215,7 +216,8 @@ std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider, ThreadSafeSender* thread_safe_sender, - mojo::SharedRemote<mojom::ChildProcessHost> process_host); + mojo::SharedRemote<mojom::ChildProcessHost> process_host, + const std::vector<std::string>& cors_exempt_header_list); ~WebWorkerFetchContextImpl() override; @@ -359,6 +361,8 @@ mojo::SharedRemote<mojom::ChildProcessHost> process_host_; + std::vector<std::string> cors_exempt_header_list_; + std::unique_ptr<NavigationResponseOverrideParameters> response_override_; blink::AcceptLanguagesWatcher* accept_languages_watcher_ = nullptr;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 6a0c1ed8e..6a5b8f7 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -3697,7 +3697,10 @@ provider->context(), render_view_->renderer_preferences(), std::move(watcher_receiver), GetLoaderFactoryBundle()->Clone(), GetLoaderFactoryBundle()->CloneWithoutAppCacheFactory(), - /*pending_subresource_loader_updater=*/mojo::NullReceiver()); + /*pending_subresource_loader_updater=*/mojo::NullReceiver(), + RenderThreadImpl::current() + ->resource_dispatcher() + ->cors_exempt_header_list()); worker_fetch_context->set_ancestor_frame_id(routing_id_); worker_fetch_context->set_frame_request_blocker(frame_request_blocker_);
diff --git a/content/renderer/render_frame_metadata_observer_impl.cc b/content/renderer/render_frame_metadata_observer_impl.cc index 9c118ebbd5..f85ce39 100644 --- a/content/renderer/render_frame_metadata_observer_impl.cc +++ b/content/renderer/render_frame_metadata_observer_impl.cc
@@ -58,10 +58,10 @@ send_metadata |= force_send; } - // Allways cache the full metadata, so that it can correctly be sent upon - // ReportAllFrameSubmissionsForTesting or - // ReportAllRootScrollsForAccessibility. This must only be done after we've - // compared the two for changes. + // Always cache the full metadata, so that it can correctly be sent upon + // ReportAllFrameSubmissionsForTesting or on android, which notifies on any + // root scroll offset change. This must only be done after we've compared the + // two for changes. last_render_frame_metadata_ = render_frame_metadata; // If the metadata is different, updates all the observers; or the metadata is @@ -109,9 +109,8 @@ } #if defined(OS_ANDROID) -void RenderFrameMetadataObserverImpl::ReportAllRootScrollsForAccessibility( - bool enabled) { - report_all_root_scrolls_for_accessibility_enabled_ = enabled; +void RenderFrameMetadataObserverImpl::ReportAllRootScrolls(bool enabled) { + report_all_root_scrolls_enabled_ = enabled; if (enabled) SendLastRenderFrameMetadata(); @@ -160,7 +159,7 @@ #if defined(OS_ANDROID) bool need_send_root_scroll = - report_all_root_scrolls_for_accessibility_enabled_ && + report_all_root_scrolls_enabled_ && rfm1.root_scroll_offset != rfm2.root_scroll_offset; if (rfm1.bottom_controls_height != rfm2.bottom_controls_height || rfm1.bottom_controls_shown_ratio != rfm2.bottom_controls_shown_ratio ||
diff --git a/content/renderer/render_frame_metadata_observer_impl.h b/content/renderer/render_frame_metadata_observer_impl.h index f253f7b82..8186274 100644 --- a/content/renderer/render_frame_metadata_observer_impl.h +++ b/content/renderer/render_frame_metadata_observer_impl.h
@@ -45,7 +45,7 @@ // mojom::RenderFrameMetadataObserver: #if defined(OS_ANDROID) - void ReportAllRootScrollsForAccessibility(bool enabled) override; + void ReportAllRootScrolls(bool enabled) override; #endif void ReportAllFrameSubmissionsForTesting(bool enabled) override; @@ -67,7 +67,7 @@ #if defined(OS_ANDROID) // When true this will notify |render_frame_metadata_observer_client_| of all // frame submissions that involve a root scroll offset change. - bool report_all_root_scrolls_for_accessibility_enabled_ = false; + bool report_all_root_scrolls_enabled_ = false; #endif // When true this will notify |render_frame_metadata_observer_client_| of all
diff --git a/content/renderer/render_frame_metadata_observer_impl_unittest.cc b/content/renderer/render_frame_metadata_observer_impl_unittest.cc index cf19f246..3ad8ed1 100644 --- a/content/renderer/render_frame_metadata_observer_impl_unittest.cc +++ b/content/renderer/render_frame_metadata_observer_impl_unittest.cc
@@ -207,7 +207,7 @@ // Enable reporting for root scroll changes. This will generate one // notification. - observer_impl().ReportAllRootScrollsForAccessibility(true); + observer_impl().ReportAllRootScrolls(true); { base::RunLoop run_loop; EXPECT_CALL(client(), OnRenderFrameMetadataChanged(expected_frame_token,
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index bc1c3feb..b15d81e0 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1974,6 +1974,11 @@ user_agent_metadata_ = user_agent_metadata; } +void RenderThreadImpl::SetCorsExemptHeaderList( + const std::vector<std::string>& list) { + resource_dispatcher_->SetCorsExemptHeaderList(list); +} + void RenderThreadImpl::UpdateScrollbarTheme( mojom::UpdateScrollbarThemeParamsPtr params) { #if defined(OS_MACOSX)
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index fa74d6e..a1ab47f 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -469,6 +469,7 @@ void SetWebKitSharedTimersSuspended(bool suspend) override; void SetUserAgent(const std::string& user_agent) override; void SetUserAgentMetadata(const blink::UserAgentMetadata& metadata) override; + void SetCorsExemptHeaderList(const std::vector<std::string>& list) override; void UpdateScrollbarTheme( mojom::UpdateScrollbarThemeParamsPtr params) override; void OnSystemColorsChanged(int32_t aqua_color_variant,
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 1bc2949..aef34da7 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -77,6 +77,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "ppapi/buildflags/buildflags.h" #include "skia/ext/platform_canvas.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/input/web_input_event_attribution.h" #include "third_party/blink/public/common/input/web_mouse_event.h" #include "third_party/blink/public/common/page/web_drag_operation.h" @@ -2887,6 +2888,9 @@ // Disable occlusion if de-jelly effect is enabled. settings.enable_occlusion &= !settings.allow_de_jelly_effect; + settings.enable_transform_interop = + base::FeatureList::IsEnabled(blink::features::kTransformInterop); + return settings; }
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc index 3bcbd72..e46e3ce 100644 --- a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc +++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -13,7 +13,6 @@ #include "content/child/scoped_child_process_reference.h" #include "content/common/service_worker/service_worker_utils.h" #include "content/public/common/content_client.h" -#include "content/renderer/render_thread_impl.h" #include "content/renderer/service_worker/service_worker_context_client.h" #include "content/renderer/worker/fetch_client_settings_object_helpers.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -30,6 +29,7 @@ // static void EmbeddedWorkerInstanceClientImpl::Create( scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, + const std::vector<std::string>& cors_exempt_header_list, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver) { // This won't be leaked because the lifetime will be managed internally. @@ -38,15 +38,18 @@ // a chance to stop by calling TerminateWorkerContext() and waiting // before destructing. new EmbeddedWorkerInstanceClientImpl(std::move(receiver), - std::move(initiator_thread_task_runner)); + std::move(initiator_thread_task_runner), + cors_exempt_header_list); } void EmbeddedWorkerInstanceClientImpl::CreateForRequest( scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, + const std::vector<std::string>& cors_exempt_header_list, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver) { EmbeddedWorkerInstanceClientImpl::Create( - std::move(initiator_thread_task_runner), std::move(receiver)); + std::move(initiator_thread_task_runner), cors_exempt_header_list, + std::move(receiver)); } void EmbeddedWorkerInstanceClientImpl::WorkerContextDestroyed() { @@ -87,7 +90,7 @@ std::move(params->subresource_loader_factories), std::move(params->subresource_loader_updater), params->script_url_to_skip_throttling, initiator_thread_task_runner_, - params->service_worker_route_id); + params->service_worker_route_id, cors_exempt_header_list_); // Record UMA to indicate StartWorker is received on renderer. StartWorkerHistogramEnum metric = params->is_installed ? StartWorkerHistogramEnum::RECEIVED_ON_INSTALLED @@ -128,9 +131,11 @@ EmbeddedWorkerInstanceClientImpl::EmbeddedWorkerInstanceClientImpl( mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver, - scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner) + scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, + const std::vector<std::string>& cors_exempt_header_list) : receiver_(this, std::move(receiver)), - initiator_thread_task_runner_(std::move(initiator_thread_task_runner)) { + initiator_thread_task_runner_(std::move(initiator_thread_task_runner)), + cors_exempt_header_list_(cors_exempt_header_list) { DCHECK(initiator_thread_task_runner_->BelongsToCurrentThread()); receiver_.set_disconnect_handler(base::BindOnce( &EmbeddedWorkerInstanceClientImpl::OnError, base::Unretained(this)));
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.h b/content/renderer/service_worker/embedded_worker_instance_client_impl.h index 1e7bb540..085104e8 100644 --- a/content/renderer/service_worker/embedded_worker_instance_client_impl.h +++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.h
@@ -46,6 +46,7 @@ // instead of just creating an instance of EmbeddedWorkerInstanceClient. static void Create( scoped_refptr<base::SingleThreadTaskRunner> initiator_task_runner, + const std::vector<std::string>& cors_exempt_header_list, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver); @@ -54,6 +55,7 @@ // service_manager::BinderRegistry. static void CreateForRequest( scoped_refptr<base::SingleThreadTaskRunner> initiator_task_runner, + const std::vector<std::string>& cors_exempt_header_list, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver); @@ -72,7 +74,8 @@ EmbeddedWorkerInstanceClientImpl( mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver, - scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, + const std::vector<std::string>& cors_exempt_header_list); // blink::mojom::EmbeddedWorkerInstanceClient implementation void StartWorker(blink::mojom::EmbeddedWorkerStartParamsPtr params) override; @@ -89,6 +92,8 @@ // StartWorker(). scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner_; + std::vector<std::string> cors_exempt_header_list_; + // nullptr means worker is not running. std::unique_ptr<ServiceWorkerContextClient> service_worker_context_client_;
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index 21e5203..8a4d954 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -113,7 +113,8 @@ subresource_loader_updater, const GURL& script_url_to_skip_throttling, scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, - int32_t service_worker_route_id) + int32_t service_worker_route_id, + const std::vector<std::string>& cors_exempt_header_list) : service_worker_version_id_(service_worker_version_id), service_worker_scope_(service_worker_scope), script_url_(script_url), @@ -129,7 +130,8 @@ std::move(subresource_loader_updater)), owner_(owner), start_timing_(std::move(start_timing)), - service_worker_route_id_(service_worker_route_id) { + service_worker_route_id_(service_worker_route_id), + cors_exempt_header_list_(cors_exempt_header_list) { DCHECK(initiator_thread_task_runner_->RunsTasksInCurrentSequence()); DCHECK(owner_); DCHECK(subresource_loaders); @@ -389,7 +391,8 @@ ->renderer() ->CreateWebSocketHandshakeThrottleProvider(), std::move(preference_watcher_receiver_), - std::move(pending_subresource_loader_updater_), service_worker_route_id_); + std::move(pending_subresource_loader_updater_), service_worker_route_id_, + cors_exempt_header_list_); } void ServiceWorkerContextClient::OnNavigationPreloadResponse(
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h index 1ebc34c..54ead25 100644 --- a/content/renderer/service_worker/service_worker_context_client.h +++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -112,7 +112,8 @@ subresource_loader_updater, const GURL& script_url_to_skip_throttling, scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner, - int32_t service_worker_route_id); + int32_t service_worker_route_id, + const std::vector<std::string>& cors_exempt_header_list); // Called on the initiator thread. ~ServiceWorkerContextClient() override; @@ -283,6 +284,8 @@ int32_t service_worker_route_id_; + std::vector<std::string> cors_exempt_header_list_; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient); };
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc index 930a790..1282704b 100644 --- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc +++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -36,7 +36,8 @@ preference_watcher_receiver, mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater, - int32_t service_worker_route_id) + int32_t service_worker_route_id, + const std::vector<std::string>& cors_exempt_header_list) : renderer_preferences_(renderer_preferences), worker_script_url_(worker_script_url), pending_url_loader_factory_(std::move(pending_url_loader_factory)), @@ -49,7 +50,8 @@ std::move(preference_watcher_receiver)), pending_subresource_loader_updater_( std::move(pending_subresource_loader_updater)), - service_worker_route_id_(service_worker_route_id) {} + service_worker_route_id_(service_worker_route_id), + cors_exempt_header_list_(cors_exempt_header_list) {} ServiceWorkerFetchContextImpl::~ServiceWorkerFetchContextImpl() {} @@ -62,6 +64,7 @@ void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread( blink::AcceptLanguagesWatcher* watcher) { resource_dispatcher_ = std::make_unique<ResourceDispatcher>(); + resource_dispatcher_->SetCorsExemptHeaderList(cors_exempt_header_list_); resource_dispatcher_->set_terminate_sync_load_event( terminate_sync_load_event_); preference_watcher_receiver_.Bind(
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.h b/content/renderer/service_worker/service_worker_fetch_context_impl.h index 24a4c2200..0eb6cc7 100644 --- a/content/renderer/service_worker/service_worker_fetch_context_impl.h +++ b/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -52,7 +52,8 @@ preference_watcher_receiver, mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater, - int32_t service_worker_route_id); + int32_t service_worker_route_id, + const std::vector<std::string>& cors_exempt_header_list); // blink::WebServiceWorkerFetchContext implementation: void SetTerminateSyncLoadEvent(base::WaitableEvent*) override; @@ -136,6 +137,7 @@ blink::AcceptLanguagesWatcher* accept_languages_watcher_ = nullptr; int32_t service_worker_route_id_; + std::vector<std::string> cors_exempt_header_list_; bool is_offline_mode_ = false; };
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc b/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc index 236fbcd..3bedd8a0 100644 --- a/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc +++ b/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc
@@ -48,7 +48,8 @@ std::make_unique<FakeURLLoaderThrottleProvider>(), /*websocket_handshake_throttle_provider=*/nullptr, mojo::NullReceiver(), mojo::NullReceiver(), - /*service_worker_route_id=*/-1); + /*service_worker_route_id=*/-1, + /*cors_exempt_header_list=*/std::vector<std::string>()); { // Call WillSendRequest() for kScriptURL.
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc index 4e33a46..8f36cdfb 100644 --- a/content/renderer/worker/dedicated_worker_host_factory_client.cc +++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -7,7 +7,9 @@ #include <utility> #include "content/renderer/loader/child_url_loader_factory_bundle.h" #include "content/renderer/loader/navigation_response_override_parameters.h" +#include "content/renderer/loader/resource_dispatcher.h" #include "content/renderer/loader/web_worker_fetch_context_impl.h" +#include "content/renderer/render_thread_impl.h" #include "content/renderer/service_worker/service_worker_provider_context.h" #include "content/renderer/worker/fetch_client_settings_object_helpers.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -97,7 +99,10 @@ std::move(renderer_preference), std::move(watcher_receiver), subresource_loader_factory_bundle_->Clone(), subresource_loader_factory_bundle_->CloneWithoutAppCacheFactory(), - std::move(pending_subresource_loader_updater_)); + std::move(pending_subresource_loader_updater_), + RenderThreadImpl::current() + ->resource_dispatcher() + ->cors_exempt_header_list()); worker_fetch_context->SetResponseOverrideForMainScript( std::move(response_override_for_main_script_)); return worker_fetch_context;
diff --git a/content/renderer/worker/embedded_shared_worker_stub.cc b/content/renderer/worker/embedded_shared_worker_stub.cc index 879da02..1b517725 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.cc +++ b/content/renderer/worker/embedded_shared_worker_stub.cc
@@ -19,8 +19,10 @@ #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" #include "third_party/blink/public/common/messaging/message_port_descriptor.h" +#include "third_party/blink/public/mojom/browser_interface_broker.mojom.h" #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" +#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom.h" #include "third_party/blink/public/platform/web_fetch_client_settings_object.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/web/web_shared_worker.h" @@ -50,12 +52,14 @@ mojo::PendingRemote<blink::mojom::SharedWorkerHost> host, mojo::PendingReceiver<blink::mojom::SharedWorker> receiver, mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> - browser_interface_broker) + browser_interface_broker, + const std::vector<std::string>& cors_exempt_header_list) : receiver_(this, std::move(receiver)), host_(std::move(host)), url_(info->url), renderer_preferences_(renderer_preferences), - preference_watcher_receiver_(std::move(preference_watcher_receiver)) { + preference_watcher_receiver_(std::move(preference_watcher_receiver)), + cors_exempt_header_list_(cors_exempt_header_list) { DCHECK(main_script_load_params); DCHECK(pending_subresource_loader_factory_bundle); @@ -112,8 +116,8 @@ info->content_security_policy_type, info->creation_address_space, FetchClientSettingsObjectFromMojomToWeb( info->outside_fetch_client_settings_object), - appcache_host_id, devtools_worker_token, content_settings.PassPipe(), - browser_interface_broker.PassPipe(), pause_on_start); + appcache_host_id, devtools_worker_token, std::move(content_settings), + std::move(browser_interface_broker), pause_on_start); // If the host drops its connection, then self-destruct. receiver_.set_disconnect_handler(base::BindOnce( @@ -126,14 +130,13 @@ } void EmbeddedSharedWorkerStub::WorkerReadyForInspection( - mojo::ScopedMessagePipeHandle devtools_agent_remote_handle, - mojo::ScopedMessagePipeHandle devtools_agent_host_receiver_handle) { - mojo::PendingRemote<blink::mojom::DevToolsAgent> remote( - std::move(devtools_agent_remote_handle), - blink::mojom::DevToolsAgent::Version_); - mojo::PendingReceiver<blink::mojom::DevToolsAgentHost> receiver( - std::move(devtools_agent_host_receiver_handle)); - host_->OnReadyForInspection(std::move(remote), std::move(receiver)); + blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase> + devtools_agent_remote, + blink::CrossVariantMojoReceiver< + blink::mojom::DevToolsAgentHostInterfaceBase> + devtools_agent_host_receiver) { + host_->OnReadyForInspection(std::move(devtools_agent_remote), + std::move(devtools_agent_host_receiver)); } void EmbeddedSharedWorkerStub::WorkerScriptLoadFailed( @@ -178,7 +181,8 @@ std::move(preference_watcher_receiver_), subresource_loader_factory_bundle_->Clone(), std::move(fallback_factory), - /*pending_subresource_loader_updater*/ mojo::NullReceiver()); + /*pending_subresource_loader_updater*/ mojo::NullReceiver(), + cors_exempt_header_list_); // TODO(horo): To get the correct first_party_to_cookies for the shared // worker, we need to check the all documents bounded by the shared worker.
diff --git a/content/renderer/worker/embedded_shared_worker_stub.h b/content/renderer/worker/embedded_shared_worker_stub.h index edae852..8198b99 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.h +++ b/content/renderer/worker/embedded_shared_worker_stub.h
@@ -78,7 +78,8 @@ mojo::PendingRemote<blink::mojom::SharedWorkerHost> host, mojo::PendingReceiver<blink::mojom::SharedWorker> receiver, mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> - browser_interface_broker); + browser_interface_broker, + const std::vector<std::string>& cors_exempt_header_list); ~EmbeddedSharedWorkerStub() override; // blink::WebSharedWorkerClient implementation. @@ -86,8 +87,11 @@ void WorkerContextClosed() override; void WorkerContextDestroyed() override; void WorkerReadyForInspection( - mojo::ScopedMessagePipeHandle devtools_agent_ptr_info, - mojo::ScopedMessagePipeHandle devtools_agent_host_request) override; + blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase> + devtools_agent_remote, + blink::CrossVariantMojoReceiver< + blink::mojom::DevToolsAgentHostInterfaceBase> + devtools_agent_host_receiver) override; void WorkerScriptLoadFailed(const std::string& error_message) override; void WorkerScriptEvaluated(bool success) override; scoped_refptr<blink::WebWorkerFetchContext> CreateWorkerFetchContext() @@ -114,6 +118,8 @@ preference_watcher_receiver_; std::unique_ptr<blink::WebSharedWorker> impl_; + std::vector<std::string> cors_exempt_header_list_; + using PendingChannel = std::pair<int /* connection_request_id */, blink::MessagePortChannel>; std::vector<PendingChannel> pending_channels_;
diff --git a/content/renderer/worker/shared_worker_factory_impl.cc b/content/renderer/worker/shared_worker_factory_impl.cc index ecb2e19f..38c30ab 100644 --- a/content/renderer/worker/shared_worker_factory_impl.cc +++ b/content/renderer/worker/shared_worker_factory_impl.cc
@@ -5,6 +5,8 @@ #include "content/renderer/worker/shared_worker_factory_impl.h" #include "base/memory/ptr_util.h" +#include "content/renderer/loader/resource_dispatcher.h" +#include "content/renderer/render_thread_impl.h" #include "content/renderer/worker/embedded_shared_worker_stub.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" @@ -53,8 +55,10 @@ appcache_host_id.value_or(base::UnguessableToken()), std::move(main_script_load_params), std::move(subresource_loader_factories), std::move(controller_info), - std::move(host), std::move(receiver), - std::move(browser_interface_broker)); + std::move(host), std::move(receiver), std::move(browser_interface_broker), + RenderThreadImpl::current() + ->resource_dispatcher() + ->cors_exempt_header_list()); } } // namespace content
diff --git a/content/test/data/accessibility/aria/aria-illegal-val.html b/content/test/data/accessibility/aria/aria-illegal-val.html index b65027e..c9e8b51 100644 --- a/content/test/data/accessibility/aria/aria-illegal-val.html +++ b/content/test/data/accessibility/aria/aria-illegal-val.html
@@ -35,7 +35,6 @@ @BLINK-ALLOW:pressed* @BLINK-ALLOW:required* @BLINK-ALLOW:restriction* -@BLINK-ALLOW:select* @BLINK-ALLOW:sort* @BLINK-ALLOW:vertical* @AURALINUX-ALLOW:atomic* @@ -65,14 +64,14 @@ --> <html> <body> -<!-- Technically, illegal atomic values should be exposed in the object attr, +<!-- Technically, illegal atomic values should be exposed in the object attr, does not seem like a priority --> <div aria-atomic="X-ILLEGAL" role="log" aria-label="Atomic illegal"></div> <div aria-autocomplete="X-ILLEGAL" role="textbox" aria-label="Autocomplete illegal"></div> <div aria-busy="X-ILLEGAL" role="log" aria-label="Busy illegal"></div> <div aria-checked="X-ILLEGAL" role="treeitem" aria-label="Checked illegal"></div> -<!-- aria-current rules from https://www.w3.org/TR/wai-aria-1.1/#aria-current: - "Any value not included in the list of allowed values should be treated by +<!-- aria-current rules from https://www.w3.org/TR/wai-aria-1.1/#aria-current: + "Any value not included in the list of allowed values should be treated by assistive technologies as if the value true had been provided." --> <div aria-current="X-ILLEGAL" aria-label="Current illegal"></div> <div aria-disabled="X-ILLEGAL" aria-label="Disabled illegal"></div> @@ -99,7 +98,7 @@ <div role="grid"> <div aria-sort="X-ILLEGAL" role="columnheader" aria-label="Sort illegal"></div> </div> -<!-- Test aria-hidden at end because a broken test can have extra object, +<!-- Test aria-hidden at end because a broken test can have extra object, and ruin the rest of the test. --> <div aria-hidden="X-ILLEGAL" aria-label="Hidden illegal"></div> </body>
diff --git a/content/test/data/accessibility/aria/aria-option.html b/content/test/data/accessibility/aria/aria-option.html index ffd7dba..b62001b7 100644 --- a/content/test/data/accessibility/aria/aria-option.html +++ b/content/test/data/accessibility/aria/aria-option.html
@@ -3,7 +3,6 @@ @WIN-ALLOW:xml-roles* @WIN-ALLOW:SELECT* @BLINK-ALLOW:focus* -@BLINK-ALLOW:select* @AURALINUX-ALLOW:xml-roles* @AURALINUX-ALLOW:select* -->
diff --git a/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-android.txt b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-android.txt new file mode 100644 index 0000000..36fc041f --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-android.txt
@@ -0,0 +1,5 @@ +android.webkit.WebView focusable scrollable +++android.widget.TabWidget role_description='tab list' +++++android.view.View role_description='tab' clickable focusable focused name='tab1' +++++android.view.View role_description='tab' clickable focusable name='tab2' item_index=1 row_index=1 +++android.widget.TextView name='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-auralinux.txt b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-auralinux.txt new file mode 100644 index 0000000..519fd2d --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[page tab list] horizontal +++++[page tab] name='tab1' selectable +++++[page tab] name='tab2' selectable +++[static] name='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-blink.txt b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-blink.txt new file mode 100644 index 0000000..1e97724 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-blink.txt
@@ -0,0 +1,8 @@ +rootWebArea +++genericContainer ignored +++++genericContainer ignored +++++++tabList horizontal +++++++++tab name='tab1' selected=false selectedFromFocus=false +++++++++tab name='tab2' selected=false selectedFromFocus=false +++++++staticText name='Done' +++++++++inlineTextBox name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-mac.txt b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-mac.txt new file mode 100644 index 0000000..717c9856 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-mac.txt
@@ -0,0 +1,5 @@ +AXWebArea AXSelected='0' +++AXTabGroup AXSelected='0' +++++AXRadioButton AXSelected='0' AXTitle='tab1' AXValue='0' +++++AXRadioButton AXSelected='0' AXTitle='tab2' AXValue='0' +++AXStaticText AXSelected='0' AXValue='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-uia-win.txt b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-uia-win.txt new file mode 100644 index 0000000..0526a14 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-uia-win.txt
@@ -0,0 +1,5 @@ +Document +++Tab Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false +++++TabItem Name='tab1' SelectionItem.IsSelected=false +++++TabItem Name='tab2' SelectionItem.IsSelected=false +++Text Name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-win.txt b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-win.txt new file mode 100644 index 0000000..c8bce0b --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false-expected-win.txt
@@ -0,0 +1,5 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL +++++ROLE_SYSTEM_PAGETAB name='tab1' FOCUSABLE +++++ROLE_SYSTEM_PAGETAB name='tab2' FOCUSABLE +++ROLE_SYSTEM_STATICTEXT name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-aria-selected-false.html b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false.html new file mode 100644 index 0000000..3823ae4 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-aria-selected-false.html
@@ -0,0 +1,21 @@ +<!-- +@BLINK-ALLOW:selectedFromFocus* +@MAC-ALLOW:AXSelected=* +@WAIT-FOR:Done +--> +<html> +<body> + <div role="tablist"> + <button role="tab" id="tab1" aria-selected="false">tab1</button> + <button role="tab">tab2</button> + </div> +</body> + +<script> + // Setting focus on "tab1" with aria-selected="false" will NOT result in it + // being selected. + document.getElementById("tab1").focus(); + document.body.appendChild(document.createTextNode("Done")); +</script> + +</html>
diff --git a/content/test/data/accessibility/html/select-follows-focus-expected-android.txt b/content/test/data/accessibility/html/select-follows-focus-expected-android.txt new file mode 100644 index 0000000..7ede48dc --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-expected-android.txt
@@ -0,0 +1,6 @@ +android.webkit.WebView focusable scrollable +++android.widget.TabWidget role_description='tab list' +++++android.view.View role_description='tab' clickable focusable focused selected name='tab1' +++++android.view.View role_description='tab' clickable focusable selected name='tab2' item_index=1 row_index=1 +++++android.view.View role_description='tab' clickable focusable name='tab3' item_index=2 row_index=2 +++android.widget.TextView name='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-expected-auralinux.txt b/content/test/data/accessibility/html/select-follows-focus-expected-auralinux.txt new file mode 100644 index 0000000..8e9ca3df --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[page tab list] horizontal +++++[page tab] name='tab1' selectable selected +++++[page tab] name='tab2' selectable selected +++++[page tab] name='tab3' selectable +++[static] name='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-expected-blink.txt b/content/test/data/accessibility/html/select-follows-focus-expected-blink.txt new file mode 100644 index 0000000..4a66fa5 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-expected-blink.txt
@@ -0,0 +1,9 @@ +rootWebArea +++genericContainer ignored +++++genericContainer ignored +++++++tabList horizontal +++++++++tab name='tab1' selected=true selectedFromFocus=true +++++++++tab name='tab2' selected=true selectedFromFocus=false +++++++++tab name='tab3' selected=false selectedFromFocus=false +++++++staticText name='Done' +++++++++inlineTextBox name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-expected-mac.txt b/content/test/data/accessibility/html/select-follows-focus-expected-mac.txt new file mode 100644 index 0000000..694d00d --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-expected-mac.txt
@@ -0,0 +1,6 @@ +AXWebArea AXSelected='0' +++AXTabGroup AXSelected='0' +++++AXRadioButton AXSelected='1' AXTitle='tab1' AXValue='1' +++++AXRadioButton AXSelected='1' AXTitle='tab2' AXValue='1' +++++AXRadioButton AXSelected='0' AXTitle='tab3' AXValue='0' +++AXStaticText AXSelected='0' AXValue='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-expected-uia-win.txt b/content/test/data/accessibility/html/select-follows-focus-expected-uia-win.txt new file mode 100644 index 0000000..830ce47 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-expected-uia-win.txt
@@ -0,0 +1,6 @@ +Document +++Tab Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false +++++TabItem Name='tab1' SelectionItem.IsSelected=true +++++TabItem Name='tab2' SelectionItem.IsSelected=true +++++TabItem Name='tab3' SelectionItem.IsSelected=false +++Text Name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-expected-win.txt b/content/test/data/accessibility/html/select-follows-focus-expected-win.txt new file mode 100644 index 0000000..12ac1cc1 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-expected-win.txt
@@ -0,0 +1,6 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL +++++ROLE_SYSTEM_PAGETAB name='tab1' SELECTED FOCUSABLE +++++ROLE_SYSTEM_PAGETAB name='tab2' SELECTED FOCUSABLE +++++ROLE_SYSTEM_PAGETAB name='tab3' FOCUSABLE +++ROLE_SYSTEM_STATICTEXT name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-android.txt b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-android.txt new file mode 100644 index 0000000..6195597 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-android.txt
@@ -0,0 +1,6 @@ +android.webkit.WebView focusable scrollable +++android.widget.TabWidget role_description='tab list' +++++android.view.View role_description='tab' clickable focusable focused name='tab1' +++++android.view.View role_description='tab' clickable focusable selected name='tab2' item_index=1 row_index=1 +++++android.view.View role_description='tab' clickable focusable name='tab3' item_index=2 row_index=2 +++android.widget.TextView name='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-auralinux.txt b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-auralinux.txt new file mode 100644 index 0000000..d283bef8 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[page tab list] horizontal multiselectable +++++[page tab] name='tab1' selectable +++++[page tab] name='tab2' selectable selected +++++[page tab] name='tab3' selectable +++[static] name='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-blink.txt b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-blink.txt new file mode 100644 index 0000000..36a76eb --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-blink.txt
@@ -0,0 +1,9 @@ +rootWebArea +++genericContainer ignored +++++genericContainer ignored +++++++tabList horizontal multiselectable +++++++++tab name='tab1' selected=false selectedFromFocus=false +++++++++tab name='tab2' selected=true selectedFromFocus=false +++++++++tab name='tab3' selected=false selectedFromFocus=false +++++++staticText name='Done' +++++++++inlineTextBox name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-mac.txt b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-mac.txt new file mode 100644 index 0000000..168b32b --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-mac.txt
@@ -0,0 +1,6 @@ +AXWebArea AXSelected='0' +++AXTabGroup AXSelected='0' +++++AXRadioButton AXSelected='0' AXTitle='tab1' AXValue='0' +++++AXRadioButton AXSelected='1' AXTitle='tab2' AXValue='1' +++++AXRadioButton AXSelected='0' AXTitle='tab3' AXValue='0' +++AXStaticText AXSelected='0' AXValue='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-uia-win.txt b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-uia-win.txt new file mode 100644 index 0000000..cd58d4722 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-uia-win.txt
@@ -0,0 +1,6 @@ +Document +++Tab Selection.CanSelectMultiple=true Selection.IsSelectionRequired=false +++++TabItem Name='tab1' SelectionItem.IsSelected=false +++++TabItem Name='tab2' SelectionItem.IsSelected=true +++++TabItem Name='tab3' SelectionItem.IsSelected=false +++Text Name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-win.txt b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-win.txt new file mode 100644 index 0000000..5cc5da94 --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-multiselect-expected-win.txt
@@ -0,0 +1,6 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++ROLE_SYSTEM_PAGETABLIST MULTISELECTABLE IA2_STATE_HORIZONTAL +++++ROLE_SYSTEM_PAGETAB name='tab1' FOCUSABLE +++++ROLE_SYSTEM_PAGETAB name='tab2' SELECTED FOCUSABLE +++++ROLE_SYSTEM_PAGETAB name='tab3' FOCUSABLE +++ROLE_SYSTEM_STATICTEXT name='Done'
diff --git a/content/test/data/accessibility/html/select-follows-focus-multiselect.html b/content/test/data/accessibility/html/select-follows-focus-multiselect.html new file mode 100644 index 0000000..e47f7ef --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus-multiselect.html
@@ -0,0 +1,22 @@ +<!-- +@BLINK-ALLOW:selectedFromFocus* +@MAC-ALLOW:AXSelected=* +@WAIT-FOR:Done +--> +<html> +<body> + <div role="tablist" aria-multiselectable="true"> + <button role="tab" id="tab1">tab1</button> + <button role="tab" aria-selected="true">tab2</button> + <button role="tab">tab3</button> + </div> +</body> + +<script> + // Setting focus on "tab1" in a multiselectable container will NOT result in + // it being selected. + document.getElementById("tab1").focus(); + document.body.appendChild(document.createTextNode("Done")); +</script> + +</html>
diff --git a/content/test/data/accessibility/html/select-follows-focus.html b/content/test/data/accessibility/html/select-follows-focus.html new file mode 100644 index 0000000..802aeeb --- /dev/null +++ b/content/test/data/accessibility/html/select-follows-focus.html
@@ -0,0 +1,21 @@ +<!-- +@BLINK-ALLOW:selectedFromFocus* +@MAC-ALLOW:AXSelected=* +@WAIT-FOR:Done +--> +<html> +<body> + <div role="tablist"> + <button role="tab" id="tab1">tab1</button> + <button role="tab" aria-selected="true">tab2</button> + <button role="tab">tab3</button> + </div> +</body> + +<script> + // Setting focus on "tab1" will result it being selected. + document.getElementById("tab1").focus(); + document.body.appendChild(document.createTextNode("Done")); +</script> + +</html>
diff --git a/content/test/data/accessibility/html/select.html b/content/test/data/accessibility/html/select.html index fc2ca669..9d8e5b5 100644 --- a/content/test/data/accessibility/html/select.html +++ b/content/test/data/accessibility/html/select.html
@@ -7,7 +7,6 @@ @WIN-ALLOW:EXTSELECTABLE @WIN-ALLOW:SELECT* @BLINK-ALLOW:focus* -@BLINK-ALLOW:select* @BLINK-ALLOW:setSize* @BLINK-ALLOW:posInSet* @BLINK-ALLOW:haspopup*
diff --git a/content/test/data/accessibility/language-detection/dynamic-basic-expected-blink.txt b/content/test/data/accessibility/language-detection/dynamic-basic-expected-blink.txt index ff0c9ef..5778638 100644 --- a/content/test/data/accessibility/language-detection/dynamic-basic-expected-blink.txt +++ b/content/test/data/accessibility/language-detection/dynamic-basic-expected-blink.txt
@@ -1,4 +1,4 @@ -rootWebArea language='en-US' +rootWebArea language='fr-FR' ++genericContainer ignored language='fr-FR' ++++genericContainer ignored language='fr-FR' ++++++genericContainer language='fr-FR'
diff --git a/content/test/data/accessibility/language-detection/dynamic-basic-expected-mac.txt b/content/test/data/accessibility/language-detection/dynamic-basic-expected-mac.txt index 37c0a420..5198c89 100644 --- a/content/test/data/accessibility/language-detection/dynamic-basic-expected-mac.txt +++ b/content/test/data/accessibility/language-detection/dynamic-basic-expected-mac.txt
@@ -1,3 +1,3 @@ -AXWebArea AXLanguage='en-US' +AXWebArea AXLanguage='fr-FR' ++AXGroup AXLanguage='fr-FR' ++++AXStaticText AXLanguage='de' AXValue='Ein Bild ist nicht zu verwechseln mit einer Sache, die man berühren kann. Können Sie meine Pfeife stopfen? Natürlich nicht! Sie ist nur eine Darstellung. Hätte ich auf mein Bild geschrieben, dies ist eine Pfeife, so hätte ich gelogen. Das Abbild einer Marmeladenschnitte ist ganz gewiss nichts Essbares.'
diff --git a/content/test/data/accessibility/language-detection/dynamic-multiple-inserts-expected-blink.txt b/content/test/data/accessibility/language-detection/dynamic-multiple-inserts-expected-blink.txt index 6b850f9..e1f7497b 100644 --- a/content/test/data/accessibility/language-detection/dynamic-multiple-inserts-expected-blink.txt +++ b/content/test/data/accessibility/language-detection/dynamic-multiple-inserts-expected-blink.txt
@@ -1,4 +1,4 @@ -rootWebArea language='en-US' +rootWebArea language='fr-FR' ++genericContainer ignored language='fr-FR' ++++genericContainer ignored language='fr-FR' ++++++genericContainer language='fr-FR'
diff --git a/content/test/data/accessibility/language-detection/dynamic-multiple-inserts-expected-mac.txt b/content/test/data/accessibility/language-detection/dynamic-multiple-inserts-expected-mac.txt index 39fd8be4..da6a48d 100644 --- a/content/test/data/accessibility/language-detection/dynamic-multiple-inserts-expected-mac.txt +++ b/content/test/data/accessibility/language-detection/dynamic-multiple-inserts-expected-mac.txt
@@ -1,4 +1,4 @@ -AXWebArea AXLanguage='en-US' +AXWebArea AXLanguage='fr-FR' ++AXGroup AXLanguage='fr-FR' ++++AXGroup AXLanguage='fr-FR' ++++++AXStaticText AXLanguage='en' AXValue='This is text created using Google Translate, it is unlikely to be idiomatic in the given target language. This text is only used to test language detection'
diff --git a/content/test/data/accessibility/language-detection/dynamic-reparenting-expected-blink.txt b/content/test/data/accessibility/language-detection/dynamic-reparenting-expected-blink.txt index 50720ddd..112584e3 100644 --- a/content/test/data/accessibility/language-detection/dynamic-reparenting-expected-blink.txt +++ b/content/test/data/accessibility/language-detection/dynamic-reparenting-expected-blink.txt
@@ -1,4 +1,4 @@ -rootWebArea language='en-US' +rootWebArea language='fr-FR' ++genericContainer ignored language='fr-FR' ++++genericContainer ignored language='fr-FR' ++++++list language='fr-FR'
diff --git a/content/test/data/accessibility/language-detection/dynamic-reparenting-expected-mac.txt b/content/test/data/accessibility/language-detection/dynamic-reparenting-expected-mac.txt index 1eeb3e5a..a69580513 100644 --- a/content/test/data/accessibility/language-detection/dynamic-reparenting-expected-mac.txt +++ b/content/test/data/accessibility/language-detection/dynamic-reparenting-expected-mac.txt
@@ -1,4 +1,4 @@ -AXWebArea AXLanguage='en-US' +AXWebArea AXLanguage='fr-FR' ++AXList AXLanguage='fr-FR' ++AXList AXLanguage='fr-FR' ++++AXGroup AXLanguage='fr-FR'
diff --git a/content/test/data/accessibility/language-detection/lang-attribute-expected-blink.txt b/content/test/data/accessibility/language-detection/lang-attribute-expected-blink.txt index a0b91f6f..fe0721d 100644 --- a/content/test/data/accessibility/language-detection/lang-attribute-expected-blink.txt +++ b/content/test/data/accessibility/language-detection/lang-attribute-expected-blink.txt
@@ -1,6 +1,6 @@ -rootWebArea language='en-US' -++genericContainer ignored language='en' -++++genericContainer language='en' +rootWebArea language='es-ES' +++genericContainer ignored language='es-ES' +++++genericContainer language='es-ES' ++++++staticText language='es-ES' name='Este documento es excelente. ' ++++++++inlineTextBox language='es-ES' name='Este documento es excelente. ' ++++++staticText language='fr' name='Ce document est excellent. '
diff --git a/content/test/data/accessibility/language-detection/lang-attribute-expected-mac.txt b/content/test/data/accessibility/language-detection/lang-attribute-expected-mac.txt index aa309f4..c7299c12 100644 --- a/content/test/data/accessibility/language-detection/lang-attribute-expected-mac.txt +++ b/content/test/data/accessibility/language-detection/lang-attribute-expected-mac.txt
@@ -1,5 +1,5 @@ -AXWebArea AXLanguage='en-US' -++AXGroup AXLanguage='en' +AXWebArea AXLanguage='es-ES' +++AXGroup AXLanguage='es-ES' ++++AXStaticText AXLanguage='es-ES' AXValue='Este documento es excelente. ' ++++AXStaticText AXLanguage='fr' AXValue='Ce document est excellent. ' ++++AXStaticText AXLanguage='en' AXValue='This document is excellent.'
diff --git a/content/test/data/accessibility/language-detection/lang-attribute-expected-win.txt b/content/test/data/accessibility/language-detection/lang-attribute-expected-win.txt index 40b1f507..8918bef 100644 --- a/content/test/data/accessibility/language-detection/lang-attribute-expected-win.txt +++ b/content/test/data/accessibility/language-detection/lang-attribute-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE language:en +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE language:es-ES ++IA2_ROLE_SECTION language:es-ES language:fr language:en ++++ROLE_SYSTEM_STATICTEXT name='Este documento es excelente. ' language:es-ES ++++ROLE_SYSTEM_STATICTEXT name='Ce document est excellent. ' language:fr
diff --git a/content/test/data/accessibility/language-detection/lang-attribute-nested-expected-blink.txt b/content/test/data/accessibility/language-detection/lang-attribute-nested-expected-blink.txt index 6fa75081..b37486e 100644 --- a/content/test/data/accessibility/language-detection/lang-attribute-nested-expected-blink.txt +++ b/content/test/data/accessibility/language-detection/lang-attribute-nested-expected-blink.txt
@@ -1,4 +1,4 @@ -rootWebArea language='en-US' +rootWebArea language='en' ++genericContainer ignored language='en' ++++genericContainer ignored language='en' ++++++genericContainer ignored language='es-ES'
diff --git a/content/test/data/accessibility/language-detection/lang-attribute-nested-expected-mac.txt b/content/test/data/accessibility/language-detection/lang-attribute-nested-expected-mac.txt index 68e063d02..b641f91 100644 --- a/content/test/data/accessibility/language-detection/lang-attribute-nested-expected-mac.txt +++ b/content/test/data/accessibility/language-detection/lang-attribute-nested-expected-mac.txt
@@ -1,4 +1,4 @@ -AXWebArea AXLanguage='en-US' +AXWebArea AXLanguage='en' ++AXGroup AXLanguage='en' ++++AXStaticText AXLanguage='en' AXValue='This document is excellent.' ++AXStaticText AXLanguage='es-ES' AXValue='Este documento es excelente.'
diff --git a/content/test/data/accessibility/language-detection/lang-attribute-switching-expected-blink.txt b/content/test/data/accessibility/language-detection/lang-attribute-switching-expected-blink.txt index 372baeb..c0d7d42 100644 --- a/content/test/data/accessibility/language-detection/lang-attribute-switching-expected-blink.txt +++ b/content/test/data/accessibility/language-detection/lang-attribute-switching-expected-blink.txt
@@ -1,4 +1,4 @@ -rootWebArea language='en-US' +rootWebArea language='en' ++genericContainer ignored language='en' ++++genericContainer ignored language='en' ++++++paragraph language='en'
diff --git a/content/test/data/accessibility/language-detection/lang-attribute-switching-expected-mac.txt b/content/test/data/accessibility/language-detection/lang-attribute-switching-expected-mac.txt index 420dbf24..2188c21 100644 --- a/content/test/data/accessibility/language-detection/lang-attribute-switching-expected-mac.txt +++ b/content/test/data/accessibility/language-detection/lang-attribute-switching-expected-mac.txt
@@ -1,4 +1,4 @@ -AXWebArea AXLanguage='en-US' +AXWebArea AXLanguage='en' ++AXGroup AXLanguage='en' ++++AXStaticText AXLanguage='en' AXValue='In the morning, I sometimes eat breakfast.' ++AXGroup AXLanguage='fr'
diff --git a/content/test/data/accessibility/language-detection/lang-attribute.html b/content/test/data/accessibility/language-detection/lang-attribute.html index ff201a7..fe3007b6 100644 --- a/content/test/data/accessibility/language-detection/lang-attribute.html +++ b/content/test/data/accessibility/language-detection/lang-attribute.html
@@ -4,9 +4,9 @@ @MAC-ALLOW:AXLanguage* --> <!DOCTYPE html> -<html lang="en"> +<html lang="es-ES"> <body> - <span lang="es-ES"> + <span> Este documento es excelente. </span> @@ -14,7 +14,7 @@ Ce document est excellent. </span> - <span> + <span lang="en"> This document is excellent. </span>
diff --git a/content/test/data/accessibility/language-detection/static-basic-expected-blink.txt b/content/test/data/accessibility/language-detection/static-basic-expected-blink.txt index 94ba26a..6d39397 100644 --- a/content/test/data/accessibility/language-detection/static-basic-expected-blink.txt +++ b/content/test/data/accessibility/language-detection/static-basic-expected-blink.txt
@@ -1,4 +1,4 @@ -rootWebArea language='en-US' +rootWebArea language='en-GB' ++genericContainer ignored language='en-GB' ++++genericContainer ignored language='en-GB' ++++++genericContainer language='fr'
diff --git a/content/test/data/accessibility/language-detection/static-basic-expected-mac.txt b/content/test/data/accessibility/language-detection/static-basic-expected-mac.txt index 929423d..b79b29f 100644 --- a/content/test/data/accessibility/language-detection/static-basic-expected-mac.txt +++ b/content/test/data/accessibility/language-detection/static-basic-expected-mac.txt
@@ -1,4 +1,4 @@ -AXWebArea AXLanguage='en-US' +AXWebArea AXLanguage='en-GB' ++AXGroup AXLanguage='fr' ++++AXStaticText AXLanguage='en' AXValue='“The famous pipe. How people reproached me for it! And yet, could you stuff my pipe? No, it’s just a representation, is it not? So if I had written on my picture ‘This is a pipe,’ I’d have been lying!"' ++AXGroup AXLanguage='en'
diff --git a/content/test/gpu/gpu_tests/maps_integration_test.py b/content/test/gpu/gpu_tests/maps_integration_test.py index 9d473120..ef1c85e 100644 --- a/content/test/gpu/gpu_tests/maps_integration_test.py +++ b/content/test/gpu/gpu_tests/maps_integration_test.py
@@ -13,6 +13,7 @@ from gpu_tests import skia_gold_integration_test_base from py_utils import cloud_storage +from telemetry.util import image_util _MAPS_PERF_TEST_PATH = os.path.join(path_util.GetChromiumSrcDir(), 'tools', 'perf', 'page_sets', 'maps_perf_test') @@ -92,7 +93,15 @@ dpr = tab.EvaluateJavaScript('window.devicePixelRatio') print 'Maps\' devicePixelRatio is ' + str(dpr) + page = _GetMapsPageForUrl(url) + if page.test_rect: + img_height, img_width = screenshot.shape[:2] + screenshot = image_util.Crop(screenshot, int(page.test_rect[0] * dpr), + int(page.test_rect[1] * dpr), + min(int(page.test_rect[2] * dpr), img_width), + min(int(page.test_rect[3] * dpr), img_height)) + self._UploadTestResultToSkiaGold(_TEST_NAME, screenshot, page, self._GetBuildIdArgs()) @@ -111,7 +120,7 @@ name=_TEST_NAME, # Exact test_rect is arbitrary, just needs to encapsulate all pixels # that are tested. - test_rect=[0, 0, 600, 400], + test_rect=[0, 0, 1000, 800], grace_period_end=datetime.date(2020, 6, 22), matching_algorithm=pixel_test_pages.VERY_PERMISSIVE_SOBEL_ALGO) return page
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 83c27b5..89d1c9a 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -367,7 +367,6 @@ crbug.com/1059760 [ mac asan ] conformance/textures/image_bitmap_from_video/* [ RetryOnFailure ] crbug.com/1059760 [ mac no-passthrough asan ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] crbug.com/1059760 [ mac asan ] conformance/textures/video/* [ RetryOnFailure ] -crbug.com/1087083 [ mac passthrough amd asan ] conformance2/textures/webgl_canvas/tex-3d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] #################### # Linux failures # @@ -447,7 +446,7 @@ crbug.com/733599 [ android ] conformance/textures/video/tex-2d-alpha-alpha-unsigned_byte.html [ RetryOnFailure ] crbug.com/733599 [ android no-angle ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ RetryOnFailure ] crbug.com/733599 [ android no-angle ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ RetryOnFailure ] -crbug.com/834933 [ android android-chromium no-angle ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html [ RetryOnFailure ] +crbug.com/834933 [ android android-chromium ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html [ RetryOnFailure ] crbug.com/834933 [ android android-chromium ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html [ RetryOnFailure ] crbug.com/891456 [ android ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ RetryOnFailure ] @@ -568,6 +567,8 @@ crbug.com/891456 [ android nvidia ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_byte.html [ RetryOnFailure ] crbug.com/1025790 [ android nvidia ] conformance/textures/misc/tex-image-canvas-corruption.html [ Skip ] crbug.com/478572 [ android nvidia ] deqp/data/gles2/shaders/functions.html [ Failure ] +# Texture tests found to generate intermittent GL errors in the GPU process +crbug.com/1090407 [ android nvidia ] conformance/textures/* [ RetryOnFailure ] # Flaky timeout on android_n5x_swarming_rel and # android-marshmallow-arm64-rel.
diff --git a/device/fido/fido_discovery_factory.cc b/device/fido/fido_discovery_factory.cc index 120c5ac6..a2e4e418 100644 --- a/device/fido/fido_discovery_factory.cc +++ b/device/fido/fido_discovery_factory.cc
@@ -47,10 +47,6 @@ FidoDiscoveryFactory::FidoDiscoveryFactory() = default; FidoDiscoveryFactory::~FidoDiscoveryFactory() = default; -void FidoDiscoveryFactory::ResetRequestState() { - request_state_ = {}; -} - std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create( FidoTransportProtocol transport) { switch (transport) { @@ -59,13 +55,10 @@ case FidoTransportProtocol::kBluetoothLowEnergy: return nullptr; case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy: - if (request_state_.cable_data_.has_value() || - request_state_.qr_generator_key_.has_value()) { + if (cable_data_.has_value() || qr_generator_key_.has_value()) { return std::make_unique<FidoCableDiscovery>( - request_state_.cable_data_.value_or( - std::vector<CableDiscoveryData>()), - request_state_.qr_generator_key_, - request_state_.cable_pairing_callback_); + cable_data_.value_or(std::vector<CableDiscoveryData>()), + qr_generator_key_, cable_pairing_callback_); } return nullptr; case FidoTransportProtocol::kNearFieldCommunication: @@ -85,14 +78,14 @@ void FidoDiscoveryFactory::set_cable_data( std::vector<CableDiscoveryData> cable_data, base::Optional<QRGeneratorKey> qr_generator_key) { - request_state_.cable_data_ = std::move(cable_data); - request_state_.qr_generator_key_ = std::move(qr_generator_key); + cable_data_ = std::move(cable_data); + qr_generator_key_ = std::move(qr_generator_key); } void FidoDiscoveryFactory::set_cable_pairing_callback( base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)> pairing_callback) { - request_state_.cable_pairing_callback_.emplace(std::move(pairing_callback)); + cable_pairing_callback_.emplace(std::move(pairing_callback)); } #if defined(OS_WIN) @@ -137,7 +130,4 @@ } #endif -FidoDiscoveryFactory::RequestState::RequestState() = default; -FidoDiscoveryFactory::RequestState::~RequestState() = default; - } // namespace device
diff --git a/device/fido/fido_discovery_factory.h b/device/fido/fido_discovery_factory.h index e8265df..7a22bd5 100644 --- a/device/fido/fido_discovery_factory.h +++ b/device/fido/fido_discovery_factory.h
@@ -34,18 +34,6 @@ FidoDiscoveryFactory(); virtual ~FidoDiscoveryFactory(); - // Resets all fields that are only meaningful for the duration of a single - // request to a safe default. - // - // The "regular" FidoDiscoveryFactory is owned by the - // AuthenticatorClientRequestDelegate and lives only for a single request. - // Instances returned from - // AuthenticatorEnvironmentImpl::GetDiscoveryFactoryOverride(), which are - // used in unit tests or by the WebDriver virtual authenticators, are - // long-lived and may handle multiple WebAuthn requests. Hence, they will be - // reset at the beginning of each new request. - void ResetRequestState(); - // Instantiates a FidoDiscoveryBase for the given transport. // // FidoTransportProtocol::kUsbHumanInterfaceDevice is not valid on Android. @@ -83,26 +71,18 @@ #endif // defined(OS_WIN) private: - // RequestState holds configuration data that is only meaningful for a - // single WebAuthn request. - struct RequestState { - RequestState(); - ~RequestState(); - base::Optional<std::vector<CableDiscoveryData>> cable_data_; - base::Optional<QRGeneratorKey> qr_generator_key_; - base::Optional< - base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>> - cable_pairing_callback_; - }; - #if defined(OS_MACOSX) || defined(OS_CHROMEOS) std::unique_ptr<FidoDiscoveryBase> MaybeCreatePlatformDiscovery() const; #endif - RequestState request_state_; #if defined(OS_MACOSX) base::Optional<fido::mac::AuthenticatorConfig> mac_touch_id_config_; #endif // defined(OS_MACOSX) + base::Optional<std::vector<CableDiscoveryData>> cable_data_; + base::Optional<QRGeneratorKey> qr_generator_key_; + base::Optional< + base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>> + cable_pairing_callback_; #if defined(OS_WIN) WinWebAuthnApi* win_webauthn_api_ = nullptr; #endif // defined(OS_WIN)
diff --git a/docs/testing/web_tests.md b/docs/testing/web_tests.md index 5e4d188..7f86b3f 100644 --- a/docs/testing/web_tests.md +++ b/docs/testing/web_tests.md
@@ -473,18 +473,12 @@ ### Debugging DevTools Tests -* Add `debug_devtools=true` to `args.gn` and compile: `autoninja -C out/Default devtools_frontend_resources` - > Debug DevTools lets you avoid having to recompile after every change to the DevTools front-end. * Do one of the following: * Option A) Run from the `chromium/src` folder: - `third_party/blink/tools/run_web_tests.sh - --additional-driver-flag='--debug-devtools' - --additional-driver-flag='--remote-debugging-port=9222' - --time-out-ms=6000000` + `third_party/blink/tools/run_web_tests.py --additional-driver-flag='--remote-debugging-port=9222' --additional-driver-flag='--debug-devtools' --time-out-ms=6000000` * Option B) If you need to debug an http/tests/inspector test, start httpd as described above. Then, run content_shell: - `out/Default/content_shell --debug-devtools --remote-debugging-port=9222 --run-web-tests - http://127.0.0.1:8000/path/to/test.html` + `out/Default/content_shell --remote-debugging-port=9222 --additional-driver-flag='--debug-devtools' --run-web-tests http://127.0.0.1:8000/path/to/test.html` * Open `http://localhost:9222` in a stable/beta/canary Chrome, click the single link to open the devtools with the test loaded. * In the loaded devtools, set any required breakpoints and execute `test()` in
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index 86076a32..d86259f6 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -622,7 +622,6 @@ "api/declarative_webrequest/webrequest_condition_attribute_unittest.cc", "api/declarative_webrequest/webrequest_condition_unittest.cc", "api/document_scan/document_scan_api_unittest.cc", - "api/document_scan/document_scan_interface_chromeos_unittest.cc", "api/document_scan/fake_document_scan_interface.cc", "api/document_scan/fake_document_scan_interface.h", "api/file_handlers/app_file_handler_util_unittest.cc", @@ -748,6 +747,7 @@ if (is_chromeos) { sources += [ "api/audio/audio_device_id_calculator_unittest.cc", + "api/document_scan/document_scan_interface_chromeos_unittest.cc", "api/feedback_private/access_rate_limiter_chromeos_unittest.cc", "api/feedback_private/feedback_private_api_chromeos_unittest.cc", "api/feedback_private/feedback_private_api_unittest_base_chromeos.cc", @@ -765,6 +765,7 @@ deps += [ "//chromeos:test_support", + "//chromeos/dbus:lorgnette_proto", "//chromeos/dbus:test_support", "//chromeos/dbus/audio", "//chromeos/dbus/media_analytics",
diff --git a/extensions/browser/api/document_scan/BUILD.gn b/extensions/browser/api/document_scan/BUILD.gn index 7ac8b406..141506a 100644 --- a/extensions/browser/api/document_scan/BUILD.gn +++ b/extensions/browser/api/document_scan/BUILD.gn
@@ -13,15 +13,22 @@ "document_scan_api.h", "document_scan_interface.cc", "document_scan_interface.h", - "document_scan_interface_chromeos.cc", - "document_scan_interface_chromeos.h", ] - if (!is_chromeos) { + if (is_chromeos) { + sources += [ + "document_scan_interface_chromeos.cc", + "document_scan_interface_chromeos.h", + ] + } else { sources += [ "document_scan_interface_nonchromeos.cc" ] } deps = [ "//extensions/common/api" ] + if (is_chromeos) { + deps += [ "//chromeos/dbus:lorgnette_proto" ] + } + public_deps = [ "//extensions/browser:browser_sources" ] }
diff --git a/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc b/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc index 2517319..12702fc7 100644 --- a/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc +++ b/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc
@@ -42,25 +42,15 @@ void DocumentScanInterfaceChromeos::OnScannerListReceived( ListScannersResultsCallback callback, - base::Optional<chromeos::LorgnetteManagerClient::ScannerTable> scanners) { + base::Optional<lorgnette::ListScannersResponse> response) { std::vector<ScannerDescription> scanner_descriptions; - if (scanners.has_value()) { - for (const auto& scanner : scanners.value()) { + if (response) { + for (const auto& scanner : response->scanners()) { ScannerDescription description; - description.name = scanner.first; - const auto& entry = scanner.second; - auto info_it = entry.find(lorgnette::kScannerPropertyManufacturer); - if (info_it != entry.end()) { - description.manufacturer = info_it->second; - } - info_it = entry.find(lorgnette::kScannerPropertyModel); - if (info_it != entry.end()) { - description.model = info_it->second; - } - info_it = entry.find(lorgnette::kScannerPropertyType); - if (info_it != entry.end()) { - description.scanner_type = info_it->second; - } + description.name = scanner.name(); + description.manufacturer = scanner.manufacturer(); + description.model = scanner.model(); + description.scanner_type = scanner.type(); description.image_mime_type = kScannerImageMimeTypePng; scanner_descriptions.push_back(description); }
diff --git a/extensions/browser/api/document_scan/document_scan_interface_chromeos.h b/extensions/browser/api/document_scan/document_scan_interface_chromeos.h index b25eaa3..b598390a 100644 --- a/extensions/browser/api/document_scan/document_scan_interface_chromeos.h +++ b/extensions/browser/api/document_scan/document_scan_interface_chromeos.h
@@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/optional.h" -#include "chromeos/dbus/lorgnette_manager_client.h" +#include "chromeos/dbus/lorgnette/lorgnette_service.pb.h" #include "extensions/browser/api/document_scan/document_scan_interface.h" namespace extensions { @@ -30,7 +30,7 @@ private: void OnScannerListReceived( ListScannersResultsCallback callback, - base::Optional<chromeos::LorgnetteManagerClient::ScannerTable> scanners); + base::Optional<lorgnette::ListScannersResponse> response); void OnScanCompleted(ScanResultsCallback callback, base::Optional<std::string> image_data);
diff --git a/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc b/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc index 0d99d9a1..f969fb6 100644 --- a/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc +++ b/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc
@@ -46,11 +46,14 @@ constexpr const char* kScannerManufacturer = "Jacques-Louis David"; constexpr const char* kScannerModel = "Le Havre"; constexpr const char* kScannerType = "Impressionism"; - GetLorgnetteManagerClient()->AddScannerTableEntry( - kScannerName, - {{lorgnette::kScannerPropertyManufacturer, kScannerManufacturer}, - {lorgnette::kScannerPropertyModel, kScannerModel}, - {lorgnette::kScannerPropertyType, kScannerType}}); + lorgnette::ScannerInfo scanner; + scanner.set_name(kScannerName); + scanner.set_manufacturer(kScannerManufacturer); + scanner.set_model(kScannerModel); + scanner.set_type(kScannerType); + lorgnette::ListScannersResponse response; + *response.add_scanners() = std::move(scanner); + GetLorgnetteManagerClient()->SetListScannersResponse(response); base::RunLoop run_loop; scan_interface_.ListScanners(base::BindOnce(
diff --git a/fuchsia/engine/browser/frame_impl_browsertest.cc b/fuchsia/engine/browser/frame_impl_browsertest.cc index aad8519..5d19e37 100644 --- a/fuchsia/engine/browser/frame_impl_browsertest.cc +++ b/fuchsia/engine/browser/frame_impl_browsertest.cc
@@ -24,6 +24,7 @@ #include "fuchsia/base/test_navigation_listener.h" #include "fuchsia/base/url_request_rewrite_test_util.h" #include "fuchsia/engine/browser/frame_impl.h" +#include "fuchsia/engine/switches.h" #include "fuchsia/engine/test/test_data.h" #include "fuchsia/engine/test/web_engine_browser_test.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -1675,6 +1676,11 @@ embedded_test_server()->StartAndReturnHandle()); } + void SetUpCommandLine(base::CommandLine* command_line) override { + // Needed for UrlRequestRewriteAddHeaders. + command_line->AppendSwitchNative(switches::kCorsExemptHeaders, "Test"); + } + std::map<GURL, net::test_server::HttpRequest> accumulated_requests_; private:
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc index d5517a0..f3f59bf 100644 --- a/gpu/config/gpu_util.cc +++ b/gpu/config/gpu_util.cc
@@ -170,6 +170,15 @@ if (blacklisted_features.count(GPU_FEATURE_TYPE_GPU_RASTERIZATION)) return kGpuFeatureStatusBlacklisted; + // Enable gpu rasterization for vulkan, unless it is overridden by + // commandline. + if (base::FeatureList::IsEnabled(features::kVulkan) && + !base::FeatureList::GetInstance()->IsFeatureOverriddenFromCommandLine( + features::kDefaultEnableGpuRasterization.name, + base::FeatureList::OVERRIDE_DISABLE_FEATURE)) { + return kGpuFeatureStatusEnabled; + } + // Gpu Rasterization on platforms that are not fully enabled is controlled by // a finch experiment. if (!base::FeatureList::IsEnabled(features::kDefaultEnableGpuRasterization)) @@ -207,11 +216,14 @@ else if (gpu_preferences.enable_oop_rasterization) return kGpuFeatureStatusEnabled; - // TODO(enne): Eventually oop rasterization will replace gpu rasterization, - // and so we will need to address the underlying bugs or turn of GPU - // rasterization for these cases. - if (blacklisted_features.count(GPU_FEATURE_TYPE_OOP_RASTERIZATION)) - return kGpuFeatureStatusBlacklisted; + // Enable OOP rasterization for vulkan, unless it is overridden by + // commandline. + if (base::FeatureList::IsEnabled(features::kVulkan) && + !base::FeatureList::GetInstance()->IsFeatureOverriddenFromCommandLine( + features::kDefaultEnableOopRasterization.name, + base::FeatureList::OVERRIDE_DISABLE_FEATURE)) { + return kGpuFeatureStatusEnabled; + } // OOP Rasterization on platforms that are not fully enabled is controlled by // a finch experiment.
diff --git a/headless/lib/headless_origin_trials_browsertest.cc b/headless/lib/headless_origin_trials_browsertest.cc index 50ea4f3..1a6c83d 100644 --- a/headless/lib/headless_origin_trials_browsertest.cc +++ b/headless/lib/headless_origin_trials_browsertest.cc
@@ -4,6 +4,7 @@ #include "base/strings/strcat.h" #include "base/test/bind_test_util.h" +#include "build/build_config.h" #include "content/public/test/browser_test.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/url_loader_interceptor.h" @@ -53,7 +54,14 @@ DISALLOW_COPY_AND_ASSIGN(HeadlessOriginTrialsBrowserTest); }; -IN_PROC_BROWSER_TEST_F(HeadlessOriginTrialsBrowserTest, TrialsCanBeEnabled) { +// Flaky on Windows Debug https://crbug.com/1090801 +#if defined(OS_WIN) && !defined(NDEBUG) +#define MAYBE_TrialsCanBeEnabled DISABLED_TrialsCanBeEnabled +#else +#define MAYBE_TrialsCanBeEnabled TrialsCanBeEnabled +#endif +IN_PROC_BROWSER_TEST_F(HeadlessOriginTrialsBrowserTest, + MAYBE_TrialsCanBeEnabled) { HeadlessBrowserContext* browser_context = browser()->CreateBrowserContextBuilder().Build(); @@ -76,8 +84,14 @@ ->GetBool()); } +// Flaky on Windows Debug https://crbug.com/1090801 +#if defined(OS_WIN) && !defined(NDEBUG) +#define MAYBE_TrialsDisabledByDefault DISABLED_TrialsDisabledByDefault +#else +#define MAYBE_TrialsDisabledByDefault TrialsDisabledByDefault +#endif IN_PROC_BROWSER_TEST_F(HeadlessOriginTrialsBrowserTest, - TrialsDisabledByDefault) { + MAYBE_TrialsDisabledByDefault) { HeadlessBrowserContext* browser_context = browser()->CreateBrowserContextBuilder().Build(); @@ -99,8 +113,15 @@ ->GetBool()); } +// Flaky on Windows Debug https://crbug.com/1090801 +#if defined(OS_WIN) && !defined(NDEBUG) +#define MAYBE_WebComponentsV0CustomElements \ + DISABLED_WebComponentsV0CustomElements +#else +#define MAYBE_WebComponentsV0CustomElements WebComponentsV0CustomElements +#endif IN_PROC_BROWSER_TEST_F(HeadlessOriginTrialsBrowserTest, - WebComponentsV0CustomElements) { + MAYBE_WebComponentsV0CustomElements) { HeadlessBrowserContext* browser_context = browser()->CreateBrowserContextBuilder().Build();
diff --git a/headless/lib/headless_web_contents_browsertest.cc b/headless/lib/headless_web_contents_browsertest.cc index 998c190..2849a48 100644 --- a/headless/lib/headless_web_contents_browsertest.cc +++ b/headless/lib/headless_web_contents_browsertest.cc
@@ -286,8 +286,14 @@ } }; +// Flaky on Windows Debug https://crbug.com/1090801 +#if defined(OS_WIN) && !defined(NDEBUG) +DISABLED_HEADLESS_ASYNC_DEVTOOLED_TEST_P( + HeadlessWebContentsScreenshotWindowPositionTest); +#else HEADLESS_ASYNC_DEVTOOLED_TEST_P( HeadlessWebContentsScreenshotWindowPositionTest); +#endif // Instantiate test case for both software and gpu compositing modes. #if defined(OS_WIN) || (defined(OS_MACOSX) && defined(ADDRESS_SANITIZER)) @@ -644,7 +650,12 @@ } }; +// Flaky on Windows Debug https://crbug.com/1090801 +#if defined(OS_WIN) && !defined(NDEBUG) +DISABLED_HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsTaggedPDFTest); +#else HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsTaggedPDFTest); +#endif #endif // BUILDFLAG(ENABLE_PRINTING)
diff --git a/headless/test/data/protocol/sanity/browser-set-initial-proxy-config-expected.txt b/headless/test/data/protocol/sanity/browser-set-initial-proxy-config-expected.txt new file mode 100644 index 0000000..3c4cb45 --- /dev/null +++ b/headless/test/data/protocol/sanity/browser-set-initial-proxy-config-expected.txt
@@ -0,0 +1,5 @@ +Tests that headless session can configure proxy. + +No proxy page title: Page with title +Bogus proxy page title: +Good proxy page title: Page with title \ No newline at end of file
diff --git a/headless/test/data/protocol/sanity/browser-set-initial-proxy-config.js b/headless/test/data/protocol/sanity/browser-set-initial-proxy-config.js new file mode 100644 index 0000000..b1abb8b6 --- /dev/null +++ b/headless/test/data/protocol/sanity/browser-set-initial-proxy-config.js
@@ -0,0 +1,41 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function(testRunner) { + testRunner.log('Tests that headless session can configure proxy.\n'); + const { result: { sessionId } } = + await testRunner.browserP().Target.attachToBrowserTarget({}); + const { protocol: bProtocol } = new TestRunner.Session(testRunner, sessionId); + + async function dumpWithProxyServer(proxyServer) { + const { result: { browserContextId } } = + await bProtocol.Target.createBrowserContext({ proxyServer }); + const { result: { targetId }} = + await bProtocol.Target.createTarget({ + browserContextId: browserContextId, + url: 'about:blank' + }); + + const { result: { sessionId } } = + await bProtocol.Target.attachToTarget({ targetId, flatten: true }); + const { protocol: pProtocol } = + new TestRunner.Session(testRunner, sessionId); + await pProtocol.Page.enable({}); + await pProtocol.Page.navigate({ + url: testRunner._testBaseURL + 'resources/title.html' + }); + await pProtocol.Page.onceLoadEventFired(); + const { result: { result: { value } } } = + await pProtocol.Runtime.evaluate({ expression: 'document.title' }); + return value; + } + + testRunner.log(`No proxy page title: ${await dumpWithProxyServer()}`); + testRunner.log(`Bogus proxy page title: ${await dumpWithProxyServer( + 'bogus')}`); + testRunner.log(`Good proxy page title: ${await dumpWithProxyServer( + new URL(testRunner._targetBaseURL).host)}`); + + testRunner.completeTest(); +})
diff --git a/headless/test/data/protocol/sanity/resources/title.html b/headless/test/data/protocol/sanity/resources/title.html new file mode 100644 index 0000000..08d4355 --- /dev/null +++ b/headless/test/data/protocol/sanity/resources/title.html
@@ -0,0 +1,3 @@ +<html> + <title>Page with title</title> +</html> \ No newline at end of file
diff --git a/headless/test/headless_protocol_browsertest.cc b/headless/test/headless_protocol_browsertest.cc index 9218eb78..18eeac2 100644 --- a/headless/test/headless_protocol_browsertest.cc +++ b/headless/test/headless_protocol_browsertest.cc
@@ -438,5 +438,7 @@ HEADLESS_PROTOCOL_COMPOSITOR_TEST(RendererOpacityAnimation, "sanity/renderer-opacity-animation.js") +HEADLESS_PROTOCOL_COMPOSITOR_TEST(BrowserSetInitialProxyConfig, + "sanity/browser-set-initial-proxy-config.js") } // namespace headless
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg index a79cb8e..dc3fe08 100644 --- a/infra/config/generated/commit-queue.cfg +++ b/infra/config/generated/commit-queue.cfg
@@ -730,7 +730,7 @@ > builders: < name: "chromium/try/ios-simulator-code-coverage" - experiment_percentage: 3 + includable_only: true > builders: < name: "chromium/try/ios-simulator-cr-recipe"
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md index d3ac896..0c728fb2 100644 --- a/infra/config/generated/cq-builders.md +++ b/infra/config/generated/cq-builders.md
@@ -339,9 +339,6 @@ * [fuchsia-compile-x64-dbg](https://ci.chromium.org/p/chromium/builders/try/fuchsia-compile-x64-dbg) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+fuchsia-compile-x64-dbg)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+fuchsia-compile-x64-dbg)) * Experiment percentage: 50 -* [ios-simulator-code-coverage](https://ci.chromium.org/p/chromium/builders/try/ios-simulator-code-coverage) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+ios-simulator-code-coverage)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+ios-simulator-code-coverage)) - * Experiment percentage: 3 - * [linux-perfetto-rel](https://ci.chromium.org/p/chromium/builders/try/linux-perfetto-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux-perfetto-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux-perfetto-rel)) * Experiment percentage: 100
diff --git a/infra/config/subprojects/chromium/master-only/try.star b/infra/config/subprojects/chromium/master-only/try.star index 01a78ad..7694bf37 100644 --- a/infra/config/subprojects/chromium/master-only/try.star +++ b/infra/config/subprojects/chromium/master-only/try.star
@@ -574,7 +574,6 @@ properties = { 'xcode_build_version': '11e146', }, - tryjob = try_.job(experiment_percentage = 3) ) try_.chromium_mac_ios_builder(
diff --git a/ios/build/bots/scripts/test_apps.py b/ios/build/bots/scripts/test_apps.py index c491d8310..6f25a063 100644 --- a/ios/build/bots/scripts/test_apps.py +++ b/ios/build/bots/scripts/test_apps.py
@@ -147,14 +147,15 @@ module = self.module_name + '_module' # If --run-with-custom-webkit is passed as a test arg, set up - # DYLD_FRAMEWORK_PATH to load the custom webkit modules. - dyld_framework_path = self.project_path + ':' + # DYLD_FRAMEWORK_PATH and DYLD_LIBRARY_PATH to load the custom webkit + # modules. + dyld_path = self.project_path if '--run-with-custom-webkit' in self.test_args: if self.host_app_path: webkit_path = os.path.join(self.host_app_path, 'WebKitFrameworks') else: webkit_path = os.path.join(self.test_app_path, 'WebKitFrameworks') - dyld_framework_path = dyld_framework_path + webkit_path + ':' + dyld_path = dyld_path + ':' + webkit_path module_data = { 'TestBundlePath': self.test_app_path, @@ -163,10 +164,10 @@ 'TestingEnvironmentVariables': { 'DYLD_LIBRARY_PATH': '%s:__PLATFORMS__/iPhoneSimulator.platform/Developer/Library' % - self.project_path, + dyld_path, 'DYLD_FRAMEWORK_PATH': '%s:__PLATFORMS__/iPhoneSimulator.platform/' - 'Developer/Library/Frameworks' % dyld_framework_path, + 'Developer/Library/Frameworks' % dyld_path, } }
diff --git a/ios/chrome/app/strings/resources/ios_strings_ar.xtb b/ios/chrome/app/strings/resources/ios_strings_ar.xtb index a81d172..bfa6bec 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ar.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ar.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">حسنًا</translation> <translation id="5871497086027727873">تم نقل عنصر واحد</translation> <translation id="5897956970858271241">الانتقال إلى الرابط المنسوخ</translation> +<translation id="5899314093904173337">يمكنك مشاركته مع المستخدمين القريبين من خلال السماح لهم بمسح رمز الاستجابة السريعة ضوئيًا باستخدام الكاميرا أو تطبيق ماسح رمز الاستجابة السريعة.</translation> <translation id="5911030830365207728">الترجمة من Google</translation> <translation id="5913600720976431809">خيارات ترجمة الصفحة</translation> <translation id="5938160824633642847">جهازك ممتلئ تقريبًا. يمكنك إخلاء بعض المساحة وإعادة المحاولة.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_az.xtb b/ios/chrome/app/strings/resources/ios_strings_az.xtb index 11ad200..94cf58b4 100644 --- a/ios/chrome/app/strings/resources/ios_strings_az.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_az.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">Ok, Anladım</translation> <translation id="5871497086027727873">1 element köçürüldü</translation> <translation id="5897956970858271241">Kopyalanmış Linkə Daxil Olun</translation> +<translation id="5899314093904173337">Yaxınlıqdakı insanlarla paylaşmaq üçün onlara bu QR kodu öz kameraları və ya QR skaner tətbiqi ilə skanlamaq icazəsi verin</translation> <translation id="5911030830365207728">Google Tərcümə</translation> <translation id="5913600720976431809">Səhifəni tərcümə etmək seçimləri</translation> <translation id="5938160824633642847">Cihaz doludur. Yer boşaldın və yenidən cəhd edin.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_et.xtb b/ios/chrome/app/strings/resources/ios_strings_et.xtb index 8492cbd9..143b1e0 100644 --- a/ios/chrome/app/strings/resources/ios_strings_et.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_et.xtb
@@ -376,7 +376,7 @@ <translation id="5869029295770560994">Selge, sain aru</translation> <translation id="5871497086027727873">1 üksus on teisaldatud</translation> <translation id="5897956970858271241">Ava kopeeritud link</translation> -<translation id="5899314093904173337">Läheduses asuvate inimestega jagamiseks paluge neil kaamera või QR-skanneriga skannida see QR-kood</translation> +<translation id="5899314093904173337">Läheduses asuvate inimestega jagamiseks paluge neil kaamera või QR-skannerirakendusega skannida see QR-kood</translation> <translation id="5911030830365207728">Google'i tõlge</translation> <translation id="5913600720976431809">Lehe tõlkimise võimalused</translation> <translation id="5938160824633642847">Seade on peaaegu täis. Vabastage ruumi ja proovige uuesti.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_hi.xtb b/ios/chrome/app/strings/resources/ios_strings_hi.xtb index 877e866..5fb8eedf 100644 --- a/ios/chrome/app/strings/resources/ios_strings_hi.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_hi.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">ठीक है, समझ लिया</translation> <translation id="5871497086027727873">1 आइटम ले जाया गया</translation> <translation id="5897956970858271241">कॉपी किए गए लिंक पर जाएं</translation> +<translation id="5899314093904173337">आस-पास के लोगों के साथ शेयर करने के लिए, उन्हें कैमरे या क्यूआर स्कैन करने वाले ऐप्लिकेशन से इस क्यूआर कोड को स्कैन करने दें</translation> <translation id="5911030830365207728">Google Translate</translation> <translation id="5913600720976431809">पेज का अनुवाद करने के विकल्प</translation> <translation id="5938160824633642847">आपके डिवाइस की करीब पूरी जगह भर गई है. जगह खाली करके दोबारा आज़माएं.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_iw.xtb b/ios/chrome/app/strings/resources/ios_strings_iw.xtb index ab2fa6c..cd61783 100644 --- a/ios/chrome/app/strings/resources/ios_strings_iw.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_iw.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">בסדר, הבנתי</translation> <translation id="5871497086027727873">פריט אחד הועבר</translation> <translation id="5897956970858271241">מעבר לקישור שהועתק</translation> +<translation id="5899314093904173337">כדי לשתף עם אנשים שנמצאים בסביבה הקרובה, הם יכולים לסרוק את קוד ה-QR הזה באמצעות המצלמה שלהם או באמצעות אפליקציית סורק QR.</translation> <translation id="5911030830365207728">Google Translate</translation> <translation id="5913600720976431809">אפשרויות לתרגום הדף</translation> <translation id="5938160824633642847">המכשיר שלך כמעט מלא. צריך לפנות מקום ולנסות שוב.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_kk.xtb b/ios/chrome/app/strings/resources/ios_strings_kk.xtb index 5da64c3..26d1512 100644 --- a/ios/chrome/app/strings/resources/ios_strings_kk.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_kk.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">Жарайды, түсінікті</translation> <translation id="5871497086027727873">1 элемент көшірілді</translation> <translation id="5897956970858271241">Көшірілген сілтеме бойынша өту</translation> +<translation id="5899314093904173337">Жаныңыздағы адамдармен бөлісу үшін олар осы QR кодын камера немесе QR сканерлеу қолданбасы арқылы сканерлеуі қажет.</translation> <translation id="5911030830365207728">Google Translate</translation> <translation id="5913600720976431809">Бетті аудару опциялары</translation> <translation id="5938160824633642847">Құрылғыңыздың жады толуға жақын. Оны босатып, әрекетті қайталаңыз.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ky.xtb b/ios/chrome/app/strings/resources/ios_strings_ky.xtb index e862dd3..e3b7e26 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ky.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ky.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">Жарайт, түшүндүм</translation> <translation id="5871497086027727873">1 нерсе жылдырылды</translation> <translation id="5897956970858271241">Көчүрүлгөн шилтеме менен өтүңүз</translation> +<translation id="5899314093904173337">Жакын жердеги адамдар менен бөлүшүү үчүн, алар камера же болбосо QR кодун скандаган колдонмо менен бул QR кодду скандашы керек</translation> <translation id="5911030830365207728">Google Котормо</translation> <translation id="5913600720976431809">Бул баракты которуу параметрлери</translation> <translation id="5938160824633642847">Түзмөгүңүздө орун аз калды. Орун бошотуп, кайталап көрүңүз.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_lo.xtb b/ios/chrome/app/strings/resources/ios_strings_lo.xtb index e5b69bf..9066f4b1 100644 --- a/ios/chrome/app/strings/resources/ios_strings_lo.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_lo.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">ຕົກລົງ, ເຂົ້າໃຈແລ້ວ</translation> <translation id="5871497086027727873">1 ລາຍການຖືກຍ້າຍໄປແລ້ວ</translation> <translation id="5897956970858271241">ເຂົ້າເບິ່ງລິ້ງທີ່ສຳເນົາ</translation> +<translation id="5899314093904173337">ອະນຸຍາດໃຫ້ເຂົາເຈົ້າສະແກນລະຫັດ QR ນີ້ດ້ວຍແອັບກ້ອງຖ່າຍຮູບ ຫຼື ເຄື່ອງສະແກນ QR ຂອງເຂົາເຈົ້າເພື່ອແບ່ງປັນກັບຄົນທີ່ຢູ່ໃກ້ຄຽງ</translation> <translation id="5911030830365207728">Google ແປພາສາ</translation> <translation id="5913600720976431809">ຕົວເລືອກໃນການແປໜ້າ</translation> <translation id="5938160824633642847">ອຸປະກອນຂອງທ່ານເກືອບເຕັມແລ້ວ. ກະລຸນາຂະຫຍາຍພື້ນທີ່ຫວ່າງ ແລະ ລອງອີກຄັ້ງ.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_mk.xtb b/ios/chrome/app/strings/resources/ios_strings_mk.xtb index 7d4e2cc..6bd0838 100644 --- a/ios/chrome/app/strings/resources/ios_strings_mk.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_mk.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">Добро, сфатив</translation> <translation id="5871497086027727873">1 ставка е преместена</translation> <translation id="5897956970858271241">Посетете го копираниот линк</translation> +<translation id="5899314093904173337">За споделување со луѓето во близина, дозволете им да го скенираат овој QR код со нивната камера или апликацијата QR скенер</translation> <translation id="5911030830365207728">Google Translate</translation> <translation id="5913600720976431809">Опции за „Преведи ја страницата“</translation> <translation id="5938160824633642847">Уредот е речиси полн. Ослободете простор и обидете се повторно.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_mn.xtb b/ios/chrome/app/strings/resources/ios_strings_mn.xtb index ab2ed09f..01f8d6d 100644 --- a/ios/chrome/app/strings/resources/ios_strings_mn.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_mn.xtb
@@ -375,7 +375,7 @@ <translation id="5869029295770560994">OK, ойлголоо.</translation> <translation id="5871497086027727873">1 зүйлийг зөөсөн байна</translation> <translation id="5897956970858271241">Хуулсан холбоосонд зочлох</translation> -<translation id="5899314093904173337">Ойролцоо байгаа хүмүүстэй хуваалцахын тулд тэдэнд энэ хурдан хариу үйлдлийн кодыг камер эсвэл хурдан хариу үйлдлийн скан хийгч аппаар нь скан хийхийг зөвшөөрнө үү</translation> +<translation id="5899314093904173337">Ойролцоо байгаа хүмүүстэй хуваалцахын тулд тэдэнд энэ хурдан хариу үйлдлийн кодыг камер эсвэл хурдан хариу үйлдлийн код скан хийдэг аппаар скан хийхийг зөвшөөрнө үү</translation> <translation id="5911030830365207728">Google Translate</translation> <translation id="5913600720976431809">Хуудсыг орчуулах сонголтууд</translation> <translation id="5938160824633642847">Таны төхөөрөмж бараг дүүрсэн байна. Зай гаргаад дахин оролдоно уу.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ta.xtb b/ios/chrome/app/strings/resources/ios_strings_ta.xtb index 33904f8..8f8e710b 100644 --- a/ios/chrome/app/strings/resources/ios_strings_ta.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_ta.xtb
@@ -376,7 +376,8 @@ <translation id="5869029295770560994">சரி, புரிந்தது</translation> <translation id="5871497086027727873">1 உருப்படி நகர்த்தப்பட்டது</translation> <translation id="5897956970858271241">நகலெடுத்த இணைப்பிற்குச் செல்</translation> -<translation id="5911030830365207728">Google மொழியாக்கம்</translation> +<translation id="5899314093904173337">அருகிலுள்ளவர்களுடன் பகிர கேமரா மூலமோ QR ஸ்கேன்னர் ஆப்ஸ் மூலமோ அவர்களை இந்த QR குறியீட்டை ஸ்கேன் செய்யச் சொல்லுங்கள்</translation> +<translation id="5911030830365207728">Google Translate</translation> <translation id="5913600720976431809">பக்கத்தை மொழிபெயர்ப்பதற்கான விருப்பத்தேர்வுகள்</translation> <translation id="5938160824633642847">உங்கள் சாதனச் சேமிப்பகம் கிட்டத்தட்ட நிரம்பிவிட்டது. இடத்தைக் காலியாக்கி, மீண்டும் முயலவும்.</translation> <translation id="5948291296578561264">உங்கள் பட நூலகத்தில் படங்களைச் சேமிக்க இது அனுமதிக்கும்.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_te.xtb b/ios/chrome/app/strings/resources/ios_strings_te.xtb index 0951394..c566a5ab 100644 --- a/ios/chrome/app/strings/resources/ios_strings_te.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_te.xtb
@@ -376,6 +376,7 @@ <translation id="5869029295770560994">సరే, అర్థమైంది</translation> <translation id="5871497086027727873">1 అంశం తరలించబడింది</translation> <translation id="5897956970858271241">కాపీ చేసిన లింక్ను సందర్శించండి</translation> +<translation id="5899314093904173337">సమీపంలోని వ్యక్తులతో షేర్ చేయడానికి, వారి కెమెరా లేదా QR స్కానర్ యాప్తో ఈ QR కోడ్ను స్కాన్ చేయడానికి వారిని అనుమతించండి</translation> <translation id="5911030830365207728">Google Translate</translation> <translation id="5913600720976431809">పేజీ అనువాద ఎంపికలు</translation> <translation id="5938160824633642847">మీ పరికరం దాదాపు నిండింది. స్థలాన్ని ఖాళీ చేసిన తర్వాత మళ్లీ ప్రయత్నించండి.</translation>
diff --git a/ios/chrome/browser/ui/fullscreen/OWNERS b/ios/chrome/browser/ui/fullscreen/OWNERS index 79e1c49..9cf8c07297 100644 --- a/ios/chrome/browser/ui/fullscreen/OWNERS +++ b/ios/chrome/browser/ui/fullscreen/OWNERS
@@ -1,2 +1,2 @@ -kkhorimoto@chromium.org +thegreenfrog@chromium.org sczs@chromium.org
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.h b/ios/chrome/browser/ui/main/browser_view_wrangler.h index 1c9f8b4..73b6ab7 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler.h +++ b/ios/chrome/browser/ui/main/browser_view_wrangler.h
@@ -52,8 +52,13 @@ // immediately after initialization. - (void)createMainBrowser; -// Destroy and rebuild the incognito Browser. -- (void)destroyAndRebuildIncognitoBrowser; +// Invoked before the incognito BrowserState is destroyed. Needs to clean up +// all the state that is tied to the BrowserState. +- (void)willDestroyIncognitoBrowserState; + +// Invoked after the incognito BrowserState has been created. Needs to create +// all the state that is tied to the BrowserState. +- (void)incognitoBrowserStateCreated; // Called before the instance is deallocated. - (void)shutdown;
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm index 1db6e05..33daf41 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -277,7 +277,7 @@ #pragma mark - Other public methods -- (void)destroyAndRebuildIncognitoBrowser { +- (void)willDestroyIncognitoBrowserState { // It is theoretically possible that a Tab has been added to |_otrTabModel| // since the deletion has been scheduled. It is unlikely to happen for real // because it would require superhuman speed. @@ -311,8 +311,11 @@ _currentInterface = nil; } } +} - _browserState->DestroyOffTheRecordChromeBrowserState(); +- (void)incognitoBrowserStateCreated { + DCHECK(_browserState); + DCHECK(_browserState->HasOffTheRecordChromeBrowserState()); // An empty _otrTabModel must be created at this point, because it is then // possible to prevent the tabChanged notification being sent. Otherwise, @@ -320,9 +323,8 @@ // be immediately deleted. [self setOtrBrowser:[self buildOtrBrowser:NO]]; DCHECK(![self.otrBrowser->GetTabModel() count]); - DCHECK(_browserState->HasOffTheRecordChromeBrowserState()); - if (otrBVCIsCurrent) { + if (_currentInterface == nil) { self.currentInterface = self.incognitoInterface; } }
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm index 20474ad..945cdb6 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
@@ -87,8 +87,13 @@ EXPECT_EQ(1UL, browser_list->AllIncognitoBrowsers().size()); Browser* prior_otr_browser = observer.GetLastAddedIncognitoBrowser(); + // WARNING: after the following call, |last_otr_browser| is unsafe. - [wrangler destroyAndRebuildIncognitoBrowser]; + [wrangler willDestroyIncognitoBrowserState]; + chrome_browser_state_->DestroyOffTheRecordChromeBrowserState(); + chrome_browser_state_->GetOffTheRecordChromeBrowserState(); + [wrangler incognitoBrowserStateCreated]; + // Expect that the prior OTR browser was removed, and a new one was added. EXPECT_EQ(prior_otr_browser, observer.GetLastRemovedIncognitoBrowser()); EXPECT_EQ(wrangler.incognitoInterface.browser,
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index bd25803..577abc30 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -38,6 +38,8 @@ #import "ios/chrome/browser/first_run/first_run.h" #include "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/main/browser.h" +#import "ios/chrome/browser/main/browser_list.h" +#import "ios/chrome/browser/main/browser_list_factory.h" #include "ios/chrome/browser/ntp/features.h" #import "ios/chrome/browser/ntp_snippets/content_suggestions_scheduler_notifications.h" #include "ios/chrome/browser/signin/identity_manager_factory.h" @@ -1785,20 +1787,17 @@ // Called when the last incognito tab was closed. - (void)lastIncognitoTabClosed { - // This seems the best place to mark the start of destroying the incognito - // browser state. - crash_keys::SetDestroyingAndRebuildingIncognitoBrowserState( - /*in_progress=*/true); - DCHECK(self.mainController.mainBrowserState - ->HasOffTheRecordChromeBrowserState()); - [self clearIOSSpecificIncognitoData]; - - // Incognito browser state cannot be deleted before all the requests are - // deleted. Queue browser state recreation on IO thread. - base::PostTaskAndReply(FROM_HERE, {web::WebThread::IO}, base::DoNothing(), - base::BindRepeating(^{ - [self destroyAndRebuildIncognitoBrowserState]; - })); + // If no other window has incognito tab, then destroy and rebuild the + // BrowserState. Otherwise, just do the state transition animation. + if ([self shouldDestroyAndRebuildIncognitoBrowserState]) { + // Incognito browser state cannot be deleted before all the requests are + // deleted. Queue empty task on IO thread and destroy the BrowserState + // when the task has executed. + base::PostTaskAndReply(FROM_HERE, {web::WebThread::IO}, base::DoNothing(), + base::BindRepeating(^{ + [self destroyAndRebuildIncognitoBrowserState]; + })); + } // a) The first condition can happen when the last incognito tab is closed // from the tab switcher. @@ -1879,51 +1878,6 @@ [self.mainCoordinator showTabSwitcher:self.tabSwitcher]; } -// Destroys and rebuilds the incognito browser state. -- (void)destroyAndRebuildIncognitoBrowserState { - // Clear the Incognito Browser and notify the _tabSwitcher that its otrBrowser - // will be destroyed. - [self.tabSwitcher setOtrBrowser:nil]; - - if (base::FeatureList::IsEnabled(kLogBreadcrumbs)) { - BreadcrumbManagerBrowserAgent::FromBrowser(self.incognitoInterface.browser) - ->SetLoggingEnabled(false); - - breakpad::StopMonitoringBreadcrumbManagerService( - BreadcrumbManagerKeyedServiceFactory::GetForBrowserState( - self.incognitoInterface.browserState)); - } - - self.incognitoInterface.browser->GetWebStateList()->RemoveObserver( - _webStateListForwardingObserver.get()); - [self.browserViewWrangler destroyAndRebuildIncognitoBrowser]; - // There should be a new URL loading browser agent for the incognito browser, - // so set the scene URL loading service on it. - UrlLoadingBrowserAgent::FromBrowser(self.incognitoInterface.browser) - ->SetSceneService(self.sceneURLLoadingService); - self.incognitoInterface.browser->GetWebStateList()->AddObserver( - _webStateListForwardingObserver.get()); - - if (base::FeatureList::IsEnabled(kLogBreadcrumbs)) { - breakpad::MonitorBreadcrumbManagerService( - BreadcrumbManagerKeyedServiceFactory::GetForBrowserState( - self.incognitoInterface.browserState)); - } - - if (self.currentInterface.incognito) { - [self activateBVCAndMakeCurrentBVCPrimary]; - } - - // Always set the new otr Browser for the tablet or grid switcher. - // Notify the _tabSwitcher with the new Incognito Browser. - [self.tabSwitcher setOtrBrowser:self.incognitoInterface.browser]; - - // This seems the best place to deem the destroying and rebuilding the - // incognito browser state to be completed. - crash_keys::SetDestroyingAndRebuildingIncognitoBrowserState( - /*in_progress=*/false); -} - - (void)openURLContexts:(NSSet<UIOpenURLContext*>*)URLContexts API_AVAILABLE(ios(13)) { if (self.mainController.appState.isInSafeMode) { @@ -1953,4 +1907,116 @@ } } +#pragma mark - Handling of destroying the incognito BrowserState + +// The incognito BrowserState should be closed when the last incognito tab is +// closed (i.e. if there are other incognito tabs open in another Scene, the +// BrowserState must not be destroyed). +- (BOOL)shouldDestroyAndRebuildIncognitoBrowserState { + ChromeBrowserState* mainBrowserState = self.mainController.mainBrowserState; + if (!mainBrowserState->HasOffTheRecordChromeBrowserState()) + return NO; + + ChromeBrowserState* otrBrowserState = + mainBrowserState->GetOffTheRecordChromeBrowserState(); + DCHECK(otrBrowserState); + + BrowserList* browserList = + BrowserListFactory::GetForBrowserState(otrBrowserState); + for (Browser* browser : browserList->AllIncognitoBrowsers()) { + WebStateList* webStateList = browser->GetWebStateList(); + if (!webStateList->empty()) + return NO; + } + + return YES; +} + +// Destroys and rebuilds the incognito BrowserState. This will inform all the +// other SceneController to destroy state tied to the BrowserState and to +// recreate it. +- (void)destroyAndRebuildIncognitoBrowserState { + // This seems the best place to mark the start of destroying the incognito + // browser state. + crash_keys::SetDestroyingAndRebuildingIncognitoBrowserState( + /*in_progress=*/true); + + [self clearIOSSpecificIncognitoData]; + + ChromeBrowserState* mainBrowserState = self.mainController.mainBrowserState; + DCHECK(mainBrowserState->HasOffTheRecordChromeBrowserState()); + + NSMutableArray<SceneController*>* sceneControllers = + [[NSMutableArray alloc] init]; + for (SceneState* sceneState in self.mainController.appState.connectedScenes) { + SceneController* sceneController = sceneState.controller; + if (sceneController.mainController.mainBrowserState == mainBrowserState) { + [sceneControllers addObject:sceneController]; + } + } + + for (SceneController* sceneController in sceneControllers) { + [sceneController willDestroyIncognitoBrowserState]; + } + + if (base::FeatureList::IsEnabled(kLogBreadcrumbs)) { + breakpad::StopMonitoringBreadcrumbManagerService( + BreadcrumbManagerKeyedServiceFactory::GetForBrowserState( + mainBrowserState->GetOffTheRecordChromeBrowserState())); + } + + // Destroy and recreate the off-the-record BrowserState. + mainBrowserState->DestroyOffTheRecordChromeBrowserState(); + mainBrowserState->GetOffTheRecordChromeBrowserState(); + + for (SceneController* sceneController in sceneControllers) { + [sceneController incognitoBrowserStateCreated]; + } + + if (base::FeatureList::IsEnabled(kLogBreadcrumbs)) { + breakpad::MonitorBreadcrumbManagerService( + BreadcrumbManagerKeyedServiceFactory::GetForBrowserState( + mainBrowserState->GetOffTheRecordChromeBrowserState())); + } + + // This seems the best place to deem the destroying and rebuilding the + // incognito browser state to be completed. + crash_keys::SetDestroyingAndRebuildingIncognitoBrowserState( + /*in_progress=*/false); +} + +- (void)willDestroyIncognitoBrowserState { + // Clear the Incognito Browser and notify the _tabSwitcher that its otrBrowser + // will be destroyed. + [self.tabSwitcher setOtrBrowser:nil]; + + if (base::FeatureList::IsEnabled(kLogBreadcrumbs)) { + BreadcrumbManagerBrowserAgent::FromBrowser(self.incognitoInterface.browser) + ->SetLoggingEnabled(false); + } + + self.incognitoInterface.browser->GetWebStateList()->RemoveObserver( + _webStateListForwardingObserver.get()); + [self.browserViewWrangler willDestroyIncognitoBrowserState]; +} + +- (void)incognitoBrowserStateCreated { + [self.browserViewWrangler incognitoBrowserStateCreated]; + + // There should be a new URL loading browser agent for the incognito browser, + // so set the scene URL loading service on it. + UrlLoadingBrowserAgent::FromBrowser(self.incognitoInterface.browser) + ->SetSceneService(self.sceneURLLoadingService); + self.incognitoInterface.browser->GetWebStateList()->AddObserver( + _webStateListForwardingObserver.get()); + + if (self.currentInterface.incognito) { + [self activateBVCAndMakeCurrentBVCPrimary]; + } + + // Always set the new otr Browser for the tablet or grid switcher. + // Notify the _tabSwitcher with the new Incognito Browser. + [self.tabSwitcher setOtrBrowser:self.incognitoInterface.browser]; +} + @end
diff --git a/ios/chrome/browser/ui/main/scene_state.h b/ios/chrome/browser/ui/main/scene_state.h index 0fb889e5..22559885 100644 --- a/ios/chrome/browser/ui/main/scene_state.h +++ b/ios/chrome/browser/ui/main/scene_state.h
@@ -68,7 +68,7 @@ // Window for the associated scene, if any. @property(nonatomic, strong) UIWindow* window; -@property(nonatomic, strong) UIWindowScene* scene API_AVAILABLE(ios(13)); +@property(nonatomic, weak) UIWindowScene* scene API_AVAILABLE(ios(13)); @property(nonatomic, strong) UISceneConnectionOptions* connectionOptions API_AVAILABLE(ios(13));
diff --git a/ios/chrome/browser/ui/overlays/overlay_presentation_context_impl.h b/ios/chrome/browser/ui/overlays/overlay_presentation_context_impl.h index 9017775e..680ecc7 100644 --- a/ios/chrome/browser/ui/overlays/overlay_presentation_context_impl.h +++ b/ios/chrome/browser/ui/overlays/overlay_presentation_context_impl.h
@@ -183,13 +183,13 @@ // The context's delegate. __weak id<OverlayPresentationContextImplDelegate> delegate_ = nil; // The window in which overlay UI will be presented. - UIWindow* window_ = nil; + __weak UIWindow* window_ = nil; // The UIViewController used as the base for overlays UI displayed using child // UIViewControllers. - UIViewController* container_view_controller_ = nil; + __weak UIViewController* container_view_controller_ = nil; // The UIViewController used as the base for overlays displayed using // presented UIViewControllers. - UIViewController* presentation_context_view_controller_ = nil; + __weak UIViewController* presentation_context_view_controller_ = nil; // The presentation capabilities of |coordinator_|'s view controller. UIPresentationCapabilities presentation_capabilities_ = UIPresentationCapabilities::kNone;
diff --git a/ios/chrome/browser/url_loading/url_loading_browser_agent.mm b/ios/chrome/browser/url_loading/url_loading_browser_agent.mm index bb60d244..dcfcfcfc 100644 --- a/ios/chrome/browser/url_loading/url_loading_browser_agent.mm +++ b/ios/chrome/browser/url_loading/url_loading_browser_agent.mm
@@ -6,7 +6,7 @@ #include "base/compiler_specific.h" #include "base/strings/string_number_conversions.h" -#include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" #import "ios/chrome/browser/main/browser.h" @@ -35,7 +35,7 @@ void StartLeakingMemory() { int* leak = new int[10 * 1024 * 1024]; ALLOW_UNUSED_LOCAL(leak); - base::PostTask(FROM_HERE, base::BindOnce(&StartLeakingMemory)); + base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(&StartLeakingMemory)); } // Helper method for inducing intentional freezes, leaks and crashes, in a
diff --git a/ios/third_party/webkit/BUILD.gn b/ios/third_party/webkit/BUILD.gn index 118d045..f9b008c 100644 --- a/ios/third_party/webkit/BUILD.gn +++ b/ios/third_party/webkit/BUILD.gn
@@ -99,6 +99,7 @@ "$_webkit_ios_out_product_dir/WebKit.framework/WebKit", "$_webkit_ios_out_product_dir/WebKitLegacy.framework", "$_webkit_ios_out_product_dir/WebKitLegacy.framework/WebKitLegacy", + "$_webkit_ios_out_product_dir/WebKitTestRunnerApp.app/Frameworks/libclang_rt.asan_iossim_dynamic.dylib", "$_webkit_ios_out_product_dir/com.apple.WebKit.Networking.xpc", "$_webkit_ios_out_product_dir/com.apple.WebKit.Networking.xpc/com.apple.WebKit.Networking.Development", "$_webkit_ios_out_product_dir/com.apple.WebKit.Plugin.64.xpc", @@ -124,6 +125,7 @@ "$_webkit_ios_out_product_dir/WebCore.framework", "$_webkit_ios_out_product_dir/WebKit.framework", "$_webkit_ios_out_product_dir/WebKitLegacy.framework", + "$_webkit_ios_out_product_dir/WebKitTestRunnerApp.app/Frameworks/libclang_rt.asan_iossim_dynamic.dylib", "$_webkit_ios_out_product_dir/com.apple.WebKit.Networking.xpc", "$_webkit_ios_out_product_dir/com.apple.WebKit.Plugin.64.xpc", "$_webkit_ios_out_product_dir/com.apple.WebKit.WebContent.Development.xpc",
diff --git a/ios/third_party/webkit/build_webkit.py b/ios/third_party/webkit/build_webkit.py index 5a797297..0353a52 100755 --- a/ios/third_party/webkit/build_webkit.py +++ b/ios/third_party/webkit/build_webkit.py
@@ -67,7 +67,8 @@ return proc.returncode # Enable rewriting WK_API_AVAILABLE() -> API_AVAILABLE(). - command.append('WK_FRAMEWORK_HEADER_POSTPROCESSING_DISABLED=NO') + if opts.ios_simulator: + command.append('WK_FRAMEWORK_HEADER_POSTPROCESSING_DISABLED=NO') proc = subprocess.Popen(command, cwd=cwd, env=env) proc.communicate()
diff --git a/ios/web/web_state/policy_decision_state_tracker.h b/ios/web/web_state/policy_decision_state_tracker.h index d624dcf4..375eb29 100644 --- a/ios/web/web_state/policy_decision_state_tracker.h +++ b/ios/web/web_state/policy_decision_state_tracker.h
@@ -19,7 +19,9 @@ // also Allow. If at least one decision is PolicyDecision::Cancel, the final // result is Cancel. Otherwise, if at least one decision is // CancelAndDisplayError, the final result is also CancelAndDisplayError, with -// the error associated with the first such decision. +// the error associated with the first such decision. If this is destroyed +// before all decisions have been received and the callback has not yet been +// invoked, the callback is invoked with PolicyDecision::Cancel. class PolicyDecisionStateTracker : public base::SupportsWeakPtr<PolicyDecisionStateTracker> { public:
diff --git a/ios/web/web_state/policy_decision_state_tracker.mm b/ios/web/web_state/policy_decision_state_tracker.mm index 173d0f8..ed63bb5e 100644 --- a/ios/web/web_state/policy_decision_state_tracker.mm +++ b/ios/web/web_state/policy_decision_state_tracker.mm
@@ -16,7 +16,11 @@ base::OnceCallback<void(WebStatePolicyDecider::PolicyDecision)> callback) : callback_(std::move(callback)) {} -PolicyDecisionStateTracker::~PolicyDecisionStateTracker() = default; +PolicyDecisionStateTracker::~PolicyDecisionStateTracker() { + if (!callback_.is_null()) { + std::move(callback_).Run(WebStatePolicyDecider::PolicyDecision::Cancel()); + } +} void PolicyDecisionStateTracker::OnSinglePolicyDecisionReceived( WebStatePolicyDecider::PolicyDecision decision) {
diff --git a/ios/web/web_state/policy_decision_state_tracker_unittest.mm b/ios/web/web_state/policy_decision_state_tracker_unittest.mm index bc3df22..72f4030f 100644 --- a/ios/web/web_state/policy_decision_state_tracker_unittest.mm +++ b/ios/web/web_state/policy_decision_state_tracker_unittest.mm
@@ -282,4 +282,64 @@ EXPECT_EQ(policy_decision_->GetDisplayError().code, error1.code); } +// Test fixture that supports destroying its PolicyDecisionStateTracker, +// allowing destructor behavior to be tested. +class PolicyDecisionStateTrackerDestructionTest : public PlatformTest { + public: + PolicyDecisionStateTrackerDestructionTest() + : policy_decision_state_tracker_( + std::make_unique<PolicyDecisionStateTracker>( + base::BindOnce(&PolicyDecisionStateTrackerDestructionTest:: + OnDecisionDetermined, + base::Unretained(this)))) {} + + void OnDecisionDetermined( + WebStatePolicyDecider::PolicyDecision policy_decision) { + policy_decision_ = policy_decision; + } + + void DestroyPolicyDecisionStateTracker() { + policy_decision_state_tracker_.reset(); + } + + std::unique_ptr<PolicyDecisionStateTracker> policy_decision_state_tracker_; + base::Optional<WebStatePolicyDecider::PolicyDecision> policy_decision_; +}; + +// Tests the case where no decisions have been received by the time the +// PolicyDecisionStateTracker is destroyed. +TEST_F(PolicyDecisionStateTrackerDestructionTest, NoDecisionsReceived) { + int num_decisions_requested = 3; + policy_decision_state_tracker_->FinishedRequestingDecisions( + num_decisions_requested); + + DestroyPolicyDecisionStateTracker(); + + EXPECT_TRUE(policy_decision_); + EXPECT_TRUE(policy_decision_->ShouldCancelNavigation()); +} + +// Tests the case where some but not all decisions have been received by the +// time the PolicyDecisionStateTracker is destroyed. +TEST_F(PolicyDecisionStateTrackerDestructionTest, OnlySomeDecisionsReceived) { + int num_decisions_requested = 3; + policy_decision_state_tracker_->FinishedRequestingDecisions( + num_decisions_requested); + + policy_decision_state_tracker_->OnSinglePolicyDecisionReceived( + WebStatePolicyDecider::PolicyDecision::Allow()); + EXPECT_FALSE(policy_decision_state_tracker_->DeterminedFinalResult()); + EXPECT_FALSE(policy_decision_); + + policy_decision_state_tracker_->OnSinglePolicyDecisionReceived( + WebStatePolicyDecider::PolicyDecision::Allow()); + EXPECT_FALSE(policy_decision_state_tracker_->DeterminedFinalResult()); + EXPECT_FALSE(policy_decision_); + + DestroyPolicyDecisionStateTracker(); + + EXPECT_TRUE(policy_decision_); + EXPECT_TRUE(policy_decision_->ShouldCancelNavigation()); +} + } // namespace web
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc index 44c4535f..f9db127 100644 --- a/media/audio/audio_manager_unittest.cc +++ b/media/audio/audio_manager_unittest.cc
@@ -104,6 +104,10 @@ const int kDefaultSampleRate = 48000; +const uint64_t kInternalSpeakerId = 10001; +const uint64_t kInternalSpeakerStableDeviceId = 10001; +const uint64_t kInternalMicId = 10002; +const uint64_t kInternalMicStableDeviceId = 10002; const uint64_t kJabraSpeaker1Id = 30001; const uint64_t kJabraSpeaker1StableDeviceId = 80001; const uint64_t kJabraSpeaker2Id = 30002; @@ -117,6 +121,30 @@ const uint64_t kWebcamMicId = 40003; const uint64_t kWebcamMicStableDeviceId = 90003; +const AudioNode kInternalSpeaker(false, + kInternalSpeakerId, + true, + kInternalSpeakerStableDeviceId, + kInternalSpeakerStableDeviceId ^ 0xFF, + "Internal Speaker", + "INTERNAL_SPEAKER", + "Speaker", + false, + 0, + 2); + +const AudioNode kInternalMic(true, + kInternalMicId, + true, + kInternalMicStableDeviceId, + kInternalMicStableDeviceId ^ 0xFF, + "Internal Mic", + "INTERNAL_MIC", + "Internal Mic", + false, + 0, + 1); + const AudioNode kJabraSpeaker1(false, kJabraSpeaker1Id, true, @@ -396,6 +424,19 @@ LOG(WARNING) << "No input devices detected"; } } + + // Helper method for (USE_CRAS) which returns |group_id| from |device_id|. + std::string getGroupID(const AudioDeviceDescriptions& device_descriptions, + const std::string device_id) { + AudioDeviceDescriptions::const_iterator it = + std::find_if(device_descriptions.begin(), device_descriptions.end(), + [&device_id](const auto& audio_device_desc) { + return audio_device_desc.unique_id == device_id; + }); + + EXPECT_NE(it, device_descriptions.end()); + return it->group_id; + } #endif // defined(USE_CRAS) bool InputDevicesAvailable() { @@ -504,6 +545,7 @@ audio_nodes.push_back(kHDMIOutput); audio_nodes.push_back(kJabraSpeaker1); audio_nodes.push_back(kJabraSpeaker2); + SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable()); @@ -572,6 +614,95 @@ ChannelLayout::CHANNEL_LAYOUT_STEREO, 2048); EXPECT_TRUE(params.Equals(golden_params)); } + +TEST_F(AudioManagerTest, LookupDefaultInputDeviceWithProperGroupId) { + // Setup devices with external microphone as active device. + // Switch active device to the internal microphone. + // Check if default device has the same group id as internal microphone. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalMic); + audio_nodes.push_back(kJabraMic1); + SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); + + ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable()); + + // Setup expectation with physical devices. + std::map<uint64_t, std::string> expectation; + expectation[kInternalMic.id] = + cras_audio_handler_->GetDeviceFromId(kInternalMic.id)->display_name; + expectation[kJabraMic1.id] = + cras_audio_handler_->GetDeviceFromId(kJabraMic1.id)->display_name; + + CreateAudioManagerForTesting<AudioManagerCras>(); + auto previous_default_device_id = + device_info_accessor_->GetDefaultInputDeviceID(); + EXPECT_EQ(base::NumberToString(kJabraMic1.id), previous_default_device_id); + AudioDeviceDescriptions device_descriptions; + device_info_accessor_->GetAudioInputDeviceDescriptions(&device_descriptions); + + CheckDeviceDescriptions(device_descriptions); + + // Set internal microphone as active. + chromeos::AudioDevice internal_microphone(kInternalMic); + cras_audio_handler_->SwitchToDevice( + internal_microphone, true, chromeos::CrasAudioHandler::ACTIVATE_BY_USER); + auto new_default_device_id = device_info_accessor_->GetDefaultInputDeviceID(); + EXPECT_NE(previous_default_device_id, new_default_device_id); + + auto default_device_group_id = + getGroupID(device_descriptions, new_default_device_id); + auto mic_group_id = + getGroupID(device_descriptions, base::NumberToString(kInternalMic.id)); + + EXPECT_EQ(default_device_group_id, mic_group_id); + EXPECT_EQ(base::NumberToString(kInternalMic.id), new_default_device_id); +} + +TEST_F(AudioManagerTest, LookupDefaultOutputDeviceWithProperGroupId) { + // Setup devices with external speaker as active device. + // Switch active device to the internal speaker. + // Check if default device has the same group id as internal speaker. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kJabraSpeaker1); + + SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); + + ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable()); + + // Setup expectation with physical devices. + std::map<uint64_t, std::string> expectation; + expectation[kInternalSpeaker.id] = + cras_audio_handler_->GetDeviceFromId(kInternalSpeaker.id)->display_name; + expectation[kJabraSpeaker1.id] = + cras_audio_handler_->GetDeviceFromId(kJabraSpeaker1.id)->display_name; + + CreateAudioManagerForTesting<AudioManagerCras>(); + auto previous_default_device_id = + device_info_accessor_->GetDefaultOutputDeviceID(); + EXPECT_EQ(base::NumberToString(kJabraSpeaker1.id), + previous_default_device_id); + AudioDeviceDescriptions device_descriptions; + device_info_accessor_->GetAudioOutputDeviceDescriptions(&device_descriptions); + + CheckDeviceDescriptions(device_descriptions); + + // Set internal speaker as active. + chromeos::AudioDevice internal_speaker(kInternalSpeaker); + cras_audio_handler_->SwitchToDevice( + internal_speaker, true, chromeos::CrasAudioHandler::ACTIVATE_BY_USER); + auto new_default_device_id = + device_info_accessor_->GetDefaultOutputDeviceID(); + EXPECT_NE(previous_default_device_id, new_default_device_id); + + auto default_device_group_id = + getGroupID(device_descriptions, new_default_device_id); + auto speaker_group_id = getGroupID(device_descriptions, + base::NumberToString(kInternalSpeaker.id)); + + EXPECT_EQ(default_device_group_id, speaker_group_id); + EXPECT_EQ(base::NumberToString(kInternalSpeaker.id), new_default_device_id); +} #else // !defined(USE_CRAS) TEST_F(AudioManagerTest, HandleDefaultDeviceIDs) {
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc index c04a2c8..4f840cf8b 100644 --- a/media/formats/mp4/mp4_stream_parser_unittest.cc +++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -410,11 +410,16 @@ audio_object_types.insert(kISO_14496_3); parser_.reset(new MP4StreamParser(audio_object_types, false, false)); auto params = GetDefaultInitParametersExpectations(); - params.duration = base::TimeDelta::FromMicroseconds(1024000); - params.liveness = DemuxerStream::LIVENESS_RECORDED; params.detected_video_track_count = 0; InitializeParserWithInitParametersExpectations(params); + + // This test file contains a single audio keyframe followed by 23 + // non-keyframes. + verifying_keyframeness_sequence_ = true; + EXPECT_CALL(*this, ParsedKeyframe()); + EXPECT_CALL(*this, ParsedNonKeyframe()).Times(23); + ParseMP4File("noise-xhe-aac.mp4", 512); EXPECT_EQ(audio_decoder_config_.profile(), AudioCodecProfile::kXHE_AAC); }
diff --git a/media/gpu/windows/av1_guids.h b/media/gpu/windows/av1_guids.h index 4d1731b..c5e4e5d 100644 --- a/media/gpu/windows/av1_guids.h +++ b/media/gpu/windows/av1_guids.h
@@ -5,6 +5,7 @@ #ifndef MEDIA_GPU_WINDOWS_AV1_GUIDS_H_ #define MEDIA_GPU_WINDOWS_AV1_GUIDS_H_ +#include <dxva.h> #include <initguid.h> #if WDK_NTDDI_VERSION <= NTDDI_WIN10_19H1
diff --git a/media/test/data/README.md b/media/test/data/README.md index d7d4d33..d0070f33 100644 --- a/media/test/data/README.md +++ b/media/test/data/README.md
@@ -51,9 +51,13 @@ #### noise-xhe-aac.mp4 Fragmented mp4 of noise encoded with xHE-AAC, from xHE-AAC samples in [Android -CTS](https://android.googlesource.com/platform/cts/+/master/tests/tests/media/res/raw) +CTS](https://android.googlesource.com/platform/cts/+/master/tests/tests/media/res/raw), +using ffmpeg version 4.2.2 (where nofillin lets audio nonkeyframes in input be +indicated the same in output, unlike more recent tip-of-tree ffmpeg's operation +with this option) to remux, unfortunately with empty MOOV not giving real +duration: ``` -ffmpeg -i noise_2ch_48khz_aot42_19_lufs_mp4.m4a -acodec copy -t 1 noise-xhe-aac.mp4 +ffmpeg -fflags nofillin -i noise_2ch_48khz_aot42_19_lufs_mp4.m4a -acodec copy -t 1 -movflags frag_keyframe+empty_moov+default_base_moof noise-xhe-aac.mp4 ``` ### FLAC
diff --git a/media/test/data/noise-xhe-aac.mp4 b/media/test/data/noise-xhe-aac.mp4 index 5e25c54..f138bb50 100644 --- a/media/test/data/noise-xhe-aac.mp4 +++ b/media/test/data/noise-xhe-aac.mp4 Binary files differ
diff --git a/mojo/public/cpp/bindings/tests/e2e_perftest.cc b/mojo/public/cpp/bindings/tests/e2e_perftest.cc index e11be65..91910a4 100644 --- a/mojo/public/cpp/bindings/tests/e2e_perftest.cc +++ b/mojo/public/cpp/bindings/tests/e2e_perftest.cc
@@ -81,8 +81,7 @@ current_iterations_ = 0; calls_outstanding_ = 0; - base::MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); - base::RunLoop run_loop; + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); quit_closure_ = run_loop.QuitClosure(); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&PingPongTest::DoPing, base::Unretained(this)));
diff --git a/net/dns/dns_response.cc b/net/dns/dns_response.cc index ffbad92..60d16d3 100644 --- a/net/dns/dns_response.cc +++ b/net/dns/dns_response.cc
@@ -93,8 +93,10 @@ } void DnsResourceRecord::SetOwnedRdata(std::string value) { + DCHECK(!value.empty()); owned_rdata = std::move(value); rdata = owned_rdata; + DCHECK_EQ(owned_rdata.data(), rdata.data()); } size_t DnsResourceRecord::CalculateRecordSize() const { @@ -557,8 +559,7 @@ bool DnsResponse::WriteRecord(base::BigEndianWriter* writer, const DnsResourceRecord& record) { - if (record.rdata.data() != record.owned_rdata.data() || - record.rdata.size() != record.owned_rdata.size()) { + if (record.rdata != base::StringPiece(record.owned_rdata)) { VLOG(1) << "record.rdata should point to record.owned_rdata."; return false; }
diff --git a/net/dns/dns_response.h b/net/dns/dns_response.h index 33c6397..c5b3281 100644 --- a/net/dns/dns_response.h +++ b/net/dns/dns_response.h
@@ -44,8 +44,8 @@ DnsResourceRecord& operator=(const DnsResourceRecord& other); DnsResourceRecord& operator=(DnsResourceRecord&& other); - // A helper to set |owned_rdata| that also sets |rdata| to point to it. - // See the definition of |owned_rdata| below. + // A helper to set |owned_rdata| that also sets |rdata| to point to it. The + // |value| must be non-empty. See the definition of |owned_rdata| below. void SetOwnedRdata(std::string value); // NAME (variable length) + TYPE (2 bytes) + CLASS (2 bytes) + TTL (4 bytes) +
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc index 0497c19..d7ccdab 100644 --- a/net/dns/dns_test_util.cc +++ b/net/dns/dns_test_util.cc
@@ -240,6 +240,26 @@ return record; } +DnsResourceRecord BuildIntegrityRecord( + std::string name, + const std::vector<uint8_t>& serialized_rdata) { + CHECK(!name.empty()); + + DnsResourceRecord record; + record.name = std::move(name); + record.type = dns_protocol::kExperimentalTypeIntegrity; + record.klass = dns_protocol::kClassIN; + record.ttl = base::TimeDelta::FromDays(1).InSeconds(); + + std::string serialized_rdata_str(serialized_rdata.begin(), + serialized_rdata.end()); + record.SetOwnedRdata(std::move(serialized_rdata_str)); + + CHECK_EQ(record.rdata.data(), record.owned_rdata.data()); + + return record; +} + } // namespace DnsResourceRecord BuildTestAddressRecord(std::string name, @@ -411,6 +431,25 @@ std::vector<DnsResourceRecord>() /* additional_records */, query); } +std::unique_ptr<DnsResponse> BuildTestDnsIntegrityResponse( + std::string hostname, + const std::vector<uint8_t>& serialized_rdata) { + CHECK(!hostname.empty()); + + std::vector<DnsResourceRecord> answers{ + BuildIntegrityRecord(hostname, serialized_rdata)}; + + std::string dns_name; + CHECK(DNSDomainFromDot(hostname, &dns_name)); + base::Optional<DnsQuery> query(base::in_place, 0, dns_name, + dns_protocol::kExperimentalTypeIntegrity); + + return std::make_unique<DnsResponse>( + 0, false, std::move(answers), + std::vector<DnsResourceRecord>() /* authority_records */, + std::vector<DnsResourceRecord>() /* additional_records */, query); +} + MockDnsClientRule::Result::Result(ResultType type) : type(type) {} MockDnsClientRule::Result::Result(std::unique_ptr<DnsResponse> response)
diff --git a/net/dns/dns_test_util.h b/net/dns/dns_test_util.h index bc056cd..4810b6e 100644 --- a/net/dns/dns_test_util.h +++ b/net/dns/dns_test_util.h
@@ -246,6 +246,10 @@ std::vector<EsniContent> esni_records, std::string answer_name = ""); +std::unique_ptr<DnsResponse> BuildTestDnsIntegrityResponse( + std::string hostname, + const std::vector<uint8_t>& serialized_rdata); + struct MockDnsClientRule { enum ResultType { NODOMAIN, // Fail asynchronously with ERR_NAME_NOT_RESOLVED and NXDOMAIN.
diff --git a/net/dns/dns_util.cc b/net/dns/dns_util.cc index ec7b0dd..5491dba 100644 --- a/net/dns/dns_util.cc +++ b/net/dns/dns_util.cc
@@ -291,6 +291,8 @@ return dns_protocol::kTypeSRV; case DnsQueryType::ESNI: return dns_protocol::kExperimentalTypeEsniDraft4; + case DnsQueryType::INTEGRITY: + return dns_protocol::kExperimentalTypeIntegrity; } }
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc index 647d44ae..d5c098c 100644 --- a/net/dns/host_cache.cc +++ b/net/dns/host_cache.cc
@@ -220,6 +220,7 @@ front.MergeAddressesFrom(back); MergeLists(&front.text_records_, back.text_records()); MergeLists(&front.hostnames_, back.hostnames()); + MergeLists(&front.integrity_data_, back.integrity_data()); if (back.esni_data_ && !front.esni_data_) { front.esni_data_ = std::move(back.esni_data_); } else if (front.esni_data_ && back.esni_data_) { @@ -299,6 +300,7 @@ text_records_(entry.text_records()), hostnames_(entry.hostnames()), esni_data_(entry.esni_data()), + integrity_data_(entry.integrity_data()), source_(entry.source()), ttl_(entry.ttl()), expires_(now + ttl), @@ -309,6 +311,7 @@ base::Optional<std::vector<std::string>>&& text_records, base::Optional<std::vector<HostPortPair>>&& hostnames, base::Optional<EsniContent>&& esni_data, + base::Optional<std::vector<bool>>&& integrity_data, Source source, base::TimeTicks expires, int network_changes) @@ -317,10 +320,15 @@ text_records_(std::move(text_records)), hostnames_(std::move(hostnames)), esni_data_(std::move(esni_data)), + integrity_data_(std::move(integrity_data)), source_(source), expires_(expires), network_changes_(network_changes) {} +void HostCache::Entry::PrepareForCacheInsertion() { + integrity_data_.reset(); +} + bool HostCache::Entry::IsStale(base::TimeTicks now, int network_changes) const { EntryStaleness stale; stale.expired_by = now - expires_; @@ -632,7 +640,9 @@ EvictOneEntry(now); } - AddEntry(key, Entry(entry, now, ttl, network_changes_)); + Entry entry_for_cache(entry, now, ttl, network_changes_); + entry_for_cache.PrepareForCacheInsertion(); + AddEntry(key, std::move(entry_for_cache)); if (delegate_ && result_changed) delegate_->ScheduleWrite(); @@ -866,6 +876,9 @@ return false; } + // We do not intend to serialize INTEGRITY records with the host cache. + base::Optional<std::vector<bool>> integrity_data; + // Assume an empty address list if we have an address type and no results. if (IsAddressType(dns_query_type) && !address_list && !text_records && !hostname_records && !esni_content) { @@ -883,8 +896,8 @@ if (found == entries_.end()) { AddEntry(key, Entry(error, address_list, std::move(text_records), std::move(hostname_records), std::move(esni_content), - Entry::SOURCE_UNKNOWN, expiration_time, - network_changes_ - 1)); + std::move(integrity_data), Entry::SOURCE_UNKNOWN, + expiration_time, network_changes_ - 1)); restore_size_++; } }
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h index 11f9293..6a39cfbd 100644 --- a/net/dns/host_cache.h +++ b/net/dns/host_cache.h
@@ -165,6 +165,13 @@ void set_esni_data(base::Optional<EsniContent> esni_data) { esni_data_ = std::move(esni_data); } + const base::Optional<std::vector<bool>>& integrity_data() const { + return integrity_data_; + } + void set_integrity_data(base::Optional<std::vector<bool>> integrity_data) { + integrity_data_ = std::move(integrity_data); + } + Source source() const { return source_; } bool has_ttl() const { return ttl_ >= base::TimeDelta(); } base::TimeDelta ttl() const { return ttl_; } @@ -208,10 +215,13 @@ base::Optional<std::vector<std::string>>&& text_results, base::Optional<std::vector<HostPortPair>>&& hostnames, base::Optional<EsniContent>&& esni_data, + base::Optional<std::vector<bool>>&& integrity_data, Source source, base::TimeTicks expires, int network_changes); + void PrepareForCacheInsertion(); + void SetResult(AddressList addresses) { addresses_ = std::move(addresses); } void SetResult(std::vector<std::string> text_records) { text_records_ = std::move(text_records); @@ -220,6 +230,9 @@ hostnames_ = std::move(hostnames); } void SetResult(EsniContent esni_data) { esni_data_ = std::move(esni_data); } + void SetResult(std::vector<bool> integrity_data) { + integrity_data_ = std::move(integrity_data); + } int total_hits() const { return total_hits_; } int stale_hits() const { return stale_hits_; } @@ -254,6 +267,7 @@ base::Optional<std::vector<std::string>> text_records_; base::Optional<std::vector<HostPortPair>> hostnames_; base::Optional<EsniContent> esni_data_; + base::Optional<std::vector<bool>> integrity_data_; // Where results were obtained (e.g. DNS lookup, hosts file, etc). Source source_ = SOURCE_UNKNOWN; // TTL obtained from the nameserver. Negative if unknown.
diff --git a/net/dns/host_resolver.cc b/net/dns/host_resolver.cc index 30dc656..7c582954 100644 --- a/net/dns/host_resolver.cc +++ b/net/dns/host_resolver.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/check.h" +#include "base/immediate_crash.h" #include "base/macros.h" #include "base/no_destructor.h" #include "base/notreached.h" @@ -80,6 +81,11 @@ } // namespace +const base::Optional<std::vector<bool>>& +HostResolver::ResolveHostRequest::GetIntegrityResultsForTesting() const { + IMMEDIATE_CRASH(); +} + const size_t HostResolver::ManagerOptions::kDefaultRetryAttempts = static_cast<size_t>(-1);
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h index 528e954..a11bb03 100644 --- a/net/dns/host_resolver.h +++ b/net/dns/host_resolver.h
@@ -105,6 +105,11 @@ // returning a result other than |ERR_IO_PENDING|. virtual const base::Optional<EsniContent>& GetEsniResults() const = 0; + // INTEGRITY results for an initial experiment related to HTTPSSVC. Each + // boolean value indicates the intactness of an INTEGRITY record. + NET_EXPORT virtual const base::Optional<std::vector<bool>>& + GetIntegrityResultsForTesting() const; + // Error info for the request. // // Should only be called after Start() signals completion, either by
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index 87bc925..ae9d58f 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -579,6 +579,14 @@ return results_ ? results_.value().esni_data() : *nullopt_result; } + const base::Optional<std::vector<bool>>& GetIntegrityResultsForTesting() + const override { + DCHECK(complete_); + static const base::NoDestructor<base::Optional<std::vector<bool>>> + nullopt_result; + return results_ ? results_.value().integrity_data() : *nullopt_result; + } + net::ResolveErrorInfo GetResolveErrorInfo() const override { DCHECK(complete_); return error_info_; @@ -1111,6 +1119,19 @@ base::FeatureList::IsEnabled(features::kRequestEsniDnsRecords)) { transactions_needed_.push(DnsQueryType::ESNI); } + + // Queue up an INTEGRITY query if we are allowed to. + if (base::FeatureList::IsEnabled(features::kDnsHttpssvc) && + features::kDnsHttpssvcUseIntegrity.Get() && + (secure_ || features::kDnsHttpssvcEnableQueryOverInsecure.Get()) && + (features::dns_httpssvc_experiment::IsExperimentDomain( + hostname.as_string()) || + features::dns_httpssvc_experiment::IsControlDomain( + hostname.as_string()))) { + // We should not be configured to query HTTPSSVC *and* INTEGRITY. + DCHECK(!features::kDnsHttpssvcUseHttpssvc.Get()); + transactions_needed_.push(DnsQueryType::INTEGRITY); + } } num_needed_transactions_ = transactions_needed_.size(); @@ -1170,10 +1191,10 @@ return trans; } - void OnEsniTransactionTimeout() { - // Currently, the ESNI transaction timer only gets started - // when all non-ESNI transactions have completed. - DCHECK(TaskIsCompleteOrOnlyEsniTransactionsRemain()); + void OnExperimentalQueryTimeout(uint16_t qtype) { + // Currently, the HTTPSSVC/INTEGRITY or ESNI transaction timer only gets + // started when all other transactions have completed. + DCHECK(TaskIsCompleteOrOnlyQtypeTransactionsRemain(qtype)); num_completed_transactions_ += transactions_started_.size(); DCHECK(num_completed_transactions_ == num_needed_transactions()); @@ -1204,8 +1225,13 @@ if (net_error != OK && !(net_error == ERR_NAME_NOT_RESOLVED && response && response->IsValid())) { - OnFailure(net_error, DnsResponse::DNS_PARSE_OK, base::nullopt); - return; + if (dns_query_type == DnsQueryType::INTEGRITY) { + // Do not allow an INTEGRITY query to fail the whole DnsTask. + response = nullptr; + } else { + OnFailure(net_error, DnsResponse::DNS_PARSE_OK, base::nullopt); + return; + } } DnsResponse::Result parse_result = DnsResponse::DNS_PARSE_RESULT_MAX; @@ -1231,6 +1257,10 @@ case DnsQueryType::ESNI: parse_result = ParseEsniDnsResponse(response, &results); break; + case DnsQueryType::INTEGRITY: + // Parse the INTEGRITY records, condensing them into a vector<bool>. + parse_result = ParseIntegrityDnsResponse(response, &results); + break; } DCHECK_LT(parse_result, DnsResponse::DNS_PARSE_RESULT_MAX); @@ -1264,6 +1294,10 @@ results = HostCache::Entry::MergeEntries( std::move(results), std::move(saved_results_).value()); break; + case DnsQueryType::INTEGRITY: + results = HostCache::Entry::MergeEntries( + std::move(results), std::move(saved_results_).value()); + break; default: // Only expect address query types with multiple transactions. NOTREACHED(); @@ -1278,6 +1312,7 @@ if (num_completed_transactions_ < num_needed_transactions()) { delegate_->OnIntermediateTransactionComplete(); MaybeStartEsniTimer(); + MaybeStartExperimentalQueryTimer(); return; } @@ -1285,6 +1320,8 @@ // are complete (if any were started). esni_cancellation_timer_.Stop(); + experimental_query_cancellation_timer_.Stop(); + ProcessResultsOnCompletion(); } @@ -1326,6 +1363,7 @@ DnsResponse::Result ParseAddressDnsResponse(const DnsResponse* response, HostCache::Entry* out_results) { + DCHECK(response); AddressList addresses; base::TimeDelta ttl; DnsResponse::Result parse_result = @@ -1346,6 +1384,7 @@ DnsResponse::Result ParseTxtDnsResponse(const DnsResponse* response, HostCache::Entry* out_results) { + DCHECK(response); std::vector<std::unique_ptr<const RecordParsed>> records; base::Optional<base::TimeDelta> response_ttl; DnsResponse::Result parse_result = ParseAndFilterResponseRecords( @@ -1371,6 +1410,7 @@ DnsResponse::Result ParsePointerDnsResponse(const DnsResponse* response, HostCache::Entry* out_results) { + DCHECK(response); std::vector<std::unique_ptr<const RecordParsed>> records; base::Optional<base::TimeDelta> response_ttl; DnsResponse::Result parse_result = ParseAndFilterResponseRecords( @@ -1399,6 +1439,7 @@ DnsResponse::Result ParseServiceDnsResponse(const DnsResponse* response, HostCache::Entry* out_results) { + DCHECK(response); std::vector<std::unique_ptr<const RecordParsed>> records; base::Optional<base::TimeDelta> response_ttl; DnsResponse::Result parse_result = ParseAndFilterResponseRecords( @@ -1430,6 +1471,7 @@ DnsResponse::Result ParseEsniDnsResponse(const DnsResponse* response, HostCache::Entry* out_results) { + DCHECK(response); std::vector<std::unique_ptr<const RecordParsed>> records; base::Optional<base::TimeDelta> response_ttl; DnsResponse::Result parse_result = ParseAndFilterResponseRecords( @@ -1480,6 +1522,42 @@ return parse_result; } + DnsResponse::Result ParseIntegrityDnsResponse(const DnsResponse* response, + HostCache::Entry* out_results) { + base::Optional<base::TimeDelta> response_ttl; + const HostCache::Entry default_entry( + OK, std::vector<bool>(), HostCache::Entry::SOURCE_DNS, response_ttl); + + if (response == nullptr) { + *out_results = default_entry; + return DnsResponse::Result::DNS_PARSE_OK; + } + + std::vector<std::unique_ptr<const RecordParsed>> records; + DnsResponse::Result parse_result = ParseAndFilterResponseRecords( + response, dns_protocol::kExperimentalTypeIntegrity, &records, + &response_ttl); + + if (parse_result != DnsResponse::DNS_PARSE_OK) { + *out_results = default_entry; + return DnsResponse::Result::DNS_PARSE_OK; + } + + // Condense results into a list of booleans. We do not cache the results, + // but this enables us to write some unit tests. + std::vector<bool> condensed_results; + for (const auto& record : records) { + const IntegrityRecordRdata& rdata = + *record->rdata<IntegrityRecordRdata>(); + condensed_results.push_back(rdata.IsIntact()); + } + + *out_results = HostCache::Entry(OK, std::move(condensed_results), + HostCache::Entry::SOURCE_DNS, response_ttl); + DCHECK_EQ(parse_result, DnsResponse::DNS_PARSE_OK); + return parse_result; + } + // Sort service targets per RFC2782. In summary, sort first by |priority|, // lowest first. For targets with the same priority, secondary sort randomly // using |weight| with higher weighted objects more likely to go first. @@ -1636,12 +1714,11 @@ delegate_->OnDnsTaskComplete(task_start_time_, results, secure_); } - // Returns whether all transactions left to execute are of transaction - // type ESNI. (In particular, this is the case if all transactions are - // complete.) - // Used for logging and starting the ESNI transaction timer (see + // Returns whether all transactions left to execute are of transaction type + // |qtype|. (In particular, this is the case if all transactions are + // complete.) Used for logging and starting the ESNI transaction timer (see // MaybeStartEsniTimer). - bool TaskIsCompleteOrOnlyEsniTransactionsRemain() const { + bool TaskIsCompleteOrOnlyQtypeTransactionsRemain(uint16_t qtype) const { // Since DoH runs all transactions concurrently and // DnsQueryType::UNSPECIFIED-with-ESNI tasks are only run using DoH, // this method only needs to check the transactions in transactions_started_ @@ -1653,10 +1730,15 @@ transactions_started_.begin(), transactions_started_.end(), [&](const std::unique_ptr<DnsTransaction>& p) { DCHECK(p); - return p->GetType() == dns_protocol::kExperimentalTypeEsniDraft4; + return p->GetType() == qtype; }); } + bool TaskIsCompleteOrOnlyEsniTransactionsRemain() const { + return TaskIsCompleteOrOnlyQtypeTransactionsRemain( + dns_protocol::kExperimentalTypeEsniDraft4); + } + // If ESNI transactions are being executed as part of this task // and all transactions except the ESNI transactions have finished, and the // ESNI transactions have not finished, starts a timer after which to abort @@ -1681,7 +1763,42 @@ total_time_taken_for_other_transactions * (0.01 * features::kEsniDnsMaxRelativeAdditionalWaitPercent.Get())), - this, &DnsTask::OnEsniTransactionTimeout); + base::BindOnce(&DnsTask::OnExperimentalQueryTimeout, + base::Unretained(this), + dns_protocol::kExperimentalTypeEsniDraft4)); + } + } + + void MaybeStartExperimentalQueryTimer() { + DCHECK(!transactions_started_.empty()); + + // Abort if neither HTTPSSVC nor INTEGRITY querying is enabled. + if (!base::FeatureList::IsEnabled(features::kDnsHttpssvc) || + (!features::kDnsHttpssvcUseIntegrity.Get() && + !features::kDnsHttpssvcUseHttpssvc.Get())) { + return; + } + + if (!experimental_query_cancellation_timer_.IsRunning() && + TaskIsCompleteOrOnlyQtypeTransactionsRemain( + dns_protocol::kExperimentalTypeIntegrity)) { + const base::TimeDelta kExtraTimeAbsolute = + features::dns_httpssvc_experiment::GetExtraTimeAbsolute(); + const int kExtraTimePercent = + features::kDnsHttpssvcExtraTimePercent.Get(); + + base::TimeDelta total_time_for_other_transactions = + tick_clock_->NowTicks() - task_start_time_; + base::TimeDelta relative_timeout = + total_time_for_other_transactions * kExtraTimePercent / 100; + + base::TimeDelta timeout = std::min(kExtraTimeAbsolute, relative_timeout); + + experimental_query_cancellation_timer_.Start( + FROM_HERE, timeout, + base::BindOnce(&DnsTask::OnExperimentalQueryTimeout, + base::Unretained(this), + dns_protocol::kExperimentalTypeIntegrity)); } } @@ -1722,6 +1839,10 @@ // the timeout parameters in net/base/features.h. base::OneShotTimer esni_cancellation_timer_; + // Timer for early abort of experimental queries. See comments describing the + // timeout parameters in net/base/features.h. + base::OneShotTimer experimental_query_cancellation_timer_; + DISALLOW_COPY_AND_ASSIGN(DnsTask); };
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index 16d7016..a4f2c96 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -86,6 +86,7 @@ using ::testing::Between; using ::testing::ByMove; using ::testing::Eq; +using ::testing::IsEmpty; using ::testing::Optional; using ::testing::Pair; using ::testing::Property; @@ -8653,6 +8654,542 @@ HostPortPair("google.com", 5))); } +class HostResolverManagerDnsTestIntegrity : public HostResolverManagerDnsTest { + public: + HostResolverManagerDnsTestIntegrity() + : HostResolverManagerDnsTest( + base::test::TaskEnvironment::TimeSource::MOCK_TIME) { + const base::FieldTrialParams params = { + {"DnsHttpssvcUseIntegrity", "true"}, + {"DnsHttpssvcExperimentDomains", "host"}, + {"DnsHttpssvcControlDomains", ""}, + {"DnsHttpssvcEnableQueryOverInsecure", "false"}, + }; + scoped_feature_list_.InitAndEnableFeatureWithParameters( + features::kDnsHttpssvc, params); + } + + protected: + struct IntegrityAddRulesOptions { + bool add_a = true; + bool add_aaaa = true; + bool add_integrity = true; + bool integrity_mangled = false; + + bool secure_a = true; + bool secure_aaaa = true; + bool secure_integrity = true; + + bool delay_a = false; + bool delay_aaaa = false; + bool delay_integrity = false; + }; + + std::vector<uint8_t> GetValidIntegrityRdata() { + const IntegrityRecordRdata kValidRecord({'f', 'o', 'o'}); + base::Optional<std::vector<uint8_t>> valid_serialized = + kValidRecord.Serialize(); + CHECK(valid_serialized); + return *valid_serialized; + } + + std::vector<uint8_t> GetMangledIntegrityRdata() { + std::vector<uint8_t> rdata = GetValidIntegrityRdata(); + constexpr size_t kOffset = 2u; + CHECK_GT(rdata.size(), kOffset); + // Create a mangled version of |kValidRecord| by erasing a byte. + rdata.erase(rdata.begin() + kOffset); + return rdata; + } + + void AddRules(MockDnsClientRuleList rules, + const IntegrityAddRulesOptions& options) { + if (options.add_a) { + rules.emplace_back("host", dns_protocol::kTypeA, options.secure_a, + MockDnsClientRule::Result(MockDnsClientRule::OK), + options.delay_a); + } + + if (options.add_aaaa) { + rules.emplace_back("host", dns_protocol::kTypeAAAA, options.secure_aaaa, + MockDnsClientRule::Result(MockDnsClientRule::OK), + options.delay_aaaa); + } + + if (options.add_integrity) { + std::vector<uint8_t> integrity_rdata = options.integrity_mangled + ? GetMangledIntegrityRdata() + : GetValidIntegrityRdata(); + rules.emplace_back( + "host", dns_protocol::kExperimentalTypeIntegrity, + options.secure_integrity, + MockDnsClientRule::Result(BuildTestDnsIntegrityResponse( + "host", std::move(integrity_rdata))), + options.delay_integrity); + } + + CreateResolver(); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + } + + std::unique_ptr<ResolveHostResponseHelper> DoIntegrityQuery(bool use_secure) { + if (use_secure) { + DnsConfigOverrides overrides; + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::SECURE; + resolver_->SetDnsConfigOverrides(overrides); + } + + return std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest( + HostPortPair("host", 108), NetworkIsolationKey(), NetLogWithSource(), + HostResolver::ResolveHostParameters(), resolve_context_.get(), + resolve_context_->host_cache())); + } + + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(HostResolverManagerDnsTestIntegrity, IntegrityQuery) { + AddRules(CreateDefaultDnsRules(), IntegrityAddRulesOptions()); + + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + EXPECT_THAT(response->result_error(), IsOk()); + base::Optional<std::vector<bool>> results = + response->request()->GetIntegrityResultsForTesting(); + + EXPECT_TRUE(response->request()->GetAddressResults()); + EXPECT_FALSE(response->request()->GetTextResults()); + EXPECT_THAT(results, Optional(UnorderedElementsAre(true))); +} + +TEST_F(HostResolverManagerDnsTestIntegrity, IntegrityQueryMangled) { + IntegrityAddRulesOptions options; + options.integrity_mangled = true; + AddRules(CreateDefaultDnsRules(), options); + + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + EXPECT_THAT(response->result_error(), IsOk()); + base::Optional<std::vector<bool>> results = + response->request()->GetIntegrityResultsForTesting(); + + EXPECT_TRUE(response->request()->GetAddressResults()); + EXPECT_FALSE(response->request()->GetTextResults()); + EXPECT_THAT(response->request()->GetIntegrityResultsForTesting(), + Optional(UnorderedElementsAre(false))); +} + +TEST_F(HostResolverManagerDnsTestIntegrity, IntegrityQueryOnlyOverSecure) { + IntegrityAddRulesOptions rules_options; + rules_options.secure_a = false; + rules_options.secure_aaaa = false; + rules_options.secure_integrity = false; + + AddRules(CreateDefaultDnsRules(), rules_options); + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(false /* use_secure */); + + EXPECT_THAT(response->result_error(), IsOk()); + base::Optional<std::vector<bool>> results = + response->request()->GetIntegrityResultsForTesting(); + + EXPECT_FALSE(results); +} + +// Ensure that the address results are preserved, even when the INTEGRITY query +// completes last. +TEST_F(HostResolverManagerDnsTestIntegrity, IntegrityQueryCompletesLast) { + IntegrityAddRulesOptions rules_options; + rules_options.delay_a = true; + rules_options.delay_aaaa = true; + rules_options.delay_integrity = true; + + AddRules(CreateDefaultDnsRules(), rules_options); + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + constexpr base::TimeDelta kQuantum = base::TimeDelta::FromMilliseconds(1); + + FastForwardBy(100 * kQuantum); + + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::A)); + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA)); + + FastForwardBy(kQuantum); + + ASSERT_TRUE(dns_client_->CompleteOneDelayedTransactionOfType( + DnsQueryType::INTEGRITY)); + + // Above, the A/AAAA queries took 100 time units. We only fast forward by 1 + // time unit (1%) before answering the INTEGRITY query, to avoid triggering + // the timeout logic. This should work, assuming + // (1) the relative timeout is > 1% and + // (2) the absolute timeout is < (101 * kQuantum). + FastForwardBy(kQuantum); + + ASSERT_THAT(response->result_error(), IsOk()); + ASSERT_TRUE(response->request()->GetAddressResults()); + EXPECT_THAT(response->request()->GetAddressResults()->endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 108), + CreateExpected("::1", 108))); + // If this expectation fails, the INTEGRITY query was probably timed out. + // Check the |kDnsHttpssvcExtraTimeMs| and |kDnsHttpssvcExtraTimePercent| + // feature params in relation to this test's FastForward steps. + EXPECT_THAT(response->request()->GetIntegrityResultsForTesting(), + Optional(UnorderedElementsAre(true))); +} + +// For symmetry with |IntegrityQueryCompletesLast|, test the case where the +// INTEGRITY query completes first. +TEST_F(HostResolverManagerDnsTestIntegrity, IntegrityQueryCompletesFirst) { + IntegrityAddRulesOptions rules_options; + rules_options.delay_a = true; + rules_options.delay_aaaa = true; + rules_options.delay_integrity = true; + + AddRules(CreateDefaultDnsRules(), rules_options); + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + constexpr base::TimeDelta kQuantum = base::TimeDelta::FromMilliseconds(10); + + FastForwardBy(kQuantum); + + ASSERT_TRUE(dns_client_->CompleteOneDelayedTransactionOfType( + DnsQueryType::INTEGRITY)); + + FastForwardBy(kQuantum); + + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::A)); + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA)); + + FastForwardBy(kQuantum); + + ASSERT_THAT(response->result_error(), IsOk()); + EXPECT_THAT(response->request()->GetIntegrityResultsForTesting(), + Optional(UnorderedElementsAre(true))); + ASSERT_TRUE(response->request()->GetAddressResults()); + EXPECT_THAT(response->request()->GetAddressResults()->endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 108), + CreateExpected("::1", 108))); +} + +// Ensure that the address results are preserved, even when the INTEGRITY query +// completes last and fails. +TEST_F(HostResolverManagerDnsTestIntegrity, + IntegrityQueryCompletesLastWithError) { + IntegrityAddRulesOptions rules_options; + rules_options.add_a = true; + rules_options.add_aaaa = true; + rules_options.add_integrity = false; + + rules_options.delay_a = true; + rules_options.delay_aaaa = true; + rules_options.delay_integrity = true; + + AddRules(CreateDefaultDnsRules(), rules_options); + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + constexpr base::TimeDelta kQuantum = base::TimeDelta::FromMilliseconds(1); + + FastForwardBy(100 * kQuantum); + + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::A)); + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA)); + + FastForwardBy(kQuantum); + + ASSERT_FALSE(dns_client_->CompleteOneDelayedTransactionOfType( + DnsQueryType::INTEGRITY)); + + FastForwardBy(kQuantum); + + ASSERT_THAT(response->result_error(), IsOk()); + ASSERT_TRUE(response->request()->GetAddressResults()); + EXPECT_THAT(response->request()->GetAddressResults()->endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 108), + CreateExpected("::1", 108))); + EXPECT_THAT(response->request()->GetIntegrityResultsForTesting(), + Optional(IsEmpty())); +} + +// Ensure that the address results are preserved, even when the INTEGRITY query +// completes first and fails. +TEST_F(HostResolverManagerDnsTestIntegrity, + IntegrityQueryCompletesFirstWithError) { + IntegrityAddRulesOptions rules_options; + rules_options.add_a = true; + rules_options.add_aaaa = true; + rules_options.add_integrity = false; + + rules_options.delay_a = true; + rules_options.delay_aaaa = true; + rules_options.delay_integrity = true; + + AddRules(CreateDefaultDnsRules(), rules_options); + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + constexpr base::TimeDelta kQuantum = base::TimeDelta::FromMilliseconds(10); + + FastForwardBy(kQuantum); + + // This fails because there is no rule for the INTEGRITY query. + ASSERT_FALSE(dns_client_->CompleteOneDelayedTransactionOfType( + DnsQueryType::INTEGRITY)); + + FastForwardBy(kQuantum); + + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::A)); + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA)); + + FastForwardBy(kQuantum); + + ASSERT_THAT(response->result_error(), IsOk()); + EXPECT_THAT(response->request()->GetIntegrityResultsForTesting(), + Optional(IsEmpty())); + ASSERT_TRUE(response->request()->GetAddressResults()); + EXPECT_THAT(response->request()->GetAddressResults()->endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 108), + CreateExpected("::1", 108))); +} + +TEST_F(HostResolverManagerDnsTestIntegrity, + IntegrityQueryCompletesLastMangled) { + IntegrityAddRulesOptions rules_options; + rules_options.integrity_mangled = true; + + rules_options.delay_a = true; + rules_options.delay_aaaa = true; + rules_options.delay_integrity = true; + + AddRules(CreateDefaultDnsRules(), rules_options); + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + constexpr base::TimeDelta kQuantum = base::TimeDelta::FromMilliseconds(1); + + FastForwardBy(100 * kQuantum); + + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::A)); + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA)); + + FastForwardBy(kQuantum); + + ASSERT_TRUE(dns_client_->CompleteOneDelayedTransactionOfType( + DnsQueryType::INTEGRITY)); + + FastForwardBy(kQuantum); + + ASSERT_THAT(response->result_error(), IsOk()); + ASSERT_TRUE(response->request()->GetAddressResults()); + EXPECT_THAT(response->request()->GetAddressResults()->endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 108), + CreateExpected("::1", 108))); + EXPECT_THAT(response->request()->GetIntegrityResultsForTesting(), + Optional(UnorderedElementsAre(false))); +} + +TEST_F(HostResolverManagerDnsTestIntegrity, + IntegrityQueryCompletesFirstMangled) { + IntegrityAddRulesOptions rules_options; + rules_options.integrity_mangled = true; + + rules_options.delay_a = true; + rules_options.delay_aaaa = true; + rules_options.delay_integrity = true; + + AddRules(CreateDefaultDnsRules(), rules_options); + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + constexpr base::TimeDelta kQuantum = base::TimeDelta::FromMilliseconds(10); + + FastForwardBy(kQuantum); + + ASSERT_TRUE(dns_client_->CompleteOneDelayedTransactionOfType( + DnsQueryType::INTEGRITY)); + + FastForwardBy(kQuantum); + + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::A)); + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA)); + + FastForwardBy(kQuantum); + + ASSERT_THAT(response->result_error(), IsOk()); + EXPECT_THAT(response->request()->GetIntegrityResultsForTesting(), + Optional(UnorderedElementsAre(false))); + ASSERT_TRUE(response->request()->GetAddressResults()); + EXPECT_THAT(response->request()->GetAddressResults()->endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 108), + CreateExpected("::1", 108))); +} + +// Make sure that INTEGRITY queries don't get cancelled *before* the configured +// timeout, but do get cancelled after it, in the case where the absolute +// timeout dominates. +TEST_F(HostResolverManagerDnsTestIntegrity, RespectsAbsoluteTimeout) { + IntegrityAddRulesOptions rules_options; + rules_options.delay_a = true; + rules_options.delay_aaaa = true; + rules_options.delay_integrity = true; + + AddRules(CreateDefaultDnsRules(), rules_options); + + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + // relative_timeout + // ┌────────────────────────────────┤ + // │ + // │ absolute_timeout + // ├────────────────────┤ + // a_aaaa_elapsed │ time + // ├────────────────────┼─────────────────────────────────────────────────> + // Now └ (moment when A and AAAA complete) + // + // When the A and AAAA queries complete, and only INTEGRITY remains, we start + // running the INTEGRITY timeout clock. This moment is |Now + a_aaaa_elapsed|, + // or just |a_aaaa_elapsed| if we let Now = 0. The INTEGRITY query is + // cancelled at the moment that |absolute_timeout| or |relative_timeout| runs + // out. + // + // The TimeDelta values of |absolute_timeout| and |relative_timeout| are + // computed from feature params. + // + // absolute_timeout = a_aaaa_elapsed + ExtraMs. + // + // relative_timeout = a_aaaa_elapsed * (1 + (ExtraPercent/100)). + // + // Assume ExtraMs > 0 and 0 < ExtraPercent < 100. + // + // For this test, we want the absolute timeout to happen *before* the relative + // timeout. Compute a value for a_aaaa_elapsed such that absolute_timeout + // comes before relative_timeout. + // + // Assuming ExtraPercent is not zero, we know that these two lines intersect + // for some value of a_aaaa_elapsed. Let's find it. + // + // Assume absolute_timeout = relative_timeout. + // a_aaaa_elapsed + ExtraMs = a_aaaa_elapsed * (1 + (ExtraPercent / 100)). + // ExtraMs = a_aaaa_elapsed * (1 + (ExtraPercent / 100)) - a_aaaa_elapsed. + // ExtraMs = a_aaaa_elapsed * ((1 + (ExtraPercent / 100)) - 1). + // ExtraMs / ((1 + (ExtraPercent / 100)) - 1) = a_aaaa_elapsed. + // Simplified: + // a_aaaa_elapsed = 100 * ExtraMs / ExtraPercent. + // + // For values of a_aaaa_elapsed < 100 * ExtraMs / ExtraPercent, + // relative_timeout < absolute_timeout. For larger values, absolute_timeout > + // relative_timeout. + + base::TimeDelta absolute_timeout = base::TimeDelta::FromMilliseconds( + features::kDnsHttpssvcExtraTimeMs.Get()); + base::TimeDelta intersection = + 100 * absolute_timeout / features::kDnsHttpssvcExtraTimePercent.Get(); + + // Let enough time pass during the A and AAAA transactions that the + // absolute timeout will be less than the relative timeout. + base::TimeDelta a_aaaa_elapsed = 50 * intersection; + + FastForwardBy(a_aaaa_elapsed); + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::A)); + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA)); + + // Since the A and AAAA queries have only just completed, we shouldn't + // have timed out the INTEGRITY query. + EXPECT_FALSE(response->complete()); + + // After half of the absolute timeout, the query should still be alive. + FastForwardBy(absolute_timeout / 2); + + // Since the absolute timeout has not yet elapsed, and it is shorter by + // design than the relative timeout, we shouldn't + // have timed out the INTEGRITY transaction. + EXPECT_FALSE(response->complete()); + + // After (more than) the timeout has passed, we should have cancelled + // the INTEGRITY transaction. + FastForwardBy(absolute_timeout); + ASSERT_THAT(response->result_error(), IsOk()); + + // Since we cancelled the transaction, we shouldn't have any INTEGRITY + // results. + EXPECT_FALSE(response->request()->GetIntegrityResultsForTesting()); + + // Out of paranoia, pass some more time to ensure no crashes occur. + FastForwardBy(base::TimeDelta::FromMilliseconds(100)); +} + +TEST_F(HostResolverManagerDnsTestIntegrity, RespectsRelativeTimeout) { + IntegrityAddRulesOptions rules_options; + rules_options.delay_a = false; + rules_options.delay_aaaa = true; + rules_options.delay_integrity = true; + + AddRules(CreateDefaultDnsRules(), rules_options); + + std::unique_ptr<ResolveHostResponseHelper> response = + DoIntegrityQuery(true /* use_secure */); + + base::TimeDelta absolute_timeout = base::TimeDelta::FromMilliseconds( + features::kDnsHttpssvcExtraTimeMs.Get()); + base::TimeDelta intersection = + 100 * absolute_timeout / features::kDnsHttpssvcExtraTimePercent.Get(); + + // Let little enough time pass during the A and AAAA transactions that the + // relative timeout will be less than the absolute timeout. + base::TimeDelta a_aaaa_elapsed = 0.05 * intersection; + + // Since the A and AAAA queries haven't both completed yet, we shouldn't time + // out the INTEGRITY query. + FastForwardBy(a_aaaa_elapsed); + + // Upon completing the AAAA transaction, the INTEGRITY timer should start + ASSERT_TRUE( + dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA)); + + base::TimeDelta relative_timeout = + a_aaaa_elapsed * features::kDnsHttpssvcExtraTimePercent.Get() / 100; + + // After *less* than the relative timeout, the query shouldn't have concluded. + FastForwardBy(relative_timeout * 0.5); + + EXPECT_FALSE(response->complete()); + + // After more than the relative timeout, the query should conclude by aborting + // the INTEGRITY query. + FastForwardBy(relative_timeout); + + // The task should have completed with a cancelled INTEGRITY query. + ASSERT_THAT(response->result_error(), IsOk()); + EXPECT_FALSE(response->request()->GetIntegrityResultsForTesting()); + ASSERT_TRUE(response->request()->GetAddressResults()); + EXPECT_THAT(response->request()->GetAddressResults()->endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 108), + CreateExpected("::1", 108))); + + // Out of paranoia, pass some more time to ensure no crashes occur. + FastForwardBy(base::TimeDelta::FromMilliseconds(100)); +} + TEST_F(HostResolverManagerDnsTest, DohProbeRequest) { ChangeDnsConfig(CreateValidDnsConfig());
diff --git a/net/dns/host_resolver_mdns_listener_impl.cc b/net/dns/host_resolver_mdns_listener_impl.cc index 88102df..d75977c 100644 --- a/net/dns/host_resolver_mdns_listener_impl.cc +++ b/net/dns/host_resolver_mdns_listener_impl.cc
@@ -74,6 +74,7 @@ switch (query_type_) { case DnsQueryType::UNSPECIFIED: case DnsQueryType::ESNI: + case DnsQueryType::INTEGRITY: NOTREACHED(); break; case DnsQueryType::A:
diff --git a/net/dns/host_resolver_mdns_task.cc b/net/dns/host_resolver_mdns_task.cc index 551ab7a..4f58456 100644 --- a/net/dns/host_resolver_mdns_task.cc +++ b/net/dns/host_resolver_mdns_task.cc
@@ -201,6 +201,9 @@ case DnsQueryType::ESNI: // ESNI queries are not expected to be useful in mDNS, so they're not // supported. + case DnsQueryType::INTEGRITY: + // INTEGRITY queries are not expected to be useful in mDNS, so they're not + // supported. NOTREACHED(); return HostCache::Entry(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN); case DnsQueryType::A:
diff --git a/net/dns/public/dns_query_type.h b/net/dns/public/dns_query_type.h index 7d407a6..1355058 100644 --- a/net/dns/public/dns_query_type.h +++ b/net/dns/public/dns_query_type.h
@@ -21,13 +21,15 @@ PTR, SRV, ESNI, - MAX = ESNI + INTEGRITY, + MAX = INTEGRITY }; const DnsQueryType kDnsQueryTypes[] = { - DnsQueryType::UNSPECIFIED, DnsQueryType::A, DnsQueryType::AAAA, - DnsQueryType::TXT, DnsQueryType::PTR, DnsQueryType::SRV, - DnsQueryType::ESNI}; + DnsQueryType::UNSPECIFIED, DnsQueryType::A, DnsQueryType::AAAA, + DnsQueryType::TXT, DnsQueryType::PTR, DnsQueryType::SRV, + DnsQueryType::ESNI, DnsQueryType::INTEGRITY, +}; static_assert(base::size(kDnsQueryTypes) == static_cast<unsigned>(DnsQueryType::MAX) + 1,
diff --git a/net/dns/record_rdata.cc b/net/dns/record_rdata.cc index 74200808..2c6f45d 100644 --- a/net/dns/record_rdata.cc +++ b/net/dns/record_rdata.cc
@@ -101,6 +101,11 @@ // length prefix static const size_t kEsniDraft4MinimumSize = 21; +// The simplest INTEGRITY record is a U16-length-prefixed nonce (containing zero +// bytes) followed by its SHA256 digest. +static constexpr size_t kIntegrityMinimumSize = + sizeof(uint16_t) + IntegrityRecordRdata::kDigestLen; + bool RecordRdata::HasValidSize(const base::StringPiece& data, uint16_t type) { switch (type) { case dns_protocol::kTypeSRV: @@ -111,6 +116,8 @@ return data.size() == IPAddress::kIPv6AddressSize; case dns_protocol::kExperimentalTypeEsniDraft4: return data.size() >= kEsniDraft4MinimumSize; + case dns_protocol::kExperimentalTypeIntegrity: + return data.size() >= kIntegrityMinimumSize; case dns_protocol::kTypeCNAME: case dns_protocol::kTypePTR: case dns_protocol::kTypeTXT:
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index 71b2acd..fdf2e725 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -236,9 +236,6 @@ // If true, disable QUIC version Q050. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q050, false) -// If true, enable QUIC version T050. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_t050_v2, true) - // A testonly reloadable flag that will always default to false. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_testonly_default_false, false) @@ -452,3 +449,6 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_willing_and_able_to_write, true) + +// If true, disable QUIC version h3-T050. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_t050, false)
diff --git a/net/third_party/quiche/BUILD.gn b/net/third_party/quiche/BUILD.gn index 59a75e2..201d6c1 100644 --- a/net/third_party/quiche/BUILD.gn +++ b/net/third_party/quiche/BUILD.gn
@@ -1426,58 +1426,6 @@ "src/spdy/platform/api/spdy_test_helpers.h", ] - # Disable building Quartc tests on iOS as they appear to be flaky there. - if (!is_ios) { - sources += [ - "src/quic/quartc/counting_packet_filter.h", - "src/quic/quartc/quartc_connection_helper.cc", - "src/quic/quartc/quartc_connection_helper.h", - "src/quic/quartc/quartc_crypto_helpers.cc", - "src/quic/quartc/quartc_crypto_helpers.h", - "src/quic/quartc/quartc_dispatcher.cc", - "src/quic/quartc/quartc_dispatcher.h", - "src/quic/quartc/quartc_endpoint.cc", - "src/quic/quartc/quartc_endpoint.h", - "src/quic/quartc/quartc_endpoint_test.cc", - "src/quic/quartc/quartc_factory.cc", - "src/quic/quartc/quartc_factory.h", - "src/quic/quartc/quartc_fakes.h", - "src/quic/quartc/quartc_interval_counter.h", - "src/quic/quartc/quartc_interval_counter_test.cc", - "src/quic/quartc/quartc_multiplexer.cc", - "src/quic/quartc/quartc_multiplexer.h", - "src/quic/quartc/quartc_multiplexer_test.cc", - "src/quic/quartc/quartc_packet_writer.cc", - "src/quic/quartc/quartc_packet_writer.h", - "src/quic/quartc/quartc_session.cc", - "src/quic/quartc/quartc_session.h", - "src/quic/quartc/quartc_session_test.cc", - "src/quic/quartc/quartc_stream.cc", - "src/quic/quartc/quartc_stream.h", - "src/quic/quartc/quartc_stream_test.cc", - "src/quic/quartc/simulated_packet_transport.cc", - "src/quic/quartc/simulated_packet_transport.h", - "src/quic/quartc/simulated_packet_transport_test.cc", - "src/quic/quartc/test/bidi_test_runner.cc", - "src/quic/quartc/test/bidi_test_runner.h", - "src/quic/quartc/test/quartc_bidi_test.cc", - "src/quic/quartc/test/quartc_competing_endpoint.cc", - "src/quic/quartc/test/quartc_competing_endpoint.h", - "src/quic/quartc/test/quartc_data_source.cc", - "src/quic/quartc/test/quartc_data_source.h", - "src/quic/quartc/test/quartc_data_source_test.cc", - "src/quic/quartc/test/quartc_peer.cc", - "src/quic/quartc/test/quartc_peer.h", - "src/quic/quartc/test/quartc_peer_test.cc", - "src/quic/quartc/test/quic_trace_interceptor.cc", - "src/quic/quartc/test/quic_trace_interceptor.h", - "src/quic/quartc/test/random_delay_link.cc", - "src/quic/quartc/test/random_delay_link.h", - "src/quic/quartc/test/random_packet_filter.cc", - "src/quic/quartc/test/random_packet_filter.h", - ] - } - deps = [ "//net", "//net:quic_test_tools",
diff --git a/services/device/hid/hid_service_win.cc b/services/device/hid/hid_service_win.cc index 8bab82b..80fff2d3 100644 --- a/services/device/hid/hid_service_win.cc +++ b/services/device/hid/hid_service_win.cc
@@ -4,15 +4,16 @@ #include "services/device/hid/hid_service_win.h" -#include <memory> - #define INITGUID #include <dbt.h> +#include <devpkey.h> #include <setupapi.h> #include <stddef.h> +#include <wdmguid.h> #include <winioctl.h> +#include <memory> #include <utility> #include "base/bind.h" @@ -22,16 +23,112 @@ #include "base/memory/free_deleter.h" #include "base/sequenced_task_runner.h" #include "base/strings/string_util.h" -#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/win/scoped_devinfo.h" +#include "base/win/win_util.h" #include "components/device_event_log/device_event_log.h" #include "services/device/hid/hid_connection_win.h" #include "services/device/hid/hid_device_info.h" namespace device { +namespace { + +// Looks up the value of a GUID-type device property specified by |property| for +// the device described by |device_info_data|. On success, returns true and sets +// |property_buffer| to the property value. Returns false if the property is not +// present or has a different type. +bool GetDeviceGuidProperty(HDEVINFO device_info_set, + SP_DEVINFO_DATA& device_info_data, + const DEVPROPKEY& property, + GUID* property_buffer) { + DEVPROPTYPE property_type; + if (!SetupDiGetDeviceProperty( + device_info_set, &device_info_data, &property, &property_type, + reinterpret_cast<PBYTE>(property_buffer), sizeof(*property_buffer), + /*RequiredSize=*/nullptr, /*Flags=*/0) || + property_type != DEVPROP_TYPE_GUID) { + return false; + } + return true; +} + +// Looks up information about the device described by |device_interface_data| +// in |device_info_set|. On success, returns true and sets |device_info_data| +// and |device_path|. Returns false if an error occurred. +bool GetDeviceInfoAndPathFromInterface( + HDEVINFO device_info_set, + SP_DEVICE_INTERFACE_DATA& device_interface_data, + SP_DEVINFO_DATA* device_info_data, + base::string16* device_path) { + // Get the required buffer size. When called with + // DeviceInterfaceDetailData == nullptr and DeviceInterfaceDetailSize == 0, + // SetupDiGetDeviceInterfaceDetail returns the required buffer size at + // RequiredSize and fails with GetLastError() == ERROR_INSUFFICIENT_BUFFER. + DWORD required_size; + if (SetupDiGetDeviceInterfaceDetail(device_info_set, &device_interface_data, + /*DeviceInterfaceDetailData=*/nullptr, + /*DeviceInterfaceDetailSize=*/0, + &required_size, + /*DeviceInfoData=*/nullptr) || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return false; + } + + std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter> + device_interface_detail_data( + static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(required_size))); + device_interface_detail_data->cbSize = sizeof(*device_interface_detail_data); + + // Call the function again with the correct buffer size to get the detailed + // data for this device. + if (!SetupDiGetDeviceInterfaceDetail(device_info_set, &device_interface_data, + device_interface_detail_data.get(), + required_size, /*RequiredSize=*/nullptr, + device_info_data)) { + return false; + } + + // Windows uses case-insensitive paths and may return paths that differ only + // by case. Canonicalize the device path by converting to lowercase. + base::string16 path = + base::string16(device_interface_detail_data->DevicePath); + DCHECK(base::IsStringASCII(path)); + *device_path = base::ToLowerASCII(path); + return true; +} + +// Returns a device info set containing only the device described by +// |device_path|, or an invalid ScopedDevInfo if there was an error while +// creating the device set. The device info is returned in |device_info_data|. +base::win::ScopedDevInfo GetDeviceInfoFromPath( + const base::string16& device_path, + SP_DEVINFO_DATA* device_info_data) { + base::win::ScopedDevInfo device_info_set(SetupDiGetClassDevs( + &GUID_DEVINTERFACE_HID, /*Enumerator=*/nullptr, + /*hwndParent=*/0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); + if (!device_info_set.is_valid()) + return base::win::ScopedDevInfo(); + + SP_DEVICE_INTERFACE_DATA device_interface_data; + device_interface_data.cbSize = sizeof(device_interface_data); + if (!SetupDiOpenDeviceInterface(device_info_set.get(), device_path.c_str(), + /*OpenFlags=*/0, &device_interface_data)) { + return base::win::ScopedDevInfo(); + } + + base::string16 intf_device_path; + GetDeviceInfoAndPathFromInterface(device_info_set.get(), + device_interface_data, device_info_data, + &intf_device_path); + DCHECK_EQ(intf_device_path, device_path); + return device_info_set; +} + +} // namespace + HidServiceWin::HidServiceWin() : task_runner_(base::SequencedTaskRunnerHandle::Get()), blocking_task_runner_( @@ -82,41 +179,37 @@ void HidServiceWin::EnumerateBlocking( base::WeakPtr<HidServiceWin> service, scoped_refptr<base::SequencedTaskRunner> task_runner) { - base::win::ScopedDevInfo dev_info( - SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, nullptr, nullptr, - DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); + base::win::ScopedDevInfo dev_info(SetupDiGetClassDevs( + &GUID_DEVINTERFACE_HID, /*Enumerator=*/nullptr, + /*hwndParent=*/nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); if (dev_info.is_valid()) { - SP_DEVICE_INTERFACE_DATA device_interface_data; - device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + SP_DEVICE_INTERFACE_DATA device_interface_data = {0}; + device_interface_data.cbSize = sizeof(device_interface_data); for (int device_index = 0; SetupDiEnumDeviceInterfaces( - dev_info.get(), nullptr, &GUID_DEVINTERFACE_HID, device_index, - &device_interface_data); + dev_info.get(), /*DeviceInfoData=*/nullptr, &GUID_DEVINTERFACE_HID, + device_index, &device_interface_data); ++device_index) { - DWORD required_size = 0; - - // Determime the required size of detail struct. - SetupDiGetDeviceInterfaceDetail(dev_info.get(), &device_interface_data, - nullptr, 0, &required_size, nullptr); - - std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter> - device_interface_detail_data( - static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(required_size))); - device_interface_detail_data->cbSize = - sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); - - // Get the detailed data for this device. - BOOL res = SetupDiGetDeviceInterfaceDetail( - dev_info.get(), &device_interface_data, - device_interface_detail_data.get(), required_size, nullptr, nullptr); - if (!res) { + SP_DEVINFO_DATA dev_info_data = {0}; + dev_info_data.cbSize = sizeof(dev_info_data); + base::string16 device_path; + if (!GetDeviceInfoAndPathFromInterface(dev_info.get(), + device_interface_data, + &dev_info_data, &device_path)) { continue; } - base::string16 device_path(device_interface_detail_data->DevicePath); - DCHECK(base::IsStringASCII(device_path)); - AddDeviceBlocking(service, task_runner, base::ToLowerASCII(device_path)); + // Get the container ID for the physical device. + GUID container_id; + if (!GetDeviceGuidProperty(dev_info.get(), dev_info_data, + DEVPKEY_Device_ContainerId, &container_id)) { + continue; + } + std::string physical_device_id = + base::UTF16ToUTF8(base::win::String16FromGUID(container_id)); + + AddDeviceBlocking(service, task_runner, device_path, physical_device_id); } } @@ -171,14 +264,15 @@ void HidServiceWin::AddDeviceBlocking( base::WeakPtr<HidServiceWin> service, scoped_refptr<base::SequencedTaskRunner> task_runner, - const base::string16& device_path) { + const base::string16& device_path, + const std::string& physical_device_id) { base::win::ScopedHandle device_handle(OpenDevice(device_path)); if (!device_handle.IsValid()) { return; } HIDD_ATTRIBUTES attrib = {0}; - attrib.Size = sizeof(HIDD_ATTRIBUTES); + attrib.Size = sizeof(attrib); if (!HidD_GetAttributes(device_handle.Get(), &attrib)) { HID_LOG(EVENT) << "Failed to get device attributes."; return; @@ -238,24 +332,24 @@ // 1023 characters plus NULL terminator is more than enough for a USB string // descriptor which is limited to 126 characters. - wchar_t buffer[1024]; + base::char16 buffer[1024]; std::string product_name; if (HidD_GetProductString(device_handle.Get(), &buffer[0], sizeof(buffer))) { // NULL termination guaranteed by the API. - product_name = base::SysWideToUTF8(buffer); + product_name = base::UTF16ToUTF8(buffer); } std::string serial_number; if (HidD_GetSerialNumberString(device_handle.Get(), &buffer[0], sizeof(buffer))) { // NULL termination guaranteed by the API. - serial_number = base::SysWideToUTF8(buffer); + serial_number = base::UTF16ToUTF8(buffer); } // This populates the HidDeviceInfo instance without a raw report descriptor. // The descriptor is unavailable on Windows because HID devices are exposed to // user-space as individual top-level collections. scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfo( - device_path, /*physical_device_id=*/"", attrib.VendorID, attrib.ProductID, + device_path, physical_device_id, attrib.VendorID, attrib.ProductID, product_name, serial_number, // TODO(reillyg): Detect Bluetooth. crbug.com/443335 mojom::HidBusType::kHIDBusTypeUSB, std::move(collection_info), @@ -268,10 +362,24 @@ void HidServiceWin::OnDeviceAdded(const GUID& class_guid, const base::string16& device_path) { + SP_DEVINFO_DATA device_info_data = {0}; + device_info_data.cbSize = sizeof(device_info_data); + auto device_info_set = GetDeviceInfoFromPath(device_path, &device_info_data); + if (!device_info_set.is_valid()) + return; + + GUID container_id; + if (!GetDeviceGuidProperty(device_info_set.get(), device_info_data, + DEVPKEY_Device_ContainerId, &container_id)) { + return; + } + std::string physical_device_id = + base::UTF16ToUTF8(base::win::String16FromGUID(container_id)); + blocking_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&HidServiceWin::AddDeviceBlocking, - weak_factory_.GetWeakPtr(), task_runner_, device_path)); + FROM_HERE, base::BindOnce(&HidServiceWin::AddDeviceBlocking, + weak_factory_.GetWeakPtr(), task_runner_, + device_path, physical_device_id)); } void HidServiceWin::OnDeviceRemoved(const GUID& class_guid,
diff --git a/services/device/hid/hid_service_win.h b/services/device/hid/hid_service_win.h index 4965888..ac6745f 100644 --- a/services/device/hid/hid_service_win.h +++ b/services/device/hid/hid_service_win.h
@@ -59,7 +59,8 @@ static void AddDeviceBlocking( base::WeakPtr<HidServiceWin> service, scoped_refptr<base::SequencedTaskRunner> task_runner, - const base::string16& device_path); + const base::string16& device_path, + const std::string& physical_device_id); // DeviceMonitorWin::Observer implementation: void OnDeviceAdded(const GUID& class_guid,
diff --git a/services/network/public/cpp/host_resolver_mojom_traits.cc b/services/network/public/cpp/host_resolver_mojom_traits.cc index 8cd78a6..e8acf94 100644 --- a/services/network/public/cpp/host_resolver_mojom_traits.cc +++ b/services/network/public/cpp/host_resolver_mojom_traits.cc
@@ -284,6 +284,7 @@ case net::DnsQueryType::SRV: return DnsQueryType::SRV; case net::DnsQueryType::ESNI: + case net::DnsQueryType::INTEGRITY: NOTIMPLEMENTED(); return DnsQueryType::UNSPECIFIED; }
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 94edb93..fef7927 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -1310,7 +1310,8 @@ url.mojom.Origin source_origin, array<CorsOriginPattern> allow_patterns, array<CorsOriginPattern> block_patterns) => (); - // Sets extra CORS safelisted request headers names dynamically. + // Sets extra CORS safelisted request headers names dynamically. Headers need + // to be in lower case. SetCorsExtraSafelistedRequestHeaderNames( array<string> cors_extra_safelisted_request_header_names);
diff --git a/services/network/public/mojom/parsed_headers.mojom b/services/network/public/mojom/parsed_headers.mojom index 96c3d1e5..01f1bf8 100644 --- a/services/network/public/mojom/parsed_headers.mojom +++ b/services/network/public/mojom/parsed_headers.mojom
@@ -24,7 +24,7 @@ CrossOriginOpenerPolicy cross_origin_opener_policy; // The parsed value of the Origin-Isolation header. - bool origin_isolation; + bool origin_isolation = false; // The parsed Accept-CH from response headers. //
diff --git a/testing/buildbot/client.devtools-frontend.integration.json b/testing/buildbot/client.devtools-frontend.integration.json index 21bc481..1fc5425 100644 --- a/testing/buildbot/client.devtools-frontend.integration.json +++ b/testing/buildbot/client.devtools-frontend.integration.json
@@ -23,6 +23,27 @@ }, "test": "blink_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" + }, + { + "args": [ + "--gtest_filter=*DevTools*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "devtools_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" } ], "isolated_scripts": [
diff --git a/testing/buildbot/devtools-frontend.ci.json b/testing/buildbot/devtools-frontend.ci.json index 207e706..2932402 100644 --- a/testing/buildbot/devtools-frontend.ci.json +++ b/testing/buildbot/devtools-frontend.ci.json
@@ -23,6 +23,27 @@ }, "test": "blink_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" + }, + { + "args": [ + "--gtest_filter=*DevTools*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "devtools_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" } ], "isolated_scripts": [
diff --git a/testing/buildbot/devtools-frontend.try.json b/testing/buildbot/devtools-frontend.try.json index 0f6efdd..d3d4b0e 100644 --- a/testing/buildbot/devtools-frontend.try.json +++ b/testing/buildbot/devtools-frontend.try.json
@@ -2,6 +2,29 @@ "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, "devtools_frontend_linux_blink_light_rel": { + "gtest_tests": [ + { + "args": [ + "--gtest_filter=*DevTools*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "devtools_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + } + ], "isolated_scripts": [ { "args": [
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index d1f21cd..9306fc8 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -1167,6 +1167,18 @@ }, }, + 'devtools_browser_tests' : { + 'devtools_browser_tests': { + 'args': [ + '--gtest_filter=*DevTools*', + ], + 'swarming': { + 'shards': 1, + }, + 'test': 'browser_tests', + } + }, + 'devtools_webkit_isolated_scripts': { 'blink_web_tests': { # layout test failures are retried 3 times when '--test-list' is not @@ -4372,6 +4384,11 @@ 'cronet_sizes', ], + 'devtools_gtests': [ + 'devtools_browser_tests', + 'layout_ng_gtests', + ], + # BEGIN composition test suites used by the GPU bots 'gpu_angle_and_desktop_representative_perf_fyi_isolated_scripts': [
diff --git a/testing/buildbot/tryserver.devtools-frontend.json b/testing/buildbot/tryserver.devtools-frontend.json index 0f6efdd..d3d4b0e 100644 --- a/testing/buildbot/tryserver.devtools-frontend.json +++ b/testing/buildbot/tryserver.devtools-frontend.json
@@ -2,6 +2,29 @@ "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, "devtools_frontend_linux_blink_light_rel": { + "gtest_tests": [ + { + "args": [ + "--gtest_filter=*DevTools*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "devtools_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + } + ], "isolated_scripts": [ { "args": [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index adc4559f..a7ca430 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -4807,7 +4807,7 @@ 'linux-xenial', ], 'test_suites': { - 'gtest_tests': 'layout_ng_gtests', + 'gtest_tests': 'devtools_gtests', 'isolated_scripts': 'devtools_webkit_isolated_scripts', }, }, @@ -5106,6 +5106,7 @@ 'linux-xenial', ], 'test_suites': { + 'gtest_tests': 'devtools_browser_tests', 'isolated_scripts': 'devtools_webkit_isolated_scripts', }, },
diff --git a/testing/scripts/OWNERS b/testing/scripts/OWNERS index 365c06b..5fe2f0fa 100644 --- a/testing/scripts/OWNERS +++ b/testing/scripts/OWNERS
@@ -9,8 +9,11 @@ per-file check_static_initializers.py=thakis@chromium.org per-file check_static_initializers.py=thomasanderson@chromium.org -per-file run-wpt_tests.py=lpz@chromium.org +per-file run_wpt_tests.py=lpz@chromium.org per-file run_wpt_tests.py=robertma@chromium.org +per-file wpt_common.py=lpz@chromium.org +per-file wpt_common.py=robertma@chromium.org +per-file wpt_common.py=rmhasan@chromium.org per-file run_performance_tests.py=johnchen@chromium.org per-file run_performance_tests.py=wenbinzhang@google.com
diff --git a/testing/scripts/get_compile_targets.py b/testing/scripts/get_compile_targets.py index aed1c56..1e5fcf0 100755 --- a/testing/scripts/get_compile_targets.py +++ b/testing/scripts/get_compile_targets.py
@@ -30,7 +30,8 @@ if filename in ('common.py', 'get_compile_targets.py', 'gpu_integration_test_adapter.py', - 'sizes_common.py'): + 'sizes_common.py', + 'wpt_common.py'): continue with common.temporary_file() as tempfile_path:
diff --git a/testing/scripts/run_android_wpt.py b/testing/scripts/run_android_wpt.py index 500754f9..39d6468 100755 --- a/testing/scripts/run_android_wpt.py +++ b/testing/scripts/run_android_wpt.py
@@ -33,6 +33,7 @@ import sys import common +import wpt_common logger = logging.getLogger(__name__) @@ -60,9 +61,7 @@ from py_utils.tempfile_ext import NamedTemporaryDirectory -BLINK_TOOLS_DIR = os.path.join(SRC_DIR, 'third_party', 'blink', 'tools') -WEB_TESTS_DIR = os.path.join(BLINK_TOOLS_DIR, os.pardir, 'web_tests') -DEFAULT_WPT = os.path.join(WEB_TESTS_DIR, 'external', 'wpt', 'wpt') +DEFAULT_WPT = os.path.join(wpt_common.WEB_TESTS_DIR, 'external', 'wpt', 'wpt') ANDROID_WEBLAYER = 'android_weblayer' ANDROID_WEBVIEW = 'android_webview' @@ -107,7 +106,7 @@ return WPTClankAdapter(device) -class WPTAndroidAdapter(common.BaseIsolatedScriptArgsAdapter): +class WPTAndroidAdapter(wpt_common.BaseWptScriptAdapter): def __init__(self, device): self.pass_through_wpt_args = [] @@ -121,14 +120,6 @@ # its safe to parse the arguments and set self._options self.parse_args() - def generate_test_output_args(self, output): - return ['--log-chromium', output] - - def generate_sharding_args(self, total_shards, shard_index): - return ['--total-chunks=%d' % total_shards, - # shard_index is 0-based but WPT's this-chunk to be 1-based - '--this-chunk=%d' % (shard_index + 1)] - @property def rest_args(self): rest_args = super(WPTAndroidAdapter, self).rest_args @@ -178,14 +169,15 @@ metadata_builder_cmd = [ sys.executable, - os.path.join(BLINK_TOOLS_DIR, 'build_wpt_metadata.py'), + os.path.join(wpt_common.BLINK_TOOLS_DIR, 'build_wpt_metadata.py'), '--android-product', self.options.product, '--ignore-default-expectations', '--metadata-output-dir', self._metadata_dir, '--additional-expectations', - os.path.join(WEB_TESTS_DIR, 'android', 'AndroidWPTNeverFixTests') + os.path.join(wpt_common.WEB_TESTS_DIR, 'android', + 'AndroidWPTNeverFixTests') ] metadata_builder_cmd.extend(self._extra_metadata_builder_args()) return common.run_command(metadata_builder_cmd) @@ -205,24 +197,6 @@ # which was deleted self._metadata_dir = None - def do_post_test_run_tasks(self): - # Move json results into layout-test-results directory - results_dir = os.path.dirname(self.options.isolated_script_test_output) - layout_test_results = os.path.join(results_dir, 'layout-test-results') - os.mkdir(layout_test_results) - shutil.copyfile(self.options.isolated_script_test_output, - os.path.join(layout_test_results, 'full_results.json')) - # create full_results_jsonp.js file which is used to - # load results into the results viewer - with open(self.options.isolated_script_test_output, 'r') as full_results, \ - open(os.path.join( - layout_test_results, 'full_results_jsonp.js'), 'w') as json_js: - json_js.write('ADD_FULL_RESULTS(%s);' % full_results.read()) - # copy layout test results viewer to layout-test-results directory - shutil.copyfile( - os.path.join(WEB_TESTS_DIR, 'fast', 'harness', 'results.html'), - os.path.join(layout_test_results, 'results.html')) - def add_extra_arguments(self, parser): # TODO: |pass_through_args| are broke and need to be supplied by way of # --binary-arg". @@ -307,7 +281,7 @@ def _extra_metadata_builder_args(self): return [ '--additional-expectations', - os.path.join(WEB_TESTS_DIR, + os.path.join(wpt_common.WEB_TESTS_DIR, 'android', 'WeblayerWPTOverrideExpectations')] def add_extra_arguments(self, parser): @@ -350,7 +324,8 @@ return [ '--additional-expectations', os.path.join( - WEB_TESTS_DIR, 'android', 'WebviewWPTOverrideExpectations')] + wpt_common.WEB_TESTS_DIR, 'android', + 'WebviewWPTOverrideExpectations')] def add_extra_arguments(self, parser): super(WPTWebviewAdapter, self).add_extra_arguments(parser) @@ -384,7 +359,8 @@ def _extra_metadata_builder_args(self): return [ '--additional-expectations', - os.path.join(WEB_TESTS_DIR, 'android', 'ClankWPTOverrideExpectations')] + os.path.join(wpt_common.WEB_TESTS_DIR, 'android', + 'ClankWPTOverrideExpectations')] def add_extra_arguments(self, parser): super(WPTClankAdapter, self).add_extra_arguments(parser)
diff --git a/testing/scripts/run_android_wpt.pydeps b/testing/scripts/run_android_wpt.pydeps index 3f75fc0..a1ecc0e39 100644 --- a/testing/scripts/run_android_wpt.pydeps +++ b/testing/scripts/run_android_wpt.pydeps
@@ -6,6 +6,7 @@ //build/android/pylib/constants/host_paths.py //testing/scripts/common.py //testing/scripts/run_android_wpt.py +//testing/scripts/wpt_common.py //testing/test_env.py //testing/xvfb.py //third_party/catapult/common/py_utils/py_utils/__init__.py
diff --git a/testing/scripts/run_wpt_tests.py b/testing/scripts/run_wpt_tests.py index 86ca893..b777ba1 100755 --- a/testing/scripts/run_wpt_tests.py +++ b/testing/scripts/run_wpt_tests.py
@@ -16,26 +16,16 @@ import json import os -import shutil import sys import common +import wpt_common -BLINK_TOOLS_DIR = os.path.join(common.SRC_DIR, 'third_party', 'blink', 'tools') -WEB_TESTS_DIR = os.path.join(BLINK_TOOLS_DIR, os.pardir, 'web_tests') WPT_METADATA_DIR = "../../wpt_expectations_metadata/" WPT_OVERRIDE_EXPECTATIONS_PATH = ( "../../third_party/blink/web_tests/WPTOverrideExpectations") -class WPTTestAdapter(common.BaseIsolatedScriptArgsAdapter): - - def generate_test_output_args(self, output): - return ['--log-chromium', output] - - def generate_sharding_args(self, total_shards, shard_index): - return ['--total-chunks=%d' % total_shards, - # shard_index is 0-based but WPT's this-chunk to be 1-based - '--this-chunk=%d' % (shard_index + 1)] +class WPTTestAdapter(wpt_common.BaseWptScriptAdapter): @property def rest_args(self): @@ -88,33 +78,11 @@ ]) return rest_args - def do_post_test_run_tasks(self): - # Move json results into layout-test-results directory - results_dir = os.path.dirname(self.options.isolated_script_test_output) - layout_test_results = os.path.join(results_dir, 'layout-test-results') - if os.path.exists(layout_test_results): - shutil.rmtree(layout_test_results) - os.mkdir(layout_test_results) - shutil.copyfile(self.options.isolated_script_test_output, - os.path.join(layout_test_results, 'full_results.json')) - # create full_results_jsonp.js file which is used to - # load results into the results viewer - with open(self.options.isolated_script_test_output, 'r') \ - as full_results, \ - open(os.path.join( - layout_test_results, 'full_results_jsonp.js'), 'w') \ - as json_js: - json_js.write('ADD_FULL_RESULTS(%s);' % full_results.read()) - # copy layout test results viewer to layout-test-results directory - shutil.copyfile( - os.path.join(WEB_TESTS_DIR, 'fast', 'harness', 'results.html'), - os.path.join(layout_test_results, 'results.html')) - def main(): # First, generate WPT metadata files. common.run_command([ sys.executable, - os.path.join(BLINK_TOOLS_DIR, 'build_wpt_metadata.py'), + os.path.join(wpt_common.BLINK_TOOLS_DIR, 'build_wpt_metadata.py'), "--metadata-output-dir", WPT_METADATA_DIR, "--additional-expectations",
diff --git a/testing/scripts/wpt_common.py b/testing/scripts/wpt_common.py new file mode 100644 index 0000000..d1186a91 --- /dev/null +++ b/testing/scripts/wpt_common.py
@@ -0,0 +1,47 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import shutil + +import common + +BLINK_TOOLS_DIR = os.path.join(common.SRC_DIR, 'third_party', 'blink', 'tools') +WEB_TESTS_DIR = os.path.join(BLINK_TOOLS_DIR, os.pardir, 'web_tests') + +class BaseWptScriptAdapter(common.BaseIsolatedScriptArgsAdapter): + """The base class for script adapters that use wptrunner to execute web + platform tests. This contains any code shared between these scripts, such + as integrating output with the results viewer. Subclasses contain other + (usually platform-specific) logic.""" + + def generate_test_output_args(self, output): + return ['--log-chromium', output] + + def generate_sharding_args(self, total_shards, shard_index): + return ['--total-chunks=%d' % total_shards, + # shard_index is 0-based but WPT's this-chunk to be 1-based + '--this-chunk=%d' % (shard_index + 1)] + + def do_post_test_run_tasks(self): + # Move json results into layout-test-results directory + results_dir = os.path.dirname(self.options.isolated_script_test_output) + layout_test_results = os.path.join(results_dir, 'layout-test-results') + if os.path.exists(layout_test_results): + shutil.rmtree(layout_test_results) + os.mkdir(layout_test_results) + shutil.copyfile(self.options.isolated_script_test_output, + os.path.join(layout_test_results, 'full_results.json')) + # create full_results_jsonp.js file which is used to + # load results into the results viewer + with open(self.options.isolated_script_test_output, 'r') \ + as full_results, \ + open(os.path.join( + layout_test_results, 'full_results_jsonp.js'), 'w') \ + as json_js: + json_js.write('ADD_FULL_RESULTS(%s);' % full_results.read()) + # copy layout test results viewer to layout-test-results directory + shutil.copyfile( + os.path.join(WEB_TESTS_DIR, 'fast', 'harness', 'results.html'), + os.path.join(layout_test_results, 'results.html')) \ No newline at end of file
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b3bc6af7..2473d6e 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1479,7 +1479,10 @@ "name": "Enabled", "params": { "ModelNum": "4" - } + }, + "enable_features": [ + "ClientSideDetectionModel" + ] } ] } @@ -2827,6 +2830,21 @@ ] } ], + "IOSCrashReportBreadcrumbs": [ + { + "platforms": [ + "ios" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "LogBreadcrumbs" + ] + } + ] + } + ], "IOSEmbedderBlockRestoreUrl": [ { "platforms": [ @@ -3493,6 +3511,21 @@ ] } ], + "MacCustomPaperSize": [ + { + "platforms": [ + "mac" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "EnableCustomMacPaperSizes" + ] + } + ] + } + ], "MacSystemMediaPermissionsInfoUI": [ { "platforms": [ @@ -4406,7 +4439,7 @@ ], "experiments": [ { - "name": "WithEnhancedExperiment_20200519", + "name": "WithEnhancedExperiment_20200603", "params": { "DefaultInIncognito": "true" }, @@ -5098,6 +5131,21 @@ ] } ], + "RespectMacLCDTextSetting": [ + { + "platforms": [ + "mac" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "RespectMacLCDTextSetting" + ] + } + ] + } + ], "RevampedContextMenu": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index bf7ccf3..60476ff 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -412,6 +412,11 @@ const base::Feature kCompositeCrossOriginIframes{ "CompositeCrossOriginIframes", base::FEATURE_DISABLED_BY_DEFAULT}; +// When enabled, enforces new interoperable semantics for 3D transforms. +// See crbug.com/1008483. +const base::Feature kTransformInterop{"TransformInterop", + base::FEATURE_DISABLED_BY_DEFAULT}; + // When enabled, beacons (and friends) have ResourceLoadPriority::kLow, // not ResourceLoadPriority::kVeryLow. const base::Feature kSetLowPriorityForBeacon{"SetLowPriorityForBeacon", @@ -478,6 +483,12 @@ const base::Feature kBlockHTMLParserOnStyleSheets{ "BlockHTMLParserOnStyleSheets", base::FEATURE_DISABLED_BY_DEFAULT}; +// Kill switch for the new <link disabled> behavior. +// TODO(crbug.com/1087043): Remove this once the feature has +// landed and no compat issues are reported. +const base::Feature kLinkDisabledNewSpecBehavior{ + "LinkDisabledNewSpecBehavior", base::FEATURE_ENABLED_BY_DEFAULT}; + // Slightly delays rendering if there are fonts being preloaded, so that // they don't miss the first paint if they can be loaded fast enough (e.g., // from the disk cache) @@ -584,5 +595,9 @@ const char kSkipTouchEventFilterFilteringProcessParamValueBrowserAndRenderer[] = "browser_and_renderer"; +// Improves support for WebXR on computers with multiple GPUs. +const base::Feature kWebXrMultiGpu{"WebXRMultiGpu", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features } // namespace blink
diff --git a/third_party/blink/common/loader/throttling_url_loader.cc b/third_party/blink/common/loader/throttling_url_loader.cc index 878131c..e81bfc3 100644 --- a/third_party/blink/common/loader/throttling_url_loader.cc +++ b/third_party/blink/common/loader/throttling_url_loader.cc
@@ -12,6 +12,7 @@ #include "net/http/http_status_code.h" #include "net/http/http_util.h" #include "net/url_request/redirect_util.h" +#include "services/network/public/cpp/cors/cors.h" #include "services/network/public/cpp/features.h" #include "services/network/public/mojom/url_response_head.mojom.h" @@ -28,6 +29,43 @@ } } +#if DCHECK_IS_ON() +void CheckThrottleWillNotCauseCorsPreflight( + const std::set<std::string>& initial_headers, + const std::set<std::string>& initial_cors_exempt_headers, + const net::HttpRequestHeaders& headers, + const net::HttpRequestHeaders& cors_exempt_headers, + const std::vector<std::string> cors_exempt_header_list) { + base::flat_set<std::string> cors_exempt_header_flat_set( + cors_exempt_header_list); + for (auto& header : headers.GetHeaderVector()) { + if (initial_headers.find(header.key) == initial_headers.end() && + !network::cors::IsCorsSafelistedHeader(header.key, header.value)) { + bool is_cors_exempt = cors_exempt_header_flat_set.count(header.key); + NOTREACHED() + << "Throttle added cors unsafe header " << header.key + << (is_cors_exempt + ? " . Header is cors exempt so should have " + "been added to RequestHeaders::cors_exempt_headers " + "instead of " + "of RequestHeaders::cors_exempt_headers." + : ""); + } + } + + for (auto& header : cors_exempt_headers.GetHeaderVector()) { + if (cors_exempt_header_flat_set.count(header.key) == 0 && + initial_cors_exempt_headers.find(header.key) == + initial_cors_exempt_headers.end()) { + NOTREACHED() << "Throttle added cors exempt header " << header.key + << " but it wasn't configured as cors exempt by the " + "browser. See " + << "StoragePartition::UpdateCorsMitigationList()."; + } + } +} +#endif + } // namespace const char ThrottlingURLLoader::kFollowRedirectReason[] = "FollowRedirect"; @@ -173,13 +211,16 @@ int32_t in_request_id, uint32_t in_options, network::ResourceRequest* in_url_request, - scoped_refptr<base::SingleThreadTaskRunner> in_task_runner) + scoped_refptr<base::SingleThreadTaskRunner> in_task_runner, + base::Optional<std::vector<std::string>> in_cors_exempt_header_list) : url_loader_factory(std::move(in_url_loader_factory)), routing_id(in_routing_id), request_id(in_request_id), options(in_options), url_request(*in_url_request), - task_runner(std::move(in_task_runner)) {} + task_runner(std::move(in_task_runner)) { + cors_exempt_header_list = std::move(in_cors_exempt_header_list); +} ThrottlingURLLoader::StartInfo::~StartInfo() = default; @@ -212,11 +253,13 @@ network::ResourceRequest* url_request, network::mojom::URLLoaderClient* client, const net::NetworkTrafficAnnotationTag& traffic_annotation, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + base::Optional<std::vector<std::string>> cors_exempt_header_list) { std::unique_ptr<ThrottlingURLLoader> loader(new ThrottlingURLLoader( std::move(throttles), client, traffic_annotation)); loader->Start(std::move(factory), routing_id, request_id, options, - url_request, std::move(task_runner)); + url_request, std::move(task_runner), + std::move(cors_exempt_header_list)); return loader; } @@ -351,7 +394,8 @@ int32_t request_id, uint32_t options, network::ResourceRequest* url_request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + base::Optional<std::vector<std::string>> cors_exempt_header_list) { DCHECK_EQ(DEFERRED_NONE, deferred_stage_); DCHECK(!loader_completed_); @@ -362,7 +406,28 @@ for (auto& entry : throttles_) { auto* throttle = entry.throttle.get(); bool throttle_deferred = false; + +#if DCHECK_IS_ON() + std::set<std::string> initial_headers, initial_cors_exempt_headers; + if (cors_exempt_header_list) { + for (auto& header : url_request->headers.GetHeaderVector()) + initial_headers.insert(header.key); + + for (auto& header : url_request->cors_exempt_headers.GetHeaderVector()) + initial_cors_exempt_headers.insert(header.key); + } +#endif + throttle->WillStartRequest(url_request, &throttle_deferred); + +#if DCHECK_IS_ON() + if (cors_exempt_header_list) { + CheckThrottleWillNotCauseCorsPreflight( + initial_headers, initial_cors_exempt_headers, url_request->headers, + url_request->cors_exempt_headers, *cors_exempt_header_list); + } +#endif + if (original_url_ != url_request->url) { DCHECK(throttle_will_start_redirect_url_.is_empty()) << "ThrottlingURLLoader doesn't support multiple throttles " @@ -384,9 +449,9 @@ } } - start_info_ = - std::make_unique<StartInfo>(factory, routing_id, request_id, options, - url_request, std::move(task_runner)); + start_info_ = std::make_unique<StartInfo>( + factory, routing_id, request_id, options, url_request, + std::move(task_runner), std::move(cors_exempt_header_list)); if (deferred) deferred_stage_ = DEFERRED_START; else @@ -611,6 +676,19 @@ throttle->WillRedirectRequest( &redirect_info_copy, *response_head, &throttle_deferred, &removed_headers, &modified_headers, &modified_cors_exempt_headers); + + if (!weak_ptr) + return; + +#if DCHECK_IS_ON() + if (start_info_->cors_exempt_header_list) { + CheckThrottleWillNotCauseCorsPreflight( + std::set<std::string>(), std::set<std::string>(), modified_headers, + modified_cors_exempt_headers, + *start_info_->cors_exempt_header_list); + } +#endif + if (redirect_info_copy.new_url != redirect_info.new_url) { DCHECK(throttle_will_redirect_redirect_url_.is_empty()) << "ThrottlingURLLoader doesn't support multiple throttles " @@ -618,8 +696,6 @@ throttle_will_redirect_redirect_url_ = redirect_info_copy.new_url; } - if (!weak_ptr) - return; if (!HandleThrottleResult(throttle, throttle_deferred, &deferred)) return;
diff --git a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc index 0d5f50c..e558b43 100644 --- a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc +++ b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
@@ -103,6 +103,8 @@ return "SpeechRecognizer"; case WebSchedulerTrackedFeature::kIdleManager: return "IdleManager"; + case WebSchedulerTrackedFeature::kPaymentManager: + return "PaymentManager"; } }
diff --git a/third_party/blink/public/blink_resources.grd b/third_party/blink/public/blink_resources.grd index ed6034a..709b4d8 100644 --- a/third_party/blink/public/blink_resources.grd +++ b/third_party/blink/public/blink_resources.grd
@@ -31,12 +31,6 @@ <include name="IDR_UASTYLE_XHTMLMP_CSS" file="../renderer/core/css/xhtmlmp.css" type="BINDATA" compress="gzip"/> <include name="IDR_UASTYLE_VIEWPORT_ANDROID_CSS" file="../renderer/core/css/viewportAndroid.css" type="BINDATA" compress="gzip"/> <include name="IDR_UASTYLE_VIEWPORT_TELEVISION_CSS" file="../renderer/core/css/viewportTelevision.css" type="BINDATA" compress="gzip"/> - <include name="IDR_INSPECT_TOOL_COMMON_JS" file="../renderer/core/inspector/inspect_tool_common.js" type="BINDATA" compress="gzip"/> - <include name="IDR_INSPECT_TOOL_COMMON_CSS" file="../renderer/core/inspector/inspect_tool_common.css" type="BINDATA" compress="gzip"/> - <include name="IDR_INSPECT_TOOL_DISTANCES_HTML" file="../renderer/core/inspector/inspect_tool_distances.html" type="BINDATA" compress="gzip"/> - <include name="IDR_INSPECT_TOOL_PAUSED_HTML" file="../renderer/core/inspector/inspect_tool_paused.html" type="BINDATA" compress="gzip"/> - <include name="IDR_INSPECT_TOOL_VIEWPORT_SIZE_HTML" file="../renderer/core/inspector/inspect_tool_viewport_size.html" type="BINDATA" compress="gzip"/> - <include name="IDR_INSPECT_TOOL_SCREENSHOT_HTML" file="../renderer/core/inspector/inspect_tool_screenshot.html" type="BINDATA" compress="gzip"/> <include name="IDR_DOCUMENTXMLTREEVIEWER_CSS" file="../renderer/core/xml/DocumentXMLTreeViewer.css" type="BINDATA" compress="gzip"/> <include name="IDR_DOCUMENTXMLTREEVIEWER_JS" file="../renderer/core/xml/DocumentXMLTreeViewer.js" type="BINDATA" compress="gzip"/> <include name="IDR_VALIDATION_BUBBLE_ICON" file="../renderer/core/html/forms/resources/input_alert.svg" type="BINDATA" compress="gzip"/>
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 8b9dcba..a593f56 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -128,6 +128,8 @@ BLINK_COMMON_EXPORT extern const base::Feature kCompositeCrossOriginIframes; +BLINK_COMMON_EXPORT extern const base::Feature kTransformInterop; + BLINK_COMMON_EXPORT extern const base::Feature kSubresourceRedirect; BLINK_COMMON_EXPORT extern const base::Feature kSetLowPriorityForBeacon; @@ -156,6 +158,8 @@ BLINK_COMMON_EXPORT extern const base::Feature kBlockHTMLParserOnStyleSheets; +BLINK_COMMON_EXPORT extern const base::Feature kLinkDisabledNewSpecBehavior; + BLINK_COMMON_EXPORT extern const base::Feature kFontPreloadingDelaysRendering; BLINK_COMMON_EXPORT extern const base::FeatureParam<int> kFontPreloadingDelaysRenderingParam; @@ -243,6 +247,8 @@ extern const char kSkipTouchEventFilterFilteringProcessParamValueBrowserAndRenderer[]; +BLINK_COMMON_EXPORT extern const base::Feature kWebXrMultiGpu; + } // namespace features } // namespace blink
diff --git a/third_party/blink/public/common/loader/throttling_url_loader.h b/third_party/blink/public/common/loader/throttling_url_loader.h index 1ce0af50..1ac750d 100644 --- a/third_party/blink/public/common/loader/throttling_url_loader.h +++ b/third_party/blink/public/common/loader/throttling_url_loader.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/strings/string_piece.h" #include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -52,7 +53,9 @@ network::ResourceRequest* url_request, network::mojom::URLLoaderClient* client, const net::NetworkTrafficAnnotationTag& traffic_annotation, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + base::Optional<std::vector<std::string>> cors_exempt_header_list = + base::nullopt); ~ThrottlingURLLoader() override; @@ -112,7 +115,8 @@ int32_t request_id, uint32_t options, network::ResourceRequest* url_request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + base::Optional<std::vector<std::string>> cors_exempt_header_list); void StartNow(); void RestartWithFlagsNow(); @@ -219,7 +223,8 @@ int32_t in_request_id, uint32_t in_options, network::ResourceRequest* in_url_request, - scoped_refptr<base::SingleThreadTaskRunner> in_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> in_task_runner, + base::Optional<std::vector<std::string>> in_cors_exempt_header_list); ~StartInfo(); scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory; @@ -230,6 +235,7 @@ network::ResourceRequest url_request; // |task_runner| is used to set up |client_receiver_|. scoped_refptr<base::SingleThreadTaskRunner> task_runner; + base::Optional<std::vector<std::string>> cors_exempt_header_list; }; // Holds any info needed to start or restart the request. Used when start is // deferred or when FollowRedirectForcingRestart() is called.
diff --git a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h index d0ffeb7..75762ca 100644 --- a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h +++ b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
@@ -91,9 +91,10 @@ kPortal = 46, kSpeechRecognizer = 47, kIdleManager = 48, + kPaymentManager = 49, // NB: This enum is used in a bitmask, so kMaxValue must be less than 64. - kMaxValue = kIdleManager + kMaxValue = kPaymentManager }; static_assert(static_cast<uint32_t>(WebSchedulerTrackedFeature::kMaxValue) < 64,
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index ae63a23..e3fa78f 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -7075,6 +7075,11 @@ parameters # If specified, disposes this context when debugging session disconnects. optional boolean disposeOnDetach + # Proxy server, similar to the one passed to --proxy-server + optional string proxyServer + # Proxy bypass list, similar to the one passed to --proxy-bypass-list + optional string proxyBypassList + returns # The id of the context created. Browser.BrowserContextID browserContextId
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index bd57df9..4bd4c4a 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -173,6 +173,8 @@ BLINK_PLATFORM_EXPORT static void EnableWebAuthenticationGetAssertionFeaturePolicy(bool); BLINK_PLATFORM_EXPORT static void EnableWebBluetooth(bool); + BLINK_PLATFORM_EXPORT static void + EnableWebBluetoothRemoteCharacteristicNewWriteValue(bool); BLINK_PLATFORM_EXPORT static void EnableWebBluetoothScanning(bool); BLINK_PLATFORM_EXPORT static void EnableWebGL2ComputeContext(bool); BLINK_PLATFORM_EXPORT static void EnableWebGLDraftExtensions(bool); @@ -241,6 +243,8 @@ BLINK_PLATFORM_EXPORT static void EnableInstalledApp(bool); + BLINK_PLATFORM_EXPORT static void EnableTransformInterop(bool); + private: WebRuntimeFeatures(); };
diff --git a/third_party/blink/public/web/web_shared_worker.h b/third_party/blink/public/web/web_shared_worker.h index c2dd48dc..a9f68c0f 100644 --- a/third_party/blink/public/web/web_shared_worker.h +++ b/third_party/blink/public/web/web_shared_worker.h
@@ -34,12 +34,14 @@ #include <memory> #include "base/unguessable_token.h" -#include "mojo/public/cpp/system/message_pipe.h" #include "services/network/public/mojom/content_security_policy.mojom-shared.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" #include "services/network/public/mojom/ip_address_space.mojom-shared.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" +#include "third_party/blink/public/mojom/browser_interface_broker.mojom-shared.h" #include "third_party/blink/public/mojom/script/script_type.mojom-shared.h" +#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-shared.h" +#include "third_party/blink/public/platform/cross_variant_mojo_util.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_security_origin.h" @@ -75,8 +77,10 @@ const WebFetchClientSettingsObject& outside_fetch_client_settings_object, const base::UnguessableToken& appcache_host_id, const base::UnguessableToken& devtools_worker_token, - mojo::ScopedMessagePipeHandle content_settings_handle, - mojo::ScopedMessagePipeHandle browser_interface_broker, + CrossVariantMojoRemote<mojom::WorkerContentSettingsProxyInterfaceBase> + content_settings, + CrossVariantMojoRemote<mojom::BrowserInterfaceBrokerInterfaceBase> + browser_interface_broker, bool pause_worker_context_on_start) = 0; // Sends a connect event to the SharedWorker context.
diff --git a/third_party/blink/public/web/web_shared_worker_client.h b/third_party/blink/public/web/web_shared_worker_client.h index 1c52096..81f8fab 100644 --- a/third_party/blink/public/web/web_shared_worker_client.h +++ b/third_party/blink/public/web/web_shared_worker_client.h
@@ -31,8 +31,9 @@ #ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SHARED_WORKER_CLIENT_H_ #define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SHARED_WORKER_CLIENT_H_ -#include "mojo/public/cpp/system/message_pipe.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-shared.h" #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h" +#include "third_party/blink/public/platform/cross_variant_mojo_util.h" #include "third_party/blink/public/platform/web_content_settings_client.h" #include "third_party/blink/public/platform/web_worker_fetch_context.h" @@ -50,8 +51,10 @@ virtual void WorkerContextClosed() = 0; virtual void WorkerContextDestroyed() = 0; virtual void WorkerReadyForInspection( - mojo::ScopedMessagePipeHandle devtools_agent_ptr_info, - mojo::ScopedMessagePipeHandle devtools_agent_host_request) {} + CrossVariantMojoRemote<mojom::DevToolsAgentInterfaceBase> + devtools_agent_remote, + CrossVariantMojoReceiver<mojom::DevToolsAgentHostInterfaceBase> + devtools_agent_host_receiver) {} virtual void WorkerScriptLoadFailed(const std::string& error_message) = 0; virtual void WorkerScriptEvaluated(bool success) = 0;
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 4781f8c12..9436d19 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -380,6 +380,7 @@ "//third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl", "//third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator_entry.idl", "//third_party/blink/renderer/modules/native_file_system/window_native_file_system.idl", + "//third_party/blink/renderer/modules/native_file_system/worker_global_scope_native_file_system.idl", "//third_party/blink/renderer/modules/native_file_system/write_params.idl", "//third_party/blink/renderer/modules/native_io/native_io_file.idl", "//third_party/blink/renderer/modules/native_io/native_io_file_sync.idl",
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc index 95efbed4..12a68121 100644 --- a/third_party/blink/renderer/core/animation/animation.cc +++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -1833,15 +1833,20 @@ UpdateFinishedState(UpdateType::kContinuous, NotificationType::kAsync); if (content_) { - base::Optional<double> inherited_time = idle || !timeline_->currentTime() - ? base::nullopt - : CurrentTimeInternal(); + base::Optional<double> inherited_time; + base::Optional<TimelinePhase> timeline_phase; - // Special case for end-exclusivity when playing backwards. - if (inherited_time == 0 && EffectivePlaybackRate() < 0) - inherited_time = -1; + if (!idle) { + inherited_time = CurrentTimeInternal(); + // Special case for end-exclusivity when playing backwards. + if (inherited_time == 0 && EffectivePlaybackRate() < 0) + inherited_time = -1; - content_->UpdateInheritedTime(inherited_time, reason); + timeline_phase = timeline_->Phase(); + } + + content_->UpdateInheritedTime(inherited_time, timeline_phase, reason); + // After updating the animation time if the animation is no longer current // blink will no longer composite the element (see // CompositingReasonFinder::RequiresCompositingFor*Animation). We cancel any
diff --git a/third_party/blink/renderer/core/animation/animation_effect.cc b/third_party/blink/renderer/core/animation/animation_effect.cc index dd0c9b4..286f2d3 100644 --- a/third_party/blink/renderer/core/animation/animation_effect.cc +++ b/third_party/blink/renderer/core/animation/animation_effect.cc
@@ -34,6 +34,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h" #include "third_party/blink/renderer/core/animation/animation.h" #include "third_party/blink/renderer/core/animation/animation_input_helpers.h" +#include "third_party/blink/renderer/core/animation/animation_timeline.h" #include "third_party/blink/renderer/core/animation/keyframe_effect.h" #include "third_party/blink/renderer/core/animation/timing_calculations.h" #include "third_party/blink/renderer/core/animation/timing_input.h" @@ -107,8 +108,32 @@ InvalidateAndNotifyOwner(); } -void AnimationEffect::UpdateInheritedTime(base::Optional<double> inherited_time, - TimingUpdateReason reason) const { +base::Optional<Timing::Phase> TimelinePhaseToTimingPhase( + base::Optional<TimelinePhase> phase) { + base::Optional<Timing::Phase> result; + if (phase) { + switch (phase.value()) { + case TimelinePhase::kBefore: + result = Timing::Phase::kPhaseBefore; + break; + case TimelinePhase::kActive: + result = Timing::Phase::kPhaseActive; + break; + case TimelinePhase::kAfter: + result = Timing::Phase::kPhaseAfter; + break; + case TimelinePhase::kInactive: + // Timing::Phase does not have an inactive phase. + break; + } + } + return result; +} + +void AnimationEffect::UpdateInheritedTime( + base::Optional<double> inherited_time, + base::Optional<TimelinePhase> inherited_timeline_phase, + TimingUpdateReason reason) const { base::Optional<double> playback_rate = base::nullopt; if (GetAnimation()) playback_rate = GetAnimation()->playbackRate(); @@ -117,15 +142,21 @@ ? Timing::AnimationDirection::kBackwards : Timing::AnimationDirection::kForwards; + base::Optional<Timing::Phase> timeline_phase = + TimelinePhaseToTimingPhase(inherited_timeline_phase); + bool needs_update = needs_update_ || last_update_time_ != inherited_time || - (owner_ && owner_->EffectSuppressed()); + (owner_ && owner_->EffectSuppressed()) || + last_update_phase_ != timeline_phase; needs_update_ = false; last_update_time_ = inherited_time; + last_update_phase_ = timeline_phase; const base::Optional<double> local_time = inherited_time; if (needs_update) { Timing::CalculatedTiming calculated = SpecifiedTiming().CalculateTimings( - local_time, direction, IsA<KeyframeEffect>(this), playback_rate); + local_time, timeline_phase, direction, IsA<KeyframeEffect>(this), + playback_rate); const bool was_canceled = calculated.phase != calculated_.phase && calculated.phase == Timing::kPhaseNone;
diff --git a/third_party/blink/renderer/core/animation/animation_effect.h b/third_party/blink/renderer/core/animation/animation_effect.h index 82238e4..a35b604b 100644 --- a/third_party/blink/renderer/core/animation/animation_effect.h +++ b/third_party/blink/renderer/core/animation/animation_effect.h
@@ -42,6 +42,7 @@ namespace blink { class Animation; +enum class TimelinePhase; class AnimationEffectOwner; class EffectTiming; class ComputedEffectTiming; @@ -134,6 +135,7 @@ // it will (if necessary) recalculate timings and (if necessary) call // updateChildrenAndEffects. void UpdateInheritedTime(base::Optional<double> inherited_time, + base::Optional<TimelinePhase> inherited_phase, TimingUpdateReason) const; void Invalidate() const { needs_update_ = true; } void InvalidateAndNotifyOwner() const; @@ -167,6 +169,7 @@ mutable Timing::CalculatedTiming calculated_; mutable bool needs_update_; mutable base::Optional<double> last_update_time_; + mutable base::Optional<Timing::Phase> last_update_phase_; double cancel_time_; const Timing::CalculatedTiming& EnsureCalculated() const; };
diff --git a/third_party/blink/renderer/core/animation/animation_effect_test.cc b/third_party/blink/renderer/core/animation/animation_effect_test.cc index 70fe11d2..027ceaa 100644 --- a/third_party/blink/renderer/core/animation/animation_effect_test.cc +++ b/third_party/blink/renderer/core/animation/animation_effect_test.cc
@@ -86,7 +86,8 @@ void UpdateInheritedTime(double time, TimingUpdateReason reason) { event_delegate_->Reset(); - AnimationEffect::UpdateInheritedTime(time, reason); + AnimationEffect::UpdateInheritedTime( + time, /*inherited_phase*/ base::nullopt, reason); } void UpdateChildrenAndEffects() const override {}
diff --git a/third_party/blink/renderer/core/animation/animation_timeline.h b/third_party/blink/renderer/core/animation/animation_timeline.h index 70ae26b2..2d68a4a 100644 --- a/third_party/blink/renderer/core/animation/animation_timeline.h +++ b/third_party/blink/renderer/core/animation/animation_timeline.h
@@ -6,7 +6,6 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_TIMELINE_H_ #include "third_party/blink/renderer/core/animation/animation.h" -#include "third_party/blink/renderer/core/animation/animation_effect.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" @@ -39,6 +38,7 @@ base::Optional<double> CurrentTimeSeconds(); String phase(); + TimelinePhase Phase() { return CurrentPhaseAndTime().phase; } virtual bool IsDocumentTimeline() const { return false; } virtual bool IsScrollTimeline() const { return false; }
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc index 775b7f7..8b5ccaa 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.cc +++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -449,7 +449,7 @@ : current_iteration; const double iteration_start = effect.SpecifiedTiming().iteration_start; const AnimationTimeDelta iteration_duration = - effect.SpecifiedTiming().iteration_duration.value(); + effect.SpecifiedTiming().IterationDuration(); return iteration_duration * (iteration_boundary - iteration_start); } @@ -1527,9 +1527,8 @@ previous_phase_ == Timing::kPhaseAfter) { // If the transition is progressing backwards it is considered to have // started at the end position. - DCHECK(animation_node.SpecifiedTiming().iteration_duration.has_value()); EnqueueEvent(event_type_names::kTransitionstart, - animation_node.SpecifiedTiming().iteration_duration.value()); + animation_node.SpecifiedTiming().IterationDuration()); } } @@ -1538,9 +1537,8 @@ (previous_phase_ == Timing::kPhaseActive || previous_phase_ == Timing::kPhaseBefore || previous_phase_ == Timing::kPhaseNone)) { - DCHECK(animation_node.SpecifiedTiming().iteration_duration.has_value()); EnqueueEvent(event_type_names::kTransitionend, - animation_node.SpecifiedTiming().iteration_duration.value()); + animation_node.SpecifiedTiming().IterationDuration()); } else if (current_phase == Timing::kPhaseBefore && (previous_phase_ == Timing::kPhaseActive || previous_phase_ == Timing::kPhaseAfter)) {
diff --git a/third_party/blink/renderer/core/animation/document_animations_test.cc b/third_party/blink/renderer/core/animation/document_animations_test.cc index f1d156c2..e3b5a672 100644 --- a/third_party/blink/renderer/core/animation/document_animations_test.cc +++ b/third_party/blink/renderer/core/animation/document_animations_test.cc
@@ -22,6 +22,7 @@ public: MockAnimationTimeline(Document* document) : AnimationTimeline(document) {} + MOCK_METHOD0(Phase, TimelinePhase()); MOCK_CONST_METHOD0(IsActive, bool()); MOCK_METHOD0(ZeroTimeInSeconds, double()); MOCK_METHOD0(InitialStartTimeForAnimations,
diff --git a/third_party/blink/renderer/core/animation/inert_effect.cc b/third_party/blink/renderer/core/animation/inert_effect.cc index 68d011a..a3c29bf 100644 --- a/third_party/blink/renderer/core/animation/inert_effect.cc +++ b/third_party/blink/renderer/core/animation/inert_effect.cc
@@ -44,7 +44,7 @@ inherited_time_(inherited_time) {} void InertEffect::Sample(HeapVector<Member<Interpolation>>& result) const { - UpdateInheritedTime(inherited_time_, kTimingUpdateOnDemand); + UpdateInheritedTime(inherited_time_, base::nullopt, kTimingUpdateOnDemand); if (!IsInEffect()) { result.clear(); return;
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect.cc b/third_party/blink/renderer/core/animation/keyframe_effect.cc index 2a7aefe..7e7dc66 100644 --- a/third_party/blink/renderer/core/animation/keyframe_effect.cc +++ b/third_party/blink/renderer/core/animation/keyframe_effect.cc
@@ -591,9 +591,10 @@ case Timing::kPhaseNone: return AnimationTimeDelta::Max(); case Timing::kPhaseBefore: - DCHECK_GE(start_time, local_time.value()); - return forwards ? AnimationTimeDelta::FromSecondsD(start_time - - local_time.value()) + // Return value is clamped at 0 to prevent unexpected results that could + // be caused by returning negative values. + return forwards ? AnimationTimeDelta::FromSecondsD(std::max<double>( + start_time - local_time.value(), 0)) : AnimationTimeDelta::Max(); case Timing::kPhaseActive: if (forwards) {
diff --git a/third_party/blink/renderer/core/animation/timing.cc b/third_party/blink/renderer/core/animation/timing.cc index ea3e60d2..27fa627 100644 --- a/third_party/blink/renderer/core/animation/timing.cc +++ b/third_party/blink/renderer/core/animation/timing.cc
@@ -153,13 +153,15 @@ Timing::CalculatedTiming Timing::CalculateTimings( base::Optional<double> local_time, + base::Optional<Phase> timeline_phase, AnimationDirection animation_direction, bool is_keyframe_effect, base::Optional<double> playback_rate) const { const double active_duration = ActiveDuration(); - const Timing::Phase current_phase = - CalculatePhase(active_duration, local_time, animation_direction, *this); + Timing::Phase current_phase = CalculatePhase( + active_duration, local_time, timeline_phase, animation_direction, *this); + const base::Optional<AnimationTimeDelta> active_time = CalculateActiveTime(active_duration, ResolvedFillMode(is_keyframe_effect), local_time, current_phase, *this);
diff --git a/third_party/blink/renderer/core/animation/timing.h b/third_party/blink/renderer/core/animation/timing.h index 18cfd212..300f8987c 100644 --- a/third_party/blink/renderer/core/animation/timing.h +++ b/third_party/blink/renderer/core/animation/timing.h
@@ -44,6 +44,7 @@ class EffectTiming; class ComputedEffectTiming; +enum class TimelinePhase; struct CORE_EXPORT Timing { USING_FAST_MALLOC(Timing); @@ -174,6 +175,7 @@ }; CalculatedTiming CalculateTimings(base::Optional<double> local_time, + base::Optional<Phase> timeline_phase, AnimationDirection animation_direction, bool is_keyframe_effect, base::Optional<double> playback_rate) const;
diff --git a/third_party/blink/renderer/core/animation/timing_calculations.h b/third_party/blink/renderer/core/animation/timing_calculations.h index c33ac8cf..731b461 100644 --- a/third_party/blink/renderer/core/animation/timing_calculations.h +++ b/third_party/blink/renderer/core/animation/timing_calculations.h
@@ -73,10 +73,12 @@ } // https://drafts.csswg.org/web-animations-1/#animation-effect-phases-and-states -static inline Timing::Phase CalculatePhase(double active_duration, - base::Optional<double> local_time, - Timing::AnimationDirection direction, - const Timing& specified) { +static inline Timing::Phase CalculatePhase( + double active_duration, + base::Optional<double> local_time, + base::Optional<Timing::Phase> timeline_phase, + Timing::AnimationDirection direction, + const Timing& specified) { DCHECK_GE(active_duration, 0); if (!local_time) return Timing::kPhaseNone; @@ -85,6 +87,8 @@ double before_active_boundary_time = std::max(std::min(specified.start_delay, end_time), 0.0); if (local_time.value() < before_active_boundary_time || + (local_time.value() == before_active_boundary_time && timeline_phase && + timeline_phase.value() == Timing::kPhaseBefore) || (local_time.value() == before_active_boundary_time && direction == Timing::AnimationDirection::kBackwards)) { return Timing::kPhaseBefore; @@ -92,6 +96,8 @@ double active_after_boundary_time = std::max( std::min(specified.start_delay + active_duration, end_time), 0.0); if (local_time > active_after_boundary_time || + (local_time.value() == active_after_boundary_time && timeline_phase && + timeline_phase.value() == Timing::kPhaseAfter) || (local_time == active_after_boundary_time && direction == Timing::AnimationDirection::kForwards)) { return Timing::kPhaseAfter;
diff --git a/third_party/blink/renderer/core/animation/timing_test.cc b/third_party/blink/renderer/core/animation/timing_test.cc index 485daea9..84e0d7fc 100644 --- a/third_party/blink/renderer/core/animation/timing_test.cc +++ b/third_party/blink/renderer/core/animation/timing_test.cc
@@ -16,8 +16,9 @@ Timing::AnimationDirection animation_direction = playback_rate < 0 ? Timing::AnimationDirection::kBackwards : Timing::AnimationDirection::kForwards; - return timing_.CalculateTimings(local_time, animation_direction, - is_keyframe_effect, playback_rate); + return timing_.CalculateTimings( + local_time, /*timeline_phase*/ base::nullopt, animation_direction, + is_keyframe_effect, playback_rate); } bool IsCurrent(base::Optional<double> local_time, double playback_rate) { return CalculateTimings(local_time, playback_rate).is_current;
diff --git a/third_party/blink/renderer/core/css/css_default_style_sheets.cc b/third_party/blink/renderer/core/css/css_default_style_sheets.cc index 8d39695..bfe68b95 100644 --- a/third_party/blink/renderer/core/css/css_default_style_sheets.cc +++ b/third_party/blink/renderer/core/css/css_default_style_sheets.cc
@@ -67,9 +67,11 @@ } static const MediaQueryEvaluator& ForcedColorsEval() { + // We use "ua-forced-colors" here instead of "forced-colors" to indicate that + // this is a UA hack for the "forced-colors" media query. DEFINE_STATIC_LOCAL( Persistent<MediaQueryEvaluator>, forced_colors_eval, - (MakeGarbageCollected<MediaQueryEvaluator>("forced-colors"))); + (MakeGarbageCollected<MediaQueryEvaluator>("ua-forced-colors"))); return *forced_colors_eval; }
diff --git a/third_party/blink/renderer/core/css/svg.css b/third_party/blink/renderer/core/css/svg.css index a4783c4c..4de9428 100644 --- a/third_party/blink/renderer/core/css/svg.css +++ b/third_party/blink/renderer/core/css/svg.css
@@ -94,7 +94,7 @@ This is added as to not break SVG content in forced colors mode: https://drafts.csswg.org/css-color-adjust-1/#forced-colors-properties */ -@media forced-colors { +@media ua-forced-colors { svg:root { color: CanvasText; }
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc index 7582cdb..bb20423 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -31,6 +31,8 @@ #include "third_party/blink/renderer/core/exported/web_shared_worker_impl.h" #include <memory> +#include <utility> + #include "base/memory/ptr_util.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" @@ -39,7 +41,6 @@ #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom-blink.h" #include "third_party/blink/public/mojom/script/script_type.mojom-blink.h" #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h" -#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_content_settings_client.h" @@ -178,8 +179,10 @@ const WebFetchClientSettingsObject& outside_fetch_client_settings_object, const base::UnguessableToken& appcache_host_id, const base::UnguessableToken& devtools_worker_token, - mojo::ScopedMessagePipeHandle content_settings_handle, - mojo::ScopedMessagePipeHandle browser_interface_broker, + CrossVariantMojoRemote< + mojom::blink::WorkerContentSettingsProxyInterfaceBase> content_settings, + CrossVariantMojoRemote<mojom::blink::BrowserInterfaceBrokerInterfaceBase> + browser_interface_broker, bool pause_worker_context_on_start) { DCHECK(IsMainThread()); CHECK(constructor_origin.Get()->CanAccessSharedWorkers()); @@ -236,17 +239,13 @@ outside_settings_object->GetHttpsState(), MakeGarbageCollected<WorkerClients>(), std::make_unique<SharedWorkerContentSettingsProxy>( - mojo::PendingRemote<mojom::blink::WorkerContentSettingsProxy>( - std::move(content_settings_handle), 0u)), + std::move(content_settings)), base::nullopt /* response_address_space */, nullptr /* origin_trial_tokens */, devtools_worker_token, std::move(worker_settings), kV8CacheOptionsDefault, nullptr /* worklet_module_response_map */, - mojo::PendingRemote<mojom::blink::BrowserInterfaceBroker>( - std::move(browser_interface_broker), - mojom::blink::BrowserInterfaceBroker::Version_), - BeginFrameProviderParams(), nullptr /* parent_feature_policy */, - base::UnguessableToken()); + std::move(browser_interface_broker), BeginFrameProviderParams(), + nullptr /* parent_feature_policy */, base::UnguessableToken()); reporting_proxy_ = MakeGarbageCollected<SharedWorkerReportingProxy>( this, ParentExecutionContextTaskRunners::Create()); @@ -284,8 +283,8 @@ } // We are now ready to inspect worker thread. - client_->WorkerReadyForInspection(devtools_agent_remote.PassPipe(), - devtools_agent_host_receiver.PassPipe()); + client_->WorkerReadyForInspection(std::move(devtools_agent_remote), + std::move(devtools_agent_host_receiver)); } void WebSharedWorkerImpl::TerminateWorkerContext() {
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h index 13006f67..8a1eb0d 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
@@ -40,8 +40,10 @@ #include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" #include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink.h" #include "third_party/blink/public/mojom/script/script_type.mojom-blink.h" #include "third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom-blink.h" +#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-blink.h" #include "third_party/blink/public/platform/web_fetch_client_settings_object.h" #include "third_party/blink/public/web/web_shared_worker_client.h" #include "third_party/blink/renderer/core/core_export.h" @@ -84,8 +86,11 @@ const WebFetchClientSettingsObject& outside_fetch_client_settings_object, const base::UnguessableToken& appcache_host_id, const base::UnguessableToken& devtools_worker_token, - mojo::ScopedMessagePipeHandle content_settings_handle, - mojo::ScopedMessagePipeHandle browser_interface_broker, + CrossVariantMojoRemote< + mojom::blink::WorkerContentSettingsProxyInterfaceBase> + ontent_settings, + CrossVariantMojoRemote<mojom::blink::BrowserInterfaceBrokerInterfaceBase> + browser_interface_broker, bool pause_worker_context_on_start) override; void Connect(MessagePortChannel) override; void TerminateWorkerContext() override;
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h index 5eab4501..2066007 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.h +++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -156,8 +156,6 @@ void CountUse(mojom::WebFeature feature) final; void CountDeprecation(mojom::WebFeature feature) final; - // Initialize and install a Document for navigation. Should only be used by - // DocumentLoader. Document* InstallNewDocument(const DocumentInit&); // EventTarget overrides:
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index dd8fbe1..c4b96447 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1673,12 +1673,30 @@ scoped_refptr<SharedBuffer> data) { CHECK(loader_.StateMachine()->IsDisplayingInitialEmptyDocument()); DCHECK(!Client()->IsLocalFrameClientImpl()); - auto params = std::make_unique<WebNavigationParams>(); - WebNavigationParams::FillStaticResponse( - params.get(), mime_type, "UTF-8", - base::make_span(data->Data(), data->size())); - loader_.CommitNavigation(std::move(params), nullptr, - CommitReason::kForcedSync); + + // Any Document requires Shutdown() before detach, even the initial empty + // document. + GetDocument()->Shutdown(); + + DomWindow()->InstallNewDocument( + DocumentInit::Create() + .WithDocumentLoader(loader_.GetDocumentLoader(), + MakeGarbageCollected<ContentSecurityPolicy>()) + .WithTypeFrom(mime_type)); + loader_.StateMachine()->AdvanceTo( + FrameLoaderStateMachine::kCommittedFirstRealLoad); + + GetDocument()->OpenForNavigation(kForceSynchronousParsing, mime_type, + AtomicString("UTF-8")); + for (const auto& segment : *data) + GetDocument()->Parser()->AppendBytes(segment.data(), segment.size()); + GetDocument()->Parser()->Finish(); + + // Upon loading of SVGImages, log PageVisits in UseCounter. + // Do not track PageVisits for inspector, web page popups, and validation + // message overlays (the other callers of this method). + if (GetDocument()->IsSVGDocument()) + loader_.GetDocumentLoader()->GetUseCounterHelper().DidCommitLoad(this); } bool LocalFrame::IsProvisional() const {
diff --git a/third_party/blink/renderer/core/html/BUILD.gn b/third_party/blink/renderer/core/html/BUILD.gn index cc9de2b..1a5d83f 100644 --- a/third_party/blink/renderer/core/html/BUILD.gn +++ b/third_party/blink/renderer/core/html/BUILD.gn
@@ -32,6 +32,7 @@ "canvas/image_element_base.h", "canvas/text_metrics.cc", "canvas/text_metrics.h", + "canvas/ukm_parameters.h", "collection_items_cache.h", "collection_type.h", "cross_origin_attribute.cc",
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc index 52d697b0..05c6f016 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -22,8 +22,10 @@ namespace blink { -CanvasRenderingContextHost::CanvasRenderingContextHost(HostType host_type) - : host_type_(host_type) {} +CanvasRenderingContextHost::CanvasRenderingContextHost( + HostType host_type, + base::Optional<UkmParameters> ukm_params) + : host_type_(host_type), ukm_params_(ukm_params) {} void CanvasRenderingContextHost::RecordCanvasSizeToUMA(const IntSize& size) { if (did_record_canvas_size_to_uma_)
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h index 0716b939..e0cfef2e 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
@@ -5,11 +5,14 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RENDERING_CONTEXT_HOST_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RENDERING_CONTEXT_HOST_H_ +#include "base/optional.h" +#include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/events/event_dispatcher.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h" +#include "third_party/blink/renderer/core/html/canvas/ukm_parameters.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/geometry/float_rect.h" @@ -37,7 +40,8 @@ kCanvasHost, kOffscreenCanvasHost, }; - CanvasRenderingContextHost(HostType host_type); + CanvasRenderingContextHost(HostType host_type, + base::Optional<UkmParameters> ukm_params); void RecordCanvasSizeToUMA(const IntSize&); @@ -105,6 +109,8 @@ // blink::CanvasImageSource bool IsOffscreenCanvas() const override; + base::Optional<UkmParameters> ukm_parameters() { return ukm_params_; } + protected: ~CanvasRenderingContextHost() override {} @@ -116,6 +122,7 @@ bool did_fail_to_create_resource_provider_ = false; bool did_record_canvas_size_to_uma_ = false; HostType host_type_ = kNone; + base::Optional<UkmParameters> ukm_params_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index fdf70fc..ba67a352 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -114,7 +114,9 @@ ExecutionContextLifecycleObserver(GetExecutionContext()), PageVisibilityObserver(document.GetPage()), CanvasRenderingContextHost( - CanvasRenderingContextHost::HostType::kCanvasHost), + CanvasRenderingContextHost::HostType::kCanvasHost, + base::make_optional<UkmParameters>( + {document.UkmRecorder(), document.UkmSourceID()})), size_(kDefaultCanvasWidth, kDefaultCanvasHeight), context_creation_was_blocked_(false), ignore_reset_(false),
diff --git a/third_party/blink/renderer/core/html/canvas/ukm_parameters.h b/third_party/blink/renderer/core/html/canvas/ukm_parameters.h new file mode 100644 index 0000000..fad8e38 --- /dev/null +++ b/third_party/blink/renderer/core/html/canvas/ukm_parameters.h
@@ -0,0 +1,20 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_UKM_PARAMETERS_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_UKM_PARAMETERS_H_ + +#include "services/metrics/public/cpp/ukm_recorder.h" +#include "services/metrics/public/cpp/ukm_source_id.h" + +namespace blink { + +struct UkmParameters { + ukm::UkmRecorder* ukm_recorder; + ukm::SourceId source_id; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_UKM_PARAMETERS_H_
diff --git a/third_party/blink/renderer/core/html/html_link_element.cc b/third_party/blink/renderer/core/html/html_link_element.cc index a551ad0..0db6448f 100644 --- a/third_party/blink/renderer/core/html/html_link_element.cc +++ b/third_party/blink/renderer/core/html/html_link_element.cc
@@ -145,8 +145,20 @@ UseCounter::Count(GetDocument(), WebFeature::kHTMLLinkElementDisabled); if (params.reason == AttributeModificationReason::kByParser) UseCounter::Count(GetDocument(), WebFeature::kHTMLLinkElementDisabledByParser); - if (LinkStyle* link = GetLinkStyle()) + // TODO(crbug.com/1087043): Remove this if() condition once the feature has + // landed and no compat issues are reported. + if (RuntimeEnabledFeatures::LinkDisabledNewSpecBehaviorEnabled( + &GetDocument())) { + LinkStyle* link = GetLinkStyle(); + if (!link) { + link = MakeGarbageCollected<LinkStyle>(this); + link_ = link; + } link->SetDisabledState(!value.IsNull()); + } else { + if (LinkStyle* link = GetLinkStyle()) + link->SetDisabledState(!value.IsNull()); + } } else { if (name == html_names::kTitleAttr) { if (LinkStyle* link = GetLinkStyle())
diff --git a/third_party/blink/renderer/core/html/html_link_element.h b/third_party/blink/renderer/core/html/html_link_element.h index e923403..bfad5af 100644 --- a/third_party/blink/renderer/core/html/html_link_element.h +++ b/third_party/blink/renderer/core/html/html_link_element.h
@@ -110,7 +110,14 @@ FetchParameters::DeferOption, ResourceClient*); bool IsAlternate() const { - return GetLinkStyle()->IsUnset() && rel_attribute_.IsAlternate(); + // TODO(crbug.com/1087043): Remove this if() condition once the feature has + // landed and no compat issues are reported. + bool not_explicitly_enabled = + !GetLinkStyle()->IsExplicitlyEnabled() || + !RuntimeEnabledFeatures::LinkDisabledNewSpecBehaviorEnabled( + &GetDocument()); + return GetLinkStyle()->IsUnset() && rel_attribute_.IsAlternate() && + not_explicitly_enabled; } bool ShouldProcessStyle() { return LinkResourceToProcess() && GetLinkStyle();
diff --git a/third_party/blink/renderer/core/html/link_style.cc b/third_party/blink/renderer/core/html/link_style.cc index af40a72d..09350f2e 100644 --- a/third_party/blink/renderer/core/html/link_style.cc +++ b/third_party/blink/renderer/core/html/link_style.cc
@@ -202,6 +202,10 @@ void LinkStyle::SetDisabledState(bool disabled) { LinkStyle::DisabledState old_disabled_state = disabled_state_; disabled_state_ = disabled ? kDisabled : kEnabledViaScript; + // Whenever the disabled attribute is removed, set the link element's + // explicitly enabled attribute to true. + if (!disabled) + explicitly_enabled_ = true; if (old_disabled_state == disabled_state_) return; @@ -231,8 +235,19 @@ } if (sheet_) { - sheet_->setDisabled(disabled); - return; + // TODO(crbug.com/1087043): Remove this if() condition once the feature has + // landed and no compat issues are reported. + if (RuntimeEnabledFeatures::LinkDisabledNewSpecBehaviorEnabled( + &GetDocument())) { + DCHECK(disabled) + << "If link is being enabled, sheet_ shouldn't exist yet"; + ClearSheet(); + GetDocument().GetStyleEngine().SetNeedsActiveStyleUpdate( + owner_->GetTreeScope()); + return; + } else { + sheet_->setDisabled(disabled); + } } if (disabled_state_ == kEnabledViaScript && owner_->ShouldProcessStyle())
diff --git a/third_party/blink/renderer/core/html/link_style.h b/third_party/blink/renderer/core/html/link_style.h index 6021121..2b4df40 100644 --- a/third_party/blink/renderer/core/html/link_style.h +++ b/third_party/blink/renderer/core/html/link_style.h
@@ -54,6 +54,8 @@ } bool IsUnset() const { return disabled_state_ == kUnset; } + bool IsExplicitlyEnabled() const { return explicitly_enabled_; } + CSSStyleSheet* Sheet() const { return sheet_.Get(); } private: @@ -76,6 +78,7 @@ DisabledState disabled_state_; PendingSheetType pending_sheet_type_; StyleEngineContext style_engine_context_; + bool explicitly_enabled_; bool loading_; bool fired_load_; bool loaded_sheet_;
diff --git a/third_party/blink/renderer/core/html/resources/forced_colors.css b/third_party/blink/renderer/core/html/resources/forced_colors.css index d733130..6b45ae9 100644 --- a/third_party/blink/renderer/core/html/resources/forced_colors.css +++ b/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -14,7 +14,7 @@ @namespace "http://www.w3.org/1999/xhtml" */ -@media forced-colors { +@media ua-forced-colors { html { color: CanvasText; fill: currentColor;
diff --git a/third_party/blink/renderer/core/inspector/inspect_tool_common.css b/third_party/blink/renderer/core/inspector/inspect_tool_common.css deleted file mode 100644 index da932de..0000000 --- a/third_party/blink/renderer/core/inspector/inspect_tool_common.css +++ /dev/null
@@ -1,41 +0,0 @@ -/* - * Copyright 2019 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -body { - margin: 0; - padding: 0; - font-size: 13px; - color: #222; -} - -body.platform-linux { - font-family: Roboto, Ubuntu, Arial, sans-serif; -} - -body.platform-mac { - color: rgb(48, 57, 66); - font-family: '.SFNSDisplay-Regular', 'Helvetica Neue', 'Lucida Grande', sans-serif; -} - -body.platform-windows { - font-family: 'Segoe UI', Tahoma, sans-serif; -} - -.fill { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -#canvas { - pointer-events: none; -} - -.hidden { - display: none !important; -}
diff --git a/third_party/blink/renderer/core/inspector/inspect_tool_common.js b/third_party/blink/renderer/core/inspector/inspect_tool_common.js deleted file mode 100644 index 2c3001c6..0000000 --- a/third_party/blink/renderer/core/inspector/inspect_tool_common.js +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -window.viewportSize = {width: 800, height: 600}; -window.deviceScaleFactor = 1; -window.emulationScaleFactor = 1; -window.pageScaleFactor = 1; -window.pageZoomFactor = 1; -window.scrollX = 0; -window.scrollY = 0; - -function reset(resetData) { - window.viewportSize = resetData.viewportSize; - window.deviceScaleFactor = resetData.deviceScaleFactor; - window.pageScaleFactor = resetData.pageScaleFactor; - window.pageZoomFactor = resetData.pageZoomFactor; - window.emulationScaleFactor = resetData.emulationScaleFactor; - window.scrollX = Math.round(resetData.scrollX); - window.scrollY = Math.round(resetData.scrollY); - - window.canvas = document.getElementById('canvas'); - if (window.canvas) { - window.canvas.width = deviceScaleFactor * viewportSize.width; - window.canvas.height = deviceScaleFactor * viewportSize.height; - window.canvas.style.width = viewportSize.width + 'px'; - window.canvas.style.height = viewportSize.height + 'px'; - - window.context = canvas.getContext('2d'); - window.context.scale(deviceScaleFactor, deviceScaleFactor); - - window.canvasWidth = viewportSize.width; - window.canvasHeight = viewportSize.height; - } - - doReset(); -} - -function doReset() { } - -function setPlatform(platform) { - window.platform = platform; - document.body.classList.add('platform-' + platform); -} - -function dispatch(message) { - const functionName = message.shift(); - window[functionName].apply(null, message); -} - -function log(text) { - let element = document.getElementById('log'); - if (!element) { - element = document.body.createChild(); - element.id = 'log'; - } - element.createChild('div').textContent = text; -} - -function eventHasCtrlOrMeta(event) { - return window.platform == 'mac' ? (event.metaKey && !event.ctrlKey) : (event.ctrlKey && !event.metaKey); -} - -Element.prototype.createChild = function(tagName, className) { - const element = createElement(tagName, className); - element.addEventListener('click', function(e) { e.stopPropagation(); }, false); - this.appendChild(element); - return element; -} - -Element.prototype.createTextChild = function(text) { - const element = document.createTextNode(text); - this.appendChild(element); - return element; -} - -Element.prototype.removeChildren = function() -{ - if (this.firstChild) - this.textContent = ''; -} - -function createElement(tagName, className) -{ - const element = document.createElement(tagName); - if (className) - element.className = className; - return element; -} - -String.prototype.trimEnd = function(maxLength) -{ - if (this.length <= maxLength) - return String(this); - 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; -};
diff --git a/third_party/blink/renderer/core/inspector/inspect_tool_distances.html b/third_party/blink/renderer/core/inspector/inspect_tool_distances.html deleted file mode 100644 index 645d6c2..0000000 --- a/third_party/blink/renderer/core/inspector/inspect_tool_distances.html +++ /dev/null
@@ -1,103 +0,0 @@ -<!-- - Copyright 2019 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. ---> -<!DOCTYPE html> -<html> -<head> -<script> - -/** - * @param {!Object} data - */ -function drawDistances(data) -{ - const info = data['distanceInfo']; - if (!info) - return; - const rect = quadToRect(getVisualQuad(info)); - const context = window.context; - context.save(); - context.strokeStyle = '#ccc'; - for (const box of info['boxes']) - context.strokeRect(box[0], box[1], box[2], box[3]); - context.strokeStyle = '#f00'; - context.lineWidth = 1; - context.rect(rect.x - 0.5, rect.y - 0.5, rect.w + 1, rect.h + 1); - context.stroke(); - context.restore(); -} - -/** - * @param {!Object} data - * @return {!Array<number>} - */ -function getVisualQuad(data) { - const style = data['style']; - if (shouldUseVisualBorder(style)) - return data['border']; - else if (ShouldUseVisualPadding(style)) - return data['padding']; - return data['content']; - - /** - * @param {!Object} style - * @return {boolean} - */ - function shouldUseVisualBorder(style) { - const sides = ['top', 'right', 'bottom', 'left']; - for (const side of sides) { - const border_width = style[`border-${side}-width`]; - const border_style = style[`border-${side}-style`]; - const border_color = style[`border-${side}-color`]; - if (border_width != '0px' && border_style != 'none' && - !border_color.endsWith('00')) - return true; - } - const outline_width = style['outline-width']; - const outline_style = style['outline-style']; - const outline_color = style['outline-color']; - if (outline_width != '0px' && outline_style != 'none' && - !outline_color.endsWith('00')) - return true; - const box_shadow = style['box-shadow']; - if (box_shadow != 'none') - return true; - return false; - } - - /** - * @param {!Object} style - * @return {boolean} - */ - function ShouldUseVisualPadding(style) { - const bg_color = style['background-color']; - const bg_image = style['background-image']; - if (!bg_color.startsWith('#FFFFFF') && !bg_color.endsWith('00')) - return true; - if (bg_image != 'none') - return true; - return false; - } -} - -/** - * @param {!Array<number>} quad - * @return {!Object} - */ -function quadToRect(quad) { - return { - x: quad[0], - y: quad[1], - w: quad[4] - quad[0], - h: quad[5] - quad[1] - } -} - -</script> -</head> -<body class="fill"> - <canvas id="canvas" class="fill"></canvas> -</body> -</html>
diff --git a/third_party/blink/renderer/core/inspector/inspect_tool_paused.html b/third_party/blink/renderer/core/inspector/inspect_tool_paused.html deleted file mode 100644 index 22f5375..0000000 --- a/third_party/blink/renderer/core/inspector/inspect_tool_paused.html +++ /dev/null
@@ -1,108 +0,0 @@ -<!-- - Copyright 2019 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. ---> -<!DOCTYPE html> -<html> -<head> -<script src="inspect_tool_common.js"></script> -<link rel="stylesheet" href="inspect_tool_common.css"> -<style> -body { - background-color: rgba(0, 0, 0, 0.31); -} - -.controls-line { - display: flex; - justify-content: center; - margin: 10px 0; -} - -.message-box { - padding: 2px 4px; - display: flex; - align-items: center; - cursor: default; - overflow: hidden; -} - -#paused-in-debugger { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} - -.controls-line > * { - background-color: rgb(255, 255, 194); - border: 1px solid rgb(202, 202, 202); - height: 22px; - box-sizing: border-box; -} - -.controls-line .button { - width: 26px; - margin-left: -1px; - margin-right: 0; - padding: 0; - flex-shrink: 0; - flex-grow: 0; - cursor: pointer; -} - -.controls-line .button .glyph { - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.75); - opacity: 0.8; - -webkit-mask-repeat: no-repeat; - -webkit-mask-position: center; - position: relative; -} - -.controls-line .button:active .glyph { - top: 1px; - left: 1px; -} - -#resume-button .glyph { - -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAKCAYAAABv7tTEAAAAAXNSR0IArs4c6QAAAFJJREFUKM+10bEJgGAMBeEPbR3BLRzEVdzEVRzELRzBVohVwEJ+iODBlQfhBeJhsmHU4C0KnFjQV6J0x1SNAhdWDJUoPTB3PvLLeaUhypM3n3sD/qc7lDrdpIEAAAAASUVORK5CYII=); - -webkit-mask-size: 13px 10px; - background-color: rgb(66, 129, 235); -} - -#step-over-button .glyph { - -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAKCAYAAAC5Sw6hAAAAAXNSR0IArs4c6QAAAOFJREFUKM+N0j8rhXEUB/DPcxW35CqhvIBrtqibkklhV8qkTHe4ZbdblcXgPVhuMdqUTUl5A2KRRCF5LGc4PT1P7qnfcr5/zu/8KdTHLFaxjHnc4RZXKI0QYxjgLQTVd42l/0wmg5iFX3iq5H6w22RS4DyRH7CB8cAXcBTGJT6xUmd0mEwuMdFQcA3fwXvGTAan8BrgPabTL9fRRyfx91PRMwyjGwcJ2EyCfsrfpPw2Pipz24NT/MZciiQYVshzOKnZ5Hturxt3k2MnCpS4SPkeHpPR8Sh3tYgttBoW9II2/AHiaEqvD2Fc0wAAAABJRU5ErkJggg==); - -webkit-mask-size: 18px 10px; -} - -</style> -<script> - -function drawPausedInDebuggerMessage(message) { - document.getElementById("paused-in-debugger").textContent = message; -} - -window.addEventListener("DOMContentLoaded", () => { - document.getElementById("resume-button").addEventListener("click", () => InspectorOverlayHost.send("resume")); - document.getElementById("step-over-button").addEventListener("click", () => InspectorOverlayHost.send("stepOver")); -}); - -document.addEventListener("keydown", event => { - if (event.key == "F8" || eventHasCtrlOrMeta(event) && event.keyCode == 220 /* backslash */) - InspectorOverlayHost.send("resume"); - else if (event.key == "F10" || eventHasCtrlOrMeta(event) && event.keyCode == 222 /* single quote */) - InspectorOverlayHost.send("stepOver"); -}); - -</script> -</head> - -<body class="fill"> - <div class="controls-line"> - <div class="message-box"><div id="paused-in-debugger"></div></div> - <div class="button" id="resume-button" title="Resume script execution (F8)."><div class="glyph"></div></div> - <div class="button" id="step-over-button" title="Step over next function call (F10)."><div class="glyph"></div></div> - </div> -</body> -</html>
diff --git a/third_party/blink/renderer/core/inspector/inspect_tool_screenshot.html b/third_party/blink/renderer/core/inspector/inspect_tool_screenshot.html deleted file mode 100644 index 8517bfb..0000000 --- a/third_party/blink/renderer/core/inspector/inspect_tool_screenshot.html +++ /dev/null
@@ -1,102 +0,0 @@ -<!-- - Copyright 2019 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. ---> -<!DOCTYPE html> -<html> -<head> -<script src="inspect_tool_common.js"></script> -<link rel="stylesheet" href="inspect_tool_common.css"> -<style> -body { - cursor: crosshair; -} -#zone { - background-color: #0003; - border: 1px solid #fffd; - display: none; - position: absolute; -} -</style> -<script> - -let anchor = null; -let position = null; - -function currentRect() { - return { - x: Math.min(anchor.x, position.x), - y: Math.min(anchor.y, position.y), - width: Math.abs(anchor.x - position.x), - height: Math.abs(anchor.y - position.y) - }; -} - -function updateZone() -{ - const zone = document.getElementById('zone'); - if (!position || !anchor) { - zone.style.display = 'none'; - return; - } - zone.style.display = 'block'; - const rect = currentRect(); - zone.style.left = rect.x + 'px'; - zone.style.top = rect.y + 'px'; - zone.style.width = rect.width + 'px'; - zone.style.height = rect.height + 'px'; -} - -function cancel() { - anchor = null; - position = null; -} - -function loaded() { - document.documentElement.addEventListener('mousedown', event => { - anchor = { x: event.pageX, y: event.pageY }; - position = anchor; - updateZone(); - event.stopPropagation(); - event.preventDefault(); - }, true); - - document.documentElement.addEventListener('mouseup', event => { - if (anchor && position) { - const rect = currentRect(); - if (rect.width >= 5 && rect.height >= 5) - InspectorOverlayHost.send(JSON.stringify(rect)); - } - cancel(); - updateZone(); - event.stopPropagation(); - event.preventDefault(); - }, true); - - document.documentElement.addEventListener('mousemove', event => { - if (anchor && event.buttons === 1) - position = { x: event.pageX, y: event.pageY }; - else - anchor = null; - updateZone(); - event.stopPropagation(); - event.preventDefault(); - }, true); - - document.documentElement.addEventListener('keydown', event => { - if (anchor && event.key === 'Escape') { - cancel(); - updateZone(); - event.stopPropagation(); - event.preventDefault(); - } - }, true); -} - -</script> -</head> -<body class="fill" onload="loaded()"> - <div id="zone"></div> -</body> -</html>
diff --git a/third_party/blink/renderer/core/inspector/inspect_tool_viewport_size.html b/third_party/blink/renderer/core/inspector/inspect_tool_viewport_size.html deleted file mode 100644 index bb0f373..0000000 --- a/third_party/blink/renderer/core/inspector/inspect_tool_viewport_size.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- - Copyright 2019 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. ---> -<!DOCTYPE html> -<html> -<head> -<script> - -const darkGridColor = "rgba(0,0,0,0.7)"; -const gridBackgroundColor = "rgba(255, 255, 255, 0.8)"; - -function drawViewSize() -{ - const text = `${viewportSize.width}px \u00D7 ${viewportSize.height}px`; - context.save(); - context.font = `14px ${window.getComputedStyle(document.body).fontFamily}`; - const textWidth = context.measureText(text).width; - context.fillStyle = gridBackgroundColor; - context.fillRect(canvasWidth - textWidth - 12, 0, canvasWidth, 25); - context.fillStyle = darkGridColor; - context.fillText(text, canvasWidth - textWidth - 6, 18); - context.restore(); -} - -</script> -</head> -<body class="fill"> - <canvas id="canvas" class="fill"></canvas> -</body> -</html>
diff --git a/third_party/blink/renderer/core/inspector/inspect_tools.cc b/third_party/blink/renderer/core/inspector/inspect_tools.cc index cbb04e0ec..093f8fb 100644 --- a/third_party/blink/renderer/core/inspector/inspect_tools.cc +++ b/third_party/blink/renderer/core/inspector/inspect_tools.cc
@@ -9,7 +9,7 @@ #include "third_party/blink/public/common/input/web_keyboard_event.h" #include "third_party/blink/public/common/input/web_pointer_event.h" #include "third_party/blink/public/platform/web_input_event_result.h" -#include "third_party/blink/public/resources/grit/blink_resources.h" +#include "third_party/blink/public/resources/grit/inspector_overlay_resources_map.h" #include "third_party/blink/renderer/core/css/css_color_value.h" #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h" #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" @@ -351,7 +351,7 @@ // NearbyDistanceTool ---------------------------------------------------------- int NearbyDistanceTool::GetDataResourceId() { - return IDR_INSPECT_TOOL_DISTANCES_HTML; + return IDR_INSPECT_TOOL_DISTANCES_JS; } bool NearbyDistanceTool::HandleMouseDown(const WebMouseEvent& event, @@ -421,7 +421,7 @@ } int ShowViewSizeTool::GetDataResourceId() { - return IDR_INSPECT_TOOL_VIEWPORT_SIZE_HTML; + return IDR_INSPECT_TOOL_VIEWPORT_SIZE_JS; } bool ShowViewSizeTool::ForwardEventsToOverlay() { @@ -438,7 +438,7 @@ } int ScreenshotTool::GetDataResourceId() { - return IDR_INSPECT_TOOL_SCREENSHOT_HTML; + return IDR_INSPECT_TOOL_SCREENSHOT_JS; } void ScreenshotTool::Dispatch(const String& message) { @@ -521,7 +521,7 @@ // PausedInDebuggerTool -------------------------------------------------------- int PausedInDebuggerTool::GetDataResourceId() { - return IDR_INSPECT_TOOL_PAUSED_HTML; + return IDR_INSPECT_TOOL_PAUSED_JS; } void PausedInDebuggerTool::Draw(float scale) {
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc index c2f0cc4f..bc331dbc 100644 --- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -38,7 +38,6 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_data.h" -#include "third_party/blink/public/resources/grit/blink_resources.h" #include "third_party/blink/public/resources/grit/inspector_overlay_resources_map.h" #include "third_party/blink/public/web/web_widget_client.h" #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h" @@ -1017,25 +1016,13 @@ frame->View()->SetBaseBackgroundColor(Color::kTransparent); scoped_refptr<SharedBuffer> data = SharedBuffer::Create(); - // TODO(crbug.com/1078267): migrate all inspector tools - if (frame_resource_name_ == IDR_INSPECT_TOOL_HIGHLIGHT_JS) { - // New source of overlay resources. - data->Append("<style>", static_cast<size_t>(7)); - data->Append(UncompressResourceAsBinary(IDR_INSPECT_COMMON_CSS)); - data->Append("</style>", static_cast<size_t>(8)); - data->Append("<script>", static_cast<size_t>(8)); - data->Append(UncompressResourceAsBinary(frame_resource_name_)); - data->Append("</script>", static_cast<size_t>(9)); - } else { - // Old source of resources. - data->Append("<style>", static_cast<size_t>(7)); - data->Append(UncompressResourceAsBinary(IDR_INSPECT_TOOL_COMMON_CSS)); - data->Append("</style>", static_cast<size_t>(8)); - data->Append("<script>", static_cast<size_t>(8)); - data->Append(UncompressResourceAsBinary(IDR_INSPECT_TOOL_COMMON_JS)); - data->Append("</script>", static_cast<size_t>(9)); - data->Append(UncompressResourceAsBinary(frame_resource_name_)); - } + + data->Append("<style>", static_cast<size_t>(7)); + data->Append(UncompressResourceAsBinary(IDR_INSPECT_COMMON_CSS)); + data->Append("</style>", static_cast<size_t>(8)); + data->Append("<script>", static_cast<size_t>(8)); + data->Append(UncompressResourceAsBinary(frame_resource_name_)); + data->Append("</script>", static_cast<size_t>(9)); frame->ForceSynchronousDocumentInstall("text/html", data); @@ -1058,6 +1045,8 @@ EvaluateInOverlay("setPlatform", "mac"); #elif defined(OS_POSIX) EvaluateInOverlay("setPlatform", "linux"); +#else + EvaluateInOverlay("setPlatform", "other"); #endif }
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index c351d83..4f878d54 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1375,6 +1375,11 @@ if (IsA<LayoutView>(this) || IsSVGForeignObject() || IsTextControl()) return true; // https://www.w3.org/TR/css-transforms-1/#containing-block-for-all-descendants + + if (RuntimeEnabledFeatures::TransformInteropEnabled() && + style->TransformStyle3D() == ETransformStyle3D::kPreserve3d) + return true; + if (style->HasTransformRelatedProperty()) { if (!IsInline() || IsAtomicInlineLevel()) return true;
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc index 9922197..6fad3ca 100644 --- a/third_party/blink/renderer/core/layout/layout_object_test.cc +++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -86,6 +86,118 @@ EXPECT_TRUE(layout_object->IsInline()); } +TEST_F(LayoutObjectTest, BackdropFilterAsGroupingProperty) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <style> div { transform-style: preserve-3d; } </style> + <div id=target1 style="backdrop-filter: blur(2px)"></div> + <div id=target2 style="will-change: backdrop-filter"></div> + <div id=target3 style="position: relative"></div> + )HTML"); + EXPECT_TRUE( + GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty()); + EXPECT_TRUE( + GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty()); + EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D()); + EXPECT_FALSE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D()); + + EXPECT_FALSE( + GetLayoutObjectByElementId("target3")->StyleRef().HasGroupingProperty()); + EXPECT_TRUE(GetLayoutObjectByElementId("target3")->StyleRef().Preserves3D()); +} + +TEST_F(LayoutObjectTest, BlendModeAsGroupingProperty) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <style> div { transform-style: preserve-3d; } </style> + <div id=target1 style="mix-blend-mode: multiply"></div> + <div id=target2 style="position: relative"></div> + )HTML"); + EXPECT_TRUE( + GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty()); + EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D()); + + EXPECT_FALSE( + GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty()); + EXPECT_TRUE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D()); +} + +TEST_F(LayoutObjectTest, CSSClipAsGroupingProperty) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <style> div { transform-style: preserve-3d; } </style> + <div id=target1 style="clip: rect(1px, 2px, 3px, 4px)"></div> + <div id=target2 style="position: absolute; clip: rect(1px, 2px, 3px, 4px)"> + </div> + <div id=target3 style="position: relative"></div> + )HTML"); + EXPECT_FALSE( + GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty()); + EXPECT_TRUE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D()); + EXPECT_TRUE( + GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty()); + EXPECT_FALSE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D()); + + EXPECT_FALSE( + GetLayoutObjectByElementId("target3")->StyleRef().HasGroupingProperty()); + EXPECT_TRUE(GetLayoutObjectByElementId("target3")->StyleRef().Preserves3D()); +} + +TEST_F(LayoutObjectTest, ClipPathAsGroupingProperty) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <style> div { transform-style: preserve-3d; } </style> + <div id=target1 style="clip-path: circle(40%)"></div> + <div id=target2 style="position: relative"></div> + )HTML"); + EXPECT_TRUE( + GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty()); + EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D()); + + EXPECT_FALSE( + GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty()); + EXPECT_TRUE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D()); +} + +TEST_F(LayoutObjectTest, IsolationAsGroupingProperty) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <style> div { transform-style: preserve-3d; } </style> + <div id=target1 style="isolation: isolate"></div> + <div id=target2 style="position: relative"></div> + )HTML"); + EXPECT_TRUE( + GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty()); + EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D()); + + EXPECT_FALSE( + GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty()); + EXPECT_TRUE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D()); +} + +TEST_F(LayoutObjectTest, MaskAsGroupingProperty) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <style> div { transform-style: preserve-3d; } </style> + <div id=target1 style="-webkit-mask:linear-gradient(black,transparent)"> + </div> + <div id=target2 style="position: relative"></div> + )HTML"); + EXPECT_TRUE( + GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty()); + EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D()); + + EXPECT_FALSE( + GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty()); + EXPECT_TRUE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D()); +} + TEST_F(LayoutObjectTest, UseCountBackdropFilterAsGroupingProperty) { SetBodyInnerHTML(R"HTML( <style> div { transform-style: preserve-3d; } </style> @@ -169,6 +281,20 @@ EXPECT_EQ(PhysicalOffset(2, 10), offset); } +TEST_F(LayoutObjectTest, ContainingBlockFixedPosUnderFlattened3DWithInterop) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <div id=container style='transform-style: preserve-3d; opacity: 0.9'> + <div id=target style='position:fixed'></div> + </div> + )HTML"); + + LayoutObject* target = GetLayoutObjectByElementId("target"); + LayoutObject* container = GetLayoutObjectByElementId("container"); + EXPECT_EQ(container, target->Container()); +} + TEST_F(LayoutObjectTest, ContainingBlockFixedLayoutObjectInTransformedDiv) { SetBodyInnerHTML(R"HTML( <div style='transform:translateX(0px)'>
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h index 3b7636a..d75eb17c 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h +++ b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
@@ -43,9 +43,6 @@ Entry NextChild( const NGInlineBreakToken* previous_inline_break_token = nullptr); - // Return true if there are no more children to process. - bool IsAtEnd() const { return !child_; } - private: NGLayoutInputNode child_; const NGBlockBreakToken* break_token_;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc index 92cec5b9d..d3dff131 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -785,7 +785,7 @@ NGLayoutResult::kNeedsRelayoutWithNoForcedTruncateAtLineClamp); } - if (child_iterator.IsAtEnd()) { + if (!child_iterator.NextChild(previous_inline_break_token.get()).node) { // We've gone through all the children. This doesn't necessarily mean that // we're done fragmenting, as there may be parallel flows [1] (visible // overflow) still needing more space than what the current fragmentainer
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_test.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_test.cc index a0ddc4069..fc9deae 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_test.cc
@@ -193,5 +193,54 @@ EXPECT_EQ(child2->GetPhysicalFragment(3)->Size(), PhysicalSize(22, 100)); } +TEST_F(NGFragmentationTest, HasSeenAllChildrenIfc) { + SetBodyInnerHTML(R"HTML( + <div id="container"> + <div style="columns:3; column-fill:auto; height:50px; line-height:20px; orphans:1; widows:1;"> + <div id="ifc" style="height:300px;"> + <br><br> + <br><br> + <br><br> + <br> + </div> + </div> + </div> + )HTML"); + + RunBlockLayoutAlgorithm(GetElementById("container")); + + const LayoutBox* ifc = ToLayoutBox(GetLayoutObjectByElementId("ifc")); + ASSERT_EQ(ifc->PhysicalFragmentCount(), 6u); + const NGPhysicalBoxFragment* fragment = ifc->GetPhysicalFragment(0); + const NGBlockBreakToken* break_token = + DynamicTo<NGBlockBreakToken>(fragment->BreakToken()); + ASSERT_TRUE(break_token); + EXPECT_FALSE(break_token->HasSeenAllChildren()); + + fragment = ifc->GetPhysicalFragment(1); + break_token = DynamicTo<NGBlockBreakToken>(fragment->BreakToken()); + ASSERT_TRUE(break_token); + EXPECT_FALSE(break_token->HasSeenAllChildren()); + + fragment = ifc->GetPhysicalFragment(2); + break_token = DynamicTo<NGBlockBreakToken>(fragment->BreakToken()); + ASSERT_TRUE(break_token); + EXPECT_FALSE(break_token->HasSeenAllChildren()); + + fragment = ifc->GetPhysicalFragment(3); + break_token = DynamicTo<NGBlockBreakToken>(fragment->BreakToken()); + ASSERT_TRUE(break_token); + EXPECT_TRUE(break_token->HasSeenAllChildren()); + + fragment = ifc->GetPhysicalFragment(4); + break_token = DynamicTo<NGBlockBreakToken>(fragment->BreakToken()); + ASSERT_TRUE(break_token); + EXPECT_TRUE(break_token->HasSeenAllChildren()); + + fragment = ifc->GetPhysicalFragment(5); + break_token = DynamicTo<NGBlockBreakToken>(fragment->BreakToken()); + EXPECT_FALSE(break_token); +} + } // anonymous namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 4668ae3f..2179c07 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1823,7 +1823,6 @@ ? kAllowDeferredParsing : kAllowAsynchronousParsing; if (IsJavaScriptURLOrXSLTCommit() || - commit_reason_ == CommitReason::kForcedSync || !Document::ThreadedParsingEnabledForTesting()) { parsing_policy = kForceSynchronousParsing; }
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 27fb37ae..e199eed 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -1197,13 +1197,7 @@ if (commit_reason != CommitReason::kInitialization) { // Note: this must be called after DispatchDidCommitLoad() for // metrics to be correctly sent to the browser process. - // kForcedSync is used in two broad cases: internal UI (inspector, web page - // popups, and validation message overlays) and svg images. Don't track - // page visits for the internal UI cases. - bool is_internal_ui = commit_reason == CommitReason::kForcedSync && - document_loader_->MimeType() != "image/svg+xml"; - if (!is_internal_ui) - document_loader_->GetUseCounterHelper().DidCommitLoad(frame_); + document_loader_->GetUseCounterHelper().DidCommitLoad(frame_); } if (document_loader_->LoadType() == WebFrameLoadType::kBackForward) { if (Page* page = frame_->GetPage())
diff --git a/third_party/blink/renderer/core/loader/frame_loader_types.h b/third_party/blink/renderer/core/loader/frame_loader_types.h index 0855972..5922922e 100644 --- a/third_party/blink/renderer/core/loader/frame_loader_types.h +++ b/third_party/blink/renderer/core/loader/frame_loader_types.h
@@ -90,8 +90,6 @@ kJavascriptUrl, // Committing a replacement document from XSLT. kXSLT, - // Used to populate certain internal-implementation frames (e.g., overlays). - kForcedSync, // All other navigations. kRegular };
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc index 834185b..51f7ddb8 100644 --- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc +++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h" #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h" #include "third_party/blink/renderer/core/html/canvas/image_data.h" +#include "third_party/blink/renderer/core/html/canvas/ukm_parameters.h" #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h" #include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h" #include "third_party/blink/renderer/platform/bindings/microtask.h" @@ -43,7 +44,8 @@ OffscreenCanvas::OffscreenCanvas(ExecutionContext* context, const IntSize& size) : CanvasRenderingContextHost( - CanvasRenderingContextHost::HostType::kOffscreenCanvasHost), + CanvasRenderingContextHost::HostType::kOffscreenCanvasHost, + base::make_optional<UkmParameters>()), execution_context_(context), size_(size) { // Other code in Blink watches for destruction of the context; be
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc index 4f66645c..51eb893 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
@@ -14,6 +14,12 @@ public: CompositingInputsUpdaterTest() : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {} + + protected: + void SetUp() override { + EnableCompositing(); + RenderingTest::SetUp(); + } }; // Tests that transitioning a sticky away from an ancestor overflow layer that
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc index 8404fe0c..ace8d80 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -107,6 +107,19 @@ return false; } +static CompositingReasons BackfaceInvisibility3DAncestorReason( + const PaintLayer& layer) { + if (RuntimeEnabledFeatures::TransformInteropEnabled()) { + if (auto* compositing_container = layer.CompositingContainer()) { + if (compositing_container->GetLayoutObject() + .StyleRef() + .BackfaceVisibility() == EBackfaceVisibility::kHidden) + return CompositingReason::kBackfaceInvisibility3DAncestor; + } + } + return CompositingReason::kNone; +} + CompositingReasons CompositingReasonFinder::DirectReasonsForPaintProperties( const LayoutObject& object) { // TODO(wangxianzhu): Don't depend on PaintLayer for CompositeAfterPaint. @@ -144,9 +157,9 @@ bool force_prefer_compositing_to_lcd_text = reasons != CompositingReason::kNone || // In CompositeAfterPaint though we don't treat hidden backface as - // a direct compositing reason, it's very likely that the object will - // be composited, and it also indicates preference of compositing, - // so we prefer composited scrolling here. + // a direct compositing reason, it's very likely that the object + // will be composited, and it also indicates preference of + // compositing, so we prefer composited scrolling here. style.BackfaceVisibility() == EBackfaceVisibility::kHidden || (object.IsLayoutView() && ShouldPreferCompositingForLayoutView(To<LayoutView>(object))); @@ -162,6 +175,8 @@ } } + reasons |= BackfaceInvisibility3DAncestorReason(*layer); + if (object.CanHaveAdditionalCompositingReasons()) reasons |= object.AdditionalCompositingReasons(); @@ -170,9 +185,9 @@ bool CompositingReasonFinder::RequiresCompositingFor3DTransform( const LayoutObject& layout_object) { - // Note that we ask the layoutObject if it has a transform, because the style - // may have transforms, but the layoutObject may be an inline that doesn't - // support them. + // Note that we ask the layoutObject if it has a transform, because the + // style may have transforms, but the layoutObject may be an inline that + // doesn't support them. if (!layout_object.HasTransformRelatedProperty()) return false; @@ -196,9 +211,10 @@ if (RequiresCompositingForRootScroller(layer)) direct_reasons |= CompositingReason::kRootScroller; - // Composite |layer| if it is inside of an ancestor scrolling layer, but that - // scrolling layer is not on the stacking context ancestor chain of |layer|. - // See the definition of the scrollParent property in Layer for more detail. + // Composite |layer| if it is inside of an ancestor scrolling layer, but + // that scrolling layer is not on the stacking context ancestor chain of + // |layer|. See the definition of the scrollParent property in Layer for + // more detail. if (const PaintLayer* scrolling_ancestor = layer.AncestorScrollingLayer()) { if (scrolling_ancestor->NeedsCompositedScrolling() && layer.ScrollParent()) { @@ -234,6 +250,8 @@ if (layout_object.CanHaveAdditionalCompositingReasons()) direct_reasons |= layout_object.AdditionalCompositingReasons(); + direct_reasons |= BackfaceInvisibility3DAncestorReason(layer); + DCHECK( !(direct_reasons & CompositingReason::kComboAllStyleDeterminedReasons)); return direct_reasons; @@ -287,8 +305,8 @@ const PaintLayer& layer) { // The root scroller needs composited scrolling layers even if it doesn't // actually have scrolling since CC has these assumptions baked in for the - // viewport. Because this is only needed for CC, we can skip it if compositing - // is not enabled. + // viewport. Because this is only needed for CC, we can skip it if + // compositing is not enabled. const auto& settings = *layer.GetLayoutObject().GetDocument().GetSettings(); if (!settings.GetAcceleratedCompositingEnabled()) return false;
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc index 980a9ef..49eb3cd 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
@@ -245,4 +245,125 @@ iframe_layer->DirectCompositingReasons()); } +TEST_F(CompositingReasonFinderTest, + CompositeWithBackfaceVisibilityAncestorAndPreserve3D) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <!DOCTYPE html> + <style> + div { width: 100px; height: 100px; position: relative } + </style> + <div style="backface-visibility: hidden; transform-style: preserve-3d"> + <div id=target></div> + </div> + )HTML"); + + PaintLayer* target_layer = + ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); + + EXPECT_EQ(CompositingReason::kBackfaceInvisibility3DAncestor, + target_layer->PotentialCompositingReasonsFromNonStyle()); + EXPECT_EQ(kPaintsIntoOwnBacking, target_layer->GetCompositingState()); +} + +TEST_F(CompositingReasonFinderTest, + CompositeWithBackfaceVisibilityAncestorAndPreserve3DWithInterveningDiv) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <!DOCTYPE html> + <style> + div { width: 100px; height: 100px } + </style> + <div style="backface-visibility: hidden; transform-style: preserve-3d"> + <div> + <div id=target style="position: relative"></div> + </div> + </div> + )HTML"); + + PaintLayer* target_layer = + ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); + + EXPECT_EQ(CompositingReason::kBackfaceInvisibility3DAncestor, + target_layer->PotentialCompositingReasonsFromNonStyle()); + EXPECT_EQ(kPaintsIntoOwnBacking, target_layer->GetCompositingState()); +} + +TEST_F(CompositingReasonFinderTest, + CompositeWithBackfaceVisibilityAncestorWithInterveningStackingDiv) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <!DOCTYPE html> + <style> + div { width: 100px; height: 100px } + </style> + <div style="backface-visibility: hidden; transform-style: preserve-3d"> + <div id=intermediate style="isolation: isolate"> + <div id=target style="position: relative"></div> + </div> + </div> + )HTML"); + + PaintLayer* intermediate_layer = + ToLayoutBoxModelObject(GetLayoutObjectByElementId("intermediate")) + ->Layer(); + + PaintLayer* target_layer = + ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); + + EXPECT_EQ(CompositingReason::kBackfaceInvisibility3DAncestor, + intermediate_layer->PotentialCompositingReasonsFromNonStyle()); + EXPECT_EQ(kPaintsIntoOwnBacking, intermediate_layer->GetCompositingState()); + + EXPECT_EQ(CompositingReason::kNone, + target_layer->PotentialCompositingReasonsFromNonStyle()); + EXPECT_NE(kPaintsIntoOwnBacking, target_layer->GetCompositingState()); +} + +TEST_F(CompositingReasonFinderTest, + CompositeWithBackfaceVisibilityAncestorAndFlattening) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <!DOCTYPE html> + <style> + div { width: 100px; height: 100px; position: relative } + </style> + <div style="backface-visibility: hidden;"> + <div id=target></div> + </div> + )HTML"); + + PaintLayer* target_layer = + ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); + + EXPECT_EQ(CompositingReason::kNone, + target_layer->PotentialCompositingReasonsFromNonStyle()); + EXPECT_NE(kPaintsIntoOwnBacking, target_layer->GetCompositingState()); +} + +TEST_F(CompositingReasonFinderTest, CompositeWithBackfaceVisibility) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <!DOCTYPE html> + <style> + div { width: 100px; height: 100px; position: relative } + </style> + <div id=target style="backface-visibility: hidden;"> + <div></div> + </div> + )HTML"); + + PaintLayer* target_layer = + ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); + + EXPECT_EQ(CompositingReason::kNone, + target_layer->PotentialCompositingReasonsFromNonStyle()); + EXPECT_EQ(kPaintsIntoOwnBacking, target_layer->GetCompositingState()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc index 50d06c46..69468c5 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
@@ -613,7 +613,6 @@ // At this point we have finished collecting all reasons to composite this // layer. layer->SetCompositingReasons(reasons_to_composite); - // If we've skipped recursing down to children but children needed an // update, remember this on the display lock context, so that we can restore // the dirty bit when the lock is unlocked.
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 29b084c..ea0a8a1 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -708,6 +708,10 @@ reasons |= CompositingReason::kWillChangeOpacity; reasons |= CompositingReason::kWillChangeFilter; reasons |= CompositingReason::kWillChangeBackdropFilter; + + if (RuntimeEnabledFeatures::TransformInteropEnabled()) + reasons |= CompositingReason::kBackfaceInvisibility3DAncestor; + return reasons; } @@ -840,6 +844,9 @@ } } + // properties_->Transform() is present if a CSS transform is present, + // and is also present if transform-style: preserve-3d is set. + // See NeedsTransform. if (properties_->Transform()) { context_.current.transform = properties_->Transform(); if (object_.StyleRef().Preserves3D()) { @@ -850,6 +857,12 @@ context_.current.rendering_context_id = 0; context_.current.should_flatten_inherited_transform = true; } + } else if (RuntimeEnabledFeatures::TransformInteropEnabled()) { + // With kTransformInterop enabled, 3D rendering contexts follow the + // DOM ancestor chain, so flattening should apply regardless of + // presence of transform. + context_.current.rendering_context_id = 0; + context_.current.should_flatten_inherited_transform = true; } } @@ -2602,6 +2615,12 @@ UpdateCssClip(); UpdateFilter(); UpdateOverflowControlsClip(); + } else if (RuntimeEnabledFeatures::TransformInteropEnabled()) { + // With kTransformInterop enabled, 3D rendering contexts follow the + // DOM ancestor chain, so flattening should apply regardless of + // presence of transform. + context_.current.rendering_context_id = 0; + context_.current.should_flatten_inherited_transform = true; } UpdateLocalBorderBoxContext(); }
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 b72bed9..97bca4a0c 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
@@ -803,6 +803,30 @@ GetDocument().View()->GetLayoutView()); } +TEST_P(PaintPropertyTreeBuilderTest, + BackfaceVisibilityWithPseudoStacking3DChildren) { + ScopedTransformInteropForTest enabled(true); + // TODO(chrishtr): implement for CAP. This entails computing + // has_backface_invisible_ancestor_in_same_3d_context in the pre-paint tree + // walk. + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + return; + + SetBodyInnerHTML(R"HTML( + <div style="backface-visibility: hidden; transform-style: preserve-3d"> + <div id=child style="isolation: isolate"></div> + </div> + )HTML"); + + // The child needs a transform node to communicate that it is backface + // visible to the compositor. + EXPECT_NE(nullptr, PaintPropertiesForElement("child")->Transform()); + EXPECT_EQ(PaintPropertiesForElement("child") + ->Transform() + ->GetBackfaceVisibilityForTesting(), + TransformPaintPropertyNode::BackfaceVisibility::kVisible); +} + TEST_P(PaintPropertyTreeBuilderTest, NoEffectAndFilterForNonStackingContext) { SetBodyInnerHTML(R"HTML( <div id="target" style="will-change: right; backface-visibility: hidden"> @@ -2864,7 +2888,9 @@ EXPECT_NE(a_properties->Transform(), b_properties->Transform()); if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { EXPECT_TRUE(a_properties->Transform()->HasRenderingContext()); + EXPECT_FALSE(a_properties->Transform()->FlattensInheritedTransform()); EXPECT_TRUE(b_properties->Transform()->HasRenderingContext()); + EXPECT_FALSE(b_properties->Transform()->FlattensInheritedTransform()); EXPECT_EQ(a_properties->Transform()->RenderingContextId(), b_properties->Transform()->RenderingContextId()); } @@ -2874,6 +2900,94 @@ frame_view->GetLayoutView()); } +TEST_P(PaintPropertyTreeBuilderTest, + IntermediateElementPreventsSharedRenderingContext) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <div id='parent' style='transform-style: preserve-3d'> + <div> + <div id='a' style='transform: translateZ(0); width: 30px; height: 40px'> + </div> + </div> + <div id='b' style='transform: translateZ(0); width: 20px; height: 10px'> + </div> + </div> + )HTML"); + LocalFrameView* frame_view = GetDocument().View(); + + LayoutObject* a = GetLayoutObjectByElementId("a"); + const ObjectPaintProperties* a_properties = + a->FirstFragment().PaintProperties(); + LayoutObject* b = GetLayoutObjectByElementId("b"); + const ObjectPaintProperties* b_properties = + b->FirstFragment().PaintProperties(); + ASSERT_TRUE(a_properties->Transform() && b_properties->Transform()); + EXPECT_NE(a_properties->Transform(), b_properties->Transform()); + + const ObjectPaintProperties* parent_properties = + b->FirstFragment().PaintProperties(); + + EXPECT_FALSE(a_properties->Transform()->HasRenderingContext()); + EXPECT_TRUE(a_properties->Transform()->FlattensInheritedTransform()); + EXPECT_TRUE(b_properties->Transform()->HasRenderingContext()); + EXPECT_FALSE(b_properties->Transform()->FlattensInheritedTransform()); + EXPECT_NE(a_properties->Transform()->RenderingContextId(), + b_properties->Transform()->RenderingContextId()); + + EXPECT_EQ(parent_properties->Transform()->RenderingContextId(), + b_properties->Transform()->RenderingContextId()); + + CHECK_EXACT_VISUAL_RECT(PhysicalRect(8, 8, 30, 40), a, + frame_view->GetLayoutView()); + CHECK_EXACT_VISUAL_RECT(PhysicalRect(8, 48, 20, 10), b, + frame_view->GetLayoutView()); +} + +TEST_P(PaintPropertyTreeBuilderTest, + IntermediateElementWithPropertiesPreventsSharedRenderingContext) { + ScopedTransformInteropForTest enabled(true); + + SetBodyInnerHTML(R"HTML( + <div id='parent' style='transform-style: preserve-3d'> + <div style="overflow: hidden"> + <div id='a' style='transform: translateZ(0); width: 30px; height: 40px'> + </div> + </div> + <div id='b' style='transform: translateZ(0); width: 20px; height: 10px'> + </div> + </div> + )HTML"); + LocalFrameView* frame_view = GetDocument().View(); + + LayoutObject* a = GetLayoutObjectByElementId("a"); + const ObjectPaintProperties* a_properties = + a->FirstFragment().PaintProperties(); + LayoutObject* b = GetLayoutObjectByElementId("b"); + const ObjectPaintProperties* b_properties = + b->FirstFragment().PaintProperties(); + ASSERT_TRUE(a_properties->Transform() && b_properties->Transform()); + EXPECT_NE(a_properties->Transform(), b_properties->Transform()); + + const ObjectPaintProperties* parent_properties = + b->FirstFragment().PaintProperties(); + + EXPECT_FALSE(a_properties->Transform()->HasRenderingContext()); + EXPECT_TRUE(a_properties->Transform()->FlattensInheritedTransform()); + EXPECT_TRUE(b_properties->Transform()->HasRenderingContext()); + EXPECT_FALSE(b_properties->Transform()->FlattensInheritedTransform()); + EXPECT_NE(a_properties->Transform()->RenderingContextId(), + b_properties->Transform()->RenderingContextId()); + + EXPECT_EQ(parent_properties->Transform()->RenderingContextId(), + b_properties->Transform()->RenderingContextId()); + + CHECK_EXACT_VISUAL_RECT(PhysicalRect(8, 8, 30, 40), a, + frame_view->GetLayoutView()); + CHECK_EXACT_VISUAL_RECT(PhysicalRect(8, 48, 20, 10), b, + frame_view->GetLayoutView()); +} + TEST_P(PaintPropertyTreeBuilderTest, FlatTransformStyleEndsRenderingContext) { SetBodyInnerHTML(R"HTML( <style>
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 9bd005c..5d2473f 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -1050,6 +1050,17 @@ return false; } +bool ComputedStyle::HasGroupingProperty() const { + if (RuntimeEnabledFeatures::TransformInteropEnabled() && + (HasNonInitialBackdropFilter() || HasBlendMode() || + (!HasAutoClip() && HasOutOfFlowPosition()) || ClipPath() || + HasIsolation() || HasMask())) + return true; + + return !IsOverflowVisible() || HasFilterInducingProperty() || + HasNonInitialOpacity(); +} + void ComputedStyle::UpdateIsStackingContextWithoutContainment( bool is_document_element, bool is_in_top_layer,
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index cd77b28..e8fc5100 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2393,10 +2393,7 @@ // Note: We currently don't include every grouping property on the spec to // maintain backward compatibility. [css-transforms] // https://drafts.csswg.org/css-transforms/#grouping-property-values - bool HasGroupingProperty() const { - return !IsOverflowVisible() || HasFilterInducingProperty() || - HasNonInitialOpacity(); - } + CORE_EXPORT bool HasGroupingProperty() const; // Return true if any transform related property (currently // transform/motionPath, transformStyle3D, perspective, or
diff --git a/third_party/blink/renderer/core/timing/performance_mark.cc b/third_party/blink/renderer/core/timing/performance_mark.cc index f6eb133b..f4346b0e 100644 --- a/third_party/blink/renderer/core/timing/performance_mark.cc +++ b/third_party/blink/renderer/core/timing/performance_mark.cc
@@ -54,7 +54,8 @@ start = performance->now(); } - detail = mark_options->detail(); + if (mark_options->hasDetail()) + detail = mark_options->detail(); } else { start = performance->now(); } @@ -69,16 +70,13 @@ return nullptr; } - scoped_refptr<SerializedScriptValue> serialized_detail; - if (detail.IsEmpty()) { - serialized_detail = SerializedScriptValue::NullValue(); - } else { - serialized_detail = SerializedScriptValue::Serialize( - script_state->GetIsolate(), detail.V8Value(), - SerializedScriptValue::SerializeOptions(), exception_state); - if (exception_state.HadException()) - return nullptr; - } + scoped_refptr<SerializedScriptValue> serialized_detail = + SerializedScriptValue::Serialize( + script_state->GetIsolate(), detail.V8Value(), + SerializedScriptValue::SerializeOptions(), exception_state); + if (exception_state.HadException()) + return nullptr; + return MakeGarbageCollected<PerformanceMark>( mark_name, start, std::move(serialized_detail), exception_state); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index 6c2da96..7fd9f6d 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -2194,15 +2194,26 @@ } AtomicString AXLayoutObject::Language() const { + if (!GetLayoutObject()) + return AXNodeObject::Language(); + + // If it's the root, get the computed language for the document element, + // because the root LayoutObject doesn't have the right value. + if (RoleValue() == ax::mojom::blink::Role::kRootWebArea) { + Element* document_element = GetDocument()->documentElement(); + if (!document_element) + return g_empty_atom; + + AtomicString lang = document_element->ComputeInheritedLanguage(); + if (!lang.IsEmpty()) + return lang; + } + // Uses the style engine to figure out the object's language. // The style engine relies on, for example, the "lang" attribute of the // current node and its ancestors, and the document's "content-language" // header. See the Language of a Node Spec at // https://html.spec.whatwg.org/C/#language - - if (!GetLayoutObject()) - return AXNodeObject::Language(); - const ComputedStyle* style = GetLayoutObject()->Style(); if (!style || !style->Locale()) return AXNodeObject::Language();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index f9eb203..f0ce26b 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -777,6 +777,9 @@ if (IsSelected() != blink::kSelectedStateUndefined) { node_data->AddBoolAttribute(ax::mojom::blink::BoolAttribute::kSelected, IsSelected() == blink::kSelectedStateTrue); + node_data->AddBoolAttribute( + ax::mojom::blink::BoolAttribute::kSelectedFromFocus, + IsSelectedFromFocus()); } if (IsRichlyEditable())
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc index 35cc9bd..b80a8696 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -391,8 +391,10 @@ // regular animations, we should not detach them immediately and update the // value in the next frame. See https://crbug.com/883312. if (IsActive(play_state_)) { - for (auto& effect : effects_) - effect->UpdateInheritedTime(base::nullopt, kTimingUpdateOnDemand); + for (auto& effect : effects_) { + effect->UpdateInheritedTime(base::nullopt, base::nullopt, + kTimingUpdateOnDemand); + } } SetPlayState(Animation::kIdle); SetCurrentTime(base::nullopt); @@ -476,7 +478,7 @@ effects_[i]->UpdateInheritedTime( local_times_[i] ? base::Optional<double>(local_times_[i]->InSecondsF()) : base::nullopt, - reason); + base::nullopt, reason); } }
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc index 21172d7..03d206c2 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc
@@ -36,7 +36,7 @@ // include that information, we do not need to supply one. base::Optional<double> playback_rate = base::nullopt; calculated_ = specified_timing_.CalculateTimings( - local_time, Timing::AnimationDirection::kForwards, false, + local_time, base::nullopt, Timing::AnimationDirection::kForwards, false, playback_rate); }
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_client.cc b/third_party/blink/renderer/modules/mediastream/user_media_client.cc index 07a8fd9..c8dbef8 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_client.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_client.cc
@@ -50,20 +50,19 @@ : user_media_request_(user_media_request) { DCHECK(user_media_request_); DCHECK(!apply_constraints_request_); - DCHECK(web_track_to_stop_.IsNull()); + DCHECK(!track_to_stop_); } UserMediaClient::Request::Request(blink::ApplyConstraintsRequest* request) : apply_constraints_request_(request) { DCHECK(apply_constraints_request_); DCHECK(!user_media_request_); - DCHECK(web_track_to_stop_.IsNull()); + DCHECK(!track_to_stop_); } -UserMediaClient::Request::Request( - const blink::WebMediaStreamTrack& web_track_to_stop) - : web_track_to_stop_(web_track_to_stop) { - DCHECK(!web_track_to_stop_.IsNull()); +UserMediaClient::Request::Request(MediaStreamComponent* track_to_stop) + : track_to_stop_(track_to_stop) { + DCHECK(track_to_stop_); DCHECK(!user_media_request_); DCHECK(!apply_constraints_request_); } @@ -184,8 +183,8 @@ MaybeProcessNextRequestInfo(); } -void UserMediaClient::StopTrack(const blink::WebMediaStreamTrack& web_track) { - pending_request_infos_.push_back(MakeGarbageCollected<Request>(web_track)); +void UserMediaClient::StopTrack(MediaStreamComponent* track) { + pending_request_infos_.push_back(MakeGarbageCollected<Request>(track)); if (!is_processing_request_) MaybeProcessNextRequestInfo(); } @@ -217,7 +216,7 @@ DCHECK(current_request->IsStopTrack()); blink::WebPlatformMediaStreamTrack* track = blink::WebPlatformMediaStreamTrack::GetTrack( - current_request->web_track_to_stop()); + current_request->track_to_stop()); if (track) { track->StopAndNotify(WTF::Bind(&UserMediaClient::CurrentRequestCompleted, WrapWeakPersistent(this)));
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_client.h b/third_party/blink/renderer/modules/mediastream/user_media_client.h index 1dc55d2..f56f66e7 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_client.h +++ b/third_party/blink/renderer/modules/mediastream/user_media_client.h
@@ -18,6 +18,7 @@ #include "third_party/blink/renderer/modules/mediastream/user_media_processor.h" #include "third_party/blink/renderer/modules/mediastream/user_media_request.h" #include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" #include "third_party/blink/renderer/platform/wtf/deque.h" @@ -51,7 +52,7 @@ void RequestUserMedia(UserMediaRequest* user_media_request); void CancelUserMediaRequest(UserMediaRequest* user_media_request); void ApplyConstraints(blink::ApplyConstraintsRequest* user_media_request); - void StopTrack(const blink::WebMediaStreamTrack& web_track); + void StopTrack(MediaStreamComponent* track); void ContextDestroyed(); bool IsCapturing(); @@ -67,7 +68,7 @@ public: explicit Request(UserMediaRequest* request); explicit Request(blink::ApplyConstraintsRequest* request); - explicit Request(const blink::WebMediaStreamTrack& request); + explicit Request(MediaStreamComponent* request); ~Request(); UserMediaRequest* MoveUserMediaRequest(); @@ -76,23 +77,22 @@ blink::ApplyConstraintsRequest* apply_constraints_request() const { return apply_constraints_request_; } - const blink::WebMediaStreamTrack& web_track_to_stop() const { - return web_track_to_stop_; - } + MediaStreamComponent* track_to_stop() const { return track_to_stop_; } bool IsUserMedia() const { return !!user_media_request_; } - bool IsApplyConstraints() const { return apply_constraints_request_; } - bool IsStopTrack() const { return !web_track_to_stop_.IsNull(); } + bool IsApplyConstraints() const { return !!apply_constraints_request_; } + bool IsStopTrack() const { return !!track_to_stop_; } void Trace(Visitor* visitor) const { visitor->Trace(user_media_request_); visitor->Trace(apply_constraints_request_); + visitor->Trace(track_to_stop_); } private: Member<UserMediaRequest> user_media_request_; Member<blink::ApplyConstraintsRequest> apply_constraints_request_; - blink::WebMediaStreamTrack web_track_to_stop_; + Member<MediaStreamComponent> track_to_stop_; DISALLOW_COPY_AND_ASSIGN(Request); };
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_controller.h b/third_party/blink/renderer/modules/mediastream/user_media_controller.h index 6a63ce86..c919757 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_controller.h +++ b/third_party/blink/renderer/modules/mediastream/user_media_controller.h
@@ -82,7 +82,7 @@ } inline void UserMediaController::StopTrack(MediaStreamComponent* track) { - Client()->StopTrack(WebMediaStreamTrack(track)); + Client()->StopTrack(track); } inline bool UserMediaController::HasRequestedUserMedia() {
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc index 4ea24dc..ed1b81a 100644 --- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc +++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
@@ -40,6 +40,9 @@ #include "third_party/blink/renderer/modules/mediastream/media_stream_local_frame_wrapper.h" #include "third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h" +#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h" +#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h" +#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/timer.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" @@ -52,10 +55,10 @@ NEW_RENDERER }; -bool IsPlayableTrack(const blink::WebMediaStreamTrack& track) { - return !track.IsNull() && !track.Source().IsNull() && - track.Source().GetReadyState() != - blink::WebMediaStreamSource::kReadyStateEnded; +bool IsPlayableTrack(blink::MediaStreamComponent* component) { + return component && component->Source() && + component->Source()->GetReadyState() != + blink::MediaStreamSource::kReadyStateEnded; } const char* LoadTypeToString(blink::WebMediaPlayer::LoadType type) { @@ -467,9 +470,10 @@ // Store the ID of audio track being played in |current_audio_track_id_|. if (!web_stream_.IsNull()) { - WebVector<WebMediaStreamTrack> audio_tracks = web_stream_.AudioTracks(); - DCHECK_GT(audio_tracks.size(), 0U); - current_audio_track_id_ = audio_tracks[0].Id(); + MediaStreamDescriptor& descriptor = *web_stream_; + auto audio_components = descriptor.AudioComponents(); + DCHECK_GT(audio_components.size(), 0U); + current_audio_track_id_ = WebString(audio_components[0]->Id()); SendLogMessage(String::Format("%s => (audio_track_id=%s)", __func__, current_audio_track_id_.Utf8().c_str())); } @@ -480,9 +484,10 @@ // Store the ID of video track being played in |current_video_track_id_|. if (!web_stream_.IsNull()) { - WebVector<WebMediaStreamTrack> video_tracks = web_stream_.VideoTracks(); - DCHECK_GT(video_tracks.size(), 0U); - current_video_track_id_ = video_tracks[0].Id(); + MediaStreamDescriptor& descriptor = *web_stream_; + auto video_components = descriptor.VideoComponents(); + DCHECK_GT(video_components.size(), 0U); + current_video_track_id_ = WebString(video_components[0]->Id()); SendLogMessage(String::Format("%s => (video_track_id=%s)", __func__, current_video_track_id_.Utf8().c_str())); } @@ -586,17 +591,18 @@ void WebMediaPlayerMS::ReloadVideo() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!web_stream_.IsNull()); - WebVector<WebMediaStreamTrack> video_tracks = web_stream_.VideoTracks(); + MediaStreamDescriptor& descriptor = *web_stream_; + auto video_components = descriptor.VideoComponents(); RendererReloadAction renderer_action = RendererReloadAction::KEEP_RENDERER; - if (video_tracks.empty()) { + if (video_components.IsEmpty()) { if (video_frame_provider_) renderer_action = RendererReloadAction::REMOVE_RENDERER; current_video_track_id_ = WebString(); - } else if (video_tracks[0].Id() != current_video_track_id_ && - IsPlayableTrack(video_tracks[0])) { + } else if (WebString(video_components[0]->Id()) != current_video_track_id_ && + IsPlayableTrack(video_components[0])) { renderer_action = RendererReloadAction::NEW_RENDERER; - current_video_track_id_ = video_tracks[0].Id(); + current_video_track_id_ = video_components[0]->Id(); } switch (renderer_action) { @@ -635,17 +641,18 @@ return; SendLogMessage(String::Format("%s()", __func__)); - WebVector<WebMediaStreamTrack> audio_tracks = web_stream_.AudioTracks(); + MediaStreamDescriptor& descriptor = *web_stream_; + auto audio_components = descriptor.AudioComponents(); RendererReloadAction renderer_action = RendererReloadAction::KEEP_RENDERER; - if (audio_tracks.empty()) { + if (audio_components.IsEmpty()) { if (audio_renderer_) renderer_action = RendererReloadAction::REMOVE_RENDERER; current_audio_track_id_ = WebString(); - } else if (audio_tracks[0].Id() != current_audio_track_id_ && - IsPlayableTrack(audio_tracks[0])) { + } else if (WebString(audio_components[0]->Id()) != current_audio_track_id_ && + IsPlayableTrack(audio_components[0])) { renderer_action = RendererReloadAction::NEW_RENDERER; - current_audio_track_id_ = audio_tracks[0].Id(); + current_audio_track_id_ = audio_components[0]->Id(); } switch (renderer_action) {
diff --git a/third_party/blink/renderer/modules/native_file_system/BUILD.gn b/third_party/blink/renderer/modules/native_file_system/BUILD.gn index c248e70..b03d53e5 100644 --- a/third_party/blink/renderer/modules/native_file_system/BUILD.gn +++ b/third_party/blink/renderer/modules/native_file_system/BUILD.gn
@@ -6,6 +6,8 @@ blink_modules_sources("native_file_system") { sources = [ + "global_native_file_system.cc", + "global_native_file_system.h", "native_file_system_directory_handle.cc", "native_file_system_directory_handle.h", "native_file_system_directory_iterator.cc", @@ -22,8 +24,6 @@ "native_file_system_writable_file_stream.h", "native_file_system_writer.cc", "native_file_system_writer.h", - "window_native_file_system.cc", - "window_native_file_system.h", ] deps = [ "//third_party/blink/renderer/platform" ] @@ -31,7 +31,7 @@ jumbo_source_set("unit_tests") { testonly = true - sources = [ "window_native_file_system_test.cc" ] + sources = [ "global_native_file_system_test.cc" ] configs += [ "//third_party/blink/renderer:config",
diff --git a/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc b/third_party/blink/renderer/modules/native_file_system/global_native_file_system.cc similarity index 72% rename from third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc rename to third_party/blink/renderer/modules/native_file_system/global_native_file_system.cc index 52dbcf37..ab58499 100644 --- a/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc +++ b/third_party/blink/renderer/modules/native_file_system/global_native_file_system.cc
@@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/native_file_system/window_native_file_system.h" +#include "third_party/blink/renderer/modules/native_file_system/global_native_file_system.h" #include <utility> +#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" @@ -15,19 +16,24 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_choose_file_system_entries_options_accepts.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" +#include "third_party/blink/renderer/core/execution_context/security_context.h" #include "third_party/blink/renderer/core/fileapi/file_error.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { namespace { +// The name to use for the root directory of a sandboxed file system. +constexpr const char kSandboxRootDirectoryName[] = ""; mojom::blink::ChooseFileSystemEntryType ConvertChooserType(const String& input, bool multiple) { @@ -58,10 +64,55 @@ return result; } +ScriptPromise GetOriginPrivateDirectoryImpl(ScriptState* script_state, + ExceptionState& exception_state) { + ExecutionContext* context = ExecutionContext::From(script_state); + if (!context->GetSecurityOrigin()->CanAccessNativeFileSystem()) { + if (context->GetSecurityContext().IsSandboxed( + network::mojom::blink::WebSandboxFlags::kOrigin)) { + exception_state.ThrowSecurityError( + "System directory access is denied because the context is " + "sandboxed and lacks the 'allow-same-origin' flag."); + return ScriptPromise(); + } else { + exception_state.ThrowSecurityError("System directory access is denied."); + return ScriptPromise(); + } + } + + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); + ScriptPromise result = resolver->Promise(); + + mojo::Remote<mojom::blink::NativeFileSystemManager> manager; + context->GetBrowserInterfaceBroker().GetInterface( + manager.BindNewPipeAndPassReceiver()); + + auto* raw_manager = manager.get(); + raw_manager->GetSandboxedFileSystem(WTF::Bind( + [](ScriptPromiseResolver* resolver, + mojo::Remote<mojom::blink::NativeFileSystemManager>, + mojom::blink::NativeFileSystemErrorPtr result, + mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle> + handle) { + ExecutionContext* context = resolver->GetExecutionContext(); + if (!context) + return; + if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + native_file_system_error::Reject(resolver, *result); + return; + } + resolver->Resolve(MakeGarbageCollected<NativeFileSystemDirectoryHandle>( + context, kSandboxRootDirectoryName, std::move(handle))); + }, + WrapPersistent(resolver), std::move(manager))); + + return result; +} + } // namespace // static -ScriptPromise WindowNativeFileSystem::chooseFileSystemEntries( +ScriptPromise GlobalNativeFileSystem::chooseFileSystemEntries( ScriptState* script_state, LocalDOMWindow& window, const ChooseFileSystemEntriesOptions* options, @@ -167,4 +218,18 @@ return resolver_result; } +ScriptPromise GlobalNativeFileSystem::getOriginPrivateDirectory( + ScriptState* script_state, + const LocalDOMWindow& window, + ExceptionState& exception_state) { + return GetOriginPrivateDirectoryImpl(script_state, exception_state); +} + +ScriptPromise GlobalNativeFileSystem::getOriginPrivateDirectory( + ScriptState* script_state, + const WorkerGlobalScope& workerGlobalScope, + ExceptionState& exception_state) { + return GetOriginPrivateDirectoryImpl(script_state, exception_state); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/native_file_system/global_native_file_system.h b/third_party/blink/renderer/modules/native_file_system/global_native_file_system.h new file mode 100644 index 0000000..26de12f --- /dev/null +++ b/third_party/blink/renderer/modules/native_file_system/global_native_file_system.h
@@ -0,0 +1,40 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_GLOBAL_NATIVE_FILE_SYSTEM_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_GLOBAL_NATIVE_FILE_SYSTEM_H_ + +#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" + +namespace blink { + +class ChooseFileSystemEntriesOptions; +class ExceptionState; +class LocalDOMWindow; +class ScriptPromise; +class ScriptState; +class WorkerGlobalScope; + +class GlobalNativeFileSystem { + STATIC_ONLY(GlobalNativeFileSystem); + + public: + static ScriptPromise chooseFileSystemEntries( + ScriptState*, + LocalDOMWindow&, + const ChooseFileSystemEntriesOptions*, + ExceptionState&); + + static ScriptPromise getOriginPrivateDirectory(ScriptState*, + const LocalDOMWindow&, + ExceptionState&); + static ScriptPromise getOriginPrivateDirectory(ScriptState*, + const WorkerGlobalScope&, + ExceptionState&); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_GLOBAL_NATIVE_FILE_SYSTEM_H_
diff --git a/third_party/blink/renderer/modules/native_file_system/window_native_file_system_test.cc b/third_party/blink/renderer/modules/native_file_system/global_native_file_system_test.cc similarity index 96% rename from third_party/blink/renderer/modules/native_file_system/window_native_file_system_test.cc rename to third_party/blink/renderer/modules/native_file_system/global_native_file_system_test.cc index 476b6549..aedf47d 100644 --- a/third_party/blink/renderer/modules/native_file_system/window_native_file_system_test.cc +++ b/third_party/blink/renderer/modules/native_file_system/global_native_file_system_test.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/native_file_system/window_native_file_system.h" +#include "third_party/blink/renderer/modules/native_file_system/global_native_file_system.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" @@ -97,7 +97,7 @@ BrowserInterfaceBrokerProxy& broker_; }; -class WindowNativeFileSystemTest : public PageTestBase { +class GlobalNativeFileSystemTest : public PageTestBase { public: void SetUp() override { PageTestBase::SetUp(); @@ -116,7 +116,7 @@ } }; -TEST_F(WindowNativeFileSystemTest, UserActivationRequiredOtherwiseDenied) { +TEST_F(GlobalNativeFileSystemTest, UserActivationRequiredOtherwiseDenied) { LocalFrame* frame = &GetFrame(); EXPECT_FALSE(frame->HasStickyUserActivation()); @@ -131,7 +131,7 @@ EXPECT_FALSE(frame->HasStickyUserActivation()); } -TEST_F(WindowNativeFileSystemTest, UserActivationChooseEntriesSuccessful) { +TEST_F(GlobalNativeFileSystemTest, UserActivationChooseEntriesSuccessful) { LocalFrame* frame = &GetFrame(); EXPECT_FALSE(frame->HasStickyUserActivation()); @@ -174,7 +174,7 @@ EXPECT_TRUE(frame->HasStickyUserActivation()); } -TEST_F(WindowNativeFileSystemTest, UserActivationChooseEntriesErrors) { +TEST_F(GlobalNativeFileSystemTest, UserActivationChooseEntriesErrors) { LocalFrame* frame = &GetFrame(); EXPECT_FALSE(frame->HasStickyUserActivation());
diff --git a/third_party/blink/renderer/modules/native_file_system/idls.gni b/third_party/blink/renderer/modules/native_file_system/idls.gni index 490d4ad4..f7dc014 100644 --- a/third_party/blink/renderer/modules/native_file_system/idls.gni +++ b/third_party/blink/renderer/modules/native_file_system/idls.gni
@@ -24,4 +24,7 @@ "write_params.idl", ] -modules_dependency_idl_files = [ "window_native_file_system.idl" ] +modules_dependency_idl_files = [ + "window_native_file_system.idl", + "worker_global_scope_native_file_system.idl", +]
diff --git a/third_party/blink/renderer/modules/native_file_system/window_native_file_system.h b/third_party/blink/renderer/modules/native_file_system/window_native_file_system.h deleted file mode 100644 index 8f4926a..0000000 --- a/third_party/blink/renderer/modules/native_file_system/window_native_file_system.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_WINDOW_NATIVE_FILE_SYSTEM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_WINDOW_NATIVE_FILE_SYSTEM_H_ - -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -class ChooseFileSystemEntriesOptions; -class ExceptionState; -class LocalDOMWindow; -class ScriptPromise; -class ScriptState; - -class WindowNativeFileSystem { - STATIC_ONLY(WindowNativeFileSystem); - - public: - static ScriptPromise chooseFileSystemEntries( - ScriptState*, - LocalDOMWindow&, - const ChooseFileSystemEntriesOptions*, - ExceptionState&); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_WINDOW_NATIVE_FILE_SYSTEM_H_
diff --git a/third_party/blink/renderer/modules/native_file_system/window_native_file_system.idl b/third_party/blink/renderer/modules/native_file_system/window_native_file_system.idl index fae73c8..9f30fb7 100644 --- a/third_party/blink/renderer/modules/native_file_system/window_native_file_system.idl +++ b/third_party/blink/renderer/modules/native_file_system/window_native_file_system.idl
@@ -3,12 +3,15 @@ // found in the LICENSE file. // https://wicg.github.io/native-file-system/#api-choosefilesystementries +// https://wicg.github.io/native-file-system/#api-getoriginprivatefilesystem [ SecureContext, RuntimeEnabled=NativeFileSystem, - ImplementedAs=WindowNativeFileSystem + ImplementedAs=GlobalNativeFileSystem ] partial interface Window { [CallWith=ScriptState, Measure, RaisesException] Promise<(FileSystemHandle or sequence<FileSystemHandle>)> chooseFileSystemEntries(optional ChooseFileSystemEntriesOptions options = {}); -}; + [CallWith=ScriptState, RaisesException] + Promise<FileSystemDirectoryHandle> getOriginPrivateDirectory(); +}; \ No newline at end of file
diff --git a/third_party/blink/renderer/modules/native_file_system/worker_global_scope_native_file_system.idl b/third_party/blink/renderer/modules/native_file_system/worker_global_scope_native_file_system.idl new file mode 100644 index 0000000..eaf542b4 --- /dev/null +++ b/third_party/blink/renderer/modules/native_file_system/worker_global_scope_native_file_system.idl
@@ -0,0 +1,13 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://wicg.github.io/native-file-system/#api-getoriginprivatefilesystem +[ + SecureContext, + RuntimeEnabled=NativeFileSystem, + ImplementedAs=GlobalNativeFileSystem +] partial interface WorkerGlobalScope { + [CallWith=ScriptState, RaisesException] + Promise<FileSystemDirectoryHandle> getOriginPrivateDirectory(); +};
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 5b83853af..8dc759ca 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -37,6 +37,8 @@ #include "gpu/command_buffer/common/capabilities.h" #include "gpu/config/gpu_feature_info.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h" +#include "third_party/blink/public/common/privacy_budget/identifiability_study_participation.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/modules/v8/html_canvas_element_or_offscreen_canvas.h" @@ -840,12 +842,14 @@ // Exposed by GL_ANGLE_depth_texture static const GLenum kSupportedInternalFormatsOESDepthTex[] = { - GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, + GL_DEPTH_COMPONENT, + GL_DEPTH_STENCIL, }; // Exposed by GL_EXT_sRGB static const GLenum kSupportedInternalFormatsEXTsRGB[] = { - GL_SRGB, GL_SRGB_ALPHA_EXT, + GL_SRGB, + GL_SRGB_ALPHA_EXT, }; // ES3 enums supported by both CopyTexImage and TexImage. @@ -916,12 +920,14 @@ // Exposed by GL_ANGLE_depth_texture static const GLenum kSupportedFormatsOESDepthTex[] = { - GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, + GL_DEPTH_COMPONENT, + GL_DEPTH_STENCIL, }; // Exposed by GL_EXT_sRGB static const GLenum kSupportedFormatsEXTsRGB[] = { - GL_SRGB, GL_SRGB_ALPHA_EXT, + GL_SRGB, + GL_SRGB_ALPHA_EXT, }; // ES3 enums @@ -940,7 +946,9 @@ // ES2 enums static const GLenum kSupportedTypesES2[] = { - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_5_6_5, + GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, }; @@ -956,7 +964,9 @@ // Exposed by GL_ANGLE_depth_texture static const GLenum kSupportedTypesOESDepthTex[] = { - GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_UNSIGNED_INT_24_8, + GL_UNSIGNED_SHORT, + GL_UNSIGNED_INT, + GL_UNSIGNED_INT_24_8, }; // ES3 enums @@ -977,7 +987,9 @@ // ES3 enums supported by TexImageSource static const GLenum kSupportedTypesTexImageSourceES3[] = { - GL_HALF_FLOAT, GL_FLOAT, GL_UNSIGNED_INT_10F_11F_11F_REV, + GL_HALF_FLOAT, + GL_FLOAT, + GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_2_10_10_10_REV, }; @@ -3009,7 +3021,8 @@ const char* const* WebGLRenderingContextBase::ExtensionTracker::Prefixes() const { static const char* const kUnprefixed[] = { - "", nullptr, + "", + nullptr, }; return prefixes_ ? prefixes_ : kUnprefixed; } @@ -4424,6 +4437,17 @@ GLenum format, GLenum type, MaybeShared<DOMArrayBufferView> pixels) { + if (IsUserInIdentifiabilityStudy()) { + base::Optional<UkmParameters> ukm_params = ukm_parameters(); + if (ukm_params) { + blink::IdentifiabilityMetricBuilder(ukm_params->source_id) + .Set(blink::IdentifiableSurface::FromTypeAndInput( + blink::IdentifiableSurface::Type::kCanvasReadback, + GetContextType()), + 0) + .Record(ukm_params->ukm_recorder); + } + } ReadPixelsHelper(x, y, width, height, format, type, pixels.View(), 0); }
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h index bc090fe..9c7a530 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -40,6 +40,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h" #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h" +#include "third_party/blink/renderer/core/html/canvas/ukm_parameters.h" #include "third_party/blink/renderer/core/layout/content_change_type.h" #include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h" #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" @@ -67,7 +68,7 @@ namespace gles2 { class GLES2Interface; } -} +} // namespace gpu namespace blink { @@ -139,6 +140,10 @@ return static_cast<HTMLCanvasElement*>(Host()); } + base::Optional<UkmParameters> ukm_parameters() const { + return Host()->ukm_parameters(); + } + virtual String ContextName() const = 0; virtual void RegisterContextExtensions() = 0;
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 bcec1705..be8c341 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -58,6 +58,12 @@ RuntimeEnabledFeatures::SetWebBluetoothEnabled(enable); } +void WebRuntimeFeatures::EnableWebBluetoothRemoteCharacteristicNewWriteValue( + bool enable) { + RuntimeEnabledFeatures:: + SetWebBluetoothRemoteCharacteristicNewWriteValueEnabled(enable); +} + void WebRuntimeFeatures::EnableWebBluetoothScanning(bool enable) { RuntimeEnabledFeatures::SetWebBluetoothScanningEnabled(enable); } @@ -678,4 +684,8 @@ RuntimeEnabledFeatures::SetInstalledAppEnabled(enable); } +void WebRuntimeFeatures::EnableTransformInterop(bool enable) { + RuntimeEnabledFeatures::SetTransformInteropEnabled(enable); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc index 1e7e0c1..5b7afb2 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
@@ -115,9 +115,9 @@ cc_picture_layer_->SetIsDrawable( (!layer_bounds.IsEmpty() && cc_display_item_list_->TotalOpCount()) || - // Backdrop filters require the layer to be drawable even if the layer + // Backdrop effects require the layer to be drawable even if the layer // draws nothing. - !layer_state.Effect().BackdropFilter().IsEmpty()); + layer_state.Effect().HasBackdropEffect()); auto safe_opaque_background_color = paint_artifact->SafeOpaqueBackgroundColor(paint_chunks);
diff --git a/third_party/blink/renderer/platform/graphics/compositing_reasons.cc b/third_party/blink/renderer/platform/graphics/compositing_reasons.cc index 9fe5b9f081..84816206 100644 --- a/third_party/blink/renderer/platform/graphics/compositing_reasons.cc +++ b/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
@@ -132,6 +132,9 @@ "Layer painted on top of other layers as decoration"}, {CompositingReason::kLayerForOther, "layerForOther", "Layer for link highlight, frame overlay, etc."}, + {CompositingReason::kBackfaceInvisibility3DAncestor, + "BackfaceInvisibility3DAncestor", + "Ancestor in same 3D rendering context has a hidden backface"}, }; } // anonymous namespace
diff --git a/third_party/blink/renderer/platform/graphics/compositing_reasons.h b/third_party/blink/renderer/platform/graphics/compositing_reasons.h index abc15c0..efeb632 100644 --- a/third_party/blink/renderer/platform/graphics/compositing_reasons.h +++ b/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -36,6 +36,8 @@ V(WillChangeOpacity) \ V(WillChangeFilter) \ V(WillChangeBackdropFilter) \ + /* Reasons that depend on ancestor properties */ \ + V(BackfaceInvisibility3DAncestor) \ /* This flag is needed only when none of the explicit kWillChange* reasons \ are set. */ \ V(WillChangeOther) \ @@ -124,7 +126,8 @@ kComboAllDirectNonStyleDeterminedReasons = kVideo | kCanvas | kPlugin | kIFrame | kOverflowScrollingParent | kOutOfFlowClipping | kVideoOverlay | kXrOverlay | kRoot | - kRootScroller | kScrollDependentPosition, + kRootScroller | kScrollDependentPosition | + kBackfaceInvisibility3DAncestor, kComboAllDirectReasons = kComboAllDirectStyleDeterminedReasons | kComboAllDirectNonStyleDeterminedReasons,
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc b/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc index 6d957efd..ca91a27 100644 --- a/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc +++ b/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
@@ -16,6 +16,8 @@ #include "third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h" #include "third_party/blink/renderer/platform/graphics/graphics_context.h" #include "third_party/blink/renderer/platform/graphics/graphics_types.h" +#include "third_party/blink/renderer/platform/wtf/hash_functions.h" +#include "third_party/blink/renderer/platform/wtf/lru_cache.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/effects/SkColorMatrix.h" @@ -45,6 +47,8 @@ #endif // DCHECK_IS_ON() +const size_t kMaxCacheSize = 1024u; + bool ShouldApplyToImage(const DarkModeSettings& settings, const FloatRect& src_rect, const FloatRect& dest_rect, @@ -88,10 +92,36 @@ } // namespace +// DarkModeInvertedColorCache - Implements cache for inverted colors. +class DarkModeInvertedColorCache { + public: + DarkModeInvertedColorCache() : cache_(kMaxCacheSize) {} + ~DarkModeInvertedColorCache() = default; + + SkColor GetInvertedColor(DarkModeColorFilter* filter, SkColor color) { + WTF::IntegralWithAllKeys<SkColor> key(color); + SkColor* cached_value = cache_.Get(key); + if (cached_value) + return *cached_value; + + SkColor inverted_color = filter->InvertColor(Color(color)).Rgb(); + cache_.Put(key, std::move(inverted_color)); + return inverted_color; + } + + void Clear() { cache_.Clear(); } + + size_t size() { return cache_.size(); } + + private: + WTF::LruCache<WTF::IntegralWithAllKeys<SkColor>, SkColor> cache_; +}; + DarkModeFilter::DarkModeFilter() : text_classifier_(nullptr), color_filter_(nullptr), - image_filter_(nullptr) { + image_filter_(nullptr), + inverted_color_cache_(new DarkModeInvertedColorCache()) { DarkModeSettings default_settings; default_settings.mode = DarkModeInversionAlgorithm::kOff; UpdateSettings(default_settings); @@ -111,6 +141,8 @@ return; } + inverted_color_cache_->Clear(); + settings_ = new_settings; color_filter_ = DarkModeColorFilter::FromSettings(settings_); if (!color_filter_) { @@ -137,8 +169,11 @@ if (role_override_.has_value()) role = role_override_.value(); - if (ShouldApplyToColor(color, role)) - return color_filter_->InvertColor(color); + if (ShouldApplyToColor(color, role)) { + return Color(inverted_color_cache_->GetInvertedColor(color_filter_.get(), + color.Rgb())); + } + return color; } @@ -165,10 +200,8 @@ if (flags.HasShader()) { dark_mode_flags.setColorFilter(color_filter_->ToSkColorFilter()); } else if (ShouldApplyToColor(flags.getColor(), role)) { - Color inverted_color = color_filter_->InvertColor(flags.getColor()); - dark_mode_flags.setColor( - SkColorSetARGB(inverted_color.Alpha(), inverted_color.Red(), - inverted_color.Green(), inverted_color.Blue())); + dark_mode_flags.setColor(inverted_color_cache_->GetInvertedColor( + color_filter_.get(), flags.getColor())); } return base::make_optional<cc::PaintFlags>(std::move(dark_mode_flags)); @@ -213,6 +246,10 @@ NOTREACHED(); } +size_t DarkModeFilter::GetInvertedColorCacheSizeForTesting() { + return inverted_color_cache_->size(); +} + ScopedDarkModeElementRoleOverride::ScopedDarkModeElementRoleOverride( GraphicsContext* graphics_context, DarkModeFilter::ElementRole role)
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_filter.h b/third_party/blink/renderer/platform/graphics/dark_mode_filter.h index 56a926f..bfd71b2 100644 --- a/third_party/blink/renderer/platform/graphics/dark_mode_filter.h +++ b/third_party/blink/renderer/platform/graphics/dark_mode_filter.h
@@ -22,6 +22,7 @@ class DarkModeColorClassifier; class DarkModeColorFilter; class ScopedDarkModeElementRoleOverride; +class DarkModeInvertedColorCache; class PLATFORM_EXPORT DarkModeFilter { public: @@ -51,6 +52,7 @@ cc::PaintFlags* flags); SkColorFilter* GetImageFilterForTesting() { return image_filter_.get(); } + size_t GetInvertedColorCacheSizeForTesting(); private: friend class ScopedDarkModeElementRoleOverride; @@ -64,6 +66,7 @@ std::unique_ptr<DarkModeColorFilter> color_filter_; sk_sp<SkColorFilter> image_filter_; base::Optional<ElementRole> role_override_; + std::unique_ptr<DarkModeInvertedColorCache> inverted_color_cache_; }; // Temporarily override the element role for the scope of this object's
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc b/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc index 1324733..5905a85 100644 --- a/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc +++ b/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc
@@ -66,5 +66,56 @@ EXPECT_NE(nullptr, filter.GetImageFilterForTesting()); } +TEST(DarkModeFilterTest, InvertedColorCacheSize) { + DarkModeFilter filter; + DarkModeSettings settings; + + settings.mode = DarkModeInversionAlgorithm::kSimpleInvertForTesting; + filter.UpdateSettings(settings); + EXPECT_EQ(0u, filter.GetInvertedColorCacheSizeForTesting()); + EXPECT_EQ(Color::kBlack, + filter.InvertColorIfNeeded( + Color::kWhite, DarkModeFilter::ElementRole::kBackground)); + EXPECT_EQ(1u, filter.GetInvertedColorCacheSizeForTesting()); + // Should get cached value. + EXPECT_EQ(Color::kBlack, + filter.InvertColorIfNeeded( + Color::kWhite, DarkModeFilter::ElementRole::kBackground)); + EXPECT_EQ(1u, filter.GetInvertedColorCacheSizeForTesting()); + + // On changing DarkModeSettings, cache should be reset. + settings.mode = DarkModeInversionAlgorithm::kInvertLightness; + filter.UpdateSettings(settings); + EXPECT_EQ(0u, filter.GetInvertedColorCacheSizeForTesting()); +} + +TEST(DarkModeFilterTest, InvertedColorCacheZeroMaxKeys) { + DarkModeFilter filter; + DarkModeSettings settings; + settings.mode = DarkModeInversionAlgorithm::kSimpleInvertForTesting; + filter.UpdateSettings(settings); + + EXPECT_EQ(0u, filter.GetInvertedColorCacheSizeForTesting()); + EXPECT_EQ(Color::kBlack, filter.InvertColorIfNeeded( + Color(SK_ColorWHITE), + DarkModeFilter::ElementRole::kBackground)); + EXPECT_EQ(1u, filter.GetInvertedColorCacheSizeForTesting()); + EXPECT_EQ( + Color(SK_ColorTRANSPARENT), + filter.InvertColorIfNeeded(Color(SK_ColorTRANSPARENT), + DarkModeFilter::ElementRole::kBackground)); + EXPECT_EQ(2u, filter.GetInvertedColorCacheSizeForTesting()); + + // Results returned from cache. + EXPECT_EQ(Color::kBlack, filter.InvertColorIfNeeded( + Color(SK_ColorWHITE), + DarkModeFilter::ElementRole::kBackground)); + EXPECT_EQ( + Color(SK_ColorTRANSPARENT), + filter.InvertColorIfNeeded(Color(SK_ColorTRANSPARENT), + DarkModeFilter::ElementRole::kBackground)); + EXPECT_EQ(2u, filter.GetInvertedColorCacheSizeForTesting()); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 0bd78bc..ab475bd 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1001,6 +1001,12 @@ // Enabled by features::kLegacyWindowsDWriteFontFallback; }, { + // TODO(crbug.com/1087043): Remove this once the feature has + // landed and no compat issues are reported. + name: "LinkDisabledNewSpecBehavior", + status: "stable", + }, + { name:"ManualSlotting", status:"experimental", }, @@ -1779,6 +1785,11 @@ origin_trial_feature_name: "RTCInsertableStreams", implied_by: ["RTCInsertableStreams"], }, + // When enabled, enforces new interoperable semantics for 3D transforms. + // See crbug.com/1008483. + { + name: "TransformInterop", + }, // This is conditionally set if the platform supports translation. { name: "TranslateService" @@ -1907,7 +1918,12 @@ }, { name: "WebBluetoothRemoteCharacteristicNewWriteValue", - status: "experimental", + status: { + "Android": "stable", + "ChromeOS": "stable", + "MacOSX": "stable", + "default": "experimental", + }, }, { name: "WebBluetoothScanning",
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc b/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc index 557c762..40fa3e0a 100644 --- a/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc +++ b/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
@@ -57,6 +57,7 @@ case Feature::kPrinting: case Feature::kPictureInPicture: case Feature::kIdleManager: + case Feature::kPaymentManager: return true; } }
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc index f0958af..a02d0938 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc
@@ -61,7 +61,7 @@ TRACE_EVENT0("renderer.scheduler", "BudgetPool_EnableThrottling"); - BlockThrottledQueues(lazy_now->Now()); + UpdateThrottlingStateForAllQueues(lazy_now->Now()); } void BudgetPool::DisableThrottling(base::sequence_manager::LazyNow* lazy_now) { @@ -90,7 +90,7 @@ budget_pool_controller_->UnregisterBudgetPool(this); } -void BudgetPool::BlockThrottledQueues(base::TimeTicks now) { +void BudgetPool::UpdateThrottlingStateForAllQueues(base::TimeTicks now) { for (TaskQueue* queue : associated_task_queues_) budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue); }
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h index f921c9c..92a6b8e3 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h
@@ -103,8 +103,10 @@ // All queues should be removed before calling Close(). void Close(); - // Block all associated queues and schedule them to run when appropriate. - void BlockThrottledQueues(base::TimeTicks now); + // Ensures that a pump is scheduled and that a fence is installed for all + // queues in this pool, based on state of those queues and latest values from + // CanRunTasksAt/GetTimeTasksCanRunUntil/GetNextAllowedRunTime. + void UpdateThrottlingStateForAllQueues(base::TimeTicks now); protected: BudgetPool(const char* name, BudgetPoolController* budget_pool_controller);
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc index e16953b..551e549 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc
@@ -132,7 +132,7 @@ scheduler_->NewTimerTaskQueue( MainThreadTaskQueue::QueueType::kFrameThrottleable, nullptr); - pool->SetWakeUpInterval(base::TimeDelta::FromSeconds(10)); + pool->SetWakeUpInterval(base::TimeTicks(), base::TimeDelta::FromSeconds(10)); pool->SetWakeUpDuration(base::TimeDelta::FromMilliseconds(10)); // Can't run tasks until a wake-up.
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc index 121a90cdf..c1beca5 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
@@ -116,7 +116,7 @@ } if (current_budget_level_->InSecondsF() < 0) - BlockThrottledQueues(end_time); + UpdateThrottlingStateForAllQueues(end_time); } void CPUTimeBudgetPool::OnQueueNextWakeUpChanged(
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc index 4259028..8e2a004 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/task/sequence_manager/sequence_manager.h" #include "base/task/sequence_manager/test/sequence_manager_for_test.h" +#include "base/test/bind_test_util.h" #include "base/test/test_mock_time_task_runner.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -1329,7 +1330,8 @@ constexpr base::TimeDelta kDelay = base::TimeDelta::FromSeconds(10); constexpr base::TimeDelta kTimeBetweenWakeUps = base::TimeDelta::FromMinutes(1); - wake_up_budget_pool_->SetWakeUpInterval(kTimeBetweenWakeUps); + wake_up_budget_pool_->SetWakeUpInterval(base::TimeTicks(), + kTimeBetweenWakeUps); wake_up_budget_pool_->SetWakeUpDuration(base::TimeDelta::FromMilliseconds(1)); Vector<base::TimeTicks> run_times; @@ -1375,6 +1377,138 @@ base::TimeTicks() + base::TimeDelta::FromSeconds(300))); } +TEST_F(TaskQueueThrottlerTest, + WakeUpBasedThrottling_IncreaseWakeUpIntervalBeforeWakeUp) { + Vector<base::TimeTicks> run_times; + task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get()); + + // Post 2 delayed tasks when the wake up interval is 1 minute. The delay of + // the 2nd task is such that it won't be ready when the 1st task completes. + wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), + base::TimeDelta::FromMinutes(1)); + timer_task_runner_->PostDelayedTask( + FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), + base::TimeDelta::FromMilliseconds(1)); + timer_task_runner_->PostDelayedTask( + FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), + base::TimeDelta::FromMinutes(2)); + + // Update the wake up interval to 1 hour. + wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), + base::TimeDelta::FromHours(1)); + + // The 1st delayed task should run after 1 minute, because increasing the wake + // up interval does not affect already scheduled wake ups. The 2nd task is + // scheduled according to the 1-hour wake up interval. + test_task_runner_->FastForwardUntilNoTasksRemain(); + EXPECT_THAT(run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromMinutes(1), + base::TimeTicks() + base::TimeDelta::FromHours(1))); +} + +TEST_F(TaskQueueThrottlerTest, + WakeUpBasedThrottling_DecreaseWakeUpIntervalBeforeWakeUp) { + Vector<base::TimeTicks> run_times; + task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get()); + + // Post a delayed task when the wake up interval is 1 hour. + wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), + base::TimeDelta::FromHours(1)); + timer_task_runner_->PostDelayedTask( + FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), + base::TimeDelta::FromMilliseconds(1)); + + // Update the wake up interval to 1 minute. + wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), + base::TimeDelta::FromMinutes(1)); + + // The delayed task should run after 1 minute, which is the most up to date + // wake up interval. + test_task_runner_->FastForwardUntilNoTasksRemain(); + EXPECT_THAT(run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromMinutes(1))); +} + +TEST_F(TaskQueueThrottlerTest, + WakeUpBasedThrottling_IncreaseWakeUpIntervalDuringWakeUp) { + wake_up_budget_pool_->SetWakeUpDuration( + base::TimeDelta::FromMilliseconds(10)); + + Vector<base::TimeTicks> run_times; + task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get()); + + // Post a 1st delayed task when the wake up interval is 1 minute. + wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), + base::TimeDelta::FromMinutes(1)); + timer_task_runner_->PostDelayedTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + TestTask(&run_times, test_task_runner_); + // Post a 2nd delayed task when the wake up interval is still 1 minute. + timer_task_runner_->PostDelayedTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + TestTask(&run_times, test_task_runner_); + // Post a 3rd task when the wake up interval is 1 hour. + timer_task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&TestTask, &run_times, test_task_runner_), + base::TimeDelta::FromSeconds(1)); + }), + base::TimeDelta::FromSeconds(1)); + // Increase the wake up interval. Since the wake up for the 2nd task is + // already scheduled, it isn't affected by this. + wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), + base::TimeDelta::FromHours(1)); + }), + base::TimeDelta::FromSeconds(1)); + + test_task_runner_->FastForwardUntilNoTasksRemain(); + EXPECT_THAT(run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromMinutes(1), + base::TimeTicks() + base::TimeDelta::FromMinutes(2), + base::TimeTicks() + base::TimeDelta::FromHours(1))); +} + +TEST_F(TaskQueueThrottlerTest, + WakeUpBasedThrottling_DecreaseWakeUpIntervalDuringWakeUp) { + wake_up_budget_pool_->SetWakeUpDuration( + base::TimeDelta::FromMilliseconds(10)); + + Vector<base::TimeTicks> run_times; + task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get()); + + // Post a 1st delayed task when the wake up interval is 1 hour. + wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), + base::TimeDelta::FromHours(1)); + timer_task_runner_->PostDelayedTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + TestTask(&run_times, test_task_runner_); + // Post a 2nd delayed task when the wake up interval is still 1 hour. + timer_task_runner_->PostDelayedTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + TestTask(&run_times, test_task_runner_); + // Post a 3rd task when the wake up interval is 1 minute. + timer_task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&TestTask, &run_times, test_task_runner_), + base::TimeDelta::FromSeconds(1)); + }), + base::TimeDelta::FromSeconds(1)); + // Decrease the wake up interval. This immediately reschedules the wake + // up for the 2nd task. + wake_up_budget_pool_->SetWakeUpInterval( + test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); + }), + base::TimeDelta::FromSeconds(1)); + + test_task_runner_->FastForwardUntilNoTasksRemain(); + EXPECT_THAT(run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromHours(1), + base::TimeTicks() + base::TimeDelta::FromHours(1) + + base::TimeDelta::FromMinutes(1), + base::TimeTicks() + base::TimeDelta::FromHours(1) + + base::TimeDelta::FromMinutes(2))); +} + TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottlingWithCPUBudgetThrottling) { wake_up_budget_pool_->SetWakeUpDuration( base::TimeDelta::FromMilliseconds(10));
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc index 567d4b46..5c034adb7 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc
@@ -26,8 +26,10 @@ return QueueBlockType::kNewTasksOnly; } -void WakeUpBudgetPool::SetWakeUpInterval(base::TimeDelta interval) { +void WakeUpBudgetPool::SetWakeUpInterval(base::TimeTicks now, + base::TimeDelta interval) { wake_up_interval_ = interval; + UpdateThrottlingStateForAllQueues(now); } void WakeUpBudgetPool::SetWakeUpDuration(base::TimeDelta duration) {
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h b/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h index cb86e2e..2339da65 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h
@@ -13,8 +13,8 @@ namespace blink { namespace scheduler { -// WakeUpBudgetPool represents a collection of task queues which share a limit -// on total cpu time. +// WakeUpBudgetPool represents a collection of task queues which run for a +// limited time at regular intervals. class PLATFORM_EXPORT WakeUpBudgetPool : public BudgetPool { public: WakeUpBudgetPool(const char* name, @@ -22,12 +22,14 @@ base::TimeTicks now); ~WakeUpBudgetPool() override; - // Note: this does not have an immediate effect and should be called only - // during initialization of a WakeUpBudgetPool. - void SetWakeUpInterval(base::TimeDelta interval); + // Sets the interval between wake ups. This can be invoked at any time. If a + // next wake up is already scheduled, it is rescheduled only if the new + // |interval| is smaller than the old interval. Wake ups after that will be + // scheduled according to |interval|. + void SetWakeUpInterval(base::TimeTicks now, base::TimeDelta interval); - // Note: this does not have an immediate effect and should be called only - // during initialization of a WakeUpBudgetPool. + // Sets the duration of wake ups. This does not have an immediate effect and + // should be called only during initialization of a WakeUpBudgetPool. void SetWakeUpDuration(base::TimeDelta duration); // BudgetPool implementation:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc index 648187d..b9fa658 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
@@ -591,7 +591,8 @@ main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool( "Page Wake Up Throttling"); - wake_up_budget_pool_->SetWakeUpInterval(kThrottledWakeUpInterval); + wake_up_budget_pool_->SetWakeUpInterval(lazy_now->Now(), + kThrottledWakeUpInterval); wake_up_budget_pool_->SetWakeUpDuration(kThrottledWakeUpDuration); }
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc b/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc index ad46c9c..e807f676 100644 --- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc +++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc
@@ -59,24 +59,6 @@ namespace { -// These test parameters control: -// - Whether ot not to setup a synchronous input handler. This simulates the -// mode that WebView runs in. -// - Whether or not the input handler says that the viewport is scrolling -// (ROOT_SCROLL or CHILD_SCROLL). -enum InputHandlerProxyTestType { - ROOT_SCROLL_NORMAL_HANDLER, - ROOT_SCROLL_SYNCHRONOUS_HANDLER, - CHILD_SCROLL_NORMAL_HANDLER, - CHILD_SCROLL_SYNCHRONOUS_HANDLER, -}; -static const InputHandlerProxyTestType test_types[] = { - ROOT_SCROLL_NORMAL_HANDLER, - ROOT_SCROLL_SYNCHRONOUS_HANDLER, - CHILD_SCROLL_NORMAL_HANDLER, - CHILD_SCROLL_SYNCHRONOUS_HANDLER, -}; - MATCHER_P(WheelEventsMatch, expected, "") { return WheelEventsMatch(arg, expected); } @@ -327,23 +309,41 @@ void DispatchQueuedInputEventsHelper() { DispatchQueuedInputEvents(); } }; +// Whether or not the input handler says that the viewport is scrolling the +// root scroller or a child. +enum class ScrollerType { kRoot, kChild }; + +// Whether or not to setup a synchronous input handler. This simulates the mode +// that WebView runs in. +enum class HandlerType { kNormal, kSynchronous }; + +// Run tests with unification both on and off. +enum class ScrollUnification { kEnabled, kDisabled }; + class InputHandlerProxyTest : public testing::Test, - public testing::WithParamInterface<InputHandlerProxyTestType> { + public testing::WithParamInterface< + std::tuple<ScrollerType, HandlerType, ScrollUnification>> { + ScrollerType GetScrollerType() { return std::get<0>(GetParam()); } + HandlerType GetHandlerType() { return std::get<1>(GetParam()); } + ScrollUnification GetScrollUnificationState() { + return std::get<2>(GetParam()); + } + public: - InputHandlerProxyTest() - : synchronous_root_scroll_(GetParam() == ROOT_SCROLL_SYNCHRONOUS_HANDLER), - install_synchronous_handler_( - GetParam() == ROOT_SCROLL_SYNCHRONOUS_HANDLER || - GetParam() == CHILD_SCROLL_SYNCHRONOUS_HANDLER), - expected_disposition_(InputHandlerProxy::DID_HANDLE) { + InputHandlerProxyTest() { + if (GetScrollUnificationState() == ScrollUnification::kEnabled) + scoped_feature_list_.InitAndEnableFeature(features::kScrollUnification); + else + scoped_feature_list_.InitAndDisableFeature(features::kScrollUnification); + input_handler_ = std::make_unique<TestInputHandlerProxy>( &mock_input_handler_, &mock_client_, /*force_input_to_main_thread=*/false); scroll_result_did_scroll_.did_scroll = true; scroll_result_did_not_scroll_.did_scroll = false; - if (install_synchronous_handler_) { + if (GetHandlerType() == HandlerType::kSynchronous) { EXPECT_CALL(mock_input_handler_, RequestUpdateForSynchronousInputHandler()) .Times(1); @@ -351,7 +351,9 @@ &mock_synchronous_input_handler_); } - mock_input_handler_.set_is_scrolling_root(synchronous_root_scroll_); + mock_input_handler_.set_is_scrolling_root( + GetHandlerType() == HandlerType::kSynchronous && + GetScrollerType() == ScrollerType::kRoot); // Set a default device so tests don't always have to set this. gesture_.SetSourceDevice(WebGestureDevice::kTouchpad); @@ -388,18 +390,18 @@ void GestureScrollIgnored(); void FlingAndSnap(); - const bool synchronous_root_scroll_; - const bool install_synchronous_handler_; testing::StrictMock<MockInputHandler> mock_input_handler_; testing::StrictMock<MockSynchronousInputHandler> mock_synchronous_input_handler_; std::unique_ptr<TestInputHandlerProxy> input_handler_; testing::StrictMock<MockInputHandlerProxyClient> mock_client_; WebGestureEvent gesture_; - InputHandlerProxy::EventDisposition expected_disposition_; + InputHandlerProxy::EventDisposition expected_disposition_ = + InputHandlerProxy::DID_HANDLE; base::HistogramTester histogram_tester_; cc::InputHandlerScrollResult scroll_result_did_scroll_; cc::InputHandlerScrollResult scroll_result_did_not_scroll_; + base::test::ScopedFeatureList scoped_feature_list_; }; // The helper basically returns the EventDisposition that is returned by @@ -599,8 +601,10 @@ cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(0); EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown, WebInputEvent::kNoModifiers, WebInputEvent::GetStaticTimeStampForTests()); @@ -759,8 +763,10 @@ cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(0); EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown, WebInputEvent::kNoModifiers, WebInputEvent::GetStaticTimeStampForTests()); @@ -853,8 +859,10 @@ ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), _)) .WillOnce(testing::Return(scroll_result_did_not_scroll_)); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } EXPECT_EQ(expected_disposition_, HandleInputEventAndFlushEventQueue(mock_input_handler_, input_handler_.get(), gesture_)); @@ -863,8 +871,10 @@ expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate); gesture_.data.scroll_update.delta_y = -40; // -Y means scroll down - i.e. in the +Y direction. @@ -1122,6 +1132,12 @@ } TEST_P(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) { + // This situation is no longer possible under scroll unification as all + // scrolling now happens on the compositor thread. This test can be removed + // when the feature ships. + if (base::FeatureList::IsEnabled(features::kScrollUnification)) + return; + // Scrolls will start by being sent to the main thread. expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1169,8 +1185,10 @@ VERIFY_AND_RESET_MOCKS(); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate); gesture_.data.scroll_update.delta_y = -40; // -Y means scroll down - i.e. in the +Y direction. @@ -1274,10 +1292,22 @@ VERIFY_AND_RESET_MOCKS(); } TEST_P(InputHandlerProxyTest, WheelScrollHandlingSwitchedToMainThread) { + // This situation is no longer possible under scroll unification as all + // scrolling now happens on the compositor thread. This test can be removed + // when the feature ships. + if (base::FeatureList::IsEnabled(features::kScrollUnification)) + return; + gesture_.SetSourceDevice(WebGestureDevice::kTouchpad); ScrollHandlingSwitchedToMainThread(); } TEST_P(InputHandlerProxyTest, TouchScrollHandlingSwitchedToMainThread) { + // This situation is no longer possible under scroll unification as all + // scrolling now happens on the compositor thread. This test can be removed + // when the feature ships. + if (base::FeatureList::IsEnabled(features::kScrollUnification)) + return; + gesture_.SetSourceDevice(WebGestureDevice::kTouchscreen); ScrollHandlingSwitchedToMainThread(); } @@ -1409,8 +1439,10 @@ EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _)) .WillOnce(Return(kImplThreadScrollState)); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(Return(false)); + } EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1); DeliverInputForBeginFrame(); @@ -1446,8 +1478,10 @@ EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _)) .WillOnce(Return(kImplThreadScrollState)); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(Return(false)); + } EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1); DeliverInputForBeginFrame(); @@ -1488,8 +1522,10 @@ // ScrollUpdate { EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(Return(false)); + } EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1); HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, delta); @@ -1504,8 +1540,10 @@ EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)) .WillOnce(Return(scroll_result_did_scroll)); EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(Return(false)); + } EXPECT_CALL(mock_input_handler_, GetSnapFlingInfoAndSetAnimatingSnapTarget(_, _, _)) .WillOnce(Return(false)); @@ -1850,7 +1888,7 @@ /*force_input_to_main_thread=*/false) {} void SetUp() override { - scoped_feature_list.InitAndEnableFeature(features::kScrollUnification); + scoped_feature_list_.InitAndEnableFeature(features::kScrollUnification); } std::unique_ptr<WebCoalescedInputEvent> ScrollBegin() { @@ -1951,7 +1989,7 @@ } InputHandlerProxy input_handler_proxy_; - base::test::ScopedFeatureList scoped_feature_list; + base::test::ScopedFeatureList scoped_feature_list_; base::SimpleTestTickClock tick_clock_; uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber; base::WeakPtrFactory<UnifiedScrollingInputHandlerProxyTest> weak_ptr_factory_{ @@ -2450,8 +2488,10 @@ EXPECT_EQ(1ul, event_disposition_recorder_.size()); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -2494,8 +2534,10 @@ mock_input_handler_, RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(1); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -2522,8 +2564,10 @@ mock_input_handler_, RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(1); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillRepeatedly(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillRepeatedly(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -2575,8 +2619,10 @@ RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(1); EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -2715,8 +2761,10 @@ .Times(2); EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()) .Times(::testing::AtLeast(1)); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillRepeatedly(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillRepeatedly(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -2800,8 +2848,10 @@ mock_input_handler_, RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(2); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillRepeatedly(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillRepeatedly(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -2868,8 +2918,10 @@ RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(1); EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -2910,8 +2962,10 @@ RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain)) .Times(1); EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(2); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -2980,8 +3034,10 @@ RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(1); EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(2); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillOnce(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -3039,8 +3095,10 @@ RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor)) .Times(1); EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(2); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillRepeatedly(testing::Return(false)); + if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) + .WillRepeatedly(testing::Return(false)); + } EXPECT_CALL( mock_input_handler_, ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)), @@ -3937,13 +3995,33 @@ 0); } +const auto kTestCombinations = testing::Combine( + testing::Values(ScrollerType::kRoot, ScrollerType::kChild), + testing::Values(HandlerType::kNormal, HandlerType::kSynchronous), + testing::Values(ScrollUnification::kEnabled, ScrollUnification::kDisabled)); + +const auto kSuffixGenerator = + [](const testing::TestParamInfo< + std::tuple<ScrollerType, HandlerType, ScrollUnification>>& info) { + std::string name = std::get<1>(info.param) == HandlerType::kSynchronous + ? "Synchronous" + : ""; + name += std::get<0>(info.param) == ScrollerType::kRoot ? "Root" : "Child"; + name += std::get<2>(info.param) == ScrollUnification::kEnabled + ? "UnifiedScroll" + : "LegacyScroll"; + return name; + }; + INSTANTIATE_TEST_SUITE_P(All, InputHandlerProxyTest, - testing::ValuesIn(test_types)); + kTestCombinations, + kSuffixGenerator); INSTANTIATE_TEST_SUITE_P(All, InputHandlerProxyMainThreadScrollingReasonTest, - testing::ValuesIn(test_types)); + kTestCombinations, + kSuffixGenerator); } // namespace test } // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/hash_functions.h b/third_party/blink/renderer/platform/wtf/hash_functions.h index 9b9ec92a..2983b6c 100644 --- a/third_party/blink/renderer/platform/wtf/hash_functions.h +++ b/third_party/blink/renderer/platform/wtf/hash_functions.h
@@ -27,6 +27,7 @@ #include "base/bit_cast.h" #include "base/memory/scoped_refptr.h" #include "build/build_config.h" +#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" namespace WTF { @@ -277,6 +278,59 @@ using Hash = PairHash<T, U>; }; +// Wrapper for integral type to extend to have 0 and max keys. +template <typename T> +struct IntegralWithAllKeys { + IntegralWithAllKeys() : IntegralWithAllKeys(0, ValueType::kEmpty) {} + explicit IntegralWithAllKeys(T value) + : IntegralWithAllKeys(value, ValueType::kValid) {} + explicit IntegralWithAllKeys(HashTableDeletedValueType) + : IntegralWithAllKeys(0, ValueType::kDeleted) {} + + bool IsHashTableDeletedValue() const { + return value_type_ == ValueType::kDeleted; + } + + unsigned Hash() const { + return HashInts(value_, static_cast<unsigned>(value_type_)); + } + + bool operator==(const IntegralWithAllKeys& b) const { + return value_ == b.value_ && value_type_ == b.value_type_; + } + + private: + enum class ValueType : uint8_t { kEmpty, kValid, kDeleted }; + + IntegralWithAllKeys(T value, ValueType value_type) + : value_(value), value_type_(value_type) { + static_assert(std::is_integral<T>::value, + "Only integral types are supported."); + } + + T value_; + ValueType value_type_; +}; + +// Specialization for integral type to have all possible values for key +// including 0 and max. +template <typename T> +struct IntegralWithAllKeysHash { + static unsigned GetHash(const IntegralWithAllKeys<T>& key) { + return key.Hash(); + } + static bool Equal(const IntegralWithAllKeys<T>& a, + const IntegralWithAllKeys<T>& b) { + return a == b; + } + static const bool safe_to_compare_to_empty_or_deleted = true; +}; + +template <typename T> +struct DefaultHash<IntegralWithAllKeys<T>> { + using Hash = IntegralWithAllKeysHash<T>; +}; + } // namespace WTF using WTF::DefaultHash;
diff --git a/third_party/blink/renderer/platform/wtf/hash_traits.h b/third_party/blink/renderer/platform/wtf/hash_traits.h index f5149002..19dfe94 100644 --- a/third_party/blink/renderer/platform/wtf/hash_traits.h +++ b/third_party/blink/renderer/platform/wtf/hash_traits.h
@@ -231,6 +231,12 @@ } }; +// Default traits disallow both 0 and max as keys -- use these traits to allow +// all values as keys. +template <typename T> +struct HashTraits<IntegralWithAllKeys<T>> + : SimpleClassHashTraits<IntegralWithAllKeys<T>> {}; + template <typename P> struct HashTraits<scoped_refptr<P>> : SimpleClassHashTraits<scoped_refptr<P>> { static_assert(sizeof(void*) == sizeof(scoped_refptr<P>),
diff --git a/third_party/blink/tools/BUILD.gn b/third_party/blink/tools/BUILD.gn index b76b17e..cfea950 100644 --- a/third_party/blink/tools/BUILD.gn +++ b/third_party/blink/tools/BUILD.gn
@@ -7,6 +7,7 @@ testonly = true data = [ "//testing/scripts/common.py", + "//testing/scripts/wpt_common.py", "//testing/xvfb.py", # Include blinkpy tools for setting up expectations.
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer.py b/third_party/blink/tools/blinkpy/w3c/test_importer.py index 6f215d9..5a7a17a7 100644 --- a/third_party/blink/tools/blinkpy/w3c/test_importer.py +++ b/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -38,8 +38,8 @@ TIMEOUT_SECONDS = 210 * 60 # Sheriff calendar URL, used for getting the ecosystem infra sheriff to TBR. -ROTATIONS_URL = 'https://rota-ng.appspot.com/legacy/all_rotations.js' -TBR_FALLBACK = 'robertma' +ROTATIONS_URL = 'https://chrome-ops-rotation-proxy.appspot.com/current/grotation:chrome-ecosystem-infra' +TBR_FALLBACK = 'robertma@google.com' _log = logging.getLogger(__file__) @@ -562,42 +562,34 @@ return '\n'.join(message_lines) def tbr_reviewer(self): - """Returns the user name or email address to use as the reviewer. + """Returns the email address to use as the reviewer. This tries to fetch the current ecosystem infra sheriff, but falls back in case of error. - - Either a user name (which is assumed to have a chromium.org email - address) or a full email address (for other cases) is returned. """ - username = '' + email = '' try: - username = self._fetch_ecosystem_infra_sheriff_username() + email = self._fetch_ecosystem_infra_sheriff_email() except (IOError, KeyError, ValueError) as error: _log.error('Exception while fetching current sheriff: %s', error) - if username in ['kyleju']: - _log.warning('Cannot TBR by %s: not a committer', username) - username = '' - return username or TBR_FALLBACK + if email in ['kyleju@google.com']: + _log.warning('Cannot TBR by %s: not a committer', email) + email = '' + return email or TBR_FALLBACK - def _fetch_ecosystem_infra_sheriff_username(self): + def _fetch_ecosystem_infra_sheriff_email(self): try: content = self.host.web.get_binary(ROTATIONS_URL) except NetworkTimeout: _log.error('Cannot fetch %s', ROTATIONS_URL) return '' data = json.loads(content) - today = datetime.date.fromtimestamp(self.host.time()).isoformat() - index = data['rotations'].index('ecosystem_infra') - calendar = data['calendar'] - for entry in calendar: - if entry['date'] == today: - if not entry['participants'][index]: - _log.info('No sheriff today.') - return '' - return entry['participants'][index][0] - _log.error('No entry found for date %s in rotations table.', today) - return '' + if not data.get('emails'): + _log.error( + 'No email found for current sheriff. Retrieved content: %s', + content) + return '' + return data['emails'][0] def fetch_new_expectations_and_baselines(self): """Modifies expectation lines and baselines based on try job results.
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py index f4f4c7f..ab1e5ab 100644 --- a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py +++ b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
@@ -465,43 +465,30 @@ 'No JSON object could be decoded\n' ]) - def test_tbr_reviewer_date_not_found(self): + def test_tbr_reviewer_no_emails_field(self): host = MockHost() - yesterday = (datetime.date.fromtimestamp(host.time()) - - datetime.timedelta(days=1)).isoformat() - host.web.urls[ROTATIONS_URL] = json.dumps({ - 'calendar': [ - { - 'date': yesterday, - 'participants': [['some-sheriff'], ['other-sheriff']], - }, - ], - 'rotations': ['ecosystem_infra', 'other_rotation'] - }) + host.web.urls[ROTATIONS_URL] = json.dumps( + {'updated_unix_timestamp': '1591108191'}) importer = TestImporter(host) self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer()) - # Use a variable here, otherwise we get different values depending on - # the machine's time zone settings (e.g. "1969-12-31" vs "1970-01-01"). - today = datetime.date.fromtimestamp(host.time()).isoformat() self.assertLog([ - 'ERROR: No entry found for date %s in rotations table.\n' % today + 'ERROR: No email found for current sheriff. Retrieved content: %s\n' + % host.web.urls[ROTATIONS_URL] ]) def test_tbr_reviewer_nobody_on_rotation(self): host = MockHost() - today = datetime.date.fromtimestamp(host.time()).isoformat() host.web.urls[ROTATIONS_URL] = json.dumps({ - 'calendar': [ - { - 'date': today, - 'participants': [[], ['some-sheriff']], - }, - ], - 'rotations': ['ecosystem_infra', 'other-rotation'] + 'emails': [], + 'updated_unix_timestamp': + '1591108191' }) importer = TestImporter(host) self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer()) - self.assertLog(['INFO: No sheriff today.\n']) + self.assertLog([ + 'ERROR: No email found for current sheriff. Retrieved content: %s\n' + % host.web.urls[ROTATIONS_URL] + ]) def test_tbr_reviewer_rotations_url_unavailable(self): def raise_exception(*_): @@ -515,47 +502,23 @@ def test_tbr_reviewer(self): host = MockHost() - today = datetime.date.fromtimestamp(host.time()) - yesterday = today - datetime.timedelta(days=1) host.web.urls[ROTATIONS_URL] = json.dumps({ - 'calendar': [ - { - 'date': yesterday.isoformat(), - 'participants': [['other-sheriff'], ['last-sheriff']], - }, - { - 'date': today.isoformat(), - 'participants': [['other-sheriff'], ['current-sheriff']], - }, - ], - 'rotations': ['other-rotation', 'ecosystem_infra'] + 'emails': ['current-sheriff@chromium.org'], + 'updated_unix_timestamp': + '1591108191', }) importer = TestImporter(host) - self.assertEqual('current-sheriff', importer.tbr_reviewer()) - self.assertLog([]) - - def test_tbr_reviewer_with_full_email_address(self): - host = MockHost() - today = datetime.date.fromtimestamp(host.time()).isoformat() - host.web.urls[ROTATIONS_URL] = json.dumps({ - 'calendar': [ - { - 'date': today, - 'participants': [['external@example.com']], - }, - ], - 'rotations': ['ecosystem_infra'] - }) - importer = TestImporter(host) - self.assertEqual('external@example.com', importer.tbr_reviewer()) + self.assertEqual('current-sheriff@chromium.org', + importer.tbr_reviewer()) self.assertLog([]) def test_tbr_reviewer_skips_non_committer(self): host = MockHost() importer = TestImporter(host) - importer._fetch_ecosystem_infra_sheriff_username = lambda: 'kyleju' + importer._fetch_ecosystem_infra_sheriff_email = lambda: 'kyleju@google.com' self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer()) - self.assertLog(['WARNING: Cannot TBR by kyleju: not a committer\n']) + self.assertLog( + ['WARNING: Cannot TBR by kyleju@google.com: not a committer\n']) def test_generate_manifest_successful_run(self): # This test doesn't test any aspect of the real manifest script, it just
diff --git a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py index 146ea4f..b8213e11 100644 --- a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py +++ b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
@@ -48,7 +48,10 @@ os_path.dirname(os_path.abspath(__file__)), '..', '..', 'lint_test_expectations.py') _, errs = input_api.subprocess.Popen( - [input_api.python_executable, lint_path], + [ + input_api.python_executable, lint_path, + '--no-check-redundant-virtual-expectations' + ], stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.PIPE).communicate() if not errs: @@ -125,7 +128,7 @@ ports_to_lint[0], expectations_dict={path: content}) # Check each expectation for issues f, w = _check_expectations(host, ports_to_lint[0], path, - test_expectations) + test_expectations, options) failures += f warnings += w except ParseError as error: @@ -246,7 +249,7 @@ return failures -def _check_expectations(host, port, path, test_expectations): +def _check_expectations(host, port, path, test_expectations, options): # Check for original expectation lines (from get_updated_lines) instead of # expectations filtered for the current port (test_expectations). expectations = test_expectations.get_updated_lines(path) @@ -254,8 +257,11 @@ failures.extend(_check_directory_glob(host, port, path, expectations)) # TODO(crbug.com/1080691): Change this to failures once # wpt_expectations_updater is fixed. - warnings = _check_redundant_virtual_expectations(host, port, path, - expectations) + warnings = [] + if not getattr(options, 'no_check_redundant_virtual_expectations', False): + warnings.extend( + _check_redundant_virtual_expectations(host, port, path, + expectations)) return failures, warnings @@ -387,6 +393,10 @@ action='append', default=[], help='paths to additional expectation files to lint.') + parser.add_option('--no-check-redundant-virtual-expectations', + action='store_true', + default=False, + help='skip checking redundant virtual expectations.') options, _ = parser.parse_args(argv)
diff --git a/third_party/blink/web_tests/FlagExpectations/composite-after-paint b/third_party/blink/web_tests/FlagExpectations/composite-after-paint index f739105..ed8abcb 100644 --- a/third_party/blink/web_tests/FlagExpectations/composite-after-paint +++ b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
@@ -53,7 +53,6 @@ # Wrong clipping of the right side of nested composited reflection with non-zero filter origin. compositing/reflections/deeply-nested-reflections.html [ Failure ] -compositing/masks/broken-mask.html [ Failure ] compositing/masks/mask-with-removed-filters.html [ Failure ] external/wpt/css/css-transforms/transform3d-backface-visibility-006.html [ Failure ] external/wpt/css/filter-effects/effect-reference-feimage-002.html [ Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item index 3edb18a..9ba28a4 100644 --- a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item +++ b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
@@ -100,7 +100,7 @@ crbug.com/626703 external/wpt/screen-orientation/onchange-event.html [ Timeout ] crbug.com/626703 external/wpt/screen-orientation/orientation-reading.html [ Timeout ] crbug.com/645988 external/wpt/uievents/order-of-events/focus-eventfocus-manual.html [ Crash Failure ] -crbug.com/645988 external/wpt/uievents/order-of-events/focus-events/focus-manual.html [ Failure Timeout ] +crbug.com/645988 external/wpt/uievents/order-of-events/focus-events/focus-manual.html [ Failure ] crbug.com/1002514 external/wpt/web-share/share-sharePromise-internal-slot.https.html [ Crash Timeout ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties.html [ Failure ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand.html [ Failure ] @@ -121,7 +121,7 @@ crbug.com/889721 fast/inline/outline-continuations.html [ Failure ] crbug.com/982194 fast/multicol/newmulticol/hide-box-vertical-lr.html [ Failure ] crbug.com/982194 fast/multicol/span/vertical-lr.html [ Failure ] -crbug.com/982194 fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Failure Pass ] +crbug.com/982194 fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Failure ] crbug.com/982194 fast/multicol/vertical-lr/nested-columns.html [ Failure ] crbug.com/814953 fast/replaced/no-focus-ring-iframe.html [ Failure ] crbug.com/986018 fast/scroll-snap/snaps-for-different-key-granularity.html [ Pass ] @@ -142,16 +142,14 @@ crbug.com/420008 crbug.com/749738 http/tests/devtools/editor/text-editor-word-jumps.js [ Crash Pass Timeout ] crbug.com/937811 http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-2.js [ Pass ] crbug.com/937811 http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass ] -crbug.com/1075869 http/tests/devtools/elements/styles-1/color-aware-property-value-edit.js [ Crash Pass Failure Timeout ] -crbug.com/959042 http/tests/devtools/elements/styles-1/edit-resource-referred-by-multiple-styletags.js [ Crash Pass Timeout ] -crbug.com/959042 http/tests/devtools/elements/styles-3/style-autocomplete.js [ Crash Pass Timeout ] +crbug.com/1075869 http/tests/devtools/elements/styles-1/color-aware-property-value-edit.js [ Failure ] crbug.com/938884 http/tests/devtools/elements/styles-3/styles-add-blank-property.js [ Pass ] crbug.com/945665 http/tests/devtools/elements/styles-3/styles-add-new-rule-tab.js [ Failure Pass ] crbug.com/945665 http/tests/devtools/elements/styles-3/styles-add-new-rule.js [ Failure Pass ] crbug.com/945665 http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Failure Pass ] crbug.com/945665 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Failure ] crbug.com/959002 crbug.com/959042 http/tests/devtools/elements/styles-3/styles-variables.js [ Crash Pass Timeout ] -crbug.com/667560 http/tests/devtools/elements/styles-4/inline-style-sourcemap.js [ Failure Pass ] +crbug.com/667560 http/tests/devtools/elements/styles-4/inline-style-sourcemap.js [ Pass ] crbug.com/959002 crbug.com/959042 http/tests/devtools/elements/styles-4/styles-keyframes.js [ Crash Pass Timeout ] crbug.com/982116 http/tests/devtools/elements/styles-4/styles-new-API.js [ Pass ] crbug.com/849978 http/tests/devtools/elements/styles-4/stylesheet-source-url-comment.js [ Pass ] @@ -167,19 +165,19 @@ crbug.com/817167 crbug.com/874695 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Crash Failure Pass Timeout ] crbug.com/818076 http/tests/devtools/oopif/oopif-elements-navigate-in.js [ Pass ] crbug.com/450493 crbug.com/971262 http/tests/devtools/profiler/live-line-level-heap-profile.js [ Crash Pass Timeout ] -crbug.com/831673 http/tests/devtools/reveal-objects.js [ Failure Pass ] +crbug.com/831673 http/tests/devtools/reveal-objects.js [ Pass ] crbug.com/849670 http/tests/devtools/service-workers/service-worker-v8-cache.js [ Pass ] crbug.com/874695 http/tests/devtools/sources/debugger-breakpoints/breakpoints-ui-shifted-breakpoint.js [ Timeout ] crbug.com/450493 crbug.com/912793 http/tests/devtools/sources/debugger-breakpoints/restore-locations-for-breakpoint-with-broken-source-map.js [ Crash Failure Pass Timeout ] crbug.com/450493 crbug.com/916975 http/tests/devtools/sources/debugger-ui/call-stack-show-more.js [ Crash Failure Pass Timeout ] crbug.com/450493 http/tests/devtools/sources/debugger/debug-inlined-scripts.js [ Failure ] -crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch-fail.js [ Failure Pass ] -crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch.js [ Failure Pass ] +crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch-fail.js [ Failure ] +crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch.js [ Failure ] crbug.com/420008 crbug.com/916975 http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Crash Failure Pass Timeout ] -crbug.com/982194 http/tests/input/discard-events-to-unstable-iframe.html [ Failure ] +crbug.com/982194 http/tests/input/discard-events-to-unstable-iframe.html [ Failure Pass ] crbug.com/24182 http/tests/misc/acid3.html [ Pass ] crbug.com/874695 http/tests/misc/drag-not-loaded-image.html [ Pass ] -crbug.com/874695 http/tests/permissions/chromium/test-request-worker.html [ Pass Timeout ] +crbug.com/874695 http/tests/permissions/chromium/test-request-worker.html [ Pass ] crbug.com/982194 http/tests/security/mixedContent/insecure-css-resources.html [ Failure Pass ] crbug.com/24182 images/png-suite/test.html [ Pass ] crbug.com/874695 crbug.com/936165 media/autoplay-muted.html [ Crash Pass Timeout ] @@ -208,8 +206,6 @@ crbug.com/982194 external/wpt/css/css-contain/contain-paint-006.html [ Failure ] crbug.com/982194 external/wpt/css/css-contain/contain-paint-clip-015.html [ Failure ] crbug.com/982194 external/wpt/css/css-contain/contain-paint-clip-016.html [ Failure ] -crbug.com/982194 external/wpt/css/css-contain/contain-size-replaced-003b.html [ Failure Pass ] -crbug.com/982194 external/wpt/css/css-contain/contain-size-replaced-003c.html [ Failure Pass ] crbug.com/982194 external/wpt/css/css-contain/counter-scoping-001.html [ Failure ] crbug.com/982194 external/wpt/css/css-contain/counter-scoping-002.html [ Failure ] crbug.com/982194 external/wpt/css/css-contain/counter-scoping-003.html [ Failure ] @@ -331,11 +327,11 @@ crbug.com/982194 external/wpt/css/css-multicol/multicol-span-all-rule-001.html [ Failure ] crbug.com/982194 external/wpt/css/css-multicol/multicol-width-005.html [ Failure ] crbug.com/982194 external/wpt/css/css-multicol/nested-with-too-tall-line.html [ Failure ] -crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-009.html [ Failure ] -crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-010.html [ Failure ] -crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-012.html [ Failure ] -crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-013.html [ Failure ] -crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-014.html [ Failure ] +crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-009.html [ Failure Pass ] +crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-010.html [ Failure Pass ] +crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-012.html [ Failure Pass ] +crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-013.html [ Failure Pass ] +crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-014.html [ Failure Pass ] crbug.com/982194 external/wpt/css/css-overflow/webkit-line-clamp-024.html [ Failure ] crbug.com/982194 external/wpt/css/css-pseudo/first-letter-exclude-inline-child-marker.html [ Failure ] crbug.com/982194 external/wpt/css/css-pseudo/first-letter-exclude-inline-marker.html [ Failure ] @@ -521,7 +517,7 @@ crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/grid-abspos-staticpos-justify-self-vertWM-002.html [ Failure ] crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/grid-abspos-staticpos-justify-self-vertWM-003.html [ Failure ] crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/grid-abspos-staticpos-justify-self-vertWM-004.html [ Failure ] -crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-paint-ignored-cases-ruby-stacking-and-clipping-001.html [ Failure Pass ] +crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-paint-ignored-cases-ruby-stacking-and-clipping-001.html [ Pass ] crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/descriptor-suffix.html [ Failure ] crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/disclosure-styles.html [ Failure ] crbug.com/982194 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/symbols-function-invalid.html [ Pass ] @@ -608,7 +604,7 @@ crbug.com/982194 external/wpt/forced-colors-mode/forced-colors-mode-19.html [ Failure ] crbug.com/982194 external/wpt/forced-colors-mode/forced-colors-mode-23.html [ Failure ] crbug.com/982194 external/wpt/forced-colors-mode/forced-colors-mode-26.tentative.html [ Pass ] -crbug.com/982194 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ] +crbug.com/982194 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ] crbug.com/982194 external/wpt/html/canvas/offscreen/the-offscreen-canvas/offscreencanvas.resize.html [ Failure Pass ] crbug.com/982194 external/wpt/html/canvas/offscreen/the-offscreen-canvas/size.attributes.parse.em.worker.html [ Pass ] crbug.com/982194 external/wpt/html/canvas/offscreen/the-offscreen-canvas/size.attributes.parse.junk.worker.html [ Pass ] @@ -690,7 +686,8 @@ crbug.com/982194 external/wpt/svg/rendering/order/z-index.svg [ Failure ] crbug.com/982194 external/wpt/svg/text/reftests/text-complex-002.svg [ Failure ] crbug.com/982194 external/wpt/svg/text/reftests/text-xml-space-001.svg [ Failure ] -crbug.com/982194 external/wpt/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html [ Crash Failure ] +crbug.com/982194 external/wpt/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html [ Failure ] +crbug.com/982194 external/wpt/webrtc/RTCDataChannel-close.html [ Pass Timeout ] crbug.com/982194 external/wpt/webrtc/RTCPeerConnection-perfect-negotiation.https.html [ Failure Pass ] crbug.com/982194 external/wpt/websockets/opening-handshake/005.html [ Pass ] crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Failure ] @@ -717,7 +714,7 @@ crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir.html [ Failure ] crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/bidi/vertical_lr.html [ Failure ] crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/bidi/vertical_rl.html [ Failure ] -crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/cue_too_long.html [ Failure ] +crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/cue_too_long.html [ Failure Pass ] crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused.html [ Failure ] crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line.html [ Failure ] crbug.com/982194 external/wpt/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text.html [ Failure ] @@ -911,7 +908,6 @@ crbug.com/982194 http/tests/devtools/application-panel/storage-view-reports-quota.js [ Pass Timeout ] crbug.com/982194 http/tests/devtools/editor/text-editor-reveal-line.js [ Pass ] crbug.com/982194 http/tests/devtools/elements/styles-1/disable-property-workingcopy-update.js [ Pass ] -crbug.com/982194 http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Failure Pass ] crbug.com/982194 http/tests/devtools/indexeddb/database-refresh-view.js [ Pass ] crbug.com/982194 http/tests/devtools/network/network-eventsource.js [ Pass ] crbug.com/982194 http/tests/devtools/network/network-search.js [ Pass ] @@ -919,7 +915,7 @@ crbug.com/982194 http/tests/devtools/resource-tree/resource-tree-frame-navigate.js [ Pass ] crbug.com/982194 http/tests/devtools/resource-tree/resource-tree-htmlimports.js [ Pass ] crbug.com/982194 http/tests/devtools/service-workers/user-agent-override.js [ Pass ] -crbug.com/982194 http/tests/devtools/sources/debugger-breakpoints/disable-breakpoints.js [ Failure ] +crbug.com/982194 http/tests/devtools/sources/debugger-breakpoints/disable-breakpoints.js [ Failure Pass ] crbug.com/982194 http/tests/devtools/sources/debugger-breakpoints/set-breakpoint.js [ Failure Pass ] crbug.com/982194 http/tests/devtools/sources/debugger-breakpoints/set-conditional-breakpoint.js [ Failure Pass ] crbug.com/982194 http/tests/devtools/sources/debugger/debugger-disable-enable.js [ Pass ] @@ -943,7 +939,6 @@ crbug.com/874695 media/remoteplayback/prompt-twice-throws.html [ Pass ] crbug.com/982194 media/video-canvas-draw.html [ Failure Pass ] crbug.com/835484 paint/invalidation/outline/inline-focus.html [ Failure ] -crbug.com/982194 paint/invalidation/svg/transform-focus-ring-repaint.html [ Failure ] crbug.com/676229 plugins/mouse-click-plugin-clears-selection.html [ Failure ] crbug.com/982194 virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure ] crbug.com/982194 virtual/cache-storage-sequence/external/wpt/service-workers/service-worker/udate-bytecheck.https.html [ Timeout ] @@ -955,7 +950,7 @@ crbug.com/982194 virtual/gpu/fast/canvas/canvas-arc-circumference.html [ Failure ] crbug.com/982194 virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill.html [ Failure ] crbug.com/982194 virtual/gpu/fast/canvas/canvas-ellipse-circumference.html [ Failure ] -crbug.com/866850 virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html [ Pass ] +crbug.com/866850 virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html [ Failure Pass ] crbug.com/829028 virtual/layout_ng_block_frag/* [ Skip ] crbug.com/982194 virtual/layout_ng_block_frag/fast/multicol/span/list-multi-column-crash.html [ Pass ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/contain-layout-017.html [ Failure ] @@ -964,8 +959,6 @@ crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/contain-paint-021.html [ Failure ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/contain-paint-clip-015.html [ Failure ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/contain-paint-clip-016.html [ Failure ] -crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/contain-size-replaced-003b.html [ Failure Pass ] -crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/contain-size-replaced-003c.html [ Failure Pass ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/counter-scoping-001.html [ Failure ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/counter-scoping-002.html [ Failure ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/counter-scoping-003.html [ Failure ] @@ -973,7 +966,6 @@ crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/quote-scoping-002.html [ Failure ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/quote-scoping-003.html [ Failure ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/css-contain/quote-scoping-004.html [ Failure ] -crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-paint-ignored-cases-ruby-stacking-and-clipping-001.html [ Failure Pass ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-transform-translatez.html [ Failure ] crbug.com/982194 virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-block-margins-2.html [ Failure ] crbug.com/982194 virtual/layout_ng_fieldset/fast/forms/fieldset/legend-small-after-margin-before-border-horizontal-mode.html [ Failure ] @@ -993,7 +985,6 @@ crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-baseline-001.html [ Failure ] crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-001.html [ Failure ] crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-003.html [ Failure ] -crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-column-row-gap-004.html [ Failure Pass ] crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001a.html [ Failure ] crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001b.html [ Failure ] crbug.com/982194 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002a.html [ Failure ] @@ -1023,8 +1014,8 @@ crbug.com/982194 virtual/omt-worker-fetch/external/wpt/fetch/metadata/sec-fetch-dest/iframe.tentative.https.sub.html [ Timeout ] crbug.com/982194 virtual/omt-worker-fetch/external/wpt/fetch/metadata/sec-fetch-dest/window-open.tentative.https.sub.html [ Timeout ] crbug.com/982194 virtual/prefer_compositing_to_lcd_text/scrollbars/hidden-scrollbars-invisible.html [ Failure ] -crbug.com/982194 virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbar-over-child-layer-nested-2.html [ Failure Pass ] -crbug.com/982194 virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbar-over-child-layer-nested.html [ Failure Pass ] +crbug.com/982194 virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbar-over-child-layer-nested-2.html [ Pass ] +crbug.com/982194 virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbar-over-child-layer-nested.html [ Pass ] crbug.com/982194 virtual/scalefactor200/css3/filters/filterRegions.html [ Failure ] crbug.com/982194 virtual/scalefactor200/external/wpt/css/filter-effects/css-filters-animation-combined-001.html [ Failure ] crbug.com/982194 virtual/scalefactor200/external/wpt/css/filter-effects/filtered-inline-applies-to-float.html [ Pass ] @@ -1035,7 +1026,7 @@ crbug.com/982194 virtual/scalefactor200withoutzoom/external/wpt/largest-contentful-paint/first-paint-equals-lcp-text.html [ Failure ] crbug.com/982194 virtual/stable/media/stable/video-object-fit-stable.html [ Failure Pass ] crbug.com/982194 virtual/text-antialias/font-format-support-color-cff2-vertical.html [ Failure ] -crbug.com/982194 virtual/threaded-no-composited-antialiasing/animations/events/animation-iteration-event.html [ Failure Pass ] +crbug.com/982194 virtual/threaded-no-composited-antialiasing/animations/events/animation-iteration-event.html [ Pass ] crbug.com/982194 virtual/threaded-no-composited-antialiasing/animations/timing/animation-duration-infinite.html [ Pass ] crbug.com/982194 virtual/threaded/external/wpt/feature-policy/experimental-features/lazyload/lazyload-disabled-tentative.sub.html [ Pass ] crbug.com/982194 virtual/threaded/external/wpt/feature-policy/experimental-features/lazyload/lazyload-enabled-tentative.sub.html [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 7fe9d53..acc8ef6e 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3627,7 +3627,6 @@ crbug.com/881180 external/wpt/xhr/open-url-multi-window-4.htm [ Timeout ] crbug.com/655458 external/wpt/workers/Worker_terminate_event_queue.htm [ Pass Timeout ] -crbug.com/655458 external/wpt/workers/semantics/multiple-workers/007.html [ Timeout ] crbug.com/910709 navigator_language/worker_navigator_language.html [ Timeout ] @@ -5841,7 +5840,7 @@ # Sheriff 2020-05-04 crbug.com/952717 [ Debug ] http/tests/xmlhttprequest/redirect-cross-origin-post.html [ Pass Failure ] -crbug.com/984467 [ Mac Debug ] virtual/gpu/fast/canvas/canvas-composite-stroke-alpha.html [ Pass Timeout ] +crbug.com/984467 virtual/gpu/fast/canvas/canvas-composite-stroke-alpha.html [ Pass Timeout ] # Sheriff 2020-05-06 crbug.com/1078863 [ Mac ] fast/speech/scripted/speechrecognition-restart-onend.html [ Pass Timeout ] @@ -5900,7 +5899,13 @@ crbug.com/1088007 virtual/gpu/fast/canvas/OffscreenCanvas-MessageChannel-transfer.html [ Pass Failure ] # Sheriff 2020-06-03 -crbug.com/1007228 [ Mac10.13 ] external/wpt/fullscreen/api/element-request-fullscreen-and-move-to-iframe-manual.html [ Pass Failure ] +crbug.com/1007228 [ Mac ] external/wpt/fullscreen/api/element-request-fullscreen-and-move-to-iframe-manual.html [ Pass Failure ] # Disabled for landing DevTools change crbug.com/1011811 http/tests/devtools/persistence/automapping-sourcemap.js [ Pass Failure ] + +# Sheriff 2020-06-03 +crbug.com/1088441 [ Mac ] http/tests/loading/bad-server-subframe.html [ Pass Failure ] +crbug.com/1090822 [ Mac10.10 ] virtual/cascade/fast/forms/month/month-appearance-basic.html [ Pass Failure ] +crbug.com/1083293 [ Linux ] media/video-aspect-ratio.html [ Pass Failure ] +crbug.com/1027434 [ Mac10.13 ] virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 694d34a..48ea662e 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -767,6 +767,11 @@ "args": ["--enable-features=MediaInspectorLogging"] }, { + "prefix": "link-disabled-old-behavior", + "bases": [ "external/wpt/css/cssom" ], + "args": ["--disable-features=LinkDisabledNewSpecBehavior"] + }, + { "prefix": "media-capture-image-ptz", "bases": [ "external/wpt/mediacapture-image" ], "args": [ "--enable-blink-features=MediaCapturePanTilt" ]
diff --git a/third_party/blink/web_tests/W3CImportExpectations b/third_party/blink/web_tests/W3CImportExpectations index 9f412f3..1b38278b9 100644 --- a/third_party/blink/web_tests/W3CImportExpectations +++ b/third_party/blink/web_tests/W3CImportExpectations
@@ -109,7 +109,6 @@ external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ui3 [ Skip ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/values3 [ Skip ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/will-change [ Skip ] -external/wpt/docs [ Skip ] external/wpt/dpub-aam [ Skip ] external/wpt/dpub-aria [ Skip ] external/wpt/html-longdesc [ Skip ]
diff --git a/third_party/blink/web_tests/cssom/stylesheetlist-01.html b/third_party/blink/web_tests/cssom/stylesheetlist-01.html index 1f621f5..bf929ef 100644 --- a/third_party/blink/web_tests/cssom/stylesheetlist-01.html +++ b/third_party/blink/web_tests/cssom/stylesheetlist-01.html
@@ -14,7 +14,7 @@ var colorTest = async_test("Check that no stylesheets are applied when disabled"); var testObj = new Object; for (var i=0; i<5; i++) { - testObj[i] = async_test("#s"+(i+1)+" accessible through document.styleSheets after disabling"); + testObj[i] = async_test(`#s${i+1}${(i<3) ? ' NOT' : ''} accessible through document.styleSheets after disabling`); } onload = function(){ @@ -38,13 +38,18 @@ colorTest.done(); count = document.styleSheets.length; + assert_equals(count, 2); // Just the <style> nodes for (i=0; i<count; i++) testObj[document.styleSheets[i].ownerNode.id] = true; for (i=0; i<5; i++) { testObj[i].step(function(){ - assert_true(testObj["s"+(i+1)]); - }, "Check if #s"+(i+1)+" is present in document.styleSheets after it is disabled"); + if (i<3) { + assert_true(!testObj["s"+(i+1)]); + } else { + assert_true(testObj["s"+(i+1)]); + } + }, "Check if #s"+(i+1)+" is present in document.styleSheets for <style> but not <link> after it is disabled"); testObj[i].done(); } };
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 22a5c83..074cc129 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -235204,10 +235204,6 @@ "549fd183560bc0abd867ede2042e7377d41d9c30", [] ], - "006-1.js": [ - "6c1ed932321caa6b5b36643b96845eff49a2a435", - [] - ], "006-expected.txt": [ "124b56d7407a58eda237af1814f82de8b4ddb6da", [] @@ -235219,6 +235215,10 @@ "008.js": [ "92593ebb865f8f376903cc282cffa2d3a31a013f", [] + ], + "exposure.any.sharedworker-expected.txt": [ + "dab9c6a93cb490b251a83d161e7c83b53f4ef3eb", + [] ] }, "navigation": { @@ -253049,7 +253049,7 @@ ] ], "idlharness.window.js": [ - "91793af71e741ef6546d1eca37e93338ab2779f7", + "8cb73acbde43399094d60c2db09cc8ebab9c1946", [ "compat/idlharness.window.html", { @@ -253061,8 +253061,13 @@ [ "script", "/resources/idlharness.js" + ], + [ + "timeout", + "long" ] - ] + ], + "timeout": "long" } ] ], @@ -264144,10 +264149,12 @@ ] ], "idlharness.https.html": [ - "fcb31ad25650a758a3cedd0e94c3d38777eaed6c", + "23fc2cb9e631797de57076128a052a22bc95198a", [ null, - {} + { + "timeout": "long" + } ] ] }, @@ -301427,10 +301434,12 @@ ] ], "idlharness.https.html": [ - "b501bde9d25511b2ac38e0431b9211ed6083a4bf", + "b8bdf46c100300351f67bb70e512720c6b104e38", [ null, - {} + { + "timeout": "long" + } ] ] }, @@ -345790,7 +345799,7 @@ }, "keyboard-lock": { "idlharness.https.window.js": [ - "7a20d8b544dfdbf55f556410b28698a86f14061e", + "9c94411eabf28fc39cd9f7a7bf96e51262bcd47e", [ "keyboard-lock/idlharness.https.window.html", { @@ -345802,8 +345811,13 @@ [ "script", "/resources/idlharness.js" + ], + [ + "timeout", + "long" ] - ] + ], + "timeout": "long" } ] ], @@ -347173,6 +347187,13 @@ ] }, "tables": { + "dynamic-table-001.html": [ + "f73227b05715f1130bd9148ea6d1604e56302d6e", + [ + null, + {} + ] + ], "table-001.html": [ "f967f62a22b2c731b0ad83ded970165539391abe", [ @@ -354818,7 +354839,7 @@ ] ], "idlharness.window.js": [ - "31cd4a14177bccd277023a98ea5956e5f018e2e1", + "c74894a45f438dc493fefbec24df65acc0d6c261", [ "picture-in-picture/idlharness.window.html", { @@ -354846,8 +354867,13 @@ [ "script", "resources/picture-in-picture-helpers.js" + ], + [ + "timeout", + "long" ] - ] + ], + "timeout": "long" } ] ], @@ -356352,10 +356378,12 @@ ] ], "idlharness.https.html": [ - "52aa8c55328c7b9226581779793955b62b4d5126", + "1cb8830f89c4a3a8eecf87d6f772592b4c40d8a6", [ null, - {} + { + "timeout": "long" + } ] ], "reconnectToPresentation_sandboxing_success.https.html": [ @@ -401718,35 +401746,59 @@ } ] ], - "005.html": [ - "d5e21ea527476b059fde7dbc67b2d04339068bd5", - [ - null, - {} - ] - ], - "006.html": [ - "7fbfd8e90f8014373f73818757b8787f0a9caeea", - [ - null, - {} - ] - ], - "007.html": [ - "5045759647bf6bbe6ebc7595e3eb5874f9f1babf", - [ - null, - { - "timeout": "long" - } - ] - ], "008.html": [ "ee38d80866e8bb4deb6322dd251dfb3da78bc492", [ null, {} ] + ], + "exposure.any.js": [ + "7e226a7333fb4904c3ea42c691f227f8ce8c194e", + [ + "workers/semantics/multiple-workers/exposure.any.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ] + ] + } + ], + [ + "workers/semantics/multiple-workers/exposure.any.serviceworker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ] + ] + } + ], + [ + "workers/semantics/multiple-workers/exposure.any.sharedworker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ] + ] + } + ], + [ + "workers/semantics/multiple-workers/exposure.any.worker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ] + ] + } + ] ] }, "navigation": {
diff --git a/third_party/blink/web_tests/external/wpt/compat/idlharness.window.js b/third_party/blink/web_tests/external/wpt/compat/idlharness.window.js index 91793af7..8cb73ac 100644 --- a/third_party/blink/web_tests/external/wpt/compat/idlharness.window.js +++ b/third_party/blink/web_tests/external/wpt/compat/idlharness.window.js
@@ -1,5 +1,6 @@ // META: script=/resources/WebIDLParser.js // META: script=/resources/idlharness.js +// META: timeout=long 'use strict';
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt index 8c956d51c..9dc4691 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt
@@ -20,7 +20,7 @@ PASS KeyframeEffect.getKeyframes() returns expected values for animations with text-shadow properties and missing keyframes PASS KeyframeEffect.getKeyframes() returns expected values for animations with background-size properties and missing keyframes FAIL KeyframeEffect.getKeyframes() returns expected values for animations with CSS variables as keyframe values assert_equals: value for 'transform' on Keyframe #1 should match expected "translate(100px)" but got "translate(var(--var-100px), 0) " -FAIL KeyframeEffect.getKeyframes() returns expected values for animations with CSS variables as keyframe values in a shorthand property assert_equals: value for 'marginTop' on Keyframe #1 should match expected "100px" but got "" +FAIL KeyframeEffect.getKeyframes() returns expected values for animations with CSS variables as keyframe values in a shorthand property assert_equals: value for 'marginBottom' on Keyframe #1 should match expected "100px" but got "" FAIL KeyframeEffect.getKeyframes() returns expected values for animations with a CSS variable which is overriden by the value in keyframe assert_array_equals: properties on Keyframe #0 should match lengths differ, expected array ["color", "composite", "computedOffset", "easing", "offset"] length 5, got ["--end-color", "color", "composite", "computedOffset", "easing", "offset"] length 6 FAIL KeyframeEffect.getKeyframes() returns expected values for animations with only custom property in a keyframe assert_equals: value for 'transform' on Keyframe #0 should match expected "translate(100px)" but got "translate(100px, 0px)" PASS KeyframeEffect.getKeyframes() reflects changes to @keyframes rules
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/support/testcommon.js b/third_party/blink/web_tests/external/wpt/css/css-animations/support/testcommon.js index e26a7a18..a7575b1 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-animations/support/testcommon.js +++ b/third_party/blink/web_tests/external/wpt/css/css-animations/support/testcommon.js
@@ -48,7 +48,8 @@ `properties on ${name} should match` ); - for (const prop in actual) { + // Iterates sorted keys to ensure stable failures. + for (const prop of Object.keys(actual).sort()) { if ( // 'offset' can be null (prop === 'offset' && typeof actual[prop] === 'number') ||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https.html b/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https.html index fcb31ad2..23fc2cb9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https.html +++ b/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <title>Font Loading API IDL tests</title> +<meta name="timeout" content="long"> <link rel="help" href="https://drafts.csswg.org/css-font-loading/#fontfacesetloadevent"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-001.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-001.tentative-expected.txt deleted file mode 100644 index b078ddb..0000000 --- a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-001.tentative-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -PASS <link disabled> prevents the stylesheet from being in document.styleSheets (from parser) -FAIL HTMLLinkElement.disabled reflects the <link disabled> attribute, and behaves consistently assert_equals: expected null but got Element node <link title="alt" rel="stylesheet" href="data:text/css,ht... -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-002.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-002.tentative-expected.txt deleted file mode 100644 index 176385c..0000000 --- a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-002.tentative-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL HTMLLinkElement.disabled reflects the <link disabled> attribute, and behaves consistently, when the sheet is an alternate assert_equals: expected null but got Element node <link title="alt" rel="alternate stylesheet" href="data:t... -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-007.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-007.tentative-expected.txt deleted file mode 100644 index 4fac017..0000000 --- a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-007.tentative-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL HTMLLinkElement.disabled setter sets the explicitly enabled state if toggled back and forth. assert_equals: expected "rgb(0, 128, 0)" but got "rgba(0, 0, 0, 0)" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/encrypted-media/idlharness.https.html b/third_party/blink/web_tests/external/wpt/encrypted-media/idlharness.https.html index b501bde..b8bdf46c 100644 --- a/third_party/blink/web_tests/external/wpt/encrypted-media/idlharness.https.html +++ b/third_party/blink/web_tests/external/wpt/encrypted-media/idlharness.https.html
@@ -3,6 +3,7 @@ <head> <meta charset=utf-8> <title>Encrypted Media Extentions IDL test</title> + <meta name="timeout" content="long"> <link rel="help" href="https://w3c.github.io/encrypted-media/"> <script src=/resources/testharness.js></script>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js b/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js index d01ff1d..749cfe3 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js +++ b/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js
@@ -204,21 +204,23 @@ // Tests the given |eventType| by creating events whose target are the element with id // 'target'. The test assumes that such element already exists. |looseCount| is set for -// eventTypes for which events would occur for other elements besides the target, so the -// counts will be larger. +// eventTypes for which events would occur for other interactions other than the ones being +// specified for the target, so the counts could be larger. async function testEventType(t, eventType, looseCount=false) { assert_implements(window.EventCounts, "Event Counts isn't supported"); - assert_equals(performance.eventCounts.get(eventType), 0); const target = document.getElementById('target'); if (requiresListener(eventType)) { target.addEventListener(eventType, () =>{}); } - assert_equals(performance.eventCounts.get(eventType), 0, 'No events yet.'); + const initialCount = performance.eventCounts.get(eventType); + if (!looseCount) { + assert_equals(initialCount, 0, 'No events yet.'); + } // Trigger two 'fast' events of the type. await applyAction(eventType, target); await applyAction(eventType, target); await new Promise(t.step_func(resolve => { - testCounts(t, resolve, looseCount, eventType, 2); + testCounts(t, resolve, looseCount, eventType, initialCount + 2); })); // The durationThreshold used by the observer. A slow events needs to be slower than that. const durationThreshold = 16; @@ -254,7 +256,7 @@ notCancelable(eventType)); // Shouldn't need async testing here since we already got the observer entry, but might as // well reuse the method. - testCounts(t, resolve, looseCount, eventType, 3); + testCounts(t, resolve, looseCount, eventType, initialCount + 3); })).observe({type: 'event', durationThreshold: durationThreshold}); }); // Cause a slow event.
diff --git a/third_party/blink/web_tests/external/wpt/keyboard-lock/idlharness.https.window.js b/third_party/blink/web_tests/external/wpt/keyboard-lock/idlharness.https.window.js index 7a20d8b..9c94411e 100644 --- a/third_party/blink/web_tests/external/wpt/keyboard-lock/idlharness.https.window.js +++ b/third_party/blink/web_tests/external/wpt/keyboard-lock/idlharness.https.window.js
@@ -1,5 +1,6 @@ // META: script=/resources/WebIDLParser.js // META: script=/resources/idlharness.js +// META: timeout=long // https://w3c.github.io/keyboard-lock/
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tables/dynamic-table-001.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tables/dynamic-table-001.html new file mode 100644 index 0000000..f73227b0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tables/dynamic-table-001.html
@@ -0,0 +1,301 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Dynamic tabular elements</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<script src="/mathml/support/mathml-fragments.js"></script> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#table-or-matrix-mtable"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#dom-and-javascript"> +<meta name="assert" content="Dynamically modify DOM tree of mtables"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> +<script src="/mathml/support/layout-comparison.js"></script> +<script> + function forceCells(mtable, rows, cols) { + while (mtable.children.length > rows) + mtable.removeChild(mtable.lastElementChild); + while (mtable.children.length < rows) + mtable.appendChild(FragmentHelper.createElement("mtr")); + for (let i = 0; i < rows; i++) { + let mtr = mtable.children[i]; + while (mtr.children.length > cols) + mtr.removeChild(mtr.lastElementChild); + while (mtr.children.length < cols) + mtr.appendChild(FragmentHelper.createElement("mtd")); + + for (let j = 0; j < cols; j++) { + let mtd = mtr.children[j]; + while (mtd.children.length > 0) + mtd.removeChild(mtd.lastElementChild); + let mspace = FragmentHelper.createElement("mspace"); + mspace.setAttribute("height", `${10*(i+1)}px`); + mspace.setAttribute("width", `${10*(j+1)}px`); + mspace.setAttribute("style", `background: black;`); + mtd.appendChild(mspace); + } + } + } + + setup({ explicit_done: true }); + window.addEventListener("load", function() { + // force initial layout so we're sure what we're testing against + document.documentElement.getBoundingClientRect(); + + let reference = document.getElementById("reference"); + + Array.from(document.querySelectorAll("[data-title]")).forEach(mtable => { + test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + forceCells(mtable, 4, 3); + const epsilon = 1; + compareLayout(mtable, reference, epsilon); + }, `${mtable.getAttribute("data-title")}`); + }); + done(); + }); +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mtable id="reference"> + <mtr> + <mtd><mspace height="10px" width="10px" style="background: blue;"/></mtd> + <mtd><mspace height="10px" width="20px" style="background: blue;"/></mtd> + <mtd><mspace height="10px" width="30px" style="background: blue;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="20px" width="10px" style="background: blue;"/></mtd> + <mtd><mspace height="20px" width="20px" style="background: blue;"/></mtd> + <mtd><mspace height="20px" width="30px" style="background: blue;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="30px" width="10px" style="background: blue;"/></mtd> + <mtd><mspace height="30px" width="20px" style="background: blue;"/></mtd> + <mtd><mspace height="30px" width="30px" style="background: blue;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="40px" width="10px" style="background: blue;"/></mtd> + <mtd><mspace height="40px" width="20px" style="background: blue;"/></mtd> + <mtd><mspace height="40px" width="30px" style="background: blue;"/></mtd> + </mtr> + </mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Filling an empty mtable element"></mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Filling empty mtr elements"> + <mtr></mtr> + <mtr></mtr> + <mtr></mtr> + <mtr></mtr> + </mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Filling empty mtd elements"> + <mtr> + <mtd></mtd> + <mtd></mtd> + <mtd></mtd> + </mtr> + <mtr> + <mtd></mtd> + <mtd></mtd> + <mtd></mtd> + </mtr> + <mtr> + <mtd></mtd> + <mtd></mtd> + <mtd></mtd> + </mtr> + <mtr> + <mtd></mtd> + <mtd></mtd> + <mtd></mtd> + </mtr> + </mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Filling an empty mtr element"> + <mtr> + <mtd><mspace height="10px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <!-- Empty mtr --> + </mtr> + <mtr> + <mtd><mspace height="30px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="40px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="30px" style="background: black;"/></mtd> + </mtr> + </mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Filling an empty mtd element"> + <mtr> + <mtd><mspace height="10px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="20px" width="10px" style="background: black;"/></mtd> + <mtd><!-- Empty --></mtd> + <mtd><mspace height="20px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="30px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="40px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="30px" style="background: black;"/></mtd> + </mtr> + </mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Adding missing elements"> + <mtr> + <mtd><mspace height="10px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="20px" style="background: black;"/></mtd> + <!-- Cell missing --> + </mtr> + <mtr> + <mtd><mspace height="20px" width="10px" style="background: black;"/></mtd> + <mtd><!-- Empty --></mtd> + <mtd><mspace height="20px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="30px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="30px" style="background: black;"/></mtd> + </mtr> + <!-- Row missing --> + </mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Removing a row"> + <mtr> + <mtd><mspace height="10px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="20px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="20px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="20px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="30px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="40px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="30px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="50px" width="10px" style="background: red;"/></mtd> + <mtd><mspace height="50px" width="20px" style="background: red;"/></mtd> + <mtd><mspace height="50px" width="30px" style="background: red;"/></mtd> + </mtr> + </mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Removing a column"> + <mtr> + <mtd><mspace height="10px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="30px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="40px" style="background: red;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="20px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="20px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="20px" width="30px" style="background: black;"/></mtd> + <mtd><mspace height="20px" width="40px" style="background: red;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="30px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="30px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="40px" style="background: red;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="40px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="30px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="40px" style="background: red;"/></mtd> + </mtr> + </mtable> + </math> + </p> + <p> + <math> + <mtable data-title="Removing extra elements"> + <mtr> + <mtd><mspace height="10px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="30px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="40px" style="background: black;"/></mtd> + <mtd><mspace height="10px" width="50px" style="background: red;"/></mtd><!-- extra mtd --> + </mtr> + <mtr> + <mtd><mspace height="20px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="20px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="20px" width="30px" style="background: black;"/></mtd> + <mtd><mspace height="20px" width="40px" style="background: black;"/><mspace height="20px" width="40px" style="background: red;"/><!-- extra child--></mtd> + </mtr> + <mtr> + <mtd><mspace height="30px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="30px" style="background: black;"/></mtd> + <mtd><mspace height="30px" width="40px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="40px" width="10px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="20px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="30px" style="background: black;"/></mtd> + <mtd><mspace height="40px" width="40px" style="background: black;"/></mtd> + </mtr> + <mtr> + <mtd><mspace height="50px" width="10px" style="background: red;"/></mtd> + <mtd><mspace height="50px" width="20px" style="background: red;"/></mtd> + <mtd><mspace height="50px" width="30px" style="background: red;"/></mtd> + <mtd><mspace height="50px" width="40px" style="background: red;"/></mtd> + </mtr> <!-- extra row --> + </mtable> + </math> + </p> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/opaque-origin.https.window.js b/third_party/blink/web_tests/external/wpt/native-file-system/opaque-origin.https.window.js index 2385c31..2655147 100644 --- a/third_party/blink/web_tests/external/wpt/native-file-system/opaque-origin.https.window.js +++ b/third_party/blink/web_tests/external/wpt/native-file-system/opaque-origin.https.window.js
@@ -38,7 +38,7 @@ // |kSandboxWindowUrl| sends two messages to this window. The first is the // result of chooseFileSystemEntries(). The second is the result of -// getSystemDirectory(). For windows using sandbox='allow-scripts', +// getOriginPrivateDirectory(). For windows using sandbox='allow-scripts', // both results must produce rejected promises. async function verify_results_from_sandboxed_child_window(test) { const event_watcher = new EventWatcher(test, self, 'message'); @@ -49,7 +49,7 @@ const second_message_event = await event_watcher.wait_for('message'); assert_equals(second_message_event.data, - 'getSystemDirectory(): REJECTED: SecurityError'); + 'getOriginPrivateDirectory(): REJECTED: SecurityError'); } promise_test(async test => { @@ -65,7 +65,7 @@ promise_test(async test => { add_iframe(test, kSandboxWindowUrl, /*sandbox=*/'allow-scripts'); await verify_results_from_sandboxed_child_window(test); -}, 'FileSystemDirectoryHandle.getSystemDirectory() and ' + +}, 'getOriginPrivateDirectory() and ' + 'chooseFileSystemEntries() must reject in a sandboxed iframe.'); promise_test(async test => { @@ -78,5 +78,5 @@ }); await verify_results_from_sandboxed_child_window(test); -}, 'FileSystemDirectoryHandle.getSystemDirectory() and ' +}, 'getOriginPrivateDirectory() and ' + 'chooseFileSystemEntries() must reject in a sandboxed opened window.');
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/resources/message-target.js b/third_party/blink/web_tests/external/wpt/native-file-system/resources/message-target.js index b9c0e4f..423bcf42 100644 --- a/third_party/blink/web_tests/external/wpt/native-file-system/resources/message-target.js +++ b/third_party/blink/web_tests/external/wpt/native-file-system/resources/message-target.js
@@ -85,8 +85,7 @@ case 'create-file': // Create a new file and then respond to the sender with it. const directory = - await FileSystemDirectoryHandle.getSystemDirectory( - { type: 'sandbox' }); + await self.getOriginPrivateDirectory(); const file_handle = await directory.getFile('temp-file', { create: true }); message_source.postMessage( @@ -97,8 +96,7 @@ case 'create-directory': // Create a new directory and then respond to the sender with it. const parent_directory = - await FileSystemDirectoryHandle.getSystemDirectory( - { type: 'sandbox' }); + await self.getOriginPrivateDirectory(); const directory_handle = await parent_directory.getDirectory('temp-directory', { create: true });
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/resources/opaque-origin-sandbox.html b/third_party/blink/web_tests/external/wpt/native-file-system/resources/opaque-origin-sandbox.html index 07301af..70b5ac54 100644 --- a/third_party/blink/web_tests/external/wpt/native-file-system/resources/opaque-origin-sandbox.html +++ b/third_party/blink/web_tests/external/wpt/native-file-system/resources/opaque-origin-sandbox.html
@@ -4,7 +4,7 @@ // Sends two messages to its creator: // (1) The result of chooseFileSystemEntries(). - // (2) The result of FileSystemDirectoryHandle.getSystemDirectory(). + // (2) The result of getOriginPrivateDirectory(). function post_message(data) { if (window.parent !== null) { @@ -27,13 +27,13 @@ } try { - window.FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }) + window.getOriginPrivateDirectory() .then(() => { - post_message('getSystemDirectory(): FULFILLED'); + post_message('getOriginPrivateDirectory(): FULFILLED'); }).catch(error => { - post_message(`getSystemDirectory(): REJECTED: ${error.name}`); + post_message(`getOriginPrivateDirectory(): REJECTED: ${error.name}`); }); } catch (error) { - post_message(`getSystemDirectory(): EXCEPTION: ${error.name}`); + post_message(`getOriginPrivateDirectory(): EXCEPTION: ${error.name}`); } </script>
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/resources/sandboxed-fs-test-helpers.js b/third_party/blink/web_tests/external/wpt/native-file-system/resources/sandboxed-fs-test-helpers.js index 5f4f269d..3ec3143 100644 --- a/third_party/blink/web_tests/external/wpt/native-file-system/resources/sandboxed-fs-test-helpers.js +++ b/third_party/blink/web_tests/external/wpt/native-file-system/resources/sandboxed-fs-test-helpers.js
@@ -8,7 +8,7 @@ async function cleanupSandboxedFileSystem() { const dir = - await FileSystemDirectoryHandle.getSystemDirectory({type: 'sandbox'}); + await self.getOriginPrivateDirectory(); for await (let entry of dir.getEntries()) await dir.removeEntry(entry.name, {recursive: entry.isDirectory}); } @@ -19,7 +19,7 @@ await cleanupSandboxedFileSystem(); const dir = - await FileSystemDirectoryHandle.getSystemDirectory({type: 'sandbox'}); + await self.getOriginPrivateDirectory(); await func(t, dir); }, description); }
diff --git a/third_party/blink/web_tests/external/wpt/picture-in-picture/idlharness.window.js b/third_party/blink/web_tests/external/wpt/picture-in-picture/idlharness.window.js index 31cd4a1..c74894a 100644 --- a/third_party/blink/web_tests/external/wpt/picture-in-picture/idlharness.window.js +++ b/third_party/blink/web_tests/external/wpt/picture-in-picture/idlharness.window.js
@@ -4,6 +4,7 @@ // META: script=/resources/testdriver.js // META: script=/resources/testdriver-vendor.js // META: script=resources/picture-in-picture-helpers.js +// META: timeout=long 'use strict';
diff --git a/third_party/blink/web_tests/external/wpt/presentation-api/controlling-ua/idlharness.https.html b/third_party/blink/web_tests/external/wpt/presentation-api/controlling-ua/idlharness.https.html index 52aa8c5..1cb8830f 100644 --- a/third_party/blink/web_tests/external/wpt/presentation-api/controlling-ua/idlharness.https.html +++ b/third_party/blink/web_tests/external/wpt/presentation-api/controlling-ua/idlharness.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Presentation API IDL tests for Controlling User Agent</title> +<meta name="timeout" content="long"> <link rel="author" title="Louay Bassbouss" href="http://www.fokus.fraunhofer.de"> <link rel="help" href="http://w3c.github.io/presentation-api/#dfn-controlling-user-agent"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation-effect-phases.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation-effect-phases.tentative.html new file mode 100644 index 0000000..df7ab694 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation-effect-phases.tentative.html
@@ -0,0 +1,154 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Verify timeline time, animation time, effect time and effect value for all fill modes in all timeline states: before start, at start, in range, at end, after end while using various effect delay values</title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="testcommon.js"></script> +<style> + .scroller { + overflow: auto; + height: 100px; + width: 100px; + } + .contents { + height: 1000px; + width: 100%; + } +</style> +<div id="log"></div> +<script> + 'use strict'; + + // Test cases are included where effect delay causes the effect iteration to + // overlap with the timeline start time and also the timeline end time. + // Timeline + // BEFORE +-----------------+ AFTER + // time: 0 timeRange + // 1) +--------+ + // 2) +-------+ + // 3) +------+ + // 4) +------+ + + // Each entry is [[test input], [test expectations]] + // test input = ["description", delay, scroll percent] + // test expectations = [timeline time, animation current time, + // effect local time, effect progress, effect phase] + const test_cases = [ + // Case 1: No delay. Effect starts at the same time as the timeline. + [["before timeline start", 0, 0.1 ], [0, 0, 0, null, "before"]], + [["at timeline start", 0, 0.2 ], [0, 0, 0, 0, "active"]], + [["in timeline range", 0, 0.5 ], [500, 500, 500, 0.833, "active"]], + + // Case 2: Positive delay. + [["before timeline start", 100, 0.1 ], [0, 0, 0, null, "before"]], + [["at timeline start", 100, 0.2 ], [0, 0, 0, null, "before"]], + [["before effect delay", 100, 0.25], [83.333, 83.333, 83.333, null, "before"]], + [["at effect start", 100, 0.26], [100, 100, 100, 0, "active"]], + [["in timeline range", 100, 0.5 ], [500, 500, 500, 0.666, "active"]], + [["at effect end", 100, 0.62], [700, 700, 700, null, "after"]], + [["after effect end", 100, 0.65], [750, 700, 700, null, "after"]], + [["at timeline end", 100, 0.8 ], [1000, 700, 700, null, "after"]], + [["after timeline end", 100, 0.9 ], [1000, 700, 700, null, "after"]], + + // Case 3: Negative delay. + // Can't test values for "before effect delay" and "at effect start" because + // they occur before the timeline start and are therefore unreachable. + [["before timeline start", -100, 0.1 ], [0, 0, 0, null, "before"]], + [["at timeline start", -100, 0.2 ], [0, 0, 0, 0.166, "active"]], + [["in timeline range", -100, 0.3 ], [166.666, 166.666, 166.666, 0.444, "active"]], + [["at effect end", -100, 0.5 ], [500, 500, 500, null, "after"]], + [["after effect end", -100, 0.51], [516.666, 500, 500, null, "after"]], + [["at timeline end", -100, 0.8 ], [1000, 500, 500, null, "after"]], + [["after timeline end", -100, 0.9 ], [1000, 500, 500, null, "after"]], + + // Case 4: Effect delay is large enough to cause the effect to not finish + // before the timeline. + [["before timeline start", 500, 0.1 ], [0, 0, 0, null, "before"]], + [["at timeline start", 500, 0.2 ], [0, 0, 0, null, "before"]], + [["before effect delay", 500, 0.4 ], [333.333, 333.333, 333.333, null, "before"]], + [["at effect start", 500, 0.5 ], [500, 500, 500, 0, "active"]], + [["in timeline range", 500, 0.65], [750, 750, 750, 0.416, "active"]], + [["at timeline end", 500, 0.8 ], [1000, 1000, 1000, 0.833, "active"]], + [["after timeline end", 500, 0.9 ], [1000, 1000, 1000, 0.833, "active"]], + // Can't scroll past the end of the scroller and therefore cannot reach the + // effect end, so "at effect end" and "after effect end" states are not + // included. + ]; + + for (const test_case of test_cases) { + const [inputs, expected] = test_case; + const [test_name, delay, scroll_percentage] = inputs; + + const description = `Current times and effect phase ${test_name} when` + + ` delay = ${delay} |`; + + promise_test( + create_scroll_timeline_fill_test(delay, scroll_percentage, expected), + description); + } + + function create_scroll_timeline_fill_test(delay, scroll_percentage, expected){ + return async t => { + const target = createDiv(t); + const timeline = createScrollTimelineWithOffsets(t, "20%", "80%"); + const effect = new KeyframeEffect( + target, + { + opacity: [0.3, 0.7] + }, + { + duration: 600, + delay: delay + } + ); + const animation = new Animation(effect, timeline); + const scroller = timeline.scrollSource; + const maxScroll = scroller.scrollHeight - scroller.clientHeight; + + animation.play(); + + await animation.ready; + + scroller.scrollTop = scroll_percentage * maxScroll; + + // Wait for new animation frame which allows the timeline to compute + // new current time. + await waitForNextFrame(); + + const [expected_timeline_current_time, + expected_animation_current_time, + expected_effect_local_time, + expected_effect_progress, + expected_effect_phase] = expected; + + assert_times_equal( + animation.timeline.currentTime, + expected_timeline_current_time, + "timeline current time" + ); + assert_times_equal( + animation.currentTime, + expected_animation_current_time, + "animation current time" + ); + assert_times_equal( + animation.effect.getComputedTiming().localTime, + expected_effect_local_time, + "animation effect local time" + ); + assert_approx_equals_or_null( + animation.effect.getComputedTiming().progress, + expected_effect_progress, + 0.001, + "animation effect progress" + ); + assert_phase_at_time( + animation, + expected_effect_phase, + animation.currentTime + ); + } + } +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/testcommon.js b/third_party/blink/web_tests/external/wpt/scroll-animations/testcommon.js index c7290f1..d9fc153 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/testcommon.js +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/testcommon.js
@@ -47,3 +47,11 @@ new KeyframeEffect(createDiv(test), KEYFRAMES, DURATION), timeline); } +function assert_approx_equals_or_null(actual, expected, tolerance, name){ + if (actual === null || expected === null){ + assert_equals(actual, expected, name); + } + else { + assert_approx_equals(actual, expected, tolerance, name); + } +}
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/resources/keyframe-utils.js b/third_party/blink/web_tests/external/wpt/web-animations/resources/keyframe-utils.js index 971e82e..fdea1d8 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/resources/keyframe-utils.js +++ b/third_party/blink/web_tests/external/wpt/web-animations/resources/keyframe-utils.js
@@ -28,7 +28,8 @@ assert_equals(Object.keys(a).sort().toString(), Object.keys(b).sort().toString(), `properties on ${name} should match`); - for (const p in a) { + // Iterates sorted keys to ensure stable failures. + for (const p of Object.keys(a).sort()) { assert_equals(a[p], b[p], `value for '${p}' on ${name}`); } }
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/testcommon.js b/third_party/blink/web_tests/external/wpt/web-animations/testcommon.js index 1eb24f6..baa7550d 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/testcommon.js +++ b/third_party/blink/web_tests/external/wpt/web-animations/testcommon.js
@@ -275,3 +275,34 @@ `expected ${expected} but got ${actual}: ${description}`); } } + +function assert_phase_at_time(animation, phase, currentTime) { + animation.currentTime = currentTime; + + if (phase === 'active') { + // If the fill mode is 'none', then progress will only be non-null if we + // are in the active phase. + animation.effect.updateTiming({ fill: 'none' }); + assert_not_equals(animation.effect.getComputedTiming().progress, null, + 'Animation effect is in active phase when current time' + + ` is ${currentTime}ms`); + } else { + // The easiest way to distinguish between the 'before' phase and the 'after' + // phase is to toggle the fill mode. For example, if the progress is null + // will the fill node is 'none' but non-null when the fill mode is + // 'backwards' then we are in the before phase. + animation.effect.updateTiming({ fill: 'none' }); + assert_equals(animation.effect.getComputedTiming().progress, null, + `Animation effect is in ${phase} phase when current time` + + ` is ${currentTime}ms` + + ' (progress is null with \'none\' fill mode)'); + + animation.effect.updateTiming({ + fill: phase === 'before' ? 'backwards' : 'forwards', + }); + assert_not_equals(animation.effect.getComputedTiming().progress, null, + `Animation effect is in ${phase} phase when current time` + + ` is ${currentTime}ms` + + ' (progress is non-null with appropriate fill mode)'); + } +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html index b62726c7..a33dbf5 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html +++ b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html
@@ -16,37 +16,6 @@ // // -------------------------------------------------------------------- -function assert_phase_at_time(animation, phase, currentTime) { - animation.currentTime = currentTime; - - if (phase === 'active') { - // If the fill mode is 'none', then progress will only be non-null if we - // are in the active phase. - animation.effect.updateTiming({ fill: 'none' }); - assert_not_equals(animation.effect.getComputedTiming().progress, null, - 'Animation effect is in active phase when current time' - + ` is ${currentTime}ms`); - } else { - // The easiest way to distinguish between the 'before' phase and the 'after' - // phase is to toggle the fill mode. For example, if the progress is null - // will the fill node is 'none' but non-null when the fill mode is - // 'backwards' then we are in the before phase. - animation.effect.updateTiming({ fill: 'none' }); - assert_equals(animation.effect.getComputedTiming().progress, null, - `Animation effect is in ${phase} phase when current time` - + ` is ${currentTime}ms` - + ' (progress is null with \'none\' fill mode)'); - - animation.effect.updateTiming({ - fill: phase === 'before' ? 'backwards' : 'forwards', - }); - assert_not_equals(animation.effect.getComputedTiming().progress, null, - `Animation effect is in ${phase} phase when current time` - + ` is ${currentTime}ms` - + ' (progress is non-null with appropriate fill mode)'); - } -} - test(t => { const animation = createDiv(t).animate(null, 1);
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/005.html b/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/005.html deleted file mode 100644 index d5e21ea..0000000 --- a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/005.html +++ /dev/null
@@ -1,38 +0,0 @@ -<!-- -if (location.hash == '#1') { - var w2 = new SharedWorker('#2'); - w2.port.onmessage = function(e) { - postMessage('1'+e.data); - } -} else if (location.hash == '#2') { - onconnect = function(e) { - var port = e.ports[0]; - var w3 = new Worker('#3'); - w3.onmessage = function(e) { - port.postMessage('2'+e.data); - } - } -} else { - postMessage('3'); -} - -/* ---> -<!doctype html> -<title>dedicated worker in shared worker in dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var w1 = new Worker('#1'); - w1.onmessage = this.step_func(function(e) { - assert_equals(e.data, '123'); - this.done(); - }); - w1.onerror = this.unreached_func("error"); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/006-1.js b/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/006-1.js deleted file mode 100644 index 6c1ed93..0000000 --- a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/006-1.js +++ /dev/null
@@ -1,3 +0,0 @@ - onconnect = function(e) { - e.ports[0].postMessage('3'); - } \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/006.html b/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/006.html deleted file mode 100644 index 7fbfd8e9..0000000 --- a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/006.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!-- -if (location.hash == '#1') { - onconnect = function(e) { - var port = e.ports[0]; - onerror = e => { - port.postMessage(String(e)) - } - var w2 = new Worker('#2'); - w2.onmessage = function(e) { - port.postMessage('1'+e.data); - } - } -} else if (location.hash == '#2') { - var w3 = new SharedWorker('006-1.js'); - w3.port.onmessage = function(e) { - postMessage('2'+e.data); - } -} - -/* ---> -<!doctype html> -<title>shared worker in dedicated worker in shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var w1 = new SharedWorker('#1'); - w1.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, '123'); - this.done(); - }); - w1.onerror = this.unreached_func("error"); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/007.html b/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/007.html deleted file mode 100644 index 5045759..0000000 --- a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/007.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!-- -if (location.hash == '#1') { - onconnect = function(e) { - var port = e.ports[0]; - var w2 = new Worker('#2'); - w2.onmessage = function(e) { - port.postMessage('1'+e.data); - } - } -} else if (location.hash == '#2') { - var w3 = new SharedWorker('#3'); - w3.port.onmessage = function(e) { - postMessage('2'+e.data); - } -} else { - onconnect = function(e) { - e.ports[0].postMessage('3'); - } -} - -/* ---> -<!doctype html> -<title>shared worker in dedicated worker in shared worker</title> -<meta name="timeout" content="long"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var w1 = new SharedWorker('#1'); - w1.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, '123'); - this.done(); - }); - w1.onerror = this.unreached_func("error"); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/exposure.any.js b/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/exposure.any.js new file mode 100644 index 0000000..7e226a73 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/exposure.any.js
@@ -0,0 +1,11 @@ +// META: global=window,worker + +test(() => { + const assert = "ServiceWorkerGlobalScope" in globalThis ? assert_equals : assert_not_equals; + assert(globalThis.Worker, undefined); +}, "Worker exposure"); + +test(() => { + const assert = globalThis.GLOBAL.isWindow() ? assert_not_equals : assert_equals; + assert(globalThis.SharedWorker, undefined); +}, "SharedWorker exposure");
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/exposure.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/exposure.any.sharedworker-expected.txt new file mode 100644 index 0000000..dab9c6a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/semantics/multiple-workers/exposure.any.sharedworker-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL Worker exposure assert_not_equals: got disallowed value undefined +PASS SharedWorker exposure +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/fast/dom/HTMLLinkElement/disabled-attribute-expected.txt b/third_party/blink/web_tests/fast/dom/HTMLLinkElement/disabled-attribute-expected.txt index 6047a00..6d5f0f8 100644 --- a/third_party/blink/web_tests/fast/dom/HTMLLinkElement/disabled-attribute-expected.txt +++ b/third_party/blink/web_tests/fast/dom/HTMLLinkElement/disabled-attribute-expected.txt
@@ -4,14 +4,12 @@ PASS test.disabled is false PASS test.disabled is true -PASS test.sheet.disabled is true -PASS test.sheet.disabled is false -FAIL test.disabled should be false. Was true. +PASS test.sheet is null PASS test_nostyle.sheet is null PASS test_nostyle.disabled is false -FAIL test_nostyle.disabled should be false. Was true. +PASS test_nostyle.disabled is true PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/fast/dom/HTMLLinkElement/disabled-attribute.html b/third_party/blink/web_tests/fast/dom/HTMLLinkElement/disabled-attribute.html index 53832cb..bd778a8 100644 --- a/third_party/blink/web_tests/fast/dom/HTMLLinkElement/disabled-attribute.html +++ b/third_party/blink/web_tests/fast/dom/HTMLLinkElement/disabled-attribute.html
@@ -18,13 +18,8 @@ // set value to true test.disabled = true; shouldBe('test.disabled', 'true'); -// Updated value should be reflected in style.sheet.disabled, 'true' in this case -shouldBe('test.sheet.disabled', 'true'); -// now set style.sheet.disabled to false -test.sheet.disabled = false; -shouldBe('test.sheet.disabled', 'false'); -// Updated value should be refectled in test.disabled -shouldBe('test.disabled', 'false'); +// Disabled <link> should have a null sheet +shouldBe('test.sheet', 'null'); debug('<br>'); // verify link.sheet is null since it does not contain an href attribute shouldBe('test_nostyle.sheet', 'null'); @@ -32,8 +27,7 @@ shouldBe('test_nostyle.disabled', 'false'); // setting it to true test_nostyle.disabled = true; -// should do nothing on setting. -shouldBe('test_nostyle.disabled', 'false'); +shouldBe('test_nostyle.disabled', 'true'); </script>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js index ae1916ab..b844404 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js
@@ -329,11 +329,14 @@ return session; } - sendCommand(method, params) { + async sendCommand(method, params) { var requestId = ++this._requestId; if (this._testRunner._dumpInspectorProtocolMessages) this._testRunner.log(`frontend => backend: ${JSON.stringify({method, params, sessionId: this._sessionId})}`); - return DevToolsAPI._sendCommand(this._sessionId, method, params); + const result = await DevToolsAPI._sendCommand(this._sessionId, method, params); + if (this._testRunner._dumpInspectorProtocolMessages) + this._testRunner.log(`backend => frontend: ${JSON.stringify(result)}`); + return result; } async evaluate(code, ...args) {
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index aa4b3c9..dea3045 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -3769,6 +3769,7 @@ method constructor method createImageBitmap method fetch + method getOriginPrivateDirectory method importScripts method queueMicrotask method setInterval
diff --git a/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt index 5aa9d67..91ae335 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -42,6 +42,8 @@ method startNotifications method stopNotifications method writeValue + method writeValueWithResponse + method writeValueWithoutResponse setter oncharacteristicvaluechanged interface BluetoothRemoteGATTDescriptor attribute @@toStringTag
diff --git a/third_party/blink/web_tests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt index 6e307a7..6bc3880 100644 --- a/third_party/blink/web_tests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -42,6 +42,8 @@ method startNotifications method stopNotifications method writeValue + method writeValueWithResponse + method writeValueWithoutResponse setter oncharacteristicvaluechanged interface BluetoothRemoteGATTDescriptor attribute @@toStringTag
diff --git a/third_party/blink/web_tests/virtual/link-disabled-old-behavior/README.md b/third_party/blink/web_tests/virtual/link-disabled-old-behavior/README.md new file mode 100644 index 0000000..01ee71c --- /dev/null +++ b/third_party/blink/web_tests/virtual/link-disabled-old-behavior/README.md
@@ -0,0 +1,6 @@ +This is a virtual test suite for the *old* <link disabled> behavior, +to ensure it respects the Feature flag, in case this behavior needs to be +disabled via Finch. + +Flag: --disable-features=LinkDisabledNewSpecBehavior +Bug: crbug.com/1087043
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-001-expected.txt b/third_party/blink/web_tests/virtual/link-disabled-old-behavior/external/wpt/css/cssom/HTMLLinkElement-disabled-001-expected.txt similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-001-expected.txt rename to third_party/blink/web_tests/virtual/link-disabled-old-behavior/external/wpt/css/cssom/HTMLLinkElement-disabled-001-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-002-expected.txt b/third_party/blink/web_tests/virtual/link-disabled-old-behavior/external/wpt/css/cssom/HTMLLinkElement-disabled-002-expected.txt similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-002-expected.txt rename to third_party/blink/web_tests/virtual/link-disabled-old-behavior/external/wpt/css/cssom/HTMLLinkElement-disabled-002-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-007-expected.txt b/third_party/blink/web_tests/virtual/link-disabled-old-behavior/external/wpt/css/cssom/HTMLLinkElement-disabled-007-expected.txt similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-disabled-007-expected.txt rename to third_party/blink/web_tests/virtual/link-disabled-old-behavior/external/wpt/css/cssom/HTMLLinkElement-disabled-007-expected.txt
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 042c78e8d..3563b633 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -3823,6 +3823,7 @@ [Worker] method constructor [Worker] method createImageBitmap [Worker] method fetch +[Worker] method getOriginPrivateDirectory [Worker] method importScripts [Worker] method queueMicrotask [Worker] method setInterval
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index eddd4bf3..b37fe851 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -11946,6 +11946,7 @@ method getComputedAccessibleNode method getComputedStyle method getDigitalGoodsService + method getOriginPrivateDirectory method getScreens method getSelection method matchMedia
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index cb634ff..b0ed85d 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -3641,6 +3641,7 @@ [Worker] method constructor [Worker] method createImageBitmap [Worker] method fetch +[Worker] method getOriginPrivateDirectory [Worker] method importScripts [Worker] method queueMicrotask [Worker] method setInterval
diff --git a/third_party/blink/web_tests/wpt_internal/system-wake-lock/idlharness-worker.https.window.js b/third_party/blink/web_tests/wpt_internal/system-wake-lock/idlharness-worker.https.window.js index a10a87c6..546b085 100644 --- a/third_party/blink/web_tests/wpt_internal/system-wake-lock/idlharness-worker.https.window.js +++ b/third_party/blink/web_tests/wpt_internal/system-wake-lock/idlharness-worker.https.window.js
@@ -8,4 +8,4 @@ { name: 'system-wake-lock' }, 'granted', false); await fetch_tests_from_worker(new Worker('resources/idlharness-worker.js')); -}, 'Run idlharness tests in a worker.'); \ No newline at end of file +}, 'Run idlharness tests in a worker.');
diff --git a/third_party/blink/web_tests/wpt_internal/system-wake-lock/idlharness.https.window.js b/third_party/blink/web_tests/wpt_internal/system-wake-lock/idlharness.https.window.js index 5420261..305c351 100644 --- a/third_party/blink/web_tests/wpt_internal/system-wake-lock/idlharness.https.window.js +++ b/third_party/blink/web_tests/wpt_internal/system-wake-lock/idlharness.https.window.js
@@ -2,6 +2,7 @@ // META: script=/resources/idlharness.js // META: script=/resources/testdriver.js // META: script=/resources/testdriver-vendor.js +// META: timeout=long 'use strict'; @@ -21,4 +22,4 @@ self.sentinel = await navigator.wakeLock.request('system'); self.sentinel.release(); } -); \ No newline at end of file +);
diff --git a/third_party/closure_compiler/externs/developer_private.js b/third_party/closure_compiler/externs/developer_private.js index e74282c..b7a1c20 100644 --- a/third_party/closure_compiler/externs/developer_private.js +++ b/third_party/closure_compiler/externs/developer_private.js
@@ -220,7 +220,6 @@ */ chrome.developerPrivate.ControllerType = { POLICY: 'POLICY', - SUPERVISED_USER_CUSTODIAN: 'SUPERVISED_USER_CUSTODIAN', }; /**
diff --git a/third_party/closure_compiler/interfaces/bluetooth_interface.js b/third_party/closure_compiler/interfaces/bluetooth_interface.js index 992665fa..81c348b 100644 --- a/third_party/closure_compiler/interfaces/bluetooth_interface.js +++ b/third_party/closure_compiler/interfaces/bluetooth_interface.js
@@ -1,48 +1,46 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file was generated by: -// tools/json_schema_compiler/compiler.py. +// ./tools/json_schema_compiler/compiler.py. /** @fileoverview Interface for bluetooth that can be overriden. */ -assertNotReached('Interface file for Closure Compiler should not be executed.'); - /** @interface */ function Bluetooth() {} Bluetooth.prototype = { /** * Get information about the Bluetooth adapter. - * @param {function(!chrome.bluetooth.AdapterState):void} callback Called with - * an AdapterState object describing the adapter state. + * @param {function(!chrome.bluetooth.AdapterState): void} callback Called + * with an AdapterState object describing the adapter state. * @see https://developer.chrome.com/extensions/bluetooth#method-getAdapterState */ - getAdapterState: assertNotReached, + getAdapterState: function(callback) {}, /** * Get information about a Bluetooth device known to the system. * @param {string} deviceAddress Address of device to get. - * @param {function(!chrome.bluetooth.Device):void} callback Called with the + * @param {function(!chrome.bluetooth.Device): void} callback Called with the * Device object describing the device. * @see https://developer.chrome.com/extensions/bluetooth#method-getDevice */ - getDevice: assertNotReached, + getDevice: function(deviceAddress, callback) {}, /** * Get a list of Bluetooth devices known to the system, including paired and * recently discovered devices. - * @param {!chrome.bluetooth.BluetoothFilter=} filter Some criteria to filter - * the list of returned bluetooth devices. If the filter is not set or set - * to <code>{}</code>, returned device list will contain all bluetooth - * devices. Right now this is only supported in ChromeOS, for other - * platforms, a full list is returned. - * @param {function(!Array<!chrome.bluetooth.Device>):void=} callback Called + * @param {?chrome.bluetooth.BluetoothFilter|undefined} filter Some criteria + * to filter the list of returned bluetooth devices. If the filter is not + * set or set to <code>{}</code>, returned device list will contain all + * bluetooth devices. Right now this is only supported in ChromeOS, for + * other platforms, a full list is returned. + * @param {function(!Array<!chrome.bluetooth.Device>): void} callback Called * when the search is completed. * @see https://developer.chrome.com/extensions/bluetooth#method-getDevices */ - getDevices: assertNotReached, + getDevices: function(filter, callback) {}, /** * <p>Start discovery. Newly discovered devices will be returned via the @@ -52,17 +50,17 @@ * changes.</p><p>Discovery will fail to start if this application has already * called startDiscovery. Discovery can be resource intensive: stopDiscovery * should be called as soon as possible.</p> - * @param {function():void=} callback Called to indicate success or failure. + * @param {function(): void=} callback Called to indicate success or failure. * @see https://developer.chrome.com/extensions/bluetooth#method-startDiscovery */ - startDiscovery: assertNotReached, + startDiscovery: function(callback) {}, /** * Stop discovery. - * @param {function():void=} callback Called to indicate success or failure. + * @param {function(): void=} callback Called to indicate success or failure. * @see https://developer.chrome.com/extensions/bluetooth#method-stopDiscovery */ - stopDiscovery: assertNotReached, + stopDiscovery: function(callback) {}, }; /**
diff --git a/third_party/closure_compiler/interfaces/bluetooth_private_interface.js b/third_party/closure_compiler/interfaces/bluetooth_private_interface.js index 744a57be..2399ca0 100644 --- a/third_party/closure_compiler/interfaces/bluetooth_private_interface.js +++ b/third_party/closure_compiler/interfaces/bluetooth_private_interface.js
@@ -1,4 +1,4 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,81 +7,95 @@ /** @fileoverview Interface for bluetoothPrivate that can be overriden. */ -assertNotReached('Interface file for Closure Compiler should not be executed.'); - /** @interface */ function BluetoothPrivate() {} BluetoothPrivate.prototype = { /** * Changes the state of the Bluetooth adapter. - * @param {!chrome.bluetoothPrivate.NewAdapterState} adapterState - * @param {function():void=} callback - * @see https://developer.chrome.com/extensions/bluetoothPrivate#method-setAdapterState + * @param {!chrome.bluetoothPrivate.NewAdapterState} adapterState The new + * state of the adapter. + * @param {function(): void=} callback Called when all the state changes have + * been completed. */ - setAdapterState: assertNotReached, + setAdapterState: function(adapterState, callback) {}, /** * @param {!chrome.bluetoothPrivate.SetPairingResponseOptions} options - * @param {function():void=} callback - * @see https://developer.chrome.com/extensions/bluetoothPrivate#method-setPairingResponse + * @param {function(): void=} callback */ - setPairingResponse: assertNotReached, + setPairingResponse: function(options, callback) {}, /** * Tears down all connections to the given device. * @param {string} deviceAddress - * @param {function():void=} callback - * @see https://developer.chrome.com/extensions/bluetoothPrivate#method-disconnectAll + * @param {function(): void=} callback */ - disconnectAll: assertNotReached, + disconnectAll: function(deviceAddress, callback) {}, /** * Forgets the given device. * @param {string} deviceAddress - * @param {function():void=} callback - * @see https://developer.chrome.com/extensions/bluetoothPrivate#method-forgetDevice + * @param {function(): void=} callback */ - forgetDevice: assertNotReached, + forgetDevice: function(deviceAddress, callback) {}, /** * Set or clear discovery filter. * @param {!chrome.bluetoothPrivate.DiscoveryFilter} discoveryFilter - * @param {function():void=} callback - * @see https://developer.chrome.com/extensions/bluetoothPrivate#method-setDiscoveryFilter + * @param {function(): void=} callback */ - setDiscoveryFilter: assertNotReached, + setDiscoveryFilter: function(discoveryFilter, callback) {}, /** * Connects to the given device. This will only throw an error if the device * address is invalid or the device is already connected. Otherwise this will * succeed and invoke |callback| with ConnectResultType. * @param {string} deviceAddress - * @param {function(!chrome.bluetoothPrivate.ConnectResultType):void=} + * @param {function(!chrome.bluetoothPrivate.ConnectResultType): void=} * callback - * @see https://developer.chrome.com/extensions/bluetoothPrivate#method-connect */ - connect: assertNotReached, + connect: function(deviceAddress, callback) {}, /** * Pairs the given device. * @param {string} deviceAddress - * @param {function():void=} callback - * @see https://developer.chrome.com/extensions/bluetoothPrivate#method-pair + * @param {function(): void=} callback */ - pair: assertNotReached, + pair: function(deviceAddress, callback) {}, + + /** + * Record that a pairing attempt finished. Ignores cancellations. + * @param {!chrome.bluetoothPrivate.TransportType} transport + * @param {number} pairingDurationMs + * @param {!chrome.bluetoothPrivate.ConnectResultType=} result + */ + recordPairing: function(transport, pairingDurationMs, result) {}, + + /** + * Record that a user-initiated reconnection attempt to an already paired + * device finished. Ignores cancellations. + * @param {!chrome.bluetoothPrivate.ConnectResultType=} result + */ + recordReconnection: function(result) {}, + + /** + * Record that a user selected a device to connect to. + * @param {number} selectionDurationMs + * @param {boolean} wasPaired + * @param {!chrome.bluetoothPrivate.TransportType} transport + */ + recordDeviceSelection: function(selectionDurationMs, wasPaired, transport) {}, }; /** * Fired when a pairing event occurs. * @type {!ChromeEvent} - * @see https://developer.chrome.com/extensions/bluetoothPrivate#event-onPairing */ BluetoothPrivate.prototype.onPairing; /** * Fired when a Bluetooth device changed its address. * @type {!ChromeEvent} - * @see https://developer.chrome.com/extensions/bluetoothPrivate#event-onDeviceAddressChanged */ BluetoothPrivate.prototype.onDeviceAddressChanged;
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 264bbe39..0cf20159 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -6,9 +6,9 @@ License File: source/libvpx/LICENSE Security Critical: yes -Date: Friday May 15 2020 +Date: Tuesday June 02 2020 Branch: master -Commit: f80e888723942e821d7f89735ab71d96662f6aa2 +Commit: c1765573149e2c0fe2acabc224c0f9085b9e7f2b Description: Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index bd99554..97af44b 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,8 +2,8 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 8 #define VERSION_PATCH 2 -#define VERSION_EXTRA "184-gf80e88872" +#define VERSION_EXTRA "194-gc17655731" #define VERSION_PACKED \ ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.8.2-184-gf80e88872" -#define VERSION_STRING " v1.8.2-184-gf80e88872" +#define VERSION_STRING_NOSP "v1.8.2-194-gc17655731" +#define VERSION_STRING " v1.8.2-194-gc17655731"
diff --git a/third_party/zlib/google/BUILD.gn b/third_party/zlib/google/BUILD.gn index b7d3d6b..a49b8c8 100644 --- a/third_party/zlib/google/BUILD.gn +++ b/third_party/zlib/google/BUILD.gn
@@ -35,15 +35,6 @@ } } -# It seems that Fuchsia bot will fail to build if we don't explicitly -# add this config as part of utils_portable. -config("zlib_portable_utils_config") { - include_dirs = [ - "//third_party/zlib", - "//third_party/zlib/google", - ] -} - # This allows other users of Chromium's zlib library, but don't use Chromium's # //base, to reuse some boilerplate code. static_library("compression_utils_portable") { @@ -51,6 +42,5 @@ "compression_utils_portable.cc", "compression_utils_portable.h", ] - deps = [ "//third_party/zlib" ] - public_configs = [ ":zlib_portable_utils_config" ] + public_deps = [ "//third_party/zlib" ] }
diff --git a/tools/android/dependency_analysis/README.md b/tools/android/dependency_analysis/README.md index a4b4181..ce706540 100644 --- a/tools/android/dependency_analysis/README.md +++ b/tools/android/dependency_analysis/README.md
@@ -4,14 +4,89 @@ analyzing the dependencies contained within the Chrome Android project. ## Usage -Currently there is only one tool. +Start by generating a JSON dependency file with a snapshot of the dependencies +for your JAR using the **JSON dependency generator** command-line tool. -### JDeps Parser -Runs jdeps on a JAR file and constructs a graph data structure in-memory of the -dependencies. Currently only creates the graph for class-level dependencies. +This snapshot file can then be used as input for various other +analysis tools listed below. -usage: - python3 process\_jdeps.py [-h] filepath -positional arguments: - filepath: Path of the JAR to run jdeps on +## Command-line tools +The usage information for any of the following tools is also accessible via +`toolname -h` or `toolname --help`. +#### JSON Dependency Generator +Runs [jdeps](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jdeps.html) +on a given JAR and writes the resulting dependency graph into a JSON file. +``` +usage: generate_json_dependency_graph.py [-h] -t TARGET -o OUTPUT [-j JDEPS_PATH] +optional arguments: + -j JDEPS_PATH, --jdeps-path JDEPS_PATH + Path to the jdeps executable. + +required arguments: + -t TARGET, --target TARGET + Path to the JAR file to run jdeps on. + -o OUTPUT, --output OUTPUT + Path to the file to write JSON output to. Will be + created if it does not yet exist and overwrite + existing content if it does. +``` +#### Class Dependency Audit +Given a JSON dependency graph, output the class-level dependencies for a given +class. +``` +usage: print_class_dependencies.py [-h] -f FILE -c CLASS_NAME + +required arguments: + -f FILE, --file FILE Path to the JSON file containing the dependency graph. + See the README on how to generate this file. + -c CLASS_NAME, --class CLASS_NAME + Case-insensitive name of the class to print + dependencies for. Matches names of the form ...input, + for example `apphooks` matches + `org.chromium.browser.AppHooks`. +``` +#### Package Dependency Audit +Given a JSON dependency graph, output the package-level dependencies for a +given package and the class dependencies comprising those dependencies. +``` +usage: print_package_dependencies.py [-h] -f FILE -p PACKAGE + +required arguments: + -f FILE, --file FILE Path to the JSON file containing the dependency graph. + See the README on how to generate this file. + -p PACKAGE, --package PACKAGE + Case-insensitive name of the package to print + dependencies for. Matches names of the form ...input, + for example `browser` matches `org.chromium.browser`. +``` + +## Example Usage +This Linux example assumes Chromium is contained in a directory `~/cr` +and that Chromium has been built as per the instructions +[here](https://chromium.googlesource.com/chromium/src/+/master/docs/linux/build_instructions.md), +although the only things these assumptions affect are the file paths. +``` +cd ~/cr/src/tools/android/dependency_analysis + +./generate_json_dependency_graph.py --target ~/cr/src/out/Default/obj/chrome/android/chrome_java__process_prebuilt.desugar.jar --output ./json_graph.txt +>>> Running jdeps and parsing output... +>>> Parsed class-level dependency graph, got 3239 nodes and 19272 edges. +>>> Created package-level dependency graph, got 500 nodes and 4954 edges. +>>> Dumping JSON representation to ./json_graph.txt. + +./print_class_dependencies.py --file ./json_graph.txt --class apphooks +>>> Printing class dependencies for org.chromium.chrome.browser.AppHooks: +>>> 35 inbound dependency(ies) for org.chromium.chrome.browser.AppHooks: +>>> org.chromium.chrome.browser.AppHooksImpl +>>> org.chromium.chrome.browser.ChromeActivity +>>> ... + +./print_package_dependencies.py --file ./json_graph.txt --package chrome.browser +>>> Printing package dependencies for org.chromium.chrome.browser: +>>> 121 inbound dependency(ies) for org.chromium.chrome.browser: +>>> org.chromium.chrome.browser.about_settings -> org.chromium.chrome.browser +>>> 1 class edge(s) comprising the dependency: +>>> AboutChromeSettings -> ChromeVersionInfo +>>> ... +``` \ No newline at end of file
diff --git a/tools/android/dependency_analysis/process_jdeps.py b/tools/android/dependency_analysis/generate_json_dependency_graph.py old mode 100644 new mode 100755 similarity index 65% rename from tools/android/dependency_analysis/process_jdeps.py rename to tools/android/dependency_analysis/generate_json_dependency_graph.py index 7034cbf..3c59a87b --- a/tools/android/dependency_analysis/process_jdeps.py +++ b/tools/android/dependency_analysis/generate_json_dependency_graph.py
@@ -1,7 +1,8 @@ +#!/usr/bin/env python3 # Copyright 2020 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Python wrapper for running jdeps and parsing its output""" +"""Command-line tool to run jdeps and process its output into a JSON file.""" import argparse import pathlib @@ -75,9 +76,9 @@ self._graph.add_nested_class_to_key(key_from, nested_to) -def run_jdeps(filepath: str): +def run_jdeps(jdeps_path: str, filepath: str): """Runs jdeps on the given filepath and returns the output.""" - jdeps_res = subprocess.run([JDEPS_PATH, '-R', '-verbose:class', filepath], + jdeps_res = subprocess.run([jdeps_path, '-R', '-verbose:class', filepath], capture_output=True, text=True, check=True) @@ -85,42 +86,47 @@ def main(): - """Parses args, runs jdeps, and creates a graph from the output. - - Currently only works for class-level dependencies. - The goal is to have more functions available for interfacing with the - constructed graph, but currently we just print its number of nodes/edges. - """ + """Runs jdeps and creates a JSON file from the output.""" arg_parser = argparse.ArgumentParser( - description='Run jdeps and process output') - arg_parser.add_argument('filepath', help='Path of the JAR to run jdeps on') + description='Runs jdeps (dependency analysis tool) on a given JAR and ' + 'writes the resulting dependency graph into a JSON file.') + required_arg_group = arg_parser.add_argument_group('required arguments') + required_arg_group.add_argument( + '-t', + '--target', + required=True, + help='Path to the JAR file to run jdeps on.') + required_arg_group.add_argument( + '-o', + '--output', + required=True, + help='Path to the file to write JSON output to. Will be created ' + 'if it does not yet exist and overwrite existing ' + 'content if it does.') + arg_parser.add_argument('-j', + '--jdeps-path', + default=JDEPS_PATH, + help='Path to the jdeps executable.') arguments = arg_parser.parse_args() - raw_jdeps_output = run_jdeps(arguments.filepath) + print('Running jdeps and parsing output...') + raw_jdeps_output = run_jdeps(arguments.jdeps_path, arguments.target) jdeps_parser = JavaClassJdepsParser() jdeps_parser.parse_raw_jdeps_output(raw_jdeps_output) class_graph = jdeps_parser.graph - - print(f"Parsed class-level dependency graph, " - f"got {class_graph.num_nodes} nodes " - f"and {class_graph.num_edges} edges.") + print(f'Parsed class-level dependency graph, ' + f'got {class_graph.num_nodes} nodes ' + f'and {class_graph.num_edges} edges.') package_graph = package_dependency.JavaPackageDependencyGraph(class_graph) + print(f'Created package-level dependency graph, ' + f'got {package_graph.num_nodes} nodes ' + f'and {package_graph.num_edges} edges.') - print(f"Created package-level dependency graph, " - f"got {package_graph.num_nodes} nodes " - f"and {package_graph.num_edges} edges.") - - print('Dumping JSON representation to testing file ' - 'dependency_analysis/testfile.txt.') - - testing_filepath = (f'{pathlib.Path(__file__).parent.absolute()}' - '/testfile.txt') + print(f'Dumping JSON representation to {arguments.output}.') serialization.dump_class_and_package_graphs_to_file( - class_graph, package_graph, testing_filepath) - print('Recreating graph from the dumped JSON representation.') - serialization.load_class_and_package_graphs_from_file(testing_filepath) + class_graph, package_graph, arguments.output) if __name__ == '__main__':
diff --git a/tools/android/dependency_analysis/process_jdeps_unittest.py b/tools/android/dependency_analysis/generate_json_dependency_graph_unittest.py similarity index 86% rename from tools/android/dependency_analysis/process_jdeps_unittest.py rename to tools/android/dependency_analysis/generate_json_dependency_graph_unittest.py index a8ae84f..5eec6a8 100755 --- a/tools/android/dependency_analysis/process_jdeps_unittest.py +++ b/tools/android/dependency_analysis/generate_json_dependency_graph_unittest.py
@@ -2,10 +2,10 @@ # Copyright 2020 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Unit tests for dependency_analysis.process_jdeps.""" +"""Unit tests for dependency_analysis.generate_json_dependency_graph.""" import unittest -import process_jdeps +import generate_json_dependency_graph class TestHelperFunctions(unittest.TestCase): @@ -13,25 +13,26 @@ def test_class_is_interesting(self): """Tests that the helper identifies a valid Chromium class name.""" self.assertTrue( - process_jdeps.class_is_interesting( + generate_json_dependency_graph.class_is_interesting( 'org.chromium.chrome.browser.Foo')) def test_class_is_interesting_longer(self): """Tests that the helper identifies a valid Chromium class name.""" self.assertTrue( - process_jdeps.class_is_interesting( + generate_json_dependency_graph.class_is_interesting( 'org.chromium.chrome.browser.foo.Bar')) def test_class_is_interesting_negative(self): """Tests that the helper ignores a non-Chromium class name.""" self.assertFalse( - process_jdeps.class_is_interesting( + generate_json_dependency_graph.class_is_interesting( 'org.notchromium.chrome.browser.Foo')) def test_class_is_interesting_not_interesting(self): """Tests that the helper ignores a builtin class name.""" self.assertFalse( - process_jdeps.class_is_interesting('java.lang.Object')) + generate_json_dependency_graph.class_is_interesting( + 'java.lang.Object')) class TestJavaClassJdepsParser(unittest.TestCase): @@ -40,7 +41,7 @@ """ def setUp(self): """Sets up a new JavaClassJdepsParser.""" - self.parser = process_jdeps.JavaClassJdepsParser() + self.parser = generate_json_dependency_graph.JavaClassJdepsParser() def test_parse_line(self): """Tests that new nodes + edges are added after a successful parse."""
diff --git a/tools/android/dependency_analysis/print_class_dependencies.py b/tools/android/dependency_analysis/print_class_dependencies.py new file mode 100755 index 0000000..98dcbbe3b --- /dev/null +++ b/tools/android/dependency_analysis/print_class_dependencies.py
@@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Command-line tool for printing class-level dependencies.""" + +import argparse + +import graph +import print_dependencies_helper +import serialization + + +def print_class_dependencies_for_key(class_graph, key): + """Prints dependencies for a valid key into the class graph.""" + node = class_graph.get_node_by_key(key) + + print(f'{len(node.inbound)} inbound dependency(ies) for {node.name}:') + for inbound_dep in graph.sorted_nodes_by_name(node.inbound): + print(f'\t{inbound_dep.name}') + + print(f'{len(node.outbound)} outbound dependency(ies) for {node.name}:') + for outbound_dep in graph.sorted_nodes_by_name(node.outbound): + print(f'\t{outbound_dep.name}') + + +def main(): + """Prints class-level dependencies for an input class.""" + arg_parser = argparse.ArgumentParser( + description='Given a JSON dependency graph, output ' + 'the class-level dependencies for a given class.') + required_arg_group = arg_parser.add_argument_group('required arguments') + required_arg_group.add_argument( + '-f', + '--file', + required=True, + help='Path to the JSON file containing the dependency graph. ' + 'See the README on how to generate this file.') + required_arg_group.add_argument( + '-c', + '--class', + required=True, + dest='class_name', + help='Case-insensitive name of the class to print dependencies for. ' + 'Matches names of the form ...input, for example ' + '`apphooks` matches `org.chromium.browser.AppHooks`.') + arguments = arg_parser.parse_args() + + class_graph = serialization.load_class_graph_from_file(arguments.file) + class_graph_keys = [node.name for node in class_graph.nodes] + valid_keys = print_dependencies_helper.get_valid_keys_matching_input( + class_graph_keys, arguments.class_name) + + if len(valid_keys) == 0: + print(f'No class found by the name {arguments.class_name}.') + elif len(valid_keys) > 1: + print( + f'Multiple valid keys found for the name {arguments.class_name}, ' + 'please disambiguate between one of the following options:') + for valid_key in valid_keys: + print(f'\t{valid_key}') + else: + print(f'Printing class dependencies for {valid_keys[0]}:') + print_class_dependencies_for_key(class_graph, valid_keys[0]) + + +if __name__ == '__main__': + main()
diff --git a/tools/android/dependency_analysis/print_dependencies_helper.py b/tools/android/dependency_analysis/print_dependencies_helper.py new file mode 100644 index 0000000..7dc2f78 --- /dev/null +++ b/tools/android/dependency_analysis/print_dependencies_helper.py
@@ -0,0 +1,17 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Various helpers for printing dependencies.""" + +from typing import List + + +def get_valid_keys_matching_input(all_keys: List, input_key: str) -> List[str]: + """Return a list of valid keys into the graph's nodes based on an input. + + For our use case (matching user input to graph nodes), + a valid key is one that ends with the input, case insensitive. + For example, 'apphooks' matches 'org.chromium.browser.AppHooks'. + """ + input_key_lower = input_key.lower() + return [key for key in all_keys if key.lower().endswith(input_key_lower)]
diff --git a/tools/android/dependency_analysis/print_dependencies_helper_unittest.py b/tools/android/dependency_analysis/print_dependencies_helper_unittest.py new file mode 100755 index 0000000..6feb4d9f --- /dev/null +++ b/tools/android/dependency_analysis/print_dependencies_helper_unittest.py
@@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Unit tests for dependency_analysis.print_dependencies_helper.""" + +import unittest +import print_dependencies_helper + + +class TestHelperFunctions(unittest.TestCase): + """Unit tests for the helper functions in the module.""" + def test_get_valid_keys_matching_input(self): + """Tests getting all valid keys for the given input.""" + test_keys = ['o.c.test.Test', 'o.c.testing.Test', 'o.c.test.Wrong'] + valid_keys = print_dependencies_helper.get_valid_keys_matching_input( + test_keys, 'test') + self.assertEqual(valid_keys, + sorted(['o.c.test.Test', 'o.c.testing.Test'])) + + def test_get_valid_keys_matching_input_no_match(self): + """Tests getting all valid keys when there is no matching key.""" + test_keys = ['o.c.test.Test', 'o.c.testing.Test', 'o.c.test.Wrong'] + valid_keys = print_dependencies_helper.get_valid_keys_matching_input( + test_keys, 'nomatch') + self.assertEqual(valid_keys, [])
diff --git a/tools/android/dependency_analysis/print_package_dependencies.py b/tools/android/dependency_analysis/print_package_dependencies.py new file mode 100755 index 0000000..bdf9288 --- /dev/null +++ b/tools/android/dependency_analysis/print_package_dependencies.py
@@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Command-line tool for printing package-level dependencies.""" + +import argparse + +import graph +import print_dependencies_helper +import serialization + + +def print_package_dependencies_for_edge(begin, end): + """Prints dependencies for an edge in the package graph. + + Since these are package edges, we also print the class dependency edges + comprising the printed package edge. + """ + if begin == end: + return + print(f'\t{begin.name} -> {end.name}') + class_deps = begin.get_class_dependencies_in_outbound_edge(end) + print(f'\t{len(class_deps)} class edge(s) comprising the dependency:') + for begin_class, end_class in graph.sorted_edges_by_name(class_deps): + print(f'\t\t{begin_class.class_name} -> {end_class.class_name}') + + +def print_package_dependencies_for_key(package_graph, key): + """Prints dependencies for a valid key into the package graph. + + Since we store self-edges for the package graph + but they aren't relevant in this case, we skip them. + """ + node = package_graph.get_node_by_key(key) + + inbound_without_self = [other for other in node.inbound if other != node] + print(f'{len(inbound_without_self)} inbound dependency(ies) ' + f'for {node.name}:') + for inbound_dep in graph.sorted_nodes_by_name(inbound_without_self): + print_package_dependencies_for_edge(inbound_dep, node) + + outbound_without_self = [other for other in node.outbound if other != node] + print(f'{len(outbound_without_self)} outbound dependency(ies) ' + f'for {node.name}:') + for outbound_dep in graph.sorted_nodes_by_name(outbound_without_self): + print_package_dependencies_for_edge(node, outbound_dep) + + +def main(): + """Prints package-level dependencies for an input package.""" + arg_parser = argparse.ArgumentParser( + description='Given a JSON dependency graph, output the package-level ' + 'dependencies for a given package and the ' + 'class dependencies comprising those dependencies') + required_arg_group = arg_parser.add_argument_group('required arguments') + required_arg_group.add_argument( + '-f', + '--file', + required=True, + help='Path to the JSON file containing the dependency graph. ' + 'See the README on how to generate this file.') + required_arg_group.add_argument( + '-p', + '--package', + required=True, + help='Case-insensitive name of the package to print dependencies for. ' + 'Matches names of the form ...input, for example ' + '`browser` matches `org.chromium.browser`.') + arguments = arg_parser.parse_args() + + _, package_graph = serialization.load_class_and_package_graphs_from_file( + arguments.file) + package_graph_keys = [node.name for node in package_graph.nodes] + valid_keys = print_dependencies_helper.get_valid_keys_matching_input( + package_graph_keys, arguments.package) + + if len(valid_keys) == 0: + print(f'No package found by the name {arguments.package}.') + elif len(valid_keys) > 1: + print(f'Multiple valid keys found for the name {arguments.package}, ' + 'please disambiguate between one of the following options:') + for valid_key in valid_keys: + print(f'\t{valid_key}') + else: + print(f'Printing package dependencies for {valid_keys[0]}:') + print_package_dependencies_for_key(package_graph, valid_keys[0]) + + +if __name__ == '__main__': + main()
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index e5efbec..9a23f43 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -65,7 +65,7 @@ _SECTION_SIZE_BLACKLIST = ['.symtab', '.shstrtab', '.strtab'] -# Tunable constant "knobs" for CreateSectionSizesAndSymbols(). +# Tunable constant "knobs" for CreateContainerAndSymbols(). class SectionSizeKnobs(object): def __init__(self): # A limit on the number of symbols an address can have, before these symbols @@ -1414,27 +1414,30 @@ _ExtendSectionRange(section_ranges, models.SECTION_OTHER, section_size) -def CreateSectionSizesAndSymbols(knobs=None, - opts=None, - metadata=None, - map_path=None, - tool_prefix=None, - output_directory=None, - elf_path=None, - apk_path=None, - mapping_path=None, - resources_pathmap_path=None, - track_string_literals=True, - apk_so_path=None, - pak_files=None, - pak_info_file=None, - linker_name=None, - size_info_prefix=None): - """Creates sections sizes and symbols for a SizeInfo. +def CreateContainerAndSymbols(knobs=None, + opts=None, + container_name=None, + metadata=None, + map_path=None, + tool_prefix=None, + output_directory=None, + elf_path=None, + apk_path=None, + mapping_path=None, + resources_pathmap_path=None, + track_string_literals=True, + apk_so_path=None, + pak_files=None, + pak_info_file=None, + linker_name=None, + size_info_prefix=None): + """Creates a Container (with sections sizes) and symbols for a SizeInfo. Args: knobs: Instance of SectionSizeKnobs. opts: Instance of ContainerArchiveOptions. + container_name: Name for the created Container. May be '' if only one + Container exists. metadata: Metadata dict from CreateMetadata(). map_path: Path to the linker .map(.gz) file to parse. tool_prefix: Prefix for c++filt & nm (required). @@ -1455,8 +1458,9 @@ size_info_prefix: Path to $out/size-info/$ApkName. Returns: - A tuple of (section_sizes, raw_symbols). - section_ranges is a dict mapping section names to their (address, size). + A tuple of (container, raw_symbols). + containers is a Container instance that stores metadata and section_sizes + (section_sizes maps section names to respective sizes). raw_symbols is a list of Symbol objects. """ knobs = knobs or SectionSizeKnobs() @@ -1608,15 +1612,22 @@ _OverwriteSymbolSizesWithRelocationCount(raw_symbols, tool_prefix, elf_path) section_sizes = {k: size for k, (address, size) in section_ranges.items()} - return section_sizes, raw_symbols + container = models.Container(name=container_name, + metadata=metadata, + section_sizes=section_sizes) + for symbol in raw_symbols: + symbol.container = container + return container, raw_symbols def CreateSizeInfo(build_config, - section_sizes_list, + container_list, raw_symbols_list, - metadata_list, normalize_names=True): """Performs operations on all symbols and creates a SizeInfo object.""" + assert len(container_list) == len(raw_symbols_list) + + all_raw_symbols = [] for raw_symbols in raw_symbols_list: file_format.SortSymbols(raw_symbols) file_format.CalculatePadding(raw_symbols) @@ -1627,16 +1638,9 @@ if normalize_names: _NormalizeNames(raw_symbols) - # TODO(huangs): Implement data fusing to compute the following for real. - assert len(section_sizes_list) == 1 - section_sizes = section_sizes_list[0] - raw_symbols = raw_symbols_list[0] - metadata = metadata_list[0] + all_raw_symbols += raw_symbols - return models.SizeInfo(build_config, - section_sizes, - raw_symbols, - metadata=metadata) + return models.SizeInfo(build_config, container_list, all_raw_symbols) def _DetectGitRevision(directory): @@ -1890,15 +1894,20 @@ value=args.output_directory, any_path_within_output_directory=args.any_path_within_output_directory) - def _Inner(sub_args, apk_prefix, apk_path): + def _Inner(idx, sub_args, apk_prefix, apk_path): """Inner helper for _DeduceMainPaths(), for one container. Params: + idx: Numeric index of the container. sub_args: Arguments specific to a container. apk_prefix: Prefix used to search for auxiliary .apk related files. apk_path: Path to .apk file that can be opened for processing, but whose filename is unimportant (e.g., can be a temp file). """ + # TODO(huangs): Assign distinct names for multiple containers. + assert idx == 0 + container_name = '' + output_directory = output_directory_finder.Tentative() opts = ContainerArchiveOptions(sub_args, output_directory=output_directory) if apk_prefix: @@ -1938,16 +1947,22 @@ size_info_prefix = os.path.join(output_directory, 'size-info', os.path.basename(apk_prefix)) - return (opts, output_directory, tool_prefix, apk_path, mapping_path, - apk_so_path, elf_path, map_path, resources_pathmap_path, - linker_name, size_info_prefix) + return (opts, output_directory, tool_prefix, container_name, apk_path, + mapping_path, apk_so_path, elf_path, map_path, + resources_pathmap_path, linker_name, size_info_prefix) - # If needed, extract .apk file to a temp file and process that instead. - if args.minimal_apks_file: - with zip_util.UnzipToTemp(args.minimal_apks_file, _APKS_MAIN_APK) as temp: - yield _Inner(args, args.minimal_apks_file, temp) - else: - yield _Inner(args, args.apk_file, args.apk_file) + # One for each container. + # TODO(huangs): Add support for multiple containers + sub_args_list = [args] + + for idx, sub_args in enumerate(sub_args_list): + # If needed, extract .apk file to a temp file and process that instead. + if sub_args.minimal_apks_file: + with zip_util.UnzipToTemp(sub_args.minimal_apks_file, + _APKS_MAIN_APK) as temp: + yield _Inner(idx, sub_args, sub_args.minimal_apks_file, temp) + else: + yield _Inner(idx, sub_args, sub_args.apk_file, sub_args.apk_file) def Run(args, on_config_error): @@ -1973,21 +1988,27 @@ knobs = SectionSizeKnobs() build_config = {} - metadata_list = [] - section_sizes_list = [] + seen_container_names = set() + container_list = [] raw_symbols_list = [] - # Generate one size info for each container. - for (opts, output_directory, tool_prefix, apk_path, mapping_path, apk_so_path, - elf_path, map_path, resources_pathmap_path, linker_name, + # Iterate over each container. + for (opts, output_directory, tool_prefix, container_name, apk_path, + mapping_path, apk_so_path, elf_path, map_path, resources_pathmap_path, + linker_name, size_info_prefix) in _DeduceMainPaths(args, on_config_error): + if container_name in seen_container_names: + raise ValueError('Duplicate container name: {}'.format(container_name)) + seen_container_names.add(container_name) + # Note that |args.apk_file| is used instead of |apk_path|, since the latter # may be an extracted temporary file. metadata = CreateMetadata(map_path, elf_path, args.apk_file, args.minimal_apks_file, tool_prefix, output_directory, linker_name, build_config) - section_sizes, raw_symbols = CreateSectionSizesAndSymbols( + container, raw_symbols = CreateContainerAndSymbols( knobs=knobs, opts=opts, + container_name=container_name, metadata=metadata, map_path=map_path, tool_prefix=tool_prefix, @@ -2003,22 +2024,21 @@ linker_name=linker_name, size_info_prefix=size_info_prefix) - metadata_list.append(metadata) - section_sizes_list.append(section_sizes) + container_list.append(container) raw_symbols_list.append(raw_symbols) size_info = CreateSizeInfo(build_config, - section_sizes_list, + container_list, raw_symbols_list, - metadata_list, normalize_names=False) if logging.getLogger().isEnabledFor(logging.DEBUG): for line in describe.DescribeSizeInfoCoverage(size_info): logging.debug(line) logging.info('Recorded info for %d symbols', len(size_info.raw_symbols)) - logging.info('Recording metadata: \n %s', - '\n '.join(describe.DescribeDict(size_info.metadata))) + for container in size_info.containers: + logging.info('Recording metadata: \n %s', + '\n '.join(describe.DescribeDict(container.metadata))) logging.info('Saving result to %s', args.size_file) file_format.SaveSizeInfo(
diff --git a/tools/binary_size/libsupersize/console.py b/tools/binary_size/libsupersize/console.py index 5cef3ec..76e5420 100644 --- a/tools/binary_size/libsupersize/console.py +++ b/tools/binary_size/libsupersize/console.py
@@ -125,8 +125,10 @@ if not first_sym: return [] size_info = self._SizeInfoForSymbol(first_sym) + container = first_sym.container tool_prefix = self._ToolPrefixForSymbol(size_info) - elf_path = self._ElfPathForSymbol(size_info, tool_prefix, elf_path) + elf_path = self._ElfPathForSymbol(size_info, container, tool_prefix, + elf_path) return string_extract.ReadStringLiterals( thing, elf_path, tool_prefix, all_rodata=all_rodata) @@ -256,13 +258,13 @@ '--tool-prefix, or setting --output-directory') return tool_prefix - def _ElfPathForSymbol(self, size_info, tool_prefix, elf_path): + def _ElfPathForSymbol(self, size_info, container, tool_prefix, elf_path): def build_id_matches(elf_path): found_build_id = archive.BuildIdFromElf(elf_path, tool_prefix) - expected_build_id = size_info.metadata.get(models.METADATA_ELF_BUILD_ID) + expected_build_id = container.metadata.get(models.METADATA_ELF_BUILD_ID) return found_build_id == expected_build_id - filename = size_info.metadata.get(models.METADATA_ELF_FILENAME) + filename = container.metadata.get(models.METADATA_ELF_FILENAME) paths_to_try = [] if elf_path: paths_to_try.append(elf_path) @@ -317,8 +319,10 @@ assert not symbol.IsDelta(), ('Cannot disasseble a Diff\'ed symbol. Try ' 'passing .before_symbol or .after_symbol.') size_info = self._SizeInfoForSymbol(symbol) + container = symbol.container tool_prefix = self._ToolPrefixForSymbol(size_info) - elf_path = self._ElfPathForSymbol(size_info, tool_prefix, elf_path) + elf_path = self._ElfPathForSymbol(size_info, container, tool_prefix, + elf_path) # Always use Android NDK's objdump because llvm-objdump does not seem to # correctly disassemble. output_directory_finder = self._output_directory_finder
diff --git a/tools/binary_size/libsupersize/describe.py b/tools/binary_size/libsupersize/describe.py index 2e5e93f..7055e5b 100644 --- a/tools/binary_size/libsupersize/describe.py +++ b/tools/binary_size/libsupersize/describe.py
@@ -214,6 +214,7 @@ section_sizes[name], notes) def _DescribeSymbol(self, sym, single_line=False): + # TODO(huangs): Render and display container name. address = 'Group' if sym.IsGroup() else hex(sym.address) last_field = '' @@ -393,13 +394,20 @@ else: summary_desc = () - if self.verbose: - titles = 'Index | Running Total | Section@Address | ...' - elif group.IsDelta(): - titles = (u'Index | Running Total | Section@Address | \u0394 PSS ' - u'(\u0394 size_without_padding) | Path') + title_parts = ['Index', 'Running Total'] + if group.container_name == '': + title_parts.append('Section@Address') else: - titles = ('Index | Running Total | Section@Address | PSS | Path') + raise ValueError('Multiple container not yet supported.') + if self.verbose: + title_parts.append('...') + else: + if group.IsDelta(): + title_parts.append(u'\u0394 PSS (\u0394 size_without_padding)') + else: + title_parts.append('PSS') + title_parts.append('Path') + titles = ' | '.join(title_parts) header_desc = (titles, '-' * 60) @@ -508,39 +516,51 @@ for line in DescribeDict(after_items))) def _DescribeDeltaSizeInfo(self, diff): - metadata_desc = self._DescribeDeltaDict('Metadata', - diff.before.metadata_legacy, - diff.after.metadata_legacy) - unsummed_sections, summed_sections = diff.ClassifySections() - section_desc = self._DescribeSectionSizes(unsummed_sections, - summed_sections, - diff.section_sizes) - group_desc = self.GenerateLines(diff.symbols) - return itertools.chain(metadata_desc, section_desc, ('',), group_desc) + desc_list = [] + if len(diff.containers) > 1: + raise ValueError('Multiple container not yet supported.') + else: # Legacy output for single Container case. + desc_list.append( + self._DescribeDeltaDict('Metadata', diff.before.metadata_legacy, + diff.after.metadata_legacy)) + c = diff.containers[0] + unsummed_sections, summed_sections = c.ClassifySections() + desc_list.append( + self._DescribeSectionSizes(unsummed_sections, summed_sections, + c.section_sizes)) + desc_list.append(('', )) + desc_list.append(self.GenerateLines(diff.symbols)) + return itertools.chain.from_iterable(desc_list) def _DescribeSizeInfo(self, size_info): - # Support legacy output by reporting |build_config| as part of metadata. - metadata_desc = itertools.chain( - ('Metadata:', ), - (' %s' % line for line in DescribeDict(size_info.metadata_legacy))) - unsummed_sections, summed_sections = size_info.ClassifySections() - section_desc = self._DescribeSectionSizes(unsummed_sections, - summed_sections, - size_info.section_sizes) - coverage_desc = () + desc_list = [] + if len(size_info.containers) > 1: + raise ValueError('Multiple container not yet supported.') + else: + # Support legacy output by reporting |build_config| as part of metadata. + desc_list.append(('Metadata:', )) + desc_list.append(' %s' % line + for line in DescribeDict(size_info.metadata_legacy)) + c = size_info.containers[0] + unsummed_sections, summed_sections = c.ClassifySections() + desc_list.append( + self._DescribeSectionSizes(unsummed_sections, summed_sections, + c.section_sizes)) + if self.verbose: - coverage_desc = itertools.chain( - ('',), DescribeSizeInfoCoverage(size_info)) - group_desc = self.GenerateLines(size_info.symbols) - return itertools.chain(metadata_desc, section_desc, coverage_desc, ('',), - group_desc) + desc_list.append(('', )) + desc_list.append(DescribeSizeInfoCoverage(size_info)) + desc_list.append(('', )) + desc_list.append(self.GenerateLines(size_info.symbols)) + return itertools.chain.from_iterable(desc_list) -def DescribeSizeInfoCoverage(size_info): +def _DescribeSizeInfoContainerCoverage(raw_symbols, container): """Yields lines describing how accurate |size_info| is.""" for section, section_name in models.SECTION_TO_SECTION_NAME.items(): - expected_size = size_info.section_sizes.get(section_name) - in_section = size_info.raw_symbols.WhereInSection(section_name) + expected_size = container.section_sizes.get(section_name) + # TODO(huangs): Also filter by container. + in_section = raw_symbols.WhereInSection(section_name) actual_size = in_section.size if expected_size is None: @@ -629,6 +649,15 @@ yield ' B) ' + repr(sym) +def DescribeSizeInfoCoverage(size_info): + # TODO(huangs): Add support for multiple containers. + assert len(size_info.containers) == 1 + c = size_info.containers[0] + # TODO(huangs): Change to use "yield from" once linters allow this. + for line in _DescribeSizeInfoContainerCoverage(size_info.raw_symbols, c): + yield line + + class DescriberCsv(Describer): def __init__(self, verbose=False): super(DescriberCsv, self).__init__() @@ -661,20 +690,26 @@ yield self._RenderCsv([name, size]) def _DescribeDeltaSizeInfo(self, diff): - unsummed_sections, summed_sections = diff.ClassifySections() - section_desc = self._DescribeSectionSizes(unsummed_sections, - summed_sections, - diff.section_sizes) - group_desc = self.GenerateLines(diff.symbols) - return itertools.chain(section_desc, ('',), group_desc) + desc_list = [] + for c in diff.containers: + unsummed_sections, summed_sections = c.ClassifySections() + desc_list.append( + self._DescribeSectionSizes(unsummed_sections, summed_sections, + c.section_sizes)) + desc_list.append(('', )) + desc_list.append(self.GenerateLines(diff.symbols)) + return itertools.chain.from_iterable(desc_list) def _DescribeSizeInfo(self, size_info): - unsummed_sections, summed_sections = size_info.ClassifySections() - section_desc = self._DescribeSectionSizes(unsummed_sections, - summed_sections, - size_info.section_sizes) - group_desc = self.GenerateLines(size_info.symbols) - return itertools.chain(section_desc, ('',), group_desc) + desc_list = [] + for c in size_info.containers: + unsummed_sections, summed_sections = c.ClassifySections() + desc_list.append( + self._DescribeSectionSizes(unsummed_sections, summed_sections, + c.section_sizes)) + desc_list.append(('', )) + desc_list.append(self.GenerateLines(size_info.symbols)) + return itertools.chain.from_iterable(desc_list) def _DescribeDeltaSymbolGroup(self, delta_group): yield self._RenderSymbolHeader(True);
diff --git a/tools/binary_size/libsupersize/diff.py b/tools/binary_size/libsupersize/diff.py index 09aafe43e..17a1ca6 100644 --- a/tools/binary_size/libsupersize/diff.py +++ b/tools/binary_size/libsupersize/diff.py
@@ -4,6 +4,7 @@ """Logic for diffing two SizeInfo objects.""" import collections +import itertools import logging import re @@ -121,20 +122,57 @@ return models.DeltaSymbolGroup(all_deltas) +def _DiffObj(before_obj, after_obj): + """Computes recursive diff of nested plain Python objects. + + Assumes no cyclical links exist. + """ + if before_obj is None: + if after_obj is None: + return None + before_obj = type(after_obj)() + elif after_obj is None: + after_obj = type(before_obj)() + if not isinstance(before_obj, type(after_obj)): + return '(type mismatch)' + if isinstance(before_obj, dict): + keys = set(before_obj.keys()) | set(after_obj.keys()) + return {k: _DiffObj(before_obj.get(k), after_obj.get(k)) for k in keys} + elif isinstance(before_obj, list): + return [ + _DiffObj(b, a) for b, a in itertools.zip_longest(before_obj, after_obj) + ] + elif isinstance(before_obj, (bool, str)): + return '%r -> %r' % (before_obj, after_obj) + elif isinstance(before_obj, (int, float, complex)): + return after_obj - before_obj + return '(unknown type)' + + +def _DiffContainerLists(before_containers, after_containers): + """Computes diffs between two lists of Containers.""" + # TODO(huangs): Add support for multiple containers (needs name matching). + assert len(before_containers) == 1 + assert len(after_containers) == 1 + ret = [] + for (before_c, after_c) in zip(before_containers, after_containers): + name = after_c.name + assert before_c.name == name + ret.append( + models.Container(name=name, + metadata=_DiffObj(before_c.metadata, after_c.metadata), + section_sizes=_DiffObj(before_c.section_sizes, + after_c.section_sizes))) + return ret + + def Diff(before, after, sort=False): """Diffs two SizeInfo objects. Returns a DeltaSizeInfo.""" assert isinstance(before, models.SizeInfo) assert isinstance(after, models.SizeInfo) - section_sizes = { - k: after.section_sizes.get(k, 0) - v - for k, v in before.section_sizes.items() - } - for k, v in after.section_sizes.items(): - if k not in section_sizes: - section_sizes[k] = v - + containers_diff = _DiffContainerLists(before.containers, after.containers) symbol_diff = _DiffSymbolGroups(before.raw_symbols, after.raw_symbols) - ret = models.DeltaSizeInfo(before, after, section_sizes, symbol_diff) + ret = models.DeltaSizeInfo(before, after, containers_diff, symbol_diff) if sort: syms = ret.symbols # Triggers clustering.
diff --git a/tools/binary_size/libsupersize/diff_test.py b/tools/binary_size/libsupersize/diff_test.py index 0d641c4..4b606bc5 100755 --- a/tools/binary_size/libsupersize/diff_test.py +++ b/tools/binary_size/libsupersize/diff_test.py
@@ -32,7 +32,11 @@ def _CreateSizeInfo(aliases=None): build_config = {} + metadata = {} section_sizes = {'.text': 100, '.bss': 40} + containers = [ + models.Container(name='', metadata=metadata, section_sizes=section_sizes) + ] TEXT = models.SECTION_TEXT symbols = [ _MakeSym(models.SECTION_DEX_METHOD, 10, 'a', 'com.Foo#bar()'), @@ -42,12 +46,13 @@ _MakeSym(TEXT, 50, 'b'), _MakeSym(TEXT, 60, ''), ] + # For simplicity, not associating |symbols| with |containers|. if aliases: for tup in aliases: syms = symbols[tup[0]:tup[1]] for sym in syms: sym.aliases = syms - return models.SizeInfo(build_config, section_sizes, symbols) + return models.SizeInfo(build_config, containers, symbols) class DiffTest(unittest.TestCase): @@ -98,6 +103,7 @@ size_info2.raw_symbols += [ _MakeSym(models.SECTION_RODATA, 11, 'asdf', name='Hello'), ] + # For simplicity, not associating |symbols| with |containers|. d = diff.Diff(size_info1, size_info2) self.assertEqual((0, 1, 1), d.raw_symbols.CountsByDiffStatus()[1:]) self.assertEqual(0, d.raw_symbols.size) @@ -151,6 +157,7 @@ _MakeSym(TEXT, 33, 'a', name='SingleCategoryPreferences$9#this$009'), _MakeSym(TEXT, 44, 'a', name='.L.ref.tmp.137'), ] + # For simplicity, not associating |symbols| with |containers|. d = diff.Diff(size_info1, size_info2) self.assertEqual((0, 0, 0), d.raw_symbols.CountsByDiffStatus()[1:]) self.assertEqual(0, d.raw_symbols.size) @@ -210,6 +217,5 @@ self.assertEqual(0, d.raw_symbols.size) - if __name__ == '__main__': unittest.main()
diff --git a/tools/binary_size/libsupersize/file_format.py b/tools/binary_size/libsupersize/file_format.py index 28120dba..ef0a890 100644 --- a/tools/binary_size/libsupersize/file_format.py +++ b/tools/binary_size/libsupersize/file_format.py
@@ -171,6 +171,8 @@ # Padding not really required, but it is useful to check for large padding and # log a warning. + # TODO(huangs): Add support for multiple containers: Need to group by + # container names and sections. seen_sections = set() for i, symbol in enumerate(raw_symbols[1:]): prev_symbol = raw_symbols[i] @@ -253,18 +255,18 @@ w.WriteLine(_SERIALIZATION_VERSION) # JSON header fields fields = { - 'section_sizes': size_info.section_sizes, 'has_components': True, 'has_padding': include_padding, } - # Preserve old format: Combine build_config and metadata. - metadata = size_info.metadata - for key in models.BUILD_CONFIG_KEYS: - if key in size_info.build_config: - if not metadata: - metadata = {} - metadata[key] = size_info.build_config[key] - fields['metadata'] = metadata + num_containers = len(size_info.containers) + has_multi_containers = (num_containers > 1) + + if has_multi_containers: + raise ValueError('Multiple container not yet supported.') + else: + # Write using old format. + fields['metadata'] = size_info.metadata_legacy + fields['section_sizes'] = size_info.containers[0].section_sizes fields_str = json.dumps(fields, indent=2, sort_keys=True) w.WriteLine(str(len(fields_str))) @@ -290,7 +292,10 @@ # Symbol counts by section. symbol_group_by_section = raw_symbols.GroupedBySectionName() - w.WriteLine('\t'.join(g.name for g in symbol_group_by_section)) + if has_multi_containers: + raise ValueError('Multiple container not yet supported.') + else: + w.WriteLine('\t'.join(g.name for g in symbol_group_by_section)) w.WriteLine('\t'.join(str(len(g)) for g in symbol_group_by_section)) def gen_delta(gen, prev_value=0): @@ -388,16 +393,26 @@ json_str = lines.read(json_len) fields = json.loads(json_str) - section_sizes = fields['section_sizes'] - # Parse old format, but separate data into build_config and metadata. - build_config = {} - metadata = fields.get('metadata') - if metadata: - for key in models.BUILD_CONFIG_KEYS: - if key in metadata: - build_config[key] = metadata[key] - del metadata[key] + has_multi_containers = False + + containers = [] + if has_multi_containers: # New format. + raise ValueError('Multiple container not yet supported.') + else: + # Parse old format, but separate data into build_config and metadata. + build_config = {} + metadata = fields.get('metadata') + if metadata: + for key in models.BUILD_CONFIG_KEYS: + if key in metadata: + build_config[key] = metadata[key] + del metadata[key] + section_sizes = fields['section_sizes'] + containers.append( + models.Container(name='', + metadata=metadata, + section_sizes=section_sizes)) has_components = fields.get('has_components', False) has_padding = fields.get('has_padding', False) @@ -406,7 +421,7 @@ _ReadLine(lines) # Path list - num_path_tuples = int(_ReadLine(lines)) # Line 4 - number of paths in list + num_path_tuples = int(_ReadLine(lines)) # Number of paths in list # Read the path list values and store for later path_tuples = [ _ReadValuesFromLine(lines, split='\t') for _ in range(num_path_tuples) @@ -419,7 +434,7 @@ # Symbol counts by section. section_names = _ReadValuesFromLine(lines, split='\t') - section_counts = [int(c) for c in _ReadValuesFromLine(lines, split='\t')] + symbol_counts = [int(c) for c in _ReadValuesFromLine(lines, split='\t')] # Addresses, sizes, paddings, path indices, component indices def read_numeric(delta=False): @@ -431,7 +446,7 @@ """ ret = [] delta_multiplier = int(delta) - for _ in section_counts: + for _ in symbol_counts: value = 0 fields = [] for f in _ReadValuesFromLine(lines, split=' '): @@ -452,14 +467,19 @@ else: component_indices = [None] * len(section_names) - raw_symbols = [None] * sum(section_counts) + raw_symbols = [None] * sum(symbol_counts) symbol_idx = 0 - for (cur_section_name, cur_section_count, cur_addresses, cur_sizes, - cur_paddings, cur_path_indices, cur_component_indices) in zip( - section_names, section_counts, addresses, sizes, paddings, - path_indices, component_indices): + for (cur_section_name, cur_symbol_count, cur_addresses, cur_sizes, + cur_paddings, cur_path_indices, + cur_component_indices) in zip(section_names, symbol_counts, addresses, + sizes, paddings, path_indices, + component_indices): + if has_multi_containers: + raise ValueError('Multiple container not yet supported.') + else: + cur_container = containers[0] alias_counter = 0 - for i in range(cur_section_count): + for i in range(cur_symbol_count): parts = _ReadValuesFromLine(lines, split='\t') full_name = parts[0] flags_part = None @@ -486,6 +506,7 @@ # Skip the constructor to avoid default value checks new_sym = models.Symbol.__new__(models.Symbol) + new_sym.container = cur_container new_sym.section_name = cur_section_name new_sym.full_name = full_name new_sym.address = cur_addresses[i] @@ -523,9 +544,8 @@ CalculatePadding(raw_symbols) return models.SizeInfo(build_config, - section_sizes, + containers, raw_symbols, - metadata=metadata, size_path=size_path)
diff --git a/tools/binary_size/libsupersize/html_report.py b/tools/binary_size/libsupersize/html_report.py index 72d9e27a11..bad1c83 100644 --- a/tools/binary_size/libsupersize/html_report.py +++ b/tools/binary_size/libsupersize/html_report.py
@@ -212,18 +212,20 @@ symbols = symbols.WhereDiffStatusIs(models.DIFF_STATUS_UNCHANGED).Inverted() meta, tree_nodes = _MakeTreeViewList(symbols, all_symbols) + assert len(size_info.containers) == 1 + c = size_info.containers[0] logging.info('Created %d tree nodes', len(tree_nodes)) meta.update({ - 'diff_mode': is_diff, - 'section_sizes': size_info.section_sizes, + 'diff_mode': is_diff, + 'section_sizes': c.section_sizes, }) if is_diff: meta.update({ - 'before_metadata': size_info.before.metadata, - 'after_metadata': size_info.after.metadata, + 'before_metadata': size_info.before.metadata_legacy, + 'after_metadata': size_info.after.metadata_legacy, }) else: - meta['metadata'] = size_info.metadata + meta['metadata'] = size_info.metadata_legacy # Write newline-delimited JSON file logging.info('Serializing JSON')
diff --git a/tools/binary_size/libsupersize/integration_test.py b/tools/binary_size/libsupersize/integration_test.py index 4cf9f22..f3312094 100755 --- a/tools/binary_size/libsupersize/integration_test.py +++ b/tools/binary_size/libsupersize/integration_test.py
@@ -215,9 +215,10 @@ minimal_apks_path, _TEST_TOOL_PREFIX, output_directory, linker_name, build_config) - section_sizes, raw_symbols = archive.CreateSectionSizesAndSymbols( + container, raw_symbols = archive.CreateContainerAndSymbols( knobs=knobs, opts=opts, + container_name='', metadata=metadata, map_path=_TEST_MAP_PATH, tool_prefix=_TEST_TOOL_PREFIX, @@ -230,7 +231,7 @@ linker_name=linker_name, size_info_prefix=size_info_prefix) IntegrationTest.cached_size_info[cache_key] = archive.CreateSizeInfo( - build_config, [section_sizes], [raw_symbols], [metadata]) + build_config, [container], [raw_symbols]) return copy.deepcopy(IntegrationTest.cached_size_info[cache_key]) def _DoArchive(self, @@ -303,15 +304,12 @@ sym_strs = (repr(sym) for sym in size_info.symbols) stats = describe.DescribeSizeInfoCoverage(size_info) - # Merge the its metadata into build_config. - merged_data = size_info.build_config.copy() - for k, v in size_info.metadata.items(): - merged_data[k] = v - if merged_data: - merged_data_desc = describe.DescribeDict(merged_data) + if len(size_info.containers) == 1: + # If there's only one container, merge the its metadata into build_config. + merged_data_desc = describe.DescribeDict(size_info.metadata_legacy) + return itertools.chain(merged_data_desc, stats, sym_strs) else: - merged_data_desc = [] - return itertools.chain(merged_data_desc, stats, sym_strs) + raise ValueError('Multiple container not yet supported.') @_CompareWithGolden() def test_Archive(self): @@ -402,8 +400,10 @@ size_info1 = self._CloneSizeInfo(use_elf=False, use_pak=True) size_info2 = self._CloneSizeInfo(use_elf=False, use_pak=True) size_info2.build_config['git_revision'] = 'xyz789' - size_info1.metadata = {"foo": 1, "bar": [1, 2, 3], "baz": "yes"} - size_info2.metadata = {"foo": 1, "bar": [1, 3], "baz": "yes"} + container1 = size_info1.containers[0] + container2 = size_info2.containers[0] + container1.metadata = {"foo": 1, "bar": [1, 2, 3], "baz": "yes"} + container2.metadata = {"foo": 1, "bar": [1, 3], "baz": "yes"} size_info1.raw_symbols -= size_info1.raw_symbols[:2] size_info2.raw_symbols -= size_info2.raw_symbols[-3:]
diff --git a/tools/binary_size/libsupersize/models.py b/tools/binary_size/libsupersize/models.py index 9e7053a..718f95f 100644 --- a/tools/binary_size/libsupersize/models.py +++ b/tools/binary_size/libsupersize/models.py
@@ -22,6 +22,7 @@ Never None, but will be '' for anonymous symbols. * is_anonymous: True when the symbol exists in an anonymous namespace (which are removed from both full_name and name during normalization). + * container: A (shared) Container instance. * section_name: E.g. ".text", ".rodata", ".data.rel.local" * section: The second character of |section_name|. E.g. "t", "r", "d". * component: The team that owns this feature. @@ -199,40 +200,67 @@ return frozenset(unsummed_sections), frozenset(summed_sections) +class Container(object): + """Info for a a single input file for SuperSize, e.g., an APK file. + + Fields: + name: Container name. Must be unique among containers, and can be ''. + metadata: A dict. + section_sizes: A dict of section_name -> size. + classified_sections: Cache for ClassifySections(). + """ + __slots__ = ( + 'name', + 'metadata', + 'section_sizes', + '_classified_sections', + ) + + def __init__(self, name, metadata, section_sizes): + # name == '' hints that only one container exists, and there's no need to + # distinguish them. This can affect console output. + self.name = name + self.metadata = metadata or {} + self.section_sizes = section_sizes # E.g. {SECTION_TEXT: 0} + self._classified_sections = None + + def ClassifySections(self): + if not self._classified_sections: + self._classified_sections = ClassifySections(self.section_sizes.keys()) + return self._classified_sections + + class BaseSizeInfo(object): """Base class for SizeInfo and DeltaSizeInfo. Fields: build_config: A dict of build configurations. - section_sizes: A dict of section_name -> size. + containers: A list of Containers. raw_symbols: A SymbolGroup containing all top-level symbols (no groups). symbols: A SymbolGroup of all symbols, where symbols have been grouped by full_name (where applicable). May be re-assigned when it is - desirable to show custom groupings while still printing metadata and - section_sizes. + desirable to show custom groupings while still printing containers. native_symbols: Subset of |symbols| that are from native code. pak_symbols: Subset of |symbols| that are from pak files. """ __slots__ = ( 'build_config', - 'section_sizes', + 'containers', 'raw_symbols', '_symbols', '_native_symbols', '_pak_symbols', - '_classified_sections', ) - def __init__(self, build_config, section_sizes, raw_symbols, symbols=None): + def __init__(self, build_config, containers, raw_symbols, symbols=None): if isinstance(raw_symbols, list): raw_symbols = SymbolGroup(raw_symbols) self.build_config = build_config - self.section_sizes = section_sizes # E.g. {SECTION_TEXT: 0} + self.containers = containers self.raw_symbols = raw_symbols self._symbols = symbols self._native_symbols = None self._pak_symbols = None - self._classified_sections = None @property def symbols(self): @@ -260,42 +288,45 @@ self._pak_symbols = self.raw_symbols.WhereIsPak() return self._pak_symbols - def ClassifySections(self): - if not self._classified_sections: - self._classified_sections = ClassifySections(self.section_sizes.keys()) - return self._classified_sections + @property + def all_section_sizes(self): + return [c.section_sizes for c in self.containers] + + @property + def metadata(self): + return [c.metadata for c in self.containers] class SizeInfo(BaseSizeInfo): """Represents all size information for a single binary. Fields: - metadata: A dict. size_path: Path to .size file this was loaded from (or None). """ __slots__ = ( - 'metadata', 'size_path', ) def __init__(self, build_config, - section_sizes, + containers, raw_symbols, - metadata=None, symbols=None, size_path=None): super(SizeInfo, self).__init__(build_config, - section_sizes, + containers, raw_symbols, symbols=symbols) - self.metadata = metadata or {} self.size_path = size_path @property def metadata_legacy(self): - """Returns |metadata| fused with |build_config|.""" - metadata = self.metadata.copy() + """Return |container[0].metadata| fused with |build_config|. + + Supported only if there is one Container. + """ + assert len(self.containers) == 1 + metadata = self.containers[0].metadata.copy() for k, v in self.build_config.items(): assert k not in metadata metadata[k] = v @@ -314,8 +345,8 @@ 'after', ) - def __init__(self, before, after, section_sizes, raw_symbols): - super(DeltaSizeInfo, self).__init__(None, section_sizes, raw_symbols) + def __init__(self, before, after, containers, raw_symbols): + super(DeltaSizeInfo, self).__init__(None, containers, raw_symbols) self.before = before self.after = after @@ -328,6 +359,10 @@ __slots__ = () @property + def container_name(self): + return self.container.name if self.container else '' + + @property def section(self): """Returns the one-letter section.""" return SECTION_NAME_TO_SECTION[self.section_name] @@ -448,6 +483,7 @@ 'object_path', 'aliases', 'padding', + 'container', 'section_name', 'source_path', 'size', @@ -476,9 +512,11 @@ self.flags = flags self.aliases = aliases self.padding = 0 + self.container = None self.component = '' def __repr__(self): + # TODO(huangs): If container name is nonempty then display it. template = ('{}@{:x}(size_without_padding={},padding={},full_name={},' 'object_path={},source_path={},flags={},num_aliases={},' 'component={})') @@ -524,6 +562,7 @@ self.after_symbol = after_symbol def __repr__(self): + # TODO(huangs): If container name is nonempty then display it. template = ('{}{}@{:x}(size_without_padding={},padding={},full_name={},' 'object_path={},source_path={},flags={})') return template.format( @@ -587,6 +626,10 @@ return None @property + def container(self): + return (self.after_symbol or self.before_symbol).container + + @property def section_name(self): return (self.after_symbol or self.before_symbol).section_name @@ -669,6 +712,7 @@ 'full_name', 'template_name', 'name', + 'container_name', 'section_name', 'is_default_sorted', # True for groups created by Sorted() ) @@ -691,6 +735,8 @@ self.full_name = full_name if full_name is not None else name self.template_name = template_name if template_name is not None else name self.name = name or '' + # TODO(huangs): Add support for multiple containers. + self.container_name = '' self.section_name = section_name or SECTION_MULTIPLE self.is_default_sorted = is_default_sorted
diff --git a/tools/binary_size/libsupersize/testdata/Console.golden b/tools/binary_size/libsupersize/testdata/Console.golden index 21052a8..f28ad8c 100644 --- a/tools/binary_size/libsupersize/testdata/Console.golden +++ b/tools/binary_size/libsupersize/testdata/Console.golden
@@ -1,12 +1,12 @@ ******************************************************************************** Entering interactive Python shell. Quick reference: -SizeInfo: ClassifySections, build_config, metadata, metadata_legacy, native_symbols, pak_symbols, raw_symbols, section_sizes, size_path, symbols -Symbol: FlagsString, IsBss, IsDelta, IsDex, IsGeneratedByToolchain, IsGroup, IsNameUnique, IsNative, IsOther, IsOverhead, IsPak, IsStringLiteral, IterLeafSymbols, SetName, address, aliases, component, end_address, flags, full_name, generated_source, is_anonymous, name, num_aliases, object_path, padding, padding_pss, pss, pss_without_padding, section, section_name, size, size_without_padding, source_path, template_name +SizeInfo: all_section_sizes, build_config, containers, metadata, metadata_legacy, native_symbols, pak_symbols, raw_symbols, size_path, symbols +Symbol: FlagsString, IsBss, IsDelta, IsDex, IsGeneratedByToolchain, IsGroup, IsNameUnique, IsNative, IsOther, IsOverhead, IsPak, IsStringLiteral, IterLeafSymbols, SetName, address, aliases, component, container, container_name, end_address, flags, full_name, generated_source, is_anonymous, name, num_aliases, object_path, padding, padding_pss, pss, pss_without_padding, section, section_name, size, size_without_padding, source_path, template_name SymbolGroup (extends Symbol): CountUniqueSymbols, Filter, GroupedBy, GroupedByAliases, GroupedByComponent, GroupedByFullName, GroupedByName, GroupedByPath, GroupedBySectionName, Inverted, IterUniqueSymbols, Sorted, SortedByAddress, SortedByCount, SortedByName, WhereAddressInRange, WhereComponentMatches, WhereFullNameMatches, WhereGeneratedByToolchain, WhereHasAnyAttribution, WhereHasComponent, WhereHasFlag, WhereHasPath, WhereInSection, WhereIsDex, WhereIsGroup, WhereIsNative, WhereIsPak, WhereIsTemplate, WhereMatches, WhereNameMatches, WhereObjectPathMatches, WherePathMatches, WherePssBiggerThan, WhereSizeBiggerThan, WhereSourceIsGenerated, WhereSourcePathMatches, WhereTemplateNameMatches, index, is_default_sorted -DeltaSizeInfo: ClassifySections, after, before, build_config, native_symbols, pak_symbols, raw_symbols, section_sizes, symbols +DeltaSizeInfo: after, all_section_sizes, before, build_config, containers, metadata, native_symbols, pak_symbols, raw_symbols, symbols DeltaSymbol (extends Symbol): after_symbol, before_symbol, diff_status DeltaSymbolGroup (extends SymbolGroup): CountsByDiffStatus, WhereDiffStatusIs, diff_status
diff --git a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp index be8c84a..8c0c89e 100644 --- a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp +++ b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
@@ -53,15 +53,18 @@ const char kExcludeFieldsParamName[] = "exclude-fields"; // Output format is documented in //docs/clang_tool_refactoring.md -class ReplacementsPrinter { +class ReplacementsPrinter : public clang::tooling::SourceFileCallbacks { public: - ReplacementsPrinter() { llvm::outs() << "==== BEGIN EDITS ====\n"; } - - ~ReplacementsPrinter() { llvm::outs() << "==== END EDITS ====\n"; } + ReplacementsPrinter() = default; + ~ReplacementsPrinter() = default; void PrintReplacement(const clang::SourceManager& source_manager, const clang::SourceRange& replacement_range, - std::string replacement_text) { + std::string replacement_text, + bool should_add_include = false) { + if (ShouldSuppressOutput()) + return; + clang::tooling::Replacement replacement( source_manager, clang::CharSourceRange::getCharRange(replacement_range), replacement_text); @@ -73,16 +76,71 @@ << ":::" << replacement.getLength() << ":::" << replacement_text << "\n"; - bool was_inserted = false; - std::tie(std::ignore, was_inserted) = - files_with_already_added_includes_.insert(file_path.str()); - if (was_inserted) - llvm::outs() << "include-user-header:::" << file_path - << ":::-1:::-1:::" << kIncludePath << "\n"; + if (should_add_include) { + bool was_inserted = false; + std::tie(std::ignore, was_inserted) = + files_with_already_added_includes_.insert(file_path.str()); + if (was_inserted) + llvm::outs() << "include-user-header:::" << file_path + << ":::-1:::-1:::" << kIncludePath << "\n"; + } } private: + // clang::tooling::SourceFileCallbacks override: + bool handleBeginSource(clang::CompilerInstance& compiler) override { + const clang::FrontendOptions& frontend_options = compiler.getFrontendOpts(); + + assert((frontend_options.Inputs.size() == 1) && + "run_tool.py should invoke the rewriter one file at a time"); + const clang::FrontendInputFile& input_file = frontend_options.Inputs[0]; + assert(input_file.isFile() && + "run_tool.py should invoke the rewriter on actual files"); + + current_language_ = input_file.getKind().getLanguage(); + + if (!ShouldSuppressOutput()) + llvm::outs() << "==== BEGIN EDITS ====\n"; + + return true; // Report that |handleBeginSource| succeeded. + } + + // clang::tooling::SourceFileCallbacks override: + void handleEndSource() override { + if (!ShouldSuppressOutput()) + llvm::outs() << "==== END EDITS ====\n"; + } + + bool ShouldSuppressOutput() { + switch (current_language_) { + case clang::Language::Unknown: + case clang::Language::Asm: + case clang::Language::LLVM_IR: + case clang::Language::OpenCL: + case clang::Language::CUDA: + case clang::Language::RenderScript: + case clang::Language::HIP: + // Rewriter can't handle rewriting the current input language. + return true; + + case clang::Language::C: + case clang::Language::ObjC: + // CheckedPtr requires C++. In particular, attempting to #include + // "base/memory/checked_ptr.h" from C-only compilation units will lead + // to compilation errors. + return true; + + case clang::Language::CXX: + case clang::Language::ObjCXX: + return false; + } + + assert(false && "Unrecognized clang::Language"); + return true; + } + std::set<std::string> files_with_already_added_includes_; + clang::Language current_language_ = clang::Language::Unknown; }; AST_MATCHER(clang::TagDecl, isNotFreeStandingTagDecl) { @@ -186,6 +244,10 @@ return Filter.Contains(Node); } +AST_MATCHER(clang::Decl, isInExternCContext) { + return Node.getLexicalDeclContext()->isExternCContext(); +} + AST_MATCHER(clang::ClassTemplateSpecializationDecl, isImplicitSpecialization) { return !Node.isExplicitSpecialization(); } @@ -231,6 +293,9 @@ return !has_sibling_with_same_type_loc; } +// Rewrites |SomeClass* field| (matched as "fieldDecl") into +// |CheckedPtr<SomeClass> field| and for each file rewritten in such way adds an +// |#include "base/memory/checked_ptr.h"|. class FieldDeclRewriter : public MatchFinder::MatchCallback { public: explicit FieldDeclRewriter(ReplacementsPrinter* replacements_printer) @@ -275,7 +340,8 @@ // Generate and print a replacement. replacements_printer_->PrintReplacement(source_manager, replacement_range, - replacement_text); + replacement_text, + true /* should_add_include */); } private: @@ -307,6 +373,35 @@ ReplacementsPrinter* const replacements_printer_; }; +// Rewrites |my_struct.ptr_field| (matched as "affectedMemberExpr") into +// |my_struct.ptr_field.get()|. +class AffectedExprRewriter : public MatchFinder::MatchCallback { + public: + AffectedExprRewriter(ReplacementsPrinter* replacements_printer) + : replacements_printer_(replacements_printer) {} + + void run(const MatchFinder::MatchResult& result) override { + const clang::SourceManager& source_manager = *result.SourceManager; + + const clang::MemberExpr* member_expr = + result.Nodes.getNodeAs<clang::MemberExpr>("affectedMemberExpr"); + assert(member_expr && "matcher should bind 'affectedMemberExpr'"); + + clang::SourceLocation member_name_start = member_expr->getMemberLoc(); + size_t member_name_length = member_expr->getMemberDecl()->getName().size(); + clang::SourceLocation insertion_loc = + member_name_start.getLocWithOffset(member_name_length); + + clang::SourceRange replacement_range(insertion_loc, insertion_loc); + + replacements_printer_->PrintReplacement(source_manager, replacement_range, + ".get()"); + } + + private: + ReplacementsPrinter* const replacements_printer_; +}; + } // namespace int main(int argc, const char* argv[]) { @@ -375,18 +470,45 @@ // the source code) FieldDeclFilterFile fields_to_exclude(exclude_fields_param); auto field_decl_matcher = - fieldDecl( - allOf(hasType(supported_pointer_types_matcher), hasUniqueTypeLoc(), - unless(anyOf(isInThirdPartyLocation(), isInMacroLocation(), - isListedInFilterFile(fields_to_exclude), - implicit_field_decl_matcher)))) + fieldDecl(allOf(hasType(supported_pointer_types_matcher), + hasUniqueTypeLoc(), + unless(anyOf(isInThirdPartyLocation(), + isInMacroLocation(), isInExternCContext(), + isListedInFilterFile(fields_to_exclude), + implicit_field_decl_matcher)))) .bind("fieldDecl"); FieldDeclRewriter field_decl_rewriter(&replacements_printer); match_finder.addMatcher(field_decl_matcher, &field_decl_rewriter); + // Matches expressions that used to return a value of type |SomeClass*| + // but after the rewrite return an instance of |CheckedPtr<SomeClass>|. + auto affected_member_expr_matcher = + memberExpr(member(field_decl_matcher)).bind("affectedMemberExpr"); + auto affected_implicit_expr_matcher = implicitCastExpr(has(expr(anyOf( + // Only single implicitCastExpr is present in case of: + // |auto* v = s.ptr_field;| + expr(affected_member_expr_matcher), + // 2nd nested implicitCastExpr is present in case of: + // |const auto* v = s.ptr_field;| + expr(implicitCastExpr(has(affected_member_expr_matcher))))))); + + // Printf-style call expr ========= + // Given + // void foo(const S& s) { + // printf("%p", s.y); + // } + // matches the |s.y| expr if it matches the |affected_implicit_expr_matcher| + // above. + auto affected_printf_arg_matcher = + expr(allOf(affected_implicit_expr_matcher, + hasParent(callExpr(callee(functionDecl(isVariadic())))))); + AffectedExprRewriter printf_arg_rewriter(&replacements_printer); + match_finder.addMatcher(affected_printf_arg_matcher, &printf_arg_rewriter); + // Prepare and run the tool. std::unique_ptr<clang::tooling::FrontendActionFactory> factory = - clang::tooling::newFrontendActionFactory(&match_finder); + clang::tooling::newFrontendActionFactory(&match_finder, + &replacements_printer); int result = tool.run(factory.get()); if (result != 0) return result;
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc new file mode 100644 index 0000000..1e77ecd --- /dev/null +++ b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
@@ -0,0 +1,37 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/checked_ptr.h" + +class SomeClass; + +struct MyStruct { + CheckedPtr<SomeClass> ptr; + CheckedPtr<SomeClass> ptr2; +}; + +int ConvertSomeClassToInt(SomeClass* some_class) { + return 123; +} + +void MyPrintf(const char* fmt, ...) {} + +void foo() { + MyStruct s; + + // Expected rewrite: MyPrintf("%p", s.ptr.get()); + MyPrintf("%p", s.ptr.get()); + + // Test - all arguments are rewritten. + // Expected rewrite: MyPrintf("%p, %p", s.ptr.get(), s.ptr2.get()); + MyPrintf("%p, %p", s.ptr.get(), s.ptr2.get()); + + // Test - only |s.ptr|-style arguments are rewritten. + // Expected rewrite: MyPrintf("%d, %p", 123, s.ptr.get()); + MyPrintf("%d, %p", 123, s.ptr.get()); + + // Test - |s.ptr| is deeply nested. + // No rewrite expected. + MyPrintf("%d", ConvertSomeClassToInt(s.ptr)); +}
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc new file mode 100644 index 0000000..0787d36e --- /dev/null +++ b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
@@ -0,0 +1,35 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +class SomeClass; + +struct MyStruct { + SomeClass* ptr; + SomeClass* ptr2; +}; + +int ConvertSomeClassToInt(SomeClass* some_class) { + return 123; +} + +void MyPrintf(const char* fmt, ...) {} + +void foo() { + MyStruct s; + + // Expected rewrite: MyPrintf("%p", s.ptr.get()); + MyPrintf("%p", s.ptr); + + // Test - all arguments are rewritten. + // Expected rewrite: MyPrintf("%p, %p", s.ptr.get(), s.ptr2.get()); + MyPrintf("%p, %p", s.ptr, s.ptr2); + + // Test - only |s.ptr|-style arguments are rewritten. + // Expected rewrite: MyPrintf("%d, %p", 123, s.ptr.get()); + MyPrintf("%d, %p", 123, s.ptr); + + // Test - |s.ptr| is deeply nested. + // No rewrite expected. + MyPrintf("%d", ConvertSomeClassToInt(s.ptr)); +}
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/various-types-expected.cc b/tools/clang/rewrite_raw_ptr_fields/tests/various-types-expected.cc index 3a29cc2..6f4b90a 100644 --- a/tools/clang/rewrite_raw_ptr_fields/tests/various-types-expected.cc +++ b/tools/clang/rewrite_raw_ptr_fields/tests/various-types-expected.cc
@@ -162,4 +162,12 @@ CheckedPtr<FreeStandingStruct> ptr_to_free_standing_struct; }; +extern "C" { +struct OtherForeignStruct; +struct ForeignStruct { + // We should not rewrite foreign, extern "C" structs. + OtherForeignStruct* ptr; +}; +} + } // namespace my_namespace
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/various-types-original.cc b/tools/clang/rewrite_raw_ptr_fields/tests/various-types-original.cc index 8ce8d93..c175467 100644 --- a/tools/clang/rewrite_raw_ptr_fields/tests/various-types-original.cc +++ b/tools/clang/rewrite_raw_ptr_fields/tests/various-types-original.cc
@@ -160,4 +160,12 @@ FreeStandingStruct* ptr_to_free_standing_struct; }; +extern "C" { +struct OtherForeignStruct; +struct ForeignStruct { + // We should not rewrite foreign, extern "C" structs. + OtherForeignStruct* ptr; +}; +} + } // namespace my_namespace
diff --git a/tools/json_schema_compiler/code.py b/tools/json_schema_compiler/code.py index ef41cf8..c23fc483 100644 --- a/tools/json_schema_compiler/code.py +++ b/tools/json_schema_compiler/code.py
@@ -124,13 +124,18 @@ def trim_comment(comment, max_len): if len(comment) <= max_len: return comment, '' + # If we ran out of space due to existing content, don't try to wrap. + if max_len <= 1: + return '', comment.lstrip() last_space = comment.rfind(' ', 0, max_len + 1) if last_space != -1: line = comment[0:last_space] comment = comment[last_space + 1:] else: - line = comment[0:max_len] - comment = comment[max_len:] + # If the line can't be split, then don't try. The comments might be + # important (e.g. JSDoc) where splitting it breaks things. + line = comment + comment = '' return line, comment.lstrip() # First line has the full maximum length. @@ -145,6 +150,7 @@ # Any subsequent lines be subject to the wrap indent. max_len = (self._comment_length - len(''.join(self._line_prefixes)) - len(comment_prefix) - wrap_indent) + assert max_len > 1 while len(comment): line, comment = trim_comment(comment, max_len) self.Append(comment_prefix + (' ' * wrap_indent) + line, substitute=False)
diff --git a/tools/json_schema_compiler/code_test.py b/tools/json_schema_compiler/code_test.py index 90e2879..6d54ecc 100755 --- a/tools/json_schema_compiler/code_test.py +++ b/tools/json_schema_compiler/code_test.py
@@ -141,12 +141,16 @@ 'longness, that is, using a different\n' '// word, length.', c.Render()) + # Words that cannot be broken up are left as too long. long_word = 'x' * 100 c = Code() + c.Comment('xxx') c.Comment(long_word) + c.Comment('xxx') self.assertEquals( - '// ' + 'x' * 77 + '\n' - '// ' + 'x' * 23, + '// xxx\n' + '// ' + 'x' * 100 + '\n' + '// xxx', c.Render()) c = Code(indent_size=2, comment_length=40) c.Comment('Pretend this is a Closure Compiler style comment, which should '
diff --git a/tools/metrics/BUILD.gn b/tools/metrics/BUILD.gn index 2d277a1..e5a8e38 100644 --- a/tools/metrics/BUILD.gn +++ b/tools/metrics/BUILD.gn
@@ -7,6 +7,7 @@ sources = [ "histograms/enums.xml", "histograms/histograms.xml", + "ukm/ukm.xml", ] output = "$root_out_dir/histograms.xml" outputs = [ output ] @@ -85,6 +86,9 @@ "//tools/metrics/common/pretty_print_xml.py", "//tools/metrics/common/etree_util.py", + "//tools/metrics/histograms/test_data/enums.xml", + "//tools/metrics/histograms/test_data/histograms.xml", + "//tools/metrics/histograms/test_data/ukm.xml", "//tools/metrics/histograms/enums.xml", "//tools/metrics/histograms/expand_owners.py", "//tools/metrics/histograms/expand_owners_unittest.py", @@ -96,6 +100,8 @@ "//tools/metrics/histograms/histogram_paths.py", "//tools/metrics/histograms/histograms_print_style.py", "//tools/metrics/histograms/merge_xml.py", + "//tools/metrics/histograms/merge_xml_test.py", + "//tools/metrics/histograms/populate_enums.py", "//tools/metrics/histograms/pretty_print.py", "//tools/metrics/histograms/pretty_print_test.py",
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index dd9e4c8a..e745e3464 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -2704,6 +2704,14 @@ </description> </action> +<action name="Autofill_CreditCardUpload_LegalMessageLinkClicked"> + <owner>siyua@chromium.org</owner> + <description> + This user action is logged when the legal message link in the credit card + upload bubble is clicked by the user. + </description> +</action> + <action name="Autofill_FilledCreditCardSuggestion"> <owner>sebsg@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a62017e..7c0329d9 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -41958,6 +41958,7 @@ <int value="1694854500" label="disable-save-password-bubble"/> <int value="1696139514" label="enable-ble-advertising-in-apps"/> <int value="1697189972" label="WebPaymentsSingleAppUiSkip:disabled"/> + <int value="1698089268" label="WebXRMultiGpu:disabled"/> <int value="1699180023" label="PaymentRequestOptionalTotal:disabled"/> <int value="1699182601" label="DockedMagnifier:disabled"/> <int value="1700394127" label="OverlayScrollbar:disabled"/> @@ -42209,6 +42210,7 @@ <int value="1971964569" label="NewEncodeCpuLoadEstimator:disabled"/> <int value="1972232935" label="DisplayMoveWindowAccels:enabled"/> <int value="1972720114" label="WebPaymentsJustInTimePaymentApp:enabled"/> + <int value="1973376634" label="WebXRMultiGpu:enabled"/> <int value="1974565950" label="enable-experimental-accessibility-labels"/> <int value="1974776131" label="MediaFeeds:disabled"/> <int value="1975657253" label="ScalableAppList:disabled"/> @@ -67915,9 +67917,8 @@ <enum name="UkmEventNameHash"> <!-- Placeholder enum. The values are UKM event name hashes truncated to 31 - bits. --> - -<!-- TODO(jwd@chromium.org): Automatically populate this enum from ukm.xml. --> + bits. This gets populated by the GetEnumsNodes function in merge_xml.py + when producing the merged XML file. --> </enum> @@ -71273,6 +71274,7 @@ <int value="46" label="Portal"/> <int value="47" label="SpeechRecognizer"/> <int value="48" label="IdleManager"/> + <int value="49" label="PaymentManager"/> </enum> <enum name="WebShareMethod">
diff --git a/tools/metrics/histograms/histogram_paths.py b/tools/metrics/histograms/histogram_paths.py index 668ed93f..4c65c102 100644 --- a/tools/metrics/histograms/histogram_paths.py +++ b/tools/metrics/histograms/histogram_paths.py
@@ -16,3 +16,11 @@ ] ALL_XMLS = [path_util.GetInputFile(f) for f in ALL_XMLS_RELATIVE] ENUMS_XML, HISTOGRAMS_XML = ALL_XMLS + +ALL_TEST_XMLS_RELATIVE = [ + 'tools/metrics/histograms/test_data/enums.xml', + 'tools/metrics/histograms/test_data/histograms.xml', + 'tools/metrics/histograms/test_data/ukm.xml', +] +ALL_TEST_XMLS = [path_util.GetInputFile(f) for f in ALL_TEST_XMLS_RELATIVE] +TEST_ENUMS_XML, TEST_HISTOGRAMS_XML, TEST_UKM_XML = ALL_TEST_XMLS \ No newline at end of file
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4b0853a3..b271f68 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -116,7 +116,7 @@ </histogram> <histogram name="Accessibility.CaptionSettingsLoadedFromPrefs" - enum="BooleanEnabled" expires_after="M85"> + enum="BooleanEnabled" expires_after="2020-12-01"> <owner>evliu@google.com</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -126,7 +126,7 @@ </histogram> <histogram name="Accessibility.CaptionSettingsLoadedFromSystemSettings" - enum="BooleanEnabled" expires_after="M85"> + enum="BooleanEnabled" expires_after="2020-12-01"> <owner>evliu@google.com</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -147,7 +147,7 @@ </histogram> <histogram name="Accessibility.CrosAutoclick" enum="BooleanEnabled" - expires_after="M85"> + expires_after="2021-06-01"> <owner>dmazzoni@chromium.org</owner> <owner>kenjibaheux@google.com</owner> <owner>dtseng@chromium.org</owner> @@ -860,7 +860,7 @@ </histogram> <histogram name="Accessibility.VTTContainsStyleBlock" enum="BooleanEnabled" - expires_after="M85"> + expires_after="2020-12-01"> <owner>evliu@google.com</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -5193,7 +5193,7 @@ </histogram> <histogram name="Android.WebView.onReceivedError.ErrorCode" - enum="WebViewClientErrorCode" expires_after="2020-04-11"> + enum="WebViewClientErrorCode" expires_after="2021-04-11"> <owner>timvolodine@chromium.org</owner> <owner>tobiasjs@chromium.org</owner> <owner>ntfschr@chromium.org</owner> @@ -5205,7 +5205,7 @@ </histogram> <histogram name="Android.WebView.onReceivedHttpError.StatusCode" - enum="HttpResponseCode" expires_after="2020-04-11"> + enum="HttpResponseCode" expires_after="2021-04-11"> <owner>timvolodine@chromium.org</owner> <owner>tobiasjs@chromium.org</owner> <owner>ntfschr@chromium.org</owner> @@ -5358,7 +5358,7 @@ </histogram> <histogram name="Android.WebView.Startup.DataDirLockAttempts" units="attempts" - expires_after="2020-09-30"> + expires_after="2020-12-10"> <owner>torne@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> <summary> @@ -5369,7 +5369,7 @@ </histogram> <histogram name="Android.WebView.Startup.InitAlreadyStarted" enum="Boolean" - expires_after="2020-09-30"> + expires_after="2020-12-10"> <owner>torne@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> <summary> @@ -12643,7 +12643,7 @@ </histogram> <histogram name="AuthPolicy.ErrorTypeOfAutoTgtRenewal" - enum="AuthPolicyErrorType" expires_after="M85"> + enum="AuthPolicyErrorType" expires_after="M88"> <owner>fsandrade@chromium.org</owner> <owner>tomdobro@chromium.org</owner> <summary> @@ -12662,7 +12662,7 @@ </histogram> <histogram name="AuthPolicy.ErrorTypeOfGetUserStatus" - enum="AuthPolicyErrorType" expires_after="M85"> + enum="AuthPolicyErrorType" expires_after="M88"> <owner>fsandrade@chromium.org</owner> <owner>tomdobro@chromium.org</owner> <summary> @@ -12672,7 +12672,7 @@ </histogram> <histogram name="AuthPolicy.ErrorTypeOfJoinADDomain" enum="AuthPolicyErrorType" - expires_after="2020-09-27"> + expires_after="M88"> <owner>fsandrade@chromium.org</owner> <owner>tomdobro@chromium.org</owner> <summary> @@ -12786,8 +12786,7 @@ </summary> </histogram> -<histogram name="AuthPolicy.TimeToJoinADDomain" units="ms" - expires_after="2020-09-27"> +<histogram name="AuthPolicy.TimeToJoinADDomain" units="ms" expires_after="M88"> <owner>fsandrade@chromium.org</owner> <owner>tomdobro@chromium.org</owner> <summary> @@ -42209,7 +42208,7 @@ </histogram> <histogram name="DocumentScan.ScanResult" enum="BooleanSuccess" - expires_after="M85"> + expires_after="M90"> <owner>fletcherw@chromium.org</owner> <owner>bmgordon@chromium.org</owner> <summary> @@ -48160,9 +48159,9 @@ </histogram> <histogram name="EnterpriseCheck.InDomain" enum="BooleanEnabled" - expires_after="M85"> - <owner>mnissler@chromium.org</owner> + expires_after="2021-05-31"> <owner>pastarmovj@chromium.org</owner> + <owner>rogerta@chromium.org</owner> <summary> Whether the machine is part of an AD domain. This check is performed once at start-up on Windows. @@ -57756,6 +57755,20 @@ </histogram> <histogram + name="Extensions.SettingsOverridden.BackToGoogleNtpOverriddenDialogResult" + enum="SettingsOverriddenDialogResult" expires_after="2021-05-01"> + <owner>rdevlin.cronin@chromium.org</owner> + <owner>extensions-core@chromium.org</owner> + <summary> + The action taken on the settings overridden dialog that was shown to alert + the user of an extension overriding the New Tab Page, when the dialog shown + is the version that asks the user if they want to go back to Google's New + Tab Page. Recorded once per instance of the dialog being shown, after the + action is taken. + </summary> +</histogram> + +<histogram name="Extensions.SettingsOverridden.GenericNtpOverriddenDialogResult" enum="SettingsOverriddenDialogResult" expires_after="2021-05-01"> <owner>rdevlin.cronin@chromium.org</owner> @@ -64464,7 +64477,7 @@ </histogram> <histogram name="GPU.WatchdogThread.WaitTime.NumOfUsers" units="seconds" - expires_after="2020-07-06"> + expires_after="2020-12-06"> <owner>magchen@chromium.org</owner> <owner>zmo@chromium.org</owner> <summary> @@ -64476,7 +64489,7 @@ </histogram> <histogram name="GPU.WatchdogThread.WaitTime.ProgressAfterWait" units="seconds" - expires_after="2020-07-06"> + expires_after="2020-12-06"> <owner>magchen@chromium.org</owner> <owner>zmo@chromium.org</owner> <summary> @@ -67781,6 +67794,17 @@ </summary> </histogram> +<histogram name="InputMethod.Assistive.EmojiSuggestAddition.AcceptanceIndex" + units="times" expires_after="2021-01-01"> + <owner>myy@google.com</owner> + <owner>essential-inputs-team@google.com</owner> + <summary> + The number of times an emoji suggest addition is accepted at a given index. + Recorded when an user accepts an emoji suggestion appeared after typing an + emoji-triggered word. + </summary> +</histogram> + <histogram name="InputMethod.Assistive.Match" enum="IMEAssistiveAction" expires_after="2021-01-01"> <owner>jiwan@google.com</owner> @@ -73147,10 +73171,9 @@ </histogram> <histogram name="ManagedUsers.FilteringResult" - enum="SupervisedUserSafetyFilterResult" expires_after="M85"> - <owner>treib@chromium.org</owner> - <owner>escordeiro@chromium.org</owner> - <owner>menegola@chromium.org</owner> + enum="SupervisedUserSafetyFilterResult" expires_after="2021-06-02"> + <owner>agawronska@chromium.org</owner> + <owner>cros-families@google.com</owner> <summary> The counts of results from supervised user URL filtering. Each entry includes the outcome of the filter (i.e. allowed, blocked, or unknown) and @@ -73228,10 +73251,9 @@ </histogram> <histogram name="ManagedUsers.Whitelist.Count" units="whitelists" - expires_after="M85"> - <owner>treib@chromium.org</owner> - <owner>escordeiro@chromium.org</owner> - <owner>menegola@chromium.org</owner> + expires_after="2021-06-02"> + <owner>agawronska@chromium.org</owner> + <owner>cros-families@google.com</owner> <summary> The number of whitelists installed for a supervised user. Recorded at every profile startup. @@ -73312,8 +73334,9 @@ </histogram> <histogram name="ManualFallback.PresentedOptions.AllPasswords" - units="Credentials" expires_after="2020-10-11"> + units="Credentials" expires_after="2021-01-15"> <owner>javierrobles@chromium.org</owner> + <owner>gambard@chromium.org</owner> <summary> Tracks the number of credentials presented to the user in the "Use other password..." view in Manual Fallback. This is logged everytime @@ -73322,8 +73345,9 @@ </histogram> <histogram name="ManualFallback.PresentedOptions.CreditCards" units="Cards" - expires_after="2020-10-11"> + expires_after="2021-01-15"> <owner>javierrobles@chromium.org</owner> + <owner>gambard@chromium.org</owner> <summary> Tracks the number of cards presented to the user in Manual Fallback. This is logged everytime the user opens this view. @@ -73331,8 +73355,9 @@ </histogram> <histogram name="ManualFallback.PresentedOptions.Passwords" units="Credentials" - expires_after="2020-10-11"> + expires_after="2021-01-15"> <owner>javierrobles@chromium.org</owner> + <owner>gambard@chromium.org</owner> <summary> Tracks the number of credentials presented to the user in the Passwords Manual Fallback view. This is logged everytime the user opens this view. @@ -73340,8 +73365,9 @@ </histogram> <histogram name="ManualFallback.PresentedOptions.Profiles" units="Profiles" - expires_after="2020-10-11"> + expires_after="2021-01-15"> <owner>javierrobles@chromium.org</owner> + <owner>gambard@chromium.org</owner> <summary> Tracks the number of profiles presented to the user in Manual Fallback. This is logged everytime the user opens this view. @@ -73349,8 +73375,9 @@ </histogram> <histogram name="ManualFallback.VisibleSuggestions.OpenCreditCards" - units="Suggestions" expires_after="2020-06-30"> + units="Suggestions" expires_after="2021-01-15"> <owner>javierrobles@chromium.org</owner> + <owner>gambard@chromium.org</owner> <summary> Tracks the number of autofill suggestions present when the user taps on the credit card button in manual fallback. @@ -73358,8 +73385,9 @@ </histogram> <histogram name="ManualFallback.VisibleSuggestions.OpenPasswords" - units="Suggestions" expires_after="2020-06-30"> + units="Suggestions" expires_after="2021-01-15"> <owner>javierrobles@chromium.org</owner> + <owner>gambard@chromium.org</owner> <summary> Tracks the number of password suggestions present when the user taps on the password button in manual fallback. @@ -73367,8 +73395,9 @@ </histogram> <histogram name="ManualFallback.VisibleSuggestions.OpenProfiles" - units="Suggestions" expires_after="2020-06-30"> + units="Suggestions" expires_after="2021-01-15"> <owner>javierrobles@chromium.org</owner> + <owner>gambard@chromium.org</owner> <summary> Tracks the number of autofill suggestions present when the user taps on the profiles (address) button in manual fallback. @@ -79839,7 +79868,7 @@ </histogram> <histogram name="Media.WebMediaPlayerImpl.HLS.HasAccessControl" enum="Boolean" - expires_after="2020-06-07"> + expires_after="2021-06-01"> <owner>sandersd@chromium.org</owner> <owner>tguilbert@chromium.org</owner> <summary> @@ -79851,7 +79880,7 @@ </histogram> <histogram name="Media.WebMediaPlayerImpl.HLS.IsCorsCrossOrigin" enum="Boolean" - expires_after="2020-04-05"> + expires_after="2021-06-01"> <owner>sandersd@chromium.org</owner> <owner>tguilbert@chromium.org</owner> <summary> @@ -79863,7 +79892,7 @@ </histogram> <histogram name="Media.WebMediaPlayerImpl.HLS.IsMixedContent" enum="Boolean" - expires_after="2020-04-05"> + expires_after="2021-06-01"> <owner>sandersd@chromium.org</owner> <owner>tguilbert@chromium.org</owner> <summary> @@ -88263,7 +88292,7 @@ </histogram> <histogram base="true" name="NavigationPredictor.CountOfURLsInPredictedSet" - units="count" expires_after="M85"> + units="count" expires_after="M89"> <owner>tbansal@chromium.org</owner> <owner>ryansturm@chromium.org</owner> <summary> @@ -99597,8 +99626,9 @@ </histogram> <histogram name="Net.SSLHandshakeDetails" enum="SSLHandshakeDetails" - expires_after="M85"> + expires_after="2021-06-01"> <owner>davidben@chromium.org</owner> + <owner>src/net/OWNERS</owner> <summary> For each successful TLS handshake, what kind of handshake was used. This metric distinguishes TLS 1.2 (or earlier) and TLS 1.3 as they have very @@ -99608,11 +99638,10 @@ </histogram> <histogram name="Net.SSLHandshakeEarlyDataReason" - enum="SSLHandshakeEarlyDataReason" expires_after="M85"> -<!-- expires-never: Used to keep track of the TLS ecosystem. --> - + enum="SSLHandshakeEarlyDataReason" expires_after="2021-06-01"> <owner>davidben@chromium.org</owner> <owner>svaldez@chromium.org</owner> + <owner>src/net/OWNERS</owner> <summary> Indicates whether a TLS 1.3 connection with 0-RTT enabled ended up using 0-RTT or not, and why; this includes reasons such as the server declining to @@ -99810,8 +99839,11 @@ </histogram> <histogram name="Net.SSLSignatureAlgorithm" enum="SSLSignatureAlgorithm" - expires_after="M85"> + expires_after="never"> +<!-- expires-never: Used to keep track of the TLS ecosystem. --> + <owner>davidben@chromium.org</owner> + <owner>src/net/OWNERS</owner> <summary> For each SSL connection with a full handshake using a DHE- or ECDHE-based key exchange, the signature algorithm used to authenticate the peer. In TLS @@ -100562,7 +100594,7 @@ </histogram> <histogram name="Net.WebSocket.CloseCode" enum="WebSocketCloseCode" - expires_after="M85"> + expires_after="M86"> <owner>ricea@chromium.org</owner> <owner>yhirano@chromium.org</owner> <owner>yoichio@chromium.org</owner> @@ -103083,7 +103115,10 @@ <histogram name="Network.Shill.WiFi.FrequenciesConnectedEver" units="units" expires_after="M85"> - <owner>kirtika@chromium.org</owner> + <obsolete> + Removed 06/2020. + </obsolete> + <owner>briannorris@chromium.org</owner> <owner>cros-network-metrics@google.com</owner> <summary> Chrome OS metric sampling the number of different frequencies (i.e. @@ -109360,6 +109395,7 @@ <histogram name="OfflinePages.Background.EffectiveConnectionType.PauseRequests" enum="NQEEffectiveConnectionType" expires_after="M77"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Effective connection type when pausing one or more background loads is requested. @@ -109372,6 +109408,7 @@ name="OfflinePages.Background.EffectiveConnectionType.RemoveRequests" enum="NQEEffectiveConnectionType" expires_after="M78"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Effective connection type when removing one or more background loads is requested. @@ -109384,6 +109421,7 @@ name="OfflinePages.Background.EffectiveConnectionType.ResumeRequests" enum="NQEEffectiveConnectionType" expires_after="M78"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Effective connection type when resuming one or more background loads is requested. @@ -109393,8 +109431,9 @@ </histogram> <histogram name="OfflinePages.Background.EffectiveConnectionType.SavePageLater" - enum="NQEEffectiveConnectionType" expires_after="M85"> + enum="NQEEffectiveConnectionType" expires_after="2021-03-01"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Effective connection type when a background load is requested. @@ -109413,6 +109452,7 @@ <histogram name="OfflinePages.Background.ImmediateStart.AvailableRequestCount" units="units" expires_after="M77"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of queued background load requests available for processing when processing starts immediately (vs. scheduled). This is for non-svelte @@ -109424,6 +109464,7 @@ name="OfflinePages.Background.ImmediateStart.AvailableRequestCount.Svelte" units="units" expires_after="M85"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of queued background load requests available for processing when processing starts immediately (vs. scheduled). This is for svelte devices @@ -109435,6 +109476,7 @@ name="OfflinePages.Background.ImmediateStart.UnavailableRequestCount" units="units" expires_after="M78"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of queued background load requests unavailable for processing when processing starts immediately (vs. scheduled). This is for non-svelte @@ -109446,6 +109488,7 @@ name="OfflinePages.Background.ImmediateStart.UnavailableRequestCount.Svelte" units="units" expires_after="M85"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of queued background load requests unavailable for processing when processing starts immediately (vs. scheduled). This is for svelte devices @@ -109456,6 +109499,7 @@ <histogram name="OfflinePages.Background.ImmediateStartStatus" enum="OfflinePagesBackgroundImmediateStartStatus" expires_after="M77"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Status of attempt to immediately start offlining a page in the background while application is still concurrently using the foreground. This may be @@ -109472,8 +109516,10 @@ </histogram> <histogram name="OfflinePages.Background.OfflinerRequestStatus" - enum="OfflinePagesBackgroundOfflinerRequestStatus" expires_after="M85"> + enum="OfflinePagesBackgroundOfflinerRequestStatus" + expires_after="2021-03-01"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Status code of background offlining (loading and saving) requests. </summary> @@ -109491,6 +109537,7 @@ <histogram name="OfflinePages.Background.RequestFailure.StartedAttemptCount" units="units" expires_after="M77"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of started attempts by failed background load requests. </summary> @@ -109499,6 +109546,7 @@ <histogram name="OfflinePages.Background.RequestSuccess.StartedAttemptCount" units="units" expires_after="M77"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of started attempts by successful background load requests. </summary> @@ -109546,6 +109594,7 @@ <histogram name="OfflinePages.Background.ScheduledStart.AvailableRequestCount" units="units" expires_after="M77"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of queued background load requests available for processing when background scheduled processing starts. This is for non-svelte devices @@ -109557,6 +109606,7 @@ name="OfflinePages.Background.ScheduledStart.AvailableRequestCount.Svelte" units="units" expires_after="M78"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of queued background load requests available for processing when background scheduled processing starts. This is for svelte devices (where @@ -109568,6 +109618,7 @@ name="OfflinePages.Background.ScheduledStart.UnavailableRequestCount" units="units" expires_after="M78"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of queued background load requests unavailable for processing when background scheduled processing starts. This is for non-svelte devices @@ -109579,6 +109630,7 @@ name="OfflinePages.Background.ScheduledStart.UnavailableRequestCount.Svelte" units="units" expires_after="M78"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Number of queued background load requests unavailable for processing when background scheduled processing starts. This is for svelte devices (where @@ -109587,22 +109639,25 @@ </histogram> <histogram name="OfflinePages.Background.TimeToCanceled" units="seconds" - expires_after="M85"> + expires_after="2021-03-01"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary>Time from background request until it was canceled.</summary> </histogram> <histogram name="OfflinePages.Background.TimeToSaved" units="seconds" - expires_after="M85"> + expires_after="2021-03-01"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Time from background request until it was successfully saved. </summary> </histogram> <histogram name="OfflinePages.Background.TimeToStart" units="ms" - expires_after="M85"> + expires_after="2021-03-01"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Time from background request until processing it was first started. This is for non-svelte devices. @@ -109610,8 +109665,9 @@ </histogram> <histogram name="OfflinePages.Background.TimeToStart.Svelte" units="ms" - expires_after="M85"> + expires_after="2021-03-01"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Time from background request until processing it was first started on svelte device. Svelte is determined by base::SysInfo::IsLowEnd(). @@ -109621,6 +109677,7 @@ <histogram name="OfflinePages.Background.UnsupportedScheme.ConnectionType" enum="NetworkConnectionType" expires_after="M85"> <owner>dougarnett@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Connection type when prerenderer reports Unsupported Scheme error. @@ -123780,16 +123837,18 @@ </histogram> <histogram name="PerformanceMonitor.IdleWakeups" units="WakeupsPerSecond" - expires_after="M85"> + expires_after="2021-06-03"> <owner>lgrey@chromium.org</owner> + <owner>markchang@chromium.org</owner> <summary> The average CPU idle wakeups per second, sampled every two minutes. </summary> </histogram> <histogram name="PerformanceMonitor.PackageExitIdleWakeups" - units="WakeupsPerSecond" expires_after="M85"> + units="WakeupsPerSecond" expires_after="2021-07-03"> <owner>lgrey@chromium.org</owner> + <owner>markchang@chromium.org</owner> <summary> (Mac only) The average package exit idle wakeups per second, sampled every two minutes. This is a subset of wakeups that indicate that the processor @@ -125092,8 +125151,9 @@ </histogram> <histogram name="Platform.Crouton.Started" enum="Platform.Crouton.Started" - expires_after="M85"> + expires_after="2021-06-02"> <owner>drinkcat@chromium.org</owner> + <owner>dnschneid@chromium.org</owner> <summary> Detects presence of /run/crouton, indicating that crouton has been started since the previous boot. Value 0/"Total count" is reported on @@ -125132,8 +125192,10 @@ </histogram> <histogram name="Platform.DetachableBase.ActivePercent" units="%" - expires_after="M85"> - <owner>kitching@google.com</owner> + expires_after="2021-06-02"> + <owner>drinkcat@chromium.org</owner> + <owner>fshao@chromium.org</owner> + <owner>chromeos-kukui@google.com</owner> <summary> Ratio of time a detachable base keyboard is active, i.e. when the USB interface is not auto-suspended. Reported every 30 seconds when the base is @@ -125142,8 +125204,10 @@ </histogram> <histogram name="Platform.DetachableBase.AttachedOnBoot" enum="BooleanAttached" - expires_after="M85"> - <owner>kitching@google.com</owner> + expires_after="2021-06-02"> + <owner>drinkcat@chromium.org</owner> + <owner>fshao@chromium.org</owner> + <owner>chromeos-kukui@google.com</owner> <summary> For devices with a detachable base: whether or not the base is connected on boot. Recorded by upstart task on boot. @@ -125151,14 +125215,18 @@ </histogram> <histogram name="Platform.DetachableBase.PairResult" - enum="DetachableBasePairResult" expires_after="M85"> - <owner>kitching@google.com</owner> + enum="DetachableBasePairResult" expires_after="2021-06-02"> + <owner>drinkcat@chromium.org</owner> + <owner>fshao@chromium.org</owner> + <owner>chromeos-kukui@google.com</owner> <summary>Result of a detachable base pair operation.</summary> </histogram> <histogram name="Platform.DetachableBase.PendingRWUpdate" - enum="DetachableBasePendingRWUpdate" expires_after="M85"> - <owner>kitching@google.com</owner> + enum="DetachableBasePendingRWUpdate" expires_after="2021-06-02"> + <owner>drinkcat@chromium.org</owner> + <owner>fshao@chromium.org</owner> + <owner>chromeos-kukui@google.com</owner> <summary> Detachable base firmware updates can be configured to only occur on boot. In this mode, any update will be considered "pending" until the @@ -125174,14 +125242,18 @@ </histogram> <histogram name="Platform.DetachableBase.ROUpdateResult" - enum="DetachableBaseROUpdateResult" expires_after="M85"> - <owner>kitching@google.com</owner> + enum="DetachableBaseROUpdateResult" expires_after="2021-06-02"> + <owner>drinkcat@chromium.org</owner> + <owner>fshao@chromium.org</owner> + <owner>chromeos-kukui@google.com</owner> <summary>Result of a detachable base RO firmware update.</summary> </histogram> <histogram name="Platform.DetachableBase.RWUpdateResult" - enum="DetachableBaseRWUpdateResult" expires_after="M85"> - <owner>kitching@google.com</owner> + enum="DetachableBaseRWUpdateResult" expires_after="2021-06-02"> + <owner>drinkcat@chromium.org</owner> + <owner>fshao@chromium.org</owner> + <owner>chromeos-kukui@google.com</owner> <summary>Result of a detachable base RW firmware update.</summary> </histogram> @@ -129569,8 +129641,9 @@ </summary> </histogram> -<histogram base="true" name="Power.Mac" units="mW" expires_after="M85"> +<histogram base="true" name="Power.Mac" units="mW" expires_after="2021-07-03"> <owner>lgrey@chromium.org</owner> + <owner>markchang@chromium.org</owner> <summary> Instantaneous power consution in milliwatts, for the system as a whole and broken down by component. Only recorded on macOS. NB: The collection method @@ -157049,7 +157122,7 @@ </histogram> <histogram name="Signin.InvestigatedScenario" enum="SigninInvestigatedScenario" - expires_after="M85"> + expires_after="M90"> <owner>treib@chromium.org</owner> <owner>mmoskvitin@google.com</owner> <summary> @@ -167023,8 +167096,9 @@ </summary> </histogram> -<histogram name="Sync.CustomSync2" enum="SyncModelTypes" expires_after="M85"> +<histogram name="Sync.CustomSync2" enum="SyncModelTypes" expires_after="M90"> <owner>treib@chromium.org</owner> + <owner>mastiz@chromium.org</owner> <summary> For users who have *not* selected the "Sync Everything" option, this records all the data types they have selected to sync. Samples are @@ -168569,7 +168643,7 @@ </histogram> <histogram name="Sync.PeakAnalysis.StopAfterAccountStateChanged" units="hits" - expires_after="M84"> + expires_after="M88"> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -168583,7 +168657,7 @@ </histogram> <histogram name="Sync.PeakAnalysis.StopAfterCredentialsChanged" units="hits" - expires_after="M84"> + expires_after="M88"> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -168596,7 +168670,7 @@ </histogram> <histogram name="Sync.PeakAnalysis.StopOnSyncManagedPrefChange" units="hits" - expires_after="M84"> + expires_after="M88"> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -168608,7 +168682,7 @@ </histogram> <histogram name="Sync.PeakAnalysis.StopOnSyncPermanentlyDisabled" units="hits" - expires_after="M84"> + expires_after="M88"> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -168719,7 +168793,7 @@ </histogram> <histogram name="Sync.Preferences.ClearedLocalPrefOnTypeMismatch" - units="BooleanHit" expires_after="M85"> + units="BooleanHit" expires_after="M88"> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -168731,6 +168805,9 @@ <histogram name="Sync.Preferences.RemotePrefTypeMismatch" units="BooleanHit" expires_after="M85"> + <obsolete> + Removed 2020-06. + </obsolete> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -169034,6 +169111,9 @@ <histogram name="Sync.SessionsBadForeignHashOnMergeCount" units="Sessions Entries" expires_after="M85"> + <obsolete> + Removed as of 2018-11. + </obsolete> <owner>mastiz@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -169085,6 +169165,9 @@ </histogram> <histogram name="Sync.SessionWindows" units="windows" expires_after="M85"> + <obsolete> + Removed as of 2018-11. + </obsolete> <owner>mastiz@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -169200,7 +169283,7 @@ </summary> </histogram> -<histogram name="Sync.Startup.TimeDeferred2" units="ms" expires_after="M85"> +<histogram name="Sync.Startup.TimeDeferred2" units="ms" expires_after="M88"> <owner>mastiz@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -169328,6 +169411,7 @@ <histogram name="Sync.SyncEverything2" enum="Boolean" expires_after="2020-11-29"> <owner>treib@chromium.org</owner> + <owner>mastiz@chromium.org</owner> <summary> Boolean histogram for whether the "Sync Everything" option was selected by the user. Samples are taken every time the Sync data types are @@ -172278,7 +172362,9 @@ </summary> </histogram> -<histogram name="Tabs.TabCountActiveWindow" units="tabs" expires_after="M85"> +<histogram name="Tabs.TabCountActiveWindow" units="tabs" expires_after="never"> +<!-- expires-never: usage drives tab optimization and analysis. --> + <owner>markchang@google.com</owner> <summary> The number of tabs open in the active window when a load completes.
diff --git a/tools/metrics/histograms/merge_xml.py b/tools/metrics/histograms/merge_xml.py index 5a301942..a0c89941 100755 --- a/tools/metrics/histograms/merge_xml.py +++ b/tools/metrics/histograms/merge_xml.py
@@ -6,10 +6,13 @@ """A script to merge multiple source xml files into a single histograms.xml.""" import argparse +import os +import sys import xml.dom.minidom import expand_owners import extract_histograms +import populate_enums def GetElementsByTagName(trees, tag): @@ -25,6 +28,32 @@ return list(e for t in trees for e in iterator(t, tag, 2)) +def GetEnumsNodes(doc, trees): + """Gets all enums from a set of DOM trees. + + If trees contain ukm events, populates a list of ints to the + "UkmEventNameHash" enum where each value is a ukm event name hash truncated + to 31 bits and each label is the corresponding event name. + + Args: + doc: The document to create the node in. + trees: A list of DOM trees. + Returns: + A list of enums DOM nodes. + """ + enums_list = GetElementsByTagName(trees, 'enums') + ukm_events = GetElementsByTagName( + GetElementsByTagName(trees, 'ukm-configuration'), 'event') + # Early return if there are not ukm events provided. MergeFiles have callers + # that do not pass ukm events so, in that case, we don't need to iterate + # the enum list. + if not ukm_events: + return enums_list + for enums in enums_list: + populate_enums.PopulateEnumsWithUkmEvents(doc, enums, ukm_events) + return enums_list + + def MakeNodeWithChildren(doc, tag, children): """Creates a DOM node with specified tag and child nodes. @@ -55,7 +84,7 @@ doc.appendChild(MakeNodeWithChildren(doc, 'histogram-configuration', # This can result in the merged document having multiple <enums> and # similar sections, but scripts ignore these anyway. - GetElementsByTagName(trees, 'enums') + + GetEnumsNodes(doc, trees) + GetElementsByTagName(trees, 'histograms') + GetElementsByTagName(trees, 'histogram_suffixes_list'))) return doc
diff --git a/tools/metrics/histograms/merge_xml_test.py b/tools/metrics/histograms/merge_xml_test.py new file mode 100644 index 0000000..36f469abd --- /dev/null +++ b/tools/metrics/histograms/merge_xml_test.py
@@ -0,0 +1,153 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import unittest + +import xml.dom.minidom + +import histogram_paths +import merge_xml + + +class MergeXmlTest(unittest.TestCase): + + def testMergeFiles(self): + """Checks that enums.xml and histograms.xml can merge successfully.""" + merged = merge_xml.MergeFiles( + [histogram_paths.TEST_ENUMS_XML, histogram_paths.TEST_HISTOGRAMS_XML]) + # If ukm.xml is not provided, there is no need to populate the + # UkmEventNameHash enum. + expected_merged = xml.dom.minidom.parseString(""" +<histogram-configuration><enums> + +<enum name="Enum1"> + <int label="Value0" value="0"/> + <int label="Value1" value="1"/> +</enum> + +<enum name="TestEnum"> + <int label="Value0" value="0"/> + <int label="Value1" value="1"/> +</enum> + +<enum name="UkmEventNameHash"> +<!-- Placeholder enum. The values are UKM event name hashes truncated to 31 + bits. This gets populated by the GetEnumsNodes function in merge_xml.py + when producing the merged XML file. --> + +</enum> + +</enums><histograms> + +<histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz"> + <summary>Foo</summary> + <owner>person@chromium.org</owner> + <component>Component</component> +</histogram> + +<histogram name="Test.Histogram" units="microseconds"> + <obsolete> + Removed 6/2020. + </obsolete> + <owner>person@chromium.org</owner> + <summary> + Summary 2 + </summary> +</histogram> + +<histogram name="Test.EnumHistogram" enum="TestEnum" expires_after="M81"> + <owner>uma@chromium.org</owner> + <obsolete> + Obsolete message + </obsolete> + <summary> + A enum histogram. + </summary> +</histogram> + +</histograms><histogram_suffixes_list> + +<histogram_suffixes name="Test.HistogramSuffixes" separator="."> + <suffix label="A histogram_suffixes" name="TestSuffix"/> + <affected-histogram name="Test.Histogram"/> +</histogram_suffixes> + +</histogram_suffixes_list></histogram-configuration> +""") + self.maxDiff = None + self.assertEqual(expected_merged.toxml(), merged.toxml()) + + def testMergeFiles_WithXmlEvents(self): + """Checks that the UkmEventNameHash enum is populated correctly. + + If ukm.xml is provided, populate a list of ints to the UkmEventNameHash enum + where where each value is a xml event name hash truncated to 31 bits and + each label is the corresponding event name. + """ + merged = merge_xml.MergeFiles(histogram_paths.ALL_TEST_XMLS) + expected_merged = xml.dom.minidom.parseString(""" +<histogram-configuration><enums> + +<enum name="Enum1"> + <int label="Value0" value="0"/> + <int label="Value1" value="1"/> +</enum> + +<enum name="TestEnum"> + <int label="Value0" value="0"/> + <int label="Value1" value="1"/> +</enum> + +<enum name="UkmEventNameHash"> +<!-- Placeholder enum. The values are UKM event name hashes truncated to 31 + bits. This gets populated by the GetEnumsNodes function in merge_xml.py + when producing the merged XML file. --> + +<int label="AbusiveExperienceHeuristic.TabUnder" value="1621538456"/>\ +<int label="Autofill.SelectedMaskedServerCard (Obsolete)" value="1913876024"/>\ +</enum> + +</enums><histograms> + +<histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz"> + <summary>Foo</summary> + <owner>person@chromium.org</owner> + <component>Component</component> +</histogram> + +<histogram name="Test.Histogram" units="microseconds"> + <obsolete> + Removed 6/2020. + </obsolete> + <owner>person@chromium.org</owner> + <summary> + Summary 2 + </summary> +</histogram> + +<histogram name="Test.EnumHistogram" enum="TestEnum" expires_after="M81"> + <owner>uma@chromium.org</owner> + <obsolete> + Obsolete message + </obsolete> + <summary> + A enum histogram. + </summary> +</histogram> + +</histograms><histogram_suffixes_list> + +<histogram_suffixes name="Test.HistogramSuffixes" separator="."> + <suffix label="A histogram_suffixes" name="TestSuffix"/> + <affected-histogram name="Test.Histogram"/> +</histogram_suffixes> + +</histogram_suffixes_list></histogram-configuration> +""") + self.maxDiff = None + self.assertEqual(expected_merged.toxml(), merged.toxml()) + + +if __name__ == '__main__': + unittest.main()
diff --git a/tools/metrics/histograms/populate_enums.py b/tools/metrics/histograms/populate_enums.py new file mode 100644 index 0000000..b3e261c --- /dev/null +++ b/tools/metrics/histograms/populate_enums.py
@@ -0,0 +1,50 @@ +# 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. + +"""Functions for populating enums with ukm events.""" + +import os +import sys +import xml.dom.minidom + +import extract_histograms + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'ukm')) +import codegen + + +def PopulateEnumWithUkmEvents(doc, enum, ukm_events): + """Populates the enum node with a list of ukm events. + + Args: + doc: The document to create the node in. + enum: The enum node needed to be populated. + ukm_events: A list of ukm event nodes. + """ + for event in ukm_events: + node = doc.createElement('int') + event_name = event.getAttribute('name') + # The value is UKM event name hash truncated to 31 bits. This is recorded in + # https://cs.chromium.org/chromium/src/components/ukm/ukm_recorder_impl.cc?rcl=728ad079d8e52ada4e321fb4f53713e4f0588072&l=114 + node.attributes['value'] = str(codegen.HashName(event_name) & 0x7fffffff) + label = event_name + # If the event is obsolete, mark it in the int's label. + if event.getElementsByTagName('obsolete'): + label += ' (Obsolete)' + node.attributes['label'] = label + enum.appendChild(node) + + +def PopulateEnumsWithUkmEvents(doc, enums, ukm_events): + """Populates enum nodes in the enums with a list of ukm events + + Args: + doc: The document to create the node in. + enums: The enums node to be iterated. + ukm_events: A list of ukm event nodes. + """ + for enum in extract_histograms.IterElementsWithTag(enums, 'enum', 1): + # We only special case 'UkmEventNameHash' currently. + if enum.getAttribute('name') == 'UkmEventNameHash': + PopulateEnumWithUkmEvents(doc, enum, ukm_events) \ No newline at end of file
diff --git a/tools/metrics/histograms/test_data/enums.xml b/tools/metrics/histograms/test_data/enums.xml new file mode 100644 index 0000000..cf4d1b7 --- /dev/null +++ b/tools/metrics/histograms/test_data/enums.xml
@@ -0,0 +1,26 @@ +<histogram-configuration> + + <!-- Enum types --> + +<enums> + +<enum name="Enum1"> + <int value="0" label="Value0"/> + <int value="1" label="Value1"/> +</enum> + +<enum name="TestEnum"> + <int value="0" label="Value0"/> + <int value="1" label="Value1"/> +</enum> + +<enum name="UkmEventNameHash"> +<!-- Placeholder enum. The values are UKM event name hashes truncated to 31 + bits. This gets populated by the GetEnumsNodes function in merge_xml.py + when producing the merged XML file. --> + +</enum> + +</enums> + +</histogram-configuration> \ No newline at end of file
diff --git a/tools/metrics/histograms/test_data/histograms.xml b/tools/metrics/histograms/test_data/histograms.xml new file mode 100644 index 0000000..1830b90 --- /dev/null +++ b/tools/metrics/histograms/test_data/histograms.xml
@@ -0,0 +1,44 @@ +<histogram-configuration> + + <!-- Second level Comment 1 --> + +<histograms> + +<histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz"> + <summary>Foo</summary> + <owner>person@chromium.org</owner> + <component>Component</component> +</histogram> + +<histogram name="Test.Histogram" units="microseconds"> + <obsolete> + Removed 6/2020. + </obsolete> + <owner>person@chromium.org</owner> + <summary> + Summary 2 + </summary> +</histogram> + +<histogram name="Test.EnumHistogram" enum="TestEnum" expires_after="M81"> + <owner>uma@chromium.org</owner> + <obsolete> + Obsolete message + </obsolete> + <summary> + A enum histogram. + </summary> +</histogram> + +</histograms> + +<histogram_suffixes_list> + +<histogram_suffixes name="Test.HistogramSuffixes" separator="."> + <suffix name="TestSuffix" label="A histogram_suffixes"/> + <affected-histogram name="Test.Histogram"/> +</histogram_suffixes> + +</histogram_suffixes_list> + +</histogram-configuration> \ No newline at end of file
diff --git a/tools/metrics/histograms/test_data/ukm.xml b/tools/metrics/histograms/test_data/ukm.xml new file mode 100644 index 0000000..ab6eb89f --- /dev/null +++ b/tools/metrics/histograms/test_data/ukm.xml
@@ -0,0 +1,27 @@ +<ukm-configuration> + +<event name="AbusiveExperienceHeuristic.TabUnder"> + <owner>csharrison@chromium.org</owner> + <metric name="DidTabUnder"> + <summary> + True if the page attempted a tab-under navigation. + </summary> + </metric> +</event> + +<event name="Autofill.SelectedMaskedServerCard"> + <obsolete> + Deprecated 2/2019 + </obsolete> + <owner>jiahuiguo@google.com</owner> + <metric name="MillisecondsSinceFormParsed"> + <summary> + Obsolete. + + Time since form parse. + </summary> + </metric> +</event> + + +</ukm-configuration> \ No newline at end of file
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 0aa2b2a..cb73a9644a 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@ { "trace_processor_shell": { "win": { - "hash": "a6de8e2ee93e5acb4c4b439879218622dc0ba3c9", - "remote_path": "perfetto_binaries/trace_processor_shell/win/9d83693a5ac5ffb0348b6217e9ac4ec587698c69/trace_processor_shell.exe" + "hash": "498eff8c51b4297bf08327846d68a6e782e5d5ff", + "remote_path": "perfetto_binaries/trace_processor_shell/win/84515482ba9ada62afb02d046ad621e91b898885/trace_processor_shell.exe" }, "mac": { "hash": "cdcb1f5b233c5d3472a561a8f567d4927dec850b", "remote_path": "perfetto_binaries/trace_processor_shell/mac/058776deb61c3c6b1022c1e613e69518db32e443/trace_processor_shell" }, "linux": { - "hash": "4187c54b7f72f17ed264b8cc2edd0b02b07e1e34", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/890735b8c86dde8a30b2c0db1d2fe3d1d9c6ee1e/trace_processor_shell" + "hash": "62e341128ce90ac37da1bcc7c391652c053bb159", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/84515482ba9ada62afb02d046ad621e91b898885/trace_processor_shell" } } } \ No newline at end of file
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 0495b70..1ae48a82 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -78,6 +78,7 @@ <item id="devtools_http_handler" hash_code="49160454" type="0" content_hash_code="88414393" os_list="linux,windows" file_path="content/browser/devtools/devtools_http_handler.cc"/> <item id="devtools_interceptor" hash_code="98123737" type="0" deprecated="2019-07-31" content_hash_code="64591843" file_path=""/> <item id="devtools_network_resource" hash_code="129652775" type="0" content_hash_code="32810159" os_list="linux,windows" file_path="chrome/browser/devtools/devtools_ui_bindings.cc"/> + <item id="devtools_proxy_config" hash_code="79904729" type="0" content_hash_code="31996982" os_list="linux,windows" file_path="content/browser/devtools/protocol/target_handler.cc"/> <item id="dial_get_app_info" hash_code="15952025" type="0" deprecated="2018-02-27" content_hash_code="90542080" file_path=""/> <item id="dial_get_device_description" hash_code="50422598" type="0" deprecated="2018-02-27" content_hash_code="129827780" file_path=""/> <item id="dial_url_fetcher" hash_code="41424546" type="0" content_hash_code="129828432" os_list="linux,windows" file_path="chrome/browser/media/router/discovery/dial/dial_url_fetcher.cc"/>
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc index 35bbef5..3d5cd70 100644 --- a/ui/accessibility/ax_enum_util.cc +++ b/ui/accessibility/ax_enum_util.cc
@@ -1884,6 +1884,8 @@ return "clipsChildren"; case ax::mojom::BoolAttribute::kSelected: return "selected"; + case ax::mojom::BoolAttribute::kSelectedFromFocus: + return "selectedFromFocus"; case ax::mojom::BoolAttribute::kSupportsTextLocation: return "supportsTextLocation"; case ax::mojom::BoolAttribute::kIsLineBreakingObject: @@ -1926,6 +1928,8 @@ return ax::mojom::BoolAttribute::kClipsChildren; if (0 == strcmp(bool_attribute, "selected")) return ax::mojom::BoolAttribute::kSelected; + if (0 == strcmp(bool_attribute, "selectedFromFocus")) + return ax::mojom::BoolAttribute::kSelectedFromFocus; if (0 == strcmp(bool_attribute, "supportsTextLocation")) return ax::mojom::BoolAttribute::kSupportsTextLocation; if (0 == strcmp(bool_attribute, "isLineBreakingObject"))
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom index a5c0fc5..2af2772 100644 --- a/ui/accessibility/ax_enums.mojom +++ b/ui/accessibility/ax_enums.mojom
@@ -734,6 +734,9 @@ // Indicates whether this node is selected or unselected. kSelected, + // Indicates whether this node is selected due to selection follows focus. + kSelectedFromFocus, + // Indicates whether this node supports text location. kSupportsTextLocation,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index 7f4a789..4e638e0 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc
@@ -1524,6 +1524,9 @@ case ax::mojom::BoolAttribute::kSelected: result += " selected=" + value; break; + case ax::mojom::BoolAttribute::kSelectedFromFocus: + result += " selected_from_focus=" + value; + break; case ax::mojom::BoolAttribute::kSupportsTextLocation: result += " supports_text_location=" + value; break;
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index 9a8f6f6..8170c252 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -497,6 +497,8 @@ return nil; for (id child in [[self AXChildren] reverseObjectEnumerator]) { + if (!NSPointInRect(point, [child accessibilityFrame])) + continue; if (id foundChild = [child accessibilityHitTest:point]) return foundChild; }
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 7a7e558..076152e 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -2073,7 +2073,23 @@ return UIA_E_ELEMENTNOTENABLED; } - if (selected == ISelectionItemProviderIsSelected()) + // The platform implements selection follows focus for single-selection + // container elements. Focus action can change a node's accessibility selected + // state, but does not cause the actual control to be selected. + // https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_selection_follows_focus + // https://www.w3.org/TR/core-aam-1.2/#mapping_events_selection + // + // We don't want to perform |Action::kDoDefault| for an ax node that has + // |kSelected=true| and |kSelectedFromFocus=false|, because perform + // |Action::kDoDefault| may cause the control to be unselected. However, if an + // ax node is selected due to focus, i.e. |kSelectedFromFocus=true|, we need + // to perform |Action::kDoDefault| on the ax node, since focus action only + // changes an ax node's accessibility selected state to |kSelected=true| and + // no |Action::kDoDefault| was performed on that node yet. So we need to + // perform |Action::kDoDefault| on the ax node to cause its associated control + // to be selected. + if (selected == ISelectionItemProviderIsSelected() && + !GetBoolAttribute(ax::mojom::BoolAttribute::kSelectedFromFocus)) return S_OK; AXActionData data;
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc index 9db37c4..e79b7ce7 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -6464,6 +6464,65 @@ EXPECT_EQ(container, container_provider); } +TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderSelectFollowFocus) { + AXNodeData root; + root.id = 1; + root.role = ax::mojom::Role::kTabList; + + AXNodeData tab1; + tab1.id = 2; + tab1.role = ax::mojom::Role::kTab; + tab1.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false); + tab1.SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kClick); + root.child_ids.push_back(tab1.id); + + Init(root, tab1); + + auto* tab1_node = GetRootAsAXNode()->children()[0]; + ComPtr<IRawElementProviderSimple> tab1_raw_element_provider_simple = + QueryInterfaceFromNode<IRawElementProviderSimple>(tab1_node); + ASSERT_NE(nullptr, tab1_raw_element_provider_simple.Get()); + + ComPtr<IRawElementProviderFragment> tab1_raw_element_provider_fragment = + IRawElementProviderFragmentFromNode(tab1_node); + ASSERT_NE(nullptr, tab1_raw_element_provider_fragment.Get()); + + ComPtr<ISelectionItemProvider> tab1_selection_item_provider; + EXPECT_HRESULT_SUCCEEDED(tab1_raw_element_provider_simple->GetPatternProvider( + UIA_SelectionItemPatternId, &tab1_selection_item_provider)); + ASSERT_NE(nullptr, tab1_selection_item_provider.Get()); + + BOOL is_selected; + // Before setting focus to "tab1", validate that "tab1" has selected=false. + tab1_selection_item_provider->get_IsSelected(&is_selected); + EXPECT_FALSE(is_selected); + + // Setting focus on "tab1" will result in selected=true. + tab1_raw_element_provider_fragment->SetFocus(); + tab1_selection_item_provider->get_IsSelected(&is_selected); + EXPECT_TRUE(is_selected); + + // Verify that we can still trigger action::kDoDefault through Select(). + EXPECT_HRESULT_SUCCEEDED(tab1_selection_item_provider->Select()); + tab1_selection_item_provider->get_IsSelected(&is_selected); + EXPECT_TRUE(is_selected); + EXPECT_EQ(tab1_node, TestAXNodeWrapper::GetNodeFromLastDefaultAction()); + // Verify that after Select(), "tab1" is still selected. + tab1_selection_item_provider->get_IsSelected(&is_selected); + EXPECT_TRUE(is_selected); + + // Since last Select() performed |action::kDoDefault|, which set + // |kSelectedFromFocus| to false. Calling Select() again will not perform + // |action::kDoDefault| again. + TestAXNodeWrapper::SetNodeFromLastDefaultAction(nullptr); + EXPECT_HRESULT_SUCCEEDED(tab1_selection_item_provider->Select()); + tab1_selection_item_provider->get_IsSelected(&is_selected); + EXPECT_TRUE(is_selected); + // Verify that after Select(),|action::kDoDefault| was not triggered on + // "tab1". + EXPECT_EQ(nullptr, TestAXNodeWrapper::GetNodeFromLastDefaultAction()); +} + TEST_F(AXPlatformNodeWinTest, IValueProvider_GetValue) { AXNodeData root; root.id = 1;
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc index 30dea56..873ab5c 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.cc +++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -99,6 +99,11 @@ } // static +void TestAXNodeWrapper::SetNodeFromLastDefaultAction(AXNode* node) { + g_node_from_last_default_action = node; +} + +// static std::unique_ptr<base::AutoReset<float>> TestAXNodeWrapper::SetScaleFactor( float value) { return std::make_unique<base::AutoReset<float>>(&g_scale_factor, value); @@ -578,6 +583,15 @@ } case ax::mojom::Action::kDoDefault: { + // If a default action such as a click is performed on an element, it + // could result in a selected state change. In which case, the element's + // selected state no longer comes from focus action, so we should set + // |kSelectedFromFocus| to false. + if (GetData().HasBoolAttribute( + ax::mojom::BoolAttribute::kSelectedFromFocus)) + ReplaceBoolAttribute(ax::mojom::BoolAttribute::kSelectedFromFocus, + false); + switch (GetData().role) { case ax::mojom::Role::kListBoxOption: case ax::mojom::Role::kCell: { @@ -603,7 +617,7 @@ default: break; } - g_node_from_last_default_action = node_; + SetNodeFromLastDefaultAction(node_); return true; } @@ -628,9 +642,21 @@ return true; } - case ax::mojom::Action::kFocus: + case ax::mojom::Action::kFocus: { g_focused_node_in_tree[tree_] = node_; + + // The platform has select follows focus behavior: + // https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_selection_follows_focus + // For test purpose, we support select follows focus for all elements, and + // not just single-selection container elements. + if (SupportsSelected(GetData().role)) { + ReplaceBoolAttribute(ax::mojom::BoolAttribute::kSelected, true); + ReplaceBoolAttribute(ax::mojom::BoolAttribute::kSelectedFromFocus, + true); + } + return true; + } case ax::mojom::Action::kShowContextMenu: g_node_from_last_show_context_menu = node_;
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h index 2f0998c..4cd51d58 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.h +++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -41,6 +41,10 @@ // called from for testing. static const AXNode* GetNodeFromLastDefaultAction(); + // Set the last node which AccessibilityPerformAction default action was + // called for testing. + static void SetNodeFromLastDefaultAction(AXNode* node); + // Set a global scale factor for testing. static std::unique_ptr<base::AutoReset<float>> SetScaleFactor(float value);
diff --git a/ui/events/event.cc b/ui/events/event.cc index 9536e0f..eb49b9f 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc
@@ -6,14 +6,16 @@ #include <cmath> #include <cstring> +#include <memory> +#include <string> #include <utility> #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" #include "build/build_config.h" #include "ui/events/base_event_utils.h" #include "ui/events/event_utils.h" @@ -28,7 +30,7 @@ #include "ui/gfx/transform_util.h" #if defined(USE_OZONE) -#include "ui/events/ozone/layout/keyboard_layout_engine.h" // nogncheck +#include "ui/events/ozone/layout/keyboard_layout_engine.h" // nogncheck #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" // nogncheck #endif @@ -40,9 +42,8 @@ namespace { constexpr int kChangedButtonFlagMask = - ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | - ui::EF_RIGHT_MOUSE_BUTTON | ui::EF_BACK_MOUSE_BUTTON | - ui::EF_FORWARD_MOUSE_BUTTON; + EF_LEFT_MOUSE_BUTTON | EF_MIDDLE_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON | + EF_BACK_MOUSE_BUTTON | EF_FORWARD_MOUSE_BUTTON; SourceEventType EventTypeToLatencySourceEventType(EventType type) { switch (type) { @@ -72,8 +73,8 @@ case ET_SCROLL_FLING_CANCEL: return SourceEventType::UNKNOWN; - case ui::ET_KEY_PRESSED: - return ui::SourceEventType::KEY_PRESS; + case ET_KEY_PRESSED: + return SourceEventType::KEY_PRESS; case ET_MOUSE_PRESSED: case ET_MOUSE_DRAGGED: @@ -141,7 +142,7 @@ #if defined(USE_OZONE) uint32_t ScanCodeFromNative(const PlatformEvent& native_event) { - const ui::KeyEvent* event = static_cast<const ui::KeyEvent*>(native_event); + const KeyEvent* event = static_cast<const KeyEvent*>(native_event); DCHECK(event->IsKeyEvent()); return event->scan_code(); } @@ -320,7 +321,7 @@ native_event_(PlatformEvent()), delete_native_event_(false), cancelable_(true), - target_(NULL), + target_(nullptr), phase_(EP_PREDISPATCH), result_(ER_UNHANDLED), source_device_id_(ED_UNKNOWN_DEVICE) { @@ -335,7 +336,7 @@ native_event_(native_event), delete_native_event_(false), cancelable_(true), - target_(NULL), + target_(nullptr), phase_(EP_PREDISPATCH), result_(ER_UNHANDLED), source_device_id_(ED_UNKNOWN_DEVICE) { @@ -358,7 +359,7 @@ native_event_(CopyNativeEvent(copy.native_event_)), delete_native_event_(true), cancelable_(true), - target_(NULL), + target_(nullptr), phase_(EP_PREDISPATCH), result_(ER_UNHANDLED), source_device_id_(copy.source_device_id_), @@ -387,7 +388,7 @@ else properties_.reset(); } - latency_.set_source_event_type(ui::SourceEventType::OTHER); + latency_.set_source_event_type(SourceEventType::OTHER); return *this; } @@ -405,8 +406,7 @@ set_cancelable(false); } -CancelModeEvent::~CancelModeEvent() { -} +CancelModeEvent::~CancelModeEvent() = default; //////////////////////////////////////////////////////////////////////////////// // LocatedEvent @@ -466,7 +466,7 @@ : LocatedEvent(native_event), changed_button_flags_(GetChangedMouseButtonFlagsFromNative(native_event)), pointer_details_(GetMousePointerDetailsFromNative(native_event)) { - latency()->set_source_event_type(ui::SourceEventType::MOUSE); + latency()->set_source_event_type(SourceEventType::MOUSE); latency()->AddLatencyNumberWithTimestamp( INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, time_stamp()); latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT); @@ -486,7 +486,7 @@ DCHECK_NE(ET_MOUSEWHEEL, type); DCHECK_EQ(changed_button_flags_, changed_button_flags_ & kChangedButtonFlagMask); - latency()->set_source_event_type(ui::SourceEventType::MOUSE); + latency()->set_source_event_type(SourceEventType::MOUSE); latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT); if (this->type() == ET_MOUSE_MOVED && IsAnyButton()) SetType(ET_MOUSE_DRAGGED); @@ -525,8 +525,7 @@ static const int kDoubleClickWidth = 4; static const int kDoubleClickHeight = 4; - if (event1.type() != ET_MOUSE_PRESSED || - event2.type() != ET_MOUSE_PRESSED) + if (event1.type() != ET_MOUSE_PRESSED || event2.type() != ET_MOUSE_PRESSED) return false; // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks. @@ -556,9 +555,9 @@ int MouseEvent::GetRepeatCount(const MouseEvent& event) { int click_count = 1; if (last_click_event_) { - if (event.type() == ui::ET_MOUSE_RELEASED) { + if (event.type() == ET_MOUSE_RELEASED) { if (event.changed_button_flags() == - last_click_event_->changed_button_flags()) { + last_click_event_->changed_button_flags()) { return last_click_event_->GetClickCount(); } else { // If last_click_event_ has changed since this button was pressed @@ -584,12 +583,12 @@ void MouseEvent::ResetLastClickForTest() { if (last_click_event_) { delete last_click_event_; - last_click_event_ = NULL; + last_click_event_ = nullptr; } } // static -MouseEvent* MouseEvent::last_click_event_ = NULL; +MouseEvent* MouseEvent::last_click_event_ = nullptr; int MouseEvent::GetClickCount() const { if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) @@ -649,8 +648,7 @@ } MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event) - : MouseEvent(mouse_wheel_event), - offset_(mouse_wheel_event.offset()) { + : MouseEvent(mouse_wheel_event), offset_(mouse_wheel_event.offset()) { DCHECK_EQ(ET_MOUSEWHEEL, type()); } @@ -660,7 +658,7 @@ base::TimeTicks time_stamp, int flags, int changed_button_flags) - : MouseEvent(ui::ET_UNKNOWN, + : MouseEvent(ET_UNKNOWN, location, root_location, time_stamp, @@ -670,7 +668,7 @@ // Set event type to ET_UNKNOWN initially in MouseEvent() to pass the // DCHECK for type to enforce that we use MouseWheelEvent() to create // a MouseWheelEvent. - SetType(ui::ET_MOUSEWHEEL); + SetType(ET_MOUSEWHEEL); } MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d& offset, @@ -822,10 +820,7 @@ KeyboardCode key_code, DomCode code, int flags) - : Event(type, EventTimeForNow(), flags), - key_code_(key_code), - code_(code) { -} + : Event(type, EventTimeForNow(), flags), key_code_(key_code), code_(code) {} KeyEvent::KeyEvent(EventType type, KeyboardCode key_code, @@ -888,7 +883,7 @@ // Check if this is a key repeat. This must be called before initial flags // processing, e.g: NormalizeFlags(), to avoid issues like crbug.com/1069690. if (IsRepeated(GetLastKeyEvent())) - set_flags(flags() | ui::EF_IS_REPEAT); + set_flags(flags() | EF_IS_REPEAT); #if defined(USE_X11) NormalizeFlags(); @@ -906,7 +901,7 @@ } void KeyEvent::ApplyLayout() const { - ui::DomCode code = code_; + DomCode code = code_; if (code == DomCode::NONE) { // Catch old code that tries to do layout without a physical key, and try // to recover using the KeyboardCode. Once key events are fully defined @@ -947,13 +942,13 @@ if (is_char()) return false; - if (type() == ui::ET_KEY_RELEASED) { + if (type() == ET_KEY_RELEASED) { delete *last_key_event; *last_key_event = nullptr; return false; } - CHECK_EQ(ui::ET_KEY_PRESSED, type()); + CHECK_EQ(ET_KEY_PRESSED, type()); KeyEvent* last = *last_key_event; if (!last) { @@ -961,7 +956,7 @@ return false; } else if (time_stamp() == last->time_stamp()) { // The KeyEvent is created from the same native event. - return (last->flags() & ui::EF_IS_REPEAT) != 0; + return (last->flags() & EF_IS_REPEAT) != 0; } DCHECK(last); @@ -976,7 +971,7 @@ #endif if (!is_repeat) { if (key_code() == last->key_code() && - flags() == (last->flags() & ~ui::EF_IS_REPEAT) && + flags() == (last->flags() & ~EF_IS_REPEAT) && (time_stamp() - last->time_stamp()).InMilliseconds() < kMaxAutoRepeatTimeMs) { is_repeat = true; @@ -985,7 +980,7 @@ if (is_repeat) { last->set_time_stamp(time_stamp()); - last->set_flags(last->flags() | ui::EF_IS_REPEAT); + last->set_flags(last->flags() | EF_IS_REPEAT); return true; } @@ -1043,8 +1038,8 @@ base::char16 KeyEvent::GetText() const { if ((flags() & EF_CONTROL_DOWN) != 0) { - ui::DomKey key; - ui::KeyboardCode key_code; + DomKey key; + KeyboardCode key_code; if (DomCodeToControlCharacter(code_, flags(), &key, &key_code)) return key.ToCharacter(); } @@ -1068,9 +1063,9 @@ // In that case, EF_EXTENDED will not be set; if it is set, the key event // originated from the relevant non-numpad dedicated key, e.g. [Insert]. return (!(flags() & EF_IS_EXTENDED_KEY) && - (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN || - key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR || - key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP || + (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN || + key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR || + key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP || key == VKEY_PRIOR)); #else return false; @@ -1131,18 +1126,16 @@ &y_offset_ordinal_, &finger_count_, &momentum_phase_); } else if (type() == ET_SCROLL_FLING_START || type() == ET_SCROLL_FLING_CANCEL) { - GetFlingData(native_event, - &x_offset_, &y_offset_, - &x_offset_ordinal_, &y_offset_ordinal_, - NULL); + GetFlingData(native_event, &x_offset_, &y_offset_, &x_offset_ordinal_, + &y_offset_ordinal_, nullptr); } else { NOTREACHED() << "Unexpected event type " << type() - << " when constructing a ScrollEvent."; + << " when constructing a ScrollEvent."; } if (IsScrollEvent()) - latency()->set_source_event_type(ui::SourceEventType::WHEEL); + latency()->set_source_event_type(SourceEventType::WHEEL); else - latency()->set_source_event_type(ui::SourceEventType::TOUCH); + latency()->set_source_event_type(SourceEventType::TOUCH); } ScrollEvent::ScrollEvent(EventType type, @@ -1166,7 +1159,7 @@ momentum_phase_(momentum_phase), scroll_event_phase_(scroll_event_phase) { CHECK(IsScrollEvent()); - latency()->set_source_event_type(ui::SourceEventType::WHEEL); + latency()->set_source_event_type(SourceEventType::WHEEL); } ScrollEvent::ScrollEvent(EventType type, @@ -1231,11 +1224,11 @@ flags | EF_FROM_TOUCH), details_(details), unique_touch_event_id_(unique_touch_event_id) { - latency()->set_source_event_type(ui::SourceEventType::TOUCH); + latency()->set_source_event_type(SourceEventType::TOUCH); // TODO(crbug.com/868056) Other touchpad gesture should report as TOUCHPAD. if (IsPinchEvent() && - details.device_type() == ui::GestureDeviceType::DEVICE_TOUCHPAD) { - latency()->set_source_event_type(ui::SourceEventType::TOUCHPAD); + details.device_type() == GestureDeviceType::DEVICE_TOUCHPAD) { + latency()->set_source_event_type(SourceEventType::TOUCHPAD); } }
diff --git a/ui/events/event.h b/ui/events/event.h index 37ffe52..04d94e5 100644 --- a/ui/events/event.h +++ b/ui/events/event.h
@@ -5,8 +5,7 @@ #ifndef UI_EVENTS_EVENT_H_ #define UI_EVENTS_EVENT_H_ -#include <stdint.h> - +#include <cstdint> #include <memory> #include <string> #include <vector> @@ -18,7 +17,6 @@ #include "base/macros.h" #include "base/strings/string16.h" #include "base/time/time.h" -#include "build/build_config.h" #include "ui/events/event_constants.h" #include "ui/events/gesture_event_details.h" #include "ui/events/gestures/gesture_types.h" @@ -36,6 +34,7 @@ } namespace ui { + class CancelModeEvent; class Event; class EventTarget; @@ -62,9 +61,7 @@ public: explicit DispatcherApi(Event* event) : event_(event) {} - void set_target(EventTarget* target) { - event_->target_ = target; - } + void set_target(EventTarget* target) { event_->target_ = target; } void set_phase(EventPhase phase) { event_->phase_ = phase; } void set_result(int result) { @@ -130,9 +127,7 @@ bool IsSynthesized() const { return (flags_ & EF_IS_SYNTHESIZED) != 0; } - bool IsCancelModeEvent() const { - return type_ == ET_CANCEL_MODE; - } + bool IsCancelModeEvent() const { return type_ == ET_CANCEL_MODE; } bool IsKeyEvent() const { return type_ == ET_KEY_PRESSED || type_ == ET_KEY_RELEASED; @@ -195,12 +190,12 @@ // An ending event is paired with the event which started it. Setting capture // should not prevent ending events from getting to their initial target. bool IsEndingEvent() const { - switch(type_) { - case ui::ET_TOUCH_CANCELLED: - case ui::ET_GESTURE_TAP_CANCEL: - case ui::ET_GESTURE_END: - case ui::ET_GESTURE_SCROLL_END: - case ui::ET_GESTURE_PINCH_END: + switch (type_) { + case ET_TOUCH_CANCELLED: + case ET_GESTURE_TAP_CANCEL: + case ET_GESTURE_END: + case ET_GESTURE_SCROLL_END: + case ET_GESTURE_PINCH_END: return true; default: return false; @@ -210,10 +205,9 @@ bool IsScrollEvent() const { // Flings can be GestureEvents too. EF_FROM_TOUCH determines if they're // Gesture or Scroll events. - return type_ == ET_SCROLL || - ((type_ == ET_SCROLL_FLING_START || - type_ == ET_SCROLL_FLING_CANCEL) && - !(flags() & EF_FROM_TOUCH)); + return type_ == ET_SCROLL || ((type_ == ET_SCROLL_FLING_START || + type_ == ET_SCROLL_FLING_CANCEL) && + !(flags() & EF_FROM_TOUCH)); } bool IsPinchEvent() const { @@ -223,18 +217,14 @@ bool IsScrollGestureEvent() const { return type_ == ET_GESTURE_SCROLL_BEGIN || - type_ == ET_GESTURE_SCROLL_UPDATE || - type_ == ET_GESTURE_SCROLL_END; + type_ == ET_GESTURE_SCROLL_UPDATE || type_ == ET_GESTURE_SCROLL_END; } bool IsFlingScrollEvent() const { - return type_ == ET_SCROLL_FLING_CANCEL || - type_ == ET_SCROLL_FLING_START; + return type_ == ET_SCROLL_FLING_CANCEL || type_ == ET_SCROLL_FLING_START; } - bool IsMouseWheelEvent() const { - return type_ == ET_MOUSEWHEEL; - } + bool IsMouseWheelEvent() const { return type_ == ET_MOUSEWHEEL; } bool IsLocatedEvent() const { return IsMouseEvent() || IsScrollEvent() || IsTouchEvent() || @@ -313,9 +303,7 @@ void SetType(EventType type); void set_cancelable(bool cancelable) { cancelable_ = cancelable; } - void set_time_stamp(base::TimeTicks time_stamp) { - time_stamp_ = time_stamp; - } + void set_time_stamp(base::TimeTicks time_stamp) { time_stamp_ = time_stamp; } private: friend class EventTestApi; @@ -348,7 +336,7 @@ public: // Convenience function that casts |event| to a LocatedEvent if it is one, // otherwise returns null. - static const ui::LocatedEvent* FromIfValid(const ui::Event* event) { + static const LocatedEvent* FromIfValid(const Event* event) { return event && event->IsLocatedEvent() ? event->AsLocatedEvent() : nullptr; } @@ -371,9 +359,7 @@ gfx::Point root_location() const { return gfx::ToFlooredPoint(root_location_); } - const gfx::PointF& root_location_f() const { - return root_location_; - } + const gfx::PointF& root_location_f() const { return root_location_; } // Transform the locations using |inverted_root_transform| and // |inverted_local_transform|. |inverted_local_transform| is only used if @@ -529,9 +515,7 @@ return (flags() & EF_RIGHT_MOUSE_BUTTON) != 0; } - bool IsAnyButton() const { - return button_flags() != 0; - } + bool IsAnyButton() const { return button_flags() != 0; } // Returns the flags for the mouse buttons. int button_flags() const { @@ -542,9 +526,8 @@ // Compares two mouse down events and returns true if the second one should // be considered a repeat of the first. - static bool IsRepeatedClickEvent( - const MouseEvent& event1, - const MouseEvent& event2); + static bool IsRepeatedClickEvent(const MouseEvent& event1, + const MouseEvent& event2); // Get the click count. Can be 1, 2 or 3 for mousedown messages, 0 otherwise. int GetClickCount() const; @@ -607,12 +590,9 @@ ~MouseWheelEvent() override; template <class T> - MouseWheelEvent(const MouseWheelEvent& model, - T* source, - T* target) + MouseWheelEvent(const MouseWheelEvent& model, T* source, T* target) : MouseEvent(model, source, target, model.type(), model.flags()), - offset_(model.x_offset(), model.y_offset()) { - } + offset_(model.x_offset(), model.y_offset()) {} // Used for synthetic events in testing and by the gesture recognizer. MouseWheelEvent(const gfx::Vector2d& offset, @@ -800,10 +780,7 @@ // Used for synthetic events with code of DOM KeyboardEvent (e.g. 'KeyA') // See also: ui/events/keycodes/dom/dom_values.txt - KeyEvent(EventType type, - KeyboardCode key_code, - DomCode code, - int flags); + KeyEvent(EventType type, KeyboardCode key_code, DomCode code, int flags); KeyEvent(const KeyEvent& rhs); @@ -1018,8 +995,8 @@ class EVENTS_EXPORT GestureEvent : public LocatedEvent { public: - // The constructor takes a default unique_touch_id of zero to support many - // (80+) existing tests that doesn't care about this id. + // The constructor takes a default unique_touch_id of zero to support many + // (80+) existing tests that doesn't care about this id. GestureEvent(float x, float y, int flags, @@ -1032,17 +1009,13 @@ // converted from |source| coordinate system to |target| coordinate system. template <typename T> GestureEvent(const GestureEvent& model, T* source, T* target) - : LocatedEvent(model, source, target), - details_(model.details_) { - } + : LocatedEvent(model, source, target), details_(model.details_) {} GestureEvent(const GestureEvent& copy); ~GestureEvent() override; const GestureEventDetails& details() const { return details_; } - uint32_t unique_touch_event_id() const { - return unique_touch_event_id_; - } + uint32_t unique_touch_event_id() const { return unique_touch_event_id_; } private: GestureEventDetails details_;
diff --git a/ui/gfx/linux/drm_util_linux.cc b/ui/gfx/linux/drm_util_linux.cc index 7482722..e1372b68 100644 --- a/ui/gfx/linux/drm_util_linux.cc +++ b/ui/gfx/linux/drm_util_linux.cc
@@ -8,15 +8,6 @@ #include "base/notreached.h" -#ifndef DRM_FORMAT_INVALID -// TODO(mcasas): Remove when uprevving //third_party/libdrm. -#define DRM_FORMAT_INVALID 0 -#endif - -#ifndef DRM_FORMAT_P010 -#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') -#endif - namespace ui { int GetFourCCFormatFromBufferFormat(gfx::BufferFormat format) {
diff --git a/ui/gl/child_window_win.cc b/ui/gl/child_window_win.cc index e17931d..3b9654a 100644 --- a/ui/gl/child_window_win.cc +++ b/ui/gl/child_window_win.cc
@@ -124,9 +124,9 @@ ChildWindowWin::ChildWindowWin(HWND parent_window) : parent_window_(parent_window) {} -bool ChildWindowWin::Initialize() { +void ChildWindowWin::Initialize() { if (window_) - return true; + return; thread_ = std::make_unique<base::Thread>("Window owner thread"); base::Thread::Options options(base::MessagePumpType::UI, 0); @@ -143,8 +143,6 @@ base::BindOnce(&CreateWindowsOnThread, gfx::Rect(window_rect).size(), &event, &window_, &initial_parent_window_)); event.Wait(); - - return true; } ChildWindowWin::~ChildWindowWin() {
diff --git a/ui/gl/child_window_win.h b/ui/gl/child_window_win.h index c977e76b..81bd99a 100644 --- a/ui/gl/child_window_win.h +++ b/ui/gl/child_window_win.h
@@ -8,6 +8,7 @@ #include "base/memory/weak_ptr.h" #include "base/task_runner.h" #include "base/threading/thread.h" +#include "ui/gl/gl_export.h" #include <windows.h> @@ -16,12 +17,12 @@ // The window DirectComposition renders into needs to be owned by the process // that's currently doing the rendering. The class creates and owns a window // which is reparented by the browser to be a child of its window. -class ChildWindowWin { +class GL_EXPORT ChildWindowWin { public: explicit ChildWindowWin(HWND parent_window); ~ChildWindowWin(); - bool Initialize(); + void Initialize(); HWND window() const { return window_; } scoped_refptr<base::TaskRunner> GetTaskRunnerForTesting();
diff --git a/ui/gl/direct_composition_surface_win.cc b/ui/gl/direct_composition_surface_win.cc index 52f8523..3477f730 100644 --- a/ui/gl/direct_composition_surface_win.cc +++ b/ui/gl/direct_composition_surface_win.cc
@@ -585,10 +585,8 @@ return false; } - if (!child_window_.Initialize()) { - DLOG(ERROR) << "Failed to initialize native window"; - return false; - } + child_window_.Initialize(); + window_ = child_window_.window(); if (!layer_tree_->Initialize(window_, d3d11_device_, dcomp_device_))
diff --git a/ui/gtk/print_dialog_gtk.cc b/ui/gtk/print_dialog_gtk.cc index 7368b29..3d140b7 100644 --- a/ui/gtk/print_dialog_gtk.cc +++ b/ui/gtk/print_dialog_gtk.cc
@@ -184,7 +184,7 @@ context_(context) {} PrintDialogGtk::~PrintDialogGtk() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); if (dialog_) { aura::Window* parent = gtk::GetAuraTransientParent(dialog_); @@ -363,7 +363,7 @@ void PrintDialogGtk::PrintDocument(const printing::MetafilePlayer& metafile, const base::string16& document_name) { // This runs on the print worker thread, does not block the UI thread. - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!owning_task_runner()->RunsTasksInCurrentSequence()); // The document printing tasks can outlive the PrintingContext that created // this dialog. @@ -389,7 +389,7 @@ } // No errors, continue printing. - base::SequencedTaskRunnerHandle::Get()->PostTask( + owning_task_runner()->PostTask( FROM_HERE, base::BindOnce(&PrintDialogGtk::SendDocumentToPrinter, this, document_name)); } @@ -487,7 +487,7 @@ } void PrintDialogGtk::SendDocumentToPrinter( const base::string16& document_name) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); // If |printer_| is nullptr then somehow the GTK printer list changed out // under us. In which case, just bail out.
diff --git a/ui/gtk/print_dialog_gtk.h b/ui/gtk/print_dialog_gtk.h index b7874e58..3c268b37 100644 --- a/ui/gtk/print_dialog_gtk.h +++ b/ui/gtk/print_dialog_gtk.h
@@ -13,7 +13,6 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted_delete_on_sequence.h" -#include "base/sequenced_task_runner_helpers.h" #include "printing/print_dialog_gtk_interface.h" #include "printing/printing_context_linux.h" #include "ui/aura/window_observer.h" @@ -84,8 +83,6 @@ base::FilePath path_to_pdf_; - SEQUENCE_CHECKER(sequence_checker_); - DISALLOW_COPY_AND_ASSIGN(PrintDialogGtk); };
diff --git a/ui/latency/average_lag_tracker.cc b/ui/latency/average_lag_tracker.cc index 4c8c7ef8..347b32d 100644 --- a/ui/latency/average_lag_tracker.cc +++ b/ui/latency/average_lag_tracker.cc
@@ -26,78 +26,10 @@ return; if (scroll_name == "ScrollBegin") { - // Flush all unfinished frames. - while (!frame_lag_infos_.empty()) { - frame_lag_infos_.front().lag_area += LagForUnfinishedFrame( - frame_lag_infos_.front().rendered_accumulated_delta); - frame_lag_infos_.front().lag_area_no_prediction += LagForUnfinishedFrame( - frame_lag_infos_.front().rendered_accumulated_delta_no_prediction); - - // Record UMA when it's the last item in queue. - CalculateAndReportAverageLagUma(frame_lag_infos_.size() == 1); - } - // |accumulated_lag_| should be cleared/reset. - DCHECK(accumulated_lag_ == 0); - - // Create ScrollBegin report, with report time equals to gpu swap time. - LagAreaInFrame first_frame(gpu_swap_begin_timestamp); - frame_lag_infos_.push_back(first_frame); - - // Reset fields. - last_reported_time_ = event_timestamp; - last_finished_frame_time_ = event_timestamp; - last_event_accumulated_delta_ = 0; - last_rendered_accumulated_delta_ = 0; - is_begin_ = true; + AddScrollBeginInFrame(gpu_swap_begin_timestamp, event_timestamp); } else if (scroll_name == "ScrollUpdate" && !last_event_timestamp_.is_null()) { - // Only accept events in nondecreasing order. - if ((event_timestamp - last_event_timestamp_).InMilliseconds() < 0) - return; - - // Pop all frames where frame_time <= event_timestamp. - while (!frame_lag_infos_.empty() && - frame_lag_infos_.front().frame_time <= event_timestamp) { - base::TimeTicks front_time = - std::max(last_event_timestamp_, last_finished_frame_time_); - base::TimeTicks back_time = frame_lag_infos_.front().frame_time; - frame_lag_infos_.front().lag_area += - LagBetween(front_time, back_time, latency, event_timestamp, - frame_lag_infos_.front().rendered_accumulated_delta); - frame_lag_infos_.front().lag_area_no_prediction += LagBetween( - front_time, back_time, latency, event_timestamp, - frame_lag_infos_.front().rendered_accumulated_delta_no_prediction); - - CalculateAndReportAverageLagUma(); - } - - // Initialize a new LagAreaInFrame when current_frame_time > frame_time. - if (frame_lag_infos_.empty() || - gpu_swap_begin_timestamp > frame_lag_infos_.back().frame_time) { - LagAreaInFrame new_frame(gpu_swap_begin_timestamp, - last_rendered_accumulated_delta_, - last_event_accumulated_delta_); - frame_lag_infos_.push_back(new_frame); - } - - // last_frame_time <= event_timestamp < frame_time - if (!frame_lag_infos_.empty()) { - // The front element in queue (if any) must satisfy frame_time > - // event_timestamp, otherwise it would be popped in the while loop. - DCHECK(last_finished_frame_time_ <= event_timestamp && - event_timestamp <= frame_lag_infos_.front().frame_time); - base::TimeTicks front_time = - std::max(last_finished_frame_time_, last_event_timestamp_); - base::TimeTicks back_time = event_timestamp; - - frame_lag_infos_.front().lag_area += - LagBetween(front_time, back_time, latency, event_timestamp, - frame_lag_infos_.front().rendered_accumulated_delta); - - frame_lag_infos_.front().lag_area_no_prediction += LagBetween( - front_time, back_time, latency, event_timestamp, - frame_lag_infos_.front().rendered_accumulated_delta_no_prediction); - } + AddScrollUpdateInFrame(latency, gpu_swap_begin_timestamp, event_timestamp); } last_event_timestamp_ = event_timestamp; @@ -105,6 +37,87 @@ last_rendered_accumulated_delta_ += latency.predicted_scroll_update_delta(); } +void AverageLagTracker::AddScrollBeginInFrame( + base::TimeTicks gpu_swap_begin_timestamp, + base::TimeTicks event_timestamp) { + // Flush all unfinished frames. + while (!frame_lag_infos_.empty()) { + frame_lag_infos_.front().lag_area += LagForUnfinishedFrame( + frame_lag_infos_.front().rendered_accumulated_delta); + frame_lag_infos_.front().lag_area_no_prediction += LagForUnfinishedFrame( + frame_lag_infos_.front().rendered_accumulated_delta_no_prediction); + + // Record UMA when it's the last item in queue. + CalculateAndReportAverageLagUma(frame_lag_infos_.size() == 1); + } + // |accumulated_lag_| should be cleared/reset. + DCHECK(accumulated_lag_ == 0); + + // Create ScrollBegin report, with report time equals to gpu swap time. + LagAreaInFrame first_frame(gpu_swap_begin_timestamp); + frame_lag_infos_.push_back(first_frame); + + // Reset fields. + last_reported_time_ = event_timestamp; + last_finished_frame_time_ = event_timestamp; + last_event_accumulated_delta_ = 0; + last_rendered_accumulated_delta_ = 0; + is_begin_ = true; +} + +void AverageLagTracker::AddScrollUpdateInFrame( + const LatencyInfo& latency, + base::TimeTicks gpu_swap_begin_timestamp, + base::TimeTicks event_timestamp) { + // Only accept events in nondecreasing order. + if ((event_timestamp - last_event_timestamp_).InMilliseconds() < 0) + return; + + // Pop all frames where frame_time <= event_timestamp. + while (!frame_lag_infos_.empty() && + frame_lag_infos_.front().frame_time <= event_timestamp) { + base::TimeTicks front_time = + std::max(last_event_timestamp_, last_finished_frame_time_); + base::TimeTicks back_time = frame_lag_infos_.front().frame_time; + frame_lag_infos_.front().lag_area += + LagBetween(front_time, back_time, latency, event_timestamp, + frame_lag_infos_.front().rendered_accumulated_delta); + frame_lag_infos_.front().lag_area_no_prediction += LagBetween( + front_time, back_time, latency, event_timestamp, + frame_lag_infos_.front().rendered_accumulated_delta_no_prediction); + + CalculateAndReportAverageLagUma(); + } + + // Initialize a new LagAreaInFrame when current_frame_time > frame_time. + if (frame_lag_infos_.empty() || + gpu_swap_begin_timestamp > frame_lag_infos_.back().frame_time) { + LagAreaInFrame new_frame(gpu_swap_begin_timestamp, + last_rendered_accumulated_delta_, + last_event_accumulated_delta_); + frame_lag_infos_.push_back(new_frame); + } + + // last_frame_time <= event_timestamp < frame_time + if (!frame_lag_infos_.empty()) { + // The front element in queue (if any) must satisfy frame_time > + // event_timestamp, otherwise it would be popped in the while loop. + DCHECK(last_finished_frame_time_ <= event_timestamp && + event_timestamp <= frame_lag_infos_.front().frame_time); + base::TimeTicks front_time = + std::max(last_finished_frame_time_, last_event_timestamp_); + base::TimeTicks back_time = event_timestamp; + + frame_lag_infos_.front().lag_area += + LagBetween(front_time, back_time, latency, event_timestamp, + frame_lag_infos_.front().rendered_accumulated_delta); + + frame_lag_infos_.front().lag_area_no_prediction += LagBetween( + front_time, back_time, latency, event_timestamp, + frame_lag_infos_.front().rendered_accumulated_delta_no_prediction); + } +} + float AverageLagTracker::LagBetween(base::TimeTicks front_time, base::TimeTicks back_time, const LatencyInfo& latency,
diff --git a/ui/latency/average_lag_tracker.h b/ui/latency/average_lag_tracker.h index 80244d90..f97738f17 100644 --- a/ui/latency/average_lag_tracker.h +++ b/ui/latency/average_lag_tracker.h
@@ -50,6 +50,12 @@ float lag_area_no_prediction; } LagAreaInFrame; + void AddScrollBeginInFrame(base::TimeTicks gpu_swap_begin_timestamp, + base::TimeTicks event_timestamp); + void AddScrollUpdateInFrame(const LatencyInfo& latency, + base::TimeTicks gpu_swap_begin_timestamp, + base::TimeTicks event_timestamp); + // Calculate lag in 1 seconds intervals and report UMA. void CalculateAndReportAverageLagUma(bool send_anyway = false);
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc index 0847634..40c4dca 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view.cc +++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -162,6 +162,93 @@ View* const anchor_view_; }; +// This class is responsible for observing events on a BubbleDialogDelegate's +// anchor widget and notifying the BubbleDialogDelegate of them. +class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver { + public: + AnchorWidgetObserver(BubbleDialogDelegate* owner, Widget* widget) + : owner_(owner) { + observer_.Add(widget); + } + ~AnchorWidgetObserver() override = default; + + void OnWidgetDestroying(Widget* widget) override { + observer_.Remove(widget); + owner_->OnAnchorWidgetDestroying(); + // |this| may be destroyed here! + } + + void OnWidgetActivationChanged(Widget* widget, bool active) override { + owner_->OnWidgetActivationChanged(widget, active); + } + + void OnWidgetBoundsChanged(Widget* widget, const gfx::Rect&) override { + owner_->OnAnchorBoundsChanged(); + } + + private: + BubbleDialogDelegate* owner_; + ScopedObserver<views::Widget, views::WidgetObserver> observer_{this}; +}; + +// This class is responsible for observing events on a BubbleDialogDelegate's +// widget and notifying the BubbleDialogDelegate of them. +class BubbleDialogDelegate::BubbleWidgetObserver : public WidgetObserver { + public: + BubbleWidgetObserver(BubbleDialogDelegate* owner, Widget* widget) + : owner_(owner) { + observer_.Add(widget); + } + ~BubbleWidgetObserver() override = default; + + void OnWidgetClosing(Widget* widget) override { + owner_->OnBubbleWidgetClosing(); + owner_->OnWidgetClosing(widget); + } + + void OnWidgetDestroying(Widget* widget) override { + observer_.Remove(widget); + owner_->OnWidgetDestroying(widget); + } + + void OnWidgetDestroyed(Widget* widget) override { + owner_->OnWidgetDestroyed(widget); + } + + void OnWidgetBoundsChanged(Widget* widget, const gfx::Rect& bounds) override { + owner_->OnWidgetBoundsChanged(widget, bounds); + } + + void OnWidgetVisibilityChanging(Widget* widget, bool visible) override { +#if defined(OS_WIN) + // On Windows we need to handle this before the bubble is visible or hidden. + // Please see the comment on the OnWidgetVisibilityChanging function. On + // other platforms it is fine to handle it after the bubble is shown/hidden. + owner_->OnBubbleWidgetVisibilityChanged(visible); +#endif + } + + void OnWidgetVisibilityChanged(Widget* widget, bool visible) override { +#if !defined(OS_WIN) + owner_->OnBubbleWidgetVisibilityChanged(visible); +#endif + owner_->OnWidgetVisibilityChanged(widget, visible); + } + + void OnWidgetActivationChanged(Widget* widget, bool active) override { + owner_->OnBubbleWidgetActivationChanged(active); + owner_->OnWidgetActivationChanged(widget, active); + } + + void OnWidgetPaintAsActiveChanged(Widget* widget, bool as_active) override { + owner_->OnBubbleWidgetPaintAsActiveChanged(as_active); + } + + private: + BubbleDialogDelegate* owner_; + ScopedObserver<views::Widget, views::WidgetObserver> observer_{this}; +}; + BubbleDialogDelegate::BubbleDialogDelegate() = default; BubbleDialogDelegate::BubbleDialogDelegate(View* anchor_view, BubbleBorder::Arrow arrow, @@ -193,7 +280,8 @@ #endif bubble_delegate->SizeToContents(); - bubble_delegate->widget_observer_.Add(bubble_widget); + bubble_delegate->bubble_widget_observer_ = + std::make_unique<BubbleWidgetObserver>(bubble_delegate, bubble_widget); return bubble_widget; } @@ -289,74 +377,45 @@ delete this; } -void BubbleDialogDelegate::OnWidgetClosing(Widget* widget) { +void BubbleDialogDelegate::OnBubbleWidgetClosing() { // To prevent keyboard focus traversal issues, the anchor view's // kAnchoredDialogKey property is cleared immediately upon Close(). This // avoids a bug that occured when a focused anchor view is made unfocusable // right after the bubble is closed. Previously, focus would advance into the // bubble then would be lost when the bubble was destroyed. - if (widget == GetWidget() && GetAnchorView()) + if (GetAnchorView()) GetAnchorView()->ClearProperty(kAnchoredDialogKey); } -void BubbleDialogDelegate::OnWidgetDestroying(Widget* widget) { - if (anchor_widget() == widget) - SetAnchorView(nullptr); - - if (widget_observer_.IsObserving(widget)) - widget_observer_.Remove(widget); +void BubbleDialogDelegate::OnAnchorWidgetDestroying() { + SetAnchorView(nullptr); } -void BubbleDialogDelegate::OnWidgetVisibilityChanging(Widget* widget, - bool visible) { -#if defined(OS_WIN) - // On Windows we need to handle this before the bubble is visible or hidden. - // Please see the comment on the OnWidgetVisibilityChanging function. On - // other platforms it is fine to handle it after the bubble is shown/hidden. - HandleVisibilityChanged(widget, visible); -#endif -} - -void BubbleDialogDelegate::OnWidgetVisibilityChanged(Widget* widget, - bool visible) { -#if !defined(OS_WIN) - HandleVisibilityChanged(widget, visible); -#endif -} - -void BubbleDialogDelegate::OnWidgetActivationChanged(Widget* widget, - bool active) { +void BubbleDialogDelegate::OnBubbleWidgetActivationChanged(bool active) { if (devtools_dismiss_override_) return; #if defined(OS_MACOSX) // Install |mac_bubble_closer_| the first time the widget becomes active. - if (widget == GetWidget() && active && !mac_bubble_closer_) { + if (active && !mac_bubble_closer_) { mac_bubble_closer_ = std::make_unique<ui::BubbleCloser>( GetWidget()->GetNativeWindow().GetNativeNSWindow(), base::BindRepeating(&BubbleDialogDelegate::OnDeactivate, base::Unretained(this))); } #endif - if (widget == GetWidget() && !active) + + if (!active) OnDeactivate(); } -void BubbleDialogDelegate::OnWidgetBoundsChanged(Widget* widget, - const gfx::Rect& new_bounds) { - if (GetBubbleFrameView() && anchor_widget() == widget) +void BubbleDialogDelegate::OnAnchorWidgetBoundsChanged() { + if (GetBubbleFrameView()) SizeToContents(); } -void BubbleDialogDelegate::OnWidgetPaintAsActiveChanged(Widget* widget, - bool paint_as_active) { - // We only care about the current widget having its state changed; if the - // anchor widget receives active status directly then there's no need to apply - // paint as active lock. - if (widget != GetWidget()) - return; - - if (!paint_as_active) { +void BubbleDialogDelegate::OnBubbleWidgetPaintAsActiveChanged(bool as_active) { + if (!as_active) { paint_as_active_lock_.reset(); return; } @@ -485,6 +544,12 @@ void BubbleDialogDelegateView::Init() {} void BubbleDialogDelegate::SetAnchorView(View* anchor_view) { + if (anchor_view && anchor_view->GetWidget()) { + anchor_widget_observer_ = + std::make_unique<AnchorWidgetObserver>(this, anchor_view->GetWidget()); + } else { + anchor_widget_observer_.reset(); + } if (GetAnchorView()) { GetAnchorView()->ClearProperty(kAnchoredDialogKey); anchor_view_observer_.reset(); @@ -497,13 +562,11 @@ if (GetWidget() && GetWidget()->IsVisible()) UpdateHighlightedButton(false); paint_as_active_lock_.reset(); - anchor_widget_->RemoveObserver(this); anchor_widget_ = nullptr; } if (anchor_view) { anchor_widget_ = anchor_view->GetWidget(); if (anchor_widget_) { - anchor_widget_->AddObserver(this); const bool visible = GetWidget() && GetWidget()->IsVisible(); UpdateHighlightedButton(visible); // Have the anchor widget's paint-as-active state track this view's @@ -576,19 +639,17 @@ AddAccelerator(ui::Accelerator(ui::VKEY_UP, ui::EF_NONE)); } -void BubbleDialogDelegate::HandleVisibilityChanged(Widget* widget, - bool visible) { - if (widget == GetWidget()) - UpdateHighlightedButton(visible); +void BubbleDialogDelegate::OnBubbleWidgetVisibilityChanged(bool visible) { + UpdateHighlightedButton(visible); // Fire ax::mojom::Event::kAlert for bubbles marked as // ax::mojom::Role::kAlertDialog; this instructs accessibility tools to read // the bubble in its entirety rather than just its title and initially focused // view. See http://crbug.com/474622 for details. - if (widget == GetWidget() && visible) { + if (visible) { if (ui::IsAlert(GetAccessibleWindowRole())) { - widget->GetRootView()->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, - true); + GetWidget()->GetRootView()->NotifyAccessibilityEvent( + ax::mojom::Event::kAlert, true); } } }
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.h b/ui/views/bubble/bubble_dialog_delegate_view.h index 660787d..8e07ffe 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view.h +++ b/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -39,8 +39,7 @@ class Button; -class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate, - public WidgetObserver { +class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate { public: enum class CloseReason { DEACTIVATION, @@ -229,20 +228,7 @@ virtual void OnBeforeBubbleWidgetInit(Widget::InitParams* params, Widget* widget) const {} - // WidgetObserver: - void OnWidgetClosing(Widget* widget) override; - void OnWidgetDestroying(Widget* widget) override; - void OnWidgetVisibilityChanging(Widget* widget, bool visible) override; - void OnWidgetVisibilityChanged(Widget* widget, bool visible) override; - void OnWidgetActivationChanged(Widget* widget, bool active) override; - void OnWidgetBoundsChanged(Widget* widget, - const gfx::Rect& new_bounds) override; - void OnWidgetPaintAsActiveChanged(Widget* widget, - bool paint_as_active) override; - protected: - class AnchorViewObserver; - // Create and initialize the bubble Widget with proper bounds. static Widget* CreateBubble(BubbleDialogDelegate* bubble_delegate); @@ -273,13 +259,54 @@ bool color_explicitly_set() const { return color_explicitly_set_; } + // Redeclarations of virtuals that BubbleDialogDelegate used to inherit from + // WidgetObserver. These should not exist; do not add new overrides of them. + // They exist to allow the WidgetObserver helper classes inside + // BubbleDialogDelegate (AnchorWidgetObserver and BubbleWidgetObserver) to + // forward specific events to BubbleDialogDelegate subclasses that were + // overriding WidgetObserver methods from BubbleDialogDelegate. Whether they + // are called for the anchor widget or the bubble widget and when is + // deliberately unspecified. + // + // TODO(ellyjones): Get rid of these. + virtual void OnWidgetClosing(Widget* widget) {} + virtual void OnWidgetDestroying(Widget* widget) {} + virtual void OnWidgetActivationChanged(Widget* widget, bool active) {} + virtual void OnWidgetDestroyed(Widget* widget) {} + virtual void OnWidgetBoundsChanged(Widget* widget, const gfx::Rect& bounds) {} + virtual void OnWidgetVisibilityChanged(Widget* widget, bool visible) {} + private: + class AnchorViewObserver; + class AnchorWidgetObserver; + class BubbleWidgetObserver; + + FRIEND_TEST_ALL_PREFIXES(BubbleDialogDelegateViewTest, + VisibleWidgetShowsInkDropOnAttaching); + FRIEND_TEST_ALL_PREFIXES(BubbleDialogDelegateViewTest, + AttachedWidgetShowsInkDropWhenVisible); + + friend class AnchorViewObserver; + friend class AnchorWidgetObserver; + friend class BubbleWidgetObserver; + friend class BubbleBorderDelegate; friend class BubbleWindowTargeter; friend class ui_devtools::PageAgentViews; + // Notify the BubbleDialogDelegate about changes in the anchor Widget. You do + // not need to call these yourself. + void OnAnchorWidgetDestroying(); + void OnAnchorWidgetBoundsChanged(); + + // Notify the BubbleDialogDelegate about changes in the bubble Widget. You do + // not need to call these yourself. + void OnBubbleWidgetClosing(); + void OnBubbleWidgetVisibilityChanged(bool visible); + void OnBubbleWidgetActivationChanged(bool active); + void OnBubbleWidgetPaintAsActiveChanged(bool as_active); + void OnDeactivate(); - void HandleVisibilityChanged(Widget* widget, bool b); // Set from UI DevTools to prevent bubbles from closing in // OnWidgetActivationChanged(). @@ -292,6 +319,8 @@ bool color_explicitly_set_ = false; Widget* anchor_widget_ = nullptr; std::unique_ptr<AnchorViewObserver> anchor_view_observer_; + std::unique_ptr<AnchorWidgetObserver> anchor_widget_observer_; + std::unique_ptr<BubbleWidgetObserver> bubble_widget_observer_; std::unique_ptr<Widget::PaintAsActiveLock> paint_as_active_lock_; bool adjust_if_offscreen_ = true; bool focus_traversable_from_anchor_view_ = true; @@ -318,8 +347,6 @@ // monitor clicks as well for the desired behavior. std::unique_ptr<ui::BubbleCloser> mac_bubble_closer_; #endif - - ScopedObserver<views::Widget, views::WidgetObserver> widget_observer_{this}; }; // BubbleDialogDelegateView is a BubbleDialogDelegate that is also a View.
diff --git a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc index 44195eb..b4013f6 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc +++ b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
@@ -524,11 +524,11 @@ // Explicitly calling OnWidgetVisibilityChanging to test functionality for // OS_WIN. Outside of the test environment this happens automatically by way // of HWNDMessageHandler. - bubble_delegate->OnWidgetVisibilityChanging(bubble_widget, true); + bubble_delegate->OnBubbleWidgetVisibilityChanged(true); EXPECT_EQ(InkDropState::ACTIVATED, ink_drop->GetTargetInkDropState()); bubble_widget->Close(); - bubble_delegate->OnWidgetVisibilityChanging(bubble_widget, false); + bubble_delegate->OnBubbleWidgetVisibilityChanged(false); EXPECT_EQ(InkDropState::DEACTIVATED, ink_drop->GetTargetInkDropState()); } @@ -548,16 +548,16 @@ Widget* bubble_widget = BubbleDialogDelegateView::CreateBubble(bubble_delegate); bubble_widget->Show(); - // Explicitly calling OnWidgetVisibilityChanging to test functionality for + // Explicitly calling OnWidgetVisibilityChanged to test functionality for // OS_WIN. Outside of the test environment this happens automatically by way // of HWNDMessageHandler. - bubble_delegate->OnWidgetVisibilityChanging(bubble_widget, true); + bubble_delegate->OnBubbleWidgetVisibilityChanged(true); EXPECT_EQ(InkDropState::HIDDEN, ink_drop->GetTargetInkDropState()); bubble_delegate->SetHighlightedButton(button); EXPECT_EQ(InkDropState::ACTIVATED, ink_drop->GetTargetInkDropState()); bubble_widget->Close(); - bubble_delegate->OnWidgetVisibilityChanging(bubble_widget, false); + bubble_delegate->OnBubbleWidgetVisibilityChanged(false); EXPECT_EQ(InkDropState::DEACTIVATED, ink_drop->GetTargetInkDropState()); }
diff --git a/ui/views/touchui/touch_selection_controller_impl.cc b/ui/views/touchui/touch_selection_controller_impl.cc index 917a40f..f8e3c7b 100644 --- a/ui/views/touchui/touch_selection_controller_impl.cc +++ b/ui/views/touchui/touch_selection_controller_impl.cc
@@ -71,21 +71,6 @@ // boundaries. constexpr int kSelectionHandleBarBottomAllowance = 3; -// Creates a widget to host SelectionHandleView. -views::Widget* CreateTouchSelectionPopupWidget( - gfx::NativeView parent, - views::WidgetDelegate* widget_delegate) { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); - params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; - params.shadow_type = views::Widget::InitParams::ShadowType::kNone; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = parent; - params.delegate = widget_delegate; - widget->Init(std::move(params)); - return widget; -} - gfx::Image* GetCenterHandleImage() { static gfx::Image* handle_image = nullptr; if (!handle_image) { @@ -209,8 +194,7 @@ using EditingHandleView = TouchSelectionControllerImpl::EditingHandleView; // A View that displays the text selection handle. -class TouchSelectionControllerImpl::EditingHandleView - : public WidgetDelegateView { +class TouchSelectionControllerImpl::EditingHandleView : public View { public: EditingHandleView(TouchSelectionControllerImpl* controller, gfx::NativeView parent, @@ -218,28 +202,33 @@ : controller_(controller), image_(GetCenterHandleImage()), is_cursor_handle_(is_cursor_handle), - draw_invisible_(false) { - widget_.reset(CreateTouchSelectionPopupWidget(parent, this)); + draw_invisible_(false), + widget_(new views::Widget) { + // Create a widget to host EditingHandleView. + views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); + params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; + params.shadow_type = views::Widget::InitParams::ShadowType::kNone; + params.parent = parent; + widget_->Init(std::move(params)); - targeter_ = new aura::WindowTargeter(); - aura::Window* window = widget_->GetNativeWindow(); - window->SetEventTargeter(std::unique_ptr<aura::WindowTargeter>(targeter_)); - - // We are owned by the TouchSelectionControllerImpl. - set_owned_by_client(); + widget_->GetNativeWindow()->SetEventTargeter( + std::make_unique<aura::WindowTargeter>()); + widget_->SetContentsView(this); } - ~EditingHandleView() override { SetWidgetVisible(false); } + EditingHandleView(const EditingHandleView&) = delete; + EditingHandleView& operator=(const EditingHandleView&) = delete; + ~EditingHandleView() override = default; + + void CloseHandleWidget() { + SetWidgetVisible(false); + widget_->CloseNow(); + } gfx::SelectionBound::Type selection_bound_type() { return selection_bound_.type(); } - // WidgetDelegateView: - void DeleteDelegate() override { - // We are owned and deleted by TouchSelectionControllerImpl. - } - // View: void OnPaint(gfx::Canvas* canvas) override { if (draw_invisible_) @@ -340,7 +329,10 @@ const gfx::Insets insets( selection_bound_.GetHeight() + kSelectionHandleVerticalVisualOffset, 0, 0, 0); - targeter_->SetInsets(insets, insets); + + // Shifts the hit-test target below the apparent bounds to make dragging + // easier. + widget_->GetNativeWindow()->targeter()->SetInsets(insets, insets); } void SetDrawInvisible(bool draw_invisible) { @@ -351,15 +343,8 @@ } private: - std::unique_ptr<Widget> widget_; TouchSelectionControllerImpl* controller_; - // A WindowTargeter that shifts the hit-test target below the apparent bounds - // to make dragging easier. The |widget_|'s NativeWindow takes ownership over - // the |targeter_| but since the |widget_|'s lifetime is known to this class, - // it can safely access the |targeter_|. - aura::WindowTargeter* targeter_; - // In local coordinates gfx::SelectionBound selection_bound_; gfx::Image* image_; @@ -379,7 +364,8 @@ // handle. bool draw_invisible_; - DISALLOW_COPY_AND_ASSIGN(EditingHandleView); + // Owning widget. + Widget* widget_ = nullptr; }; TouchSelectionControllerImpl::TouchSelectionControllerImpl( @@ -412,6 +398,10 @@ aura::Env::GetInstance()->RemoveEventObserver(this); if (client_widget_) client_widget_->RemoveObserver(this); + // Close the owning Widgets to clean up the EditingHandleViews. + selection_handle_1_->CloseHandleWidget(); + selection_handle_2_->CloseHandleWidget(); + cursor_handle_->CloseHandleWidget(); } void TouchSelectionControllerImpl::SelectionChanged() { @@ -466,11 +456,11 @@ // TODO(varunjain): Fix this: crbug.com/269003 dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(focus)); - if (dragging_handle_ != cursor_handle_.get()) { + if (dragging_handle_ != cursor_handle_) { // The non-dragging-handle might have recently become visible. - EditingHandleView* non_dragging_handle = selection_handle_1_.get(); - if (dragging_handle_ == selection_handle_1_.get()) { - non_dragging_handle = selection_handle_2_.get(); + EditingHandleView* non_dragging_handle = selection_handle_1_; + if (dragging_handle_ == selection_handle_1_) { + non_dragging_handle = selection_handle_2_; // if handle 1 is being dragged, it is corresponding to the end of // selection and the other handle to the start of selection. selection_bound_1_ = screen_bound_focus; @@ -488,15 +478,13 @@ screen_bound_anchor.edge_end() == screen_bound_focus.edge_end()) { selection_handle_1_->SetWidgetVisible(false); selection_handle_2_->SetWidgetVisible(false); - SetHandleBound(cursor_handle_.get(), anchor, screen_bound_anchor_clipped); + SetHandleBound(cursor_handle_, anchor, screen_bound_anchor_clipped); return; } cursor_handle_->SetWidgetVisible(false); - SetHandleBound(selection_handle_1_.get(), anchor, - screen_bound_anchor_clipped); - SetHandleBound(selection_handle_2_.get(), focus, - screen_bound_focus_clipped); + SetHandleBound(selection_handle_1_, anchor, screen_bound_anchor_clipped); + SetHandleBound(selection_handle_2_, focus, screen_bound_focus_clipped); } } @@ -522,15 +510,15 @@ gfx::Point drag_pos_in_client = drag_pos; ConvertPointToClientView(dragging_handle_, &drag_pos_in_client); - if (dragging_handle_ == cursor_handle_.get()) { + if (dragging_handle_ == cursor_handle_) { client_view_->MoveCaretTo(drag_pos_in_client); return; } // Find the stationary selection handle. - gfx::SelectionBound anchor_bound = - selection_handle_1_.get() == dragging_handle_ ? selection_bound_2_ - : selection_bound_1_; + gfx::SelectionBound anchor_bound = selection_handle_1_ == dragging_handle_ + ? selection_bound_2_ + : selection_bound_1_; // Find selection end points in client_view's coordinate system. gfx::Point p2 = anchor_bound.edge_start_rounded(); @@ -729,12 +717,12 @@ return GetSelectionWidgetBounds(bound); } -WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() { - return selection_handle_1_.get(); +View* TouchSelectionControllerImpl::GetHandle1View() { + return selection_handle_1_; } -WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() { - return selection_handle_2_.get(); +View* TouchSelectionControllerImpl::GetHandle2View() { + return selection_handle_2_; } } // namespace views
diff --git a/ui/views/touchui/touch_selection_controller_impl.h b/ui/views/touchui/touch_selection_controller_impl.h index 46355a0..a1e3b629 100644 --- a/ui/views/touchui/touch_selection_controller_impl.h +++ b/ui/views/touchui/touch_selection_controller_impl.h
@@ -19,7 +19,6 @@ #include "ui/views/widget/widget_observer.h" namespace views { -class WidgetDelegateView; // Touch specific implementation of TouchEditingControllerDeprecated. // Responsible for displaying selection handles and menu elements relevant in a @@ -34,6 +33,9 @@ // Use ui::TouchEditingControllerFactory::Create() instead. explicit TouchSelectionControllerImpl(ui::TouchEditable* client_view); + TouchSelectionControllerImpl(const TouchSelectionControllerImpl&) = delete; + TouchSelectionControllerImpl& operator=(const TouchSelectionControllerImpl&) = + delete; ~TouchSelectionControllerImpl() override; // ui::TouchEditingControllerDeprecated: @@ -106,14 +108,16 @@ bool IsSelectionHandle2Visible(); bool IsCursorHandleVisible(); gfx::Rect GetExpectedHandleBounds(const gfx::SelectionBound& bound); - WidgetDelegateView* GetHandle1View(); - WidgetDelegateView* GetHandle2View(); + View* GetHandle1View(); + View* GetHandle2View(); ui::TouchEditable* client_view_; Widget* client_widget_ = nullptr; - std::unique_ptr<EditingHandleView> selection_handle_1_; - std::unique_ptr<EditingHandleView> selection_handle_2_; - std::unique_ptr<EditingHandleView> cursor_handle_; + // Non-owning pointers to EditingHandleViews. These views are owned by their + // Widget and cleaned up when their Widget closes. + EditingHandleView* selection_handle_1_; + EditingHandleView* selection_handle_2_; + EditingHandleView* cursor_handle_; bool command_executed_ = false; base::TimeTicks selection_start_time_; @@ -136,8 +140,6 @@ // Selection bounds, clipped to client view's boundaries. gfx::SelectionBound selection_bound_1_clipped_; gfx::SelectionBound selection_bound_2_clipped_; - - DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerImpl); }; } // namespace views
diff --git a/ui/views/touchui/touch_selection_controller_impl_unittest.cc b/ui/views/touchui/touch_selection_controller_impl_unittest.cc index b2f2d5c4..c542898 100644 --- a/ui/views/touchui/touch_selection_controller_impl_unittest.cc +++ b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -147,7 +147,7 @@ void SimulateSelectionHandleDrag(gfx::Vector2d v, int selection_handle) { TouchSelectionControllerImpl* controller = GetSelectionController(); - views::WidgetDelegateView* handle = nullptr; + views::View* handle = nullptr; if (selection_handle == 1) handle = controller->GetHandle1View(); else
diff --git a/ui/views/view.cc b/ui/views/view.cc index 885eb4ac..5315af8 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -511,8 +511,10 @@ // Notify the parent. if (parent_) { parent_->ChildVisibilityChanged(this); - parent_->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, - true); + if (!view_accessibility_ || !view_accessibility_->IsIgnored()) { + parent_->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, + true); + } } // This notifies all sub-views recursively.
diff --git a/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js b/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js index 029e992..a193123 100644 --- a/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js +++ b/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js
@@ -147,6 +147,8 @@ return 'Uninitialized'; case DeviceStateType.kDisabled: return 'Disabled'; + case DeviceStateType.kDisabling: + return 'Disabling'; case DeviceStateType.kEnabling: return 'Enabling'; case DeviceStateType.kEnabled: @@ -161,27 +163,24 @@ } /** - * @param {string} value - * @return {!chromeos.networkConfig.mojom.DeviceStateType} + * @param {!chromeos.networkConfig.mojom.DeviceStateType} value + * @return {boolean} */ - static getDeviceStateTypeFromString(value) { + static deviceStateIsIntermediate(value) { const DeviceStateType = chromeos.networkConfig.mojom.DeviceStateType; switch (value) { - case 'Uninitialized': - return DeviceStateType.kUninitialized; - case 'Disabled': - return DeviceStateType.kDisabled; - case 'Enabling': - return DeviceStateType.kEnabling; - case 'Enabled': - return DeviceStateType.kEnabled; - case 'Prohibited': - return DeviceStateType.kProhibited; - case 'Unavailable': - return DeviceStateType.kUnavailable; + case DeviceStateType.kUninitialized: + case DeviceStateType.kDisabling: + case DeviceStateType.kEnabling: + case DeviceStateType.kUnavailable: + return true; + case DeviceStateType.kDisabled: + case DeviceStateType.kEnabled: + case DeviceStateType.kProhibited: + return false; } - assertNotReached('Unexpected value: ' + value); - return DeviceStateType.kUnavailable; + assertNotReached('Unexpected enum value: ' + OncMojo.getEnumString(value)); + return false; } /**