diff --git a/BUILD.gn b/BUILD.gn index 6c5f05698..6552bd7 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -385,10 +385,10 @@ "//chrome/android:chrome_public_apk", "//chrome/android:chrome_public_test_apk", "//chrome/android/features/media_router:media_router_junit_tests", + "//chrome/browser/android/examples/custom_tabs_client:custom_tabs_client_example_apk", "//chrome/browser/android/examples/partner_browser_customizations_provider:partner_browser_customizations_example_apk", "//chrome/test/chromedriver/test/webview_shell:chromedriver_webview_shell_apk", "//content/shell/android:content_shell_test_apk", - "//third_party/custom_tabs_client:custom_tabs_client_example_apk", ] } @@ -813,8 +813,8 @@ if (build_dawn_tests) { deps += [ - "//third_party/dawn:dawn_end2end_tests_temp_group", - "//third_party/dawn:dawn_unittests_temp_group", + "//third_party/dawn/src/tests:dawn_end2end_tests", + "//third_party/dawn/src/tests:dawn_unittests", ] } @@ -928,8 +928,8 @@ "//sandbox/linux:chrome_sandbox", "//sandbox/linux:sandbox_linux_unittests", "//third_party/breakpad:minidump_stackwalk($host_toolchain)", - "//third_party/dawn:dawn_end2end_tests_temp_group", - "//third_party/dawn:dawn_unittests_temp_group", + "//third_party/dawn/src/tests:dawn_end2end_tests", + "//third_party/dawn/src/tests:dawn_unittests", # Blocked on https://github.com/catapult-project/catapult/issues/2297 #"//third_party/catapult/telemetry:bitmaptools",
diff --git a/DEPS b/DEPS index ac4afd1..11dd954 100644 --- a/DEPS +++ b/DEPS
@@ -175,11 +175,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': 'ad653d8378d7a17502956c4addebb68eb3129961', + 'skia_revision': 'eb1d5a2e233ccfa7d0f6e0ac7355bf4a17aff2d0', # 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': '02ab339626274f8c4040dd94bda29136e206827f', + 'v8_revision': 'a0ab34903ce450d674f591ce3ffdf1314a5ffa99', # 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. @@ -187,11 +187,11 @@ # 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': '965eedbfbf1e613ff4ebffe8bf4c291bc39a259c', + 'angle_revision': '3d894d87b25bcfcc1e410cbc08109ad78665c632', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '20220a0b0640436b659d0361a9d0789bc81d4177', + 'swiftshader_revision': 'e52e2dbcdf9d46b63ec6cc4df8bdea6f916c97e9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -210,7 +210,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling googletest # and whatever else without interference from each other. - 'googletest_revision': '10b1902d893ea8cc43c69541d70868f91af3646b', + 'googletest_revision': 'e3f0319d89f4cbf32993de595d984183b1a9fc57', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -246,7 +246,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': '5e43b27e8b453a22e365561b6a9a08d47999e6d4', + 'devtools_frontend_revision': 'decaee5ce9bf0b533cca09010f61e0816bf43775', # 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. @@ -525,7 +525,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'd36b5e8f3d12b4123032a3a3abc9296984a617a3', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'fb7a6f4f266117319b36ae57c89d3acf07412bb5', 'condition': 'checkout_ios', }, @@ -856,7 +856,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e9d37e79b47f1b63df9b5569047b7bbd52dbab32', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9aba22264b1bce883ebff2c54573ef26546339ad', 'condition': 'checkout_linux', }, @@ -875,11 +875,6 @@ 'condition': 'checkout_linux', }, - 'src/third_party/custom_tabs_client/src': { - 'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + 'a633542d9854151eb4f0bfd1d93da88f5934a11a', - 'condition': 'checkout_android', - }, - 'src/third_party/depot_tools': Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '08f4d59e0b177d3d15b65f9826bbf05491b3841d', @@ -1235,7 +1230,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'e1432869418635b0097a59315b7df26a6a74fc9b', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '38cf748e7a5f5da132b43e93957468f1462397a2', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1465,7 +1460,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '8a948a3e2b43db313e3afef36af4109e9d401746', + Var('webrtc_git') + '/src.git' + '@' + '3e2809f4f0cd922a0785f7bbad704fa53fcf16fc', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1540,7 +1535,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8c8408b7248ca4e68d9a3b740a99cb89cef392d5', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@62d5d8e82707f4013636a3275c612424f4cd891c', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/gfx/aw_picture.cc b/android_webview/browser/gfx/aw_picture.cc index 5e5b2d5df..3d58d45 100644 --- a/android_webview/browser/gfx/aw_picture.cc +++ b/android_webview/browser/gfx/aw_picture.cc
@@ -34,6 +34,9 @@ const JavaParamRef<jobject>& obj, const JavaParamRef<jobject>& canvas) { const SkIRect bounds = picture_->cullRect().roundOut(); + if (bounds.isEmpty()) { + return; + } std::unique_ptr<SoftwareCanvasHolder> canvas_holder = SoftwareCanvasHolder::Create(canvas, gfx::Vector2d(), gfx::Size(bounds.width(), bounds.height()),
diff --git a/android_webview/docs/developer-ui.md b/android_webview/docs/developer-ui.md index ffbd1acf..78cea80 100644 --- a/android_webview/docs/developer-ui.md +++ b/android_webview/docs/developer-ui.md
@@ -38,7 +38,52 @@ ## Crash UI -TODO(http://crbug.com/1058571): document this. +Crash UI shows recent WebView-caused crashes from apps on the device, similar +to `chrome://crashes`. You can access it by tapping the "Crashes" option in the +bottom navigation bar. + +*** note +**Note:** +You have to opt in android crash collection in order for crash reports to show +up in the UI. An error message will show up if you haven't opted-in. To opt-in, +go to the device settings > Google > three-dotted menu > Usage & diagnostics +and make sure it's enabled. For AOSP builds, you can enable crash collection +by enabling the `enable-crash-reporter-for-testing` flag from the +[Flags UI](#Flag-UI). +*** + + + +Tap a crash entry to expand it for more info and actions for that crash. + +*** note +**Note:** Some types of crashes such as renderer crashes can show up instantly +in the UI. However, most WebView crashes will require relaunching the +application where the crash happened so it can be detected and appear in the +UI. +*** + +### Force upload a crash report + +Crash reports are automatically reported to WebView's crash collection server. +Sometimes a crash report may not be automatically uploaded. For instance, when +the device is not connected to Wifi (will show in the crashes list with +"pending upload" status). The crash report can also skip upload due to random +sampling (will appear with "skipped" status). You can force upload that crash +report by pressing the "Upload this crash report" button. After the crash +report is uploaded you can then use the upload ID to open a bug report to +provide more info about that crash. + +### Provide more info about a crash + +While the crash server has most of the information we need to solve issues, it +is helpful if you can provide additional details in a bug report, such as steps +to reproduce the crash. To do so press the "File bug report" button which will +open [crbug.com](https://bugs.chromium.org/p/chromium/issues/entry?template=Webview+Bugs) +in the browser. You can use the bug report template to provide additional info +about the crash for the WebView engineering team. Make sure to fill all the +relevant fields in the bug report and leave the crash upload ID in the bug +description so that the WebView team can effectively investigate the crash. ## Flag UI
diff --git a/android_webview/docs/images/webview_crashes_ui.png b/android_webview/docs/images/webview_crashes_ui.png new file mode 100644 index 0000000..5a91217 --- /dev/null +++ b/android_webview/docs/images/webview_crashes_ui.png Binary files differ
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni index 30cab84..ce911bf 100644 --- a/android_webview/system_webview_apk_tmpl.gni +++ b/android_webview/system_webview_apk_tmpl.gni
@@ -19,7 +19,7 @@ system_webview_package_name = "com.android.webview" # Whether to enable standalone and trichrome WebView bundle build targets. - enable_webview_bundles = false + enable_webview_bundles = true } template("system_webview_apk_or_module_tmpl") {
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index e8a5e4b..8f2849b 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -734,6 +734,10 @@ "system/accessibility/autoclick_scroll_view.h", "system/accessibility/dictation_button_tray.cc", "system/accessibility/dictation_button_tray.h", + "system/accessibility/floating_accessibility_controller.cc", + "system/accessibility/floating_accessibility_controller.h", + "system/accessibility/floating_accessibility_view.cc", + "system/accessibility/floating_accessibility_view.h", "system/accessibility/floating_menu_button.cc", "system/accessibility/floating_menu_button.h", "system/accessibility/select_to_speak_tray.cc", @@ -1961,6 +1965,7 @@ "system/accessibility/accessibility_feature_pod_controller_unittest.cc", "system/accessibility/autoclick_menu_bubble_controller_unittest.cc", "system/accessibility/dictation_button_tray_unittest.cc", + "system/accessibility/floating_accessibility_controller_unittest.cc", "system/accessibility/select_to_speak_tray_unittest.cc", "system/accessibility/switch_access_menu_bubble_controller_unittest.cc", "system/accessibility/tray_accessibility_unittest.cc",
diff --git a/ash/accessibility/accessibility_controller_impl.cc b/ash/accessibility/accessibility_controller_impl.cc index d20924a..a897794f 100644 --- a/ash/accessibility/accessibility_controller_impl.cc +++ b/ash/accessibility/accessibility_controller_impl.cc
@@ -32,6 +32,7 @@ #include "ash/sticky_keys/sticky_keys_controller.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/accessibility/accessibility_feature_disable_dialog.h" +#include "ash/system/accessibility/floating_accessibility_controller.h" #include "ash/system/accessibility/switch_access_menu_bubble_controller.h" #include "ash/system/power/backlights_forced_off_setter.h" #include "ash/system/power/power_status.h" @@ -590,6 +591,10 @@ registry->RegisterBooleanPref( prefs::kAccessibilityFloatingMenuEnabled, false, user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); + registry->RegisterIntegerPref( + prefs::kAccessibilityFloatingMenuPosition, + static_cast<int>(kDefaultFloatingMenuPosition), + user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); registry->RegisterBooleanPref( prefs::kAccessibilityFocusHighlightEnabled, false, user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); @@ -1147,6 +1152,20 @@ return virtual_keyboard().IsEnterpriseIconVisible(); } +void AccessibilityControllerImpl::ShowFloatingMenuIfEnabled() { + if (floating_menu().enabled()) { + DCHECK(!floating_menu_controller_); + floating_menu_controller_ = + std::make_unique<FloatingAccessibilityController>(); + floating_menu_controller_->Show(GetFloatingMenuPosition()); + } +} + +FloatingAccessibilityController* +AccessibilityControllerImpl::GetFloatingMenuControllerForTesting() { + return floating_menu_controller_.get(); +} + void AccessibilityControllerImpl::SetTabletModeShelfNavigationButtonsEnabled( bool enabled) { if (!active_user_prefs_) @@ -1388,6 +1407,11 @@ &AccessibilityControllerImpl::UpdateAutoclickMenuPositionFromPref, base::Unretained(this))); pref_change_registrar_->Add( + prefs::kAccessibilityFloatingMenuPosition, + base::BindRepeating( + &AccessibilityControllerImpl::UpdateFloatingMenuPositionFromPref, + base::Unretained(this))); + pref_change_registrar_->Add( prefs::kAccessibilityLargeCursorDipSize, base::BindRepeating( &AccessibilityControllerImpl::UpdateLargeCursorFromPref, @@ -1445,6 +1469,7 @@ UpdateAutoclickStabilizePositionFromPref(); UpdateAutoclickMovementThresholdFromPref(); UpdateAutoclickMenuPositionFromPref(); + UpdateFloatingMenuPositionFromPref(); UpdateLargeCursorFromPref(); UpdateShortcutsEnabledFromPref(); UpdateTabletModeShelfNavigationButtonsFromPref(); @@ -1547,6 +1572,26 @@ bounds_in_screen); } +void AccessibilityControllerImpl::SetFloatingMenuPosition( + FloatingMenuPosition position) { + if (!active_user_prefs_) + return; + active_user_prefs_->SetInteger(prefs::kAccessibilityFloatingMenuPosition, + static_cast<int>(position)); + active_user_prefs_->CommitPendingWrite(); +} + +void AccessibilityControllerImpl::UpdateFloatingMenuPositionFromPref() { + if (floating_menu_controller_) + floating_menu_controller_->SetMenuPosition(GetFloatingMenuPosition()); +} + +FloatingMenuPosition AccessibilityControllerImpl::GetFloatingMenuPosition() { + DCHECK(active_user_prefs_); + return static_cast<FloatingMenuPosition>(active_user_prefs_->GetInteger( + prefs::kAccessibilityFloatingMenuPosition)); +} + void AccessibilityControllerImpl::UpdateLargeCursorFromPref() { DCHECK(active_user_prefs_); const bool enabled =
diff --git a/ash/accessibility/accessibility_controller_impl.h b/ash/accessibility/accessibility_controller_impl.h index 9e3c17f..9a9c34f 100644 --- a/ash/accessibility/accessibility_controller_impl.h +++ b/ash/accessibility/accessibility_controller_impl.h
@@ -36,6 +36,7 @@ class AccessibilityHighlightController; class AccessibilityObserver; +class FloatingAccessibilityController; class ScopedBacklightsForcedOff; class SelectToSpeakEventHandler; class SwitchAccessMenuBubbleController; @@ -58,8 +59,8 @@ kCaretHighlight, KCursorHighlight, kDictation, - kFocusHighlight, kFloatingMenu, + kFocusHighlight, kFullscreenMagnifier, kDockedMagnifier, kHighContrast, @@ -167,9 +168,9 @@ Feature& caret_highlight() const; Feature& cursor_highlight() const; FeatureWithDialog& dictation() const; + Feature& floating_menu() const; Feature& focus_highlight() const; FeatureWithDialog& fullscreen_magnifier() const; - Feature& floating_menu() const; FeatureWithDialog& docked_magnifier() const; FeatureWithDialog& high_contrast() const; Feature& large_cursor() const; @@ -205,6 +206,10 @@ FloatingMenuPosition GetAutoclickMenuPosition(); void RequestAutoclickScrollableBoundsForPoint(gfx::Point& point_in_screen); + void SetFloatingMenuPosition(FloatingMenuPosition position); + FloatingMenuPosition GetFloatingMenuPosition(); + FloatingAccessibilityController* GetFloatingMenuControllerForTesting(); + // Update the autoclick menu bounds if necessary. This may need to happen when // the display work area changes, or if system ui regions change (like the // virtual keyboard position). @@ -289,6 +294,8 @@ return tablet_mode_shelf_navigation_buttons_enabled_; } + void ShowFloatingMenuIfEnabled() override; + bool dictation_active() const { return dictation_active_; } // Returns true if accessibility shortcuts have been disabled. @@ -417,6 +424,7 @@ void UpdateAutoclickStabilizePositionFromPref(); void UpdateAutoclickMovementThresholdFromPref(); void UpdateAutoclickMenuPositionFromPref(); + void UpdateFloatingMenuPositionFromPref(); void UpdateLargeCursorFromPref(); void UpdateSwitchAccessKeyCodesFromPref(SwitchAccessCommand command); void UpdateSwitchAccessAutoScanEnabledFromPref(); @@ -461,6 +469,9 @@ std::unique_ptr<AccessibilityHighlightController> accessibility_highlight_controller_; + // Used to display accessibility floating menu. + std::unique_ptr<FloatingAccessibilityController> floating_menu_controller_; + // Used to force the backlights off to darken the screen. std::unique_ptr<ScopedBacklightsForcedOff> scoped_backlights_forced_off_;
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 609750a..648ccafc 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1862,9 +1862,6 @@ <message name="IDS_ASH_PIN_KEYBOARD_DELETE_ACCESSIBLE_NAME" desc="Text to be spoken when the focus is set to the delete button of the PIN keyboard."> Delete </message> - <message name="IDS_ASH_LOGIN_MANAGED_DEVICE_INDICATOR" desc="Template for text shown as a bottom status on the login screen, informing the user that this device is managed."> - <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> managed by <ph name="DOMAIN">$2<ex>yourdomain.com</ex></ph> - </message> <message name="IDS_ASH_LOGIN_POD_OWNER_USER" desc="Login/lock screen user pod menu title for a user who owns the device."> <ph name="USER_NAME">$1<ex>Ivan Arbuzov</ex></ph> (owner) </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_LOGIN_MANAGED_DEVICE_INDICATOR.png.sha1 b/ash/ash_strings_grd/IDS_ASH_LOGIN_MANAGED_DEVICE_INDICATOR.png.sha1 deleted file mode 100644 index 5e287ad..0000000 --- a/ash/ash_strings_grd/IDS_ASH_LOGIN_MANAGED_DEVICE_INDICATOR.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -c65621e3e10bd49f7ac4356d7c3dc5763d542be8 \ No newline at end of file
diff --git a/ash/login/ui/bottom_status_indicator.h b/ash/login/ui/bottom_status_indicator.h index 24cd08b..55cc007a 100644 --- a/ash/login/ui/bottom_status_indicator.h +++ b/ash/login/ui/bottom_status_indicator.h
@@ -24,7 +24,6 @@ public: enum class ContentType { kNone, - kManagedDevice, kAdbSideLoadingEnabled, };
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 35a13f2..12c28c4f 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -38,8 +38,6 @@ #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_provider.h" -#include "ash/system/model/enterprise_domain_model.h" -#include "ash/system/model/system_tray_model.h" #include "ash/system/power/power_button_controller.h" #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_delegate.h" @@ -60,7 +58,6 @@ #include "ui/chromeos/devicetype_utils.h" #include "ui/display/display.h" #include "ui/display/manager/display_manager.h" -#include "ui/display/manager/managed_display_info.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" @@ -507,13 +504,6 @@ std::move(bottom_status_indicator_layout)); AddChildView(bottom_status_indicator_); - std::string entreprise_domain_name = Shell::Get() - ->system_tray_model() - ->enterprise_domain() - ->enterprise_display_domain(); - if (!entreprise_domain_name.empty()) - ShowEntrepriseDomainName(entreprise_domain_name); - note_action_ = new NoteActionLaunchButton(initial_note_action_state); top_header_->AddChildView(note_action_); @@ -642,21 +632,6 @@ } } -void LockContentsView::ShowEntrepriseDomainName( - const std::string& entreprise_domain_name) { - bottom_status_indicator_->SetIcon( - kLoginScreenEnterpriseIcon, - AshColorProvider::ContentLayerType::kIconPrimary); - bottom_status_indicator_->SetText( - l10n_util::GetStringFUTF16(IDS_ASH_LOGIN_MANAGED_DEVICE_INDICATOR, - ui::GetChromeOSDeviceName(), - base::UTF8ToUTF16(entreprise_domain_name)), - gfx::kGoogleGrey200); - bottom_status_indicator_->set_content_type( - BottomStatusIndicator::ContentType::kManagedDevice); - UpdateBottomStatusIndicatorVisibility(); -} - void LockContentsView::ShowAdbEnabled() { bottom_status_indicator_->SetIcon( kLockScreenAlertIcon, AshColorProvider::ContentLayerType::kIconRed); @@ -2146,12 +2121,8 @@ } void LockContentsView::UpdateBottomStatusIndicatorVisibility() { - bool visible = - bottom_status_indicator_->content_type() == - BottomStatusIndicator::ContentType::kAdbSideLoadingEnabled || - (bottom_status_indicator_->content_type() == - BottomStatusIndicator::ContentType::kManagedDevice && - !extension_ui_visible_); + bool visible = bottom_status_indicator_->content_type() == + BottomStatusIndicator::ContentType::kAdbSideLoadingEnabled; bottom_status_indicator_->SetVisible(visible); }
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h index 165053c..a43a6c1 100644 --- a/ash/login/ui/lock_contents_view.h +++ b/ash/login/ui/lock_contents_view.h
@@ -139,7 +139,6 @@ void FocusNextUser(); void FocusPreviousUser(); - void ShowEntrepriseDomainName(const std::string& entreprise_domain_name); void ShowAdbEnabled(); void ShowSystemInfo(); void ShowParentAccessDialog(); @@ -285,8 +284,7 @@ void LayoutTopHeader(); // Lay out the bottom status indicator. This is called when system information - // is shown if ADB is enabled and at the initialization of lock screen if the - // device is enrolled. + // is shown if ADB is enabled. void LayoutBottomStatusIndicator(); // Lay out the expanded public session view. @@ -443,7 +441,7 @@ // Bubble for displaying supervised user deprecation message. LoginErrorBubble* supervised_user_deprecation_bubble_; - // Bottom status indicator displaying entreprise domain or ADB enabled alert + // Bottom status indicator displaying ADB enabled alert. BottomStatusIndicator* bottom_status_indicator_; // Tracks the visibility of the extension Ui window.
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc index 28cff72..b81ee27 100644 --- a/ash/login/ui/lock_contents_view_unittest.cc +++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -39,7 +39,6 @@ #include "ash/shelf/shelf_navigation_widget.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" -#include "ash/system/model/system_tray_model.h" #include "ash/system/power/backlights_forced_off_setter.h" #include "ash/system/power/power_button_controller.h" #include "ash/system/status_area_widget.h" @@ -716,8 +715,8 @@ test_api.system_info()->GetBoundsInScreen().right(), note_action_size.width()); - // Verify that bottom status indicator is invisible if neither adb sideloading - // is enabled nor the device is enrolled. + // Verify that warning indicator is invisible if ADB sideloading is not + // enabled. EXPECT_FALSE(test_api.bottom_status_indicator()->GetVisible()); } @@ -819,31 +818,6 @@ EXPECT_TRUE(test_api.bottom_status_indicator()->GetVisible()); } -// Show bottom status indicator if device is enrolled -TEST_F(LockContentsViewUnitTest, ShowStatusIndicatorIfEnrolledDevice) { - // If the device is enrolled, bottom_status_indicator should be visible. - Shell::Get()->system_tray_model()->SetEnterpriseDisplayDomain( - "BestCompanyEver", false); - - auto* contents = new LockContentsView( - mojom::TrayActionState::kAvailable, LockScreen::ScreenType::kLock, - DataDispatcher(), - std::make_unique<FakeLoginDetachableBaseModel>(DataDispatcher())); - SetUserCount(1); - - std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents); - LockContentsView::TestApi test_api(contents); - - EXPECT_TRUE(test_api.bottom_status_indicator()->GetVisible()); - - // bottom_status_indicator should not be visible when displaying enterprise - // domain and extension UI is visible. - DataDispatcher()->NotifyOobeDialogState(OobeDialogState::EXTENSION_LOGIN); - EXPECT_FALSE(test_api.bottom_status_indicator()->GetVisible()); - DataDispatcher()->NotifyOobeDialogState(OobeDialogState::HIDDEN); - EXPECT_TRUE(test_api.bottom_status_indicator()->GetVisible()); -} - // Verifies the easy unlock tooltip is automatically displayed when requested. TEST_F(LockContentsViewUnitTest, EasyUnlockForceTooltipCreatesTooltipWidget) { auto* lock = new LockContentsView(
diff --git a/ash/public/cpp/accessibility_controller.h b/ash/public/cpp/accessibility_controller.h index 0f062a70..3f04151a 100644 --- a/ash/public/cpp/accessibility_controller.h +++ b/ash/public/cpp/accessibility_controller.h
@@ -108,6 +108,9 @@ // Disables restoring of recommended policy values. virtual void DisablePolicyRecommendationRestorerForTesting() {} + // Shows floating accessibility menu if it was enabled by policy. + virtual void ShowFloatingMenuIfEnabled() {} + protected: AccessibilityController(); virtual ~AccessibilityController();
diff --git a/ash/public/cpp/accessibility_controller_enums.h b/ash/public/cpp/accessibility_controller_enums.h index f3c21f0..e8f58ef 100644 --- a/ash/public/cpp/accessibility_controller_enums.h +++ b/ash/public/cpp/accessibility_controller_enums.h
@@ -122,9 +122,9 @@ kMaxValue = kScroll }; -// Display location of the on-screen floating menus used by accessibility features(e.g. the -// Automatic Clicks) . These values are written to prefs so they should not be changed. New values -// should be added at the end. +// Display location of the on-screen floating menus used by accessibility +// features(e.g. the Automatic Clicks) . These values are written to prefs so +// they should not be changed. New values should be added at the end. enum class FloatingMenuPosition { // The bottom right of the screen. kBottomRight,
diff --git a/ash/public/cpp/ash_constants.h b/ash/public/cpp/ash_constants.h index f6a9fde..9e71e3c 100644 --- a/ash/public/cpp/ash_constants.h +++ b/ash/public/cpp/ash_constants.h
@@ -60,6 +60,10 @@ constexpr FloatingMenuPosition kDefaultAutoclickMenuPosition = FloatingMenuPosition::kSystemDefault; +// The default floating accessibility menu position. +constexpr FloatingMenuPosition kDefaultFloatingMenuPosition = + FloatingMenuPosition::kSystemDefault; + // The default frame color. constexpr SkColor kDefaultFrameColor = SkColorSetRGB(0xFD, 0xFE, 0xFF);
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc index 047297ea..9bee26a 100644 --- a/ash/public/cpp/ash_pref_names.cc +++ b/ash/public/cpp/ash_pref_names.cc
@@ -80,6 +80,9 @@ // A boolean pref which determines whether floating accessibility menu is // enabled. const char kAccessibilityFloatingMenuEnabled[] = "settings.a11y.floating_menu"; +// Floating a11y menu position, a FloatingMenuPosition; +const char kAccessibilityFloatingMenuPosition[] = + "settings.a11y.floating_menu_position"; // A boolean pref which determines whether focus highlighting is enabled. const char kAccessibilityFocusHighlightEnabled[] = "settings.a11y.focus_highlight";
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h index b0d8c1054..4a2b3ad 100644 --- a/ash/public/cpp/ash_pref_names.h +++ b/ash/public/cpp/ash_pref_names.h
@@ -32,6 +32,7 @@ ASH_PUBLIC_EXPORT extern const char kAccessibilityCaretHighlightEnabled[]; ASH_PUBLIC_EXPORT extern const char kAccessibilityCursorHighlightEnabled[]; ASH_PUBLIC_EXPORT extern const char kAccessibilityFloatingMenuEnabled[]; +ASH_PUBLIC_EXPORT extern const char kAccessibilityFloatingMenuPosition[]; ASH_PUBLIC_EXPORT extern const char kAccessibilityFocusHighlightEnabled[]; ASH_PUBLIC_EXPORT extern const char kAccessibilitySelectToSpeakEnabled[]; ASH_PUBLIC_EXPORT extern const char kAccessibilitySwitchAccessEnabled[];
diff --git a/ash/system/accessibility/floating_accessibility_controller.cc b/ash/system/accessibility/floating_accessibility_controller.cc new file mode 100644 index 0000000..2571ec4 --- /dev/null +++ b/ash/system/accessibility/floating_accessibility_controller.cc
@@ -0,0 +1,187 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/accessibility/floating_accessibility_controller.h" + +#include "ash/public/cpp/shell_window_ids.h" +#include "ash/session/session_controller_impl.h" +#include "ash/shell.h" +#include "ash/system/tray/tray_background_view.h" +#include "ash/system/tray/tray_constants.h" +#include "ash/wm/collision_detection/collision_detection_utils.h" +#include "ash/wm/work_area_insets.h" +#include "base/logging.h" +#include "ui/compositor/scoped_layer_animation_settings.h" + +namespace ash { + +namespace { + +constexpr int kFloatingMenuHeight = 64; +constexpr base::TimeDelta kAnimationDuration = + base::TimeDelta::FromMilliseconds(150); + +FloatingMenuPosition DefaultSystemPosition() { + return base::i18n::IsRTL() ? FloatingMenuPosition::kBottomLeft + : FloatingMenuPosition::kBottomRight; +} + +} // namespace + +FloatingAccessibilityController::FloatingAccessibilityController() { + Shell::Get()->locale_update_controller()->AddObserver(this); +} +FloatingAccessibilityController::~FloatingAccessibilityController() { + Shell::Get()->locale_update_controller()->RemoveObserver(this); + if (bubble_widget_ && !bubble_widget_->IsClosed()) + bubble_widget_->CloseNow(); +} + +void FloatingAccessibilityController::Show(FloatingMenuPosition position) { + // Kiosk check. + if (!Shell::Get()->session_controller()->IsRunningInAppMode()) { + NOTREACHED() + << "Floating accessibility menu can only be run in a kiosk session."; + return; + } + + DCHECK(!bubble_view_); + + position_ = position; + TrayBubbleView::InitParams init_params; + init_params.delegate = this; + // We need our view to be on the same level as the autoclicks menu, so neither + // of them is overlapping each other. + init_params.parent_window = Shell::GetContainer( + Shell::GetPrimaryRootWindow(), kShellWindowId_AutoclickContainer); + init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect; + // The widget's shadow is drawn below and on the sides of the view, with a + // width of kCollisionWindowWorkAreaInsetsDp. Set the top inset to 0 to ensure + // the scroll view is drawn at kCollisionWindowWorkAreaInsetsDp above the + // bubble menu when the position is at the bottom of the screen. The space + // between the bubbles belongs to the scroll view bubble's shadow. + init_params.insets = gfx::Insets(0, kCollisionWindowWorkAreaInsetsDp, + kCollisionWindowWorkAreaInsetsDp, + kCollisionWindowWorkAreaInsetsDp); + init_params.max_height = kFloatingMenuHeight; + init_params.corner_radius = kUnifiedTrayCornerRadius; + init_params.has_shadow = false; + init_params.translucent = true; + bubble_view_ = new FloatingAccessibilityBubbleView(init_params); + + menu_view_ = new FloatingAccessibilityView(this); + menu_view_->SetBorder( + views::CreateEmptyBorder(kUnifiedTopShortcutSpacing, 0, 0, 0)); + bubble_view_->AddChildView(menu_view_); + + menu_view_->SetPaintToLayer(); + menu_view_->layer()->SetFillsBoundsOpaquely(false); + + bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_); + TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_); + bubble_view_->InitializeAndShowBubble(); + + SetMenuPosition(position_); +} + +void FloatingAccessibilityController::SetMenuPosition( + FloatingMenuPosition new_position) { + if (!menu_view_ || !bubble_view_ || !bubble_widget_) + return; + + // Update the menu view's UX if the position has changed, or if it's not the + // default position (because that can change with language direction). + if (position_ != new_position || + new_position == FloatingMenuPosition::kSystemDefault) { + menu_view_->SetMenuPosition(new_position); + } + position_ = new_position; + + // If this is the default system position, pick the position based on the + // language direction. + if (new_position == FloatingMenuPosition::kSystemDefault) + new_position = DefaultSystemPosition(); + + // Calculates the ideal bounds. + // TODO(katie): Support multiple displays: draw the menu on whichever display + // the cursor is on. + aura::Window* window = Shell::GetPrimaryRootWindow(); + gfx::Rect work_area = + WorkAreaInsets::ForWindow(window)->user_work_area_bounds(); + gfx::Rect new_bounds; + + gfx::Size preferred_size = menu_view_->GetPreferredSize(); + switch (new_position) { + case FloatingMenuPosition::kBottomRight: + new_bounds = gfx::Rect(work_area.right() - preferred_size.width(), + work_area.bottom() - preferred_size.height(), + preferred_size.width(), preferred_size.height()); + break; + case FloatingMenuPosition::kBottomLeft: + new_bounds = + gfx::Rect(work_area.x(), work_area.bottom() - preferred_size.height(), + preferred_size.width(), preferred_size.height()); + break; + case FloatingMenuPosition::kTopLeft: + // Because there is no inset at the top of the widget, add + // 2 * kCollisionWindowWorkAreaInsetsDp to the top of the work area. + // to ensure correct padding. + new_bounds = gfx::Rect( + work_area.x(), work_area.y() + 2 * kCollisionWindowWorkAreaInsetsDp, + preferred_size.width(), preferred_size.height()); + break; + case FloatingMenuPosition::kTopRight: + // Because there is no inset at the top of the widget, add + // 2 * kCollisionWindowWorkAreaInsetsDp to the top of the work area. + // to ensure correct padding. + new_bounds = + gfx::Rect(work_area.right() - preferred_size.width(), + work_area.y() + 2 * kCollisionWindowWorkAreaInsetsDp, + preferred_size.width(), preferred_size.height()); + break; + case FloatingMenuPosition::kSystemDefault: + return; + } + + gfx::Rect resting_bounds = + CollisionDetectionUtils::AdjustToFitMovementAreaByGravity( + display::Screen::GetScreen()->GetDisplayNearestWindow( + bubble_widget_->GetNativeWindow()), + new_bounds); + // Un-inset the bounds to get the widget's bounds, which includes the drop + // shadow. + resting_bounds.Inset(-kCollisionWindowWorkAreaInsetsDp, 0, + -kCollisionWindowWorkAreaInsetsDp, + -kCollisionWindowWorkAreaInsetsDp); + if (bubble_widget_->GetWindowBoundsInScreen() == resting_bounds) + return; + + ui::ScopedLayerAnimationSettings settings( + bubble_widget_->GetLayer()->GetAnimator()); + settings.SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + settings.SetTransitionDuration(kAnimationDuration); + settings.SetTweenType(gfx::Tween::EASE_OUT); + bubble_widget_->SetBounds(resting_bounds); +} + +void FloatingAccessibilityController::OnDetailedMenuEnabled(bool enabled) { + // TODO(crbug.com/1061068): Implement detailed menu view logic. + detailed_view_shown_ = enabled; +} + +void FloatingAccessibilityController::BubbleViewDestroyed() { + bubble_view_ = nullptr; + bubble_widget_ = nullptr; + menu_view_ = nullptr; +} + +void FloatingAccessibilityController::OnLocaleChanged() { + // Layout update is needed when language changes between LTR and RTL, if the + // position is the system default. + if (position_ == FloatingMenuPosition::kSystemDefault) + SetMenuPosition(position_); +} + +} // namespace ash
diff --git a/ash/system/accessibility/floating_accessibility_controller.h b/ash/system/accessibility/floating_accessibility_controller.h new file mode 100644 index 0000000..28686dd --- /dev/null +++ b/ash/system/accessibility/floating_accessibility_controller.h
@@ -0,0 +1,54 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_ACCESSIBILITY_FLOATING_ACCESSIBILITY_CONTROLLER_H_ +#define ASH_SYSTEM_ACCESSIBILITY_FLOATING_ACCESSIBILITY_CONTROLLER_H_ + +#include "ash/public/cpp/accessibility_controller_enums.h" +#include "ash/public/cpp/ash_constants.h" +#include "ash/system/accessibility/floating_accessibility_view.h" +#include "ash/system/locale/locale_update_controller_impl.h" + +namespace ash { + +class FloatingAccessibilityView; + +// Controls the floating accessibility menu. +class FloatingAccessibilityController + : public FloatingAccessibilityView::Delegate, + public TrayBubbleView::Delegate, + public LocaleChangeObserver { + public: + FloatingAccessibilityController(); + FloatingAccessibilityController(const FloatingAccessibilityController&) = + delete; + FloatingAccessibilityController& operator=( + const FloatingAccessibilityController&) = delete; + ~FloatingAccessibilityController() override; + + // Starts showing the floating menu when called. + void Show(FloatingMenuPosition position); + void SetMenuPosition(FloatingMenuPosition new_position); + + private: + friend class FloatingAccessibilityControllerTest; + // FloatingAccessibilityView::Delegate: + void OnDetailedMenuEnabled(bool enabled) override; + // TrayBubbleView::Delegate: + void BubbleViewDestroyed() override; + // LocaleChangeObserver: + void OnLocaleChanged() override; + + FloatingAccessibilityView* menu_view_ = nullptr; + FloatingAccessibilityBubbleView* bubble_view_ = nullptr; + views::Widget* bubble_widget_ = nullptr; + + bool detailed_view_shown_ = false; + + FloatingMenuPosition position_ = kDefaultFloatingMenuPosition; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_ACCESSIBILITY_FLOATING_ACCESSIBILITY_CONTROLLER_H_
diff --git a/ash/system/accessibility/floating_accessibility_controller_unittest.cc b/ash/system/accessibility/floating_accessibility_controller_unittest.cc new file mode 100644 index 0000000..f45e8059 --- /dev/null +++ b/ash/system/accessibility/floating_accessibility_controller_unittest.cc
@@ -0,0 +1,179 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/accessibility/floating_accessibility_controller.h" + +#include "ash/accessibility/accessibility_controller_impl.h" +#include "ash/public/cpp/session/session_types.h" +#include "ash/session/session_controller_impl.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" + +namespace ash { + +namespace { + +// A buffer for checking whether the menu view is near this region of the +// screen. This buffer allows for things like padding and the shelf size, +// but is still smaller than half the screen size, so that we can check the +// general corner in which the menu is displayed. +const int kMenuViewBoundsBuffer = 100; + +ui::GestureEvent CreateTapEvent() { + return ui::GestureEvent(0, 0, 0, base::TimeTicks(), + ui::GestureEventDetails(ui::ET_GESTURE_TAP)); +} + +} // namespace +class FloatingAccessibilityControllerTest : public AshTestBase { + public: + AccessibilityControllerImpl* accessibility_controller() { + return Shell::Get()->accessibility_controller(); + } + + FloatingAccessibilityController* controller() { + return accessibility_controller()->GetFloatingMenuControllerForTesting(); + } + + FloatingMenuPosition menu_position() { return controller()->position_; } + + FloatingAccessibilityView* menu_view() { + return controller() ? controller()->menu_view_ : nullptr; + } + + bool detailed_view_shown() { return controller()->detailed_view_shown_; } + + views::View* GetMenuButton(FloatingAccessibilityView::ButtonId button_id) { + FloatingAccessibilityView* view = menu_view(); + if (!view) + return nullptr; + return view->GetViewByID(static_cast<int>(button_id)); + } + + void SetUpKioskSession() { + SessionInfo info; + info.is_running_in_app_mode = true; + Shell::Get()->session_controller()->SetSessionInfo(info); + } + + gfx::Rect GetMenuViewBounds() { + FloatingAccessibilityView* view = menu_view(); + return view ? view->GetBoundsInScreen() + : gfx::Rect(-kMenuViewBoundsBuffer, -kMenuViewBoundsBuffer); + } + + void Show() { accessibility_controller()->ShowFloatingMenuIfEnabled(); } + + void SetUpVisibleMenu() { + SetUpKioskSession(); + accessibility_controller()->floating_menu().SetEnabled(true); + accessibility_controller()->ShowFloatingMenuIfEnabled(); + } +}; + +TEST_F(FloatingAccessibilityControllerTest, MenuIsNotShownWhenNotEnabled) { + accessibility_controller()->ShowFloatingMenuIfEnabled(); + EXPECT_EQ(controller(), nullptr); +} + +TEST_F(FloatingAccessibilityControllerTest, ShowingMenu) { + SetUpKioskSession(); + accessibility_controller()->floating_menu().SetEnabled(true); + accessibility_controller()->ShowFloatingMenuIfEnabled(); + + EXPECT_TRUE(controller()); + EXPECT_EQ(menu_position(), + accessibility_controller()->GetFloatingMenuPosition()); +} + +TEST_F(FloatingAccessibilityControllerTest, CanChangePosition) { + SetUpVisibleMenu(); + + accessibility_controller()->SetFloatingMenuPosition( + FloatingMenuPosition::kTopRight); + + // Get the full root window bounds to test the position. + gfx::Rect window_bounds = Shell::GetPrimaryRootWindow()->bounds(); + + // Test cases rotate clockwise. + const struct { + gfx::Point expected_location; + FloatingMenuPosition expected_position; + } kTestCases[] = { + {gfx::Point(window_bounds.width(), window_bounds.height()), + FloatingMenuPosition::kBottomRight}, + {gfx::Point(0, window_bounds.height()), + FloatingMenuPosition::kBottomLeft}, + {gfx::Point(0, 0), FloatingMenuPosition::kTopLeft}, + {gfx::Point(window_bounds.width(), 0), FloatingMenuPosition::kTopRight}, + }; + + // Find the autoclick menu position button. + views::View* button = + GetMenuButton(FloatingAccessibilityView::ButtonId::kPosition); + ASSERT_TRUE(button) << "No position button found."; + + // Loop through all positions twice. + for (int i = 0; i < 2; i++) { + for (const auto& test : kTestCases) { + SCOPED_TRACE( + base::StringPrintf("Testing position #[%d]", test.expected_position)); + // Tap the position button. + ui::GestureEvent event = CreateTapEvent(); + button->OnGestureEvent(&event); + + // Pref change happened. + EXPECT_EQ(test.expected_position, menu_position()); + + // Menu is in generally the correct screen location. + EXPECT_LT( + GetMenuViewBounds().ManhattanDistanceToPoint(test.expected_location), + kMenuViewBoundsBuffer); + } + } +} + +TEST_F(FloatingAccessibilityControllerTest, DetailedViewToggle) { + SetUpVisibleMenu(); + + // Find the autoclick menu position button. + views::View* button = + GetMenuButton(FloatingAccessibilityView::ButtonId::kSettingsList); + ASSERT_TRUE(button) << "No accessibility features list button found."; + EXPECT_FALSE(detailed_view_shown()); + + ui::GestureEvent event = CreateTapEvent(); + button->OnGestureEvent(&event); + EXPECT_TRUE(detailed_view_shown()); + + event = CreateTapEvent(); + button->OnGestureEvent(&event); + EXPECT_FALSE(detailed_view_shown()); +} + +TEST_F(FloatingAccessibilityControllerTest, LocaleChangeObserver) { + SetUpVisibleMenu(); + gfx::Rect window_bounds = Shell::GetPrimaryRootWindow()->bounds(); + + // RTL should position the menu on the bottom left. + base::i18n::SetICUDefaultLocale("he"); + // Trigger the LocaleChangeObserver, which should cause a layout of the menu. + ash::LocaleUpdateController::Get()->OnLocaleChanged( + "en", "en", "he", base::DoNothing::Once<ash::LocaleNotificationResult>()); + EXPECT_TRUE(base::i18n::IsRTL()); + EXPECT_LT( + GetMenuViewBounds().ManhattanDistanceToPoint(window_bounds.bottom_left()), + kMenuViewBoundsBuffer); + + // LTR should position the menu on the bottom right. + base::i18n::SetICUDefaultLocale("en"); + ash::LocaleUpdateController::Get()->OnLocaleChanged( + "he", "he", "en", base::DoNothing::Once<ash::LocaleNotificationResult>()); + EXPECT_FALSE(base::i18n::IsRTL()); + EXPECT_LT(GetMenuViewBounds().ManhattanDistanceToPoint( + window_bounds.bottom_right()), + kMenuViewBoundsBuffer); +} + +} // namespace ash
diff --git a/ash/system/accessibility/floating_accessibility_view.cc b/ash/system/accessibility/floating_accessibility_view.cc new file mode 100644 index 0000000..13025b5 --- /dev/null +++ b/ash/system/accessibility/floating_accessibility_view.cc
@@ -0,0 +1,165 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/accessibility/floating_accessibility_view.h" + +#include "ash/accessibility/accessibility_controller_impl.h" +#include "ash/keyboard/ui/keyboard_ui_controller.h" +#include "ash/public/cpp/system_tray.h" +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/root_window_controller.h" +#include "ash/shelf/shelf.h" +#include "ash/shell.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/style/ash_color_provider.h" +#include "ash/system/accessibility/floating_menu_button.h" +#include "ash/system/tray/tray_constants.h" +#include "ui/views/controls/separator.h" +#include "ui/views/layout/box_layout.h" + +namespace ash { + +namespace { + +constexpr int kPanelPositionButtonPadding = 16; +constexpr int kPanelPositionButtonSize = 36; +constexpr int kSeparatorHeight = 16; + +std::unique_ptr<views::Separator> CreateSeparator() { + auto separator = std::make_unique<views::Separator>(); + separator->SetColor(AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kSeparator, + AshColorProvider::AshColorMode::kDark)); + separator->SetPreferredHeight(kSeparatorHeight); + int total_height = kUnifiedTopShortcutSpacing * 2 + kTrayItemSize; + int separator_spacing = (total_height - kSeparatorHeight) / 2; + separator->SetBorder(views::CreateEmptyBorder( + separator_spacing - kUnifiedTopShortcutSpacing, 0, separator_spacing, 0)); + return separator; +} + +std::unique_ptr<views::View> CreateButtonRowContainer() { + auto button_container = std::make_unique<views::View>(); + button_container->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, + gfx::Insets(0, kPanelPositionButtonPadding, kPanelPositionButtonPadding, + kPanelPositionButtonPadding), + kPanelPositionButtonPadding)); + return button_container; +} + +} // namespace + +FloatingAccessibilityBubbleView::FloatingAccessibilityBubbleView( + const TrayBubbleView::InitParams& init_params) + : TrayBubbleView(init_params) {} + +FloatingAccessibilityBubbleView::~FloatingAccessibilityBubbleView() = default; + +bool FloatingAccessibilityBubbleView::IsAnchoredToStatusArea() const { + return false; +} + +const char* FloatingAccessibilityBubbleView::GetClassName() const { + return "FloatingAccessibilityBubbleView"; +} + +FloatingAccessibilityView::FloatingAccessibilityView(Delegate* delegate) + : delegate_(delegate) { + std::unique_ptr<views::BoxLayout> layout = std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), 0); + SetLayoutManager(std::move(layout)); + + // TODO(crbug.com/1061068): Add buttons view that represents enabled features. + + std::unique_ptr<views::View> tray_button_container = + CreateButtonRowContainer(); + a11y_tray_button_ = + tray_button_container->AddChildView(std::make_unique<FloatingMenuButton>( + this, kUnifiedMenuAccessibilityIcon, + IDS_ASH_STATUS_TRAY_ACCESSIBILITY, + /*flip_for_rtl*/ true, kTrayItemSize)); + + std::unique_ptr<views::View> position_button_container = + CreateButtonRowContainer(); + position_button_ = position_button_container->AddChildView( + std::make_unique<FloatingMenuButton>( + this, kAutoclickPositionBottomLeftIcon, + IDS_ASH_AUTOCLICK_OPTION_CHANGE_POSITION, /*flip_for_rtl*/ false, + kPanelPositionButtonSize, false)); + + AddChildView(std::move(tray_button_container)); + AddChildView(CreateSeparator()); + AddChildView(std::move(position_button_container)); + + // Set view IDs for testing. + position_button_->SetId(static_cast<int>(ButtonId::kPosition)); + a11y_tray_button_->SetId(static_cast<int>(ButtonId::kSettingsList)); +} + +FloatingAccessibilityView::~FloatingAccessibilityView() {} + +void FloatingAccessibilityView::SetMenuPosition(FloatingMenuPosition position) { + switch (position) { + case FloatingMenuPosition::kBottomRight: + position_button_->SetVectorIcon(kAutoclickPositionBottomRightIcon); + return; + case FloatingMenuPosition::kBottomLeft: + position_button_->SetVectorIcon(kAutoclickPositionBottomLeftIcon); + return; + case FloatingMenuPosition::kTopLeft: + position_button_->SetVectorIcon(kAutoclickPositionTopLeftIcon); + return; + case FloatingMenuPosition::kTopRight: + position_button_->SetVectorIcon(kAutoclickPositionTopRightIcon); + return; + case FloatingMenuPosition::kSystemDefault: + position_button_->SetVectorIcon(base::i18n::IsRTL() + ? kAutoclickPositionBottomLeftIcon + : kAutoclickPositionBottomRightIcon); + return; + } +} + +void FloatingAccessibilityView::ButtonPressed(views::Button* sender, + const ui::Event& event) { + if (sender == a11y_tray_button_) { + delegate_->OnDetailedMenuEnabled(!a11y_tray_button_->IsToggled()); + a11y_tray_button_->SetToggled(!a11y_tray_button_->IsToggled()); + return; + } + + if (sender == position_button_) { + FloatingMenuPosition new_position; + // Rotate clockwise throughout the screen positions. + switch ( + Shell::Get()->accessibility_controller()->GetFloatingMenuPosition()) { + case FloatingMenuPosition::kBottomRight: + new_position = FloatingMenuPosition::kBottomLeft; + break; + case FloatingMenuPosition::kBottomLeft: + new_position = FloatingMenuPosition::kTopLeft; + break; + case FloatingMenuPosition::kTopLeft: + new_position = FloatingMenuPosition::kTopRight; + break; + case FloatingMenuPosition::kTopRight: + new_position = FloatingMenuPosition::kBottomRight; + break; + case FloatingMenuPosition::kSystemDefault: + new_position = base::i18n::IsRTL() ? FloatingMenuPosition::kTopLeft + : FloatingMenuPosition::kBottomLeft; + break; + } + Shell::Get()->accessibility_controller()->SetFloatingMenuPosition( + new_position); + } + return; +} + +const char* FloatingAccessibilityView::GetClassName() const { + return "AccessiblityFloatingView"; +} + +} // namespace ash
diff --git a/ash/system/accessibility/floating_accessibility_view.h b/ash/system/accessibility/floating_accessibility_view.h new file mode 100644 index 0000000..0041e4e --- /dev/null +++ b/ash/system/accessibility/floating_accessibility_view.h
@@ -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. + +#ifndef ASH_SYSTEM_ACCESSIBILITY_FLOATING_ACCESSIBILITY_VIEW_H_ +#define ASH_SYSTEM_ACCESSIBILITY_FLOATING_ACCESSIBILITY_VIEW_H_ + +#include <vector> + +#include "ash/public/cpp/accessibility_controller_enums.h" +#include "ash/shell_observer.h" +#include "ash/system/tray/tray_bubble_view.h" +#include "ui/views/controls/button/button.h" + +namespace ash { + +class FloatingMenuButton; + +class FloatingAccessibilityBubbleView : public TrayBubbleView { + public: + explicit FloatingAccessibilityBubbleView( + const TrayBubbleView::InitParams& init_params); + FloatingAccessibilityBubbleView(const FloatingAccessibilityBubbleView&) = + delete; + FloatingAccessibilityBubbleView& operator=( + const FloatingAccessibilityBubbleView&) = delete; + ~FloatingAccessibilityBubbleView() override; + + // TrayBubbleView: + bool IsAnchoredToStatusArea() const override; + + // views::View: + const char* GetClassName() const override; +}; + +// This floating view displays the currently enabled accessibility options, +// along with buttons to configure them. +// ---- Layout: +// ---- ?[Dictation] ?[SelectToSpeak] ?[VirtualKeyboard] +// ---- | [Open settings list] +// ---- | [Change menu location] +class FloatingAccessibilityView : public views::View, + public views::ButtonListener { + public: + // Used for testing. Starts 1 because views IDs should not be 0. + enum ButtonId { + kPosition = 1, + kSettingsList = 2, + kDictation = 3, + kSelectToSpeak = 4, + kVirtualKeyboard = 5, + }; + class Delegate { + public: + // When the user click on the settings list button. + virtual void OnDetailedMenuEnabled(bool enabled) {} + virtual ~Delegate() = default; + }; + + FloatingAccessibilityView(Delegate* delegate); + FloatingAccessibilityView& operator=(const FloatingAccessibilityView&) = + delete; + ~FloatingAccessibilityView() override; + FloatingAccessibilityView(const FloatingAccessibilityView&) = delete; + + void SetMenuPosition(FloatingMenuPosition position); + + private: + // views::ButtonListener: + void ButtonPressed(views::Button* sender, const ui::Event& event) override; + + // views::View: + const char* GetClassName() const override; + + // Button to list all available features. + FloatingMenuButton* a11y_tray_button_ = nullptr; + // Button to move the view around corners. + FloatingMenuButton* position_button_ = nullptr; + + Delegate* const delegate_; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_ACCESSIBILITY_FLOATING_ACCESSIBILITY_VIEW_H_
diff --git a/base/BUILD.gn b/base/BUILD.gn index bb24f72..5b481711 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -195,6 +195,10 @@ "callback_internal.h", "callback_list.h", "cancelable_callback.h", + "check.cc", + "check.h", + "check_op.cc", + "check_op.h", "command_line.cc", "command_line.h", "compiler_specific.h",
diff --git a/base/check.cc b/base/check.cc new file mode 100644 index 0000000..9e5e747 --- /dev/null +++ b/base/check.cc
@@ -0,0 +1,101 @@ +// 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/check.h" + +// check.h is a widely included header and its size has significant impact on +// build time. Try not to raise this limit unless absolutely necessary. See +// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md +#ifndef NACL_TC_REV +#pragma clang max_tokens_here 17000 +#endif + +#include "base/logging.h" +#include "build/build_config.h" + +namespace logging { + +CheckError CheckError::Check(const char* file, + int line, + const char* condition) { + CheckError check_error(new LogMessage(file, line, LOG_FATAL)); + check_error.stream() << "Check failed: " << condition << ". "; + return check_error; +} + +CheckError CheckError::CheckOp(const char* file, + int line, + CheckOpResult* check_op_result) { + CheckError check_error(new LogMessage(file, line, LOG_FATAL)); + check_error.stream() << "Check failed: " << check_op_result->message_; + free(check_op_result->message_); + check_op_result->message_ = nullptr; + return check_error; +} + +CheckError CheckError::DCheck(const char* file, + int line, + const char* condition) { + CheckError check_error(new LogMessage(file, line, LOG_DCHECK)); + check_error.stream() << "Check failed: " << condition << ". "; + return check_error; +} + +CheckError CheckError::DCheckOp(const char* file, + int line, + CheckOpResult* check_op_result) { + CheckError check_error(new LogMessage(file, line, LOG_DCHECK)); + check_error.stream() << "Check failed: " << check_op_result->message_; + free(check_op_result->message_); + check_op_result->message_ = nullptr; + return check_error; +} + +CheckError CheckError::PCheck(const char* file, + int line, + const char* condition) { + SystemErrorCode err_code = logging::GetLastSystemErrorCode(); +#if defined(OS_WIN) + CheckError check_error( + new Win32ErrorLogMessage(file, line, LOG_FATAL, err_code)); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + CheckError check_error(new ErrnoLogMessage(file, line, LOG_FATAL, err_code)); +#endif + check_error.stream() << "Check failed: " << condition << ". "; + return check_error; +} + +CheckError CheckError::PCheck(const char* file, int line) { + return PCheck(file, line, ""); +} + +CheckError CheckError::DPCheck(const char* file, + int line, + const char* condition) { + SystemErrorCode err_code = logging::GetLastSystemErrorCode(); +#if defined(OS_WIN) + CheckError check_error( + new Win32ErrorLogMessage(file, line, LOG_DCHECK, err_code)); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + CheckError check_error(new ErrnoLogMessage(file, line, LOG_DCHECK, err_code)); +#endif + check_error.stream() << "Check failed: " << condition << ". "; + return check_error; +} + +std::ostream& CheckError::stream() { + return log_message_->stream(); +} + +CheckError::~CheckError() { + delete log_message_; +} + +CheckError::CheckError(LogMessage* log_message) : log_message_(log_message) {} + +void RawCheck(const char* message) { + RawLog(LOG_FATAL, message); +} + +} // namespace logging
diff --git a/base/check.h b/base/check.h new file mode 100644 index 0000000..4f10d1ae --- /dev/null +++ b/base/check.h
@@ -0,0 +1,160 @@ +// 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 BASE_CHECK_H_ +#define BASE_CHECK_H_ + +#include <iosfwd> + +#include "base/base_export.h" +#include "base/compiler_specific.h" +#include "base/immediate_crash.h" + +// This header defines the CHECK, DCHECK, and DPCHECK macros. +// +// CHECK dies with a fatal error if its condition is not true. It is not +// controlled by NDEBUG, so the check will be executed regardless of compilation +// mode. +// +// DCHECK, the "debug mode" check, is enabled depending on NDEBUG and +// DCHECK_ALWAYS_ON, and its severity depends on DCHECK_IS_CONFIGURABLE. +// +// (D)PCHECK is like (D)CHECK, but includes the system error code (c.f. +// perror(3)). +// +// Additional information can be streamed to these macros and will be included +// in the log output if the condition doesn't hold (you may need to include +// <ostream>): +// +// CHECK(condition) << "Additional info."; +// +// The condition is evaluated exactly once. Even in build modes where e.g. +// DCHECK is disabled, the condition and any stream arguments are still +// referenced to avoid warnings about unused variables and functions. +// +// For the (D)CHECK_EQ, etc. macros, see base/check_op.h. However, that header +// is *significantly* larger than check.h, so try to avoid including it in +// header files. + +namespace logging { + +// Class used to explicitly ignore an ostream, and optionally a boolean value. +class VoidifyStream { + public: + VoidifyStream() = default; + explicit VoidifyStream(bool ignored) {} + + // This operator has lower precedence than << but higher than ?: + void operator&(std::ostream&) {} +}; + +// Helper macro which avoids evaluating the arguents to a stream if the +// condition is false. +#define LAZY_CHECK_STREAM(stream, condition) \ + !(condition) ? (void)0 : ::logging::VoidifyStream() & (stream) + +// Macro which uses but does not evaluate expr and any stream parameters. +#define EAT_CHECK_STREAM_PARAMS(expr) \ + true ? (void)0 \ + : ::logging::VoidifyStream(expr) & (*::logging::g_swallow_stream) +BASE_EXPORT extern std::ostream* g_swallow_stream; + +class CheckOpResult; +class LogMessage; + +// Class used for raising a check error upon destruction. +class BASE_EXPORT CheckError { + public: + static CheckError Check(const char* file, int line, const char* condition); + static CheckError CheckOp(const char* file, int line, CheckOpResult* result); + + static CheckError DCheck(const char* file, int line, const char* condition); + static CheckError DCheckOp(const char* file, int line, CheckOpResult* result); + + static CheckError PCheck(const char* file, int line, const char* condition); + static CheckError PCheck(const char* file, int line); + + static CheckError DPCheck(const char* file, int line, const char* condition); + + // Stream for adding optional details to the error message. + std::ostream& stream(); + + ~CheckError(); + + CheckError(const CheckError& other) = delete; + CheckError& operator=(const CheckError& other) = delete; + CheckError(CheckError&& other) = default; + CheckError& operator=(CheckError&& other) = default; + + private: + explicit CheckError(LogMessage* log_message); + + LogMessage* log_message_; +}; + +#if defined(OFFICIAL_BUILD) && defined(NDEBUG) + +// Discard log strings to reduce code bloat. +// +// This is not calling BreakDebugger since this is called frequently, and +// calling an out-of-line function instead of a noreturn inline macro prevents +// compiler optimizations. +#define CHECK(condition) \ + UNLIKELY(!(condition)) ? IMMEDIATE_CRASH() : EAT_CHECK_STREAM_PARAMS() + +#define PCHECK(condition) \ + LAZY_CHECK_STREAM( \ + ::logging::CheckError::PCheck(__FILE__, __LINE__).stream(), \ + UNLIKELY(!(condition))) + +#else + +#define CHECK(condition) \ + LAZY_CHECK_STREAM( \ + ::logging::CheckError::Check(__FILE__, __LINE__, #condition).stream(), \ + !ANALYZER_ASSUME_TRUE(condition)) + +#define PCHECK(condition) \ + LAZY_CHECK_STREAM( \ + ::logging::CheckError::PCheck(__FILE__, __LINE__, #condition).stream(), \ + !ANALYZER_ASSUME_TRUE(condition)) + +#endif + +#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) +#define DCHECK_IS_ON() false +#else +#define DCHECK_IS_ON() true +#endif + +#if DCHECK_IS_ON() + +#define DCHECK(condition) \ + LAZY_CHECK_STREAM( \ + ::logging::CheckError::DCheck(__FILE__, __LINE__, #condition).stream(), \ + !ANALYZER_ASSUME_TRUE(condition)) + +#define DPCHECK(condition) \ + LAZY_CHECK_STREAM( \ + ::logging::CheckError::DPCheck(__FILE__, __LINE__, #condition).stream(), \ + !ANALYZER_ASSUME_TRUE(condition)) + +#else + +#define DCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition)) +#define DPCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition)) + +#endif + +// Async signal safe checking mechanism. +BASE_EXPORT void RawCheck(const char* message); +#define RAW_CHECK(condition) \ + do { \ + if (!(condition)) \ + ::logging::RawCheck("Check failed: " #condition "\n"); \ + } while (0) + +} // namespace logging + +#endif // BASE_CHECK_H_
diff --git a/base/check_op.cc b/base/check_op.cc new file mode 100644 index 0000000..7e080646 --- /dev/null +++ b/base/check_op.cc
@@ -0,0 +1,68 @@ +// 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/check_op.h" + +// check_op.h is a widely included header and its size has significant impact on +// build time. Try not to raise this limit unless absolutely necessary. See +// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md +#ifndef NACL_TC_REV +#pragma clang max_tokens_here 235000 +#endif + +#include <cstdio> +#include <sstream> + +namespace logging { + +char* CheckOpValueStr(int v) { + char buf[50]; + snprintf(buf, sizeof(buf), "%d", v); + return strdup(buf); +} + +char* CheckOpValueStr(unsigned v) { + char buf[50]; + snprintf(buf, sizeof(buf), "%u", v); + return strdup(buf); +} + +char* CheckOpValueStr(unsigned long v) { + char buf[50]; + snprintf(buf, sizeof(buf), "%lu", v); + return strdup(buf); +} + +char* CheckOpValueStr(const void* v) { + char buf[50]; + snprintf(buf, sizeof(buf), "%p", v); + return strdup(buf); +} + +char* CheckOpValueStr(std::nullptr_t v) { + return strdup("nullptr"); +} + +char* CheckOpValueStr(double v) { + char buf[50]; + snprintf(buf, sizeof(buf), "%.6lf", v); + return strdup(buf); +} + +char* StreamValToStr(const void* v, + void (*stream_func)(std::ostream&, const void*)) { + std::stringstream ss; + stream_func(ss, v); + return strdup(ss.str().c_str()); +} + +CheckOpResult::CheckOpResult(const char* expr_str, char* v1_str, char* v2_str) { + std::ostringstream ss; + ss << expr_str << " (" << v1_str << " vs. " << v2_str << ")"; + message_ = strdup(ss.str().c_str()); + free(v1_str); + free(v2_str); +} + +} // namespace logging
diff --git a/base/check_op.h b/base/check_op.h new file mode 100644 index 0000000..67e28d1d --- /dev/null +++ b/base/check_op.h
@@ -0,0 +1,218 @@ +// 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 BASE_CHECK_OP_H_ +#define BASE_CHECK_OP_H_ + +#include <cstddef> +#include <type_traits> + +#include "base/check.h" +#include "base/template_util.h" + +// This header defines the (DP)CHECK_EQ etc. macros. +// +// (DP)CHECK_EQ(x, y) is similar to (DP)CHECK(x == y) but will also log the +// values of x and y if the condition doesn't old. This works for basic types +// and types with an operator<< or .ToString() method. +// +// The operands are evaluated exactly once, and even in build modes where e.g. +// DCHECK is disabled, the operands and their stringification methods are still +// referenced to avoid warnings about unused variables or functions. +// +// To support the stringification of the check operands, this header is +// *significantly* larger than base/check.h, so it should be avoided in common +// headers. + +namespace logging { + +// Functions for turning check operand values into strings. +// Caller takes ownership of the returned string. +BASE_EXPORT char* CheckOpValueStr(int v); +BASE_EXPORT char* CheckOpValueStr(unsigned v); +BASE_EXPORT char* CheckOpValueStr(unsigned long v); +BASE_EXPORT char* CheckOpValueStr(const void* v); +BASE_EXPORT char* CheckOpValueStr(std::nullptr_t v); +BASE_EXPORT char* CheckOpValueStr(double v); + +// Convert a streamable value to string out-of-line to avoid <sstream>. +BASE_EXPORT char* StreamValToStr(const void* v, + void (*stream_func)(std::ostream&, + const void*)); + +template <typename T> +inline typename std::enable_if< + base::internal::SupportsOstreamOperator<const T&>::value && + !std::is_function<typename std::remove_pointer<T>::type>::value, + char*>::type +CheckOpValueStr(const T& v) { + auto f = [](std::ostream& s, const void* p) { + s << *reinterpret_cast<const T*>(p); + }; + + // operator& might be overloaded, so do the std::addressof dance. + // __builtin_addressof is preferred since it also handles Obj-C ARC pointers. + // Some casting is still needed, because T might be volatile. +#if defined(__has_builtin) && __has_builtin(__builtin_addressof) + const void* vp = const_cast<const void*>( + reinterpret_cast<const volatile void*>(__builtin_addressof(v))); +#else + const void* vp = reinterpret_cast<const void*>( + const_cast<const char*>(&reinterpret_cast<const volatile char&>(v))); +#endif + return StreamValToStr(vp, f); +} + +// Overload for types that have no operator<< but do have .ToString() defined. +template <typename T> +inline typename std::enable_if< + !base::internal::SupportsOstreamOperator<const T&>::value && + base::internal::SupportsToString<const T&>::value, + char*>::type +CheckOpValueStr(const T& v) { + return strdup(v.ToString().c_str()); +} + +// Provide an overload for functions and function pointers. Function pointers +// don't implicitly convert to void* but do implicitly convert to bool, so +// without this function pointers are always printed as 1 or 0. (MSVC isn't +// standards-conforming here and converts function pointers to regular +// pointers, so this is a no-op for MSVC.) +template <typename T> +inline typename std::enable_if< + std::is_function<typename std::remove_pointer<T>::type>::value, + char*>::type +CheckOpValueStr(const T& v) { + return CheckOpValueStr(reinterpret_cast<const void*>(v)); +} + +// We need overloads for enums that don't support operator<<. +// (i.e. scoped enums where no operator<< overload was declared). +template <typename T> +inline typename std::enable_if< + !base::internal::SupportsOstreamOperator<const T&>::value && + std::is_enum<T>::value, + char*>::type +CheckOpValueStr(const T& v) { + return CheckOpValueStr( + static_cast<typename std::underlying_type<T>::type>(v)); +} + +// Captures the result of a CHECK_op and facilitates testing as a boolean. +class CheckOpResult { + public: + // An empty result signals success. + constexpr CheckOpResult() : message_(nullptr) {} + + // A non-success result. expr_str is something like "foo != bar". v1_str and + // v2_str are the stringified run-time values of foo and bar. Takes ownership + // of v1_str and v2_str. + BASE_EXPORT CheckOpResult(const char* expr_str, char* v1_str, char* v2_str); + + // Returns true if the check succeeded. + constexpr explicit operator bool() const { return !message_; } + + friend class CheckError; + + private: + char* message_; +}; + +#if defined(OFFICIAL_BUILD) && defined(NDEBUG) + +// Discard log strings to reduce code bloat. +#define CHECK_OP(name, op, val1, val2) CHECK((val1)op(val2)) + +#else + +// Helper macro for binary operators. +// The 'switch' is used to prevent the 'else' from being ambiguous when the +// macro is used in an 'if' clause such as: +// if (a == 1) +// CHECK_EQ(2, a); +#define CHECK_OP(name, op, val1, val2) \ + switch (0) \ + case 0: \ + default: \ + if (::logging::CheckOpResult true_if_passed = \ + ::logging::Check##name##Impl((val1), (val2), \ + #val1 " " #op " " #val2)) \ + ; \ + else \ + ::logging::CheckError::CheckOp(__FILE__, __LINE__, &true_if_passed) \ + .stream() + +#endif + +// The int-int overload avoids address-taking static int members. +#define DEFINE_CHECK_OP_IMPL(name, op) \ + template <typename T, typename U> \ + constexpr ::logging::CheckOpResult Check##name##Impl( \ + const T& v1, const U& v2, const char* expr_str) { \ + if (ANALYZER_ASSUME_TRUE(v1 op v2)) \ + return ::logging::CheckOpResult(); \ + else \ + return ::logging::CheckOpResult(expr_str, CheckOpValueStr(v1), \ + CheckOpValueStr(v2)); \ + } \ + constexpr ::logging::CheckOpResult Check##name##Impl(int v1, int v2, \ + const char* expr_str) { \ + if (ANALYZER_ASSUME_TRUE(v1 op v2)) \ + return ::logging::CheckOpResult(); \ + else \ + return ::logging::CheckOpResult(expr_str, CheckOpValueStr(v1), \ + CheckOpValueStr(v2)); \ + } + +// clang-format off +DEFINE_CHECK_OP_IMPL(EQ, ==) +DEFINE_CHECK_OP_IMPL(NE, !=) +DEFINE_CHECK_OP_IMPL(LE, <=) +DEFINE_CHECK_OP_IMPL(LT, < ) +DEFINE_CHECK_OP_IMPL(GE, >=) +DEFINE_CHECK_OP_IMPL(GT, > ) +#undef DEFINE_CHECK_OP_IMPL +#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2) +#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2) +#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2) +#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2) +#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2) +#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2) +// clang-format on + +#if DCHECK_IS_ON() + +#define DCHECK_OP(name, op, val1, val2) \ + switch (0) \ + case 0: \ + default: \ + if (::logging::CheckOpResult true_if_passed = \ + ::logging::Check##name##Impl((val1), (val2), \ + #val1 " " #op " " #val2)) \ + ; \ + else \ + ::logging::CheckError::DCheckOp(__FILE__, __LINE__, &true_if_passed) \ + .stream() + +#else + +// Don't do any evaluation but still reference the same stuff as when enabled. +#define DCHECK_OP(name, op, val1, val2) \ + EAT_CHECK_STREAM_PARAMS((::logging::CheckOpValueStr(val1), \ + ::logging::CheckOpValueStr(val2), (val1)op(val2))) + +#endif + +// clang-format off +#define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2) +#define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2) +#define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2) +#define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2) +#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2) +#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2) +// clang-format on + +} // namespace logging + +#endif // BASE_CHECK_OP_H_
diff --git a/base/check_unittest.cc b/base/check_unittest.cc index 6cdc372b..fd81621 100644 --- a/base/check_unittest.cc +++ b/base/check_unittest.cc
@@ -87,9 +87,10 @@ EXPECT_CHECK("Check failed: false. foo", CHECK(false) << "foo"); double a = 2, b = 1; - EXPECT_CHECK("Check failed: a < b (2 vs. 1)", CHECK_LT(a, b)); + EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000)", CHECK_LT(a, b)); - EXPECT_CHECK("Check failed: a < b (2 vs. 1)foo", CHECK_LT(a, b) << "foo"); + EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000)foo", + CHECK_LT(a, b) << "foo"); } TEST_F(CheckTest, PCheck) {
diff --git a/base/compiler_specific.h b/base/compiler_specific.h index 2962537..592c496 100644 --- a/base/compiler_specific.h +++ b/base/compiler_specific.h
@@ -247,4 +247,36 @@ #define STACK_UNINITIALIZED #endif +// The ANALYZER_ASSUME_TRUE(bool arg) macro adds compiler-specific hints +// to Clang which control what code paths are statically analyzed, +// and is meant to be used in conjunction with assert & assert-like functions. +// The expression is passed straight through if analysis isn't enabled. +// +// ANALYZER_SKIP_THIS_PATH() suppresses static analysis for the current +// codepath and any other branching codepaths that might follow. +#if defined(__clang_analyzer__) + +inline constexpr bool AnalyzerNoReturn() __attribute__((analyzer_noreturn)) { + return false; +} + +inline constexpr bool AnalyzerAssumeTrue(bool arg) { + // AnalyzerNoReturn() is invoked and analysis is terminated if |arg| is + // false. + return arg || AnalyzerNoReturn(); +} + +#define ANALYZER_ASSUME_TRUE(arg) logging::AnalyzerAssumeTrue(!!(arg)) +#define ANALYZER_SKIP_THIS_PATH() \ + static_cast<void>(::logging::AnalyzerNoReturn()) +#define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var); + +#else // !defined(__clang_analyzer__) + +#define ANALYZER_ASSUME_TRUE(arg) (arg) +#define ANALYZER_SKIP_THIS_PATH() +#define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var); + +#endif // defined(__clang_analyzer__) + #endif // BASE_COMPILER_SPECIFIC_H_
diff --git a/base/fuchsia/fuchsia_logging.h b/base/fuchsia/fuchsia_logging.h index ba55f8db..46d33e77 100644 --- a/base/fuchsia/fuchsia_logging.h +++ b/base/fuchsia/fuchsia_logging.h
@@ -24,7 +24,7 @@ int line, LogSeverity severity, zx_status_t zx_err); - ~ZxLogMessage(); + ~ZxLogMessage() override; private: zx_status_t zx_err_;
diff --git a/base/logging.cc b/base/logging.cc index 608cc1122..57f68adbd 100644 --- a/base/logging.cc +++ b/base/logging.cc
@@ -4,6 +4,13 @@ #include "base/logging.h" +// logging.h is a widely included header and its size has significant impact on +// build time. Try not to raise this limit unless absolutely necessary. See +// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md +#ifndef NACL_TC_REV +#pragma clang max_tokens_here 370000 +#endif // NACL_TC_REV + #include <limits.h> #include <stdint.h> @@ -551,22 +558,6 @@ return log_message_handler; } -// Explicit instantiations for commonly used comparisons. -template std::string* MakeCheckOpString<int, int>( - const int&, const int&, const char* names); -template std::string* MakeCheckOpString<unsigned long, unsigned long>( - const unsigned long&, const unsigned long&, const char* names); -template std::string* MakeCheckOpString<unsigned long, unsigned int>( - const unsigned long&, const unsigned int&, const char* names); -template std::string* MakeCheckOpString<unsigned int, unsigned long>( - const unsigned int&, const unsigned long&, const char* names); -template std::string* MakeCheckOpString<std::string, std::string>( - const std::string&, const std::string&, const char* name); - -void MakeCheckOpValueString(std::ostream* os, std::nullptr_t p) { - (*os) << "nullptr"; -} - #if !defined(NDEBUG) // Displays a message box to the user with the error message in it. // Used for fatal messages, where we close the app simultaneously. @@ -604,21 +595,6 @@ stream_ << "Check failed: " << condition << ". "; } -LogMessage::LogMessage(const char* file, int line, std::string* result) - : severity_(LOG_FATAL), file_(file), line_(line) { - Init(file, line); - stream_ << "Check failed: " << *result; - delete result; -} - -LogMessage::LogMessage(const char* file, int line, LogSeverity severity, - std::string* result) - : severity_(severity), file_(file), line_(line) { - Init(file, line); - stream_ << "Check failed: " << *result; - delete result; -} - LogMessage::~LogMessage() { size_t stack_start = stream_.tellp(); #if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && !defined(__UCLIBC__) && \ @@ -1066,9 +1042,7 @@ int line, LogSeverity severity, SystemErrorCode err) - : err_(err), - log_message_(file, line, severity) { -} + : LogMessage(file, line, severity), err_(err) {} Win32ErrorLogMessage::~Win32ErrorLogMessage() { stream() << ": " << SystemErrorCodeToString(err_); @@ -1082,9 +1056,7 @@ int line, LogSeverity severity, SystemErrorCode err) - : err_(err), - log_message_(file, line, severity) { -} + : LogMessage(file, line, severity), err_(err) {} ErrnoLogMessage::~ErrnoLogMessage() { stream() << ": " << SystemErrorCodeToString(err_);
diff --git a/base/logging.h b/base/logging.h index bc602f9..7644ec1 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -9,21 +9,18 @@ #include <cassert> #include <cstdint> -#include <cstring> #include <sstream> #include <string> -#include <type_traits> -#include <utility> #include "base/base_export.h" #include "base/callback_forward.h" +#include "base/check.h" +#include "base/check_op.h" #include "base/compiler_specific.h" -#include "base/immediate_crash.h" #include "base/logging_buildflags.h" #include "base/macros.h" #include "base/scoped_clear_last_error.h" #include "base/strings/string_piece_forward.h" -#include "base/template_util.h" #include "build/build_config.h" #if defined(OS_CHROMEOS) @@ -338,37 +335,6 @@ BASE_EXPORT void SetLogMessageHandler(LogMessageHandlerFunction handler); BASE_EXPORT LogMessageHandlerFunction GetLogMessageHandler(); -// The ANALYZER_ASSUME_TRUE(bool arg) macro adds compiler-specific hints -// to Clang which control what code paths are statically analyzed, -// and is meant to be used in conjunction with assert & assert-like functions. -// The expression is passed straight through if analysis isn't enabled. -// -// ANALYZER_SKIP_THIS_PATH() suppresses static analysis for the current -// codepath and any other branching codepaths that might follow. -#if defined(__clang_analyzer__) - -inline constexpr bool AnalyzerNoReturn() __attribute__((analyzer_noreturn)) { - return false; -} - -inline constexpr bool AnalyzerAssumeTrue(bool arg) { - // AnalyzerNoReturn() is invoked and analysis is terminated if |arg| is - // false. - return arg || AnalyzerNoReturn(); -} - -#define ANALYZER_ASSUME_TRUE(arg) logging::AnalyzerAssumeTrue(!!(arg)) -#define ANALYZER_SKIP_THIS_PATH() \ - static_cast<void>(::logging::AnalyzerNoReturn()) -#define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var); - -#else // !defined(__clang_analyzer__) - -#define ANALYZER_ASSUME_TRUE(arg) (arg) -#define ANALYZER_SKIP_THIS_PATH() -#define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var); - -#endif // defined(__clang_analyzer__) typedef int LogSeverity; const LogSeverity LOG_VERBOSE = -1; // This is level 1 verbosity @@ -525,203 +491,6 @@ true ? (void)0 \ : ::logging::LogMessageVoidify() & (*::logging::g_swallow_stream) -// Captures the result of a CHECK_EQ (for example) and facilitates testing as a -// boolean. -class CheckOpResult { - public: - // |message| must be non-null if and only if the check failed. - constexpr CheckOpResult(std::string* message) : message_(message) {} - // Returns true if the check succeeded. - constexpr operator bool() const { return !message_; } - // Returns the message. - std::string* message() { return message_; } - - private: - std::string* message_; -}; - -// CHECK dies with a fatal error if condition is not true. It is *not* -// controlled by NDEBUG, so the check will be executed regardless of -// compilation mode. -// -// We make sure CHECK et al. always evaluates their arguments, as -// doing CHECK(FunctionWithSideEffect()) is a common idiom. - -#if defined(OFFICIAL_BUILD) && defined(NDEBUG) - -// Make all CHECK functions discard their log strings to reduce code bloat, and -// improve performance, for official release builds. -// -// This is not calling BreakDebugger since this is called frequently, and -// calling an out-of-line function instead of a noreturn inline macro prevents -// compiler optimizations. -#define CHECK(condition) \ - UNLIKELY(!(condition)) ? IMMEDIATE_CRASH() : EAT_STREAM_PARAMETERS - -// PCHECK includes the system error code, which is useful for determining -// why the condition failed. In official builds, preserve only the error code -// message so that it is available in crash reports. The stringified -// condition and any additional stream parameters are dropped. -#define PCHECK(condition) \ - LAZY_STREAM(PLOG_STREAM(FATAL), UNLIKELY(!(condition))); \ - EAT_STREAM_PARAMETERS - -#define CHECK_OP(name, op, val1, val2) CHECK((val1) op (val2)) - -#else // !(OFFICIAL_BUILD && NDEBUG) - -// Do as much work as possible out of line to reduce inline code size. -#define CHECK(condition) \ - LAZY_STREAM(::logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \ - !ANALYZER_ASSUME_TRUE(condition)) - -#define PCHECK(condition) \ - LAZY_STREAM(PLOG_STREAM(FATAL), !ANALYZER_ASSUME_TRUE(condition)) \ - << "Check failed: " #condition ". " - -// Helper macro for binary operators. -// Don't use this macro directly in your code, use CHECK_EQ et al below. -// The 'switch' is used to prevent the 'else' from being ambiguous when the -// macro is used in an 'if' clause such as: -// if (a == 1) -// CHECK_EQ(2, a); -#define CHECK_OP(name, op, val1, val2) \ - switch (0) case 0: default: \ - if (::logging::CheckOpResult true_if_passed = \ - ::logging::Check##name##Impl((val1), (val2), \ - #val1 " " #op " " #val2)) \ - ; \ - else \ - ::logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream() - -#endif // !(OFFICIAL_BUILD && NDEBUG) - -// This formats a value for a failing CHECK_XX statement. Ordinarily, -// it uses the definition for operator<<, with a few special cases below. -template <typename T> -inline typename std::enable_if< - base::internal::SupportsOstreamOperator<const T&>::value && - !std::is_function<typename std::remove_pointer<T>::type>::value, - void>::type -MakeCheckOpValueString(std::ostream* os, const T& v) { - (*os) << v; -} - -// Overload for types that no operator<< but do have .ToString() defined. -template <typename T> -inline typename std::enable_if< - !base::internal::SupportsOstreamOperator<const T&>::value && - base::internal::SupportsToString<const T&>::value, - void>::type -MakeCheckOpValueString(std::ostream* os, const T& v) { - (*os) << v.ToString(); -} - -// Provide an overload for functions and function pointers. Function pointers -// don't implicitly convert to void* but do implicitly convert to bool, so -// without this function pointers are always printed as 1 or 0. (MSVC isn't -// standards-conforming here and converts function pointers to regular -// pointers, so this is a no-op for MSVC.) -template <typename T> -inline typename std::enable_if< - std::is_function<typename std::remove_pointer<T>::type>::value, - void>::type -MakeCheckOpValueString(std::ostream* os, const T& v) { - (*os) << reinterpret_cast<const void*>(v); -} - -// We need overloads for enums that don't support operator<<. -// (i.e. scoped enums where no operator<< overload was declared). -template <typename T> -inline typename std::enable_if< - !base::internal::SupportsOstreamOperator<const T&>::value && - std::is_enum<T>::value, - void>::type -MakeCheckOpValueString(std::ostream* os, const T& v) { - (*os) << static_cast<typename std::underlying_type<T>::type>(v); -} - -// We need an explicit overload for std::nullptr_t. -BASE_EXPORT void MakeCheckOpValueString(std::ostream* os, std::nullptr_t p); - -// Build the error message string. This is separate from the "Impl" -// function template because it is not performance critical and so can -// be out of line, while the "Impl" code should be inline. Caller -// takes ownership of the returned string. -template<class t1, class t2> -std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { - std::ostringstream ss; - ss << names << " ("; - MakeCheckOpValueString(&ss, v1); - ss << " vs. "; - MakeCheckOpValueString(&ss, v2); - ss << ")"; - std::string* msg = new std::string(ss.str()); - return msg; -} - -// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated -// in logging.cc. -extern template BASE_EXPORT std::string* MakeCheckOpString<int, int>( - const int&, const int&, const char* names); -extern template BASE_EXPORT -std::string* MakeCheckOpString<unsigned long, unsigned long>( - const unsigned long&, const unsigned long&, const char* names); -extern template BASE_EXPORT -std::string* MakeCheckOpString<unsigned long, unsigned int>( - const unsigned long&, const unsigned int&, const char* names); -extern template BASE_EXPORT -std::string* MakeCheckOpString<unsigned int, unsigned long>( - const unsigned int&, const unsigned long&, const char* names); -extern template BASE_EXPORT -std::string* MakeCheckOpString<std::string, std::string>( - const std::string&, const std::string&, const char* name); - -// Helper functions for CHECK_OP macro. -// The (int, int) specialization works around the issue that the compiler -// will not instantiate the template version of the function on values of -// unnamed enum type - see comment below. -// -// The checked condition is wrapped with ANALYZER_ASSUME_TRUE, which under -// static analysis builds, blocks analysis of the current path if the -// condition is false. -#define DEFINE_CHECK_OP_IMPL(name, op) \ - template <class t1, class t2> \ - constexpr std::string* Check##name##Impl(const t1& v1, const t2& v2, \ - const char* names) { \ - if (ANALYZER_ASSUME_TRUE(v1 op v2)) \ - return nullptr; \ - else \ - return ::logging::MakeCheckOpString(v1, v2, names); \ - } \ - constexpr std::string* Check##name##Impl(int v1, int v2, \ - const char* names) { \ - if (ANALYZER_ASSUME_TRUE(v1 op v2)) \ - return nullptr; \ - else \ - return ::logging::MakeCheckOpString(v1, v2, names); \ - } -DEFINE_CHECK_OP_IMPL(EQ, ==) -DEFINE_CHECK_OP_IMPL(NE, !=) -DEFINE_CHECK_OP_IMPL(LE, <=) -DEFINE_CHECK_OP_IMPL(LT, < ) -DEFINE_CHECK_OP_IMPL(GE, >=) -DEFINE_CHECK_OP_IMPL(GT, > ) -#undef DEFINE_CHECK_OP_IMPL - -#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2) -#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2) -#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2) -#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2) -#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2) -#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2) - -#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) -#define DCHECK_IS_ON() false -#else -#define DCHECK_IS_ON() true -#endif - // Definitions for DLOG et al. #if DCHECK_IS_ON() @@ -776,95 +545,6 @@ #endif // DCHECK_IS_ON() -// DCHECK et al. make sure to reference |condition| regardless of -// whether DCHECKs are enabled; this is so that we don't get unused -// variable warnings if the only use of a variable is in a DCHECK. -// This behavior is different from DLOG_IF et al. -// -// Note that the definition of the DCHECK macros depends on whether or not -// DCHECK_IS_ON() is true. When DCHECK_IS_ON() is false, the macros use -// EAT_STREAM_PARAMETERS to avoid expressions that would create temporaries. - -#if DCHECK_IS_ON() - -#define DCHECK(condition) \ - LAZY_STREAM(LOG_STREAM(DCHECK), !ANALYZER_ASSUME_TRUE(condition)) \ - << "Check failed: " #condition ". " -#define DPCHECK(condition) \ - LAZY_STREAM(PLOG_STREAM(DCHECK), !ANALYZER_ASSUME_TRUE(condition)) \ - << "Check failed: " #condition ". " - -#else // DCHECK_IS_ON() - -#define DCHECK(condition) EAT_STREAM_PARAMETERS << !(condition) -#define DPCHECK(condition) EAT_STREAM_PARAMETERS << !(condition) - -#endif // DCHECK_IS_ON() - -// Helper macro for binary operators. -// Don't use this macro directly in your code, use DCHECK_EQ et al below. -// The 'switch' is used to prevent the 'else' from being ambiguous when the -// macro is used in an 'if' clause such as: -// if (a == 1) -// DCHECK_EQ(2, a); -#if DCHECK_IS_ON() - -#define DCHECK_OP(name, op, val1, val2) \ - switch (0) case 0: default: \ - if (::logging::CheckOpResult true_if_passed = \ - ::logging::Check##name##Impl((val1), (val2), \ - #val1 " " #op " " #val2)) \ - ; \ - else \ - ::logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \ - true_if_passed.message()).stream() - -#else // DCHECK_IS_ON() - -// When DCHECKs aren't enabled, DCHECK_OP still needs to reference operator<< -// overloads for |val1| and |val2| to avoid potential compiler warnings about -// unused functions. For the same reason, it also compares |val1| and |val2| -// using |op|. -// -// Note that the contract of DCHECK_EQ, etc is that arguments are only evaluated -// once. Even though |val1| and |val2| appear twice in this version of the macro -// expansion, this is OK, since the expression is never actually evaluated. -#define DCHECK_OP(name, op, val1, val2) \ - EAT_STREAM_PARAMETERS << (::logging::MakeCheckOpValueString( \ - ::logging::g_swallow_stream, val1), \ - ::logging::MakeCheckOpValueString( \ - ::logging::g_swallow_stream, val2), \ - (val1)op(val2)) - -#endif // DCHECK_IS_ON() - -// Equality/Inequality checks - compare two values, and log a -// LOG_DCHECK message including the two values when the result is not -// as expected. The values must have operator<<(ostream, ...) -// defined. -// -// You may append to the error message like so: -// DCHECK_NE(1, 2) << "The world must be ending!"; -// -// We are very careful to ensure that each argument is evaluated exactly -// once, and that anything which is legal to pass as a function argument is -// legal here. In particular, the arguments may be temporary expressions -// which will end up being destroyed at the end of the apparent statement, -// for example: -// DCHECK_EQ(string("abc")[1], 'b'); -// -// WARNING: These don't compile correctly if one of the arguments is a pointer -// and the other is NULL. In new code, prefer nullptr instead. To -// work around this for C++98, simply static_cast NULL to the type of the -// desired pointer. - -#define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2) -#define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2) -#define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2) -#define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2) -#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2) -#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2) - #if BUILDFLAG(ENABLE_LOG_ERROR_NOT_REACHED) // Implement logging of NOTREACHED() as a dedicated function to get function // call overhead down to a minimum. @@ -896,15 +576,7 @@ // Used for CHECK(). Implied severity = LOG_FATAL. LogMessage(const char* file, int line, const char* condition); - // Used for CHECK_EQ(), etc. Takes ownership of the given string. - // Implied severity = LOG_FATAL. - LogMessage(const char* file, int line, std::string* result); - - // Used for DCHECK_EQ(), etc. Takes ownership of the given string. - LogMessage(const char* file, int line, LogSeverity severity, - std::string* result); - - ~LogMessage(); + virtual ~LogMessage(); std::ostream& stream() { return stream_; } @@ -955,7 +627,7 @@ #if defined(OS_WIN) // Appends a formatted system message of the GetLastError() type. -class BASE_EXPORT Win32ErrorLogMessage { +class BASE_EXPORT Win32ErrorLogMessage : public LogMessage { public: Win32ErrorLogMessage(const char* file, int line, @@ -963,19 +635,16 @@ SystemErrorCode err); // Appends the error message before destructing the encapsulated class. - ~Win32ErrorLogMessage(); - - std::ostream& stream() { return log_message_.stream(); } + ~Win32ErrorLogMessage() override; private: SystemErrorCode err_; - LogMessage log_message_; DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage); }; #elif defined(OS_POSIX) || defined(OS_FUCHSIA) // Appends a formatted system message of the errno type -class BASE_EXPORT ErrnoLogMessage { +class BASE_EXPORT ErrnoLogMessage : public LogMessage { public: ErrnoLogMessage(const char* file, int line, @@ -983,13 +652,10 @@ SystemErrorCode err); // Appends the error message before destructing the encapsulated class. - ~ErrnoLogMessage(); - - std::ostream& stream() { return log_message_.stream(); } + ~ErrnoLogMessage() override; private: SystemErrorCode err_; - LogMessage log_message_; DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage); }; @@ -1015,12 +681,6 @@ #define RAW_LOG(level, message) \ ::logging::RawLog(::logging::LOG_##level, message) -#define RAW_CHECK(condition) \ - do { \ - if (!(condition)) \ - ::logging::RawLog(::logging::LOG_FATAL, \ - "Check failed: " #condition "\n"); \ - } while (0) #if defined(OS_WIN) // Returns true if logging to file is enabled.
diff --git a/base/mac/mac_logging.h b/base/mac/mac_logging.h index 30e43ead..72315e9c 100644 --- a/base/mac/mac_logging.h +++ b/base/mac/mac_logging.h
@@ -38,7 +38,7 @@ int line, LogSeverity severity, OSStatus status); - ~OSStatusLogMessage(); + ~OSStatusLogMessage() override; private: OSStatus status_;
diff --git a/base/mac/mach_logging.h b/base/mac/mach_logging.h index 59ab762..c0247d2 100644 --- a/base/mac/mach_logging.h +++ b/base/mac/mach_logging.h
@@ -39,7 +39,7 @@ int line, LogSeverity severity, mach_error_t mach_err); - ~MachLogMessage(); + ~MachLogMessage() override; private: mach_error_t mach_err_; @@ -106,7 +106,7 @@ int line, LogSeverity severity, kern_return_t bootstrap_err); - ~BootstrapLogMessage(); + ~BootstrapLogMessage() override; private: kern_return_t bootstrap_err_;
diff --git a/base/util/timer/wall_clock_timer_unittest.cc b/base/util/timer/wall_clock_timer_unittest.cc index cfb5c950..961f5c0 100644 --- a/base/util/timer/wall_clock_timer_unittest.cc +++ b/base/util/timer/wall_clock_timer_unittest.cc
@@ -133,8 +133,7 @@ TEST_F(WallClockTimerTest, Stop) { ::testing::StrictMock<base::MockOnceClosure> callback; - const auto start_time = base::Time::Now(); - clock_.SetNow(start_time); + clock_.SetNow(base::Time::Now()); // Set up a WallClockTimer. WallClockTimer wall_clock_timer(&clock_, @@ -158,4 +157,63 @@ ::testing::Mock::VerifyAndClearExpectations(&callback); } +TEST_F(WallClockTimerTest, RestartRunningTimer) { + ::testing::StrictMock<base::MockOnceClosure> first_callback; + ::testing::StrictMock<base::MockOnceClosure> second_callback; + constexpr auto delay = base::TimeDelta::FromMinutes(1); + + // Set up a WallClockTimer that will invoke |first_callback| in one minute. + clock_.SetNow(base::Time::Now()); + WallClockTimer wall_clock_timer(&clock_, + task_environment_.GetMockTickClock()); + wall_clock_timer.Start(FROM_HERE, clock_.Now() + delay, first_callback.Get()); + + // After 30 seconds, replace the timer with |second_callback| with new one + // minute delay. + constexpr auto past_time = delay / 2; + FastForwardBy(past_time); + wall_clock_timer.Start(FROM_HERE, clock_.Now() + delay, + second_callback.Get()); + + // |first_callback| is due but it won't be called because it's replaced. + FastForwardBy(past_time); + ::testing::Mock::VerifyAndClearExpectations(&first_callback); + ::testing::Mock::VerifyAndClearExpectations(&second_callback); + + // Timer invokes the |second_callback|. + EXPECT_CALL(second_callback, Run()); + FastForwardBy(past_time); + ::testing::Mock::VerifyAndClearExpectations(&first_callback); + ::testing::Mock::VerifyAndClearExpectations(&second_callback); +} + +TEST_F(WallClockTimerTest, DoubleStop) { + ::testing::StrictMock<base::MockOnceClosure> callback; + clock_.SetNow(base::Time::Now()); + + // Set up a WallClockTimer. + WallClockTimer wall_clock_timer(&clock_, + task_environment_.GetMockTickClock()); + constexpr auto delay = base::TimeDelta::FromMinutes(1); + wall_clock_timer.Start(FROM_HERE, clock_.Now() + delay, callback.Get()); + + // After 15 seconds, timer is stopped. + constexpr auto past_time = delay / 4; + FastForwardBy(past_time); + EXPECT_TRUE(wall_clock_timer.IsRunning()); + wall_clock_timer.Stop(); + EXPECT_FALSE(wall_clock_timer.IsRunning()); + + // And timer is stopped again later. The second stop should be a no-op. + FastForwardBy(past_time); + EXPECT_FALSE(wall_clock_timer.IsRunning()); + wall_clock_timer.Stop(); + EXPECT_FALSE(wall_clock_timer.IsRunning()); + + // Timer won't fire after stop. + FastForwardBy(past_time, /*with_power=*/false); + FastForwardBy(delay - past_time * 3); + ::testing::Mock::VerifyAndClearExpectations(&callback); +} + } // namespace util
diff --git a/build/android/pylib/local/emulator/OWNERS b/build/android/pylib/local/emulator/OWNERS new file mode 100644 index 0000000..0853590d --- /dev/null +++ b/build/android/pylib/local/emulator/OWNERS
@@ -0,0 +1,4 @@ +bpastene@chromium.org +hypan@google.com +jbudorick@chromium.org +liaoyuke@chromium.org
diff --git a/build/android/pylib/local/emulator/avd.py b/build/android/pylib/local/emulator/avd.py index 012071ba..ccdbf09 100644 --- a/build/android/pylib/local/emulator/avd.py +++ b/build/android/pylib/local/emulator/avd.py
@@ -236,8 +236,9 @@ avd_dir = os.path.join(android_avd_home, '%s.avd' % self._config.avd_name) config_ini = os.path.join(avd_dir, 'config.ini') - with open(root_ini, 'a') as root_ini_file: - root_ini_file.write('path.rel=avd/%s.avd\n' % self._config.avd_name) + if os.path.exists(root_ini): + with open(root_ini, 'a') as root_ini_file: + root_ini_file.write('path.rel=avd/%s.avd\n' % self._config.avd_name) if os.path.exists(config_ini): with open(config_ini) as config_ini_file: @@ -263,7 +264,10 @@ self._Initialize() instance = _AvdInstance(self._emulator_path, self._emulator_home, self._config) - instance.Start(read_only=False, snapshot_save=snapshot) + # Enable debug for snapshot when it is set to True + debug_tags = 'snapshot' if snapshot else None + instance.Start( + read_only=False, snapshot_save=snapshot, debug_tags=debug_tags) device_utils.DeviceUtils(instance.serial).WaitUntilFullyBooted( timeout=180, retries=0) instance.Stop() @@ -496,7 +500,8 @@ read_only=True, snapshot_save=False, window=False, - writable_system=False): + writable_system=False, + debug_tags=None): """Starts the emulator running an instance of the given AVD.""" with tempfile_ext.TemporaryFileName() as socket_path, (contextlib.closing( @@ -517,6 +522,8 @@ emulator_cmd.append('-no-snapshot-save') if writable_system: emulator_cmd.append('-writable-system') + if debug_tags: + emulator_cmd.extend(['-debug', debug_tags]) emulator_env = {} if self._emulator_home: @@ -531,11 +538,14 @@ sock.listen(1) - logging.info('Starting emulator.') + logging.info('Starting emulator with commands: %s', + ' '.join(emulator_cmd)) # TODO(jbudorick): Add support for logging emulator stdout & stderr at # higher logging levels. - self._sink = open('/dev/null', 'w') + # Enable the emulator log when debug_tags is set. + if not debug_tags: + self._sink = open('/dev/null', 'w') self._emulator_proc = cmd_helper.Popen( emulator_cmd, stdout=self._sink, stderr=self._sink, env=emulator_env)
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index c084d0b..17d4cfb 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200413.3.1 \ No newline at end of file +0.20200414.2.1 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index c084d0b..d82e38e3 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200413.3.1 \ No newline at end of file +0.20200414.1.1 \ No newline at end of file
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc index 19371cf9..1b454f3a 100644 --- a/cc/metrics/compositor_frame_reporter.cc +++ b/cc/metrics/compositor_frame_reporter.cc
@@ -290,7 +290,7 @@ } void CompositorFrameReporter::OnDidNotProduceFrame() { - did_not_produce_frame_ = true; + did_not_produce_frame_time_ = base::TimeTicks::Now(); } void CompositorFrameReporter::SetBlinkBreakdown(
diff --git a/cc/metrics/compositor_frame_reporter.h b/cc/metrics/compositor_frame_reporter.h index f0139cb9..4105713 100644 --- a/cc/metrics/compositor_frame_reporter.h +++ b/cc/metrics/compositor_frame_reporter.h
@@ -152,11 +152,17 @@ void OnAbortBeginMainFrame(base::TimeTicks timestamp); void OnDidNotProduceFrame(); bool did_finish_impl_frame() const { return did_finish_impl_frame_; } - bool did_not_produce_frame() const { return did_not_produce_frame_; } base::TimeTicks impl_frame_finish_time() const { return impl_frame_finish_time_; } + bool did_not_produce_frame() const { + return did_not_produce_frame_time_.has_value(); + } + base::TimeTicks did_not_produce_frame_time() const { + return *did_not_produce_frame_time_; + } + bool did_abort_main_frame() const { return main_frame_abort_time_.has_value(); } @@ -236,13 +242,14 @@ // Indicates if work on Impl frame is finished. bool did_finish_impl_frame_ = false; - // Flag indicating if DidNotProduceFrame is called for this reporter - bool did_not_produce_frame_ = false; // The time that work on Impl frame is finished. It's only valid if the // reporter is in a stage other than begin impl frame. base::TimeTicks impl_frame_finish_time_; base::TimeTicks frame_deadline_; + // The timestamp of when the frame was marked as not having produced a frame + // (through a call to DidNotProduceFrame()). + base::Optional<base::TimeTicks> did_not_produce_frame_time_; base::Optional<base::TimeTicks> main_frame_abort_time_; }; } // namespace cc
diff --git a/cc/metrics/compositor_frame_reporting_controller.cc b/cc/metrics/compositor_frame_reporting_controller.cc index 4ba0175d..caa801c 100644 --- a/cc/metrics/compositor_frame_reporting_controller.cc +++ b/cc/metrics/compositor_frame_reporting_controller.cc
@@ -52,6 +52,11 @@ return base::TimeTicks::Now(); } +bool CompositorFrameReportingController::HasReporterAt( + PipelineStage stage) const { + return !!reporters_[stage].get(); +} + void CompositorFrameReportingController::WillBeginImplFrame( const viz::BeginFrameArgs& args) { base::TimeTicks begin_time = Now(); @@ -291,6 +296,19 @@ } } +void CompositorFrameReportingController::OnStoppedRequestingBeginFrames() { + // If the client stopped requesting begin-frames, that means the begin-frames + // currently being handled are no longer expected to produce any + // compositor-frames. So terminate the reporters. + auto now = Now(); + for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) { + if (reporters_[i]) { + reporters_[i]->TerminateFrame(FrameTerminationStatus::kDidNotProduceFrame, + now); + } + } +} + void CompositorFrameReportingController::SetBlinkBreakdown( std::unique_ptr<BeginMainFrameMetrics> details, base::TimeTicks main_thread_start_time) { @@ -314,16 +332,18 @@ PipelineStage target) { auto& reporter = reporters_[target]; if (reporter) { - auto termination_time = (target == PipelineStage::kBeginMainFrame && - reporter->did_abort_main_frame()) - ? reporter->main_frame_abort_time() - : Now(); - if (reporters_[target]->did_not_produce_frame()) - reporters_[target]->TerminateFrame( - FrameTerminationStatus::kDidNotProduceFrame, termination_time); - else - reporters_[target]->TerminateFrame( - FrameTerminationStatus::kReplacedByNewReporter, termination_time); + auto termination_status = FrameTerminationStatus::kReplacedByNewReporter; + base::TimeTicks termination_time; + if (reporter->did_not_produce_frame()) { + termination_time = reporter->did_not_produce_frame_time(); + termination_status = FrameTerminationStatus::kDidNotProduceFrame; + } else if (target == PipelineStage::kBeginMainFrame && + reporter->did_abort_main_frame()) { + termination_time = reporter->main_frame_abort_time(); + } else { + termination_time = Now(); + } + reporter->TerminateFrame(termination_status, termination_time); } reporters_[target] = std::move(reporters_[start]); }
diff --git a/cc/metrics/compositor_frame_reporting_controller.h b/cc/metrics/compositor_frame_reporting_controller.h index 8eb99e0..8e63a48 100644 --- a/cc/metrics/compositor_frame_reporting_controller.h +++ b/cc/metrics/compositor_frame_reporting_controller.h
@@ -65,6 +65,7 @@ virtual void DidPresentCompositorFrame( uint32_t frame_token, const viz::FrameTimingDetails& details); + void OnStoppedRequestingBeginFrames(); void SetBlinkBreakdown(std::unique_ptr<BeginMainFrameMetrics> details, base::TimeTicks main_thread_start_time); @@ -74,7 +75,7 @@ virtual void AddActiveTracker(FrameSequenceTrackerType type); virtual void RemoveActiveTracker(FrameSequenceTrackerType type); - base::flat_set<FrameSequenceTrackerType> active_trackers_; + std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; } protected: struct SubmittedCompositorFrame { @@ -87,8 +88,8 @@ ~SubmittedCompositorFrame(); }; base::TimeTicks Now() const; - std::unique_ptr<CompositorFrameReporter> - reporters_[PipelineStage::kNumPipelineStages]; + + bool HasReporterAt(PipelineStage stage) const; private: void AdvanceReporterStage(PipelineStage start, PipelineStage target); @@ -101,6 +102,7 @@ viz::BeginFrameId last_submitted_frame_id_; bool next_activate_has_invalidation_ = false; + base::flat_set<FrameSequenceTrackerType> active_trackers_; // The latency reporter passed to each CompositorFrameReporter. Owned here // because it must be common among all reporters. @@ -108,6 +110,9 @@ // outlive the objects in |submitted_compositor_frames_|. std::unique_ptr<LatencyUkmReporter> latency_ukm_reporter_; + std::unique_ptr<CompositorFrameReporter> + reporters_[PipelineStage::kNumPipelineStages]; + // Mapping of frame token to pipeline reporter for submitted compositor // frames. // DO NOT reorder this line and the one above. The latency_ukm_reporter_ must
diff --git a/cc/metrics/compositor_frame_reporting_controller_unittest.cc b/cc/metrics/compositor_frame_reporting_controller_unittest.cc index 64da64b..e2e8268 100644 --- a/cc/metrics/compositor_frame_reporting_controller_unittest.cc +++ b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
@@ -37,12 +37,10 @@ TestCompositorFrameReportingController& operator=( const TestCompositorFrameReportingController& controller) = delete; - std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; } - int ActiveReporters() { int count = 0; for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) { - if (reporters_[i]) + if (reporters()[i]) ++count; } return count;
diff --git a/cc/metrics/compositor_timing_history.cc b/cc/metrics/compositor_timing_history.cc index db50742..25d1813 100644 --- a/cc/metrics/compositor_timing_history.cc +++ b/cc/metrics/compositor_timing_history.cc
@@ -662,6 +662,7 @@ void CompositorTimingHistory::BeginImplFrameNotExpectedSoon() { SetBeginMainFrameNeededContinuously(false); SetCompositorDrawingContinuously(false); + compositor_frame_reporting_controller_->OnStoppedRequestingBeginFrames(); } void CompositorTimingHistory::WillBeginMainFrame(
diff --git a/cc/scheduler/begin_frame_tracker.cc b/cc/scheduler/begin_frame_tracker.cc index fe8f840..0480a2c 100644 --- a/cc/scheduler/begin_frame_tracker.cc +++ b/cc/scheduler/begin_frame_tracker.cc
@@ -16,7 +16,7 @@ BeginFrameTracker::~BeginFrameTracker() = default; -void BeginFrameTracker::Start(viz::BeginFrameArgs new_args) { +void BeginFrameTracker::Start(const viz::BeginFrameArgs& new_args) { // Trace the frame time being passed between BeginFrameTrackers. TRACE_EVENT_FLOW_STEP0( TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs",
diff --git a/cc/scheduler/begin_frame_tracker.h b/cc/scheduler/begin_frame_tracker.h index 2f5f3b1..fc04109 100644 --- a/cc/scheduler/begin_frame_tracker.h +++ b/cc/scheduler/begin_frame_tracker.h
@@ -49,7 +49,7 @@ // Start using a new BFA value and check invariant properties. // **Must** only be called after finishing with any previous BFA. - void Start(viz::BeginFrameArgs new_args); + void Start(const viz::BeginFrameArgs& new_args); // Finish using the current BFA. // **Must** only be called while still using a BFA. void Finish();
diff --git a/cc/test/fake_compositor_frame_reporting_controller.cc b/cc/test/fake_compositor_frame_reporting_controller.cc index 739158d..ea3dc87 100644 --- a/cc/test/fake_compositor_frame_reporting_controller.cc +++ b/cc/test/fake_compositor_frame_reporting_controller.cc
@@ -17,14 +17,14 @@ void FakeCompositorFrameReportingController::WillBeginMainFrame( const viz::BeginFrameArgs& args) { - if (!reporters_[PipelineStage::kBeginImplFrame]) + if (!HasReporterAt(PipelineStage::kBeginImplFrame)) CompositorFrameReportingController::WillBeginImplFrame(args); CompositorFrameReportingController::WillBeginMainFrame(args); } void FakeCompositorFrameReportingController::BeginMainFrameAborted( const viz::BeginFrameId& id) { - if (!reporters_[PipelineStage::kBeginMainFrame]) { + if (!HasReporterAt(PipelineStage::kBeginMainFrame)) { viz::BeginFrameArgs args = viz::BeginFrameArgs(); args.frame_id = id; args.frame_time = Now(); @@ -35,7 +35,7 @@ } void FakeCompositorFrameReportingController::WillCommit() { - if (!reporters_[PipelineStage::kBeginMainFrame]) { + if (!HasReporterAt(PipelineStage::kBeginMainFrame)) { viz::BeginFrameArgs args = viz::BeginFrameArgs(); args.frame_id = viz::BeginFrameId(); args.frame_time = Now(); @@ -46,19 +46,19 @@ } void FakeCompositorFrameReportingController::DidCommit() { - if (!reporters_[PipelineStage::kBeginMainFrame]) + if (!HasReporterAt(PipelineStage::kBeginMainFrame)) WillCommit(); CompositorFrameReportingController::DidCommit(); } void FakeCompositorFrameReportingController::WillActivate() { - if (!reporters_[PipelineStage::kCommit]) + if (!HasReporterAt(PipelineStage::kCommit)) DidCommit(); CompositorFrameReportingController::WillActivate(); } void FakeCompositorFrameReportingController::DidActivate() { - if (!reporters_[PipelineStage::kCommit]) + if (!HasReporterAt(PipelineStage::kCommit)) WillActivate(); CompositorFrameReportingController::DidActivate(); }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 0226f80c..0c1cba8 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -301,6 +301,7 @@ "//chrome/browser/profiles/android:java", "//chrome/browser/settings:java", "//chrome/browser/share/android:java_resources", + "//chrome/browser/tab:java", "//chrome/browser/thumbnail:java", "//chrome/browser/ui/android/appmenu:factory_java", "//chrome/browser/ui/android/appmenu:java", @@ -475,7 +476,6 @@ "//chrome/browser/notifications/scheduler/public:jni_enums", "//chrome/browser/supervised_user/supervised_user_error_page:enums_srcjar", "//chrome/browser/ui:cookie_controls_enforcement_javagen", - "//chrome/browser/ui:tab_model_enums_java", "//chrome/browser/updates/announcement_notification:jni_enums", "//components/autofill_assistant/browser:autofill_assistant_enums_java", "//components/browsing_data/core:browsing_data_utils_java", @@ -795,6 +795,7 @@ "//base:base_java", "//base:base_java_test_support", "//chrome/android:chrome_java", + "//chrome/browser/tab:java", "//chrome/browser/ui/android/appmenu:java", "//chrome/test/android:chrome_java_test_support", "//content/public/android:content_java", @@ -850,6 +851,7 @@ "//chrome/browser/profiles/android:java", "//chrome/browser/settings:java", "//chrome/browser/settings:javatests", + "//chrome/browser/tab:java", "//chrome/browser/thumbnail:java", "//chrome/browser/thumbnail:javatests", "//chrome/browser/ui/android/appmenu:java", @@ -1040,6 +1042,7 @@ "//chrome/android:app_hooks_java", "//chrome/android:chrome_java", "//chrome/android/features/vr:java", + "//chrome/browser/tab:java", "//chrome/browser/util:java", "//chrome/test/android:chrome_java_test_support", "//components/embedder_support/android:util_java", @@ -1672,6 +1675,7 @@ "//base:base_java", "//base:base_java_test_support", "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", "//components/offline_items_collection/core:core_java", "//components/sync/protocol:protocol_java", "//content/public/android:content_java", @@ -3007,6 +3011,7 @@ "//chrome/android:chrome_java", "//chrome/browser/flags:java", "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", "//chrome/browser/util:java", "//chrome/test/android:chrome_java_test_support", "//components/embedder_support/android:context_menu_java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index eeca7fc..f75c3a2 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1577,32 +1577,24 @@ "java/src/org/chromium/chrome/browser/tab/AccessibilityVisibilityHandler.java", "java/src/org/chromium/chrome/browser/tab/AuthenticatorNavigationInterceptor.java", "java/src/org/chromium/chrome/browser/tab/AuthenticatorNavigationInterceptorTabHelper.java", - "java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java", "java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateClientImpl.java", "java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java", "java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTabHelper.java", "java/src/org/chromium/chrome/browser/tab/RedirectHandlerTabHelper.java", "java/src/org/chromium/chrome/browser/tab/SadTab.java", "java/src/org/chromium/chrome/browser/tab/SadTabView.java", - "java/src/org/chromium/chrome/browser/tab/Tab.java", "java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java", - "java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java", - "java/src/org/chromium/chrome/browser/tab/TabAttributes.java", "java/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelper.java", "java/src/org/chromium/chrome/browser/tab/TabBrowserControlsOffsetHelper.java", "java/src/org/chromium/chrome/browser/tab/TabBuilder.java", "java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java", "java/src/org/chromium/chrome/browser/tab/TabContextMenuPopulator.java", - "java/src/org/chromium/chrome/browser/tab/TabCreationState.java", "java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java", "java/src/org/chromium/chrome/browser/tab/TabFavicon.java", "java/src/org/chromium/chrome/browser/tab/TabHelpers.java", - "java/src/org/chromium/chrome/browser/tab/TabHidingType.java", "java/src/org/chromium/chrome/browser/tab/TabIdManager.java", "java/src/org/chromium/chrome/browser/tab/TabImpl.java", "java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java", - "java/src/org/chromium/chrome/browser/tab/TabLifecycle.java", - "java/src/org/chromium/chrome/browser/tab/TabObserver.java", "java/src/org/chromium/chrome/browser/tab/TabParentIntent.java", "java/src/org/chromium/chrome/browser/tab/TabState.java", "java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index f00e666..a93eab8 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -35,6 +35,7 @@ "//chrome/android:chrome_java", "//chrome/browser/image_fetcher:java", "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", "//chrome/browser/ui/messages/android:java", "//chrome/browser/util:java", "//components/browser_ui/modaldialog/android:java",
diff --git a/chrome/android/features/keyboard_accessory/BUILD.gn b/chrome/android/features/keyboard_accessory/BUILD.gn index 062b5200..235b10d 100644 --- a/chrome/android/features/keyboard_accessory/BUILD.gn +++ b/chrome/android/features/keyboard_accessory/BUILD.gn
@@ -61,6 +61,7 @@ "//chrome/android:chrome_test_java", "//chrome/android:chrome_test_util_java", "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", "//chrome/browser/ui/messages/android:java", "//chrome/test/android:chrome_java_test_support", "//components/autofill/android:autofill_java",
diff --git a/chrome/android/features/keyboard_accessory/internal/BUILD.gn b/chrome/android/features/keyboard_accessory/internal/BUILD.gn index 82919c4..5a710458 100644 --- a/chrome/android/features/keyboard_accessory/internal/BUILD.gn +++ b/chrome/android/features/keyboard_accessory/internal/BUILD.gn
@@ -17,6 +17,7 @@ "//chrome/android/features/keyboard_accessory/public:public_java", "//chrome/browser/flags:java", "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", "//chrome/browser/ui/android/favicon:java", "//chrome/browser/util:java", "//components/autofill/android:autofill_java",
diff --git a/chrome/android/features/start_surface/internal/BUILD.gn b/chrome/android/features/start_surface/internal/BUILD.gn index 4631bec..dccbd57f 100644 --- a/chrome/android/features/start_surface/internal/BUILD.gn +++ b/chrome/android/features/start_surface/internal/BUILD.gn
@@ -65,6 +65,7 @@ "//chrome/android/third_party/compositor_animator:compositor_animator_java", "//chrome/browser/flags:java", "//chrome/browser/preferences:java", + "//chrome/browser/tab:java", "//chrome/browser/ui/messages/android:java", "//components/browser_ui/widget/android:java", "//third_party/android_deps:android_support_v7_appcompat_java",
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java index a7a0c65..0bb47fd 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java
@@ -172,7 +172,7 @@ @Test @EnormousTest @DisableIf - .Build(sdk_is_less_than = Build.VERSION_CODES.M, message = "https://crbug.com/1045938") + .Build(sdk_is_less_than = Build.VERSION_CODES.N, message = "https://crbug.com/1045938") @CommandLineFlags.Add({BASE_PARAMS}) public void testTabToGridFromLiveTabWith10TabsWithoutThumbnail() throws InterruptedException { // Note that most of the tabs won't have thumbnails.
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index 1af43b7..2f4a644 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -181,6 +181,7 @@ "//chrome/browser/android/lifecycle:java", "//chrome/browser/flags:java", "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", "//chrome/browser/ui/android/favicon:java", "//chrome/browser/ui/android/strings:ui_strings_grd", "//chrome/browser/ui/messages/android:java",
diff --git a/chrome/android/features/vr/BUILD.gn b/chrome/android/features/vr/BUILD.gn index 56cb5bb..54ec251c 100644 --- a/chrome/android/features/vr/BUILD.gn +++ b/chrome/android/features/vr/BUILD.gn
@@ -76,6 +76,7 @@ "//chrome/browser/flags:java", "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", "//chrome/browser/util:java", "//components/browser_ui/modaldialog/android:java", "//components/embedder_support/android:content_view_java",
diff --git a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java index 019bbb1..273b5d6 100644 --- a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java
@@ -47,6 +47,7 @@ import org.chromium.chrome.browser.tab.TabAssociatedApp; import org.chromium.chrome.browser.tab.TabBrowserControlsConstraintsHelper; 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.tabmodel.ChromeTabCreator; @@ -536,7 +537,7 @@ // Reparent all existing tabs. for (TabModel model : mActivity.getTabModelSelector().getModels()) { for (int i = 0; i < model.getCount(); ++i) { - model.getTabAt(i).updateAttachment(window, null); + ((TabImpl) model.getTabAt(i)).updateAttachment(window, null); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java index 8fca74ce..9f2bb0a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java
@@ -27,14 +27,6 @@ boolean shouldBeFocused, @Nullable String pastedText, @OmniboxFocusReason int reason); /** - * Performs a search query on the current {@link Tab}. This calls {@link - * TemplateUrlService#getUrlForSearchQuery(String)} to get a url based on {@code query} and - * loads that url in the current {@link Tab}. - * @param query The {@link String} that represents the text query that should be searched for. - */ - void performSearchQuery(String query); - - /** * @return Whether the URL bar is currently focused. */ boolean isUrlBarFocused();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 6cd6e7b2..11eecb3b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -220,12 +220,6 @@ } @Override - public void performSearchQuery(String query) { - if (mFakeboxDelegate == null) return; - mFakeboxDelegate.performSearchQuery(query); - } - - @Override public boolean isCurrentPage() { if (mIsDestroyed) return false; if (mFakeboxDelegate == null) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java index 5de63a5..6a95ae84 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -267,11 +267,10 @@ setSearchProviderInfo(searchProviderHasLogo, searchProviderIsGoogle); mSearchProviderLogoView.showSearchProviderInitialView(); - mQueryTileSection = new QueryTileSection(findViewById(R.id.query_tiles), - mSearchBoxCoordinator, profile, mManager::performSearchQuery); + mQueryTileSection = new QueryTileSection( + findViewById(R.id.query_tiles), mSearchBoxCoordinator, profile); - mTileGroup.startObserving( - getMaxRowsForMostVisitedTiles() * getMaxColumnsForMostVisitedTiles()); + mTileGroup.startObserving(getMaxTileRows() * getMaxTileColumns()); VrModuleProvider.registerVrModeObserver(this); if (VrModuleProvider.getDelegate().isInVr()) onEnterVr(); @@ -786,15 +785,15 @@ } } - private int getMaxRowsForMostVisitedTiles() { - return mQueryTileSection != null && mQueryTileSection.shouldConsiderAsSmallScreen() ? 1 : 2; + private static int getMaxTileRows() { + return 2; } /** * Determines The maximum number of tiles to try and fit in a row. On smaller screens, there * may not be enough space to fit all of them. */ - private int getMaxColumnsForMostVisitedTiles() { + private int getMaxTileColumns() { return 4; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index 7451c42..330bee2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -78,12 +78,6 @@ void focusSearchBox(boolean beginVoiceSearch, String pastedText); /** - * Performs a search query on the current {@link Tab}. - * @param query The {@link String} representing the query text. - */ - void performSearchQuery(String query); - - /** * @return whether the {@link NewTabPage} associated with this manager is the current page * displayed to the user. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index 9c4f4e4..1b4b961 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -66,6 +66,7 @@ import org.chromium.chrome.browser.util.AccessibilityUtil; import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.widget.CompositeTouchDelegate; +import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.common.ResourceRequestBody; import org.chromium.ui.base.DeviceFormFactor; @@ -729,8 +730,14 @@ // When we restore tabs, we focus the selected tab so the URL of the page shows. } - @Override - public void performSearchQuery(String query) { + /** + * Performs a search query on the current {@link Tab}. This calls + * {@link TemplateUrlService#getUrlForSearchQuery(String)} to get a url based on {@code query} + * and loads that url in the current {@link Tab}. + * @param query The {@link String} that represents the text query that should be searched for. + */ + @VisibleForTesting + public void performSearchQueryForTest(String query) { if (TextUtils.isEmpty(query)) return; String queryUrl = TemplateUrlServiceFactory.get().getUrlForSearchQuery(query);
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 7f8ef90e..e7dc62ae 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
@@ -13,8 +13,6 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.ntp.search.SearchBoxCoordinator; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.ui.display.DisplayAndroid; -import org.chromium.ui.display.DisplayUtil; import java.util.List; @@ -24,24 +22,17 @@ * section. */ public class QueryTileSection { - private static final String QUERY_TILES_SHORTEN_MOST_VISITED_TILES_FOR_SMALL_SCREEN = - "shorten_most_visited_tiles_for_small_screen"; - private static final int SMALL_SCREEN_HEIGHT_THRESHOLD_DP = 600; - private final ViewGroup mQueryTileSectionView; private final SearchBoxCoordinator mSearchBoxCoordinator; - private final Callback<String> mSubmitQueryCallback; private QueryTileCoordinator mQueryTileCoordinator; private TileProvider mTileProvider; /** Constructor. */ public QueryTileSection(ViewGroup queryTileSectionView, - SearchBoxCoordinator searchBoxCoordinator, Profile profile, - Callback<String> performSearchQueryCallback) { + SearchBoxCoordinator searchBoxCoordinator, Profile profile) { mQueryTileSectionView = queryTileSectionView; mSearchBoxCoordinator = searchBoxCoordinator; - mSubmitQueryCallback = performSearchQueryCallback; - if (!isFeatureEnabled()) return; + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES)) return; mTileProvider = TileProviderFactory.getForProfile(profile); mQueryTileCoordinator = QueryTileCoordinatorFactory.create( @@ -52,46 +43,15 @@ } private void onTileClicked(Tile tile) { - if (tile == null) { - mTileProvider.getQueryTiles(this::setTiles); - } else { - boolean isLastLevelTile = tile.children.isEmpty(); - setTiles(tile.children); - if (isLastLevelTile) { - mSubmitQueryCallback.onResult(tile.queryText); - } else { - // TODO(shaktisahu): Show chip on fakebox; - } - } - } + mTileProvider.getQueryTiles(tiles -> { + mQueryTileCoordinator.setTiles(tiles); + mQueryTileSectionView.setVisibility(tiles.isEmpty() ? View.GONE : View.VISIBLE); + }); - private void setTiles(List<Tile> tiles) { - mQueryTileCoordinator.setTiles(tiles); - mQueryTileSectionView.setVisibility(tiles.isEmpty() ? View.GONE : View.VISIBLE); + if (tile != null) mSearchBoxCoordinator.setSearchText(tile.queryText); } private void getVisuals(Tile tile, Callback<List<Bitmap>> callback) { mTileProvider.getVisuals(tile.id, callback); } - - /** - * @return Whether the screen height is small. Used for shortening the most visited tiles - * section on NTP so that feed is still visible above the fold. - */ - public boolean shouldConsiderAsSmallScreen() { - if (!isFeatureEnabled()) return false; - boolean shortenMostVisitedTiles = ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( - ChromeFeatureList.QUERY_TILES, - QUERY_TILES_SHORTEN_MOST_VISITED_TILES_FOR_SMALL_SCREEN, false); - if (!shortenMostVisitedTiles) return false; - - DisplayAndroid display = - DisplayAndroid.getNonMultiDisplay(mQueryTileSectionView.getContext()); - int screenHeightDp = DisplayUtil.pxToDp(display, display.getDisplayHeight()); - return screenHeightDp < SMALL_SCREEN_HEIGHT_THRESHOLD_DP; - } - - private static boolean isFeatureEnabled() { - return ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES); - } -} +} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/FourStateCookieSettingsPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/FourStateCookieSettingsPreference.java index c5bfbdd..7ba71be 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/FourStateCookieSettingsPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/FourStateCookieSettingsPreference.java
@@ -21,8 +21,6 @@ import org.chromium.components.browser_ui.widget.text.TextViewWithCompoundDrawables; import org.chromium.components.content_settings.CookieControlsMode; -import java.util.Arrays; - /** * A 4-state radio group Preference used for the Cookies subpage of SiteSettings. */ @@ -36,14 +34,25 @@ BLOCK } - // Signals used to determine the view and button states. - private boolean mCookiesContentSettingEnforced; - private boolean mThirdPartyBlockingEnforced; - private boolean mAllowCookies; - private boolean mBlockThirdPartyCookies; - // An enum indicating when to block third-party cookies. - private @CookieControlsMode int mCookieControlsMode; - private CookieSettingsState mState = CookieSettingsState.UNINITIALIZED; + /** + * Signals used to determine the view and button states. + */ + public static class Params { + // Whether the cookies content setting is enabled. + public boolean allowCookies; + // Whether third-party blocking is enabled. + public boolean blockThirdPartyCookies; + // An enum indicating when to block third-party cookies. + public @CookieControlsMode int cookieControlsMode; + + // Whether the cookies content setting is enforced. + public boolean cookiesContentSettingEnforced; + // Whether third-party blocking is enforced. + public boolean thirdPartyBlockingEnforced; + } + + // Keeps the params that are applied to the UI if the params are set before the UI is ready. + private Params mInitializationParams; // UI Elements. private RadioButtonWithDescription mAllowButton; @@ -66,23 +75,12 @@ /** * Sets the cookie settings state and updates the radio buttons. - * @param cookiesContentSettingEnforced Whether the cookies content setting is enforced. - * @param thirdPartyBlockingEnforced Whether third-party blocking is enforced. - * @param allowCookies Whether the cookies content setting is enabled. - * @param blockThirdPartyCookies Whether third-party blocking is enabled. - * @param cookieControlsMode The CookieControlsMode enum for the current cookie settings state. */ - public void setState(boolean cookiesContentSettingEnforced, boolean thirdPartyBlockingEnforced, - boolean allowCookies, boolean blockThirdPartyCookies, - @CookieControlsMode int cookieControlsMode) { - mCookiesContentSettingEnforced = cookiesContentSettingEnforced; - mThirdPartyBlockingEnforced = thirdPartyBlockingEnforced; - mAllowCookies = allowCookies; - mBlockThirdPartyCookies = blockThirdPartyCookies; - mCookieControlsMode = cookieControlsMode; - + public void setState(Params state) { if (mRadioGroup != null) { - setRadioButtons(); + configureRadioButtons(state); + } else { + mInitializationParams = state; } } @@ -90,22 +88,30 @@ * @return The state that is currently selected. */ public CookieSettingsState getState() { - return mState; + if (mRadioGroup == null && mInitializationParams == null) { + return CookieSettingsState.UNINITIALIZED; + } + + // Calculate the state from mInitializationParams if the UI is not initialized yet. + if (mInitializationParams != null) { + return getActiveState(mInitializationParams); + } + + if (mAllowButton.isChecked()) { + return CookieSettingsState.ALLOW; + } else if (mBlockThirdPartyIncognitoButton.isChecked()) { + return CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO; + } else if (mBlockThirdPartyButton.isChecked()) { + return CookieSettingsState.BLOCK_THIRD_PARTY; + } else { + assert mBlockButton.isChecked(); + return CookieSettingsState.BLOCK; + } } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { - if (mAllowButton.isChecked()) { - mState = CookieSettingsState.ALLOW; - } else if (mBlockThirdPartyIncognitoButton.isChecked()) { - mState = CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO; - } else if (mBlockThirdPartyButton.isChecked()) { - mState = CookieSettingsState.BLOCK_THIRD_PARTY; - } else if (mBlockButton.isChecked()) { - mState = CookieSettingsState.BLOCK; - } - - callChangeListener(mState); + callChangeListener(getState()); } @Override @@ -128,48 +134,51 @@ mManagedView.setCompoundDrawablesRelativeWithIntrinsicBounds( managedIcon, drawables[1], drawables[2], drawables[3]); - setRadioButtons(); + if (mInitializationParams != null) { + configureRadioButtons(mInitializationParams); + } } - private RadioButtonWithDescription getActiveRadioButton() { + private CookieSettingsState getActiveState(Params params) { // These conditions only check the preference combinations that deterministically decide // your cookie settings state. In the future we would refactor the backend preferences to // reflect the only possible states you can be in // (Allow/BlockThirdPartyIncognito/BlockThirdParty/Block), instead of using this // combination of multiple signals. - if (!mAllowCookies) { - mState = CookieSettingsState.BLOCK; - return mBlockButton; - } else if (mBlockThirdPartyCookies || mCookieControlsMode == CookieControlsMode.ON) { + if (!params.allowCookies) { + return CookieSettingsState.BLOCK; + } else if (params.blockThirdPartyCookies + || params.cookieControlsMode == CookieControlsMode.ON) { // Having CookieControlsMode.ON is equivalent to having the BLOCK_THIRD_PARTY_COOKIES // pref set to enabled, because it means third party cookie blocking is always on. - mState = CookieSettingsState.BLOCK_THIRD_PARTY; - return mBlockThirdPartyButton; - } else if (mCookieControlsMode == CookieControlsMode.INCOGNITO_ONLY) { - mState = CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO; - return mBlockThirdPartyIncognitoButton; + return CookieSettingsState.BLOCK_THIRD_PARTY; + } else if (params.cookieControlsMode == CookieControlsMode.INCOGNITO_ONLY) { + return CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO; } else { - mState = CookieSettingsState.ALLOW; - return mAllowButton; + return CookieSettingsState.ALLOW; } } - private void setRadioButtons() { + private void configureRadioButtons(Params params) { + assert (mRadioGroup != null); mAllowButton.setEnabled(true); mBlockThirdPartyIncognitoButton.setEnabled(true); mBlockThirdPartyButton.setEnabled(true); mBlockButton.setEnabled(true); - for (RadioButtonWithDescription button : getEnforcedButtons()) { + for (RadioButtonWithDescription button : getEnforcedButtons(params)) { button.setEnabled(false); } - mManagedView.setVisibility((mCookiesContentSettingEnforced || mThirdPartyBlockingEnforced) + mManagedView.setVisibility( + (params.cookiesContentSettingEnforced || params.thirdPartyBlockingEnforced) ? View.VISIBLE : View.GONE); - RadioButtonWithDescription button = getActiveRadioButton(); + RadioButtonWithDescription button = getButton(getActiveState(params)); // Always want to enable the selected option. button.setEnabled(true); button.setChecked(true); + + mInitializationParams = null; } /** @@ -179,27 +188,45 @@ return args; } + private RadioButtonWithDescription getButton(CookieSettingsState state) { + switch (state) { + case ALLOW: + return mAllowButton; + case BLOCK_THIRD_PARTY_INCOGNITO: + return mBlockThirdPartyIncognitoButton; + case BLOCK_THIRD_PARTY: + return mBlockThirdPartyButton; + case BLOCK: + return mBlockButton; + case UNINITIALIZED: + assert false; + return null; + } + assert false; + return null; + } + /** * @return An array of radio buttons that have to be disabled as they can't be selected due to * policy restrictions. */ - private RadioButtonWithDescription[] getEnforcedButtons() { - if (!mCookiesContentSettingEnforced && !mThirdPartyBlockingEnforced) { + private RadioButtonWithDescription[] getEnforcedButtons(Params params) { + if (!params.cookiesContentSettingEnforced && !params.thirdPartyBlockingEnforced) { return buttons(); } - if (mCookiesContentSettingEnforced && mThirdPartyBlockingEnforced) { + if (params.cookiesContentSettingEnforced && params.thirdPartyBlockingEnforced) { return buttons(mAllowButton, mBlockThirdPartyIncognitoButton, mBlockThirdPartyButton, mBlockButton); } - if (mCookiesContentSettingEnforced) { - if (mAllowCookies) { + if (params.cookiesContentSettingEnforced) { + if (params.allowCookies) { return buttons(mBlockButton); } else { return buttons(mAllowButton, mBlockThirdPartyIncognitoButton, mBlockThirdPartyButton, mBlockButton); } } - if (mBlockThirdPartyCookies) { + if (params.blockThirdPartyCookies) { return buttons(mAllowButton, mBlockThirdPartyIncognitoButton); } else { return buttons(mBlockThirdPartyIncognitoButton, mBlockThirdPartyButton); @@ -207,24 +234,8 @@ } @VisibleForTesting - public boolean isStateEnforced(CookieSettingsState state) { - RadioButtonWithDescription button; - switch (state) { - case ALLOW: - button = mAllowButton; - break; - case BLOCK_THIRD_PARTY_INCOGNITO: - button = mBlockThirdPartyIncognitoButton; - break; - case BLOCK_THIRD_PARTY: - button = mBlockThirdPartyButton; - break; - case BLOCK: - button = mBlockButton; - break; - default: - return false; - } - return Arrays.asList(getEnforcedButtons()).contains(button); + boolean isButtonEnabledForTesting(CookieSettingsState state) { + assert getButton(state) != null; + return getButton(state).isEnabled(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/SingleCategorySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/SingleCategorySettings.java index 754ce5e..ef0dbf6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/SingleCategorySettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/SingleCategorySettings.java
@@ -1034,11 +1034,18 @@ private void configureFourStateCookieToggle( FourStateCookieSettingsPreference fourStateCookieToggle) { fourStateCookieToggle.setOnPreferenceChangeListener(this); - fourStateCookieToggle.setState(mCategory.isManaged(), - PrefServiceBridge.getInstance().isManagedPreference(Pref.BLOCK_THIRD_PARTY_COOKIES), - WebsitePreferenceBridge.isCategoryEnabled(ContentSettingsType.COOKIES), - PrefServiceBridge.getInstance().getBoolean(Pref.BLOCK_THIRD_PARTY_COOKIES), - PrefServiceBridge.getInstance().getInteger(Pref.COOKIE_CONTROLS_MODE)); + FourStateCookieSettingsPreference.Params params = + new FourStateCookieSettingsPreference.Params(); + params.allowCookies = + WebsitePreferenceBridge.isCategoryEnabled(ContentSettingsType.COOKIES); + params.blockThirdPartyCookies = + PrefServiceBridge.getInstance().getBoolean(Pref.BLOCK_THIRD_PARTY_COOKIES); + params.cookieControlsMode = + PrefServiceBridge.getInstance().getInteger(Pref.COOKIE_CONTROLS_MODE); + params.cookiesContentSettingEnforced = mCategory.isManaged(); + params.thirdPartyBlockingEnforced = + PrefServiceBridge.getInstance().isManagedPreference(Pref.BLOCK_THIRD_PARTY_COOKIES); + fourStateCookieToggle.setState(params); } private void configureTriStateToggle(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java index 0f29641..0f707a1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java
@@ -6,6 +6,8 @@ import android.text.TextUtils; +import androidx.annotation.Nullable; + import org.chromium.base.ContextUtils; import org.chromium.content_public.browser.ImeAdapter; import org.chromium.content_public.browser.ImeEventObserver; @@ -37,8 +39,9 @@ super(tab); tab.addObserver(new EmptyTabObserver() { @Override - public void onInitialized(Tab tab, TabState tabState) { - if (tabState != null) setAppId(tabState.openerAppId); + public void onInitialized( + Tab tab, String appId, @Nullable Boolean hasThemeColor, int themeColor) { + setAppId(appId); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelper.java index 9ad63b1..fa46584 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelper.java
@@ -80,7 +80,8 @@ mConstraintsChangedCallback = (constraints) -> updateEnabledState(); mTab.addObserver(new EmptyTabObserver() { @Override - public void onInitialized(Tab tab, TabState tabState) { + public void onInitialized( + Tab tab, String appId, @Nullable Boolean hasThemeColor, int themeColor) { updateVisibilityDelegate(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java index 3738986..eeac2c8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -301,7 +301,14 @@ return mWindowAndroid; } - @Override + /** + * Update the attachment state to Window(Activity). + * @param window A new {@link WindowAndroid} to attach the tab to. If {@code null}, + * the tab is being detached. See {@link ReparentingTask#detach()} for details. + * @param tabDelegateFactory The new delegate factory this tab should be using. Can be + * {@code null} even when {@code window} is not, meaning we simply want to swap out + * {@link WindowAndroid} for this tab and keep using the current delegate factory. + */ public void updateAttachment( @Nullable WindowAndroid window, @Nullable TabDelegateFactory tabDelegateFactory) { // Non-null delegate factory while being detached is not valid. @@ -845,7 +852,12 @@ if (mTimestampMillis == INVALID_TIMESTAMP) { mTimestampMillis = System.currentTimeMillis(); } - for (TabObserver observer : mObservers) observer.onInitialized(this, tabState); + String appId = tabState != null ? tabState.openerAppId : null; + Boolean hasThemeColor = tabState != null ? tabState.hasThemeColor() : null; + int themeColor = tabState != null ? tabState.getThemeColor() : 0; + for (TabObserver observer : mObservers) { + observer.onInitialized(this, appId, hasThemeColor, themeColor); + } TraceEvent.end("Tab.initialize"); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java index 5009aeb8..265654db40 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java
@@ -213,13 +213,14 @@ // TabObserver @Override - public void onInitialized(Tab tab, TabState tabState) { - if (tabState == null) return; + public void onInitialized( + Tab tab, String appId, @Nullable Boolean hasThemeColor, int themeColor) { + if (hasThemeColor == null) return; // Update from TabState. - mIsUsingColorFromTabContents = tabState.hasThemeColor(); + mIsUsingColorFromTabContents = hasThemeColor; mIsDefaultColorUsed = !mIsUsingColorFromTabContents; - mColor = mIsDefaultColorUsed ? getDefaultColor() : tabState.getThemeColor(); + mColor = mIsDefaultColorUsed ? getDefaultColor() : themeColor; updateIfNeeded(false); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab_activity_glue/ReparentingTask.java b/chrome/android/java/src/org/chromium/chrome/browser/tab_activity_glue/ReparentingTask.java index ecb778f..1564ee96 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab_activity_glue/ReparentingTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab_activity_glue/ReparentingTask.java
@@ -144,7 +144,7 @@ // TabModelSelector of this Tab, if present, gets notified to remove the tab from // the TabModel it belonged to. - mTab.updateAttachment(null, null); + ((TabImpl) mTab).updateAttachment(null, null); } /** @@ -174,7 +174,7 @@ // Assert that the tab is currently in detached state. assert mTab.getWebContents() == null || mTab.getWebContents().getTopLevelNativeWindow() == null; - mTab.updateAttachment(window, tabDelegateFactory); + ((TabImpl) mTab).updateAttachment(window, tabDelegateFactory); ReparentingTaskJni.get().attachTab(mTab.getWebContents()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java index 66a1142..e6883bf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
@@ -848,9 +848,6 @@ } @Override - public void performSearchQuery(String query) {} - - @Override public void setUrlBarFocus(boolean shouldBeFocused, @Nullable String pastedText, @LocationBar.OmniboxFocusReason int reason) {}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java index 6625573..19af068 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.share.ShareDelegateImpl; import org.chromium.chrome.browser.share.ShareHelper; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabImpl; import org.chromium.chrome.browser.ui.RootUiCoordinator; import org.chromium.chrome.browser.util.ChromeFileProvider; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController; @@ -183,7 +184,7 @@ }; }); TestThreadUtils.runOnUiThreadBlocking( - () -> mockActivity.getActivityTab().updateAttachment(window, null)); + () -> ((TabImpl) mockActivity.getActivityTab()).updateAttachment(window, null)); TestThreadUtils.runOnUiThreadBlocking( ()
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 23495461..67dbe4b0 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
@@ -261,7 +261,7 @@ /** * Checks if the button representing the given state matches the managed expectation. */ - private void checkFourStateCookieToggleButtonUnmanaged(final SettingsActivity settingsActivity, + private void checkFourStateCookieToggleButtonEnabled(final SettingsActivity settingsActivity, final CookieSettingsState state, final boolean expected) { TestThreadUtils.runOnUiThreadBlocking(() -> { SingleCategorySettings preferences = @@ -269,8 +269,8 @@ FourStateCookieSettingsPreference fourStateCookieToggle = (FourStateCookieSettingsPreference) preferences.findPreference( SingleCategorySettings.FOUR_STATE_COOKIE_TOGGLE_KEY); - Assert.assertNotEquals("Button should be " + (expected ? "unmanaged" : "managed"), - fourStateCookieToggle.isStateEnforced(state), expected); + Assert.assertEquals(state + " button should be " + (expected ? "enabled" : "disabled"), + fourStateCookieToggle.isButtonEnabledForTesting(state), expected); }); } @@ -544,58 +544,57 @@ } /** - * Set the cookie content setting to managed and ensure the correct radio buttons are enforced. + * Set the cookie content setting to allow through policy and ensure the correct radio buttons + * are enabled. */ @Test @SmallTest @Feature({"Preferences"}) @Policies.Add({ @Policies.Item(key = "DefaultCookiesSetting", string = "1") }) - public void testDefaultCookiesSettingManagedTrue() throws Exception { + public void testDefaultCookiesSettingManagedAllow() throws Exception { checkDefaultCookiesSettingManaged(true); checkThirdPartyCookieBlockingManaged(false); - // The ContentSetting is managed (and set to true) while ThirdPartyCookieBlocking is not - // managed. This means that every button other than BLOCKED is unmanaged. + // The ContentSetting is managed (and set to ALLOW) while ThirdPartyCookieBlocking is not + // managed. This means that every button other than BLOCK is enabled. SettingsActivity settingsActivity = SiteSettingsTestUtils.startSiteSettingsCategory(SiteSettingsCategory.Type.COOKIES); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.ALLOW, true); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.ALLOW, true); + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO, true); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY, true); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.BLOCK, false); + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.BLOCK, false); settingsActivity.finish(); } /** - * Set the cookie content setting to managed and ensure the correct radio buttons are enforced. + * Set the cookie content setting to block through a policy and ensure the correct radio buttons + * are enabled. */ @Test @SmallTest @Feature({"Preferences"}) @Policies.Add({ @Policies.Item(key = "DefaultCookiesSetting", string = "2") }) - public void testDefaultCookiesSettingManagedFalse() throws Exception { + public void testDefaultCookiesSettingManagedBlock() { checkDefaultCookiesSettingManaged(true); checkThirdPartyCookieBlockingManaged(false); - // The ContentSetting is managed (and set to false) while ThirdPartyCookieBlocking is not + // The ContentSetting is managed (and set to BLOCK) while ThirdPartyCookieBlocking is not // managed. This means cookies should always be blocked, so the user cannot choose any other - // options and all buttons should be managed. + // options and all buttons except the active one should be disabled. SettingsActivity settingsActivity = SiteSettingsTestUtils.startSiteSettingsCategory(SiteSettingsCategory.Type.COOKIES); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.ALLOW, false); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.ALLOW, false); + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO, false); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY, false); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.BLOCK, false); + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.BLOCK, true); settingsActivity.finish(); } /** - * Set third-party cookie blocking to managed and ensure the correct radio buttons are enforced. + * Enable third-party cookie blocking through policy and ensure the correct radio buttons are + * enabled. */ @Test @SmallTest @@ -607,22 +606,21 @@ checkThirdPartyCookieBlockingManaged(true); // ThirdPartyCookieBlocking is managed (and set to true) while the ContentSetting is not // managed. This means a user can choose only between BLOCK_THIRD_PARTY and BLOCK, so only - // these should be unmanaged. + // these should be enabled. SettingsActivity settingsActivity = SiteSettingsTestUtils.startSiteSettingsCategory(SiteSettingsCategory.Type.COOKIES); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.ALLOW, false); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.ALLOW, false); + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO, false); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY, true); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.BLOCK, true); + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.BLOCK, true); settingsActivity.finish(); } /** - * Set third-party cookie blocking to managed and ensure the correct radio buttons are enforced. + * Disable third-party cookie blocking through policy and ensure the correct radio buttons are + * enabled. */ @Test @SmallTest @@ -634,23 +632,21 @@ checkThirdPartyCookieBlockingManaged(true); // ThirdPartyCookieBlocking is managed (and set to false) while the ContentSetting is not // managed. This means a user can only choose to ALLOW all cookies or BLOCK all cookies, so - // only these should be unmanaged. + // only these should be enabled. SettingsActivity settingsActivity = SiteSettingsTestUtils.startSiteSettingsCategory(SiteSettingsCategory.Type.COOKIES); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.ALLOW, true); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.ALLOW, true); + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO, false); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY, false); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.BLOCK, true); + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.BLOCK, true); settingsActivity.finish(); } /** - * Set both the cookie content setting and third-party cookie blocking to managed and ensure the - * correct radio buttons are enforced. + * Set both the cookie content setting and third-party cookie blocking through policy and ensure + * the correct radio buttons are enabled. */ @Test @SmallTest @@ -664,18 +660,16 @@ checkDefaultCookiesSettingManaged(true); checkThirdPartyCookieBlockingManaged(true); // The ContentSetting and ThirdPartyCookieBlocking are managed. This means a user has a - // fixed setting for cookies that they cannot change. Therefore, all buttons should be - // managed. + // fixed setting for cookies that they cannot change. Therefore, all buttons except the + // selected one should be disabled. SettingsActivity settingsActivity = SiteSettingsTestUtils.startSiteSettingsCategory(SiteSettingsCategory.Type.COOKIES); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.ALLOW, false); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.ALLOW, true); + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO, false); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY, false); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.BLOCK, false); + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.BLOCK, false); settingsActivity.finish(); } @@ -689,17 +683,15 @@ checkDefaultCookiesSettingManaged(false); checkThirdPartyCookieBlockingManaged(false); // The ContentSetting and ThirdPartyCookieBlocking are unmanaged. This means all buttons - // should be unmanaged. + // should be enabled. SettingsActivity settingsActivity = SiteSettingsTestUtils.startSiteSettingsCategory(SiteSettingsCategory.Type.COOKIES); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.ALLOW, true); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.ALLOW, true); + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY_INCOGNITO, true); - checkFourStateCookieToggleButtonUnmanaged( + checkFourStateCookieToggleButtonEnabled( settingsActivity, CookieSettingsState.BLOCK_THIRD_PARTY, true); - checkFourStateCookieToggleButtonUnmanaged( - settingsActivity, CookieSettingsState.BLOCK, true); + checkFourStateCookieToggleButtonEnabled(settingsActivity, CookieSettingsState.BLOCK, true); settingsActivity.finish(); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelperTest.java index 3ce26d9..38dca84 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelperTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelperTest.java
@@ -75,7 +75,7 @@ initHelper(); Mockito.verify(mDelegateFactory, Mockito.never()) .createBrowserControlsVisibilityDelegate(mTab); - mRegisteredTabObserver.onInitialized(mTab, null); + mRegisteredTabObserver.onInitialized(mTab, null, null, 0); Mockito.verify(mDelegateFactory, Mockito.times(1)) .createBrowserControlsVisibilityDelegate(mTab); verifyUpdateState(BrowserControlsState.BOTH); @@ -126,7 +126,7 @@ initHelper(); Mockito.verify(mDelegateFactory, Mockito.never()) .createBrowserControlsVisibilityDelegate(mTab); - mRegisteredTabObserver.onInitialized(mTab, null); + mRegisteredTabObserver.onInitialized(mTab, null, null, 0); Mockito.verify(mDelegateFactory).createBrowserControlsVisibilityDelegate(mTab); Mockito.verifyNoMoreInteractions(mDelegateFactory); verifyUpdateState(BrowserControlsState.BOTH);
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index ca39bc9..e8d8e2e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4740,6 +4740,13 @@ #endif // OS_CHROMEOS #if defined(OS_CHROMEOS) + {"enable-edu-coexistence-consent-log", + flag_descriptions::kEnableEduCoexistenceConsentLogName, + flag_descriptions::kEnableEduCoexistenceConsentLogDescription, kOsCrOS, + FEATURE_VALUE_TYPE(chromeos::features::kEduCoexistenceConsentLog)}, +#endif // OS_CHROMEOS + +#if defined(OS_CHROMEOS) {"enable-assistant-routines", flag_descriptions::kEnableAssistantRoutinesName, flag_descriptions::kEnableAssistantRoutinesDescription, kOsCrOS,
diff --git a/chrome/browser/android/examples/custom_tabs_client/BUILD.gn b/chrome/browser/android/examples/custom_tabs_client/BUILD.gn new file mode 100644 index 0000000..7b21ce5 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/BUILD.gn
@@ -0,0 +1,79 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +android_resources("chrome_tabs_client_example_apk_resources") { + sources = [ + "src/res/anim/slide_in_left.xml", + "src/res/anim/slide_in_right.xml", + "src/res/anim/slide_out_left.xml", + "src/res/anim/slide_out_right.xml", + "src/res/drawable-hdpi/cover.jpg", + "src/res/drawable-hdpi/ic_arrow_back.png", + "src/res/drawable-hdpi/ic_launcher.png", + "src/res/drawable-hdpi/ic_notification_icon.png", + "src/res/drawable-hdpi/ic_play.png", + "src/res/drawable-hdpi/ic_share.png", + "src/res/drawable-hdpi/ic_stop.png", + "src/res/drawable-mdpi/cover.jpg", + "src/res/drawable-mdpi/ic_arrow_back.png", + "src/res/drawable-mdpi/ic_launcher.png", + "src/res/drawable-mdpi/ic_notification_icon.png", + "src/res/drawable-mdpi/ic_play.png", + "src/res/drawable-mdpi/ic_share.png", + "src/res/drawable-mdpi/ic_stop.png", + "src/res/drawable-xhdpi/cover.jpg", + "src/res/drawable-xhdpi/ic_arrow_back.png", + "src/res/drawable-xhdpi/ic_launcher.png", + "src/res/drawable-xhdpi/ic_notification_icon.png", + "src/res/drawable-xhdpi/ic_play.png", + "src/res/drawable-xhdpi/ic_share.png", + "src/res/drawable-xhdpi/ic_stop.png", + "src/res/drawable-xxhdpi/cover.jpg", + "src/res/drawable-xxhdpi/ic_arrow_back.png", + "src/res/drawable-xxhdpi/ic_launcher.png", + "src/res/drawable-xxhdpi/ic_notification_icon.png", + "src/res/drawable-xxhdpi/ic_play.png", + "src/res/drawable-xxhdpi/ic_share.png", + "src/res/drawable-xxhdpi/ic_stop.png", + "src/res/drawable-xxxhdpi/ic_arrow_back.png", + "src/res/drawable-xxxhdpi/ic_launcher.png", + "src/res/drawable-xxxhdpi/ic_share.png", + "src/res/layout/main.xml", + "src/res/layout/remote_view.xml", + "src/res/raw/amazing_grace.mp3", + "src/res/values/strings.xml", + ] + android_manifest = "src/AndroidManifest.xml" + custom_package = "org.chromium.customtabsclient" + deps = [ "//third_party/android_deps:android_support_v7_appcompat_java" ] +} + +android_apk("custom_tabs_client_example_apk") { + sources = [ + "src/java/org/chromium/customtabsclient/BottomBarManager.java", + "src/java/org/chromium/customtabsclient/BrowserActionsReceiver.java", + "src/java/org/chromium/customtabsclient/MainActivity.java", + "src/java/org/chromium/customtabsclient/SessionHelper.java", + "src/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java", + "src/java/org/chromium/customtabsclient/shared/KeepAliveService.java", + "src/java/org/chromium/customtabsclient/shared/ServiceConnection.java", + "src/java/org/chromium/customtabsclient/shared/ServiceConnectionCallback.java", + ] + + android_manifest = "src/AndroidManifest.xml" + min_sdk_version = 19 + target_sdk_version = 21 + apk_name = "CustomTabsClientExample" + + deps = [ + ":chrome_tabs_client_example_apk_resources", + "//third_party/android_deps:android_support_v7_appcompat_java", + "//third_party/android_deps:androidx_annotation_annotation_java", + "//third_party/android_deps:androidx_appcompat_appcompat_java", + "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java", + "//third_party/android_sdk/androidx_browser:androidx_browser_java", + ] +}
diff --git a/chrome/browser/android/examples/custom_tabs_client/OWNERS b/chrome/browser/android/examples/custom_tabs_client/OWNERS new file mode 100644 index 0000000..0922ed2 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/OWNERS
@@ -0,0 +1,4 @@ +file://chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS + +# COMPONENT: UI>Browser>Mobile>CustomTabs +# OS: Android \ No newline at end of file
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/AndroidManifest.xml b/chrome/browser/android/examples/custom_tabs_client/src/AndroidManifest.xml new file mode 100644 index 0000000..f5d3ae19a --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/AndroidManifest.xml
@@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.chromium.customtabsclient" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk + android:minSdkVersion="19" + android:targetSdkVersion="21" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:allowBackup="false" + android:theme="@style/Theme.AppCompat.Light" > + + <activity + android:name="org.chromium.customtabsclient.MainActivity" + android:label="@string/app_name"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + + <intent-filter> + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE"/> + <data android:scheme="https" + android:host="www.example.com" + android:pathPrefix="/notifications"/> + </intent-filter> + + </activity> + <service + android:name=".shared.KeepAliveService" + android:exported="true"/> + <receiver android:name=".BottomBarManager"/> + + + <service + android:name="android.support.customtabs.trusted.TrustedWebActivityService" + android:enabled="true" + android:exported="true"> + + <meta-data android:name="android.support.customtabs.trusted.SMALL_ICON" + android:resource="@drawable/ic_notification_icon" /> + + <intent-filter> + <action android:name="android.support.customtabs.trusted.TRUSTED_WEB_ACTIVITY_SERVICE"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> + </service> + </application> +</manifest>
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/BottomBarManager.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/BottomBarManager.java new file mode 100644 index 0000000..7ad3574 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/BottomBarManager.java
@@ -0,0 +1,86 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.customtabsclient; + +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.media.MediaPlayer; +import android.widget.RemoteViews; +import android.widget.Toast; + +import androidx.browser.customtabs.CustomTabsIntent; +import androidx.browser.customtabs.CustomTabsSession; + +import java.lang.ref.WeakReference; + +/** + * A {@link BroadcastReceiver} that manages the interaction with the active Custom Tab. + */ +public class BottomBarManager extends BroadcastReceiver { + private static WeakReference<MediaPlayer> sMediaPlayerWeakRef; + + @Override + public void onReceive(Context context, Intent intent) { + int clickedId = intent.getIntExtra(CustomTabsIntent.EXTRA_REMOTEVIEWS_CLICKED_ID, -1); + Toast.makeText(context, "Current URL " + intent.getDataString() + "\nClicked id " + + clickedId, Toast.LENGTH_SHORT).show(); + + CustomTabsSession session = SessionHelper.getCurrentSession(); + if (session == null) return; + + if (clickedId == R.id.play_pause) { + MediaPlayer player = sMediaPlayerWeakRef.get(); + if (player != null) { + boolean isPlaying = player.isPlaying(); + if (isPlaying) player.pause(); + else player.start(); + // Update the play/stop icon to respect the current state. + session.setSecondaryToolbarViews(createRemoteViews(context, isPlaying), + getClickableIDs(), getOnClickPendingIntent(context)); + } + } else if (clickedId == R.id.cover) { + // Clicking on the cover image will dismiss the bottom bar. + session.setSecondaryToolbarViews(null, null, null); + } + } + + /** + * Creates a RemoteViews that will be shown as the bottom bar of the custom tab. + * @param showPlayIcon If true, a play icon will be shown, otherwise show a pause icon. + * @return The created RemoteViews instance. + */ + public static RemoteViews createRemoteViews(Context context, boolean showPlayIcon) { + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.remote_view); + + int iconRes = showPlayIcon ? R.drawable.ic_play : R.drawable.ic_stop; + remoteViews.setImageViewResource(R.id.play_pause, iconRes); + return remoteViews; + } + + /** + * @return A list of View ids, the onClick event of which is handled by Custom Tab. + */ + public static int[] getClickableIDs() { + return new int[]{R.id.play_pause, R.id.cover}; + } + + /** + * @return The PendingIntent that will be triggered when the user clicks on the Views listed by + * {@link BottomBarManager#getClickableIDs()}. + */ + public static PendingIntent getOnClickPendingIntent(Context context) { + Intent broadcastIntent = new Intent(context, BottomBarManager.class); + return PendingIntent.getBroadcast(context, 0, broadcastIntent, 0); + } + + /** + * Sets the {@link MediaPlayer} to be used when the user clicks on the RemoteViews. + */ + public static void setMediaPlayer(MediaPlayer player) { + sMediaPlayerWeakRef = new WeakReference<>(player); + } +}
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/BrowserActionsReceiver.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/BrowserActionsReceiver.java new file mode 100644 index 0000000..93f6752 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/BrowserActionsReceiver.java
@@ -0,0 +1,22 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.customtabsclient; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.widget.Toast; + +/** + * A {@link BroadcastReceiver} that handles the callback if default menu items are chosen from + * Browser Actions. + */ +public class BrowserActionsReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String toastMsg = "Chosen item Id: " + intent.getDataString(); + Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show(); + } +} \ No newline at end of file
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java new file mode 100644 index 0000000..d67d86b0 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java
@@ -0,0 +1,298 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.customtabsclient; + +import android.app.ActivityManager; +import android.app.ActivityOptions; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.util.Log; +import android.util.Pair; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.TextView; + +import androidx.browser.customtabs.CustomTabsCallback; +import androidx.browser.customtabs.CustomTabsClient; +import androidx.browser.customtabs.CustomTabsIntent; +import androidx.browser.customtabs.CustomTabsServiceConnection; +import androidx.browser.customtabs.CustomTabsSession; + +import org.chromium.customtabsclient.shared.CustomTabsHelper; +import org.chromium.customtabsclient.shared.ServiceConnection; +import org.chromium.customtabsclient.shared.ServiceConnectionCallback; + +import java.util.ArrayList; +import java.util.List; + +/** + * Example client activity for using Chrome Custom Tabs. + */ +public class MainActivity + extends AppCompatActivity implements OnClickListener, ServiceConnectionCallback { + private static final String TAG = "CustomTabsClientExample"; + private static final String TOOLBAR_COLOR = "#ef6c00"; + + private EditText mEditText; + private CustomTabsSession mCustomTabsSession; + private CustomTabsClient mClient; + private CustomTabsServiceConnection mConnection; + private String mPackageNameToBind; + private Button mConnectButton; + private Button mWarmupButton; + private Button mMayLaunchButton; + private Button mLaunchButton; + private MediaPlayer mMediaPlayer; + + /** + * Once per second, asks the framework for the process importance, and logs any change. + */ + private Runnable mLogImportance = new Runnable() { + private int mPreviousImportance = -1; + private boolean mPreviousServiceInUse = false; + private Handler mHandler = new Handler(Looper.getMainLooper()); + + @Override + public void run() { + ActivityManager.RunningAppProcessInfo state = + new ActivityManager.RunningAppProcessInfo(); + ActivityManager.getMyMemoryState(state); + int importance = state.importance; + boolean serviceInUse = state.importanceReasonCode + == ActivityManager.RunningAppProcessInfo.REASON_SERVICE_IN_USE; + if (importance != mPreviousImportance || serviceInUse != mPreviousServiceInUse) { + mPreviousImportance = importance; + mPreviousServiceInUse = serviceInUse; + String message = "New importance = " + importance; + if (serviceInUse) message += " (Reason: Service in use)"; + Log.w(TAG, message); + } + mHandler.postDelayed(this, 1000); + } + }; + + private static class NavigationCallback extends CustomTabsCallback { + @Override + public void onNavigationEvent(int navigationEvent, Bundle extras) { + Log.w(TAG, "onNavigationEvent: Code = " + navigationEvent); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + mEditText = (EditText) findViewById(R.id.edit); + mConnectButton = (Button) findViewById(R.id.connect_button); + mWarmupButton = (Button) findViewById(R.id.warmup_button); + mMayLaunchButton = (Button) findViewById(R.id.may_launch_button); + mLaunchButton = (Button) findViewById(R.id.launch_button); + Spinner spinner = (Spinner) findViewById(R.id.spinner); + mEditText.requestFocus(); + mConnectButton.setOnClickListener(this); + mWarmupButton.setOnClickListener(this); + mMayLaunchButton.setOnClickListener(this); + mLaunchButton.setOnClickListener(this); + mMediaPlayer = MediaPlayer.create(this, R.raw.amazing_grace); + findViewById(R.id.register_twa_service).setOnClickListener(this); + + Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com")); + PackageManager pm = getPackageManager(); + List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities( + activityIntent, PackageManager.MATCH_ALL); + List<Pair<String, String>> packagesSupportingCustomTabs = new ArrayList<>(); + for (ResolveInfo info : resolvedActivityList) { + Intent serviceIntent = new Intent(); + serviceIntent.setAction("android.support.customtabs.action.CustomTabsService"); + serviceIntent.setPackage(info.activityInfo.packageName); + if (pm.resolveService(serviceIntent, 0) != null) { + packagesSupportingCustomTabs.add( + Pair.create(info.loadLabel(pm).toString(), info.activityInfo.packageName)); + } + } + + final ArrayAdapter<Pair<String, String>> adapter = new ArrayAdapter<Pair<String, String>>( + this, 0, packagesSupportingCustomTabs) { + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view = convertView; + if (view == null) { + view = LayoutInflater.from(MainActivity.this).inflate( + android.R.layout.simple_list_item_2, parent, false); + } + Pair<String, String> data = getItem(position); + ((TextView) view.findViewById(android.R.id.text1)).setText(data.first); + ((TextView) view.findViewById(android.R.id.text2)).setText(data.second); + return view; + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + return getView(position, convertView, parent); + } + }; + spinner.setAdapter(adapter); + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + Pair<String, String> item = adapter.getItem(position); + if (TextUtils.isEmpty(item.second)) { + onNothingSelected(parent); + return; + } + mPackageNameToBind = item.second; + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + mPackageNameToBind = null; + } + }); + + mLogImportance.run(); + } + + @Override + protected void onDestroy() { + unbindCustomTabsService(); + super.onDestroy(); + } + + private CustomTabsSession getSession() { + if (mClient == null) { + mCustomTabsSession = null; + } else if (mCustomTabsSession == null) { + mCustomTabsSession = mClient.newSession(new NavigationCallback()); + SessionHelper.setCurrentSession(mCustomTabsSession); + } + return mCustomTabsSession; + } + + private void bindCustomTabsService() { + if (mClient != null) return; + if (TextUtils.isEmpty(mPackageNameToBind)) { + mPackageNameToBind = CustomTabsHelper.getPackageNameToUse(this); + if (mPackageNameToBind == null) return; + } + mConnection = new ServiceConnection(this); + boolean ok = CustomTabsClient.bindCustomTabsService(this, mPackageNameToBind, mConnection); + if (ok) { + mConnectButton.setEnabled(false); + } else { + mConnection = null; + } + } + + private void unbindCustomTabsService() { + if (mConnection == null) return; + unbindService(mConnection); + mClient = null; + mCustomTabsSession = null; + } + + @Override + public void onClick(View v) { + String url = mEditText.getText().toString(); + int viewId = v.getId(); + + if (viewId == R.id.connect_button) { + bindCustomTabsService(); + } else if (viewId == R.id.warmup_button) { + boolean success = false; + if (mClient != null) success = mClient.warmup(0); + if (!success) mWarmupButton.setEnabled(false); + } else if (viewId == R.id.may_launch_button) { + CustomTabsSession session = getSession(); + boolean success = false; + if (mClient != null) success = session.mayLaunchUrl(Uri.parse(url), null, null); + if (!success) mMayLaunchButton.setEnabled(false); + } else if (viewId == R.id.launch_button) { + CustomTabsSession session = getSession(); + CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(session); + builder.setToolbarColor(Color.parseColor(TOOLBAR_COLOR)).setShowTitle(true); + prepareMenuItems(builder); + prepareActionButton(builder); + if (session != null) prepareBottombar(builder); + builder.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left); + builder.setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right); + builder.setCloseButtonIcon( + BitmapFactory.decodeResource(getResources(), R.drawable.ic_arrow_back)); + CustomTabsIntent customTabsIntent = builder.build(); + if (session != null) { + CustomTabsHelper.addKeepAliveExtra(this, customTabsIntent.intent); + } else { + if (!TextUtils.isEmpty(mPackageNameToBind)) { + customTabsIntent.intent.setPackage(mPackageNameToBind); + } + } + customTabsIntent.launchUrl(this, Uri.parse(url)); + } + } + + private void prepareMenuItems(CustomTabsIntent.Builder builder) { + Intent menuIntent = new Intent(); + menuIntent.setClass(getApplicationContext(), this.getClass()); + // Optional animation configuration when the user clicks menu items. + Bundle menuBundle = ActivityOptions.makeCustomAnimation(this, android.R.anim.slide_in_left, + android.R.anim.slide_out_right).toBundle(); + PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, menuIntent, 0, + menuBundle); + builder.addMenuItem("Menu entry 1", pi); + } + + private void prepareActionButton(CustomTabsIntent.Builder builder) { + // An example intent that sends an email. + Intent actionIntent = new Intent(Intent.ACTION_SEND); + actionIntent.setType("*/*"); + actionIntent.putExtra(Intent.EXTRA_EMAIL, "example@example.com"); + actionIntent.putExtra(Intent.EXTRA_SUBJECT, "example"); + PendingIntent pi = PendingIntent.getActivity(this, 0, actionIntent, 0); + Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_share); + builder.setActionButton(icon, "send email", pi, true); + } + + private void prepareBottombar(CustomTabsIntent.Builder builder) { + BottomBarManager.setMediaPlayer(mMediaPlayer); + builder.setSecondaryToolbarViews(BottomBarManager.createRemoteViews(this, true), + BottomBarManager.getClickableIDs(), BottomBarManager.getOnClickPendingIntent(this)); + } + + @Override + public void onServiceConnected(CustomTabsClient client) { + mClient = client; + mConnectButton.setEnabled(false); + mWarmupButton.setEnabled(true); + mMayLaunchButton.setEnabled(true); + mLaunchButton.setEnabled(true); + } + + @Override + public void onServiceDisconnected() { + mConnectButton.setEnabled(true); + mWarmupButton.setEnabled(false); + mMayLaunchButton.setEnabled(false); + mLaunchButton.setEnabled(false); + mClient = null; + } +}
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/SessionHelper.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/SessionHelper.java new file mode 100644 index 0000000..98a46d1 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/SessionHelper.java
@@ -0,0 +1,34 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.customtabsclient; + +import android.support.annotation.Nullable; + +import androidx.browser.customtabs.CustomTabsSession; + +import java.lang.ref.WeakReference; + +/** + * A class that keeps tracks of the current {@link CustomTabsSession} and helps other components of + * the app to get access to the current session. + */ +public class SessionHelper { + private static WeakReference<CustomTabsSession> sCurrentSession; + + /** + * @return The current {@link CustomTabsSession} object. + */ + public static @Nullable CustomTabsSession getCurrentSession() { + return sCurrentSession == null ? null : sCurrentSession.get(); + } + + /** + * Sets the current session to the given one. + * @param session The current session. + */ + public static void setCurrentSession(CustomTabsSession session) { + sCurrentSession = new WeakReference<CustomTabsSession>(session); + } +}
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java new file mode 100644 index 0000000..132769ce --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java
@@ -0,0 +1,132 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.customtabsclient.shared; + +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.text.TextUtils; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * Helper class for Custom Tabs. + */ +public class CustomTabsHelper { + private static final String TAG = "CustomTabsHelper"; + static final String STABLE_PACKAGE = "com.android.chrome"; + static final String BETA_PACKAGE = "com.chrome.beta"; + static final String DEV_PACKAGE = "com.chrome.dev"; + static final String LOCAL_PACKAGE = "com.google.android.apps.chrome"; + private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE = + "android.support.customtabs.extra.KEEP_ALIVE"; + private static final String ACTION_CUSTOM_TABS_CONNECTION = + "android.support.customtabs.action.CustomTabsService"; + + private static String sPackageNameToUse; + + private CustomTabsHelper() {} + + public static void addKeepAliveExtra(Context context, Intent intent) { + Intent keepAliveIntent = new Intent().setClassName( + context.getPackageName(), KeepAliveService.class.getCanonicalName()); + intent.putExtra(EXTRA_CUSTOM_TABS_KEEP_ALIVE, keepAliveIntent); + } + + /** + * Goes through all apps that handle VIEW intents and have a warmup service. Picks + * the one chosen by the user if there is one, otherwise makes a best effort to return a + * valid package name. + * + * This is <strong>not</strong> threadsafe. + * + * @param context {@link Context} to use for accessing {@link PackageManager}. + * @return The package name recommended to use for connecting to custom tabs related components. + */ + public static String getPackageNameToUse(Context context) { + if (sPackageNameToUse != null) return sPackageNameToUse; + + PackageManager pm = context.getPackageManager(); + // Get default VIEW intent handler. + Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com")); + ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0); + String defaultViewHandlerPackageName = null; + if (defaultViewHandlerInfo != null) { + defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName; + } + + // Get all apps that can handle VIEW intents. + List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0); + List<String> packagesSupportingCustomTabs = new ArrayList<>(); + for (ResolveInfo info : resolvedActivityList) { + Intent serviceIntent = new Intent(); + serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION); + serviceIntent.setPackage(info.activityInfo.packageName); + if (pm.resolveService(serviceIntent, 0) != null) { + packagesSupportingCustomTabs.add(info.activityInfo.packageName); + } + } + + // Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents + // and service calls. + if (packagesSupportingCustomTabs.isEmpty()) { + sPackageNameToUse = null; + } else if (packagesSupportingCustomTabs.size() == 1) { + sPackageNameToUse = packagesSupportingCustomTabs.get(0); + } else if (!TextUtils.isEmpty(defaultViewHandlerPackageName) + && !hasSpecializedHandlerIntents(context, activityIntent) + && packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) { + sPackageNameToUse = defaultViewHandlerPackageName; + } else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) { + sPackageNameToUse = STABLE_PACKAGE; + } else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) { + sPackageNameToUse = BETA_PACKAGE; + } else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) { + sPackageNameToUse = DEV_PACKAGE; + } else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) { + sPackageNameToUse = LOCAL_PACKAGE; + } + return sPackageNameToUse; + } + + /** + * Used to check whether there is a specialized handler for a given intent. + * @param intent The intent to check with. + * @return Whether there is a specialized handler for the given intent. + */ + private static boolean hasSpecializedHandlerIntents(Context context, Intent intent) { + try { + PackageManager pm = context.getPackageManager(); + List<ResolveInfo> handlers = pm.queryIntentActivities( + intent, + PackageManager.GET_RESOLVED_FILTER); + if (handlers == null || handlers.size() == 0) { + return false; + } + for (ResolveInfo resolveInfo : handlers) { + IntentFilter filter = resolveInfo.filter; + if (filter == null) continue; + if (filter.countDataAuthorities() == 0 || filter.countDataPaths() == 0) continue; + if (resolveInfo.activityInfo == null) continue; + return true; + } + } catch (RuntimeException e) { + Log.e(TAG, "Runtime exception while getting specialized handlers"); + } + return false; + } + + /** + * @return All possible chrome package names that provide custom tabs feature. + */ + public static String[] getPackages() { + return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE}; + } +}
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/KeepAliveService.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/KeepAliveService.java new file mode 100644 index 0000000..3bde921 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/KeepAliveService.java
@@ -0,0 +1,22 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.customtabsclient.shared; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; + +/** + * Empty service used by the custom tab to bind to, raising the application's importance. + */ +public class KeepAliveService extends Service { + private static final Binder sBinder = new Binder(); + + @Override + public IBinder onBind(Intent intent) { + return sBinder; + } +}
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/ServiceConnection.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/ServiceConnection.java new file mode 100644 index 0000000..3de4ff2f --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/ServiceConnection.java
@@ -0,0 +1,37 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.customtabsclient.shared; + +import android.content.ComponentName; + +import androidx.browser.customtabs.CustomTabsClient; +import androidx.browser.customtabs.CustomTabsServiceConnection; + +import java.lang.ref.WeakReference; + +/** + * Implementation for the CustomTabsServiceConnection that avoids leaking the + * ServiceConnectionCallback + */ +public class ServiceConnection extends CustomTabsServiceConnection { + // A weak reference to the ServiceConnectionCallback to avoid leaking it. + private WeakReference<ServiceConnectionCallback> mConnectionCallback; + + public ServiceConnection(ServiceConnectionCallback connectionCallback) { + mConnectionCallback = new WeakReference<>(connectionCallback); + } + + @Override + public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) { + ServiceConnectionCallback connectionCallback = mConnectionCallback.get(); + if (connectionCallback != null) connectionCallback.onServiceConnected(client); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + ServiceConnectionCallback connectionCallback = mConnectionCallback.get(); + if (connectionCallback != null) connectionCallback.onServiceDisconnected(); + } +}
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/ServiceConnectionCallback.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/ServiceConnectionCallback.java new file mode 100644 index 0000000..dcb57a9 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/shared/ServiceConnectionCallback.java
@@ -0,0 +1,23 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.customtabsclient.shared; + +import androidx.browser.customtabs.CustomTabsClient; + +/** + * Callback for events when connecting and disconnecting from Custom Tabs Service. + */ +public interface ServiceConnectionCallback { + /** + * Called when the service is connected. + * @param client a CustomTabsClient + */ + void onServiceConnected(CustomTabsClient client); + + /** + * Called when the service is disconnected. + */ + void onServiceDisconnected(); +}
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_in_left.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_in_left.xml new file mode 100644 index 0000000..373537bb3 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_in_left.xml
@@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="-100%p" android:toXDelta="0" + android:duration="@android:integer/config_mediumAnimTime"/> +</set>
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_in_right.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_in_right.xml new file mode 100644 index 0000000..75d0675 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_in_right.xml
@@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="100%p" android:toXDelta="0" + android:duration="@android:integer/config_mediumAnimTime"/> +</set>
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_out_left.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_out_left.xml new file mode 100644 index 0000000..6ce1676 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_out_left.xml
@@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="0" android:toXDelta="-100%p" + android:duration="@android:integer/config_mediumAnimTime"/> +</set>
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_out_right.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_out_right.xml new file mode 100644 index 0000000..def11b2 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/anim/slide_out_right.xml
@@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="0" android:toXDelta="100%p" + android:duration="@android:integer/config_mediumAnimTime"/> +</set>
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/cover.jpg b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/cover.jpg new file mode 100644 index 0000000..190160bf --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/cover.jpg Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_arrow_back.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_arrow_back.png new file mode 100644 index 0000000..fe424468 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_arrow_back.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_launcher.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..2a25824 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_launcher.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_notification_icon.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_notification_icon.png new file mode 100644 index 0000000..c2c80d4 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_notification_icon.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_play.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_play.png new file mode 100644 index 0000000..8baf85a --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_play.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_share.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_share.png new file mode 100644 index 0000000..b09a692 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_share.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_stop.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_stop.png new file mode 100644 index 0000000..33fe924 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-hdpi/ic_stop.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/cover.jpg b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/cover.jpg new file mode 100644 index 0000000..2d44a17 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/cover.jpg Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_arrow_back.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_arrow_back.png new file mode 100644 index 0000000..0904000 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_arrow_back.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_launcher.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..c38d44c --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_launcher.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_notification_icon.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_notification_icon.png new file mode 100644 index 0000000..9960b1b --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_notification_icon.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_play.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_play.png new file mode 100644 index 0000000..000238c --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_play.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_share.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_share.png new file mode 100644 index 0000000..e944fd70c --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_share.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_stop.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_stop.png new file mode 100644 index 0000000..4315863 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-mdpi/ic_stop.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/cover.jpg b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/cover.jpg new file mode 100644 index 0000000..39d46b17 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/cover.jpg Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_arrow_back.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_arrow_back.png new file mode 100644 index 0000000..ebc826c --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_arrow_back.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_launcher.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..b12097c --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_launcher.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_notification_icon.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_notification_icon.png new file mode 100644 index 0000000..00f5b4f --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_notification_icon.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_play.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_play.png new file mode 100644 index 0000000..e4d298d --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_play.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_share.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_share.png new file mode 100644 index 0000000..22a8783 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_share.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_stop.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_stop.png new file mode 100644 index 0000000..7f24bf2 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xhdpi/ic_stop.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/cover.jpg b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/cover.jpg new file mode 100644 index 0000000..3e05d2f --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/cover.jpg Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_arrow_back.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_arrow_back.png new file mode 100644 index 0000000..099f9edc --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_arrow_back.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_launcher.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..71b68abe --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_launcher.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_notification_icon.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_notification_icon.png new file mode 100644 index 0000000..c2c7d73 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_notification_icon.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_play.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_play.png new file mode 100644 index 0000000..9f5d2b7b --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_play.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_share.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_share.png new file mode 100644 index 0000000..a35b3cd --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_share.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_stop.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_stop.png new file mode 100644 index 0000000..82a4ccc --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxhdpi/ic_stop.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_arrow_back.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_arrow_back.png new file mode 100644 index 0000000..fb06e1d --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_arrow_back.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_launcher.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..32443be --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_launcher.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_share.png b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_share.png new file mode 100644 index 0000000..e351c7b --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/drawable-xxxhdpi/ic_share.png Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/layout/main.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/layout/main.xml new file mode 100644 index 0000000..c185d8d --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/layout/main.xml
@@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="match_parent" + android:layout_width="match_parent"> + + <LinearLayout + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:padding="5dp" + android:orientation="vertical" > + + <EditText + android:id="@+id/edit" + android:padding="5dp" + android:layout_margin="5dp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="@string/url_hint" + android:inputType="textNoSuggestions" + android:text="@string/default_url" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="3dp" + android:orientation="horizontal"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="3dp" + android:text="@string/package_label"/> + + <Spinner + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/spinner" + android:layout_margin="3dp" + android:layout_gravity="center_horizontal" /> + </LinearLayout> + + <Space + android:layout_width="match_parent" + android:layout_height="5dp" /> + + <Button + android:id="@+id/connect_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="3dp" + android:textAllCaps="false" + android:text="@string/connect_button_text" + android:enabled="true" /> + + <Button + android:id="@+id/warmup_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="3dp" + android:textAllCaps="false" + android:text="@string/warmup_button_text" + android:enabled="false" /> + + <Button + android:id="@+id/may_launch_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="3dp" + android:textAllCaps="false" + android:text="@string/may_launch_button_text" + android:enabled="false" /> + + <Button + android:id="@+id/launch_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="3dp" + android:textAllCaps="false" + android:text="@string/launch_button_text" + android:enabled="true" /> + + <Button + android:id="@+id/launch_browser_actions_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="3dp" + android:textAllCaps="false" + android:text="@string/launch_browser_actions_button_text" /> + + <Button + android:id="@+id/register_twa_service" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="3dp" + android:textAllCaps="false" + android:text="@string/register_twa_service" /> + + </LinearLayout> + +</ScrollView>
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/layout/remote_view.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/layout/remote_view.xml new file mode 100644 index 0000000..f41ae36 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/layout/remote_view.xml
@@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="56dp" + android:orientation="horizontal" + android:background="@android:color/white"> + + <android.widget.ImageView + android:id="@+id/cover" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_margin="4dp" + android:scaleType="centerCrop" + android:src="@drawable/cover"/> + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:orientation="vertical" + android:padding="4dp"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/amazing_grace" + android:paddingTop="2dp" + android:textSize="16sp" + android:textColor="@android:color/black"/> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingTop="2dp" + android:text="@string/artist" + android:textSize="12sp" + android:textColor="#666666"/> + </LinearLayout> + + <android.widget.ImageView + android:id="@+id/play_pause" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginStart="4dp" + android:layout_marginTop="4dp" + android:layout_marginBottom="4dp" + android:layout_marginEnd="8dp" + android:src="@drawable/ic_play"/> +</LinearLayout>
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/raw/amazing_grace.mp3 b/chrome/browser/android/examples/custom_tabs_client/src/res/raw/amazing_grace.mp3 new file mode 100644 index 0000000..08009a6 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/raw/amazing_grace.mp3 Binary files differ
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/values/strings.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/values/strings.xml new file mode 100644 index 0000000..f1fc619 --- /dev/null +++ b/chrome/browser/android/examples/custom_tabs_client/src/res/values/strings.xml
@@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright 2015 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + <string name="app_name">Chrome Custom Tabs Example</string> + <string name="url_hint">Please type the url here.</string> + <string name="warmup_button_text">Warmup Chrome</string> + <string name="may_launch_button_text">May Launch URL</string> + <string name="launch_button_text">Launch URL in a Chrome Custom Tab</string> + <string name="connect_button_text">Connect to the service</string> + <string name="launch_browser_actions_button_text">Launch URL in Browser Actions Context Menu</string> + <string name="register_twa_service">Register TrustedWebActivityService</string> + <string name="default_url">https://www.google.com</string> + <string name="package_label">Package:</string> + <string name="amazing_grace">Amazing Grace 2011</string> + <string name="artist">Kevin MacLeod</string> +</resources>
diff --git a/third_party/custom_tabs_client/testing_with_chromium.md b/chrome/browser/android/examples/custom_tabs_client/testing_with_chromium.md similarity index 100% rename from third_party/custom_tabs_client/testing_with_chromium.md rename to chrome/browser/android/examples/custom_tabs_client/testing_with_chromium.md
diff --git a/chrome/browser/android/metrics/BUILD.gn b/chrome/browser/android/metrics/BUILD.gn index d79c9ff..2a7b9c60 100644 --- a/chrome/browser/android/metrics/BUILD.gn +++ b/chrome/browser/android/metrics/BUILD.gn
@@ -38,6 +38,7 @@ ":ukm_java_test_support", "//base:base_java_test_support", "//chrome/android:chrome_java", + "//chrome/browser/tab:java", "//chrome/test/android:chrome_java_test_support", "//components/metrics:metrics_java", "//content/public/test/android:content_java_test_support",
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm index 0004eb0..c3c52feb 100644 --- a/chrome/browser/chrome_browser_application_mac.mm +++ b/chrome/browser/chrome_browser_application_mac.mm
@@ -21,6 +21,7 @@ #include "content/public/browser/native_event_processor_mac.h" #include "content/public/browser/native_event_processor_observer_mac.h" #include "ui/base/cocoa/accessibility_focus_overrider.h" +#include "ui/events/base_event_utils.h" namespace chrome_browser_application_mac { @@ -94,6 +95,16 @@ default: break; } + + // TODO(bokan): Added temporarily to debug https://crbug.com/1039833. + base::TimeTicks event_timestamp = + ui::EventTimeStampFromSeconds([event timestamp]); + base::TimeTicks now = ui::EventTimeForNow(); + base::TimeDelta diff = now - event_timestamp; + desc += base::StringPrintf(" Now: %lld Diff: %lld", + (now - base::TimeTicks()).InSeconds(), + diff.InSeconds()); + return desc; }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 9b73c809..6a13105 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -2189,6 +2189,8 @@ "printing/server_printers_fetcher.h", "printing/server_printers_provider.cc", "printing/server_printers_provider.h", + "printing/server_printers_provider_factory.cc", + "printing/server_printers_provider_factory.h", "printing/specifics_translation.cc", "printing/specifics_translation.h", "printing/synced_printers_manager.cc",
diff --git a/chrome/browser/chromeos/app_mode/app_session.cc b/chrome/browser/chromeos/app_mode/app_session.cc index 74521616..070abde 100644 --- a/chrome/browser/chromeos/app_mode/app_session.cc +++ b/chrome/browser/chromeos/app_mode/app_session.cc
@@ -7,6 +7,7 @@ #include <errno.h> #include <signal.h> +#include "ash/public/cpp/accessibility_controller.h" #include "base/bind.h" #include "base/lazy_instance.h" #include "base/location.h" @@ -66,6 +67,13 @@ power_manager::REQUEST_RESTART_OTHER, "kiosk app session"); } +void StartFloatingAccessibilityMenu() { + ash::AccessibilityController* accessibility_controller = + ash::AccessibilityController::Get(); + if (accessibility_controller) + accessibility_controller->ShowFloatingMenuIfEnabled(); +} + // Sends a SIGFPE signal to plugin subprocesses that matches |child_ids| // to trigger a dump. void DumpPluginProcessOnIOThread(const std::set<int>& child_ids) { @@ -207,6 +215,8 @@ plugin_handler_ = std::make_unique<KioskSessionPluginHandler>(this); + StartFloatingAccessibilityMenu(); + // For a demo app, we don't need to either setup the update service or // the idle app name notification. if (DemoAppLauncher::IsDemoAppSession( @@ -240,6 +250,8 @@ // the browser window was closed. browser_window_handler_ = std::make_unique<BrowserWindowHandler>(this, browser); + + StartFloatingAccessibilityMenu(); } void AppSession::SetAttemptUserExitForTesting(base::OnceClosure closure) {
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc index 9611ec1..33e17425d 100644 --- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc +++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
@@ -248,8 +248,8 @@ base::Bind(&AutoEnrollmentCheckScreen::OnConnectRequested, base::Unretained(this))); error_screen_->SetHideCallback( - base::BindRepeating(&AutoEnrollmentCheckScreen::OnErrorScreenHidden, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce(&AutoEnrollmentCheckScreen::OnErrorScreenHidden, + weak_ptr_factory_.GetWeakPtr())); error_screen_->SetParentScreen(AutoEnrollmentCheckScreenView::kScreenId); error_screen_->Show(); histogram_helper_->OnErrorShow(error_state);
diff --git a/chrome/browser/chromeos/login/oobe_screen.cc b/chrome/browser/chromeos/login/oobe_screen.cc index 662d6ad2..72fd795 100644 --- a/chrome/browser/chromeos/login/oobe_screen.cc +++ b/chrome/browser/chromeos/login/oobe_screen.cc
@@ -51,7 +51,6 @@ constexpr StaticOobeScreenId OobeScreen::SCREEN_FATAL_ERROR; constexpr StaticOobeScreenId OobeScreen::SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE; -constexpr StaticOobeScreenId OobeScreen::SCREEN_SPECIAL_LOGIN; constexpr StaticOobeScreenId OobeScreen::SCREEN_SPECIAL_OOBE; constexpr StaticOobeScreenId OobeScreen::SCREEN_TEST_NO_WINDOW; constexpr StaticOobeScreenId OobeScreen::SCREEN_UNKNOWN;
diff --git a/chrome/browser/chromeos/login/oobe_screen.h b/chrome/browser/chromeos/login/oobe_screen.h index 4aded92b..8cdb256 100644 --- a/chrome/browser/chromeos/login/oobe_screen.h +++ b/chrome/browser/chromeos/login/oobe_screen.h
@@ -66,8 +66,6 @@ constexpr static StaticOobeScreenId SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE{ "ad-password-change"}; - // Special "first screen" that initiates login flow. - constexpr static StaticOobeScreenId SCREEN_SPECIAL_LOGIN{"login"}; // Special "first screen" that initiates full OOBE flow. constexpr static StaticOobeScreenId SCREEN_SPECIAL_OOBE{"oobe"}; // Special test value that commands not to create any window yet.
diff --git a/chrome/browser/chromeos/login/screens/error_screen.cc b/chrome/browser/chromeos/login/screens/error_screen.cc index bbbcb42..8cf07a8 100644 --- a/chrome/browser/chromeos/login/screens/error_screen.cc +++ b/chrome/browser/chromeos/login/screens/error_screen.cc
@@ -151,8 +151,8 @@ // Not really used on JS side yet so no need to propagate to screen context. } -void ErrorScreen::SetHideCallback(const base::Closure& on_hide) { - on_hide_callback_.reset(new base::Closure(on_hide)); +void ErrorScreen::SetHideCallback(base::OnceClosure on_hide) { + on_hide_callback_ = std::move(on_hide); } void ErrorScreen::ShowCaptivePortal() { @@ -198,8 +198,8 @@ void ErrorScreen::DoHide() { LOG(WARNING) << "Network error screen message is hidden"; if (on_hide_callback_) { - on_hide_callback_->Run(); - on_hide_callback_.reset(); + std::move(on_hide_callback_).Run(); + on_hide_callback_ = base::OnceClosure(); } network_portal_detector::GetInstance()->SetStrategy( PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN); @@ -207,8 +207,8 @@ void ErrorScreen::ShowImpl() { if (!on_hide_callback_) { - SetHideCallback(base::Bind(&ErrorScreen::DefaultHideCallback, - weak_factory_.GetWeakPtr())); + SetHideCallback(base::BindOnce(&ErrorScreen::DefaultHideCallback, + weak_factory_.GetWeakPtr())); } if (view_) view_->Show();
diff --git a/chrome/browser/chromeos/login/screens/error_screen.h b/chrome/browser/chromeos/login/screens/error_screen.h index ba4168b0..c4ed92f5 100644 --- a/chrome/browser/chromeos/login/screens/error_screen.h +++ b/chrome/browser/chromeos/login/screens/error_screen.h
@@ -86,7 +86,7 @@ void SetParentScreen(OobeScreenId parent_screen); // Sets callback that is called on hide. - void SetHideCallback(const base::Closure& on_hide); + void SetHideCallback(base::OnceClosure on_hide); // Shows captive portal dialog. void ShowCaptivePortal(); @@ -171,7 +171,7 @@ OobeScreenId parent_screen_ = OobeScreen::SCREEN_UNKNOWN; // Optional callback that is called when NetworkError screen is hidden. - std::unique_ptr<base::Closure> on_hide_callback_; + base::OnceClosure on_hide_callback_; // Callbacks to be invoked when a connection attempt is requested. base::CallbackList<void()> connect_request_callbacks_;
diff --git a/chrome/browser/chromeos/login/screens/update_required_screen.cc b/chrome/browser/chromeos/login/screens/update_required_screen.cc index 73542812..d4447aa 100644 --- a/chrome/browser/chromeos/login/screens/update_required_screen.cc +++ b/chrome/browser/chromeos/login/screens/update_required_screen.cc
@@ -248,7 +248,7 @@ weak_factory_.GetWeakPtr())); error_screen_->SetUIState(NetworkError::UI_STATE_UPDATE); error_screen_->SetParentScreen(UpdateRequiredView::kScreenId); - error_screen_->SetHideCallback(base::BindRepeating( + error_screen_->SetHideCallback(base::BindOnce( &UpdateRequiredScreen::OnErrorScreenHidden, weak_factory_.GetWeakPtr())); error_screen_->SetIsPersistentError(true /* is_persistent */); error_screen_->Show();
diff --git a/chrome/browser/chromeos/login/screens/update_screen.cc b/chrome/browser/chromeos/login/screens/update_screen.cc index 615417e1..a7e02cb 100644 --- a/chrome/browser/chromeos/login/screens/update_screen.cc +++ b/chrome/browser/chromeos/login/screens/update_screen.cc
@@ -169,7 +169,7 @@ &UpdateScreen::OnConnectRequested, weak_factory_.GetWeakPtr())); error_screen_->SetUIState(NetworkError::UI_STATE_UPDATE); error_screen_->SetParentScreen(UpdateView::kScreenId); - error_screen_->SetHideCallback(base::BindRepeating( + error_screen_->SetHideCallback(base::BindOnce( &UpdateScreen::OnErrorScreenHidden, weak_factory_.GetWeakPtr())); error_screen_->Show(); histogram_helper_->OnErrorShow(error_screen_->GetErrorState());
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc index 8d09bce2..415f9f5 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -176,8 +176,7 @@ // Returns true if signin (not oobe) should be displayed. bool ShouldShowSigninScreen(chromeos::OobeScreenId first_screen) { return (first_screen == chromeos::OobeScreen::SCREEN_UNKNOWN && - IsOobeComplete()) || - first_screen == chromeos::OobeScreen::SCREEN_SPECIAL_LOGIN; + IsOobeComplete()); } void MaybeShowDeviceDisabledScreen() { @@ -1081,7 +1080,7 @@ switches::kNaturalScrollDefault)); auto session_state = session_manager::SessionState::OOBE; - if (IsOobeComplete() || first_screen == OobeScreen::SCREEN_SPECIAL_LOGIN) + if (IsOobeComplete()) session_state = session_manager::SessionState::LOGIN_PRIMARY; session_manager::SessionManager::Get()->SetSessionState(session_state);
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index c9fb4e9..8f7a952e 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -114,6 +114,7 @@ #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h" +#include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h" @@ -623,7 +624,7 @@ UMA_HISTOGRAM_MEDIUM_TIMES("OOBE.EULAToSignInTime", delta); } VLOG(1) << "Showing login screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_SPECIAL_LOGIN); + UpdateStatusAreaVisibilityForScreen(GaiaView::kScreenId); GetLoginDisplayHost()->StartSignInScreen(); login_screen_started_ = true; } @@ -1539,8 +1540,6 @@ ShowWelcomeScreen(); } else if (screen_id == NetworkScreenView::kScreenId) { ShowNetworkScreen(); - } else if (screen_id == OobeScreen::SCREEN_SPECIAL_LOGIN) { - ShowLoginScreen(); } else if (screen_id == PackagedLicenseView::kScreenId) { ShowPackagedLicenseScreen(); } else if (screen_id == UpdateView::kScreenId) {
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc index a36b034..7c4e99c 100644 --- a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc +++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
@@ -893,13 +893,21 @@ } } - const auto& timezone_info = probe_result->timezone_info; - if (!timezone_info.is_null()) { - em::TimezoneInfo* const timezone_info_out = - response_params_.device_status->mutable_timezone_info(); - timezone_info_out->set_posix(timezone_info->posix); - timezone_info_out->set_region(timezone_info->region); + // Process TimezoneResult. + const auto& timezone_result = probe_result->timezone_result; + if (!timezone_result.is_null()) { + if (timezone_result->is_error()) { + LOG(ERROR) << "cros_healthd: Error getting timezone info: " + << timezone_result->get_error()->msg; + } else { + const auto& timezone_info = timezone_result->get_timezone_info(); + em::TimezoneInfo* const timezone_info_out = + response_params_.device_status->mutable_timezone_info(); + timezone_info_out->set_posix(timezone_info->posix); + timezone_info_out->set_region(timezone_info->region); + } } + const auto& memory_info = probe_result->memory_info; if (!memory_info.is_null()) { em::MemoryInfo* const memory_info_out = @@ -921,12 +929,20 @@ backlight_info_out->set_brightness(backlight->brightness); } } - const auto& fan_info = probe_result->fan_info; - if (fan_info.has_value()) { - for (const auto& fan : fan_info.value()) { - em::FanInfo* const fan_info_out = - response_params_.device_status->add_fan_info(); - fan_info_out->set_speed_rpm(fan->speed_rpm); + + // Process FanResult. + const auto& fan_result = probe_result->fan_result; + if (!fan_result.is_null()) { + if (fan_result->is_error()) { + LOG(ERROR) << "cros_healthd: Error getting fan info: " + << fan_result->get_error()->msg; + } else { + const auto& fan_info = fan_result->get_fan_info(); + for (const auto& fan : fan_info) { + em::FanInfo* const fan_info_out = + response_params_.device_status->add_fan_info(); + fan_info_out->set_speed_rpm(fan->speed_rpm); + } } }
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc index 3a96dee..6cdc44e 100644 --- a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc +++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
@@ -480,8 +480,10 @@ base::Optional<std::vector< chromeos::cros_healthd::mojom::NonRemovableBlockDeviceInfoPtr>> block_device_info(std::move(storage_vector)); - chromeos::cros_healthd::mojom::TimezoneInfo timezone_info(kPosixTimezone, - kTimezoneRegion); + auto timezone_result = + chromeos::cros_healthd::mojom::TimezoneResult::NewTimezoneInfo( + chromeos::cros_healthd::mojom::TimezoneInfo::New(kPosixTimezone, + kTimezoneRegion)); chromeos::cros_healthd::mojom::MemoryInfo memory_info( kFakeTotalMemory, kFakeFreeMemory, kFakeAvailableMemory, kFakePageFaults); std::vector<chromeos::cros_healthd::mojom::BacklightInfoPtr> backlight_vector; @@ -491,10 +493,13 @@ std::vector<chromeos::cros_healthd::mojom::FanInfoPtr> fan_vector; chromeos::cros_healthd::mojom::FanInfo fan_info(kFakeSpeedRpm); fan_vector.push_back(fan_info.Clone()); + auto fan_result = chromeos::cros_healthd::mojom::FanResult::NewFanInfo( + std::move(fan_vector)); chromeos::cros_healthd::mojom::TelemetryInfo fake_info( battery_info.Clone(), std::move(block_device_info), - cached_vpd_info.Clone(), std::move(cpu_result), timezone_info.Clone(), - memory_info.Clone(), std::move(backlight_vector), std::move(fan_vector)); + cached_vpd_info.Clone(), std::move(cpu_result), + std::move(timezone_result), memory_info.Clone(), + std::move(backlight_vector), std::move(fan_result)); // Create fake SampledData. em::CPUTempInfo fake_cpu_temp_sample;
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager.cc b/chrome/browser/chromeos/printing/cups_printers_manager.cc index 6dd013b1..6ba3c52 100644 --- a/chrome/browser/chromeos/printing/cups_printers_manager.cc +++ b/chrome/browser/chromeos/printing/cups_printers_manager.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/chromeos/printing/printer_event_tracker_factory.h" #include "chrome/browser/chromeos/printing/printers_map.h" #include "chrome/browser/chromeos/printing/server_printers_provider.h" +#include "chrome/browser/chromeos/printing/server_printers_provider_factory.h" #include "chrome/browser/chromeos/printing/synced_printers_manager.h" #include "chrome/browser/chromeos/printing/synced_printers_manager_factory.h" #include "chrome/browser/chromeos/printing/usb_printer_detector.h" @@ -62,7 +63,7 @@ std::unique_ptr<PrinterConfigurer> printer_configurer, std::unique_ptr<UsbPrinterNotificationController> usb_notification_controller, - std::unique_ptr<ServerPrintersProvider> server_printers_provider, + ServerPrintersProvider* server_printers_provider, std::unique_ptr<EnterprisePrintersProvider> enterprise_printers_provider, PrinterEventTracker* event_tracker, PrefService* pref_service) @@ -75,7 +76,7 @@ auto_usb_printer_configurer_(std::move(printer_configurer), this, usb_notification_controller_.get()), - server_printers_provider_(std::move(server_printers_provider)), + server_printers_provider_(server_printers_provider), enterprise_printers_provider_(std::move(enterprise_printers_provider)), enterprise_printers_provider_observer_(this), event_tracker_(event_tracker) { @@ -529,7 +530,8 @@ AutomaticUsbPrinterConfigurer auto_usb_printer_configurer_; - std::unique_ptr<ServerPrintersProvider> server_printers_provider_; + // Not owned. + ServerPrintersProvider* server_printers_provider_; std::unique_ptr<EnterprisePrintersProvider> enterprise_printers_provider_; ScopedObserver<EnterprisePrintersProvider, @@ -577,7 +579,8 @@ UsbPrinterDetector::Create(), ZeroconfPrinterDetector::Create(), CreatePpdProvider(profile), PrinterConfigurer::Create(profile), UsbPrinterNotificationController::Create(profile), - ServerPrintersProvider::Create(profile), + ServerPrintersProviderFactory::GetInstance()->GetForBrowserContext( + profile), EnterprisePrintersProvider::Create(CrosSettings::Get(), profile), PrinterEventTrackerFactory::GetInstance()->GetForBrowserContext(profile), profile->GetPrefs()); @@ -592,7 +595,7 @@ std::unique_ptr<PrinterConfigurer> printer_configurer, std::unique_ptr<UsbPrinterNotificationController> usb_notification_controller, - std::unique_ptr<ServerPrintersProvider> server_printers_provider, + ServerPrintersProvider* server_printers_provider, std::unique_ptr<EnterprisePrintersProvider> enterprise_printers_provider, PrinterEventTracker* event_tracker, PrefService* pref_service) { @@ -600,8 +603,8 @@ synced_printers_manager, std::move(usb_detector), std::move(zeroconf_detector), std::move(ppd_provider), std::move(printer_configurer), std::move(usb_notification_controller), - std::move(server_printers_provider), - std::move(enterprise_printers_provider), event_tracker, pref_service); + server_printers_provider, std::move(enterprise_printers_provider), + event_tracker, pref_service); } // static
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager.h b/chrome/browser/chromeos/printing/cups_printers_manager.h index a13890a..1419474 100644 --- a/chrome/browser/chromeos/printing/cups_printers_manager.h +++ b/chrome/browser/chromeos/printing/cups_printers_manager.h
@@ -65,7 +65,7 @@ std::unique_ptr<PrinterConfigurer> printer_configurer, std::unique_ptr<UsbPrinterNotificationController> usb_notification_controller, - std::unique_ptr<ServerPrintersProvider> server_printers_provider, + ServerPrintersProvider* server_printers_provider, std::unique_ptr<EnterprisePrintersProvider> enterprise_printers_provider, PrinterEventTracker* event_tracker, PrefService* pref_service);
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager_factory.cc b/chrome/browser/chromeos/printing/cups_printers_manager_factory.cc index 630514a..9aefd1a 100644 --- a/chrome/browser/chromeos/printing/cups_printers_manager_factory.cc +++ b/chrome/browser/chromeos/printing/cups_printers_manager_factory.cc
@@ -7,6 +7,7 @@ #include "base/memory/singleton.h" #include "chrome/browser/chromeos/printing/cups_printers_manager.h" #include "chrome/browser/chromeos/printing/cups_printers_manager_proxy.h" +#include "chrome/browser/chromeos/printing/server_printers_provider_factory.h" #include "chrome/browser/chromeos/printing/synced_printers_manager_factory.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/incognito_helpers.h" @@ -32,6 +33,7 @@ "CupsPrintersManagerFactory", BrowserContextDependencyManager::GetInstance()), proxy_(CupsPrintersManagerProxy::Create()) { + DependsOn(chromeos::ServerPrintersProviderFactory::GetInstance()); DependsOn(chromeos::SyncedPrintersManagerFactory::GetInstance()); }
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc b/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc index 8996c8a..e9232b5d8 100644 --- a/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc +++ b/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc
@@ -357,9 +357,6 @@ auto usb_notif_controller = std::make_unique<FakeUsbPrinterNotificationController>(); usb_notif_controller_ = usb_notif_controller.get(); - auto server_printers_provider = - std::make_unique<FakeServerPrintersProvider>(); - server_printers_provider_ = server_printers_provider.get(); auto enterprise_printers_provider = std::make_unique<FakeEnterprisePrintersProvider>(); enterprise_printers_provider_ = enterprise_printers_provider.get(); @@ -371,9 +368,8 @@ &synced_printers_manager_, std::move(usb_detector), std::move(zeroconf_detector), ppd_provider_, std::move(printer_configurer), std::move(usb_notif_controller), - std::move(server_printers_provider), - std::move(enterprise_printers_provider), &event_tracker_, - &pref_service_); + &server_printers_provider_, std::move(enterprise_printers_provider), + &event_tracker_, &pref_service_); manager_->AddObserver(this); } @@ -414,7 +410,7 @@ FakePrinterDetector* zeroconf_detector_; // Not owned. TestPrinterConfigurer* printer_configurer_; // Not owned. FakeUsbPrinterNotificationController* usb_notif_controller_; // Not owned. - FakeServerPrintersProvider* server_printers_provider_; // Not owned. + FakeServerPrintersProvider server_printers_provider_; scoped_refptr<FakePpdProvider> ppd_provider_; // This is unused, it's just here for memory ownership.
diff --git a/chrome/browser/chromeos/printing/server_printers_provider.h b/chrome/browser/chromeos/printing/server_printers_provider.h index 98c2333..773214e 100644 --- a/chrome/browser/chromeos/printing/server_printers_provider.h +++ b/chrome/browser/chromeos/printing/server_printers_provider.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "chrome/browser/chromeos/printing/printer_detector.h" +#include "components/keyed_service/core/keyed_service.h" class Profile; @@ -21,11 +22,11 @@ // printers are signaled through a callback registered with the method // RegisterPrintersFoundCallback(...). All methods must be called from the UI // sequence, the callback is also called from this sequence. -class ServerPrintersProvider { +class ServerPrintersProvider : public KeyedService { public: // |profile| is a user profile, it cannot be nullptr. static std::unique_ptr<ServerPrintersProvider> Create(Profile* profile); - virtual ~ServerPrintersProvider() = default; + ~ServerPrintersProvider() override = default; using OnPrintersUpdateCallback = base::RepeatingCallback<void(bool complete)>;
diff --git a/chrome/browser/chromeos/printing/server_printers_provider_factory.cc b/chrome/browser/chromeos/printing/server_printers_provider_factory.cc new file mode 100644 index 0000000..c2a182b --- /dev/null +++ b/chrome/browser/chromeos/printing/server_printers_provider_factory.cc
@@ -0,0 +1,50 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/printing/server_printers_provider_factory.h" + +#include "base/no_destructor.h" +#include "chrome/browser/chromeos/printing/server_printers_provider.h" +#include "chrome/browser/profiles/incognito_helpers.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" + +namespace chromeos { + +// static +ServerPrintersProviderFactory* ServerPrintersProviderFactory::GetInstance() { + static base::NoDestructor<ServerPrintersProviderFactory> instance; + return instance.get(); +} + +// static +ServerPrintersProvider* ServerPrintersProviderFactory::GetForBrowserContext( + content::BrowserContext* context) { + return static_cast<ServerPrintersProvider*>( + GetInstance()->GetServiceForBrowserContext(context, true)); +} + +ServerPrintersProviderFactory::ServerPrintersProviderFactory() + : BrowserContextKeyedServiceFactory( + "ServerPrintersProviderFactory", + BrowserContextDependencyManager::GetInstance()) {} + +ServerPrintersProviderFactory::~ServerPrintersProviderFactory() = default; + +KeyedService* ServerPrintersProviderFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + auto* profile = Profile::FromBrowserContext(context); + return ServerPrintersProvider::Create(profile).release(); +} + +content::BrowserContext* ServerPrintersProviderFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return chrome::GetBrowserContextRedirectedInIncognito(context); +} + +bool ServerPrintersProviderFactory::ServiceIsNULLWhileTesting() const { + return true; +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/server_printers_provider_factory.h b/chrome/browser/chromeos/printing/server_printers_provider_factory.h new file mode 100644 index 0000000..0a48e42 --- /dev/null +++ b/chrome/browser/chromeos/printing/server_printers_provider_factory.h
@@ -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. + +#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_SERVER_PRINTERS_PROVIDER_FACTORY_H_ +#define CHROME_BROWSER_CHROMEOS_PRINTING_SERVER_PRINTERS_PROVIDER_FACTORY_H_ + +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} + +namespace base { +template <typename T> +class NoDestructor; +} + +namespace chromeos { + +class ServerPrintersProvider; + +class ServerPrintersProviderFactory : public BrowserContextKeyedServiceFactory { + public: + static ServerPrintersProviderFactory* GetInstance(); + static ServerPrintersProvider* GetForBrowserContext( + content::BrowserContext* context); + + private: + friend class base::NoDestructor<ServerPrintersProviderFactory>; + + ServerPrintersProviderFactory(); + ~ServerPrintersProviderFactory() override; + + // BrowserContextKeyedServiceFactory overrides: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + bool ServiceIsNULLWhileTesting() const override; + + DISALLOW_COPY_AND_ASSIGN(ServerPrintersProviderFactory); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PRINTING_SERVER_PRINTERS_PROVIDER_FACTORY_H_
diff --git a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc index 0f43e71..b67d56b 100644 --- a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc +++ b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
@@ -33,7 +33,9 @@ : delegate_(delegate), profile_(profile), account_id_(token_key.account_id), - resolution_data_(resolution_data) {} + resolution_data_(resolution_data), + web_flow_started_(false), + scoped_observer_(this) {} GaiaRemoteConsentFlow::~GaiaRemoteConsentFlow() { if (web_flow_) @@ -46,40 +48,16 @@ this, profile_, resolution_data_.url, WebAuthFlow::INTERACTIVE); } - auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_); - std::vector<CoreAccountId> accounts; - if (IdentityAPI::GetFactoryInstance() - ->Get(profile_) - ->AreExtensionsRestrictedToPrimaryAccount()) { - CoreAccountId primary_account_id = identity_manager->GetPrimaryAccountId(); - accounts.push_back(primary_account_id); - } else { - auto chrome_accounts_with_refresh_tokens = - identity_manager->GetAccountsWithRefreshTokens(); - for (const auto& chrome_account : chrome_accounts_with_refresh_tokens) { - // An account in persistent error state would make multilogin fail. - // Showing only a subset of accounts seems to be a better alternative than - // failing with an error. - if (identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( - chrome_account.account_id)) { - continue; - } - accounts.push_back(chrome_account.account_id); - } - } - - set_accounts_in_cookie_task_ = - identity_manager->GetAccountsCookieMutator() - ->SetAccountsInCookieForPartition( - this, - {gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, - accounts}, - base::BindOnce(&GaiaRemoteConsentFlow::OnSetAccountsComplete, - base::Unretained(this))); + SetAccountsInCookie(); } void GaiaRemoteConsentFlow::OnSetAccountsComplete( signin::SetAccountsInCookieResult result) { + set_accounts_in_cookie_task_.reset(); + if (web_flow_started_) { + return; + } + if (result != signin::SetAccountsInCookieResult::kSuccess) { delegate_->OnGaiaRemoteConsentFlowFailed( GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED); @@ -102,8 +80,9 @@ base::Bind(&GaiaRemoteConsentFlow::OnConsentResultSet, base::Unretained(this))); - set_accounts_in_cookie_task_.reset(); + scoped_observer_.Add(IdentityManagerFactory::GetForProfile(profile_)); web_flow_->Start(); + web_flow_started_ = true; } void GaiaRemoteConsentFlow::OnConsentResultSet( @@ -163,6 +142,10 @@ return web_flow_->GetGuestPartition()->GetCookieManagerForBrowserProcess(); } +void GaiaRemoteConsentFlow::OnEndBatchOfRefreshTokenStateChanges() { + SetAccountsInCookie(); +} + void GaiaRemoteConsentFlow::SetWebAuthFlowForTesting( std::unique_ptr<WebAuthFlow> web_auth_flow) { if (web_flow_) @@ -170,4 +153,44 @@ web_flow_ = std::move(web_auth_flow); } +void GaiaRemoteConsentFlow::SetAccountsInCookie() { + // Reset a task that is already in flight because it contains stale + // information. + if (set_accounts_in_cookie_task_) + set_accounts_in_cookie_task_.reset(); + + auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_); + std::vector<CoreAccountId> accounts; + if (IdentityAPI::GetFactoryInstance() + ->Get(profile_) + ->AreExtensionsRestrictedToPrimaryAccount()) { + CoreAccountId primary_account_id = identity_manager->GetPrimaryAccountId(); + accounts.push_back(primary_account_id); + } else { + auto chrome_accounts_with_refresh_tokens = + identity_manager->GetAccountsWithRefreshTokens(); + for (const auto& chrome_account : chrome_accounts_with_refresh_tokens) { + // An account in persistent error state would make multilogin fail. + // Showing only a subset of accounts seems to be a better alternative than + // failing with an error. + if (identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + chrome_account.account_id)) { + continue; + } + accounts.push_back(chrome_account.account_id); + } + } + + // base::Unretained() is safe here because this class owns + // |set_accounts_in_cookie_task_| that will eventually invoke this callback. + set_accounts_in_cookie_task_ = + identity_manager->GetAccountsCookieMutator() + ->SetAccountsInCookieForPartition( + this, + {gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, + accounts}, + base::BindOnce(&GaiaRemoteConsentFlow::OnSetAccountsComplete, + base::Unretained(this))); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h index 9c5d486..433777b 100644 --- a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h +++ b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h
@@ -8,9 +8,12 @@ #include "base/callback_list.h" #include "base/macros.h" +#include "base/scoped_observer.h" #include "chrome/browser/extensions/api/identity/extension_token_key.h" #include "chrome/browser/extensions/api/identity/web_auth_flow.h" #include "components/signin/public/identity_manager/accounts_cookie_mutator.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h" #include "google_apis/gaia/core_account_id.h" #include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/oauth2_mint_token_flow.h" @@ -19,7 +22,8 @@ class GaiaRemoteConsentFlow : public WebAuthFlow::Delegate, - public signin::AccountsCookieMutator::PartitionDelegate { + public signin::AccountsCookieMutator::PartitionDelegate, + public signin::IdentityManager::Observer { public: enum Failure { WINDOW_CLOSED, @@ -60,27 +64,37 @@ void OnConsentResultSet(const std::string& consent_result, const std::string& window_id); - // WebAuthFlow::Delegate implementation. + // WebAuthFlow::Delegate: void OnAuthFlowFailure(WebAuthFlow::Failure failure) override; - // AccountsCookieMutator::PartitionDelegate: + // signin::AccountsCookieMutator::PartitionDelegate: std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcherForPartition( GaiaAuthConsumer* consumer) override; network::mojom::CookieManager* GetCookieManagerForPartition() override; + // signin::IdentityManager::Observer: + void OnEndBatchOfRefreshTokenStateChanges() override; + void SetWebAuthFlowForTesting(std::unique_ptr<WebAuthFlow> web_auth_flow); private: + void SetAccountsInCookie(); + Delegate* delegate_; Profile* profile_; CoreAccountId account_id_; RemoteConsentResolutionData resolution_data_; + std::unique_ptr<WebAuthFlow> web_flow_; + bool web_flow_started_; + std::unique_ptr<signin::AccountsCookieMutator::SetAccountsInCookieTask> set_accounts_in_cookie_task_; std::unique_ptr<base::CallbackList<void(const std::string&, const std::string&)>::Subscription> identity_api_set_consent_result_subscription_; + ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer> + scoped_observer_; }; } // namespace extensions
diff --git a/chrome/browser/extensions/events_apitest.cc b/chrome/browser/extensions/events_apitest.cc index ac199da..803088a 100644 --- a/chrome/browser/extensions/events_apitest.cc +++ b/chrome/browser/extensions/events_apitest.cc
@@ -208,10 +208,16 @@ } } -// Disabled due to flaky timeouts. https://crbug.com/833854 +// This test is OK on Windows, but times out on other platforms. +// https://crbug.com/833854 +#if defined(OS_WIN) +#define MAYBE_NewlyIntroducedListener NewlyIntroducedListener +#else +#define MAYBE_NewlyIntroducedListener DISABLED_NewlyIntroducedListener +#endif // Tests that if an extension's updated version has a new lazy listener, it // fires properly after the update. -IN_PROC_BROWSER_TEST_F(EventsApiTest, DISABLED_NewlyIntroducedListener) { +IN_PROC_BROWSER_TEST_F(EventsApiTest, MAYBE_NewlyIntroducedListener) { std::vector<ExtensionCRXData> data; data.emplace_back("v1"); data.emplace_back("v2");
diff --git a/chrome/browser/extensions/standard_management_policy_provider.cc b/chrome/browser/extensions/standard_management_policy_provider.cc index 785ee71..9b5bb60b 100644 --- a/chrome/browser/extensions/standard_management_policy_provider.cc +++ b/chrome/browser/extensions/standard_management_policy_provider.cc
@@ -23,7 +23,11 @@ #endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) #if defined(OS_CHROMEOS) +#include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/extensions/default_web_app_ids.h" +#include "chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h" +#include "components/policy/core/common/policy_pref_names.h" +#include "components/prefs/pref_service.h" #endif // defined(OS_CHROMEOS) namespace extensions { @@ -63,6 +67,21 @@ return false; } +#if defined(OS_CHROMEOS) +bool IsOsSettingsDisabledBySystemFeaturesPolicy() { + PrefService* const local_state = g_browser_process->local_state(); + if (!local_state) + return false; + + const base::ListValue* system_features_pref = + local_state->GetList(policy::policy_prefs::kSystemFeaturesDisableList); + + return system_features_pref && system_features_pref->Find(base::Value( + policy::SystemFeature::OS_SETTINGS)) != + system_features_pref->end(); +} +#endif + } // namespace StandardManagementPolicyProvider::StandardManagementPolicyProvider( @@ -93,7 +112,8 @@ #if defined(OS_CHROMEOS) if (extension->id() == chromeos::default_web_apps::kOsSettingsAppId && (installation_mode == ExtensionManagement::INSTALLATION_BLOCKED || - installation_mode == ExtensionManagement::INSTALLATION_REMOVED)) { + installation_mode == ExtensionManagement::INSTALLATION_REMOVED) && + IsOsSettingsDisabledBySystemFeaturesPolicy()) { return ReturnLoadError(extension, error); } #endif // defined(OS_CHROMEOS)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index ede26a7..ffd4e5d 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1370,7 +1370,12 @@ { "name": "enable-edu-coexistence", "owners": [ "anastasiian@chromium.org", "sinhak@chromium.org" ], - "expiry_milestone": 83 + "expiry_milestone": 85 + }, + { + "name": "enable-edu-coexistence-consent-log", + "owners": [ "anastasiian@chromium.org", "sinhak@chromium.org" ], + "expiry_milestone": 85 }, { "name": "enable-encryption-migration",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index d0a5b83..39d98f0 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -505,6 +505,12 @@ const char kEnableEduCoexistenceDescription[] = "Allows Family Link managed users to add secondary EDU accounts."; +const char kEnableEduCoexistenceConsentLogName[] = + "Enable parent consent logging in EDU account addition flow"; +const char kEnableEduCoexistenceConsentLogDescription[] = + "If enabled, parent consent gets logged to ARI before adding the account " + "to the device."; + const char kEnableSaveDataName[] = "Enables save data feature"; const char kEnableSaveDataDescription[] = "Enables save data feature. May cause user's traffic to be proxied via "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index b7f1c2b3..a833253 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -308,6 +308,9 @@ extern const char kEnableEduCoexistenceName[]; extern const char kEnableEduCoexistenceDescription[]; +extern const char kEnableEduCoexistenceConsentLogName[]; +extern const char kEnableEduCoexistenceConsentLogDescription[]; + extern const char kEnableSaveDataName[]; extern const char kEnableSaveDataDescription[];
diff --git a/chrome/browser/media/feeds/media_feeds_converter.cc b/chrome/browser/media/feeds/media_feeds_converter.cc index b5d6429..ec100186 100644 --- a/chrome/browser/media/feeds/media_feeds_converter.cc +++ b/chrome/browser/media/feeds/media_feeds_converter.cc
@@ -677,11 +677,6 @@ } } - if (!convert_property.Run(schema_org::property::kPublication, false, - base::BindOnce(&GetLiveDetails))) { - continue; - } - if (!convert_property.Run( schema_org::property::kIdentifier, false, base::BindOnce(&GetIdentifiers<mojom::MediaFeedItem>))) { @@ -698,17 +693,16 @@ base::BindOnce(&GetDuration))) { continue; } - } - - if (converted_item->type == mojom::MediaFeedItemType::kTVSeries) { - auto* num_episodes = - GetProperty(item.get(), schema_org::property::kNumberOfEpisodes); - if (!num_episodes || !IsPositiveInteger(*num_episodes)) + if (!convert_property.Run(schema_org::property::kPublication, false, + base::BindOnce(&GetLiveDetails))) { continue; - auto* num_seasons = - GetProperty(item.get(), schema_org::property::kNumberOfSeasons); - if (!num_seasons || !IsPositiveInteger(*num_seasons)) + } + } else if (converted_item->type == mojom::MediaFeedItemType::kMovie) { + if (!convert_property.Run(schema_org::property::kPublication, false, + base::BindOnce(&GetLiveDetails))) { continue; + } + } else if (converted_item->type == mojom::MediaFeedItemType::kTVSeries) { if (!convert_property.Run(schema_org::property::kEpisode, false, base::BindOnce(&GetEpisode))) { continue;
diff --git a/chrome/browser/media/feeds/media_feeds_store.mojom b/chrome/browser/media/feeds/media_feeds_store.mojom index 43ed787..80a6d7c 100644 --- a/chrome/browser/media/feeds/media_feeds_store.mojom +++ b/chrome/browser/media/feeds/media_feeds_store.mojom
@@ -224,7 +224,7 @@ mojo_base.mojom.String16 name; // The author that created the content. - Author author; + Author? author; // The date/time this feed item was published. mojo_base.mojom.Time date_published;
diff --git a/chrome/browser/policy/extension_policy_browsertest.cc b/chrome/browser/policy/extension_policy_browsertest.cc index 23193649..61d20e9 100644 --- a/chrome/browser/policy/extension_policy_browsertest.cc +++ b/chrome/browser/policy/extension_policy_browsertest.cc
@@ -347,7 +347,7 @@ } IN_PROC_BROWSER_TEST_F(ExtensionPolicyTest, - ExtensionInstallBlacklistOsSettings) { + SystemFeaturesDisableListOsSettings) { extensions::ExtensionPrefs* extension_prefs = extensions::ExtensionPrefs::Get(browser()->profile()); @@ -357,6 +357,33 @@ ASSERT_TRUE(registry->enabled_extensions().GetByID( chromeos::default_web_apps::kOsSettingsAppId)); + base::ListValue feature_list; + feature_list.AppendString("os_settings"); + PolicyMap policies; + policies.Set(key::kSystemFeaturesDisableList, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, + feature_list.CreateDeepCopy(), nullptr); + UpdateProviderPolicy(policies); + + EXPECT_EQ(1u, registry->disabled_extensions().size()); + extensions::ExtensionService* service = extension_service(); + EXPECT_FALSE(service->IsExtensionEnabled( + chromeos::default_web_apps::kOsSettingsAppId)); + EXPECT_EQ(extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY, + extension_prefs->GetDisableReasons( + chromeos::default_web_apps::kOsSettingsAppId)); +} + +// Ensure that OS Settings is only blocked by the SystemFeaturesDisableList +// policy. +IN_PROC_BROWSER_TEST_F(ExtensionPolicyTest, + ExtensionInstallBlacklistOsSettings) { + extensions::ExtensionRegistry* registry = extension_registry(); + const extensions::Extension* bookmark_app = InstallOSSettings(); + ASSERT_TRUE(bookmark_app); + ASSERT_TRUE(registry->enabled_extensions().GetByID( + chromeos::default_web_apps::kOsSettingsAppId)); + base::ListValue blacklist; blacklist.AppendString(chromeos::default_web_apps::kOsSettingsAppId); PolicyMap policies; @@ -365,31 +392,6 @@ blacklist.CreateDeepCopy(), nullptr); UpdateProviderPolicy(policies); - EXPECT_EQ(1u, registry->disabled_extensions().size()); - extensions::ExtensionService* service = extension_service(); - EXPECT_FALSE(service->IsExtensionEnabled( - chromeos::default_web_apps::kOsSettingsAppId)); - EXPECT_EQ(extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY, - extension_prefs->GetDisableReasons( - chromeos::default_web_apps::kOsSettingsAppId)); -} - -// Ensure that OS Settings is not blocked by the ExtensionAllowedTypes policy. -IN_PROC_BROWSER_TEST_F(ExtensionPolicyTest, ExtensionAllowedTypesOsSettings) { - extensions::ExtensionRegistry* registry = extension_registry(); - const extensions::Extension* bookmark_app = InstallOSSettings(); - ASSERT_TRUE(bookmark_app); - ASSERT_TRUE(registry->enabled_extensions().GetByID( - chromeos::default_web_apps::kOsSettingsAppId)); - - base::ListValue allowed_types; - allowed_types.AppendString("theme"); - PolicyMap policies; - policies.Set(key::kExtensionAllowedTypes, POLICY_LEVEL_MANDATORY, - POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, - allowed_types.CreateDeepCopy(), nullptr); - UpdateProviderPolicy(policies); - extensions::ExtensionService* service = extension_service(); EXPECT_TRUE(service->IsExtensionEnabled( chromeos::default_web_apps::kOsSettingsAppId));
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index e88ed4ef..264895d9 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -350,6 +350,17 @@ } #endif +// Helper function that deletes entries from the kProfilesLastActive pref list. +// It is called when every ephemeral profile is handled. +void RemoveFromLastActiveProfilesPrefList(base::FilePath path) { + PrefService* local_state = g_browser_process->local_state(); + DCHECK(local_state); + ListPrefUpdate update(local_state, prefs::kProfilesLastActive); + base::ListValue* profile_list = update.Get(); + base::Value entry_value = base::Value(path.BaseName().MaybeAsASCII()); + profile_list->EraseListValue(entry_value); +} + #if defined(OS_CHROMEOS) bool IsLoggedIn() { return user_manager::UserManager::IsInitialized() && @@ -896,6 +907,7 @@ base::FilePath profile_path = entry->GetPath(); if (entry->IsEphemeral()) { profiles_to_delete.push_back(profile_path); + RemoveFromLastActiveProfilesPrefList(profile_path); if (profile_path.BaseName().MaybeAsASCII() == last_used_profile) last_active_profile_deleted = true; } else if (new_profile_path.empty()) { @@ -1923,6 +1935,8 @@ } } + RemoveFromLastActiveProfilesPrefList(profile_dir); + const base::FilePath new_active_profile_dir = found_entry ? found_entry->GetPath() : GenerateNextProfileDirectoryPath(); FinishDeletingProfile(profile_dir, new_active_profile_dir);
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc index 7314e0d5..65812a2 100644 --- a/chrome/browser/profiles/profile_manager_unittest.cc +++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -1214,15 +1214,29 @@ PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kProfileLastUsed, profile_name1); + // Set the last used profiles. + ListPrefUpdate update(local_state, prefs::kProfilesLastActive); + base::ListValue* initial_last_active_profile_list = update.Get(); + initial_last_active_profile_list->Append( + std::make_unique<base::Value>(path1.BaseName().MaybeAsASCII())); + initial_last_active_profile_list->Append( + std::make_unique<base::Value>(path2.BaseName().MaybeAsASCII())); + profile_manager->CleanUpEphemeralProfiles(); content::RunAllTasksUntilIdle(); + const base::ListValue* final_last_active_profile_list = + local_state->GetList(prefs::kProfilesLastActive); // The ephemeral profile should be deleted, and the last used profile set to - // the other one. + // the other one. Also, the ephemeral profile should be removed from the + // kProfilesLastActive list. EXPECT_FALSE(base::DirectoryExists(path1)); EXPECT_TRUE(base::DirectoryExists(path2)); EXPECT_EQ(profile_name2, local_state->GetString(prefs::kProfileLastUsed)); ASSERT_EQ(1u, storage.GetNumberOfProfiles()); + ASSERT_EQ(1u, final_last_active_profile_list->GetSize()); + ASSERT_EQ(path2.BaseName().MaybeAsASCII(), + (final_last_active_profile_list->GetList())[0].GetString()); // Mark the remaining profile ephemeral and clean up. storage.GetAllProfilesAttributes()[0]->SetIsEphemeral(true); @@ -1233,6 +1247,7 @@ EXPECT_FALSE(base::DirectoryExists(path2)); EXPECT_EQ(0u, storage.GetNumberOfProfiles()); EXPECT_EQ("Profile 1", local_state->GetString(prefs::kProfileLastUsed)); + ASSERT_EQ(0u, final_last_active_profile_list->GetSize()); } TEST_F(ProfileManagerTest, CleanUpEphemeralProfilesWithGuestLastUsedProfile) {
diff --git a/chrome/browser/resources/chromeos/crostini_upgrader/app.html b/chrome/browser/resources/chromeos/crostini_upgrader/app.html index de309cd3d..b105134 100644 --- a/chrome/browser/resources/chromeos/crostini_upgrader/app.html +++ b/chrome/browser/resources/chromeos/crostini_upgrader/app.html
@@ -14,7 +14,7 @@ } #icon { - fill: var(--cros-default-button-color); + fill: var(--cros-default-icon-color-prominent); height: 32px; margin-top: 28px; width: 32px; @@ -62,7 +62,7 @@ } paper-progress { - --paper-progress-active-color: var(--cros-default-button-color); + --paper-progress-active-color: var(--cros-default-icon-color-prominent); --paper-progress-container-color: rgba(var(--google-blue-600-rgb), .24); margin-top: 36px; width: 100%;
diff --git a/chrome/browser/resources/chromeos/login/oobe_network.js b/chrome/browser/resources/chromeos/login/oobe_network.js index 0d4837b..418ae1c 100644 --- a/chrome/browser/resources/chromeos/login/oobe_network.js +++ b/chrome/browser/resources/chromeos/login/oobe_network.js
@@ -113,8 +113,8 @@ * @private */ onShown_() { + this.$.networkSelectLogin.refresh(); this.async(function() { - this.$.networkSelectLogin.refresh(); if (this.isConnected_) this.$.nextButton.focus(); else
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.html b/chrome/browser/resources/chromeos/login/sync_consent.html index 15553a1..005eb9b 100644 --- a/chrome/browser/resources/chromeos/login/sync_consent.html +++ b/chrome/browser/resources/chromeos/login/sync_consent.html
@@ -85,7 +85,7 @@ <div slot="footer" class="layout vertical"> <!-- "Sync settings" --> - <div class="overview-list-item flex layout horizontal"> + <div class="overview-list-item layout horizontal"> <img class="overview-list-item-icon" src="images/settings_gear.svg" width="24" height="24"> <div class="flex layout vertical center-justified"> @@ -99,8 +99,10 @@ </div> </div> + <div class="flex"></div> + <!-- "Chrome sync" --> - <div class="overview-list-item flex layout horizontal"> + <div class="overview-list-item layout horizontal"> <img class="overview-list-item-icon" src="images/browser_sync.svg" width="24" height="24"> <div class="flex layout vertical center-justified"> @@ -117,8 +119,10 @@ </div> </div> + <div class="flex"></div> + <!-- Personalize Google services --> - <div class="overview-list-item flex layout horizontal"> + <div class="overview-list-item layout horizontal"> <hd-iron-icon class="overview-list-item-icon" icon1x="sync-consent-32:googleg" icon2x="sync-consent-64:googleg"> </hd-iron-icon>
diff --git a/chrome/browser/resources/media/media_feeds.js b/chrome/browser/resources/media/media_feeds.js index a22c956..a4d009a 100644 --- a/chrome/browser/resources/media/media_feeds.js +++ b/chrome/browser/resources/media/media_feeds.js
@@ -279,7 +279,8 @@ sortKey === 'userStatus' || sortKey === 'lastFetchResult' || sortKey === 'fetchFailedCount' || sortKey === 'lastFetchItemCount' || sortKey === 'lastFetchPlayNextCount' || - sortKey === 'lastFetchContentTypes' || sortKey === 'safeSearchResult') { + sortKey === 'lastFetchContentTypes' || sortKey === 'safeSearchResult' || + sortKey === 'type') { return val1 > val2 ? 1 : -1; } else if ( sortKey === 'lastDiscoveryTime' || sortKey === 'lastFetchTime' ||
diff --git a/chrome/browser/signin/chrome_signin_helper_unittest.cc b/chrome/browser/signin/chrome_signin_helper_unittest.cc index 074d24f..a3e9d3a 100644 --- a/chrome/browser/signin/chrome_signin_helper_unittest.cc +++ b/chrome/browser/signin/chrome_signin_helper_unittest.cc
@@ -68,7 +68,7 @@ bool is_main_frame) : is_main_frame_(is_main_frame), headers_(new net::HttpResponseHeaders(std::string())) { - headers_->AddHeader(header_name + ": " + header_value); + headers_->SetHeader(header_name, header_value); } ~TestResponseAdapter() override {}
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc index 341e8d1a8..45cd3bd 100644 --- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc +++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc
@@ -253,13 +253,13 @@ auto redirect_head = network::mojom::URLResponseHead::New(); redirect_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); - redirect_head->headers->AddHeader("X-Response-1: Foo"); - redirect_head->headers->AddHeader("X-Response-2: Bar"); + redirect_head->headers->SetHeader("X-Response-1", "Foo"); + redirect_head->headers->SetHeader("X-Response-2", "Bar"); auto response_head = network::mojom::URLResponseHead::New(); response_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); - response_head->headers->AddHeader("X-Response-3: Foo"); - response_head->headers->AddHeader("X-Response-4: Bar"); + response_head->headers->SetHeader("X-Response-3", "Foo"); + response_head->headers->SetHeader("X-Response-4", "Bar"); std::string body("Hello."); network::URLLoaderCompletionStatus status; status.decoded_body_length = body.size();
diff --git a/chrome/browser/signin/chrome_signin_url_loader_throttle_unittest.cc b/chrome/browser/signin/chrome_signin_url_loader_throttle_unittest.cc index 18a8222..0dc76fe 100644 --- a/chrome/browser/signin/chrome_signin_url_loader_throttle_unittest.cc +++ b/chrome/browser/signin/chrome_signin_url_loader_throttle_unittest.cc
@@ -167,8 +167,8 @@ auto response_head = network::mojom::URLResponseHead::New(); response_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); - response_head->headers->AddHeader("X-Response-1: Foo"); - response_head->headers->AddHeader("X-Response-2: Bar"); + response_head->headers->SetHeader("X-Response-1", "Foo"); + response_head->headers->SetHeader("X-Response-2", "Bar"); std::vector<std::string> request_headers_to_remove; net::HttpRequestHeaders modified_request_headers; @@ -211,8 +211,8 @@ response_head = network::mojom::URLResponseHead::New(); response_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); - response_head->headers->AddHeader("X-Response-3: Foo"); - response_head->headers->AddHeader("X-Response-4: Bar"); + response_head->headers->SetHeader("X-Response-3", "Foo"); + response_head->headers->SetHeader("X-Response-4", "Bar"); throttle->WillProcessResponse(kTestRedirectURL, response_head.get(), &defer);
diff --git a/chrome/browser/subresource_filter/BUILD.gn b/chrome/browser/subresource_filter/BUILD.gn index d112ecdc2..73c2f2c 100644 --- a/chrome/browser/subresource_filter/BUILD.gn +++ b/chrome/browser/subresource_filter/BUILD.gn
@@ -25,6 +25,7 @@ "//base:base_java_test_support", "//chrome/android:chrome_java", "//chrome/android:chrome_test_java", + "//chrome/browser/tab:java", "//chrome/test/android:chrome_java_test_support", "//components/safe_browsing/android:safe_browsing_java", "//content/public/test/android:content_java_test_support",
diff --git a/chrome/browser/subresource_filter/ad_tagging_browsertest.cc b/chrome/browser/subresource_filter/ad_tagging_browsertest.cc index 848f60fb..8106d808e 100644 --- a/chrome/browser/subresource_filter/ad_tagging_browsertest.cc +++ b/chrome/browser/subresource_filter/ad_tagging_browsertest.cc
@@ -529,7 +529,7 @@ // This test is flaky. See crbug.com/1069346. IN_PROC_BROWSER_TEST_F( AdTaggingBrowserTest, - DISABLED_ChildrenOfFrameWithWindowStopAbortedLoad_StillCorrectlyTagged) { + ChildrenOfFrameWithWindowStopAbortedLoad_StillCorrectlyTagged) { TestSubresourceFilterObserver observer(web_contents()); // Main frame.
diff --git a/chrome/browser/supervised_user/supervised_user_model_type_controller_unittest.cc b/chrome/browser/supervised_user/supervised_user_model_type_controller_unittest.cc new file mode 100644 index 0000000..99aa38f --- /dev/null +++ b/chrome/browser/supervised_user/supervised_user_model_type_controller_unittest.cc
@@ -0,0 +1,65 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h" + +#include "base/bind_helpers.h" +#include "chrome/browser/supervised_user/supervised_user_constants.h" +#include "chrome/test/base/testing_profile.h" +#include "components/sync/base/model_type.h" +#include "components/sync/driver/data_type_controller.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +using syncer::DataTypeController; + +class SupervisedUserSyncModelTypeControllerTest : public testing::Test { + private: + content::BrowserTaskEnvironment task_environment_; +}; + +TEST_F(SupervisedUserSyncModelTypeControllerTest, + SupervisedUserMeetsPreconditions) { + TestingProfile::Builder builder; + builder.SetSupervisedUserId(supervised_users::kChildAccountSUID); + std::unique_ptr<Profile> child_profile = builder.Build(); + ASSERT_TRUE(child_profile->IsSupervised()); + + SupervisedUserSyncModelTypeController controller( + syncer::SUPERVISED_USER_SETTINGS, child_profile.get(), + /*dump_stack=*/base::DoNothing(), + /*store_factory=*/base::DoNothing(), + /*syncable_service=*/nullptr); + EXPECT_EQ(DataTypeController::PreconditionState::kPreconditionsMet, + controller.GetPreconditionState()); +} + +TEST_F(SupervisedUserSyncModelTypeControllerTest, + NonSupervisedUserDoesNotMeetPreconditions) { + TestingProfile::Builder builder; + std::unique_ptr<Profile> non_child_profile = builder.Build(); + ASSERT_FALSE(non_child_profile->IsSupervised()); + + SupervisedUserSyncModelTypeController controller( + syncer::SUPERVISED_USER_SETTINGS, non_child_profile.get(), + /*dump_stack=*/base::DoNothing(), + /*store_factory=*/base::DoNothing(), + /*syncable_service=*/nullptr); + EXPECT_EQ(DataTypeController::PreconditionState::kMustStopAndClearData, + controller.GetPreconditionState()); +} + +TEST_F(SupervisedUserSyncModelTypeControllerTest, HasTransportModeDelegate) { + TestingProfile::Builder builder; + builder.SetSupervisedUserId(supervised_users::kChildAccountSUID); + std::unique_ptr<Profile> child_profile = builder.Build(); + ASSERT_TRUE(child_profile->IsSupervised()); + + SupervisedUserSyncModelTypeController controller( + syncer::SUPERVISED_USER_SETTINGS, child_profile.get(), + /*dump_stack=*/base::DoNothing(), + /*store_factory=*/base::DoNothing(), + /*syncable_service=*/nullptr); + EXPECT_TRUE(controller.GetDelegateForTransportModeForTest()); +}
diff --git a/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.cc b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.cc index 9ceadc1..df4aeb76 100644 --- a/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.cc +++ b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.cc
@@ -6,26 +6,27 @@ #include "base/bind.h" #include "chrome/browser/profiles/profile.h" -#include "components/browser_sync/browser_sync_client.h" #include "components/sync/model/model_type_store_service.h" SupervisedUserSyncModelTypeController::SupervisedUserSyncModelTypeController( syncer::ModelType type, const Profile* profile, const base::RepeatingClosure& dump_stack, - browser_sync::BrowserSyncClient* sync_client) + syncer::OnceModelTypeStoreFactory store_factory, + base::WeakPtr<syncer::SyncableService> syncable_service) : SyncableServiceBasedModelTypeController( type, - sync_client->GetModelTypeStoreService()->GetStoreFactory(), - sync_client->GetSyncableServiceForType(type), - dump_stack), + std::move(store_factory), + syncable_service, + dump_stack, + DelegateMode::kTransportModeWithSingleModel), profile_(profile) { DCHECK(type == syncer::SUPERVISED_USER_SETTINGS || type == syncer::SUPERVISED_USER_WHITELISTS); } SupervisedUserSyncModelTypeController:: - ~SupervisedUserSyncModelTypeController() {} + ~SupervisedUserSyncModelTypeController() = default; syncer::DataTypeController::PreconditionState SupervisedUserSyncModelTypeController::GetPreconditionState() const {
diff --git a/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h index b7a277a92..13e93f7 100644 --- a/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h +++ b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h
@@ -11,12 +11,9 @@ class Profile; -namespace browser_sync { -class BrowserSyncClient; -} // namespace browser_sync - // A DataTypeController for supervised user sync datatypes, which enables or -// disables these types based on the profile's IsSupervised state. +// disables these types based on the profile's IsSupervised state. Runs in +// sync transport mode. class SupervisedUserSyncModelTypeController : public syncer::SyncableServiceBasedModelTypeController { public: @@ -25,7 +22,8 @@ syncer::ModelType type, const Profile* profile, const base::RepeatingClosure& dump_stack, - browser_sync::BrowserSyncClient* sync_client); + syncer::OnceModelTypeStoreFactory store_factory, + base::WeakPtr<syncer::SyncableService> syncable_service); ~SupervisedUserSyncModelTypeController() override; // DataTypeController override.
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc index f5b4ab1..aeda1c63d 100644 --- a/chrome/browser/sync/chrome_sync_client.cc +++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -359,9 +359,13 @@ #if BUILDFLAG(ENABLE_SUPERVISED_USERS) controllers.push_back(std::make_unique<SupervisedUserSyncModelTypeController>( - syncer::SUPERVISED_USER_SETTINGS, profile_, dump_stack, this)); + syncer::SUPERVISED_USER_SETTINGS, profile_, dump_stack, + model_type_store_factory, + GetSyncableServiceForType(syncer::SUPERVISED_USER_SETTINGS))); controllers.push_back(std::make_unique<SupervisedUserSyncModelTypeController>( - syncer::SUPERVISED_USER_WHITELISTS, profile_, dump_stack, this)); + syncer::SUPERVISED_USER_WHITELISTS, profile_, dump_stack, + model_type_store_factory, + GetSyncableServiceForType(syncer::SUPERVISED_USER_WHITELISTS))); #endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn index 37d7b38..cef802e 100644 --- a/chrome/browser/tab/BUILD.gn +++ b/chrome/browser/tab/BUILD.gn
@@ -8,5 +8,26 @@ import("//chrome/browser/buildflags.gni") android_library("java") { - sources = [ "java/src/org/chromium/chrome/browser/tab/Dummy.java" ] + sources = [ + "java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java", + "java/src/org/chromium/chrome/browser/tab/Tab.java", + "java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java", + "java/src/org/chromium/chrome/browser/tab/TabAttributes.java", + "java/src/org/chromium/chrome/browser/tab/TabCreationState.java", + "java/src/org/chromium/chrome/browser/tab/TabHidingType.java", + "java/src/org/chromium/chrome/browser/tab/TabLifecycle.java", + "java/src/org/chromium/chrome/browser/tab/TabObserver.java", + ] + + # TabSelectionType, TabLaunchType + srcjar_deps = [ "//chrome/browser/ui:tab_model_enums_java" ] + + deps = [ + "//base:base_java", + "//chrome/browser/ui/android/native_page:java", + "//components/embedder_support/android:content_view_java", + "//components/find_in_page/android:java", + "//content/public/android:content_java", + "//ui/android:ui_full_java", + ] }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/DEPS new file mode 100644 index 0000000..d6bcdb1 --- /dev/null +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -0,0 +1,18 @@ +noparent = True + +include_rules = [ + "-chrome", + "+base/android/java/src/org/chromium/base", + "+chrome/browser/ui/android/native_page", + "+components/find_in_page/android/java", + "+content/public/android/java/src/org/chromium/content_public", + "+ui/android/java/src/org/chromium/ui/base", +] + +specific_include_rules = { + 'Tab\.java': [ + "-components", + "+components/embedder_support/android/java/src/org/chromium/components/embedder_support/view", + "+url/android/java/src/org/chromium/url", + ], +}
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Dummy.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Dummy.java deleted file mode 100644 index 5cab495..0000000 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Dummy.java +++ /dev/null
@@ -1,11 +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.tab; - -/** - * Dummy class to get the build working for the new target chrome/browser/tab:java. - * TODO(jinsukkim): Remove the class once the real target classes are in place. - */ -public class Dummy {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java similarity index 81% rename from chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java rename to chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java index 1ae9df4..cd39015 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
@@ -25,7 +25,7 @@ */ public class EmptyTabObserver implements TabObserver { @Override - public void onInitialized(Tab tab, TabState tabState) {} + public void onInitialized(Tab tab, String appId, Boolean hasThemeColor, int themeColor) {} @Override public void onShown(Tab tab, @TabSelectionType int type) {} @@ -34,19 +34,19 @@ public void onHidden(Tab tab, @TabHidingType int reason) {} @Override - public void onClosingStateChanged(Tab tab, boolean closing) { } + public void onClosingStateChanged(Tab tab, boolean closing) {} @Override - public void onDestroyed(Tab tab) { } + public void onDestroyed(Tab tab) {} @Override - public void onContentChanged(Tab tab) { } + public void onContentChanged(Tab tab) {} @Override - public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) { } + public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) {} @Override - public void onPageLoadStarted(Tab tab, String url) { } + public void onPageLoadStarted(Tab tab, String url) {} @Override public void onPageLoadFinished(Tab tab, String url) {} @@ -61,40 +61,40 @@ public void onRestoreFailed(Tab tab) {} @Override - public void onFaviconUpdated(Tab tab, Bitmap icon) { } + public void onFaviconUpdated(Tab tab, Bitmap icon) {} @Override - public void onTitleUpdated(Tab tab) { } + public void onTitleUpdated(Tab tab) {} @Override - public void onUrlUpdated(Tab tab) { } + public void onUrlUpdated(Tab tab) {} @Override - public void onSSLStateUpdated(Tab tab) { } + public void onSSLStateUpdated(Tab tab) {} @Override public void onCrash(Tab tab) {} @Override - public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) { } + public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) {} @Override - public void onContextMenuShown(Tab tab, ContextMenu menu) { } + public void onContextMenuShown(Tab tab, ContextMenu menu) {} @Override public void onCloseContents(Tab tab) {} @Override - public void onLoadStarted(Tab tab, boolean toDifferentDocument) { } + public void onLoadStarted(Tab tab, boolean toDifferentDocument) {} @Override - public void onLoadStopped(Tab tab, boolean toDifferentDocument) { } + public void onLoadStopped(Tab tab, boolean toDifferentDocument) {} @Override public void onLoadProgressChanged(Tab tab, float progress) {} @Override - public void onUpdateUrl(Tab tab, String url) { } + public void onUpdateUrl(Tab tab, String url) {} @Override public void onDidFailLoad(Tab tab, boolean isMainFrame, int errorCode, String failingUrl) {} @@ -112,16 +112,16 @@ public void didFirstVisuallyNonEmptyPaint(Tab tab) {} @Override - public void onDidChangeThemeColor(Tab tab, int color) { } + public void onDidChangeThemeColor(Tab tab, int color) {} @Override - public void onDidAttachInterstitialPage(Tab tab) { } + public void onDidAttachInterstitialPage(Tab tab) {} @Override - public void onDidDetachInterstitialPage(Tab tab) { } + public void onDidDetachInterstitialPage(Tab tab) {} @Override - public void onBackgroundColorChanged(Tab tab, int color) { } + public void onBackgroundColorChanged(Tab tab, int color) {} @Override public void webContentsCreated(Tab tab, WebContents sourceWebContents,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Tab.java similarity index 91% rename from chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java rename to chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Tab.java index 3aa292a..8466575 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -65,17 +65,6 @@ WindowAndroid getWindowAndroid(); /** - * Update the attachment state to Window(Activity). - * @param window A new {@link WindowAndroid} to attach the tab to. If {@code null}, - * the tab is being detached. See {@link ReparentingTask#detach()} for details. - * @param tabDelegateFactory The new delegate factory this tab should be using. Can be - * {@code null} even when {@code window} is not, meaning we simply want to swap out - * {@link WindowAndroid} for this tab and keep using the current delegate factory. - */ - void updateAttachment( - @Nullable WindowAndroid window, @Nullable TabDelegateFactory tabDelegateFactory); - - /** * @return Content view used for rendered web contents. Can be null * if web contents is null. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java rename to chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAttributes.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAttributes.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/tab/TabAttributes.java rename to chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAttributes.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabCreationState.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabCreationState.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/tab/TabCreationState.java rename to chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabCreationState.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHidingType.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabHidingType.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/tab/TabHidingType.java rename to chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabHidingType.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabLifecycle.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabLifecycle.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/tab/TabLifecycle.java rename to chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabLifecycle.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java similarity index 97% rename from chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java rename to chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java index ec45486..54cb7b3e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java
@@ -9,7 +9,6 @@ import androidx.annotation.Nullable; -import org.chromium.chrome.browser.TabLoadStatus; import org.chromium.components.find_in_page.FindMatchRectsDetails; import org.chromium.components.find_in_page.FindNotificationDetails; import org.chromium.content_public.browser.LoadUrlParams; @@ -25,9 +24,12 @@ * Called when a {@link Tab} finished initialization. The {@link TabState} contains, * if not {@code null}, various states that a Tab should restore itself from. * @param tab The notifying {@link Tab}. - * @param tabState {@link TabState} to restore tab's state from if not {@code null}. + * @param appId ID of the external app that opened this tab. + * @param hasThemeColor {@code true} if the tab has a theme color set. {@code null} + * if theme color info is not available from TabState. + * @param themeColor Theme color. */ - void onInitialized(Tab tab, TabState tabState); + void onInitialized(Tab tab, String appId, @Nullable Boolean hasThemeColor, int themeColor); /** * Called when a {@link Tab} is shown.
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc index c2c5675..8f8c04f 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -31,6 +31,7 @@ #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/font.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/paint_vector_icon.h" @@ -78,6 +79,7 @@ constexpr autofill::PopupItemId kItemTypesUsingLeadingIcons[] = { autofill::PopupItemId::POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS, autofill::PopupItemId::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY, + autofill::PopupItemId::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY, autofill::PopupItemId::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN, autofill::PopupItemId::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_RE_SIGNIN, autofill::PopupItemId:: @@ -132,6 +134,10 @@ return gfx::CreateVectorIcon(vector_icons::kSettingsIcon, kIconSize, gfx::kChromeIconGrey); } + if (icon_str == "empty") { + return gfx::CreateVectorIcon(omnibox::kHttpIcon, kIconSize, + gfx::kChromeIconGrey); + } if (icon_str == "google") { #if BUILDFLAG(GOOGLE_CHROME_BRANDING) return gfx::CreateVectorIcon(kGoogleGLogoIcon, kIconSize, @@ -1097,6 +1103,7 @@ case autofill::PopupItemId::POPUP_ITEM_ID_SCAN_CREDIT_CARD: case autofill::PopupItemId::POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO: case autofill::PopupItemId::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY: + case autofill::PopupItemId::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY: case autofill::PopupItemId::POPUP_ITEM_ID_HIDE_AUTOFILL_SUGGESTIONS: case autofill::PopupItemId::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN: case autofill::PopupItemId::
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc index 8f32702..0d06389 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc
@@ -47,6 +47,7 @@ {autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN, 1}, {autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_RE_SIGNIN, 1}, {autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN_AND_GENERATE, 1}, + {autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY, 1}, }; class TestAXEventObserver : public views::AXEventObserver {
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc index fe80ab0a..350aa98 100644 --- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc +++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
@@ -4,7 +4,9 @@ #include "chrome/browser/ui/views/passwords/account_chooser_dialog_view.h" +#include <algorithm> #include <memory> +#include <utility> #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -54,6 +56,7 @@ CredentialsItemView* credential_view = new CredentialsItemView(button_listener, titles.first, titles.second, form.get(), loader_factory); + credential_view->SetStoreIndicatorIcon(form->in_store); ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get(); gfx::Insets insets = layout_provider->GetInsetsMetric(views::INSETS_DIALOG_SUBSECTION);
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.cc b/chrome/browser/ui/views/passwords/credentials_item_view.cc index eec0539f..1236aa40b 100644 --- a/chrome/browser/ui/views/passwords/credentials_item_view.cc +++ b/chrome/browser/ui/views/passwords/credentials_item_view.cc
@@ -4,17 +4,22 @@ #include "chrome/browser/ui/views/passwords/credentials_item_view.h" +#include <algorithm> +#include <memory> +#include <utility> + #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/grit/theme_resources.h" -#include "components/autofill/core/common/password_form.h" #include "third_party/skia/include/core/SkPath.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/insets.h" +#include "ui/gfx/paint_vector_icon.h" #include "ui/views/border.h" #include "ui/views/bubble/tooltip_icon.h" #include "ui/views/controls/image_view.h" @@ -64,6 +69,9 @@ views::BoxLayout::Orientation::kHorizontal)); layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kCenter); + layout->set_between_child_spacing( + ChromeLayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_RELATED_LABEL_HORIZONTAL)); // Create an image-view for the avatar. Make sure it ignores events so that // the parent can receive the events instead. auto image_view = std::make_unique<CircularImageView>(); @@ -94,12 +102,6 @@ views::BoxLayout::Orientation::kVertical)); text_layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kStart); - text_container->SetProperty( - views::kMarginsKey, - gfx::Insets(0, - ChromeLayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_RELATED_LABEL_HORIZONTAL), - 0, 0)); layout->SetFlexForView(text_container, 1); } @@ -133,6 +135,24 @@ CredentialsItemView::~CredentialsItemView() = default; +void CredentialsItemView::SetStoreIndicatorIcon( + autofill::PasswordForm::Store store) { +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + if (store == autofill::PasswordForm::Store::kAccountStore && + !store_indicator_icon_view_) { + store_indicator_icon_view_ = + AddChildView(std::make_unique<views::ImageView>()); + store_indicator_icon_view_->set_can_process_events_within_subtree(false); + store_indicator_icon_view_->SetImage( + gfx::CreateVectorIcon(kGoogleGLogoIcon, gfx::kPlaceholderColor)); + } else if (store == autofill::PasswordForm::Store::kProfileStore && + store_indicator_icon_view_) { + RemoveChildView(store_indicator_icon_view_); + store_indicator_icon_view_ = nullptr; + } +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) +} + void CredentialsItemView::UpdateAvatar(const gfx::ImageSkia& image) { image_view_->SetImage(ScaleImageForAccountAvatar(image)); }
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.h b/chrome/browser/ui/views/passwords/credentials_item_view.h index f8452ee..e5a3a7b 100644 --- a/chrome/browser/ui/views/passwords/credentials_item_view.h +++ b/chrome/browser/ui/views/passwords/credentials_item_view.h
@@ -7,14 +7,13 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "build/branding_buildflags.h" +#include "build/buildflag.h" #include "chrome/browser/ui/passwords/account_avatar_fetcher.h" +#include "components/autofill/core/common/password_form.h" #include "ui/views/controls/button/button.h" #include "ui/views/style/typography.h" -namespace autofill { -struct PasswordForm; -} - namespace gfx { class ImageSkia; } @@ -44,6 +43,10 @@ int lower_text_style = views::style::STYLE_SECONDARY); ~CredentialsItemView() override; + // If |store| is kAccountStore and the build is official, adds a G logo icon + // to the view. If |store| is kProfileStore, removes any existing icon. + void SetStoreIndicatorIcon(autofill::PasswordForm::Store store); + const autofill::PasswordForm* form() const { return form_; } // AccountAvatarFetcherDelegate: @@ -58,6 +61,13 @@ const autofill::PasswordForm* form_; views::ImageView* image_view_; + +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + // Optional right-aligned icon to distinguish account store credentials and + // profile store ones. + views::ImageView* store_indicator_icon_view_ = nullptr; +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) + views::Label* upper_label_ = nullptr; views::Label* lower_label_ = nullptr; views::ImageView* info_icon_ = nullptr;
diff --git a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc index 1461b4a..1593912e 100644 --- a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc +++ b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
@@ -40,6 +40,7 @@ #include "chrome/browser/ui/views/web_apps/web_app_menu_button.h" #include "chrome/browser/ui/views/web_apps/web_app_origin_text.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h" #include "chrome/common/chrome_features.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/common/features.h" @@ -646,33 +647,38 @@ params.page_action_icon_delegate = this; page_action_icon_controller_->Init(params, this); - // Extensions toolbar area with pinned extensions is lower priority than, for - // example, the menu button or other toolbar buttons, and pinned extensions - // should hide before other toolbar buttons. - constexpr int kLowPriorityFlexOrder = 2; - if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) { - extensions_container_ = - AddChildView(std::make_unique<ExtensionsToolbarContainer>( - browser_view_->browser(), - ExtensionsToolbarContainer::DisplayMode::kCompact)); - extensions_container_->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification( - extensions_container_->animating_layout_manager() - ->GetDefaultFlexRule()) - .WithOrder(kLowPriorityFlexOrder)); - views::SetHitTestComponent(extensions_container_, - static_cast<int>(HTCLIENT)); - } else { - browser_actions_container_ = - AddChildView(std::make_unique<BrowserActionsContainer>( - browser_view_->browser(), nullptr, this, false /* interactive */)); - browser_actions_container_->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(browser_actions_container_->GetFlexRule()) - .WithOrder(kLowPriorityFlexOrder)); - views::SetHitTestComponent(browser_actions_container_, - static_cast<int>(HTCLIENT)); + // Do not create the extensions or browser actions container if it is a + // System Web App. + if (!web_app::IsSystemWebApp(browser_view_->browser())) { + // Extensions toolbar area with pinned extensions is lower priority than, + // for example, the menu button or other toolbar buttons, and pinned + // extensions should hide before other toolbar buttons. + constexpr int kLowPriorityFlexOrder = 2; + if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) { + extensions_container_ = + AddChildView(std::make_unique<ExtensionsToolbarContainer>( + browser_view_->browser(), + ExtensionsToolbarContainer::DisplayMode::kCompact)); + extensions_container_->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification( + extensions_container_->animating_layout_manager() + ->GetDefaultFlexRule()) + .WithOrder(kLowPriorityFlexOrder)); + views::SetHitTestComponent(extensions_container_, + static_cast<int>(HTCLIENT)); + } else { + browser_actions_container_ = + AddChildView(std::make_unique<BrowserActionsContainer>( + browser_view_->browser(), nullptr, this, + false /* interactive */)); + browser_actions_container_->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(browser_actions_container_->GetFlexRule()) + .WithOrder(kLowPriorityFlexOrder)); + views::SetHitTestComponent(browser_actions_container_, + static_cast<int>(HTCLIENT)); + } } if (app_controller->HasTitlebarMenuButton()) {
diff --git a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc index f010830..602d877 100644 --- a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc +++ b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
@@ -223,6 +223,12 @@ InstallAndLaunchMockPopup(); EXPECT_EQ(BrowserList::GetInstance()->size(), 2u); } + +IN_PROC_BROWSER_TEST_F(AppBrowserControllerBrowserTest, + NoExtensionsContainerExists) { + InstallAndLaunchMockPopup(); + EXPECT_EQ(app_browser_->window()->GetExtensionsContainer(), nullptr); +} #endif #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc index 90fb512..08661ca9 100644 --- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -703,8 +703,8 @@ if (GetCurrentScreen() != ErrorScreenView::kScreenId) { error_screen_->SetUIState(NetworkError::UI_STATE_SIGNIN); error_screen_->SetParentScreen(kScreenId); - error_screen_->SetHideCallback(base::Bind(&EnrollmentScreenHandler::DoShow, - weak_ptr_factory_.GetWeakPtr())); + error_screen_->SetHideCallback(base::BindOnce( + &EnrollmentScreenHandler::DoShow, weak_ptr_factory_.GetWeakPtr())); error_screen_->Show(); histogram_helper_->OnErrorShow(error_screen_->GetErrorState()); }
diff --git a/chrome/browser/ui/webui/discards/discards.mojom b/chrome/browser/ui/webui/discards/discards.mojom index d4d0aba..b834549 100644 --- a/chrome/browser/ui/webui/discards/discards.mojom +++ b/chrome/browser/ui/webui/discards/discards.mojom
@@ -104,7 +104,12 @@ url.mojom.Url main_frame_url; - // TODO(siggi): Estimate data. + // This field is a dictionary of values, where each value is generated by + // a performance_manager::NodeDataDescriber implementation and keyed by the + // name it registered with. The intent is for each describer to describe + // private node-related or node-attached data in some way, to allow presenting + // otherwise hidden state in the chrome://discards/graph view. + string description_json; }; // Represents the momentary state of a Frame node. @@ -115,6 +120,9 @@ int64 page_id; int64 parent_frame_id; int64 process_id; + + // See PageInfo::description_json. + string description_json; }; // Represents the momentary state of a Process node. @@ -123,6 +131,9 @@ mojo_base.mojom.ProcessId pid; uint64 private_footprint_kb; + + // See PageInfo::description_json. + string description_json; }; // Represents the momentary state of a Worker node. @@ -135,6 +146,9 @@ array<int64> client_frame_ids; array<int64> client_worker_ids; array<int64> child_worker_ids; + + // See PageInfo::description_json. + string description_json; }; // Used to transport favicon data.
diff --git a/chrome/browser/ui/webui/discards/graph_dump_impl.cc b/chrome/browser/ui/webui/discards/graph_dump_impl.cc index c5033d7..93b84c32 100644 --- a/chrome/browser/ui/webui/discards/graph_dump_impl.cc +++ b/chrome/browser/ui/webui/discards/graph_dump_impl.cc
@@ -9,6 +9,7 @@ #include "base/base64.h" #include "base/bind.h" +#include "base/json/json_string_value_serializer.h" #include "base/macros.h" #include "base/task/cancelable_task_tracker.h" #include "base/task/post_task.h" @@ -19,6 +20,8 @@ #include "components/favicon/core/favicon_service.h" #include "components/favicon_base/favicon_callback.h" #include "components/performance_manager/public/graph/graph.h" +#include "components/performance_manager/public/graph/node_data_describer.h" +#include "components/performance_manager/public/graph/node_data_describer_registry.h" #include "components/performance_manager/public/performance_manager.h" #include "components/performance_manager/public/web_contents_proxy.h" #include "content/public/browser/browser_task_traits.h" @@ -35,6 +38,16 @@ return performance_manager::Node::GetSerializationId(node); } +// Best effort convert |value| to a string. +std::string ToJSON(const base::Value& value) { + std::string result; + JSONStringValueSerializer serializer(&result); + if (serializer.Serialize(value)) + return result; + + return std::string(); +} + } // namespace class DiscardsGraphDumpImpl::FaviconRequestHelper { @@ -372,6 +385,8 @@ frame_info->page_id = GetSerializationId(page); frame_info->url = frame->GetURL(); + frame_info->description_json = ToJSON( + graph_->GetNodeDataDescriberRegistry()->DescribeFrameNodeData(frame)); if (created) change_subscriber_->FrameCreated(std::move(frame_info)); @@ -388,6 +403,9 @@ page_info->id = GetSerializationId(page_node); page_info->main_frame_url = page_node->GetMainFrameUrl(); + page_info->description_json = ToJSON( + graph_->GetNodeDataDescriberRegistry()->DescribePageNodeData(page_node)); + if (created) change_subscriber_->PageCreated(std::move(page_info)); else @@ -405,6 +423,9 @@ process_info->pid = process->GetProcessId(); process_info->private_footprint_kb = process->GetPrivateFootprintKb(); + process_info->description_json = ToJSON( + graph_->GetNodeDataDescriberRegistry()->DescribeProcessNodeData(process)); + if (created) change_subscriber_->ProcessCreated(std::move(process_info)); else @@ -435,6 +456,9 @@ worker_info->child_worker_ids.push_back(GetSerializationId(child_worker)); } + worker_info->description_json = ToJSON( + graph_->GetNodeDataDescriberRegistry()->DescribeWorkerNodeData(worker)); + if (created) change_subscriber_->WorkerCreated(std::move(worker_info)); else
diff --git a/chrome/browser/ui/webui/discards/graph_dump_impl.h b/chrome/browser/ui/webui/discards/graph_dump_impl.h index d70ccaf..b137b89 100644 --- a/chrome/browser/ui/webui/discards/graph_dump_impl.h +++ b/chrome/browser/ui/webui/discards/graph_dump_impl.h
@@ -92,6 +92,10 @@ // Ignored. void OnHadFormInteractionChanged( const performance_manager::FrameNode* frame_node) override {} + // Ignored. + void OnFirstContentfulPaint( + const performance_manager::FrameNode* frame_node, + base::TimeDelta time_since_navigation_start) override {} // PageNodeObserver implementation: void OnPageNodeAdded(const performance_manager::PageNode* page_node) override;
diff --git a/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc b/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc index f1b2e7d..147d095c 100644 --- a/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc +++ b/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc
@@ -8,11 +8,14 @@ #include <set> #include <utility> +#include "base/json/json_reader.h" #include "base/run_loop.h" #include "base/stl_util.h" #include "base/test/bind_test_util.h" #include "base/time/time.h" #include "chrome/browser/ui/webui/discards/discards.mojom.h" +#include "components/performance_manager/public/graph/node_data_describer.h" +#include "components/performance_manager/public/graph/node_data_describer_registry.h" #include "components/performance_manager/test_support/graph_impl.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "content/public/test/browser_task_environment.h" @@ -26,7 +29,7 @@ using performance_manager::NodeBase; -const std::string kHtmlMimeType = "text/html"; +const char kHtmlMimeType[] = "text/html"; class TestChangeStream : public discards::mojom::GraphChangeStream { public: @@ -139,6 +142,31 @@ performance_manager::TestGraphImpl graph_; }; +class TestNodeDataDescriber : public performance_manager::NodeDataDescriber { + public: + // NodeDataDescriber implementations: + base::Value DescribeFrameNodeData( + const performance_manager::FrameNode* node) const override { + return base::Value("frame"); + } + base::Value DescribePageNodeData( + const performance_manager::PageNode* node) const override { + return base::Value("page"); + } + base::Value DescribeProcessNodeData( + const performance_manager::ProcessNode* node) const override { + return base::Value("process"); + } + base::Value DescribeSystemNodeData( + const performance_manager::SystemNode* node) const override { + return base::Value("system"); + } + base::Value DescribeWorkerNodeData( + const performance_manager::WorkerNode* node) const override { + return base::Value("worker"); + } +}; + } // namespace TEST_F(DiscardsGraphDumpImplTest, ChangeStream) { @@ -175,6 +203,9 @@ impl->BindWithGraph(&graph_, graph_dump_remote.BindNewPipeAndPassReceiver()); graph_.PassToGraph(std::move(impl)); + TestNodeDataDescriber describer; + graph_.GetNodeDataDescriberRegistry()->RegisterDescriber(&describer, "test"); + TestChangeStream change_stream; graph_dump_remote->SubscribeToChanges(change_stream.GetRemote()); @@ -186,11 +217,22 @@ EXPECT_EQ(2u, change_stream.process_map().size()); for (const auto& kv : change_stream.process_map()) { - EXPECT_NE(0u, kv.second->id); + const auto* process_info = kv.second.get(); + EXPECT_NE(0u, process_info->id); + EXPECT_EQ(base::JSONReader::Read("{\"test\":\"process\"}"), + base::JSONReader::Read(process_info->description_json)); } EXPECT_EQ(3u, change_stream.frame_map().size()); + for (const auto& kv : change_stream.frame_map()) { + EXPECT_EQ(base::JSONReader::Read("{\"test\":\"frame\"}"), + base::JSONReader::Read(kv.second->description_json)); + } EXPECT_EQ(1u, change_stream.worker_map().size()); + for (const auto& kv : change_stream.worker_map()) { + EXPECT_EQ(base::JSONReader::Read("{\"test\":\"worker\"}"), + base::JSONReader::Read(kv.second->description_json)); + } // Count the top-level frames as we go. size_t top_level_frames = 0; @@ -218,6 +260,8 @@ const auto& page = kv.second; EXPECT_NE(0u, page->id); EXPECT_EQ(kExampleUrl, page->main_frame_url); + EXPECT_EQ(base::JSONReader::Read("{\"test\":\"page\"}"), + base::JSONReader::Read(kv.second->description_json)); } // Test change notifications. @@ -249,4 +293,6 @@ EXPECT_EQ(nullptr, graph_.TakeFromGraph(impl_raw)); worker->RemoveClientFrame(mock_graph.frame.get()); + + graph_.GetNodeDataDescriberRegistry()->UnregisterDescriber(&describer); }
diff --git a/chrome/browser/upboarding/query_tiles/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java b/chrome/browser/upboarding/query_tiles/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java index edf01c1..0a5615d8 100644 --- a/chrome/browser/upboarding/query_tiles/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java +++ b/chrome/browser/upboarding/query_tiles/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java
@@ -8,11 +8,8 @@ import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.support.test.espresso.action.ViewActions; import android.support.test.filters.SmallTest; import org.junit.After; @@ -22,7 +19,6 @@ import org.junit.runner.RunWith; import org.chromium.base.Callback; -import org.chromium.base.ContextUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -32,8 +28,6 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.NewTabPageTestUtils; import org.chromium.chrome.test.util.browser.Features; -import org.chromium.content_public.browser.test.util.Criteria; -import org.chromium.content_public.browser.test.util.CriteriaHelper; import java.util.ArrayList; import java.util.List; @@ -44,8 +38,6 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class QueryTileSectionTest { - private static final String SEARCH_URL_PATTERN = "https://www.google.com/search?q="; - @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); @@ -66,35 +58,13 @@ @Features.EnableFeatures(ChromeFeatureList.QUERY_TILES) public void testSimpleTest() throws Exception { onView(withId(R.id.query_tiles)).check(matches(isDisplayed())); - onView(withText("Tile 1")).check(matches(isDisplayed())); - } - - @Test - @SmallTest - @Features.EnableFeatures(ChromeFeatureList.QUERY_TILES) - public void testLeafLevelTileLoadsSearchResultsPage() throws Exception { - onView(withId(R.id.query_tiles)).check(matches(isDisplayed())); - onView(withText("Tile 1")).perform(ViewActions.click()); - onView(withText("Tile 1_1")).check(matches(isDisplayed())).perform(ViewActions.click()); - waitForSearchResultsPage(mActivityTestRule.getActivity().getActivityTab()); - } - - private static void waitForSearchResultsPage(final Tab tab) { - CriteriaHelper.pollUiThread(new Criteria("The SRP was never loaded.") { - @Override - public boolean isSatisfied() { - return tab.getUrl().getValidSpecOrEmpty().contains(SEARCH_URL_PATTERN); - } - }); } private static class TestTileProvider implements TileProvider { private List<Tile> mTiles = new ArrayList<>(); private TestTileProvider() { - List<Tile> children = new ArrayList<>(); - children.add(new Tile("tile1_1", "Tile 1_1", "Tile 1_1", "Tile 1_1 Query", null)); - Tile tile = new Tile("1", "Tile 1", "Tile 1", "Tile 1 Query", children); + Tile tile = new Tile("1", "Tile 1", "Tile 1", "Tile 1", null); mTiles.add(tile); } @@ -105,12 +75,7 @@ @Override public void getVisuals(String id, Callback<List<Bitmap>> callback) { - List<Bitmap> bitmapList = new ArrayList<>(); - Bitmap bitmap = BitmapFactory.decodeResource( - ContextUtils.getApplicationContext().getResources(), - R.drawable.chrome_sync_logo); - bitmapList.add(bitmap); - callback.onResult(bitmapList); + callback.onResult(null); } } -} \ No newline at end of file +}
diff --git a/chrome/common/channel_info_posix.cc b/chrome/common/channel_info_posix.cc index 1632dce..88b20489b 100644 --- a/chrome/common/channel_info_posix.cc +++ b/chrome/common/channel_info_posix.cc
@@ -70,6 +70,13 @@ #if defined(OS_LINUX) && !defined(OS_CHROMEOS) std::string GetDesktopName(base::Environment* env) { #if BUILDFLAG(GOOGLE_CHROME_BRANDING) + // Google Chrome packaged as a snap is a special case: the application name + // is always "google-chrome", regardless of the channel (channels are built + // in to snapd, switching between them or doing parallel installs does not + // require distinct application names). + std::string snap_name; + if (env->GetVar("SNAP_NAME", &snap_name) && snap_name == "google-chrome") + return "google-chrome.desktop"; version_info::Channel product_channel(GetChannel()); switch (product_channel) { case version_info::Channel::DEV:
diff --git a/chrome/installer/linux/snap/build.sh b/chrome/installer/linux/snap/build.sh index f811aac..ce37c98 100755 --- a/chrome/installer/linux/snap/build.sh +++ b/chrome/installer/linux/snap/build.sh
@@ -53,6 +53,14 @@ process_template "${SCRIPTDIR}/chrome.launcher.in" "${LAUNCHER_SCRIPT}" chmod +x "${LAUNCHER_SCRIPT}" process_template "${SCRIPTDIR}/snapcraft.yaml.in" "${TMPFILEDIR}/snapcraft.yaml" +if [ "$SNAPNAME" = "google-chrome" ]; then + LOGO="product_logo_256" + if [ "$CHANNEL" = "beta" ]; then + sed -i -e "s:$LOGO.png:$LOGO_beta.png:" "${TMPFILEDIR}/snapcraft.yaml" + elif [ "$CHANNEL" = "unstable" ]; then + sed -i -e "s:$LOGO.png:$LOGO_dev.png:" "${TMPFILEDIR}/snapcraft.yaml" + fi +fi cd "${TMPFILEDIR}"
diff --git a/chrome/installer/util/lzma_util.cc b/chrome/installer/util/lzma_util.cc index f20c13d..5dce9b6 100644 --- a/chrome/installer/util/lzma_util.cc +++ b/chrome/installer/util/lzma_util.cc
@@ -18,7 +18,6 @@ #include "base/logging.h" #include "base/optional.h" #include "base/strings/utf_string_conversions.h" -#include "base/win/windows_version.h" extern "C" { #include "third_party/lzma_sdk/7z.h" @@ -370,12 +369,12 @@ // Unmap the target file from the process's address space. mapped_file.reset(); last_folder_index = -1; - // Flush to avoid an interesting bug in Windows 7 through Windows 10 - // 1809; see - // https://randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/ - // for details. - if (base::win::GetVersion() < base::win::Version::WIN10_RS5) - target_file.Flush(); + // Flush to avoid odd behavior, such as the bug in Windows 7 through + // Windows 10 1809 for PE files described in + // https://randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/. + // We've also observed oddly empty files on other Windows versions, so + // this is unconditional. + target_file.Flush(); } }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index a4a9d562..6ff4045 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2963,7 +2963,7 @@ testonly = true data_deps = [ "//testing:run_perf_test" ] if (build_dawn_tests) { - data_deps += [ "//third_party/dawn:dawn_perf_tests_temp_group" ] + data_deps += [ "//third_party/dawn/src/tests:dawn_perf_tests" ] } } @@ -5425,6 +5425,7 @@ "../browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc", "../browser/supervised_user/child_accounts/permission_request_creator_apiary_unittest.cc", "../browser/supervised_user/kids_management_url_checker_client_unittest.cc", + "../browser/supervised_user/supervised_user_model_type_controller_unittest.cc", "../browser/supervised_user/supervised_user_pref_store_unittest.cc", "../browser/supervised_user/supervised_user_service_unittest.cc", "../browser/supervised_user/supervised_user_settings_service_unittest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index b95c647..57f385f8 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -208,6 +208,7 @@ "//chrome/android/third_party/compositor_animator:compositor_animator_java", "//chrome/browser/flags:java", "//chrome/browser/preferences:java", + "//chrome/browser/tab:java", "//chrome/browser/ui/android/appmenu:java", "//chrome/browser/ui/android/appmenu:test_support_java", "//chrome/browser/ui/android/favicon:java",
diff --git a/chrome/test/data/ad_tagging/create_frame.js b/chrome/test/data/ad_tagging/create_frame.js index 02314ad..ff0fb5cf 100644 --- a/chrome/test/data/ad_tagging/create_frame.js +++ b/chrome/test/data/ad_tagging/create_frame.js
@@ -65,16 +65,21 @@ document.body.appendChild(frame); frame.contentWindow.stop(); - // We load the scripts in frame_factory.html to allow subframe creation. + // We load the scripts in frame_factory.html to allow subframe creation. We + // set the async attribute to false to ensure that these scripts are loaded in + // insertion order. let script1 = document.createElement('script'); + script1.async = false; script1.src = 'create_frame.js'; frame.contentDocument.head.appendChild(script1); let script2 = document.createElement('script'); + script1.async = false; script2.src = 'ad_script.js'; frame.contentDocument.head.appendChild(script2); let script3 = document.createElement('script'); + script1.async = false; script3.src = 'ad_script_2.js'; // Set title so we know when all scripts have loaded. script3.onload = function() {
diff --git a/chrome/test/data/content_index/content_index.js b/chrome/test/data/content_index/content_index.js index 637c4d3..04d49086 100644 --- a/chrome/test/data/content_index/content_index.js +++ b/chrome/test/data/content_index/content_index.js
@@ -22,7 +22,7 @@ icons: [{ src: '/anchor_download_test.png', }], - launchUrl: '/content_index/content_index.html?launch', + url: '/content_index/content_index.html?launch', }); }
diff --git a/chrome/test/data/origin_policy_browsertest/OWNERS b/chrome/test/data/origin_policy_browsertest/OWNERS index cc8f52f4..41bfb92e 100644 --- a/chrome/test/data/origin_policy_browsertest/OWNERS +++ b/chrome/test/data/origin_policy_browsertest/OWNERS
@@ -1 +1 @@ -file://third_party/blink/common/origin_policy/OWNERS +file://services/network/origin_policy/OWNERS
diff --git a/chrome/test/origin_policy/OWNERS b/chrome/test/origin_policy/OWNERS index b0812f6..9f5e5e7 100644 --- a/chrome/test/origin_policy/OWNERS +++ b/chrome/test/origin_policy/OWNERS
@@ -1,2 +1,2 @@ -file://third_party/blink/common/origin_policy/OWNERS +file://services/network/origin_policy/OWNERS # COMPONENT: Blink>SecurityFeature
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn index 05c97d1..295598b 100644 --- a/chrome/updater/BUILD.gn +++ b/chrome/updater/BUILD.gn
@@ -215,7 +215,10 @@ deps += [ "//chrome/updater/win:updater_tests" ] - data_deps = [ "//chrome/updater/win:updater" ] + data_deps = [ + "//chrome/updater/win:updater", + "//chrome/updater/win/installer", + ] } if (is_mac) {
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc index a763b94d..8453215 100644 --- a/chrome/updater/test/integration_tests.cc +++ b/chrome/updater/test/integration_tests.cc
@@ -4,6 +4,7 @@ #include "chrome/updater/test/integration_tests.h" +#include "base/test/task_environment.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -22,15 +23,12 @@ ExpectClean(); Clean(); } + + private: + base::test::TaskEnvironment environment_; }; -// TODO(crbug.com/1063064): Fix the test on Windows. -#if defined(OS_WIN) -#define MAYBE_InstallUninstall DISABLED_InstallUninstall -#else -#define MAYBE_InstallUninstall InstallUninstall -#endif -TEST_F(IntegrationTest, MAYBE_InstallUninstall) { +TEST_F(IntegrationTest, InstallUninstall) { Install(); ExpectInstalled(); Uninstall();
diff --git a/chrome/updater/test/integration_tests_win.cc b/chrome/updater/test/integration_tests_win.cc index efe49a3..3035eacd 100644 --- a/chrome/updater/test/integration_tests_win.cc +++ b/chrome/updater/test/integration_tests_win.cc
@@ -8,6 +8,9 @@ #include "base/path_service.h" #include "base/process/launch.h" #include "base/process/process.h" +#include "base/synchronization/waitable_event.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "chrome/updater/updater_version.h" #include "chrome/updater/util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,6 +35,15 @@ if (!process.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(60), exit_code)) return false; + base::WaitableEvent sleep(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + // The process will exit before it is done uninstalling: sleep for five + // seconds to allow uninstall to complete. + base::ThreadPool::PostDelayedTask( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&sleep)), + base::TimeDelta::FromSeconds(5)); + sleep.Wait(); return true; } @@ -68,7 +80,7 @@ // Files must not exist on the file system. - // EXPECT_FALSE(base::PathExists(GetProductPath())); + EXPECT_FALSE(base::PathExists(GetProductPath())); } void ExpectInstalled() {
diff --git a/chrome/updater/win/BUILD.gn b/chrome/updater/win/BUILD.gn index ee66bf8..21949b8 100644 --- a/chrome/updater/win/BUILD.gn +++ b/chrome/updater/win/BUILD.gn
@@ -2,7 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/util/process_version.gni") import("//chrome/process_version_rc_template.gni") +import("//chrome/updater/branding.gni") import("//testing/test.gni") # This target builds the updater executable, its installer, and unittests. @@ -33,9 +35,16 @@ data_deps = [ ":uninstall.cmd" ] } -copy("uninstall.cmd") { - sources = [ "setup/uninstall.cmd" ] - outputs = [ "$target_gen_dir/uninstall.cmd" ] +process_version("uninstall.cmd") { + template_file = "setup/uninstall.cmd" + output = "$target_gen_dir/uninstall.cmd" + process_only = true + extra_args = [ + "-e", + "PRODUCT_FULLNAME=\"$updater_product_full_name\"", + "-e", + "COMPANY_SHORTNAME=\"$updater_company_short_name\"", + ] } process_version_rc_template("version_resources") {
diff --git a/chrome/updater/win/setup/uninstall.cmd b/chrome/updater/win/setup/uninstall.cmd index bbaf5ce6c..32457c98 100644 --- a/chrome/updater/win/setup/uninstall.cmd +++ b/chrome/updater/win/setup/uninstall.cmd
@@ -1,9 +1,10 @@ -rem Deletes the script's parent directory if \AppData\Local\ChromeUpdater\ is -rem anywhere in the directory path. Sleeps 3 seconds and tries 3 times to -rem delete the directory. +rem Deletes the script's parent directory if +rem \AppData\Local\@COMPANY_SHORTNAME@\@PRODUCT_FULLNAME@\ is anywhere in the +rem directory path. Sleeps 3 seconds and tries 3 times to delete the +rem directory. @echo off set Directory=%~dp0 -@echo %Directory% | FindStr /R \\AppData\\Local\\Google\\GoogleUpdater\\ > nul +@echo %Directory% | FindStr /R \\AppData\\Local\\@COMPANY_SHORTNAME@\\@PRODUCT_FULLNAME@\\ > nul IF %ERRORLEVEL% NEQ 0 exit 1 @echo Deleting "%Directory%"... for /L %%G IN (1,1,3) do (
diff --git a/chromecast/browser/DEPS b/chromecast/browser/DEPS index 74768e0..7fd9bbee 100644 --- a/chromecast/browser/DEPS +++ b/chromecast/browser/DEPS
@@ -16,6 +16,7 @@ "+components/cdm/browser", "+components/crash", "+components/download/public/common", + "+components/exo", "+components/heap_profiling", "+components/keyed_service", "+components/network_hints",
diff --git a/chromecast/browser/ui/aura/accessibility/ax_tree_source_aura.cc b/chromecast/browser/ui/aura/accessibility/ax_tree_source_aura.cc index 6ca2402..c1d2a7a 100644 --- a/chromecast/browser/ui/aura/accessibility/ax_tree_source_aura.cc +++ b/chromecast/browser/ui/aura/accessibility/ax_tree_source_aura.cc
@@ -7,6 +7,9 @@ #include "chromecast/browser/accessibility/accessibility_manager.h" #include "chromecast/browser/cast_browser_process.h" #include "chromecast/browser/ui/aura/accessibility/automation_manager_aura.h" +#include "components/exo/fullscreen_shell_surface.h" +#include "components/exo/shell_surface_util.h" +#include "components/exo/surface.h" #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/ax_tree_data.h" @@ -14,17 +17,20 @@ #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/views/accessibility/ax_aura_obj_wrapper.h" +#include "ui/views/accessibility/ax_view_obj_wrapper.h" AXTreeSourceAura::AXTreeSourceAura(views::AXAuraObjWrapper* root, const ui::AXTreeID& tree_id, views::AXAuraObjCache* cache) - : AXTreeSourceViews(root, tree_id, cache) {} + : AXTreeSourceViews(root, tree_id, cache), cache_(cache) {} AXTreeSourceAura::~AXTreeSourceAura() = default; bool AXTreeSourceAura::GetTreeData(ui::AXTreeData* tree_data) const { AXTreeSourceViews::GetTreeData(tree_data); + // TODO(b/1069055) : This is a temporary solution to override the + // superclass method which does not set the correct focus_id. aura::Window* root_window = chromecast::shell::CastBrowserProcess::GetInstance() ->accessibility_manager() @@ -35,8 +41,37 @@ aura::client::GetFocusClient(root_window); if (focus_client) { aura::Window* window = focus_client->GetFocusedWindow(); - tree_data->focus_id = - AutomationManagerAura::GetInstance()->GetIDFromWindow(window); + tree_data->focus_id = ui::AXNode::kInvalidAXID; + + // Search for the full screen shell surface that holds the child + // tree for our UI. This is the node that should receive focus. + if (window) { + std::stack<aura::Window*> stack; + stack.push(window); + while (!stack.empty()) { + aura::Window* top = stack.top(); + stack.pop(); + DCHECK(top); + + exo::Surface* surface = exo::GetShellMainSurface(top); + if (surface) { + views::Widget* widget = + views::Widget::GetWidgetForNativeWindow(top); + if (widget) { + exo::FullscreenShellSurface* full_screen_shell_surface = + static_cast<exo::FullscreenShellSurface*>( + widget->widget_delegate()); + tree_data->focus_id = cache_->GetID(full_screen_shell_surface); + break; + } + } + for (aura::Window* child : top->children()) + stack.push(child); + } + if (tree_data->focus_id == -1) { + LOG(ERROR) << "Could not find node to focus in desktop tree."; + } + } } } return true;
diff --git a/chromecast/browser/ui/aura/accessibility/ax_tree_source_aura.h b/chromecast/browser/ui/aura/accessibility/ax_tree_source_aura.h index 1e78bf57..7f774aa5 100644 --- a/chromecast/browser/ui/aura/accessibility/ax_tree_source_aura.h +++ b/chromecast/browser/ui/aura/accessibility/ax_tree_source_aura.h
@@ -25,6 +25,8 @@ ui::AXNodeData* out_data) const override; private: + views::AXAuraObjCache* cache_; + DISALLOW_COPY_AND_ASSIGN(AXTreeSourceAura); };
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 59c33e9..83c6789 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13038.0.0 \ No newline at end of file +13039.0.0 \ No newline at end of file
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index 910e60b0..73124fc7 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -154,6 +154,10 @@ const base::Feature kEduCoexistence{"EduCoexistence", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables parent consent logging in EDU account addition flow. +const base::Feature kEduCoexistenceConsentLog{ + "EduCoexistenceConsentLog", base::FEATURE_DISABLED_BY_DEFAULT}; + // If enabled, emoji suggestion will be shown when user type "space". const base::Feature kEmojiSuggestAddition{"EmojiSuggestAddition", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index bfbef5a7..249ff9548 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -80,6 +80,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kEduCoexistence; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +extern const base::Feature kEduCoexistenceConsentLog; +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kExoPointerLock; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kFilesNG; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kMojoDBusRelay;
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc b/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc index 4e1fbb4..875150ea 100644 --- a/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc +++ b/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc
@@ -117,9 +117,9 @@ return mojom::CpuResult::NewCpuInfo(std::move(cpu_info)); } -mojom::TimezoneInfoPtr MakeTimezoneInfo() { - return mojom::TimezoneInfo::New("MST7MDT,M3.2.0,M11.1.0" /* posix */, - "America/Denver" /* region */); +mojom::TimezoneResultPtr MakeTimezoneResult() { + return mojom::TimezoneResult::NewTimezoneInfo(mojom::TimezoneInfo::New( + "MST7MDT,M3.2.0,M11.1.0" /* posix */, "America/Denver" /* region */)); } mojom::MemoryInfoPtr MakeMemoryInfo() { @@ -138,11 +138,11 @@ return backlight_info; } -base::Optional<std::vector<mojom::FanInfoPtr>> MakeFanInfo() { - std::vector<mojom::FanInfoPtr> fan_info; - fan_info.push_back(mojom::FanInfo::New(1200 /* speed_rpm */)); - fan_info.push_back(mojom::FanInfo::New(2650 /* speed_rpm */)); - return fan_info; +mojom::FanResultPtr MakeFanResult() { + std::vector<mojom::FanInfoPtr> fan_vector; + fan_vector.push_back(mojom::FanInfo::New(1200 /* speed_rpm */)); + fan_vector.push_back(mojom::FanInfo::New(2650 /* speed_rpm */)); + return mojom::FanResult::NewFanInfo(std::move(fan_vector)); } mojom::TelemetryInfoPtr MakeTelemetryInfo() { @@ -150,9 +150,9 @@ MakeBatteryInfo() /* battery_info */, MakeNonRemovableBlockDeviceInfo() /* block_device_info */, MakeCachedVpdInfo() /* vpd_info */, MakeCpuResult() /* cpu_result */, - MakeTimezoneInfo() /* timezone_info */, + MakeTimezoneResult() /* timezone_result */, MakeMemoryInfo() /* memory_info */, - MakeBacklightInfo() /* backlight_info */, MakeFanInfo() /* fan_info */ + MakeBacklightInfo() /* backlight_info */, MakeFanResult() /* fan_result */ ); }
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom b/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom index d22fb65..8f42697 100644 --- a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom +++ b/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
@@ -38,6 +38,8 @@ kFileReadError, // An error parsing data into a consumable form. kParseError, + // An error using a system utility. + kSystemUtilityError, }; // Structure that contains error information for a telemetry probe. @@ -131,6 +133,15 @@ uint32 max_clock_speed_khz; }; +// Timezone probe result. Can either be populated with the TimezoneInfo or an +// error retrieving the information. +union TimezoneResult { + // Valid TimezoneInfo. + TimezoneInfo timezone_info; + // The error that occurred attempting to retrieve the TimezoneInfo. + ProbeError error; +}; + // Timezone information. struct TimezoneInfo { // The timezone of the device in POSIX standard. @@ -162,6 +173,15 @@ uint32 brightness; }; +// Fan probe result. Can either be populated with the FanInfo or an error +// retrieving the information +union FanResult { + // A list of valid FanInfo. + array<FanInfo> fan_info; + // The error that occurred attempting to retrieve the FanInfo. + ProbeError error; +}; + // Fan information. struct FanInfo { // Fan speed in RPM. @@ -191,7 +211,7 @@ CpuResult? cpu_result; // Information about the device's timezone. Only present when kTimezone was // included in the categories input to ProbeTelemetryInfo. - TimezoneInfo? timezone_info; + TimezoneResult? timezone_result; // Information about the system's memory. Only present when kMemory was // included in the categories input to ProbeTelemetryInfo. MemoryInfo? memory_info; @@ -200,5 +220,5 @@ array<BacklightInfo>? backlight_info; // Information about each of the device's fans. Only present when kFan was // included in the categories input to ProbeTelemetryInfo. - array<FanInfo>? fan_info; + FanResult? fan_result; };
diff --git a/components/autofill/core/browser/address_rewriter.cc b/components/autofill/core/browser/address_rewriter.cc index 1b85a50..030a5ab 100644 --- a/components/autofill/core/browser/address_rewriter.cc +++ b/components/autofill/core/browser/address_rewriter.cc
@@ -57,7 +57,7 @@ CompiledRuleVector* compiled_rules) { base::StringPiece data = data_string; re2::RE2::Options options; - options.set_utf8(true); + options.set_encoding(RE2::Options::EncodingUTF8); options.set_word_boundary(true); size_t token_end = 0;
diff --git a/components/autofill/core/browser/geo/autofill_country.cc b/components/autofill/core/browser/geo/autofill_country.cc index 4eb8f2b..961b1dc 100644 --- a/components/autofill/core/browser/geo/autofill_country.cc +++ b/components/autofill/core/browser/geo/autofill_country.cc
@@ -25,13 +25,28 @@ AutofillCountry::AutofillCountry(const std::string& country_code, const std::string& locale) { - auto result = - CountryDataMap::GetInstance()->country_data().find(country_code); - DCHECK(result != CountryDataMap::GetInstance()->country_data().end()); - const CountryData& data = result->second; + CountryDataMap* country_data_map = CountryDataMap::GetInstance(); - country_code_ = country_code; - name_ = l10n_util::GetDisplayNameForCountry(country_code, locale); + // If the country code is an alias (e.g. "GB" for "UK") expand the country + // code. + country_code_ = country_data_map->HasCountryCodeAlias(country_code) + ? country_data_map->GetCountryCodeForAlias(country_code) + : country_code; + + // If there is no entry in the |CountryDataMap| for the + // |country_code_for_country_data| use the country code derived from the + // locale. This reverts to US. + country_data_map->HasCountryData(country_code_) + ? country_code_ + : CountryCodeForLocale(locale); + + // Acquire the country address data. + const CountryData& data = country_data_map->GetCountryData(country_code_); + + // Translate the country name by the supplied local. + name_ = l10n_util::GetDisplayNameForCountry(country_code_, locale); + + // Get the localized strings associate with the address fields. postal_code_label_ = l10n_util::GetStringUTF16(data.postal_code_label_id); state_label_ = l10n_util::GetStringUTF16(data.state_label_id); address_required_fields_ = data.address_required_fields;
diff --git a/components/autofill/core/browser/geo/autofill_country_unittest.cc b/components/autofill/core/browser/geo/autofill_country_unittest.cc index 8f3994d..94315c1 100644 --- a/components/autofill/core/browser/geo/autofill_country_unittest.cc +++ b/components/autofill/core/browser/geo/autofill_country_unittest.cc
@@ -14,6 +14,7 @@ #include "base/android/build_info.h" #endif +using autofill::CountryDataMap; using base::ASCIIToUTF16; namespace autofill { @@ -30,6 +31,11 @@ EXPECT_EQ("US", united_states_es.country_code()); EXPECT_EQ(ASCIIToUTF16("Estados Unidos"), united_states_es.name()); + AutofillCountry great_britain_uk_alias("UK", "en_GB"); + EXPECT_EQ("GB", great_britain_uk_alias.country_code()); + EXPECT_EQ("GB", great_britain_uk_alias.country_code()); + EXPECT_EQ(ASCIIToUTF16("United Kingdom"), great_britain_uk_alias.name()); + AutofillCountry canada_en("CA", "en_US"); EXPECT_EQ("CA", canada_en.country_code()); EXPECT_EQ(ASCIIToUTF16("Canada"), canada_en.name()); @@ -74,4 +80,27 @@ } } +// Test alias mappings for falsely existing country codes. +TEST(AutofillCountryTest, AliasMappingsForCountryData) { + CountryDataMap* country_data_map = CountryDataMap::GetInstance(); + + // There should be country data for the "GB". + EXPECT_TRUE(country_data_map->HasCountryData("GB")); + + // Check the correctness of the alias definitions. + EXPECT_TRUE(country_data_map->HasCountryCodeAlias("UK")); + EXPECT_FALSE(country_data_map->HasCountryCodeAlias("does_not_exist")); + + // Query not existing mapping. + auto expected_country_code = std::string(); + auto actual_country_code = + country_data_map->GetCountryCodeForAlias("does_not_exist"); + EXPECT_EQ(expected_country_code, actual_country_code); + + // GB should map the UK. + expected_country_code = "GB"; + actual_country_code = country_data_map->GetCountryCodeForAlias("UK"); + EXPECT_EQ(expected_country_code, actual_country_code); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/geo/country_data.cc b/components/autofill/core/browser/geo/country_data.cc index 1105e78..e00e620 100644 --- a/components/autofill/core/browser/geo/country_data.cc +++ b/components/autofill/core/browser/geo/country_data.cc
@@ -19,6 +19,17 @@ CountryData country_data; }; +// Alias definitions record for CountryData requests. A request for +// |country_code_alias| is served with the |CountryData| for +// |country_code_target|. +struct StaticCountryCodeAliasData { + char country_code_alias[3]; + char country_code_target[3]; +}; + +// Alias definitions. +const StaticCountryCodeAliasData kCountryCodeAliases[] = {{"UK", "GB"}}; + // Maps country codes to localized label string identifiers. Keep this sorted // by country code. // This list is comprized of countries appearing in both @@ -790,7 +801,7 @@ return country_codes; } -std::map<std::string, CountryData> GetCountryData() { +std::map<std::string, CountryData> GetCountryDataMap() { std::map<std::string, CountryData> country_data; // Add all the countries we have explicit data for. for (const auto& static_data : kCountryData) { @@ -813,6 +824,18 @@ return country_data; } +std::map<std::string, std::string> GetCountryCodeAliasMap() { + std::map<std::string, std::string> country_code_aliases; + // Create mappings for the aliases defined in |kCountryCodeAliases|. + for (const auto& static_alias_data : kCountryCodeAliases) { + // Insert the alias. + country_code_aliases.insert( + std::make_pair(std::string(static_alias_data.country_code_alias), + std::string(static_alias_data.country_code_target))); + } + return country_code_aliases; +} + } // namespace // static @@ -821,8 +844,38 @@ } CountryDataMap::CountryDataMap() - : country_data_(GetCountryData()), country_codes_(GetCountryCodes()) {} + : country_data_(GetCountryDataMap()), + country_code_aliases_(GetCountryCodeAliasMap()), + country_codes_(GetCountryCodes()) {} CountryDataMap::~CountryDataMap() = default; +bool CountryDataMap::HasCountryData(const std::string& country_code) const { + return country_data_.count(country_code) > 0; +} + +const CountryData& CountryDataMap::GetCountryData( + const std::string& country_code) const { + auto lookup = country_data_.find(country_code); + if (lookup != country_data_.end()) + return lookup->second; + // If there is no entry for country_code return the entry for the US. + return country_data_.find("US")->second; +} + +bool CountryDataMap::HasCountryCodeAlias( + const std::string& country_code_alias) const { + return country_code_aliases_.count(country_code_alias) > 0; +} + +const std::string CountryDataMap::GetCountryCodeForAlias( + const std::string& country_code_alias) const { + auto lookup = country_code_aliases_.find(country_code_alias); + if (lookup != country_code_aliases_.end()) { + DCHECK(HasCountryData(lookup->second)); + return lookup->second; + } + return std::string(); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/geo/country_data.h b/components/autofill/core/browser/geo/country_data.h index b6a9497..8266102 100644 --- a/components/autofill/core/browser/geo/country_data.h +++ b/components/autofill/core/browser/geo/country_data.h
@@ -58,10 +58,23 @@ public: static CountryDataMap* GetInstance(); - const std::map<std::string, CountryData>& country_data() { - return country_data_; - } + // Returns true if a |CountryData| entry for the supplied |country_code| + // exists. + bool HasCountryData(const std::string& country_code) const; + // Returns true if there is a country code alias for |country_code|. + bool HasCountryCodeAlias(const std::string& country_code_alias) const; + + // Returns the country code for a country code alias. If no alias definition + // is present return an empty string. + const std::string GetCountryCodeForAlias( + const std::string& country_code_alias) const; + + // Lookup the |CountryData| for the supplied |country_code|. If no entry + // exists, return the data for the US as a best guess. + const CountryData& GetCountryData(const std::string& country_code) const; + + // Return a constant reference to a vector of all country codes. const std::vector<std::string>& country_codes() { return country_codes_; } private: @@ -70,6 +83,7 @@ friend struct base::DefaultSingletonTraits<CountryDataMap>; const std::map<std::string, CountryData> country_data_; + const std::map<std::string, std::string> country_code_aliases_; const std::vector<std::string> country_codes_; DISALLOW_COPY_AND_ASSIGN(CountryDataMap);
diff --git a/components/autofill/core/browser/ui/popup_item_ids.h b/components/autofill/core/browser/ui/popup_item_ids.h index 4d7333b..f975bc36 100644 --- a/components/autofill/core/browser/ui/popup_item_ids.h +++ b/components/autofill/core/browser/ui/popup_item_ids.h
@@ -34,6 +34,7 @@ POPUP_ITEM_ID_ACCOUNT_STORAGE_PASSWORD_ENTRY = -22, POPUP_ITEM_ID_ACCOUNT_STORAGE_USERNAME_ENTRY = -23, POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_RE_SIGNIN = -24, + POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY = -25, }; } // namespace autofill
diff --git a/components/os_crypt/key_storage_libsecret.cc b/components/os_crypt/key_storage_libsecret.cc index 975a69e..a0aa3d0 100644 --- a/components/os_crypt/key_storage_libsecret.cc +++ b/components/os_crypt/key_storage_libsecret.cc
@@ -19,14 +19,6 @@ const char kApplicationName[] = "chromium"; #endif -// Deprecated in M55 (crbug.com/639298) -const SecretSchema kKeystoreSchemaV1 = { - "chrome_libsecret_os_crypt_password", - SECRET_SCHEMA_NONE, - { - {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING}, - }}; - const SecretSchema kKeystoreSchemaV2 = { "chrome_libsecret_os_crypt_password_v2", SECRET_SCHEMA_DONT_MATCH_NAME, @@ -106,9 +98,6 @@ SecretValue* password_libsecret = ToSingleSecret(helper.results()); if (!password_libsecret) { - std::string password = Migrate(); - if (!password.empty()) - return password; return AddRandomPasswordInLibsecret(); } AnalyseKeyHistory(helper.results()); @@ -124,52 +113,3 @@ LibsecretLoader::EnsureKeyringUnlocked(); return loaded; } - -std::string KeyStorageLibsecret::Migrate() { - LibsecretAttributesBuilder attrs; - - // Detect old entry. - LibsecretLoader::SearchHelper helper; - helper.Search(&kKeystoreSchemaV1, attrs.Get(), - SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS); - if (!helper.success()) - return std::string(); - - SecretValue* password_libsecret = ToSingleSecret(helper.results()); - if (!password_libsecret) - return std::string(); - - VLOG(1) << "OSCrypt detected a deprecated password in Libsecret."; - std::string password( - LibsecretLoader::secret_value_get_text(password_libsecret)); - LibsecretLoader::secret_value_unref(password_libsecret); - - // Create new entry. - GError* error = nullptr; - bool success = LibsecretLoader::secret_password_store_sync( - &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), - nullptr, &error, "application", kApplicationName, nullptr); - if (error) { - VLOG(1) << "Failed to store migrated password. " << error->message; - g_error_free(error); - return std::string(); - } - if (!success) { - VLOG(1) << "Failed to store migrated password."; - return std::string(); - } - - // Delete old entry. - // Even if deletion failed, we have to use the password that we created. - success = LibsecretLoader::secret_password_clear_sync( - &kKeystoreSchemaV1, nullptr, &error, nullptr); - if (error) { - VLOG(1) << "OSCrypt failed to delete deprecated password. " - << error->message; - g_error_free(error); - } - - VLOG(1) << "OSCrypt migrated from deprecated password."; - - return password; -}
diff --git a/components/os_crypt/key_storage_libsecret.h b/components/os_crypt/key_storage_libsecret.h index 31cf0c7..3679633a 100644 --- a/components/os_crypt/key_storage_libsecret.h +++ b/components/os_crypt/key_storage_libsecret.h
@@ -25,12 +25,6 @@ private: std::string AddRandomPasswordInLibsecret(); - // TODO(crbug.com/639298) Older Chromium releases stored passwords with a - // problematic schema. Detect password entries with the old schema and migrate - // them to the new schema. Returns the migrated password or an empty string if - // none we migrated. - std::string Migrate(); - DISALLOW_COPY_AND_ASSIGN(KeyStorageLibsecret); };
diff --git a/components/os_crypt/key_storage_libsecret_unittest.cc b/components/os_crypt/key_storage_libsecret_unittest.cc index b2e1bf8..60749878 100644 --- a/components/os_crypt/key_storage_libsecret_unittest.cc +++ b/components/os_crypt/key_storage_libsecret_unittest.cc
@@ -14,13 +14,6 @@ namespace { -const SecretSchema kKeystoreSchemaV1 = { - "chrome_libsecret_os_crypt_password", - SECRET_SCHEMA_NONE, - { - {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING}, - }}; - const SecretSchema kKeystoreSchemaV2 = { "chrome_libsecret_os_crypt_password_v2", SECRET_SCHEMA_DONT_MATCH_NAME, @@ -41,8 +34,7 @@ public: void Reset() { mapping_.clear(); - ClearV1Password(); - ClearV2Password(); + ClearPassword(); for (GObject* o : objects_returned_to_caller_) { ASSERT_EQ(o->ref_count, 1u); g_object_unref(o); @@ -50,31 +42,18 @@ objects_returned_to_caller_.clear(); } - void ClearV1Password() { - if (v1_password_) { - ASSERT_EQ(v1_password_->ref_count, 1u); - g_object_unref(v1_password_); - v1_password_ = nullptr; - } - } - void ClearV2Password() { - if (v2_password_) { - ASSERT_EQ(v2_password_->ref_count, 1u); - g_object_unref(v2_password_); - v2_password_ = nullptr; + void ClearPassword() { + if (password_) { + ASSERT_EQ(password_->ref_count, 1u); + g_object_unref(password_); + password_ = nullptr; } } - void SetV1Password(const std::string& password) { - ASSERT_FALSE(v1_password_); - v1_password_ = static_cast<GObject*>(g_object_new(G_TYPE_OBJECT, nullptr)); - mapping_[v1_password_] = password; - } - - void SetV2Password(const std::string& password) { - ASSERT_FALSE(v2_password_); - v2_password_ = static_cast<GObject*>(g_object_new(G_TYPE_OBJECT, nullptr)); - mapping_[v2_password_] = password; + void SetPassword(const std::string& password) { + ASSERT_FALSE(password_); + password_ = static_cast<GObject*>(g_object_new(G_TYPE_OBJECT, nullptr)); + mapping_[password_] = password; } GObject* MakeTempObject(const std::string& value) { @@ -92,13 +71,11 @@ return mapping_[static_cast<GObject*>(opaque_id)].c_str(); } - GObject* v1_password() { return v1_password_; } - GObject* v2_password() { return v2_password_; } + GObject* password() { return password_; } std::unordered_map<GObject*, std::string> mapping_; std::vector<GObject*> objects_returned_to_caller_; - GObject* v1_password_ = nullptr; - GObject* v2_password_ = nullptr; + GObject* password_ = nullptr; }; base::LazyInstance<MockPasswordStore>::Leaky g_password_store = LAZY_INSTANCE_INITIALIZER; @@ -137,11 +114,6 @@ GCancellable* cancellable, GError** error); - static gboolean mock_secret_password_clear_sync(const SecretSchema* schema, - GCancellable* cancellable, - GError** error, - ...); - static SecretValue* mock_secret_item_get_secret(SecretItem* item); static guint64 mock_secret_item_get_created(SecretItem* item); @@ -168,7 +140,7 @@ return true; EXPECT_STREQ(kKeystoreSchemaV2.name, schema->name); - g_password_store.Pointer()->SetV2Password(password); + g_password_store.Pointer()->SetPassword(password); return true; } @@ -185,24 +157,16 @@ SecretSearchFlags flags, GCancellable* cancellable, GError** error) { - bool is_known_schema = strcmp(schema->name, kKeystoreSchemaV2.name) == 0 || - strcmp(schema->name, kKeystoreSchemaV1.name) == 0; - EXPECT_TRUE(is_known_schema); + EXPECT_STREQ(kKeystoreSchemaV2.name, schema->name); EXPECT_TRUE(flags & SECRET_SEARCH_UNLOCK); EXPECT_TRUE(flags & SECRET_SEARCH_LOAD_SECRETS); GObject* item = nullptr; MockPasswordStore* store = g_password_store.Pointer(); - if (strcmp(schema->name, kKeystoreSchemaV2.name) == 0) { - GObject* password = store->v2_password(); - if (password) - item = store->MakeTempObject(store->GetString(password)); - } else if (strcmp(schema->name, kKeystoreSchemaV1.name) == 0) { - GObject* password = store->v1_password(); - if (password) - item = store->MakeTempObject(store->GetString(password)); - } + GObject* password = store->password(); + if (password) + item = store->MakeTempObject(store->GetString(password)); if (!item) { return nullptr; @@ -215,18 +179,6 @@ } // static -gboolean MockLibsecretLoader::mock_secret_password_clear_sync( - const SecretSchema* schema, - GCancellable* cancellable, - GError** error, - ...) { - // We would only delete entries in the deprecated schema. - EXPECT_STREQ(kKeystoreSchemaV1.name, schema->name); - g_password_store.Pointer()->ClearV1Password(); - return true; -} - -// static SecretValue* MockLibsecretLoader::mock_secret_item_get_secret( SecretItem* item) { // Add a ref to make sure that the caller unrefs with secret_value_unref. @@ -254,9 +206,6 @@ secret_service_search_sync = &MockLibsecretLoader::mock_secret_service_search_sync; secret_item_get_secret = &MockLibsecretLoader::mock_secret_item_get_secret; - // Used by Migrate() - secret_password_clear_sync = - &MockLibsecretLoader::mock_secret_password_clear_sync; secret_item_get_created = &MockLibsecretLoader::mock_secret_item_get_created; secret_item_get_modified = &MockLibsecretLoader::mock_secret_item_get_modified; @@ -290,7 +239,7 @@ TEST_F(LibsecretTest, LibsecretRepeats) { KeyStorageLibsecret libsecret; MockLibsecretLoader::ResetForOSCrypt(); - g_password_store.Pointer()->SetV2Password("initial password"); + g_password_store.Pointer()->SetPassword("initial password"); std::string password = libsecret.GetKey(); EXPECT_FALSE(password.empty()); std::string password_repeat = libsecret.GetKey(); @@ -306,13 +255,4 @@ EXPECT_NE(password, password_new); } -TEST_F(LibsecretTest, LibsecretMigratesFromSchemaV1ToV2) { - KeyStorageLibsecret libsecret; - MockLibsecretLoader::ResetForOSCrypt(); - g_password_store.Pointer()->SetV1Password("swallow"); - g_password_store.Pointer()->ClearV2Password(); - std::string password = libsecret.GetKey(); - EXPECT_EQ("swallow", password); -} - } // namespace
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc index 7929c2d..b896caf4 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.cc +++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -112,6 +112,7 @@ } void ContentPasswordManagerDriver::InformNoSavedCredentials() { + GetPasswordAutofillManager()->OnNoCredentialsFound(); GetPasswordAutofillAgent()->InformNoSavedCredentials(); }
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index 311a692..d6b0a90 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -392,12 +392,60 @@ "here."; } +// Callback called upon each migration step of the logins table. It's used to +// inject custom schema migration logic not covered by the generic +// SQLTableBuilder migration. |new_version| indicates how far +// SQLTableBuilder is in the migration process. +bool LoginsTablePostMigrationStepCallback(sql::Database* db, + unsigned new_version) { + // In version 26, the primary key of the logins table became an + // AUTOINCREMENT field. Since SQLite doesn't allow changing the column type, + // the only way is to actually create a temp table with the primary key + // properly set as an AUTOINCREMENT field, and move the data there. The code + // has been adjusted such that newly created tables have the primary key + // properly set as AUTOINCREMENT. + if (new_version == 26) { + // This statement creates the logins database similar to version 26 with + // the primary key column set to AUTOINCREMENT. + const char temp_table_create_statement_version_26[] = + "CREATE TABLE logins_temp (origin_url VARCHAR NOT NULL,action_url " + "VARCHAR,username_element VARCHAR,username_value " + "VARCHAR,password_element VARCHAR,password_value BLOB,submit_element " + "VARCHAR,signon_realm VARCHAR NOT NULL,preferred INTEGER NOT " + "NULL,date_created INTEGER NOT NULL,blacklisted_by_user INTEGER NOT " + "NULL,scheme INTEGER NOT NULL,password_type INTEGER,times_used " + "INTEGER,form_data BLOB,date_synced INTEGER,display_name " + "VARCHAR,icon_url VARCHAR,federation_url VARCHAR,skip_zero_click " + "INTEGER,generation_upload_status INTEGER,possible_username_pairs " + "BLOB,id INTEGER PRIMARY KEY AUTOINCREMENT,date_last_used " + "INTEGER,UNIQUE (origin_url, username_element, username_value, " + "password_element, signon_realm))"; + const char move_data_statement[] = + "INSERT INTO logins_temp SELECT * from logins"; + const char drop_table_statement[] = "DROP TABLE logins"; + const char rename_table_statement[] = + "ALTER TABLE logins_temp RENAME TO logins"; + + sql::Transaction transaction(db); + if (!(transaction.Begin() && + db->Execute(temp_table_create_statement_version_26) && + db->Execute(move_data_statement) && + db->Execute(drop_table_statement) && + db->Execute(rename_table_statement) && transaction.Commit())) { + return false; + } + } + return true; +} + // Call this after having called InitializeBuilders(), to migrate the database // from the current version to kCurrentVersionNumber. bool MigrateLogins(unsigned current_version, SQLTableBuilders builders, sql::Database* db) { - if (!builders.logins->MigrateFrom(current_version, db)) + if (!builders.logins->MigrateFrom( + current_version, db, + base::BindRepeating(&LoginsTablePostMigrationStepCallback))) return false; if (!builders.sync_entities_metadata->MigrateFrom(current_version, db)) @@ -453,45 +501,6 @@ return false; } - // In version 26, the primary key of the logins table became an AUTOINCREMENT - // field. Since SQLite doesn't allow changing the column type, the only way is - // to actually create a temp table with the primary key propely set as an - // AUTOINCREMENT field, and move the data there. The code has been adjusted - // such that newly created tables have the primary key properly set as - // AUTOINCREMENT. - if (current_version < 26) { - // This statement creates the logins database similar to version 26 with the - // primary key column set to AUTOINCREMENT. - std::string temp_table_create_statement_version_26 = - "CREATE TABLE logins_temp (origin_url VARCHAR NOT NULL,action_url " - "VARCHAR,username_element VARCHAR,username_value " - "VARCHAR,password_element VARCHAR,password_value BLOB,submit_element " - "VARCHAR,signon_realm VARCHAR NOT NULL,preferred INTEGER NOT " - "NULL,date_created INTEGER NOT NULL,blacklisted_by_user INTEGER NOT " - "NULL,scheme INTEGER NOT NULL,password_type INTEGER,times_used " - "INTEGER,form_data BLOB,date_synced INTEGER,display_name " - "VARCHAR,icon_url VARCHAR,federation_url VARCHAR,skip_zero_click " - "INTEGER,generation_upload_status INTEGER,possible_username_pairs " - "BLOB,id INTEGER PRIMARY KEY AUTOINCREMENT,date_last_used " - "INTEGER,UNIQUE (origin_url, username_element, username_value, " - "password_element, signon_realm))"; - std::string move_data_statement = - "INSERT INTO logins_temp SELECT * from logins"; - std::string drop_table_statement = "DROP TABLE logins"; - std::string rename_table_statement = - "ALTER TABLE logins_temp RENAME TO logins"; - - sql::Transaction transaction(db); - if (!(transaction.Begin() && - db->Execute(temp_table_create_statement_version_26.c_str()) && - db->Execute(move_data_statement.c_str()) && - db->Execute(drop_table_statement.c_str()) && - db->Execute(rename_table_statement.c_str()) && - transaction.Commit())) { - return false; - } - } - return true; }
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc index 9690704d..3dc0b88 100644 --- a/components/password_manager/core/browser/password_autofill_manager.cc +++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -260,6 +260,16 @@ return suggestion; } +// Entry showing the empty state (i.e. no passwords found in account-storage). +autofill::Suggestion CreateAccountStorageEmptyEntry() { + autofill::Suggestion suggestion( + l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_NO_ACCOUNT_STORE_MATCHES)); + suggestion.frontend_id = + autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY; + suggestion.icon = "empty"; + return suggestion; +} + bool ContainsOtherThanManagePasswords( const std::vector<autofill::Suggestion> suggestions) { return std::any_of(suggestions.begin(), suggestions.end(), @@ -278,6 +288,15 @@ }); } +bool HasLoadingSuggestion(base::span<const autofill::Suggestion> suggestions, + autofill::PopupItemId item_id) { + return std::any_of(suggestions.begin(), suggestions.end(), + [&item_id](const autofill::Suggestion& suggestion) { + return suggestion.frontend_id == item_id && + suggestion.is_loading; + }); +} + std::vector<autofill::Suggestion> SetUnlockLoadingState( base::span<const autofill::Suggestion> suggestions, autofill::PopupItemId unlock_item, @@ -329,6 +348,7 @@ int identifier) { ClearPreviewedForm(); if (identifier == autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY || + identifier == autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY || identifier == autofill::POPUP_ITEM_ID_GENERATE_PASSWORD_ENTRY || identifier == autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN || identifier == @@ -375,7 +395,9 @@ metrics_util::LogPasswordDropdownItemSelected( PasswordDropdownSelectedOption::kGenerate, password_client_->IsIncognito()); - } else if (identifier == autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY) { + } else if (identifier == autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY || + identifier == + autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY) { password_client_->NavigateToManagePasswordsPage( ManagePasswordsReferrer::kPasswordDropdown); metrics_util::LogContextOfShowAllSavedPasswordsAccepted( @@ -461,7 +483,6 @@ if (!autofill_client_ || autofill_client_->GetPopupSuggestions().empty()) return; - // TODO(https://crbug.com/1043963): Add empty state. UpdatePopup(BuildSuggestions(base::string16(), ForPasswordField(AreSuggestionForPasswordField( autofill_client_->GetPopupSuggestions())), @@ -469,6 +490,15 @@ ShowPasswordSuggestions(true))); } +void PasswordAutofillManager::OnNoCredentialsFound() { + if (!autofill_client_ || + !HasLoadingSuggestion( + autofill_client_->GetPopupSuggestions(), + autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN)) + return; + UpdatePopup({CreateAccountStorageEmptyEntry()}); +} + void PasswordAutofillManager::DeleteFillData() { fill_data_.reset(); if (autofill_client_) { @@ -586,6 +616,7 @@ for (const auto& suggestion : suggestions) { switch (suggestion.frontend_id) { case autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY: + case autofill::PopupItemId::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY: metrics_util::LogContextOfShowAllSavedPasswordsShown( metrics_util::ShowAllSavedPasswordsContext::kPassword); continue; @@ -720,6 +751,8 @@ if (unlock_item == autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN_AND_GENERATE) { password_client_->GeneratePassword(); + autofill_client_->HideAutofillPopup( + autofill::PopupHidingReason::kAcceptSuggestion); } return; }
diff --git a/components/password_manager/core/browser/password_autofill_manager.h b/components/password_manager/core/browser/password_autofill_manager.h index 06075c8d..db91791 100644 --- a/components/password_manager/core/browser/password_autofill_manager.h +++ b/components/password_manager/core/browser/password_autofill_manager.h
@@ -94,6 +94,10 @@ // Called when main frame navigates. Not called for in-page navigations. void DidNavigateMainFrame(); + // Called if no suggestions were found. Assumed to be mutually exclusive with + // |OnAddPasswordFillData|. + void OnNoCredentialsFound(); + // A public version of FillSuggestion(), only for use in tests. bool FillSuggestionForTest(const base::string16& username);
diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc index 24470d9..8312aa9 100644 --- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc +++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -789,6 +789,9 @@ }); EXPECT_CALL(*client.GetPasswordFeatureManager(), SetAccountStorageOptIn(true)); + EXPECT_CALL( + autofill_client, + HideAutofillPopup(autofill::PopupHidingReason::kAcceptSuggestion)); EXPECT_CALL(client, GeneratePassword()); password_autofill_manager_->DidAcceptSuggestion( @@ -796,6 +799,39 @@ autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN_AND_GENERATE, 1); } +// Test that the popup shows an empty state if opted-into an empty store. +TEST_F(PasswordAutofillManagerTest, SuccessfullOptInMayShowEmptyState) { + TestPasswordManagerClient client; + NiceMock<MockAutofillClient> autofill_client; + InitializePasswordAutofillManager(&client, &autofill_client); + client.SetAccountStorageOptIn(true); + const CoreAccountId kAliceId = client.identity_test_env() + .SetUnconsentedPrimaryAccount(kAliceEmail) + .account_id; + testing::Mock::VerifyAndClearExpectations(&autofill_client); + + // Only the unlock button was available. After being clicked, it's in a + // loading state which the DeleteFillData() call will end. + Suggestion unlock_suggestion( + /*label=*/"Unlock passwords and fill", /*value=*/"", /*icon=*/"", + /*fronend_id=*/ + autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_OPT_IN); + unlock_suggestion.is_loading = Suggestion::IsLoading(true); + EXPECT_CALL(autofill_client, GetPopupSuggestions) + .WillRepeatedly(Return(std::vector<Suggestion>{unlock_suggestion})); + EXPECT_CALL(autofill_client, + HideAutofillPopup(autofill::PopupHidingReason::kStaleData)); + EXPECT_CALL( + autofill_client, + UpdatePopup( + SuggestionVectorIdsAre(ElementsAreArray( + {autofill::POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY})), + PopupType::kPasswords)); + + password_autofill_manager_->DeleteFillData(); + password_autofill_manager_->OnNoCredentialsFound(); +} + // Test that the popup is updated once "opt in and fill" is clicked". TEST_F(PasswordAutofillManagerTest, AddOnFillDataAfterOptInAndFillPopulatesPopup) { @@ -813,10 +849,11 @@ base::string16 additional_username(base::ASCIIToUTF16("bar.foo@example.com")); new_data.additional_logins[additional_username] = additional; EXPECT_CALL(autofill_client, GetPopupSuggestions()) - .Times(2) .WillRepeatedly(Return(CreateTestSuggestions( /*has_opt_in_and_fill=*/false, /*has_opt_in_and_generate*/ false, /*has_re_signin=*/false))); + EXPECT_CALL(autofill_client, + HideAutofillPopup(autofill::PopupHidingReason::kStaleData)); EXPECT_CALL( autofill_client, UpdatePopup( @@ -825,6 +862,8 @@ autofill::POPUP_ITEM_ID_PASSWORD_ENTRY, autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY}))), PopupType::kPasswords)); + + password_autofill_manager_->DeleteFillData(); password_autofill_manager_->OnAddPasswordFillData(new_data); }
diff --git a/components/password_manager/core/browser/sql_table_builder.cc b/components/password_manager/core/browser/sql_table_builder.cc index 36455d6..274789a7b 100644 --- a/components/password_manager/core/browser/sql_table_builder.cc +++ b/components/password_manager/core/browser/sql_table_builder.cc
@@ -196,11 +196,17 @@ return ++sealed_version_; } -bool SQLTableBuilder::MigrateFrom(unsigned old_version, - sql::Database* db) const { +bool SQLTableBuilder::MigrateFrom( + unsigned old_version, + sql::Database* db, + const base::RepeatingCallback<bool(sql::Database*, unsigned)>& + post_migration_step_callback) const { for (; old_version < sealed_version_; ++old_version) { if (!MigrateToNextFrom(old_version, db)) return false; + if (post_migration_step_callback && + !post_migration_step_callback.Run(db, old_version + 1)) + return false; } return true;
diff --git a/components/password_manager/core/browser/sql_table_builder.h b/components/password_manager/core/browser/sql_table_builder.h index 1c8f46c6..838b958 100644 --- a/components/password_manager/core/browser/sql_table_builder.h +++ b/components/password_manager/core/browser/sql_table_builder.h
@@ -1,6 +1,6 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. Use of this source -// code is governed by a BSD-style license that can be found in the LICENSE -// file. +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SQL_TABLE_BUILDER_H_ #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SQL_TABLE_BUILDER_H_ @@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/bind_helpers.h" #include "base/macros.h" #include "base/strings/string_piece.h" @@ -87,7 +88,17 @@ // Assuming that the database connected through |db| contains a table called // |table_name_| in a state described by version |old_version|, migrates it to // the current version, which must be sealed. Returns true on success. - bool MigrateFrom(unsigned old_version, sql::Database* db) const; + // |post_migration_step_callback| is executed after each migration step in to + // allow the calling site to inject custom logic to run upon each migration + // step from |old_version| to the current version. The passed parameter + // corresponds to database to be migrated and the new version number that has + // been reached after the migration step. |post_migration_step_callback| + // returns true on success, otherwise the migration is aborted. + bool MigrateFrom( + unsigned old_version, + sql::Database* db, + const base::RepeatingCallback<bool(sql::Database*, unsigned)>& + post_migration_step_callback = base::NullCallback()) const; // If |db| connects to a database where table |table_name_| already exists, // this is a no-op and returns true. Otherwise, |table_name_| is created in a
diff --git a/components/password_manager/core/browser/sql_table_builder_unittest.cc b/components/password_manager/core/browser/sql_table_builder_unittest.cc index 80c4408..d35786da 100644 --- a/components/password_manager/core/browser/sql_table_builder_unittest.cc +++ b/components/password_manager/core/browser/sql_table_builder_unittest.cc
@@ -7,11 +7,13 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/macros.h" +#include "base/test/mock_callback.h" #include "sql/database.h" #include "sql/statement.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::Return; using ::testing::UnorderedElementsAre; namespace password_manager { @@ -310,4 +312,26 @@ std::string::npos); } +TEST_F(SQLTableBuilderTest, MigrateFromWithSuccessfulCallback) { + EXPECT_EQ(0u, builder()->SealVersion()); + EXPECT_EQ(1u, builder()->SealVersion()); + + base::MockCallback<base::RepeatingCallback<bool(sql::Database*, unsigned)>> + migation_callback; + + EXPECT_CALL(migation_callback, Run(db(), 1u)).WillOnce(Return(true)); + EXPECT_TRUE(builder()->MigrateFrom(0, db(), migation_callback.Get())); +} + +TEST_F(SQLTableBuilderTest, MigrateFromWithUnsuccessfulCallback) { + EXPECT_EQ(0u, builder()->SealVersion()); + EXPECT_EQ(1u, builder()->SealVersion()); + + base::MockCallback<base::RepeatingCallback<bool(sql::Database*, unsigned)>> + migation_callback; + + EXPECT_CALL(migation_callback, Run(db(), 1u)).WillOnce(Return(false)); + EXPECT_FALSE(builder()->MigrateFrom(0, db(), migation_callback.Get())); +} + } // namespace password_manager
diff --git a/components/password_manager_strings.grdp b/components/password_manager_strings.grdp index c2ab7de..18c1a4d 100644 --- a/components/password_manager_strings.grdp +++ b/components/password_manager_strings.grdp
@@ -43,6 +43,9 @@ <message name="IDS_PASSWORD_MANAGER_RE_SIGNIN_ACCOUNT_STORE" desc="A menu item informing signed-out users to sign-in again to use account-stored passwords."> Sign in to use passwords stored in your Google account </message> + <message name="IDS_PASSWORD_MANAGER_NO_ACCOUNT_STORE_MATCHES" desc="The menu item indicating that the account store doesn't contain passwords for the current site."> + No password match. Manage all saved passwords. + </message> <if expr="not use_titlecase"> <message name="IDS_PASSWORD_MANAGER_MANAGE_PASSWORDS" desc="The menu item in the password field drop down that opens the list of saved passwords."> Manage passwords…
diff --git a/components/password_manager_strings_grdp/IDS_PASSWORD_MANAGER_NO_ACCOUNT_STORE_MATCHES.png.sha1 b/components/password_manager_strings_grdp/IDS_PASSWORD_MANAGER_NO_ACCOUNT_STORE_MATCHES.png.sha1 new file mode 100644 index 0000000..8f714ef --- /dev/null +++ b/components/password_manager_strings_grdp/IDS_PASSWORD_MANAGER_NO_ACCOUNT_STORE_MATCHES.png.sha1
@@ -0,0 +1 @@ +5a36eba8302b1aca1911d2a2873ecbc09363d290 \ No newline at end of file
diff --git a/components/performance_manager/graph/frame_node_impl.cc b/components/performance_manager/graph/frame_node_impl.cc index 6eb3db5..bd2d47c 100644 --- a/components/performance_manager/graph/frame_node_impl.cc +++ b/components/performance_manager/graph/frame_node_impl.cc
@@ -87,15 +87,22 @@ is_ad_frame_.SetAndMaybeNotify(this, true); } +void FrameNodeImpl::SetHadFormInteraction() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + document_.had_form_interaction.SetAndMaybeNotify(this, true); +} + void FrameNodeImpl::OnNonPersistentNotificationCreated() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (auto* observer : GetObservers()) observer->OnNonPersistentNotificationCreated(this); } -void FrameNodeImpl::SetHadFormInteraction() { +void FrameNodeImpl::OnFirstContentfulPaint( + base::TimeDelta time_since_navigation_start) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - document_.had_form_interaction.SetAndMaybeNotify(this, true); + for (auto* observer : GetObservers()) + observer->OnFirstContentfulPaint(this, time_since_navigation_start); } const RenderFrameHostProxy& FrameNodeImpl::GetRenderFrameHostProxy() const {
diff --git a/components/performance_manager/graph/frame_node_impl.h b/components/performance_manager/graph/frame_node_impl.h index 2ac334d..0fd7658 100644 --- a/components/performance_manager/graph/frame_node_impl.h +++ b/components/performance_manager/graph/frame_node_impl.h
@@ -77,8 +77,10 @@ void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) override; void SetOriginTrialFreezePolicy(mojom::InterventionPolicy policy) override; void SetIsAdFrame() override; - void OnNonPersistentNotificationCreated() override; void SetHadFormInteraction() override; + void OnNonPersistentNotificationCreated() override; + void OnFirstContentfulPaint( + base::TimeDelta time_since_navigation_start) override; const RenderFrameHostProxy& GetRenderFrameHostProxy() const override; // Partial FrameNodbase::TimeDelta time_since_navigatione implementation:
diff --git a/components/performance_manager/graph/frame_node_impl_unittest.cc b/components/performance_manager/graph/frame_node_impl_unittest.cc index 4c1c0d3..baf144f0 100644 --- a/components/performance_manager/graph/frame_node_impl_unittest.cc +++ b/components/performance_manager/graph/frame_node_impl_unittest.cc
@@ -137,10 +137,11 @@ MOCK_METHOD1(OnIsAdFrameChanged, void(const FrameNode*)); MOCK_METHOD1(OnFrameIsHoldingWebLockChanged, void(const FrameNode*)); MOCK_METHOD1(OnFrameIsHoldingIndexedDBLockChanged, void(const FrameNode*)); - MOCK_METHOD1(OnNonPersistentNotificationCreated, void(const FrameNode*)); MOCK_METHOD2(OnPriorityAndReasonChanged, void(const FrameNode*, const PriorityAndReason& previous_value)); MOCK_METHOD1(OnHadFormInteractionChanged, void(const FrameNode*)); + MOCK_METHOD1(OnNonPersistentNotificationCreated, void(const FrameNode*)); + MOCK_METHOD2(OnFirstContentfulPaint, void(const FrameNode*, base::TimeDelta)); void SetCreatedFrameNode(const FrameNode* frame_node) { created_frame_node_ = frame_node; @@ -340,6 +341,21 @@ graph()->RemoveFrameNodeObserver(&obs); } +TEST_F(FrameNodeImplTest, FirstContentfulPaint) { + auto process = CreateNode<ProcessNodeImpl>(); + auto page = CreateNode<PageNodeImpl>(); + auto frame_node = CreateFrameNodeAutoId(process.get(), page.get()); + + MockObserver obs; + graph()->AddFrameNodeObserver(&obs); + + base::TimeDelta fcp = base::TimeDelta::FromMilliseconds(1364); + EXPECT_CALL(obs, OnFirstContentfulPaint(frame_node.get(), fcp)); + frame_node->OnFirstContentfulPaint(fcp); + + graph()->RemoveFrameNodeObserver(&obs); +} + TEST_F(FrameNodeImplTest, PublicInterface) { auto process = CreateNode<ProcessNodeImpl>(); auto page = CreateNode<PageNodeImpl>();
diff --git a/components/performance_manager/public/graph/frame_node.h b/components/performance_manager/public/graph/frame_node.h index d3d49d9..bf74cc4 100644 --- a/components/performance_manager/public/graph/frame_node.h +++ b/components/performance_manager/public/graph/frame_node.h
@@ -230,6 +230,15 @@ virtual void OnNonPersistentNotificationCreated( const FrameNode* frame_node) = 0; + // Invoked when the frame has had a first contentful paint, as defined here: + // https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint + // This may not fire for all frames, depending on if the load is interrupted + // or if the content is even visible. It will fire at most once for a given + // frame. It will only fire for main-frame nodes. + virtual void OnFirstContentfulPaint( + const FrameNode* frame_node, + base::TimeDelta time_since_navigation_start) = 0; + private: DISALLOW_COPY_AND_ASSIGN(FrameNodeObserver); }; @@ -263,6 +272,9 @@ void OnHadFormInteractionChanged(const FrameNode* frame_node) override {} void OnNonPersistentNotificationCreated( const FrameNode* frame_node) override {} + void OnFirstContentfulPaint( + const FrameNode* frame_node, + base::TimeDelta time_since_navigation_start) override {} private: DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
diff --git a/components/performance_manager/public/mojom/coordination_unit.mojom b/components/performance_manager/public/mojom/coordination_unit.mojom index 1cf95e6..7bdcdf1 100644 --- a/components/performance_manager/public/mojom/coordination_unit.mojom +++ b/components/performance_manager/public/mojom/coordination_unit.mojom
@@ -49,7 +49,18 @@ SetIsAdFrame(); // Event signals. + + // Called when the associated frame has caused a non-persistent notification + // to be created. OnNonPersistentNotificationCreated(); + + // Invoked when the frame associated with this document has had a first + // contentful paint, as defined here: + // https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint + // This may not fire for all frames, depending on if the load is interrupted + // or if the content is even visible. It will fire at most once for a given + // frame. It will only fire for main-frame nodes. + OnFirstContentfulPaint(mojo_base.mojom.TimeDelta time_since_navigation_start); }; interface ProcessCoordinationUnit {
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 73e17c8..feb6533 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -3226,7 +3226,7 @@ 'tags': ['local-data-access'], 'desc': '''Configures the directory that <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will use for storing user data. - If you set this policy, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will use the provided directory regardless whether the user has specified the '--user-data-dir' flag or not. To avoid data loss or other unexpected errors this policy should not be set to a volume's root directory or to a directory used for other purposes, because <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> manages its contents. + If you set this policy, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will use the provided directory regardless whether the user has specified the '--user-data-dir' flag or not. To avoid data loss or other unexpected errors this policy should not be set to a directory used for other purposes, because <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> manages its contents. See https://www.chromium.org/administrators/policy-list-3/user-data-directory-variables for a list of variables that can be used. @@ -11747,7 +11747,7 @@ 'caption': '''Disable all variations''', }, ], - 'supported_on': ['chrome.*:82-'], + 'supported_on': ['chrome.*:83-'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -11792,7 +11792,7 @@ 'caption': '''Disable all variations''', }, ], - 'supported_on': ['chrome_os:82-'], + 'supported_on': ['chrome_os:83-'], 'features': { 'dynamic_refresh': True, 'per_profile': False,
diff --git a/components/policy/tools/template_writers/writers/ios_app_config_writer.py b/components/policy/tools/template_writers/writers/ios_app_config_writer.py index e280a80..f82ee54 100755 --- a/components/policy/tools/template_writers/writers/ios_app_config_writer.py +++ b/components/policy/tools/template_writers/writers/ios_app_config_writer.py
@@ -54,7 +54,7 @@ 'string-enum-list': 'stringArray', 'main': 'boolean', 'list': 'stringArray', - 'dict': None, + 'dict': 'string', } def GetTemplateText(self):
diff --git a/components/policy/tools/template_writers/writers/ios_app_config_writer_unittest.py b/components/policy/tools/template_writers/writers/ios_app_config_writer_unittest.py index 71e85c1..df741e3 100755 --- a/components/policy/tools/template_writers/writers/ios_app_config_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/ios_app_config_writer_unittest.py
@@ -125,9 +125,10 @@ def testDictPolicy(self): policy_json = self._GetTestPolicyTemplate('DictPolicy', 'dict') - # Dict policies are not supported by the appconfig.xml format and should not - # be present in the output. - expected = self._GetExpectedOutput('83.0.4089.0', None) + # Dict policies are not supported by the appconfig.xml format, therefore + # they are treated as JSON strings. + expected = self._GetExpectedOutput('83.0.4089.0', + '<string keyName="DictPolicy"/>') output = self.GetOutput(policy_json, { '_google_chrome': '1', 'version': '83.0.4089.0'
diff --git a/components/safe_browsing/content/triggers/ad_popup_trigger_unittest.cc b/components/safe_browsing/content/triggers/ad_popup_trigger_unittest.cc index 56fb756..5515555e 100644 --- a/components/safe_browsing/content/triggers/ad_popup_trigger_unittest.cc +++ b/components/safe_browsing/content/triggers/ad_popup_trigger_unittest.cc
@@ -17,7 +17,6 @@ #include "content/public/test/browser_task_environment.h" #include "content/public/test/navigation_simulator.h" #include "content/public/test/test_renderer_host.h" -#include "testing/gmock/include/gmock/gmock-generated-function-mockers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/safe_browsing/content/triggers/ad_sampler_trigger_unittest.cc b/components/safe_browsing/content/triggers/ad_sampler_trigger_unittest.cc index 6b3eca6..208eed2 100644 --- a/components/safe_browsing/content/triggers/ad_sampler_trigger_unittest.cc +++ b/components/safe_browsing/content/triggers/ad_sampler_trigger_unittest.cc
@@ -15,7 +15,6 @@ #include "content/public/test/browser_task_environment.h" #include "content/public/test/navigation_simulator.h" #include "content/public/test/test_renderer_host.h" -#include "testing/gmock/include/gmock/gmock-generated-function-mockers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc index d70ec097..4aaa6184 100644 --- a/components/sync/driver/model_type_controller.cc +++ b/components/sync/driver/model_type_controller.cc
@@ -260,6 +260,12 @@ delegate_->RecordMemoryUsageAndCountsHistograms(); } +ModelTypeControllerDelegate* +ModelTypeController::GetDelegateForTransportModeForTest() { + auto it = delegate_map_.find(SyncMode::kTransportOnly); + return it != delegate_map_.end() ? it->second.get() : nullptr; +} + void ModelTypeController::ReportModelError(SyncError::ErrorType error_type, const ModelError& error) { DCHECK(CalledOnValidThread());
diff --git a/components/sync/driver/model_type_controller.h b/components/sync/driver/model_type_controller.h index feba0a8..b940ec7 100644 --- a/components/sync/driver/model_type_controller.h +++ b/components/sync/driver/model_type_controller.h
@@ -61,6 +61,8 @@ void GetStatusCounters(StatusCountersCallback callback) override; void RecordMemoryUsageAndCountsHistograms() override; + ModelTypeControllerDelegate* GetDelegateForTransportModeForTest(); + protected: // Subclasses that use this constructor must call InitModelTypeController(). explicit ModelTypeController(ModelType type);
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index 44a6eb1..589ca3d 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -1471,8 +1471,13 @@ } ModelTypeSet ProfileSyncService::GetModelTypesForTransportOnlyMode() const { - ModelTypeSet allowed_types = {USER_CONSENTS, SECURITY_EVENTS, - SHARING_MESSAGE}; + ModelTypeSet allowed_types = { + SECURITY_EVENTS, + SHARING_MESSAGE, + SUPERVISED_USER_SETTINGS, + SUPERVISED_USER_WHITELISTS, + USER_CONSENTS, + }; if (autofill_enable_account_wallet_storage_) { if (!GetUserSettings()->IsUsingSecondaryPassphrase() ||
diff --git a/components/sync/driver/profile_sync_service_unittest.cc b/components/sync/driver/profile_sync_service_unittest.cc index 18070e02..707d53c 100644 --- a/components/sync/driver/profile_sync_service_unittest.cc +++ b/components/sync/driver/profile_sync_service_unittest.cc
@@ -21,6 +21,7 @@ #include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/signin/public/identity_manager/primary_account_mutator.h" +#include "components/sync/base/model_type.h" #include "components/sync/base/pref_names.h" #include "components/sync/base/user_demographics.h" #include "components/sync/base/user_selectable_type.h" @@ -71,6 +72,7 @@ void Configure(ModelTypeSet desired_types, const ConfigureContext& context) override { state_ = CONFIGURED; + desired_types_ = desired_types; DCHECK(!configure_called_.is_null()); configure_called_.Run(context.reason); } @@ -79,13 +81,14 @@ void ResetDataTypeErrors() override {} void PurgeForMigration(ModelTypeSet undesired_types) override {} void Stop(ShutdownReason reason) override {} - ModelTypeSet GetActiveDataTypes() const override { return ModelTypeSet(); } + ModelTypeSet GetActiveDataTypes() const override { return desired_types_; } bool IsNigoriEnabled() const override { return true; } State state() const override { return state_; } private: ConfigureCalled configure_called_; State state_; + ModelTypeSet desired_types_; }; ACTION_P(ReturnNewFakeDataTypeManager, configure_called) { @@ -177,8 +180,11 @@ void CreateService(ProfileSyncService::StartBehavior behavior) { DCHECK(!service_); + // Include a regular controller and a transport-mode controller. DataTypeController::TypeVector controllers; controllers.push_back(std::make_unique<FakeDataTypeController>(BOOKMARKS)); + controllers.push_back( + std::make_unique<FakeDataTypeController>(SUPERVISED_USER_SETTINGS)); std::unique_ptr<SyncClientMock> sync_client = profile_sync_service_bundle_.CreateSyncClientMock(); @@ -199,8 +205,11 @@ void CreateServiceWithLocalSyncBackend() { DCHECK(!service_); + // Include a regular controller and a transport-mode controller. DataTypeController::TypeVector controllers; controllers.push_back(std::make_unique<FakeDataTypeController>(BOOKMARKS)); + controllers.push_back( + std::make_unique<FakeDataTypeController>(SUPERVISED_USER_SETTINGS)); std::unique_ptr<SyncClientMock> sync_client = profile_sync_service_bundle_.CreateSyncClientMock(); @@ -421,6 +430,27 @@ EXPECT_EQ(kLastSyncedTime, sync_prefs.GetLastSyncedTime()); } +TEST_F(ProfileSyncServiceTest, ModelTypesForTransportMode) { + CreateService(ProfileSyncService::AUTO_START); + SignIn(); + InitializeForNthSync(); + + // Disable sync-the-feature. + service()->GetUserSettings()->SetSyncRequested(false); + ASSERT_FALSE(service()->IsSyncFeatureActive()); + ASSERT_FALSE(service()->IsSyncFeatureEnabled()); + + // Sync-the-transport is still active. + ASSERT_EQ(SyncService::TransportState::ACTIVE, + service()->GetTransportState()); + + // ModelTypes for sync-the-feature are not configured. + EXPECT_FALSE(service()->GetActiveDataTypes().Has(BOOKMARKS)); + + // ModelTypes for sync-the-transport are configured. + EXPECT_TRUE(service()->GetActiveDataTypes().Has(SUPERVISED_USER_SETTINGS)); +} + // Verify that the SetSetupInProgress function call updates state // and notifies observers. TEST_F(ProfileSyncServiceTest, SetupInProgress) {
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn index 66b9a70..90af920 100644 --- a/components/viz/common/BUILD.gn +++ b/components/viz/common/BUILD.gn
@@ -123,8 +123,8 @@ deps = [ "//base", + "//third_party/dawn/src/dawn:dawn_proc", "//third_party/dawn/src/dawn:dawncpp", - "//third_party/dawn/src/dawn:libdawn_proc", "//third_party/dawn/src/dawn_native", ] }
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 596e298c..3af9363 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -413,8 +413,8 @@ public_deps += [ "//third_party/dawn/src/dawn:dawn_headers" ] deps += [ + "//third_party/dawn/src/dawn:dawn_proc", "//third_party/dawn/src/dawn:dawncpp", - "//third_party/dawn/src/dawn:libdawn_proc", "//third_party/dawn/src/dawn_native", ] }
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc index 8c82bbc..43d34c09 100644 --- a/components/viz/service/display/surface_aggregator.cc +++ b/components/viz/service/display/surface_aggregator.cc
@@ -988,9 +988,13 @@ // If the current frame has copy requests or cached render passes, then // aggregate the entire thing, as otherwise parts of the copy requests may be // ignored and we could cache partially drawn render pass. + // If there are pixel-moving backdrop filters then the damage rect might be + // expanded later, so we can't drop quads that are outside the current damage + // rect safely. const bool ignore_undamaged = aggregate_only_damaged_ && !has_copy_requests_ && - !has_cached_render_passes_ && !moved_pixel_passes_.count(dest_pass->id); + !has_cached_render_passes_ && !has_pixel_moving_backdrop_filter_ && + !moved_pixel_passes_.count(dest_pass->id); // Damage rect in the quad space of the current shared quad state. // TODO(jbauman): This rect may contain unnecessary area if // transform isn't axis-aligned. @@ -1247,6 +1251,7 @@ base::AutoReset<bool> reset_is_visited(¤t_pass_entry->is_visited, true); RenderPass* render_pass = current_pass_entry->render_pass; if (current_pass_entry->has_pixel_moving_backdrop_filter) { + has_pixel_moving_backdrop_filter_ = true; // If the render pass has a backdrop filter that moves pixels, its entire // bounds, with proper transform applied, may be added to the damage // rect if it intersects. @@ -1799,6 +1804,7 @@ valid_surfaces_.clear(); has_cached_render_passes_ = false; + has_pixel_moving_backdrop_filter_ = false; damage_ranges_.clear(); damage_rects_union_of_surfaces_on_top_ = gfx::Rect(); new_surfaces_.clear();
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h index eae92812..6da752f 100644 --- a/components/viz/service/display/surface_aggregator.h +++ b/components/viz/service/display/surface_aggregator.h
@@ -408,6 +408,11 @@ // passes. This is valid during Aggregate after PrewalkTree is called. bool has_cached_render_passes_; + // True if any RenderPasses in the aggregated frame have a backdrop filter + // that moves pixels. This is valid during Aggregate after PrewalkTree is + // called. + bool has_pixel_moving_backdrop_filter_ = false; + // For each FrameSinkId, contains a vector of SurfaceRanges that will damage // the display if they're damaged. base::flat_map<FrameSinkId, std::vector<SurfaceRange>> damage_ranges_;
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc index ba0162e..0a3f1ae 100644 --- a/components/viz/service/display/surface_aggregator_unittest.cc +++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -4285,7 +4285,8 @@ } // Render passes with pixel-moving filters will increase the damage only if - // the damage of the contents will overlap the render pass. + // the damage of the contents will overlap the render pass. Since one of the + // render passes has a pixel-moving backdrop filter no quads are ignored. { int root_pass_ids[] = {1, 2}; const gfx::Size pass_with_filter_size(5, 5); @@ -4332,7 +4333,7 @@ EXPECT_EQ(1u, aggregated_pass_list[0]->quad_list.size()); EXPECT_EQ(gfx::Rect(1, 1), aggregated_pass_list[1]->damage_rect); - EXPECT_EQ(0u, aggregated_pass_list[1]->quad_list.size()); + EXPECT_EQ(1u, aggregated_pass_list[1]->quad_list.size()); // First render pass draw quad overlaps with damage rect and has background // filter, so it should be damaged. SurfaceDrawQuad is after background @@ -4342,7 +4343,8 @@ } // If the render pass with background filters does not intersect the damage - // rect, the damage won't be expanded to cover the render pass. + // rect, the damage won't be expanded to cover the render pass. Since one of + // the render passes has a pixel-moving backdrop filter no quads are ignored. { int root_pass_ids[] = {1, 2}; const gfx::Size pass_with_filter_size(5, 5); @@ -4384,7 +4386,7 @@ // Pass 0 has background blur filter but does NOT overlap with damage rect. EXPECT_EQ(gfx::Rect(), aggregated_pass_list[0]->damage_rect); - EXPECT_EQ(0u, aggregated_pass_list[0]->quad_list.size()); + EXPECT_EQ(1u, aggregated_pass_list[0]->quad_list.size()); EXPECT_EQ(gfx::Rect(1, 1, 3, 3), aggregated_pass_list[1]->damage_rect); EXPECT_EQ(1u, aggregated_pass_list[1]->quad_list.size()); @@ -4393,7 +4395,7 @@ // drawn. SurfaceDrawQuad is after background filter, so corresponding // RenderPassDrawQuad should be drawn. EXPECT_EQ(gfx::Rect(6, 6, 3, 3), aggregated_pass_list[2]->damage_rect); - EXPECT_EQ(1u, aggregated_pass_list[2]->quad_list.size()); + EXPECT_EQ(2u, aggregated_pass_list[2]->quad_list.size()); } }
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm index c7fb942..50972ce 100644 --- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm +++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
@@ -120,6 +120,78 @@ base::ClampToRange(static_cast<int>(lroundf(255.0f * b)), 0, 255); } +// TODO(bokan): Added temporarily to debug https://crbug.com/1039833. +// Needed only in temporary method below. +CommandDispatcher* GetCommandDispatcher(NSWindow* theWindow) { + if ([theWindow conformsToProtocol:@protocol(CommandDispatchingWindow)]) { + return [static_cast<NSObject<CommandDispatchingWindow>*>(theWindow) + commandDispatcher]; + } + return nil; +} + +// TODO(bokan): Added temporarily to debug https://crbug.com/1039833. +// Returns a string with class names of each ancestor view of this one +// (inclusive). +std::string GetViewHierarchyString(NSView* thisView) { + std::string ret = ""; + NSView* view = thisView; + while (view) { + ret += base::SysNSStringToUTF8(NSStringFromClass([view class])) + "->"; + view = [view superview]; + } + + return ret; +} + +// TODO(bokan): Added temporarily to debug https://crbug.com/1039833. +// Returns a string with information about all the app's windows and current +// event redispatch state of this window and the event's window. +std::string GetWindowInfoString(NSWindow* thisWindow, NSEvent* theEvent) { + std::string windowInfoStr = "["; + NSArray* windows = [NSApp windows]; + bool foundEventWindow = false; + for (unsigned int i = 0; i < [windows count]; ++i) { + NSWindow* window = windows[i]; + if (thisWindow == window) + windowInfoStr += "SELF-"; + if ([NSApp keyWindow] == window) + windowInfoStr += "KEY-"; + if ([NSApp mainWindow] == window) + windowInfoStr += "MAIN-"; + if ([theEvent windowNumber] == [window windowNumber]) { + foundEventWindow = true; + windowInfoStr += "EVENT-"; + } + + std::string className = + base::SysNSStringToUTF8(NSStringFromClass([window class])); + NSRect rect = [window frame]; + windowInfoStr += base::StringPrintf( + "%ld<%s - %dx%d>, ", static_cast<long>([window windowNumber]), + className.c_str(), static_cast<int>(NSWidth(rect)), + static_cast<int>(NSHeight(rect))); + } + windowInfoStr += "]"; + + if (!foundEventWindow) + windowInfoStr += base::StringPrintf( + " Event: %ld", static_cast<long>([theEvent windowNumber])); + + windowInfoStr += base::StringPrintf( + " isRedispatch[this:%d event:%d]", + GetCommandDispatcher(thisWindow) == nil + ? -1 + : static_cast<int>( + [GetCommandDispatcher(thisWindow) isRedispatchingKeyEvent]), + GetCommandDispatcher([theEvent window]) == nil + ? -1 + : static_cast<int>([GetCommandDispatcher([theEvent window]) + isRedispatchingKeyEvent])); + + return windowInfoStr; +} + // Extract underline information from an attributed string. Mostly copied from // third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm void ExtractUnderlines(NSAttributedString* string, @@ -921,6 +993,16 @@ - (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv { TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::keyEvent"); + // TODO(bokan): Added temporarily to debug https://crbug.com/1039833. + static auto* windowInfoKey = base::debug::AllocateCrashKeyString( + "window-info", base::debug::CrashKeySize::Size256); + static auto* viewInfoKey = base::debug::AllocateCrashKeyString( + "view-info", base::debug::CrashKeySize::Size256); + base::debug::ScopedCrashKeyString scopedKeyWindow( + windowInfoKey, GetWindowInfoString([self window], theEvent)); + base::debug::ScopedCrashKeyString scopedKeyView(viewInfoKey, + GetViewHierarchyString(self)); + NSEventType eventType = [theEvent type]; NSEventModifierFlags modifierFlags = [theEvent modifierFlags]; int keyCode = [theEvent keyCode];
diff --git a/content/browser/renderer_host/input/fling_controller.cc b/content/browser/renderer_host/input/fling_controller.cc index ff74cc7..58b13bd5 100644 --- a/content/browser/renderer_host/input/fling_controller.cc +++ b/content/browser/renderer_host/input/fling_controller.cc
@@ -407,13 +407,27 @@ return false; } + gfx::Vector2dF velocity_from_gfs( + fling_start_event.data.fling_start.velocity_x, + fling_start_event.data.fling_start.velocity_y); + + float max_velocity_from_gfs = + std::max(fabs(velocity_from_gfs.x()), fabs(velocity_from_gfs.y())); + float max_velocity = std::max(fabs(current_fling_parameters_.velocity.x()), + fabs(current_fling_parameters_.velocity.y())); + + // Scale the default bound multiplier to compute the maximum scroll distance a + // fling can travel based on physics based fling curve. + float boost_multiplier = max_velocity / max_velocity_from_gfs; + fling_curve_ = std::unique_ptr<blink::WebGestureCurve>( ui::WebGestureCurveImpl::CreateFromDefaultPlatformCurve( current_fling_parameters_.source_device, current_fling_parameters_.velocity, gfx::Vector2dF() /*initial_offset*/, false /*on_main_thread*/, GetContentClient()->browser()->ShouldUseMobileFlingCurve(), - current_fling_parameters_.global_point, root_widget_viewport_size)); + current_fling_parameters_.global_point, boost_multiplier, + root_widget_viewport_size)); return true; }
diff --git a/content/browser/renderer_host/input/fling_controller_unittest.cc b/content/browser/renderer_host/input/fling_controller_unittest.cc index 95d1771..f8067cb 100644 --- a/content/browser/renderer_host/input/fling_controller_unittest.cc +++ b/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -6,13 +6,17 @@ #include "base/rand_util.h" #include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" #include "base/test/simple_test_tick_clock.h" #include "base/test/task_environment.h" #include "build/build_config.h" +#include "build/chromecast_buildflags.h" #include "content/browser/renderer_host/input/gesture_event_queue.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/ui_base_features.h" #include "ui/events/base_event_utils.h" #include "ui/events/blink/fling_booster.h" +#include "ui/events/gestures/physics_based_fling_curve.h" #if defined(OS_WIN) #include "ui/display/win/test/scoped_screen_win.h" @@ -21,6 +25,7 @@ using blink::WebGestureEvent; using blink::WebInputEvent; using blink::WebMouseWheelEvent; +using ui::PhysicsBasedFlingCurve; namespace { constexpr double kFrameDelta = 1000.0 / 60.0; @@ -702,4 +707,134 @@ EXPECT_FALSE(FlingInProgress()); } +class FlingControllerWithPhysicsBasedFlingTest : public FlingControllerTest { + public: + // testing::Test + FlingControllerWithPhysicsBasedFlingTest() { + scoped_feature_list_.InitAndEnableFeature( + features::kExperimentalFlingAnimation); + } + + ~FlingControllerWithPhysicsBasedFlingTest() override = default; + + private: + base::test::ScopedFeatureList scoped_feature_list_; + DISALLOW_COPY_AND_ASSIGN(FlingControllerWithPhysicsBasedFlingTest); +}; + +INSTANTIATE_TEST_SUITE_P(All, + FlingControllerWithPhysicsBasedFlingTest, + testing::Bool()); + +// Ensure the bounding distance for boosted physics based flings is increased +// by a factor of the boost_multiplier and default multiplier +TEST_P(FlingControllerWithPhysicsBasedFlingTest, + ControllerBoostsTouchscreenFling) { + // We use a velocity of 4500 in this test because it yields a scroll delta + // that is greater than viewport * boost_multiplier * kDefaultBoundsMultiplier + + // Android and Chromecast use Mobile fling curve so they are ignored + // for this test + bool use_mobile_fling_curve = false; +#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMECAST) + use_mobile_fling_curve = true; +#endif + if (use_mobile_fling_curve) + return; + + SimulateFlingStart(blink::WebGestureDevice::kTouchscreen, + gfx::Vector2dF(4500, 0)); + EXPECT_TRUE(FlingInProgress()); + // Fling progress must send GSU events. + AdvanceTime(); + ProgressFling(NowTicks()); + ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType()); + EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, + last_sent_gesture_.data.scroll_update.inertial_phase); + EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f); + + // Now cancel the fling. + SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen); + EXPECT_FALSE(FlingInProgress()); + + // The second GFS can be boosted so it should boost the just deactivated + // fling. To test that the correct bounds scale is used, the scroll delta + // is accumulated after each frame. + SimulateFlingStart(blink::WebGestureDevice::kTouchscreen, + gfx::Vector2dF(4500, 0)); + EXPECT_TRUE(FlingInProgress()); + if (NeedsBeginFrameForFlingProgress()) + ProgressFling(NowTicks()); + float total_scroll_delta = last_sent_gesture_.data.scroll_update.delta_x; + while (true) { + if (last_sent_gesture_.GetType() == WebInputEvent::kGestureScrollEnd) { + break; + } + AdvanceTime(); + ProgressFling(NowTicks()); + total_scroll_delta += last_sent_gesture_.data.scroll_update.delta_x; + } + + // We expect the scroll delta to be the viewport * [boost_multiplier = 2] * + // multiplier + float expected_delta = + 2 * PhysicsBasedFlingCurve::default_bounds_multiplier_for_testing() * + GetRootWidgetViewportSize().width(); + EXPECT_EQ(ceilf(total_scroll_delta), roundf(expected_delta)); +} + +// Ensure that once a fling finishes, the next fling has a boost_multiplier of 1 +TEST_P(FlingControllerWithPhysicsBasedFlingTest, + ControllerDoesntBoostFinishedFling) { + // Android and Chromecast use Mobile fling curve so they are ignored + // for this test + bool use_mobile_fling_curve = false; +#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMECAST) + use_mobile_fling_curve = true; +#endif + if (use_mobile_fling_curve) + return; + SimulateFlingStart(blink::WebGestureDevice::kTouchscreen, + gfx::Vector2dF(1000, 0), /*wait_before_processing=*/true); + EXPECT_TRUE(FlingInProgress()); + AdvanceTime(); + ProgressFling(NowTicks()); + + // Fast forward so that the fling ends. + double time_to_advance_ms = 1000.0; + AdvanceTime(time_to_advance_ms); + ProgressFling(NowTicks()); + ASSERT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType()) + << "Unexpected Last Sent Gesture: " + << WebInputEvent::GetName(last_sent_gesture_.GetType()); + EXPECT_EQ(fling_controller_->CurrentFlingVelocity().x(), 0); + EXPECT_FALSE(FlingInProgress()); + + // Now send a new fling, ensure boost_multiplier is 1 + AdvanceTime(); + SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen); + + SimulateFlingStart(blink::WebGestureDevice::kTouchscreen, + gfx::Vector2dF(10000, 0)); + EXPECT_TRUE(FlingInProgress()); + if (NeedsBeginFrameForFlingProgress()) + ProgressFling(NowTicks()); + float total_scroll_delta = last_sent_gesture_.data.scroll_update.delta_x; + while (true) { + if (last_sent_gesture_.GetType() == WebInputEvent::kGestureScrollEnd) { + break; + } + AdvanceTime(); + ProgressFling(NowTicks()); + total_scroll_delta += last_sent_gesture_.data.scroll_update.delta_x; + } + + // We expect the scroll delta to be the viewport * [boost_multiplier = 1] * + // multiplier + float expected_delta = + PhysicsBasedFlingCurve::default_bounds_multiplier_for_testing() * + GetRootWidgetViewportSize().width(); + EXPECT_EQ(ceilf(total_scroll_delta), roundf(expected_delta)); +} + } // namespace content
diff --git a/content/browser/renderer_host/input/web_input_event_builders_mac.mm b/content/browser/renderer_host/input/web_input_event_builders_mac.mm index cfc2815..d03a597 100644 --- a/content/browser/renderer_host/input/web_input_event_builders_mac.mm +++ b/content/browser/renderer_host/input/web_input_event_builders_mac.mm
@@ -35,6 +35,7 @@ #include <stdint.h> +#include "base/debug/dump_without_crashing.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/time/time.h" @@ -235,19 +236,35 @@ blink::WebKeyboardEvent WebKeyboardEventBuilder::Build(NSEvent* event, bool record_debug_uma) { + // TODO(bokan) Temporary to debug crbug.com/1039833. + // It's assumed that some clients may fall into a bad state and produce these + // bad timestamps on lots of subsequent events. To prevent sending an + // overwhelming amount of crash reports stop after sending 5. + static int dump_without_crashing_throttle = 5; + ui::ComputeEventLatencyOS(event); base::TimeTicks now = ui::EventTimeForNow(); base::TimeTicks hardware_timestamp = ui::EventTimeStampFromSeconds([event timestamp]); if (record_debug_uma) { if (ui::EventTypeFromNative(event) == ui::ET_KEY_PRESSED) { + base::TimeDelta diff = now - hardware_timestamp; UMA_HISTOGRAM_CUSTOM_TIMES( now > hardware_timestamp ? "Event.Latency.OS_NO_VALIDATION.POSITIVE.KEY_PRESSED" : "Event.Latency.OS_NO_VALIDATION.NEGATIVE.KEY_PRESSED", - (now - hardware_timestamp).magnitude(), - base::TimeDelta::FromMilliseconds(1), + diff.magnitude(), base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromSeconds(60), 50); + + // TODO(bokan) Temporary to debug crbug.com/1039833. We've seen in UMA + // that we often receive key press events with the OS timestamp differing + // from the current timestamp by many seconds. Try to capture a few crash + // reports from the wild to see if we can find some pattern. + if (diff.magnitude() > base::TimeDelta::FromSeconds(5) && + dump_without_crashing_throttle > 0) { + --dump_without_crashing_throttle; + base::debug::DumpWithoutCrashing(); + } } } ui::DomCode dom_code = ui::DomCodeFromNSEvent(event);
diff --git a/content/browser/speech/tts_platform_fuzzer.cc b/content/browser/speech/tts_platform_fuzzer.cc deleted file mode 100644 index d60a85c..0000000 --- a/content/browser/speech/tts_platform_fuzzer.cc +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "build/build_config.h" -#include "content/public/browser/tts_platform.h" - -#if defined(OS_WIN) -#include <objbase.h> -#endif - -namespace content { - -// Entry point for LibFuzzer. -extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) { - int utterance_id = 0; - std::string utterance; - std::string lang; - VoiceData voice; - UtteranceContinuousParameters params; - params.pitch = 1.0; - params.rate = 1.0; - params.volume = 0.1; - -#if defined(OS_WIN) - static bool initialized = false; - if (!initialized) { - initialized = true; - CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - } -#endif - - // First byte gives us the utterance ID. - size_t i = 0; - if (i < size) - utterance_id = data[i++]; - - // Decide whether we want to fuzz the language, rate, pitch, - // voice name, and all that. Half the time we'll just leave - // those empty and fuzz only the utterance, otherwise it's - // possible the fuzzer would never spend any effort fuzzing - // utteranes. - if (i < size && (data[i++] % 2 == 0)) { - // The next few bytes determine the language. Ensure that - // we frequently get some common real languages but allow - // arbitrary strings up to 10 characters. - if (i < size) { - int lang_choice = data[i++]; - switch (lang_choice) { - case 0: - lang = ""; - break; - case 1: - lang = "en"; - break; - case 2: - lang = "fr"; - break; - case 3: - lang = "es"; - break; - default: - int lang_len = 1 + (lang_choice - 4) % 10; - for (int j = 0; j < lang_len; j++) { - if (i < size) - lang.append(1, data[i++]); - } - } - } - - // Set native_voice_identifier - if (i < size) { - int voice_len = data[i++] % 10; - for (int j = 0; j < voice_len; j++) { - if (i < size) - voice.native_voice_identifier.append(1, data[i++]); - } - } - - // Set rate, pitch. - if (i + 4 <= size) { - params.rate = *reinterpret_cast<const float*>(&data[i]); - i += 4; - } - if (i + 4 <= size) { - params.pitch = *reinterpret_cast<const float*>(&data[i]); - i += 4; - } - } - - // The rest of the data becomes the utterance. - while (i < size) - utterance.append(1, data[i++]); - - TtsPlatform* tts = TtsPlatform::GetInstance(); - CHECK(tts->PlatformImplAvailable()); - - VLOG(1) << "id=" << utterance_id << " lang='" << lang << "'" - << " voice='" << voice.native_voice_identifier << "'" - << " pitch=" << params.pitch << " rate=" << params.rate - << " volume=" << params.volume << " utterance='" << utterance << "'"; - - tts->StopSpeaking(); - tts->Speak(utterance_id, utterance, lang, voice, params, - base::BindOnce([](bool success) {})); - - return 0; -} - -} // namespace content
diff --git a/content/renderer/input/widget_input_handler_manager.h b/content/renderer/input/widget_input_handler_manager.h index 7f913af..bb202cb 100644 --- a/content/renderer/input/widget_input_handler_manager.h +++ b/content/renderer/input/widget_input_handler_manager.h
@@ -243,8 +243,10 @@ // Control of UMA. We emit one UMA metric per navigation telling us // whether any non-move input arrived before we starting updating the page or - // displaying content to the user. - bool have_emitted_uma_ = false; + // displaying content to the user. It must be atomic because navigation can + // occur on the renderer thread (resetting this) coincident with the UMA + // being sent on the compositor thread. + std::atomic<bool> have_emitted_uma_{false}; #if defined(OS_ANDROID) std::unique_ptr<SynchronousCompositorProxyRegistry>
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc index b5a203b..0ef62c4 100644 --- a/content/renderer/loader/web_url_loader_impl.cc +++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -61,6 +61,7 @@ #include "net/ssl/ssl_info.h" #include "services/network/public/cpp/http_raw_request_response_info.h" #include "services/network/public/cpp/resource_request.h" +#include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/blink/public/common/features.h" @@ -1021,6 +1022,19 @@ return WebURLError(*status.blocked_by_response_reason, status.resolve_error_info, has_copy_in_cache, url); } + + if (status.trust_token_operation_status != + network::mojom::TrustTokenOperationStatus::kOk) { + DCHECK(status.error_code == net::ERR_TRUST_TOKEN_OPERATION_CACHE_HIT || + status.error_code == net::ERR_TRUST_TOKEN_OPERATION_FAILED) + << "Unexpected error code on Trust Token operation failure (or cache " + "hit): " + << status.error_code; + + return WebURLError(status.error_code, status.trust_token_operation_status, + url); + } + return WebURLError(status.error_code, status.extended_error_code, status.resolve_error_info, has_copy_in_cache, WebURLError::IsWebSecurityViolation::kFalse, url);
diff --git a/content/test/data/content_index/test.html b/content/test/data/content_index/test.html index ab036b5..4f6bdb1 100644 --- a/content/test/data/content_index/test.html +++ b/content/test/data/content_index/test.html
@@ -18,7 +18,7 @@ description: 'Description!', category: 'article', icons, - launchUrl: '/content_index/test.html', + url: '/content_index/test.html', }); sendResultToTest('ok'); } catch (e) {
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn index 2f22106..38d1079e 100644 --- a/content/test/fuzzer/BUILD.gn +++ b/content/test/fuzzer/BUILD.gn
@@ -161,42 +161,6 @@ ] } -# Note: this compiles and runs on Mac but may cause -# system instability; if you try it out, close other -# programs and then reboot afterwards. It should be -# possible to make it work on Linux if you use the -# --enable-speech-dispatcher flag. -if (is_win) { - fuzzer_test("tts_platform_fuzzer") { - sources = [ - "../../browser/speech/mock_tts_controller.cc", - "../../browser/speech/tts_mac.mm", - "../../browser/speech/tts_platform_fuzzer.cc", - "../../browser/speech/tts_platform_impl.cc", - "../../browser/speech/tts_platform_impl.h", - "../../browser/speech/tts_win.cc", - "../../public/browser/tts_controller.h", - "../../public/browser/tts_platform.h", - "//content/common/content_export.h", - ] - - # Don't try to link the code that calls GetContentClient(), because - # then we'd need to link in most of //content. - defines = [ "NO_CONTENT_CLIENT" ] - - # TODO(https://crbug.com/927728): Refactor target to not require this. - check_includes = false - - deps = [ - "//base", - "//base/test:test_support", - "//third_party/webrtc_overrides:webrtc_component", - "//ui/base", - "//url:url", - ] - } -} - fuzzer_test("speech_audio_encoder_fuzzer") { sources = [ "../../browser/speech/audio_buffer.cc",
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index f9b8ec5..4b2f106 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn
@@ -415,8 +415,8 @@ if (use_dawn) { deps += [ + "//third_party/dawn/src/dawn:dawn_proc", "//third_party/dawn/src/dawn:dawncpp", - "//third_party/dawn/src/dawn:libdawn_proc", "//third_party/dawn/src/dawn_native", ] }
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 96cbd52..bc5929c 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn
@@ -390,8 +390,8 @@ if (skia_use_dawn) { deps += [ "//components/viz/common:dawn_context_provider", + "//third_party/dawn/src/dawn:dawn_proc", "//third_party/dawn/src/dawn:dawncpp", - "//third_party/dawn/src/dawn:libdawn_proc", ] }
diff --git a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm index a0ac288..92a014f4 100644 --- a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm +++ b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
@@ -13,7 +13,6 @@ #import "ios/chrome/browser/main/test_browser.h" #import "ios/chrome/browser/metrics/previous_session_info.h" #import "ios/chrome/browser/metrics/previous_session_info_private.h" -#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/ui/main/browser_interface_provider.h" #import "ios/chrome/browser/ui/main/scene_state.h" #import "ios/chrome/browser/ui/main/test/fake_scene_state.h"
diff --git a/ios/chrome/app/application_delegate/url_opener_unittest.mm b/ios/chrome/app/application_delegate/url_opener_unittest.mm index 58c9c2b..7fe1cc1 100644 --- a/ios/chrome/app/application_delegate/url_opener_unittest.mm +++ b/ios/chrome/app/application_delegate/url_opener_unittest.mm
@@ -12,7 +12,6 @@ #include "ios/chrome/app/application_delegate/startup_information.h" #include "ios/chrome/app/startup/chrome_app_startup_parameters.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/ui/main/test/stub_browser_interface.h" #import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h" #import "ios/chrome/browser/url_loading/url_loading_params.h"
diff --git a/ios/chrome/app/chrome_overlay_window.mm b/ios/chrome/app/chrome_overlay_window.mm index 64d55b6..08e2c0f 100644 --- a/ios/chrome/app/chrome_overlay_window.mm +++ b/ios/chrome/app/chrome_overlay_window.mm
@@ -9,7 +9,6 @@ #import "ios/chrome/browser/metrics/drag_and_drop_recorder.h" #import "ios/chrome/browser/metrics/size_class_recorder.h" #import "ios/chrome/browser/metrics/user_interface_style_recorder.h" -#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/ui/util/ui_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/app/tab_opener_unittest.mm b/ios/chrome/app/tab_opener_unittest.mm index 16d393b8..2b7e450 100644 --- a/ios/chrome/app/tab_opener_unittest.mm +++ b/ios/chrome/app/tab_opener_unittest.mm
@@ -9,7 +9,6 @@ #include "ios/chrome/app/application_delegate/startup_information.h" #import "ios/chrome/app/application_delegate/tab_opening.h" #import "ios/chrome/app/application_delegate/url_opener.h" -#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/ui/main/scene_controller.h" #import "ios/chrome/browser/ui/main/scene_state.h" #import "ios/testing/scoped_block_swizzler.h"
diff --git a/ios/chrome/browser/metrics/BUILD.gn b/ios/chrome/browser/metrics/BUILD.gn index 1851a2f..b59b1aeb 100644 --- a/ios/chrome/browser/metrics/BUILD.gn +++ b/ios/chrome/browser/metrics/BUILD.gn
@@ -180,7 +180,6 @@ "//components/google/core/common", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", - "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui/util", "//ios/chrome/browser/web_state_list", "//ios/web",
diff --git a/ios/chrome/browser/metrics/new_tab_page_uma.mm b/ios/chrome/browser/metrics/new_tab_page_uma.mm index a7e776f..a9466a2 100644 --- a/ios/chrome/browser/metrics/new_tab_page_uma.mm +++ b/ios/chrome/browser/metrics/new_tab_page_uma.mm
@@ -8,8 +8,6 @@ #include "components/google/core/common/google_util.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" -#import "ios/chrome/browser/tabs/tab_model.h" -#import "ios/chrome/browser/tabs/tab_model_list.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/web/public/web_state.h" #include "url/gurl.h"
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn index 22915a1..a0c27c5 100644 --- a/ios/chrome/browser/passwords/BUILD.gn +++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -69,6 +69,7 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/infobars", "//ios/chrome/browser/infobars:public", + "//ios/chrome/browser/main:public", "//ios/chrome/browser/signin", "//ios/chrome/browser/ssl", "//ios/chrome/browser/sync/glue",
diff --git a/ios/chrome/browser/passwords/password_controller.h b/ios/chrome/browser/passwords/password_controller.h index d617746..a2ab586 100644 --- a/ios/chrome/browser/passwords/password_controller.h +++ b/ios/chrome/browser/passwords/password_controller.h
@@ -15,6 +15,7 @@ #import "ios/web/public/web_state_observer_bridge.h" @protocol ApplicationCommands; +class Browser; @class NotifyUserAutoSigninViewController; @protocol PasswordBreachCommands; @protocol PasswordFormFiller; @@ -70,6 +71,9 @@ // Delegate used by this PasswordController to show UI on BVC. @property(weak, nonatomic) id<PasswordControllerDelegate> delegate; +// The browser. +@property(nonatomic, assign) Browser* browser; + // |webState| should not be nil. - (instancetype)initWithWebState:(web::WebState*)webState;
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index e21e05f..c09657cd 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -46,6 +46,7 @@ #include "ios/chrome/browser/infobars/infobar_ios.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h" #import "ios/chrome/browser/infobars/infobar_type.h" +#import "ios/chrome/browser/main/browser.h" #include "ios/chrome/browser/passwords/credential_manager.h" #import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h" #import "ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h" @@ -864,10 +865,9 @@ object:nil]; // TODO(crbug.com/886583): add eg tests - // TODO(crbug.com/1029346): add browser value. self.actionSheetCoordinator = [[ActionSheetCoordinator alloc] initWithBaseViewController:self.baseViewController - browser:nil + browser:self.browser title:@"" message:@"" rect:self.baseViewController.view.frame
diff --git a/ios/chrome/browser/passwords/password_tab_helper.h b/ios/chrome/browser/passwords/password_tab_helper.h index 3f97d4b..d78821177 100644 --- a/ios/chrome/browser/passwords/password_tab_helper.h +++ b/ios/chrome/browser/passwords/password_tab_helper.h
@@ -9,10 +9,9 @@ #include "ios/web/public/web_state_observer.h" #import "ios/web/public/web_state_user_data.h" -@protocol ApplicationCommands; +class Browser; @protocol FormSuggestionProvider; @class PasswordController; -@protocol PasswordBreachCommands; @protocol PasswordControllerDelegate; @protocol PasswordFormFiller; @protocol PasswordsUiDelegate; @@ -35,13 +34,12 @@ // Sets the BaseViewController from which to present UI. void SetBaseViewController(UIViewController* baseViewController); - // Sets the PasswordController dispatcher. - void SetDispatcher( - id<ApplicationCommands, PasswordBreachCommands> dispatcher); - // Sets the PasswordController delegate. void SetPasswordControllerDelegate(id<PasswordControllerDelegate> delegate); + // Sets the Browser. + void SetBrowser(Browser* browser); + // Returns an object that can provide suggestions from the PasswordController. // May return nil. id<FormSuggestionProvider> GetSuggestionProvider();
diff --git a/ios/chrome/browser/passwords/password_tab_helper.mm b/ios/chrome/browser/passwords/password_tab_helper.mm index 17184721..633a3ca 100644 --- a/ios/chrome/browser/passwords/password_tab_helper.mm +++ b/ios/chrome/browser/passwords/password_tab_helper.mm
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" +#import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/passwords/password_controller.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -28,16 +29,15 @@ controller_.baseViewController = baseViewController; } -void PasswordTabHelper::SetDispatcher( - id<ApplicationCommands, PasswordBreachCommands> dispatcher) { - controller_.dispatcher = dispatcher; -} - void PasswordTabHelper::SetPasswordControllerDelegate( id<PasswordControllerDelegate> delegate) { controller_.delegate = delegate; } +void PasswordTabHelper::SetBrowser(Browser* browser) { + controller_.browser = browser; +} + id<FormSuggestionProvider> PasswordTabHelper::GetSuggestionProvider() { return controller_.suggestionProvider; }
diff --git a/ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h b/ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h index 82b9431..789b969 100644 --- a/ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h +++ b/ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h
@@ -33,12 +33,6 @@ // |-executeCancelHandler|) has occurred. @property(nonatomic, copy) ProceduralBlock noInteractionAction; -// TODO(crbug.com/1029346): Remove this init after migrate away from downstream -// AlertCoordinator use. -- (instancetype)initWithBaseViewController:(UIViewController*)viewController - title:(NSString*)title - message:(NSString*)message; - // Init a coordinator for displaying a alert on this view controller. - (instancetype)initWithBaseViewController:(UIViewController*)viewController browser:(Browser*)browser
diff --git a/ios/chrome/browser/ui/alert_coordinator/alert_coordinator.mm b/ios/chrome/browser/ui/alert_coordinator/alert_coordinator.mm index 27958b1..33493ee 100644 --- a/ios/chrome/browser/ui/alert_coordinator/alert_coordinator.mm +++ b/ios/chrome/browser/ui/alert_coordinator/alert_coordinator.mm
@@ -43,17 +43,6 @@ @synthesize rawCancelAction = _rawCancelAction; @synthesize message = _message; -// TODO(crbug.com/1029346): Remove this init after migrate away from downstream -// AlertCoordinator use. -- (instancetype)initWithBaseViewController:(UIViewController*)viewController - title:(NSString*)title - message:(NSString*)message { - return [self initWithBaseViewController:viewController - browser:nil - title:title - message:message]; -} - - (instancetype)initWithBaseViewController:(UIViewController*)viewController browser:(Browser*)browser title:(NSString*)title
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm index 1521ad4..52da932 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm
@@ -453,7 +453,7 @@ editedNodes:editedNodes allowsCancel:NO selectedFolder:self.folder - dispatcher:self.dispatcher]; + browser:_browser]; folderViewController.delegate = self; self.folderViewController = folderViewController; self.folderViewController.navigationItem.largeTitleDisplayMode =
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h b/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h index ade36301..99e5c31 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h
@@ -9,7 +9,6 @@ #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" @class BookmarkFolderEditorViewController; -@protocol BrowserCommands; class Browser; namespace bookmarks { @@ -52,7 +51,7 @@ + (instancetype) folderCreatorWithBookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel parentFolder:(const bookmarks::BookmarkNode*)parentFolder - dispatcher:(id<BrowserCommands>)dispatcher; + browser:(Browser*)browser; // |bookmarkModel| must not be null and must be loaded. // |folder| must not be NULL and be editable.
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.mm index 7d81e30..0c0a8ce 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.mm
@@ -115,14 +115,18 @@ + (instancetype)folderCreatorWithBookmarkModel: (bookmarks::BookmarkModel*)bookmarkModel parentFolder:(const BookmarkNode*)parentFolder - dispatcher:(id<BrowserCommands>)dispatcher { - DCHECK(dispatcher); + browser:(Browser*)browser { + DCHECK(browser); BookmarkFolderEditorViewController* folderCreator = [[self alloc] initWithBookmarkModel:bookmarkModel]; folderCreator.parentFolder = parentFolder; folderCreator.folder = NULL; + folderCreator.browser = browser; folderCreator.editingExistingFolder = NO; - folderCreator.dispatcher = dispatcher; + // TODO(crbug.com/1045047): Use HandlerForProtocol after commands protocol + // clean up. + folderCreator.dispatcher = + static_cast<id<BrowserCommands>>(browser->GetCommandDispatcher()); return folderCreator; } @@ -305,7 +309,7 @@ editedNodes:editedNodes allowsCancel:NO selectedFolder:self.parentFolder - dispatcher:self.dispatcher]; + browser:_browser]; folderViewController.delegate = self; self.folderViewController = folderViewController;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.h b/ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.h index bb4cfe0..b2c303f 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.h
@@ -11,7 +11,7 @@ #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" @class BookmarkFolderViewController; -@protocol BrowserCommands; +class Browser; namespace bookmarks { class BookmarkModel; class BookmarkNode; @@ -56,7 +56,7 @@ editedNodes:(const std::set<const bookmarks::BookmarkNode*>&)nodes allowsCancel:(BOOL)allowsCancel selectedFolder:(const bookmarks::BookmarkNode*)selectedFolder - dispatcher:(id<BrowserCommands>)dispatcher; + browser:(Browser*)browser; // This method changes the currently selected folder and updates the UI. The // delegate is not notified of the change.
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.mm index c21420d..23f425f 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.mm
@@ -79,8 +79,8 @@ @property(nonatomic, assign, readonly) const std::vector<const BookmarkNode*>& folders; -// The dispatcher for this ViewController. -@property(nonatomic, readonly, weak) id<BrowserCommands> dispatcher; +// The browser for this ViewController. +@property(nonatomic, readonly) Browser* browser; // Reloads the model and the updates |self.tableView| to reflect any model // changes. @@ -115,18 +115,19 @@ (const std::set<const BookmarkNode*>&)nodes allowsCancel:(BOOL)allowsCancel selectedFolder:(const BookmarkNode*)selectedFolder - dispatcher:(id<BrowserCommands>)dispatcher { + browser:(Browser*)browser { DCHECK(bookmarkModel); DCHECK(bookmarkModel->loaded()); + DCHECK(browser); DCHECK(selectedFolder == NULL || selectedFolder->is_folder()); self = [super initWithStyle:UITableViewStylePlain]; if (self) { + _browser = browser; _allowsCancel = allowsCancel; _allowsNewFolders = allowsNewFolders; _bookmarkModel = bookmarkModel; _editedNodes = nodes; _selectedFolder = selectedFolder; - _dispatcher = dispatcher; // Set up the bookmark model oberver. _modelBridge.reset( @@ -449,7 +450,7 @@ [BookmarkFolderEditorViewController folderCreatorWithBookmarkModel:self.bookmarkModel parentFolder:self.selectedFolder - dispatcher:self.dispatcher]; + browser:self.browser]; folderCreator.delegate = self; [self.navigationController pushViewController:folderCreator animated:YES]; self.folderAddController = folderCreator;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm index 713328a..5506458 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -624,7 +624,7 @@ editedNodes:nodes allowsCancel:YES selectedFolder:selectedFolder - dispatcher:self.handler]; + browser:self.browser]; self.folderSelector.delegate = self; UINavigationController* navController = [[BookmarkNavigationController alloc] initWithRootViewController:self.folderSelector];
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 4fccda1..2c59622 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -2549,12 +2549,12 @@ SnapshotTabHelper::FromWebState(webState)->SetDelegate(self); - // TODO(crbug.com/777557): do not pass the dispatcher to PasswordTabHelper. + // TODO(crbug.com/1069763): do not pass the browser to PasswordTabHelper. if (PasswordTabHelper* passwordTabHelper = PasswordTabHelper::FromWebState(webState)) { passwordTabHelper->SetBaseViewController(self); - passwordTabHelper->SetDispatcher(self.dispatcher); passwordTabHelper->SetPasswordControllerDelegate(self); + passwordTabHelper->SetBrowser(self.browser); } if (!IsIPadIdiom()) { @@ -2604,10 +2604,10 @@ - (void)uninstallDelegatesForWebState:(web::WebState*)webState { DCHECK_EQ(webState->GetDelegate(), _webStateDelegate.get()); - // TODO(crbug.com/777557): do not pass the dispatcher to PasswordTabHelper. + // TODO(crbug.com/1069763): do not pass the browser to PasswordTabHelper. if (PasswordTabHelper* passwordTabHelper = PasswordTabHelper::FromWebState(webState)) { - passwordTabHelper->SetDispatcher(nil); + passwordTabHelper->SetBrowser(self.browser); } if (!IsIPadIdiom()) {
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_app_interface.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_app_interface.mm index 26b84ea..0e0b7f8 100644 --- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_app_interface.mm +++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_app_interface.mm
@@ -5,7 +5,6 @@ #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_app_interface.h" #import "ios/chrome/app/main_controller.h" -#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/test/app/chrome_test_util.h" #import "ios/chrome/test/app/tab_test_util.h"
diff --git a/ios/chrome/browser/url_loading/BUILD.gn b/ios/chrome/browser/url_loading/BUILD.gn index 3f641faf..86102b08 100644 --- a/ios/chrome/browser/url_loading/BUILD.gn +++ b/ios/chrome/browser/url_loading/BUILD.gn
@@ -36,7 +36,6 @@ "//ios/chrome/browser/prerender", "//ios/chrome/browser/sessions", "//ios/chrome/browser/snapshots", - "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/ntp:util", "//ios/chrome/browser/web", @@ -76,7 +75,6 @@ "//ios/chrome/browser/main:test_support", "//ios/chrome/browser/ntp", "//ios/chrome/browser/search_engines", - "//ios/chrome/browser/tabs", "//ios/chrome/browser/web", "//ios/chrome/browser/web:web_internal", "//ios/chrome/browser/web_state_list",
diff --git a/ios/chrome/browser/url_loading/scene_url_loading_service.mm b/ios/chrome/browser/url_loading/scene_url_loading_service.mm index c8f8a3e..e179464 100644 --- a/ios/chrome/browser/url_loading/scene_url_loading_service.mm +++ b/ios/chrome/browser/url_loading/scene_url_loading_service.mm
@@ -7,7 +7,6 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" -#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/url_loading/url_loading_browser_agent.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/web_state_list/web_state_list.h"
diff --git a/ios/chrome/browser/url_loading/url_loading_browser_agent_unittest.mm b/ios/chrome/browser/url_loading/url_loading_browser_agent_unittest.mm index da2fe86..8a67b94 100644 --- a/ios/chrome/browser/url_loading/url_loading_browser_agent_unittest.mm +++ b/ios/chrome/browser/url_loading/url_loading_browser_agent_unittest.mm
@@ -14,8 +14,6 @@ #include "ios/chrome/browser/main/test_browser.h" #import "ios/chrome/browser/ntp/new_tab_page_tab_helper.h" #import "ios/chrome/browser/ntp/new_tab_page_tab_helper_delegate.h" -#import "ios/chrome/browser/tabs/tab_helper_util.h" -#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/url_loading/scene_url_loading_service.h" #import "ios/chrome/browser/url_loading/test_scene_url_loading_service.h" #import "ios/chrome/browser/url_loading/url_loading_notifier_browser_agent.h"
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc index 5ebd3ca..906861b 100644 --- a/media/gpu/chromeos/video_decoder_pipeline.cc +++ b/media/gpu/chromeos/video_decoder_pipeline.cc
@@ -319,7 +319,7 @@ DCHECK(!client_reset_cb_); DVLOGF(3); - need_notify_decoder_flushed_ = false; + need_apply_new_resolution = false; client_reset_cb_ = std::move(closure); decoder_->Reset( base::BindOnce(&VideoDecoderPipeline::OnResetDone, decoder_weak_this_)); @@ -431,7 +431,7 @@ // After outputting a frame, flush might be completed. CallFlushCbIfNeeded(DecodeStatus::OK); - CallOnPipelineFlushedIfNeeded(); + CallApplyResolutionChangeIfNeeded(); } bool VideoDecoderPipeline::HasPendingFrames() const { @@ -468,19 +468,19 @@ void VideoDecoderPipeline::PrepareChangeResolution() { DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_); DVLOGF(3); - DCHECK(!need_notify_decoder_flushed_); + DCHECK(!need_apply_new_resolution); - need_notify_decoder_flushed_ = true; - CallOnPipelineFlushedIfNeeded(); + need_apply_new_resolution = true; + CallApplyResolutionChangeIfNeeded(); } -void VideoDecoderPipeline::CallOnPipelineFlushedIfNeeded() { +void VideoDecoderPipeline::CallApplyResolutionChangeIfNeeded() { DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_); DVLOGF(3); - if (need_notify_decoder_flushed_ && !HasPendingFrames()) { - need_notify_decoder_flushed_ = false; - decoder_->OnPipelineFlushed(); + if (need_apply_new_resolution && !HasPendingFrames()) { + need_apply_new_resolution = false; + decoder_->ApplyResolutionChange(); } }
diff --git a/media/gpu/chromeos/video_decoder_pipeline.h b/media/gpu/chromeos/video_decoder_pipeline.h index 396055e..030ed90 100644 --- a/media/gpu/chromeos/video_decoder_pipeline.h +++ b/media/gpu/chromeos/video_decoder_pipeline.h
@@ -59,7 +59,7 @@ virtual DmabufVideoFramePool* GetVideoFramePool() const = 0; // After this method is called from |decoder_|, the client needs to call - // DecoderInterface::OnPipelineFlushed() when all pending frames are + // DecoderInterface::ApplyResolutionChange() when all pending frames are // flushed. virtual void PrepareChangeResolution() = 0; @@ -114,7 +114,7 @@ // After DecoderInterface calls |prepare_change_resolution_cb| passed // from the constructor, this method is called when the pipeline flushes // pending frames. - virtual void OnPipelineFlushed() = 0; + virtual void ApplyResolutionChange() = 0; protected: // Decoder task runner. All public methods of @@ -217,8 +217,8 @@ // i.e. |image_processor_| or |frame_converter_| has pending frames. bool HasPendingFrames() const; - // Call DecoderInterface::OnPipelineFlushed() when we need to. - void CallOnPipelineFlushedIfNeeded(); + // Call DecoderInterface::ApplyResolutionChange() when we need to. + void CallApplyResolutionChangeIfNeeded(); // Call |client_flush_cb_| with |status|. void CallFlushCbIfNeeded(DecodeStatus status); @@ -271,8 +271,8 @@ base::OnceClosure client_reset_cb_; // True if we need to notify |decoder_| that the pipeline is flushed via - // DecoderInterface::OnPipelineFlushed(). - bool need_notify_decoder_flushed_ = false; + // DecoderInterface::ApplyResolutionChange(). + bool need_apply_new_resolution = false; // True if the decoder needs bitstream conversion before decoding. bool needs_bitstream_conversion_ = false;
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc index bc2176e..58f99f4 100644 --- a/media/gpu/v4l2/v4l2_device.cc +++ b/media/gpu/v4l2/v4l2_device.cc
@@ -886,7 +886,8 @@ } std::pair<base::Optional<struct v4l2_format>, int> V4L2Queue::GetFormat() { - struct v4l2_format format = {}; + struct v4l2_format format; + memset(&format, 0, sizeof(format)); format.type = type_; if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) { VPQLOGF(2) << "Failed to get format";
diff --git a/media/gpu/v4l2/v4l2_slice_video_decoder.cc b/media/gpu/v4l2/v4l2_slice_video_decoder.cc index aa5526e..7cd43f2 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decoder.cc +++ b/media/gpu/v4l2/v4l2_slice_video_decoder.cc
@@ -425,7 +425,7 @@ client_->PrepareChangeResolution(); } -void V4L2SliceVideoDecoder::OnPipelineFlushed() { +void V4L2SliceVideoDecoder::ApplyResolutionChange() { DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_); DVLOGF(3); DCHECK(continue_change_resolution_cb_);
diff --git a/media/gpu/v4l2/v4l2_slice_video_decoder.h b/media/gpu/v4l2/v4l2_slice_video_decoder.h index 801edede..d5b82bb 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decoder.h +++ b/media/gpu/v4l2/v4l2_slice_video_decoder.h
@@ -55,7 +55,7 @@ const OutputCB& output_cb) override; void Reset(base::OnceClosure closure) override; void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override; - void OnPipelineFlushed() override; + void ApplyResolutionChange() override; // V4L2VideoDecoderBackend::Client implementation void OnBackendError() override;
diff --git a/media/gpu/vaapi/vaapi_video_decoder.cc b/media/gpu/vaapi/vaapi_video_decoder.cc index b7f676a..c97f1a0 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.cc +++ b/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -240,7 +240,7 @@ case AcceleratedVideoDecoder::kConfigChange: // A new set of output buffers is requested. We either didn't have any // output buffers yet or encountered a resolution change. - // After the pipeline flushes all frames, OnPipelineFlushed() will be + // After the pipeline flushes all frames, ApplyResolutionChange() will be // called and we can start changing resolution. DCHECK(client_); SetState(State::kChangingResolution); @@ -392,7 +392,7 @@ output_cb_.Run(std::move(video_frame)); } -void VaapiVideoDecoder::OnPipelineFlushed() { +void VaapiVideoDecoder::ApplyResolutionChange() { DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_); DCHECK(state_ == State::kChangingResolution || state_ == State::kWaitingForInput);
diff --git a/media/gpu/vaapi/vaapi_video_decoder.h b/media/gpu/vaapi/vaapi_video_decoder.h index 01e282d..db186f1 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.h +++ b/media/gpu/vaapi/vaapi_video_decoder.h
@@ -54,7 +54,7 @@ const OutputCB& output_cb) override; void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override; void Reset(base::OnceClosure reset_cb) override; - void OnPipelineFlushed() override; + void ApplyResolutionChange() override; // DecodeSurfaceHandler<VASurface> implementation. scoped_refptr<VASurface> CreateSurface() override;
diff --git a/printing/BUILD.gn b/printing/BUILD.gn index 6fce8a07..08997f4 100644 --- a/printing/BUILD.gn +++ b/printing/BUILD.gn
@@ -331,6 +331,7 @@ "page_range_unittest.cc", "page_setup_unittest.cc", "print_settings_conversion_unittest.cc", + "print_settings_unittest.cc", "printing_test.h", "printing_utils_unittest.cc", "units_unittest.cc",
diff --git a/printing/print_settings_unittest.cc b/printing/print_settings_unittest.cc new file mode 100644 index 0000000..295e9cb --- /dev/null +++ b/printing/print_settings_unittest.cc
@@ -0,0 +1,42 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "printing/print_settings.h" + +#include "base/test/gtest_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace printing { + +TEST(PrintSettingsTest, IsColorModelSelected) { + { + base::Optional<bool> color(IsColorModelSelected(COLOR)); + ASSERT_TRUE(color.has_value()); + EXPECT_TRUE(color.value()); + } + { + base::Optional<bool> gray(IsColorModelSelected(GRAY)); + ASSERT_TRUE(gray.has_value()); + EXPECT_FALSE(gray.value()); + } + { + // Test lower bound validity. + base::Optional<bool> lower(IsColorModelSelected(UNKNOWN_COLOR_MODEL + 1)); + EXPECT_TRUE(lower.has_value()); + } + { + // Test upper bound validity. + base::Optional<bool> upper(IsColorModelSelected(COLOR_MODEL_LAST)); + EXPECT_TRUE(upper.has_value()); + } +} + +TEST(PrintSettingsDeathTest, IsColorModelSelectedUnknown) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + EXPECT_DCHECK_DEATH(IsColorModelSelected(UNKNOWN_COLOR_MODEL)); + EXPECT_DCHECK_DEATH(IsColorModelSelected(UNKNOWN_COLOR_MODEL - 1)); + EXPECT_DCHECK_DEATH(IsColorModelSelected(COLOR_MODEL_LAST + 1)); +} + +} // namespace printing
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index f8991a6..99cac1d4 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -6608,8 +6608,8 @@ mojom::kBrowserProcessId, std::move(factory_params)); EXPECT_EQ(client->completion_status().error_code, net::ERR_TRUST_TOKEN_OPERATION_FAILED); - EXPECT_THAT(client->completion_status().trust_token_operation_status, - Optional(mojom::TrustTokenOperationStatus::kUnavailable)); + EXPECT_EQ(client->completion_status().trust_token_operation_status, + mojom::TrustTokenOperationStatus::kUnavailable); } } // namespace
diff --git a/services/network/public/cpp/url_loader_completion_status.h b/services/network/public/cpp/url_loader_completion_status.h index ef883a9a..f6dfe60 100644 --- a/services/network/public/cpp/url_loader_completion_status.h +++ b/services/network/public/cpp/url_loader_completion_status.h
@@ -71,7 +71,16 @@ // Optional Trust Tokens (https://github.com/wicg/trust-token-api) error // details. - base::Optional<mojom::TrustTokenOperationStatus> trust_token_operation_status; + // + // A non-kOk value denotes that the request failed because a Trust Tokens + // operation was attempted and failed for the given reason. + // + // The status is set to kOk in all other cases. In particular, a value of kOk + // does not imply that a Trust Tokens operation was executed successfully + // alongside this request, or even that a Trust Tokens operation was + // attempted. + mojom::TrustTokenOperationStatus trust_token_operation_status = + mojom::TrustTokenOperationStatus::kOk; // Optional SSL certificate info. base::Optional<net::SSLInfo> ssl_info;
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 2664641..da03acd 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -1622,7 +1622,8 @@ status.proxy_server = url_request_->proxy_server(); status.resolve_error_info = url_request_->response_info().resolve_error_info; - status.trust_token_operation_status = trust_token_status_; + if (trust_token_status_) + status.trust_token_operation_status = *trust_token_status_; if ((options_ & mojom::kURLLoadOptionSendSSLInfoForCertificateError) && net::IsCertStatusError(url_request_->ssl_info().cert_status)) {
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index 2e38c68..2f99c4fe 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -4965,8 +4965,8 @@ delete_run_loop.Run(); EXPECT_EQ(client()->completion_status().error_code, net::OK); - EXPECT_THAT(client()->completion_status().trust_token_operation_status, - Optional(mojom::TrustTokenOperationStatus::kOk)); + EXPECT_EQ(client()->completion_status().trust_token_operation_status, + mojom::TrustTokenOperationStatus::kOk); // The page should still have loaded. base::FilePath file = GetTestFilePath("simple_page.html"); std::string expected; @@ -5020,8 +5020,8 @@ EXPECT_EQ(client()->completion_status().error_code, net::ERR_TRUST_TOKEN_OPERATION_CACHE_HIT); - EXPECT_THAT(client()->completion_status().trust_token_operation_status, - Optional(mojom::TrustTokenOperationStatus::kAlreadyExists)); + EXPECT_EQ(client()->completion_status().trust_token_operation_status, + mojom::TrustTokenOperationStatus::kAlreadyExists); EXPECT_FALSE(client()->response_head()); EXPECT_FALSE(client()->response_body().is_valid()); @@ -5062,8 +5062,8 @@ EXPECT_EQ(client()->completion_status().error_code, net::ERR_TRUST_TOKEN_OPERATION_FAILED); - EXPECT_THAT(client()->completion_status().trust_token_operation_status, - Optional(mojom::TrustTokenOperationStatus::kFailedPrecondition)); + EXPECT_EQ(client()->completion_status().trust_token_operation_status, + mojom::TrustTokenOperationStatus::kFailedPrecondition); EXPECT_FALSE(client()->response_head()); EXPECT_FALSE(client()->response_body().is_valid()); @@ -5104,8 +5104,8 @@ EXPECT_EQ(client()->completion_status().error_code, net::ERR_TRUST_TOKEN_OPERATION_FAILED); - EXPECT_THAT(client()->completion_status().trust_token_operation_status, - Optional(mojom::TrustTokenOperationStatus::kBadResponse)); + EXPECT_EQ(client()->completion_status().trust_token_operation_status, + mojom::TrustTokenOperationStatus::kBadResponse); } // When URLLoader receives a request parameterized to perform a Trust Tokens @@ -5145,8 +5145,8 @@ EXPECT_EQ(client()->completion_status().error_code, net::ERR_TRUST_TOKEN_OPERATION_FAILED); - EXPECT_THAT(client()->completion_status().trust_token_operation_status, - Optional(mojom::TrustTokenOperationStatus::kInternalError)); + EXPECT_EQ(client()->completion_status().trust_token_operation_status, + mojom::TrustTokenOperationStatus::kInternalError); } } // namespace network
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 990fd1b..1211bcbc 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -521,8 +521,8 @@ if (skia_use_dawn) { public_deps += [ "//third_party/dawn/src/dawn:dawncpp_headers" ] deps += [ + "//third_party/dawn/src/dawn:dawn_proc", "//third_party/dawn/src/dawn:dawncpp", - "//third_party/dawn/src/dawn:libdawn_proc", "//third_party/dawn/src/dawn_native", ] }
diff --git a/testing/gmock/BUILD.gn b/testing/gmock/BUILD.gn index c62825a..0e7cc53 100644 --- a/testing/gmock/BUILD.gn +++ b/testing/gmock/BUILD.gn
@@ -10,7 +10,6 @@ testonly = true sources = [ "include/gmock/gmock-actions.h", - "include/gmock/gmock-generated-function-mockers.h", "include/gmock/gmock-matchers.h", "include/gmock/gmock.h", ]
diff --git a/testing/gmock/include/gmock/gmock-generated-function-mockers.h b/testing/gmock/include/gmock/gmock-generated-function-mockers.h deleted file mode 100644 index b9986c7..0000000 --- a/testing/gmock/include/gmock/gmock-generated-function-mockers.h +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// The file/directory layout of Google Test is not yet considered stable. Until -// it stabilizes, Chromium code will use forwarding headers in testing/gtest -// and testing/gmock, instead of directly including files in -// third_party/googletest. - -#include "third_party/googletest/src/googlemock/include/gmock/gmock-generated-function-mockers.h"
diff --git a/third_party/blink/public/blink_typemaps.gni b/third_party/blink/public/blink_typemaps.gni index 397290a7..13192d8 100644 --- a/third_party/blink/public/blink_typemaps.gni +++ b/third_party/blink/public/blink_typemaps.gni
@@ -12,6 +12,4 @@ "//services/viz/public/cpp/compositing/returned_resource.typemap", "//services/viz/public/cpp/compositing/surface_id.typemap", "//services/viz/public/cpp/compositing/surface_info.typemap", - "//ui/display/mojom/display_rotation_for_blink.typemap", - "//ui/gfx/mojom/gpu_fence_handle_for_blink.typemap", ]
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn index 402f79f2..13ba2da 100644 --- a/third_party/blink/public/common/BUILD.gn +++ b/third_party/blink/public/common/BUILD.gn
@@ -130,7 +130,6 @@ "notifications/notification_resources.h", "notifications/platform_notification_data.h", "oom_intervention/oom_intervention_types.h", - "origin_policy/origin_policy.h", "origin_trials/origin_trial_policy.h", "origin_trials/trial_token.h", "origin_trials/trial_token_validator.h",
diff --git a/third_party/blink/public/common/origin_policy/OWNERS b/third_party/blink/public/common/origin_policy/OWNERS deleted file mode 100644 index cc8f52f4..0000000 --- a/third_party/blink/public/common/origin_policy/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://third_party/blink/common/origin_policy/OWNERS
diff --git a/third_party/blink/public/common/origin_policy/origin_policy.h b/third_party/blink/public/common/origin_policy/origin_policy.h deleted file mode 100644 index b4ee595..0000000 --- a/third_party/blink/public/common/origin_policy/origin_policy.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_POLICY_ORIGIN_POLICY_H_ -#define THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_POLICY_ORIGIN_POLICY_H_ - -#include <memory> -#include <set> -#include <string> -#include <vector> - -#include "base/strings/string_piece.h" -#include "third_party/blink/public/common/common_export.h" -#include "url/origin.h" - -namespace blink { - -class OriginPolicyParser; - -class BLINK_COMMON_EXPORT OriginPolicy { - public: - ~OriginPolicy(); - - // Create & parse the manifest. - static std::unique_ptr<OriginPolicy> From(base::StringPiece); - - struct CSP { - std::string policy; - bool report_only; - }; - const std::vector<CSP>& GetContentSecurityPolicies() const { return csp_; } - - const std::vector<std::string>& GetFeaturePolicies() const { - return features_; - } - - const std::set<url::Origin>& GetFirstPartySet() const { - return first_party_set_; - } - - private: - friend class OriginPolicyParser; - - OriginPolicy(); - - std::vector<CSP> csp_; - std::vector<std::string> features_; - std::set<url::Origin> first_party_set_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_ORIGIN_POLICY_ORIGIN_POLICY_H_
diff --git a/third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom b/third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom index bd79dea3..ca03424 100644 --- a/third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom +++ b/third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom
@@ -6,7 +6,7 @@ // These values map to the features which can be controlled by Document Policy. enum DocumentPolicyFeature { - kNotFound = 0, + kDefault = 0, // Controls access to font-display attribute in @font-face CSS rule kFontDisplay = 1, // Takes a parameter, |bpp|, i.e. byte-per-pixel ratio, that images
diff --git a/third_party/blink/public/platform/DEPS b/third_party/blink/public/platform/DEPS index 07cfbe0..4a8c2f8 100644 --- a/third_party/blink/public/platform/DEPS +++ b/third_party/blink/public/platform/DEPS
@@ -45,6 +45,7 @@ "+services/network/public/mojom/cors.mojom-shared.h", "+services/network/public/mojom/fetch_api.mojom-shared.h", "+services/network/public/mojom/referrer_policy.mojom-shared.h", + "+services/network/public/mojom/trust_tokens.mojom-shared.h", "+services/network/public/mojom/web_client_hints_types.mojom-shared.h", "+services/service_manager/public/mojom",
diff --git a/third_party/blink/public/platform/web_url_error.h b/third_party/blink/public/platform/web_url_error.h index b7b3a60..c555176 100644 --- a/third_party/blink/public/platform/web_url_error.h +++ b/third_party/blink/public/platform/web_url_error.h
@@ -36,6 +36,7 @@ #include "net/dns/public/resolve_error_info.h" #include "services/network/public/cpp/blocked_by_response_reason.h" #include "services/network/public/cpp/cors/cors_error_status.h" +#include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "third_party/blink/public/platform/web_url.h" namespace blink { @@ -71,6 +72,16 @@ HasCopyInCache, const WebURL&); + // Constructs a new error for a request failing due to a Trust Tokens error. + // This takes an integer error code in addition to a TrustTokenOperationStatus + // because there are multiple Trust Tokens //net error codes. + // + // |trust_token_operation_error| must be an actual error (i.e., not kOk). + BLINK_PLATFORM_EXPORT WebURLError( + int reason, + network::mojom::TrustTokenOperationStatus trust_token_operation_error, + const WebURL& url); + int reason() const { return reason_; } int extended_reason() const { return extended_reason_; } const net::ResolveErrorInfo& resolve_error_info() const { @@ -86,6 +97,10 @@ blocked_by_response_reason() const { return blocked_by_response_reason_; } + network::mojom::TrustTokenOperationStatus trust_token_operation_error() + const { + return trust_token_operation_error_; + } private: // A numeric error code detailing the reason for this error. The value must @@ -114,6 +129,16 @@ // More detailed reason for failing the response with // ERR_net::ERR_BLOCKED_BY_RESPONSE |error_code|. base::Optional<network::BlockedByResponseReason> blocked_by_response_reason_; + + // More detailed reason for failing the response with + // net::ERR_TRUST_TOKEN_OPERATION_FAILED or + // net::ERR_TRUST_TOKEN_OPERATION_CACHE_HIT. + // + // A value of kOk means that this request failed for a reason other than a + // Trust Tokens operation failure. This does not necessarily mean that a Trust + // Tokens operation was executed successfully, or even that one was attempted. + network::mojom::TrustTokenOperationStatus trust_token_operation_error_ = + network::mojom::TrustTokenOperationStatus::kOk; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc b/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc index 3a5b825..3d314f5 100644 --- a/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc +++ b/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
@@ -16,7 +16,8 @@ const BeginFrameProviderParams& begin_frame_provider_params) : begin_frame_provider_( MakeGarbageCollected<BeginFrameProvider>(begin_frame_provider_params, - this)), + this, + context)), callback_collection_(context), context_(context) {}
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index 4aacd0d..89289906 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -449,31 +449,33 @@ DisplayLockContext::ScopedForcedUpdate DisplayLockContext::GetScopedForcedUpdate() { - if (!is_locked_) - return ScopedForcedUpdate(nullptr); + ++update_forced_; + if (update_forced_ == 1) { + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( + TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), "LockForced", + TRACE_ID_LOCAL(this)); + } - DCHECK(!update_forced_); - update_forced_ = true; - TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( - TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), "LockForced", - TRACE_ID_LOCAL(this)); - - // Now that the update is forced, we should ensure that style layout, and - // prepaint code can reach it via dirty bits. Note that paint isn't a part of - // this, since |update_forced_| doesn't force paint to happen. See - // ShouldPaint(). - MarkForStyleRecalcIfNeeded(); - MarkForLayoutIfNeeded(); - MarkAncestorsForPrePaintIfNeeded(); + if (IsLocked()) { + // Now that the update is forced, we should ensure that style layout, and + // prepaint code can reach it via dirty bits. Note that paint isn't a part + // of this, since |update_forced_| doesn't force paint to happen. See + // ShouldPaint(). + MarkForStyleRecalcIfNeeded(); + MarkForLayoutIfNeeded(); + MarkAncestorsForPrePaintIfNeeded(); + } return ScopedForcedUpdate(this); } void DisplayLockContext::NotifyForcedUpdateScopeEnded() { DCHECK(update_forced_); - update_forced_ = false; - TRACE_EVENT_NESTABLE_ASYNC_END0( - TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), "LockForced", - TRACE_ID_LOCAL(this)); + --update_forced_; + if (update_forced_ == 0) { + TRACE_EVENT_NESTABLE_ASYNC_END0( + TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), "LockForced", + TRACE_ID_LOCAL(this)); + } } void DisplayLockContext::Unlock() { @@ -605,7 +607,7 @@ if (IsElementDirtyForLayout()) { // Forces the marking of ancestors to happen, even if // |DisplayLockContext::ShouldLayout()| returns false. - base::AutoReset<bool> scoped_force(&update_forced_, true); + base::AutoReset<int> scoped_force(&update_forced_, update_forced_ + 1); if (child_layout_was_blocked_) { // We've previously blocked a child traversal when doing self-layout for // the locked element, so we're marking it with child-needs-layout so that
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h index 870b662..f285130 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.h +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -328,7 +328,8 @@ // style recalc on them. HeapHashSet<Member<Element>> whitespace_reattach_set_; - bool update_forced_ = false; + // If non-zero, then the update has been forced. + int update_forced_ = 0; StyleType blocked_style_traversal_type_ = kStyleUpdateNotRequired; // Signifies whether we've blocked a layout tree reattachment on |element_|'s
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc index eb7c5e57..bd0aa6e 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -51,8 +51,6 @@ reason)) { DCHECK(locked_activatable_ancestor->GetDisplayLockContext()); DCHECK(locked_activatable_ancestor->GetDisplayLockContext()->IsLocked()); - DCHECK(!locked_activatable_ancestor->GetDisplayLockContext() - ->UpdateForced()); scoped_forced_update_list_.push_back( locked_activatable_ancestor->GetDisplayLockContext() ->GetScopedForcedUpdate()); @@ -212,10 +210,8 @@ auto* ancestor_node = DynamicTo<Element>(ancestor); if (!ancestor_node) continue; - if (auto* context = ancestor_node->GetDisplayLockContext()) { - DCHECK(!context->UpdateForced()); + if (auto* context = ancestor_node->GetDisplayLockContext()) scoped_update_forced_list_.push_back(context->GetScopedForcedUpdate()); - } } }
diff --git a/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc b/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc index fb58514..0d398fe 100644 --- a/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc +++ b/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc
@@ -11,6 +11,10 @@ namespace { +constexpr const char* kReportTo = "report-to"; +constexpr const char* kNone = "none"; +constexpr const char* kWildCard = "*"; + base::Optional<PolicyValue> ItemToPolicyValue( const net::structured_headers::Item& item) { switch (item.Type()) { @@ -34,8 +38,32 @@ mojom::blink::DocumentPolicyFeature feature; PolicyValue policy_value; base::Optional<std::string> endpoint_group; + // Wildcard feature('*') is used to specify default endpoint for features. + bool is_wildcard = false; }; +base::Optional<ParsedFeature> ParseWildcardFeature( + const net::structured_headers::ParameterizedMember& directive) { + // Wildcard feature can only have 1 param, which is 'report-to'. + if (directive.params.size() != 1) + return base::nullopt; + + const auto& param = directive.params.front(); + + // Wildcard feature can only have 1 param, which is 'report-to'. + if (param.first != kReportTo) + return base::nullopt; + + base::Optional<std::string> endpoint_group = ItemToString(param.second); + + if (!endpoint_group) + return base::nullopt; + + return base::make_optional<ParsedFeature>( + {mojom::blink::DocumentPolicyFeature::kDefault, PolicyValue(), + endpoint_group, true}); +} + base::Optional<ParsedFeature> ParseFeature( const net::structured_headers::ParameterizedMember& directive, const DocumentPolicyNameFeatureMap& name_feature_map, @@ -59,6 +87,10 @@ return base::nullopt; std::string feature_name = feature_token.GetString(); + + if (feature_name == kWildCard) + return ParseWildcardFeature(directive); + auto feature_iter = name_feature_map.find(feature_name); // Parse feature_name string to DocumentPolicyFeature. @@ -98,7 +130,7 @@ // Document-Policy header that specifies the endpoint group that the policy // should send report to. If left unspecified, no report will be send upon // policy violation. - if (param_name == "report-to") { + if (param_name == kReportTo) { base::Optional<std::string> endpoint_group = ItemToString(param.second); if (!endpoint_group) return base::nullopt; @@ -132,6 +164,35 @@ return parsed_feature; } +// Apply |default_endpoint| to given |parsed_policy|. +void ApplyDefaultEndpoint(DocumentPolicy::ParsedDocumentPolicy& parsed_policy, + const std::string& default_endpoint) { + DocumentPolicy::FeatureEndpointMap& endpoint_map = parsed_policy.endpoint_map; + + if (!default_endpoint.empty()) { + // Fill |default_endpoint| to all feature entry whose |endpoint_group| + // is missing. + for (const auto& feature_and_value : parsed_policy.feature_state) { + mojom::blink::DocumentPolicyFeature feature = feature_and_value.first; + + if (endpoint_map.find(feature) == endpoint_map.end()) + endpoint_map.emplace(feature, default_endpoint); + } + } + + // Remove |endpoint_group| for feature entry if its |endpoint_group| + // is "none". + // Note: if |default_endpoint| is "none", all "none" items are filtered out + // here. it would be equivalent to doing nothing. + for (auto iter = endpoint_map.begin(); iter != endpoint_map.end();) { + if (iter->second == kNone) { + iter = endpoint_map.erase(iter); + } else { + ++iter; + } + } +} + } // namespace // static @@ -157,6 +218,7 @@ return base::nullopt; DocumentPolicy::ParsedDocumentPolicy parse_result; + std::string default_endpoint = ""; for (const net::structured_headers::ParameterizedMember& directive : root.value()) { base::Optional<ParsedFeature> parsed_feature_option = @@ -167,6 +229,11 @@ ParsedFeature parsed_feature = *parsed_feature_option; + if (parsed_feature.is_wildcard) { + default_endpoint = *parsed_feature.endpoint_group; + continue; + } + // If feature is not available, i.e. not enabled, ignore the entry. if (available_features.find(parsed_feature.feature) == available_features.end()) @@ -179,6 +246,9 @@ *parsed_feature.endpoint_group); } } + + ApplyDefaultEndpoint(parse_result, default_endpoint); + return parse_result; }
diff --git a/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc b/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc index d4324757..f13f639 100644 --- a/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc +++ b/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc
@@ -63,6 +63,10 @@ "no-f-bool;report-to=default,f-double;value=2.0;report-to=default", "no-f-bool;report-to=default,f-double;report-to=default;value=2.0", "no-f-bool;report-to=default,f-double;report-to=endpoint;value=2.0", + "no-f-bool,f-double;value=2.0;report-to=endpoint,*;report-to=default", + "*;report-to=default", // An empty policy. + "no-f-bool;report-to=none, f-double;value=2.0, *;report-to=default", + "no-f-bool;report-to=none, f-double;value=2.0, *;report-to=none", }; const char* const kInvalidPolicies[] = { @@ -116,7 +120,43 @@ {"no-f-bool;report-to=default,f-double;value=1", {{{kBoolFeature, PolicyValue(false)}, {kDoubleFeature, PolicyValue(1.0)}}, - {{kBoolFeature, "default"}}}}}; + {{kBoolFeature, "default"}}}}, + {"no-f-bool;report-to=none, f-double;value=2.0, *;report-to=default", + {/* feature_state */ {{kBoolFeature, PolicyValue(false)}, + {kDoubleFeature, PolicyValue(2.0)}}, + /* endpoint_map */ {{kDoubleFeature, "default"}}}}, + {"no-f-bool;report-to=not_none, f-double;value=2.0, " + "*;report-to=default", + {/* feature_state */ {{kBoolFeature, PolicyValue(false)}, + {kDoubleFeature, PolicyValue(2.0)}}, + /* endpoint_map */ {{kBoolFeature, "not_none"}, + {kDoubleFeature, "default"}}}}, + {"no-f-bool;report-to=not_none, f-double;value=2.0, *;report-to=none", + {/* feature_state */ {{kBoolFeature, PolicyValue(false)}, + {kDoubleFeature, PolicyValue(2.0)}}, + /* endpoint_map */ {{kBoolFeature, "not_none"}}}}, + // Default endpoint can be specified anywhere in the header, not + // necessary at the end. + {"no-f-bool;report-to=not_none, *;report-to=default, " + "f-double;value=2.0", + {/* feature_state */ {{kBoolFeature, PolicyValue(false)}, + {kDoubleFeature, PolicyValue(2.0)}}, + /* endpoint_map */ {{kBoolFeature, "not_none"}, + {kDoubleFeature, "default"}}}}, + // Default endpoint can be specified multiple times in the header. + // According to SH rules, last value wins. + {"no-f-bool;report-to=not_none, f-double;value=2.0, " + "*;report-to=default, " + "*;report-to=none", + {/* feature_state */ {{kBoolFeature, PolicyValue(false)}, + {kDoubleFeature, PolicyValue(2.0)}}, + /* endpoint_map */ {{kBoolFeature, "not_none"}}}}, + // Even if default endpoint is not specified, none still should be + // treated as a reserved keyword for endpoint names. + {"no-f-bool;report-to=none", + {/* feature_state */ {{kBoolFeature, PolicyValue(false)}}, + /* endpoint_map */ {}}}, +}; const DocumentPolicy::FeatureState kParsedPolicies[] = { {}, // An empty policy
diff --git a/third_party/blink/renderer/core/fetch/fetch_manager.cc b/third_party/blink/renderer/core/fetch/fetch_manager.cc index 5c62a59..d02e450 100644 --- a/third_party/blink/renderer/core/fetch/fetch_manager.cc +++ b/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -12,10 +12,12 @@ #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/request_mode.h" #include "services/network/public/mojom/fetch_api.mojom-blink.h" +#include "services/network/public/mojom/trust_tokens.mojom-blink.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/public/platform/web_url_request.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/v8_response_init.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/core/dom/abort_signal.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" @@ -25,6 +27,7 @@ #include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h" #include "third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.h" #include "third_party/blink/renderer/core/fetch/response.h" +#include "third_party/blink/renderer/core/fetch/trust_token_to_mojom.h" #include "third_party/blink/renderer/core/fileapi/blob.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/frame.h" @@ -226,7 +229,9 @@ void PerformNetworkError(const String& message); void PerformHTTPFetch(ExceptionState&); void PerformDataFetch(); - void Failed(const String& message); + // If |dom_exception| is provided, throws the specified DOMException instead + // of the usual "Failed to fetch" TypeError. + void Failed(const String& message, DOMException* dom_exception); void NotifyFinished(); ExecutionContext* GetExecutionContext() { return execution_context_; } @@ -530,11 +535,18 @@ } void FetchManager::Loader::DidFail(const ResourceError& error) { - Failed(String()); + if (error.TrustTokenOperationError() != + network::mojom::blink::TrustTokenOperationStatus::kOk) { + Failed(String(), + TrustTokenErrorToDOMException(error.TrustTokenOperationError())); + return; + } + + Failed(String(), nullptr); } void FetchManager::Loader::DidFailRedirectCheck() { - Failed(String()); + Failed(String(), nullptr); } void FetchManager::Loader::Start(ExceptionState& exception_state) { @@ -690,7 +702,7 @@ } void FetchManager::Loader::PerformNetworkError(const String& message) { - Failed(message); + Failed(message, nullptr); } void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) { @@ -832,7 +844,8 @@ threadable_loader_->Start(request); } -void FetchManager::Loader::Failed(const String& message) { +void FetchManager::Loader::Failed(const String& message, + DOMException* dom_exception) { if (failed_ || finished_) return; failed_ = true; @@ -846,8 +859,12 @@ if (resolver_) { ScriptState* state = resolver_->GetScriptState(); ScriptState::Scope scope(state); - resolver_->Reject(V8ThrowException::CreateTypeError(state->GetIsolate(), - "Failed to fetch")); + if (dom_exception) { + resolver_->Reject(dom_exception); + } else { + resolver_->Reject(V8ThrowException::CreateTypeError(state->GetIsolate(), + "Failed to fetch")); + } } NotifyFinished(); }
diff --git a/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc b/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc index 1fe53b72..c0064caf 100644 --- a/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc +++ b/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "third_party/blink/renderer/core/fetch/trust_token_to_mojom.h" +#include "third_party/blink/renderer/core/dom/dom_exception.h" namespace blink { @@ -87,4 +88,27 @@ return true; } +DOMException* TrustTokenErrorToDOMException( + network::mojom::blink::TrustTokenOperationStatus error) { + // This should only be called on failure. + DCHECK_NE(error, network::mojom::blink::TrustTokenOperationStatus::kOk); + + switch (error) { + case network::mojom::blink::TrustTokenOperationStatus::kAlreadyExists: + return DOMException::Create( + "Redemption operation aborted due to Signed Redemption Record " + "cache hit", + DOMException::GetErrorName( + DOMExceptionCode::kNoModificationAllowedError)); + case network::mojom::blink::TrustTokenOperationStatus::kFailedPrecondition: + return DOMException::Create( + "Precondition failed during Trust Tokens operation", + DOMException::GetErrorName(DOMExceptionCode::kInvalidStateError)); + default: + return DOMException::Create( + "Error executing Trust Tokens operation", + DOMException::GetErrorName(DOMExceptionCode::kOperationError)); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h b/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h index 680f710..4097c23 100644 --- a/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h +++ b/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h
@@ -11,6 +11,8 @@ namespace blink { +class DOMException; + // Converts an IDL trustToken object to its Mojo counterpart. // The elements of trustToken (and of TrustTokenParams) comprise: // - an operation type, always populated @@ -32,6 +34,13 @@ ExceptionState* exception_state, network::mojom::blink::TrustTokenParams* out); +// Converts a Mojo TrustTokenOperationStatus denoting an error into a +// DOMException suitable for displaying to the API's client. +// +// This should only be called on failure; |status| must not equal kOk. +DOMException* TrustTokenErrorToDOMException( + network::mojom::blink::TrustTokenOperationStatus error); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_TRUST_TOKEN_TO_MOJOM_H_
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc index 39c0443..de92635 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -1399,14 +1399,6 @@ LogToConsole(message); } -void ContentSecurityPolicy::ReportMissingReportURI(const String& policy) { - LogToConsole("The Content Security Policy '" + policy + - "' was delivered in report-only mode, but does not specify a " - "'report-uri'; the policy will have no effect. Please either " - "add a 'report-uri' directive, or deliver the policy via the " - "'Content-Security-Policy' header."); -} - void ContentSecurityPolicy::LogToConsole(const String& message, mojom::ConsoleMessageLevel level) { LogToConsole(MakeGarbageCollected<ConsoleMessage>(
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.h b/third_party/blink/renderer/core/frame/csp/content_security_policy.h index deb8f0d..22473bea 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.h +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
@@ -382,7 +382,6 @@ void ReportInvalidSandboxFlags(const String&); void ReportInvalidSourceExpression(const String& directive_name, const String& source); - void ReportMissingReportURI(const String&); void ReportUnsupportedDirective(const String&); void ReportInvalidInReportOnly(const String&); void ReportInvalidDirectiveInMeta(const String& directive_name);
diff --git a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc index f6307f0..2f3920be 100644 --- a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc +++ b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
@@ -171,13 +171,6 @@ directives->SetEvalDisabledErrorMessage(message); } - if (directives->IsReportOnly() && - source != ContentSecurityPolicySource::kMeta && - directives->ReportEndpoints().IsEmpty()) { - policy->ReportMissingReportURI( - String(begin, static_cast<wtf_size_t>(end - begin))); - } - return directives; }
diff --git a/third_party/blink/renderer/core/html/resources/android.css b/third_party/blink/renderer/core/html/resources/android.css index 8212135..b6ee01f 100644 --- a/third_party/blink/renderer/core/html/resources/android.css +++ b/third_party/blink/renderer/core/html/resources/android.css
@@ -30,6 +30,12 @@ /* These styles override other user-agent styles for Chromium on Android. */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + input[type="date" i]:disabled, input[type="datetime-local" i]:disabled, input[type="month" i]:disabled,
diff --git a/third_party/blink/renderer/core/html/resources/controls_refresh.css b/third_party/blink/renderer/core/html/resources/controls_refresh.css index d3e87b5..276d0fc 100644 --- a/third_party/blink/renderer/core/html/resources/controls_refresh.css +++ b/third_party/blink/renderer/core/html/resources/controls_refresh.css
@@ -8,6 +8,12 @@ * using the refreshed controls UI. */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + select, select:-internal-list-box, input,
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 c35e7e7..8752b6d 100644 --- a/third_party/blink/renderer/core/html/resources/forced_colors.css +++ b/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -8,6 +8,12 @@ * is enabled. */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + @media forced-colors { body { background-color: Canvas; @@ -223,4 +229,4 @@ background-color: Window !important; } -} \ No newline at end of file +}
diff --git a/third_party/blink/renderer/core/html/resources/input_multiple_fields.css b/third_party/blink/renderer/core/html/resources/input_multiple_fields.css index db849b0..d0591f6 100644 --- a/third_party/blink/renderer/core/html/resources/input_multiple_fields.css +++ b/third_party/blink/renderer/core/html/resources/input_multiple_fields.css
@@ -3,6 +3,12 @@ * found in the LICENSE file. */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + input[type="date" i], input[type="datetime-local" i], input[type="month" i],
diff --git a/third_party/blink/renderer/core/html/resources/linux.css b/third_party/blink/renderer/core/html/resources/linux.css index f45f6c7..847265f 100644 --- a/third_party/blink/renderer/core/html/resources/linux.css +++ b/third_party/blink/renderer/core/html/resources/linux.css
@@ -30,6 +30,12 @@ /* These styles override other user-agent styles for Chromium on Linux. */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + select:not(:-internal-list-box) { /* Selects with popup menus look like buttons with a drop down triangle on Linux. */ background-color: ButtonFace;
diff --git a/third_party/blink/renderer/core/html/resources/mac.css b/third_party/blink/renderer/core/html/resources/mac.css index e575c8e7a..1e1677ba 100644 --- a/third_party/blink/renderer/core/html/resources/mac.css +++ b/third_party/blink/renderer/core/html/resources/mac.css
@@ -3,6 +3,12 @@ * found in the LICENSE file. */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + select, input[type="color" i][list] { /* TODO(tkent): Use ButtonFace and border same as buttons. */ background-color: #f8f8f8;
diff --git a/third_party/blink/renderer/core/html/resources/quirks.css b/third_party/blink/renderer/core/html/resources/quirks.css index e880fe0e..4e9d8a8 100644 --- a/third_party/blink/renderer/core/html/resources/quirks.css +++ b/third_party/blink/renderer/core/html/resources/quirks.css
@@ -21,6 +21,12 @@ * */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + /* Give floated images margins of 3px */ img[align="left" i] { margin-right: 3px;
diff --git a/third_party/blink/renderer/core/html/resources/win.css b/third_party/blink/renderer/core/html/resources/win.css index ce9f3120..c1dfae2 100644 --- a/third_party/blink/renderer/core/html/resources/win.css +++ b/third_party/blink/renderer/core/html/resources/win.css
@@ -32,6 +32,12 @@ core/html/resources/tml.css. So far we have used this file exclusively for making our form elements match Firefox's. */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + /* * Update padding for all text-like types including unknown types. * Non-text types have input[type="foo" i] with padding properties in
diff --git a/third_party/blink/renderer/core/html/resources/win_quirks.css b/third_party/blink/renderer/core/html/resources/win_quirks.css index 196d0820..09e5fbd 100644 --- a/third_party/blink/renderer/core/html/resources/win_quirks.css +++ b/third_party/blink/renderer/core/html/resources/win_quirks.css
@@ -32,6 +32,12 @@ as defined in core/html/resources/quirks.css. So far we have used this file exclusively for making our form elements match Firefox's. */ +/* This sheet is appended to html.css before parsing which means the selectors + below are in the default html namespace: + + @namespace "http://www.w3.org/1999/xhtml" +*/ + textarea { /* Matches IE's text offsets in quirksmode (causes text to wrap the same as IE). */ padding: 2px 0 0 2px;
diff --git a/third_party/blink/renderer/core/layout/layout_theme_mac.mm b/third_party/blink/renderer/core/layout/layout_theme_mac.mm index 90ffe6c..f9912f0 100644 --- a/third_party/blink/renderer/core/layout/layout_theme_mac.mm +++ b/third_party/blink/renderer/core/layout/layout_theme_mac.mm
@@ -161,6 +161,7 @@ return [[NSFileManager defaultManager] displayNameAtPath:file.GetPath()]; return file.name(); } + bool PopsMenuByArrowKeys() const override; protected: // Controls color values returned from FocusRingColor(). @@ -377,6 +378,10 @@ return WebTestSupport::IsRunningWebTest(); } +bool LayoutThemeMacRefresh::PopsMenuByArrowKeys() const { + return true; +} + static FontSelectionValue ToFontWeight(NSInteger app_kit_font_weight) { DCHECK_GT(app_kit_font_weight, 0); DCHECK_LT(app_kit_font_weight, 15);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc index f65bb23..c264b97 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
@@ -74,6 +74,9 @@ } } + if (!use_path_fallback_) + ClearPath(); + fill_bounding_box_ = FloatRect( length_context.ResolveLengthPair(svg_style.X(), svg_style.Y(), style), bounding_box_size);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc index 66bff8d5..6ad438e 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
@@ -69,6 +69,19 @@ TransformHelper::DependsOnReferenceBox(StyleRef()); LayoutSVGModelObject::StyleDidChange(diff, old_style); SVGResources::UpdatePaints(*GetElement(), old_style, StyleRef()); + + // Most of the stroke attributes (caps, joins, miters, width, etc.) will cause + // a re-layout which will clear the stroke-path cache; however, there are a + // couple of additional properties that *won't* cause a layout, but are + // significant enough to require invalidating the cache. + if (!diff.NeedsFullLayout() && old_style && stroke_path_cache_) { + const auto& old_svg_style = old_style->SvgStyle(); + const auto& svg_style = StyleRef().SvgStyle(); + if (old_svg_style.StrokeDashOffset() != svg_style.StrokeDashOffset() || + *old_svg_style.StrokeDashArray() != *svg_style.StrokeDashArray()) { + stroke_path_cache_.reset(); + } + } } void LayoutSVGShape::WillBeDestroyed() { @@ -76,10 +89,20 @@ LayoutSVGModelObject::WillBeDestroyed(); } +void LayoutSVGShape::ClearPath() { + path_.reset(); + stroke_path_cache_.reset(); +} + void LayoutSVGShape::CreatePath() { if (!path_) path_ = std::make_unique<Path>(); *path_ = To<SVGGeometryElement>(GetElement())->AsPath(); + + // When the path changes, we need to ensure the stale stroke path cache is + // cleared. Because this is done in all callsites, we can just DCHECK that it + // has been cleared here. + DCHECK(!stroke_path_cache_); } float LayoutSVGShape::DashScaleFactor() const { @@ -150,24 +173,33 @@ bool LayoutSVGShape::ShapeDependentStrokeContains( const HitTestLocation& location) { - // In case the subclass didn't create path during UpdateShapeFromElement() - // for optimization but still calls this method. - if (!HasPath()) - CreatePath(); + if (!stroke_path_cache_) { + // In case the subclass didn't create path during UpdateShapeFromElement() + // for optimization but still calls this method. + if (!HasPath()) + CreatePath(); - StrokeData stroke_data; - SVGLayoutSupport::ApplyStrokeStyleToStrokeData(stroke_data, StyleRef(), *this, - DashScaleFactor()); + StrokeData stroke_data; + SVGLayoutSupport::ApplyStrokeStyleToStrokeData(stroke_data, StyleRef(), + *this, DashScaleFactor()); - if (HasNonScalingStroke()) { - // The reason is similar to the above code about HasPath(). - if (!rare_data_) - UpdateNonScalingStrokeData(); - return NonScalingStrokePath().StrokeContains( - NonScalingStrokeTransform().MapPoint(location.TransformedPoint()), - stroke_data); + if (HasNonScalingStroke()) { + // The reason is similar to the above code about HasPath(). + if (!rare_data_) + UpdateNonScalingStrokeData(); + stroke_path_cache_ = std::make_unique<Path>( + NonScalingStrokePath().StrokePath(stroke_data)); + } else { + stroke_path_cache_ = + std::make_unique<Path>(path_->StrokePath(stroke_data)); + } } - return path_->StrokeContains(location.TransformedPoint(), stroke_data); + + DCHECK(stroke_path_cache_); + auto point = location.TransformedPoint(); + if (HasNonScalingStroke()) + point = NonScalingStrokeTransform().MapPoint(point); + return stroke_path_cache_->Contains(point); } bool LayoutSVGShape::ShapeDependentFillContains( @@ -217,6 +249,10 @@ if (EverHadLayout() && SelfNeedsLayout()) SVGResourcesCache::ClientLayoutChanged(*this); + // The cached stroke may be affected by the ancestor transform, and so needs + // to be cleared regardless of whether the shape or bounds have changed. + stroke_path_cache_.reset(); + bool update_parent_boundaries = false; bool bbox_changed = false; // UpdateShapeFromElement() also updates the object & stroke bounds - which
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h index 803a52e..615840901 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
@@ -131,7 +131,7 @@ float VisualRectOutsetForRasterEffects() const override; - void ClearPath() { path_.reset(); } + void ClearPath(); void CreatePath(); // Update (cached) shape data and the (object) bounding box. @@ -189,6 +189,7 @@ // into removing it. std::unique_ptr<Path> path_; mutable std::unique_ptr<LayoutSVGShapeRareData> rare_data_; + std::unique_ptr<Path> stroke_path_cache_; StrokeGeometryClass geometry_class_; bool needs_boundaries_update_ : 1;
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 009f19f..1e495e2 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -37,7 +37,6 @@ #include "base/time/default_tick_clock.h" #include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/features.h" -#include "third_party/blink/public/common/origin_policy/origin_policy.h" #include "third_party/blink/public/mojom/commit_result/commit_result.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/web_url_request.h"
diff --git a/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc b/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc index 2ce3837..58b7110 100644 --- a/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc +++ b/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
@@ -7,7 +7,7 @@ #include <base/macros.h> #include <memory> #include "base/memory/scoped_refptr.h" -#include "testing/gmock/include/gmock/gmock-generated-function-mockers.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h" #include "third_party/blink/public/platform/web_mixed_content.h"
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc index 043e3619..75fc370 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -58,6 +58,10 @@ LayoutUnit(box_strut.bottom), LayoutUnit(box_strut.left)); } +inline bool HasSelection(const LayoutObject* layout_object) { + return layout_object->GetSelectionState() != SelectionState::kNone; +} + inline bool IsVisibleToPaint(const NGPhysicalFragment& fragment, const ComputedStyle& style) { return !fragment.IsHiddenForPaint() && @@ -1364,7 +1368,8 @@ if (!paint_info.IntersectsCullRect(child->InkOverflow(), paint_offset + child->Offset()) && // Don't skip empty size text in order to paint selection for <br>. - !(child_fragment.IsText() && child_fragment.Size().IsEmpty())) + !(child_fragment.IsText() && child_fragment.Size().IsEmpty() && + HasSelection(child_fragment.GetLayoutObject()))) continue; if (child_fragment.Type() == NGPhysicalFragment::kFragmentText) { @@ -1437,7 +1442,7 @@ if (!paint_info.IntersectsCullRect( item.InkOverflow(), paint_offset + item.OffsetInContainerBlock()) && // Don't skip <br>, it doesn't have ink but need to paint selection. - !item.IsLineBreak()) + !(item.IsLineBreak() && HasSelection(item.GetLayoutObject()))) return; NGTextFragmentPainter<NGInlineCursor> text_painter(cursor, parent_offset);
diff --git a/third_party/blink/renderer/core/paint/paint_timing.cc b/third_party/blink/renderer/core/paint/paint_timing.cc index 6e71405..32c14a5 100644 --- a/third_party/blink/renderer/core/paint/paint_timing.cc +++ b/third_party/blink/renderer/core/paint/paint_timing.cc
@@ -21,6 +21,7 @@ #include "third_party/blink/renderer/core/timing/dom_window_performance.h" #include "third_party/blink/renderer/core/timing/window_performance.h" #include "third_party/blink/renderer/platform/instrumentation/histogram.h" +#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" @@ -245,6 +246,12 @@ if (interactive_detector) { interactive_detector->OnFirstContentfulPaint(first_contentful_paint_swap_); } + auto* coordinator = GetSupplementable()->GetResourceCoordinator(); + if (coordinator && GetFrame() && GetFrame()->IsMainFrame()) { + PerformanceTiming* timing = performance->timing(); + base::TimeDelta fcp = stamp - timing->NavigationStartAsMonotonicTime(); + coordinator->OnFirstContentfulPaint(fcp); + } } void PaintTiming::SetFirstImagePaintSwap(base::TimeTicks stamp) {
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 721fc7b1..eacf2d3 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -30,6 +30,7 @@ #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/time/time.h" +#include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "third_party/blink/public/common/blob/blob_utils.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h" @@ -1694,6 +1695,12 @@ return; } + if (error.TrustTokenOperationError() != + network::mojom::TrustTokenOperationStatus::kOk) { + trust_token_operation_error_ = + TrustTokenErrorToDOMException(error.TrustTokenOperationError()); + } + HandleNetworkError(); } @@ -2082,6 +2089,7 @@ visitor->Trace(upload_); visitor->Trace(blob_loader_); visitor->Trace(response_text_); + visitor->Trace(trust_token_operation_error_); XMLHttpRequestEventTarget::Trace(visitor); ThreadableLoaderClient::Trace(visitor); DocumentParserClient::Trace(visitor);
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h index ce493b4..bd83562 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" #include "third_party/blink/renderer/bindings/core/v8/v8_trust_token.h" #include "third_party/blink/renderer/core/dom/document_parser_client.h" +#include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/core/loader/threadable_loader_client.h" #include "third_party/blink/renderer/core/probe/async_task_id.h" @@ -159,6 +160,9 @@ String responseType(); void setResponseType(const String&, ExceptionState&); String responseURL(); + DOMException* trustTokenOperationError() const { + return trust_token_operation_error_; + } // For Inspector. void SendForInspectorXHRReplay(scoped_refptr<EncodedFormData>, @@ -303,6 +307,7 @@ AtomicString method_; HTTPHeaderMap request_headers_; network::mojom::blink::TrustTokenParamsPtr trust_token_params_; + Member<DOMException> trust_token_operation_error_; // Not converted to ASCII lowercase. Must be lowered later or compared // using case insensitive comparison functions if needed. AtomicString mime_type_override_;
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl index a17a33b..99a761e 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl
@@ -78,4 +78,5 @@ [Custom=Getter, RaisesException=Getter] readonly attribute USVString responseText; // TODO(foolip): responseXML should be [Exposed=Window]. [MeasureAs=XMLHttpRequestResponseXML, RaisesException=Getter] readonly attribute Document? responseXML; + [RuntimeEnabled=TrustTokens, SecureContext] readonly attribute DOMException trustTokenOperationError; };
diff --git a/third_party/blink/renderer/modules/content_index/content_description.idl b/third_party/blink/renderer/modules/content_index/content_description.idl index 93b2652..8869c228 100644 --- a/third_party/blink/renderer/modules/content_index/content_description.idl +++ b/third_party/blink/renderer/modules/content_index/content_description.idl
@@ -18,5 +18,5 @@ required DOMString description; ContentCategory category = ""; sequence<ContentIconDefinition> icons = []; - required USVString launchUrl; + required USVString url; };
diff --git a/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc b/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc index cbf40e6a..fbe9ec1 100644 --- a/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc +++ b/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc
@@ -59,7 +59,7 @@ result->icons.push_back(blink::mojom::blink::ContentIconDefinition::New( icon->src(), icon->sizes(), icon->type())); } - result->launch_url = description->launchUrl(); + result->launch_url = description->url(); return result; } @@ -85,7 +85,7 @@ } result->setIcons(blink_icons); - result->setLaunchUrl(description->launch_url); + result->setUrl(description->launch_url); return result; }
diff --git a/third_party/blink/renderer/modules/content_index/content_description_type_converter_test.cc b/third_party/blink/renderer/modules/content_index/content_description_type_converter_test.cc index 5a3733c..c97cba6b 100644 --- a/third_party/blink/renderer/modules/content_index/content_description_type_converter_test.cc +++ b/third_party/blink/renderer/modules/content_index/content_description_type_converter_test.cc
@@ -26,7 +26,7 @@ icon_definition->setSrc(url); description->setIcons({icon_definition}); - description->setLaunchUrl(url); + description->setUrl(url); return description; } @@ -40,7 +40,7 @@ return cd1.id() == cd2.id() && cd1.title() == cd2.title() && cd1.description() == cd2.description() && cd1.category() == cd2.category() && cd1.icons() == cd2.icons() && - cd1.launchUrl() == cd2.launchUrl(); + cd1.url() == cd2.url(); } TEST(ContentDescriptionConversionTest, RoundTrip) {
diff --git a/third_party/blink/renderer/modules/content_index/content_index.cc b/third_party/blink/renderer/modules/content_index/content_index.cc index 7d77fb4..b4f5016 100644 --- a/third_party/blink/renderer/modules/content_index/content_index.cc +++ b/third_party/blink/renderer/modules/content_index/content_index.cc
@@ -38,7 +38,7 @@ if (description.description().IsEmpty()) return "Description cannot be empty"; - if (description.launchUrl().IsEmpty()) + if (description.url().IsEmpty()) return "Invalid launch URL provided"; for (const auto& icon : description.icons()) { @@ -51,7 +51,7 @@ } KURL launch_url = - registration->GetExecutionContext()->CompleteURL(description.launchUrl()); + registration->GetExecutionContext()->CompleteURL(description.url()); auto* security_origin = registration->GetExecutionContext()->GetSecurityOrigin(); if (!security_origin->CanRequest(launch_url))
diff --git a/third_party/blink/renderer/platform/exported/web_url_error.cc b/third_party/blink/renderer/platform/exported/web_url_error.cc index c0672826..05f0252a 100644 --- a/third_party/blink/renderer/platform/exported/web_url_error.cc +++ b/third_party/blink/renderer/platform/exported/web_url_error.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/public/platform/web_url_error.h" #include "net/base/net_errors.h" +#include "services/network/public/mojom/trust_tokens.mojom-shared.h" namespace blink { @@ -50,4 +51,15 @@ url_(url), cors_error_status_(cors_error_status) {} +WebURLError::WebURLError( + int reason, + network::mojom::TrustTokenOperationStatus trust_token_operation_error, + const WebURL& url) + : reason_(reason), + url_(url), + trust_token_operation_error_(trust_token_operation_error) { + DCHECK_NE(trust_token_operation_error, + network::mojom::TrustTokenOperationStatus::kOk); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc b/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc index 7595c82..e912dbf 100644 --- a/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc +++ b/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
@@ -18,11 +18,15 @@ BeginFrameProvider::BeginFrameProvider( const BeginFrameProviderParams& begin_frame_provider_params, - BeginFrameProviderClient* client) + BeginFrameProviderClient* client, + ContextLifecycleNotifier* context) : needs_begin_frame_(false), requested_needs_begin_frame_(false), + cfs_receiver_(this, context), + efs_receiver_(this, context), frame_sink_id_(begin_frame_provider_params.frame_sink_id), parent_frame_sink_id_(begin_frame_provider_params.parent_frame_sink_id), + compositor_frame_sink_(context), begin_frame_client_(client) {} void BeginFrameProvider::ResetCompositorFrameSink() { @@ -74,9 +78,9 @@ parent_frame_sink_id_, frame_sink_id_, efs_receiver_.BindNewPipeAndPassRemote(task_runner), cfs_receiver_.BindNewPipeAndPassRemote(task_runner), - compositor_frame_sink_.BindNewPipeAndPassReceiver()); + compositor_frame_sink_.BindNewPipeAndPassReceiver(task_runner)); - compositor_frame_sink_.set_disconnect_with_reason_handler(base::BindOnce( + compositor_frame_sink_.set_disconnect_with_reason_handler(WTF::Bind( &BeginFrameProvider::OnMojoConnectionError, WrapWeakPersistent(this))); } @@ -121,6 +125,9 @@ } void BeginFrameProvider::Trace(Visitor* visitor) { + visitor->Trace(cfs_receiver_); + visitor->Trace(efs_receiver_); + visitor->Trace(compositor_frame_sink_); visitor->Trace(begin_frame_client_); }
diff --git a/third_party/blink/renderer/platform/graphics/begin_frame_provider.h b/third_party/blink/renderer/platform/graphics/begin_frame_provider.h index 6672388..012d1a8e7 100644 --- a/third_party/blink/renderer/platform/graphics/begin_frame_provider.h +++ b/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
@@ -13,6 +13,8 @@ #include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink.h" #include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/platform_export.h" namespace blink { @@ -35,7 +37,8 @@ public: explicit BeginFrameProvider( const BeginFrameProviderParams& begin_frame_provider_params, - BeginFrameProviderClient*); + BeginFrameProviderClient*, + ContextLifecycleNotifier*); void CreateCompositorFrameSinkIfNeeded(); @@ -77,12 +80,20 @@ bool needs_begin_frame_; bool requested_needs_begin_frame_; - mojo::Receiver<viz::mojom::blink::CompositorFrameSinkClient> cfs_receiver_{ - this}; - mojo::Receiver<mojom::blink::EmbeddedFrameSinkClient> efs_receiver_{this}; + HeapMojoReceiver<viz::mojom::blink::CompositorFrameSinkClient, + BeginFrameProvider, + HeapMojoWrapperMode::kWithoutContextObserver> + cfs_receiver_; + + HeapMojoReceiver<mojom::blink::EmbeddedFrameSinkClient, + BeginFrameProvider, + HeapMojoWrapperMode::kWithoutContextObserver> + efs_receiver_; viz::FrameSinkId frame_sink_id_; viz::FrameSinkId parent_frame_sink_id_; - mojo::Remote<viz::mojom::blink::CompositorFrameSink> compositor_frame_sink_; + HeapMojoRemote<viz::mojom::blink::CompositorFrameSink, + HeapMojoWrapperMode::kWithoutContextObserver> + compositor_frame_sink_; Member<BeginFrameProviderClient> begin_frame_client_; };
diff --git a/third_party/blink/renderer/platform/graphics/path.h b/third_party/blink/renderer/platform/graphics/path.h index 79f98c7..f19aba2 100644 --- a/third_party/blink/renderer/platform/graphics/path.h +++ b/third_party/blink/renderer/platform/graphics/path.h
@@ -82,6 +82,7 @@ bool Contains(const FloatPoint&) const; bool Contains(const FloatPoint&, WindRule) const; bool StrokeContains(const FloatPoint&, const StrokeData&) const; + SkPath StrokePath(const StrokeData&) const; FloatRect BoundingRect() const; FloatRect StrokeBoundingRect(const StrokeData&) const; @@ -192,7 +193,6 @@ float radius_y, float start_angle, float end_angle); - SkPath StrokePath(const StrokeData&) const; SkPath path_; };
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc index 9991d6a..cdc6ad92 100644 --- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc +++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
@@ -72,4 +72,9 @@ had_form_interaction_ = true; } +void DocumentResourceCoordinator::OnFirstContentfulPaint( + base::TimeDelta time_since_navigation_start) { + service_->OnFirstContentfulPaint(time_since_navigation_start); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h index 73797f7..a3b67ff 100644 --- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h +++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
@@ -35,6 +35,7 @@ void SetIsAdFrame(); void OnNonPersistentNotificationCreated(); void SetHadFormInteraction(); + void OnFirstContentfulPaint(base::TimeDelta time_since_navigation_start); private: explicit DocumentResourceCoordinator(const BrowserInterfaceBrokerProxy&);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_error.cc b/third_party/blink/renderer/platform/loader/fetch/resource_error.cc index a670684..2ee5788 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_error.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
@@ -26,13 +26,16 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_error.h" +#include "base/strings/string_number_conversions.h" #include "net/base/net_errors.h" +#include "services/network/public/mojom/trust_tokens.mojom-blink-forward.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/resource_request_blocked_reason.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/platform/web_url_error.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h" +#include "third_party/blink/renderer/platform/loader/fetch/trust_token_params_conversion.h" namespace blink { @@ -101,7 +104,8 @@ is_access_check_(error.is_web_security_violation()), has_copy_in_cache_(error.has_copy_in_cache()), cors_error_status_(error.cors_error_status()), - blocked_by_response_reason_(error.blocked_by_response_reason()) { + blocked_by_response_reason_(error.blocked_by_response_reason()), + trust_token_operation_error_(error.trust_token_operation_error()) { DCHECK_NE(error_code_, 0); InitializeDescription(); } @@ -114,6 +118,7 @@ error_copy.has_copy_in_cache_ = has_copy_in_cache_; error_copy.localized_description_ = localized_description_.IsolatedCopy(); error_copy.is_access_check_ = is_access_check_; + error_copy.trust_token_operation_error_ = trust_token_operation_error_; return error_copy; } @@ -127,6 +132,11 @@ return WebURLError(*cors_error_status_, has_copy_in_cache, failing_url_); } + if (trust_token_operation_error_ != + network::mojom::blink::TrustTokenOperationStatus::kOk) { + return WebURLError(error_code_, trust_token_operation_error_, failing_url_); + } + return WebURLError( error_code_, extended_error_code_, resolve_error_info_, has_copy_in_cache, is_access_check_ ? WebURLError::IsWebSecurityViolation::kTrue @@ -159,6 +169,9 @@ if (a.resolve_error_info_ != b.resolve_error_info_) return false; + if (a.trust_token_operation_error_ != b.trust_token_operation_error_) + return false; + return true; } @@ -299,7 +312,10 @@ << ", IsAccessCheck = " << error.IsAccessCheck() << ", IsTimeout = " << error.IsTimeout() << ", HasCopyInCache = " << error.HasCopyInCache() - << ", IsCacheMiss = " << error.IsCacheMiss(); + << ", IsCacheMiss = " << error.IsCacheMiss() + << ", TrustTokenOperationError = " + << String::FromUTF8(base::NumberToString( + static_cast<int32_t>(error.TrustTokenOperationError()))); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_error.h b/third_party/blink/renderer/platform/loader/fetch/resource_error.h index 7c1e833..71c3e58 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_error.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_error.h
@@ -32,6 +32,7 @@ #include "net/dns/public/resolve_error_info.h" #include "services/network/public/cpp/blocked_by_response_reason.h" #include "services/network/public/cpp/cors/cors_error_status.h" +#include "services/network/public/mojom/trust_tokens.mojom-blink.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -92,6 +93,11 @@ return cors_error_status_; } + network::mojom::blink::TrustTokenOperationStatus TrustTokenOperationError() + const { + return trust_token_operation_error_; + } + explicit operator WebURLError() const; static bool Compare(const ResourceError&, const ResourceError&); @@ -110,6 +116,11 @@ base::Optional<network::CorsErrorStatus> cors_error_status_; base::Optional<network::BlockedByResponseReason> blocked_by_response_reason_; + + // Refer to the member comment in WebURLError. + network::mojom::blink::TrustTokenOperationStatus + trust_token_operation_error_ = + network::mojom::blink::TrustTokenOperationStatus::kOk; }; inline bool operator==(const ResourceError& a, const ResourceError& b) {
diff --git a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni index 8af9005..d439274c 100644 --- a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni +++ b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -23,7 +23,4 @@ "//third_party/blink/public/common/mediastream/media_stream.typemap", "//third_party/blink/public/common/screen_orientation/screen_orientation_lock_types.typemap", "//third_party/blink/public/mojom/bluetooth/bluetooth.typemap", - "//ui/gfx/geometry/mojom/geometry.typemap", - "//ui/gfx/mojom/color_space.typemap", - "//ui/gfx/mojom/transform.typemap", ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index ec60930..ad333f3 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -220,7 +220,6 @@ crbug.com/974652 [ Debug ] virtual/gpu/fast/canvas/OffscreenCanvas-copyImage.html [ Pass Failure ] crbug.com/974652 [ Debug ] fast/canvas/OffscreenCanvas-copyImage.html [ Pass Failure ] -crbug.com/1011060 virtual/gpu/fast/canvas/canvas-getImageData-smooth.html [ Pass Failure ] crbug.com/1011060 virtual/gpu/fast/canvas/bug382588.html [ Pass Failure ] crbug.com/1011060 virtual/gpu/fast/canvas/canvas-lost-gpu-context.html [ Pass Failure Crash ] @@ -4864,7 +4863,6 @@ # Canvas tests that are affected by change to Skia GPU rect shadow rendering. crbug.com/990918 virtual/gpu/fast/canvas/canvas-shadow-source-in.html [ Pass Failure ] crbug.com/990918 virtual/gpu/fast/canvas/canvas-composite-shadow.html [ Pass Failure ] -crbug.com/990918 virtual/gpu/fast/canvas/canvas-shadow.html [ Pass Failure ] # Sheriff failures 2017-09-21 crbug.com/767469 http/tests/navigation/start-load-during-provisional-loader-detach.html [ Pass Failure ] @@ -4950,9 +4948,6 @@ # Sheriff failures 2017-11-16 crbug.com/785980 [ Win ] http/tests/devtools/network/network-xhr-same-url-as-main-resource.js [ Failure Pass ] -# Sheriff failures 2017-11-29 -crbug.com/786641 virtual/gpu/fast/canvas/OffscreenCanvas-2d-imageSmoothing.html [ Pass Failure Timeout ] - # Sheriff failures 2017-12-04 crbug.com/667560 http/tests/devtools/elements/styles-4/inline-style-sourcemap.js [ Pass Failure ] @@ -5205,7 +5200,6 @@ # Sheriff 2018-04-11 crbug.com/831796 fast/events/autoscroll-in-textfield.html [ Failure Pass ] crbug.com/831673 http/tests/devtools/reveal-objects.js [ Pass Timeout ] -crbug.com/831496 virtual/gpu/fast/canvas/fillrect_gradient.html [ Pass Timeout ] crbug.com/829952 fast/webgl/texImage-imageBitmap-from-image-resize.html [ Pass Timeout ] crbug.com/832274 [ Linux ] fast/forms/search/search-appearance-basic.html [ Pass Failure ] @@ -5495,7 +5489,6 @@ crbug.com/922951 http/tests/cache/subresource-fragment-identifier.html [ Failure Pass Timeout Crash ] crbug.com/922951 http/tests/devtools/tracing/timeline-network-received-data.js [ Failure Pass Timeout Crash ] crbug.com/922951 http/tests/history/back-to-post.html [ Failure Pass Timeout Crash ] -crbug.com/922951 http/tests/security/offscreencanvas-placeholder-read-blocked-no-crossorigin.html [ Failure Pass Timeout Crash ] crbug.com/922951 http/tests/security/cookies/basic.html [ Failure Pass Timeout Crash ] crbug.com/922951 http/tests/webaudio/autoplay-crossorigin.html [ Failure Pass Timeout Crash ] crbug.com/922951 media/controls/overflow-menu-hide-on-click-outside-stoppropagation.html [ Failure Pass Timeout Crash ] @@ -5504,8 +5497,6 @@ crbug.com/922951 virtual/audio-service/media/controls/overflow-menu-hide-on-click-outside-stoppropagation.html [ Failure Pass Timeout Crash ] crbug.com/922951 virtual/audio-service/media/controls/overflow-menu-hide-on-click-outside.html [ Failure Pass Timeout Crash ] crbug.com/922951 virtual/audio-service/media/controls/overflow-menu-toggle-class-for-animation.html [ Failure Pass Timeout Crash ] -crbug.com/922951 virtual/gpu/fast/canvas/OffscreenCanvas-MessageChannel-transfer.html [ Failure Pass Timeout Crash ] -crbug.com/922951 virtual/gpu/fast/canvas/color-space/canvas-drawImage-offscreenCanvas.html [ Failure Pass Timeout Crash ] crbug.com/922951 virtual/prefer_compositing_to_lcd_text/scrollbars/resize-scales-with-dpi-150.html [ Failure Pass Timeout Crash ] crbug.com/922951 virtual/scalefactor150/fast/events/synthetic-events/tap-on-scaled-screen.html [ Failure Pass Timeout Crash ] crbug.com/922951 virtual/threaded/http/tests/devtools/tracing/frame-model-instrumentation.js [ Failure Pass Timeout Crash ] @@ -5793,9 +5784,6 @@ crbug.com/971319 [ Mac ] media/audio-garbage-collect.html [ Pass Timeout ] crbug.com/971319 [ Mac ] virtual/audio-service/media/audio-garbage-collect.html [ Pass Timeout ] -# Sheriff 2019-06-06 -crbug.com/971612 fast/canvas/OffscreenCanvas-MessageChannel-transfer.html [ Pass Failure ] - # Sheriff 2019-06-13 crbug.com/973692 [ Mac ] external/wpt/css/css-text/parsing/hyphens-computed.html [ Failure ] crbug.com/973726 [ Mac ] fast/css/large-list-of-rules-crash.html [ Pass Timeout ] @@ -6045,8 +6033,6 @@ crbug.com/1010170 [ Mac ] media/video-played-reset.html [ Failure ] # Sheriff 2019-10-02 -crbug.com/1010472 [ Linux Debug ] fast/canvas/color-space/canvas-drawImage-offscreenCanvas.html [ Timeout Pass ] -crbug.com/1010472 [ Mac Debug ] fast/canvas/color-space/canvas-drawImage-offscreenCanvas.html [ Timeout Pass ] crbug.com/1010483 [ Win ] fast/parser/residual-style-dom.html [ Crash Pass ] crbug.com/1010483 [ Win ] fast/parser/residual-style-hang.html [ Crash Pass ] crbug.com/1010483 [ Win ] fast/selectors/specificity-overflow.html [ Crash Pass ] @@ -6464,9 +6450,6 @@ crbug.com/1049454 external/wpt/service-workers/service-worker/windowclient-navigate.https.html [ Pass Timeout ] -# Sheriff 2020-02-10 -crbug.com/1050306 [ Fuchsia ] virtual/gpu/fast/canvas/canvas-filter-frameless-document.html [ Crash Pass Timeout ] - # Swiftshader issue. crbug.com/1048149 external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html [ Crash Timeout ] crbug.com/1048149 external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-screeny.html [ Crash Timeout ] @@ -6644,8 +6627,6 @@ crbug.com/1061043 fast/plugins/keypress-event.html [ Pass Failure ] crbug.com/1061097 http/tests/security/promise-access-control-allow.htm [ Pass Failure ] crbug.com/1061131 [ Mac ] virtual/threaded-prefer-compositing/fast/scrolling/middle-click-autoscroll-latching-clicked-node.html [ Pass Timeout ] -crbug.com/1061131 [ Win ] fast/canvas/toBlob-in-detached-document.html [ Pass Crash ] -crbug.com/1061131 [ Mac ] fast/canvas/toBlob-in-detached-document.html [ Pass Crash ] crbug.com/1061131 [ Mac ] editing/selection/replaced-boundaries-1.html [ Pass Failure ] crbug.com/1058888 [ Linux ] animations/animationworklet/peek-updated-composited-property-on-main.html [ Pass Failure ] @@ -6660,6 +6641,11 @@ crbug.com/1064127 virtual/threaded/external/wpt/web-animations/timing-model/animations/update-playback-rate-slow.html [ Pass Failure ] crbug.com/1064463 external/wpt/web-animations/interfaces/Animation/style-change-events.html [ Pass Failure ] +# These tests will pass once the --enable-features=TrustTokens flag is on by +# default. A virtual test suite runs the same tests with the flag enabled. +crbug.com/1061765 http/tests/loading/trust-tokens/* [ Skip ] +crbug.com/1061765 external/wpt/trust-tokens/end-to-end/* [ Skip ] + # Sheriff 2020-03-26 crbug.com/1064839 fast/hidpi/image-srcset-svg-canvas-2x.html [ Pass Failure ] # Sheriff 2020-03-27 @@ -6673,9 +6659,6 @@ crbug.com/1066732 fast/events/platform-wheelevent-paging-x-in-scrolling-div.html [ Pass Failure ] crbug.com/1066732 fast/events/platform-wheelevent-paging-y-in-scrolling-div.html [ Pass Failure ] -# These tests will pass once the --enable-features=TrustTokens flag is on by default. -crbug.com/1061765 external/wpt/trust-tokens/end-to-end/* [ Skip ] - # Test flakes crbug.com/1066716 http/tests/cache/zero-length-xhr.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 505ab11..ea957f80 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -729,7 +729,7 @@ }, { "prefix": "trust-tokens", - "bases": [ "external/wpt/trust-tokens/end-to-end" ], + "bases": [ "external/wpt/trust-tokens/end-to-end", "http/tests/loading/trust-tokens" ], "args": [ "--enable-features=TrustTokens" ] } ]
diff --git a/third_party/blink/web_tests/css3/masking/clip-path-reference-mutated.html b/third_party/blink/web_tests/css3/masking/clip-path-reference-mutated.html deleted file mode 100644 index fc4e61d..0000000 --- a/third_party/blink/web_tests/css3/masking/clip-path-reference-mutated.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!DOCTYPE html> -<script src="../../resources/run-after-layout-and-paint.js"></script> -<style> -#target { - width: 100px; - height: 100px; - background-color: green; - clip-path: url(#clip); -} -</style> -<div id="target"></div> -<svg height="0" width="0"> - <defs> - <clipPath id="clip" clipPathUnits="objectBoundingBox"> - <circle cx="0.5" cy="0.5" r="0.25"></circle> - </clipPath> - </defs> -</svg> -<script> -runAfterLayoutAndPaint(function() { - document.querySelector('circle').setAttribute('r', 1); -}, true); -</script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json index f2aa665..fc943145 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -61823,6 +61823,18 @@ {} ] ], + "css/css-masking/clip-path/reference-nonexisting-existing-local.html": [ + [ + "css/css-masking/clip-path/reference-nonexisting-existing-local.html", + [ + [ + "/css/css-masking/clip-path/reference/reference-nonexisting-existing-local-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-masking/clip-rule/clip-rule-001.html": [ [ "css/css-masking/clip-rule/clip-rule-001.html", @@ -108677,6 +108689,18 @@ {} ] ], + "css/filter-effects/clip-under-filter-003.html": [ + [ + "css/filter-effects/clip-under-filter-003.html", + [ + [ + "/css/filter-effects/reference/clip-under-filter-003-ref.html", + "==" + ] + ], + {} + ] + ], "css/filter-effects/css-backdrop-filters-animation-blur.html": [ [ "css/filter-effects/css-backdrop-filters-animation-blur.html", @@ -150878,6 +150902,9 @@ "css/css-masking/clip-path/reference/reference-local-url-with-base-001-ref.html": [ [] ], + "css/css-masking/clip-path/reference/reference-nonexisting-existing-local-ref.html": [ + [] + ], "css/css-masking/clip-path/svg-clipPath.svg": [ [] ], @@ -160814,6 +160841,9 @@ "css/filter-effects/reference/clip-under-filter-002-ref.html": [ [] ], + "css/filter-effects/reference/clip-under-filter-003-ref.html": [ + [] + ], "css/filter-effects/reference/drop-shadow-clipped-001-ref.html": [ [] ], @@ -208721,23 +208751,6 @@ {} ] ], - "appmanifest/idlharness.window.js": [ - [ - "appmanifest/idlharness.window.html", - { - "script_metadata": [ - [ - "script", - "/resources/WebIDLParser.js" - ], - [ - "script", - "/resources/idlharness.js" - ] - ] - } - ] - ], "audio-output/idlharness.https.window.js": [ [ "audio-output/idlharness.https.window.html", @@ -223981,6 +223994,18 @@ {} ] ], + "css/css-grid/grid-definition/flex-and-minmax-content-resolution-columns-001.html": [ + [ + "css/css-grid/grid-definition/flex-and-minmax-content-resolution-columns-001.html", + {} + ] + ], + "css/css-grid/grid-definition/flex-and-minmax-content-resolution-rows-001.html": [ + [ + "css/css-grid/grid-definition/flex-and-minmax-content-resolution-rows-001.html", + {} + ] + ], "css/css-grid/grid-definition/grid-auto-repeat-max-size-001.html": [ [ "css/css-grid/grid-definition/grid-auto-repeat-max-size-001.html", @@ -224311,6 +224336,12 @@ {} ] ], + "css/css-grid/grid-model/compute-intrinsic-widths-scrollbar-001.html": [ + [ + "css/css-grid/grid-model/compute-intrinsic-widths-scrollbar-001.html", + {} + ] + ], "css/css-grid/grid-model/grid-box-sizing-001.html": [ [ "css/css-grid/grid-model/grid-box-sizing-001.html", @@ -352759,10 +352790,6 @@ "0b9c714df2a45545212397d7e391655f3e1091cf", "support" ], - "appmanifest/idlharness.window.js": [ - "55e8b9871e794c944f329e0e9df6ec140124c660", - "testharness" - ], "audio-output/META.yml": [ "b6a7d4d06259117af8fb843f6a8d252bac01a8f3", "support" @@ -355944,7 +355971,7 @@ "testharness" ], "content-security-policy/inheritance/iframe-all-local-schemes.sub.html": [ - "cd38c902f05f7871fdec0eafe5481e5eba1928ae", + "20a9cbdc9e086163000baafb9c74d4e9d32b071a", "testharness" ], "content-security-policy/inheritance/iframe-srcdoc-inheritance.html": [ @@ -399055,6 +399082,14 @@ "7fb5d8e117d9f0b7e23bf3921843e8ea29ef4522", "reftest" ], + "css/css-grid/grid-definition/flex-and-minmax-content-resolution-columns-001.html": [ + "b92eb9f0dddc63ca5d241c35dca2e0c32d406d24", + "testharness" + ], + "css/css-grid/grid-definition/flex-and-minmax-content-resolution-rows-001.html": [ + "ebaa2c08e4b6fff5042f4c0a4997a28f5cac293a", + "testharness" + ], "css/css-grid/grid-definition/fr-unit-with-percentage.html": [ "82c97abdd5740d466f049d8b45b67e241f204899", "reftest" @@ -399943,6 +399978,10 @@ "a5376827eb91a2e4a92fe4738b1a319fcdc38ee8", "testharness" ], + "css/css-grid/grid-model/compute-intrinsic-widths-scrollbar-001.html": [ + "d61f7ad14e6b911aca586a5a05713c9811db5a0c", + "testharness" + ], "css/css-grid/grid-model/display-grid.html": [ "7c6b743327ebfa74a841add8c51a5ea7ffb73ec4", "reftest" @@ -404271,6 +404310,10 @@ "c65761bddfc095e0e85b4feaea4359516a8df5b1", "reftest" ], + "css/css-masking/clip-path/reference-nonexisting-existing-local.html": [ + "d02e1439e64e79a65c185c703e4813e33225e679", + "reftest" + ], "css/css-masking/clip-path/reference/clip-path-circle-2-ref.html": [ "7794d32b3f0e2415dbfda8ff12475b0e4f0b4117", "support" @@ -404375,6 +404418,10 @@ "f718ea6abfbab54333ba674ff0dcd320d8672bcd", "support" ], + "css/css-masking/clip-path/reference/reference-nonexisting-existing-local-ref.html": [ + "f718ea6abfbab54333ba674ff0dcd320d8672bcd", + "support" + ], "css/css-masking/clip-path/svg-clipPath.svg": [ "d31a1df42e0ed94c43c2f9d0999d7dbde9e83130", "support" @@ -442835,6 +442882,10 @@ "8b6a66d45232e9924fe079bfbeff88c1aa0b0f53", "reftest" ], + "css/filter-effects/clip-under-filter-003.html": [ + "2cfda2a0d3be03edc4f75a7fd1e319e1cc1008b4", + "reftest" + ], "css/filter-effects/crashtests/multiple-references-id-crash-001.html": [ "9ee04e1015d3c9fc04e8fab240a15d59ae92892d", "crashtest" @@ -443479,6 +443530,10 @@ "60c2c336346dbd236ba29104fdd7a20fa29e7264", "support" ], + "css/filter-effects/reference/clip-under-filter-003-ref.html": [ + "e60456b3058be9055adbf45c4feffee4b40e9b56", + "support" + ], "css/filter-effects/reference/drop-shadow-clipped-001-ref.html": [ "305b1d2233de6845713fd43f2cfc1f72b1afdb60", "support" @@ -486624,7 +486679,7 @@ "support" ], "interfaces/appmanifest.idl": [ - "35c491a5f7bf0e714bec09112755c174d96663d4", + "2adc370012422f51514db9a2ee8768f532019736", "support" ], "interfaces/audio-output.idl": [
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/idlharness.window.js b/third_party/blink/web_tests/external/wpt/appmanifest/idlharness.window.js deleted file mode 100644 index 55e8b98..0000000 --- a/third_party/blink/web_tests/external/wpt/appmanifest/idlharness.window.js +++ /dev/null
@@ -1,17 +0,0 @@ -// META: script=/resources/WebIDLParser.js -// META: script=/resources/idlharness.js - -// https://w3c.github.io/manifest/ - -'use strict'; - -idl_test( - ['appmanifest'], - ['html', 'dom'], - idl_array => { - idl_array.add_objects({ - Window: ['window'], - BeforeInstallPromptEvent: ['new BeforeInstallPromptEvent("type")'], - }); - } -);
diff --git a/third_party/blink/web_tests/external/wpt/content-index/content-index.https.window.js b/third_party/blink/web_tests/external/wpt/content-index/content-index.https.window.js index 082ebc3b..5687070 100644 --- a/third_party/blink/web_tests/external/wpt/content-index/content-index.https.window.js +++ b/third_party/blink/web_tests/external/wpt/content-index/content-index.https.window.js
@@ -22,8 +22,8 @@ await expectTypeError(index.add(createDescription({iconUrl: '/non-existent-icon.png'}))); await expectTypeError(index.add(createDescription({iconUrl: '/images/broken.png'}))); - await expectTypeError(index.add(createDescription({launchUrl: 'https://other-domain.com/'}))); - await expectTypeError(index.add(createDescription({launchUrl: '/different-scope'}))); + await expectTypeError(index.add(createDescription({url: 'https://other-domain.com/'}))); + await expectTypeError(index.add(createDescription({url: '/different-scope'}))); await index.add(createDescription({}));
diff --git a/third_party/blink/web_tests/external/wpt/content-index/resources.js b/third_party/blink/web_tests/external/wpt/content-index/resources.js index 1a758ab..51e9800 100644 --- a/third_party/blink/web_tests/external/wpt/content-index/resources.js +++ b/third_party/blink/web_tests/external/wpt/content-index/resources.js
@@ -14,8 +14,8 @@ function createDescription({id = 'id', title = 'title', description = 'description', category = 'homepage', iconUrl = '/images/green-256x256.png', - launchUrl = scope, includeIcons = true}) { - return {id, title, description, category, icons: includeIcons ? [{src: iconUrl}] : [], launchUrl}; + url = scope, includeIcons = true}) { + return {id, title, description, category, icons: includeIcons ? [{src: iconUrl}] : [], url}; } // Creates a Promise test for |func| given the |description|. The |func| will be
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/empty-grid-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/empty-grid-001.html new file mode 100644 index 0000000..10702c7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/empty-grid-001.html
@@ -0,0 +1,70 @@ +<!DOCTYPE html> +<title>CSS Grid: empty grid without explicit tracks.</title> +<link rel="author" title="Sergio Villar" href="mailto:svillar@igalia.com"/> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos"/> +<link rel="issue" href="https://crrev.com/562167"/> +<meta name="assert" content="Test ensures that the grids with no in-flow items are actually empty."/> + +<link href="/css/support/grid.css" rel="stylesheet"/> +<link href="/css/support/width-keyword-classes.css" rel="stylesheet"/> +<link href="/fonts/ahem.css" rel="stylesheet" type="text/css"/> +<style> +.gridWithAbsolutePositionedItem { + /* Ensures that the grid container is the containing block of the absolutely positioned grid children. */ + position: relative; +} + +.grid { + grid-auto-columns: 200px; + grid-auto-rows: 200px; +} + +.item { + position: absolute; + font: 10px/1 Ahem; +} + +</style> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> +<script> +function addRemoveItem() +{ + var gridItem = document.createElement("div"); + gridItem.style.width = "100px"; + gridItem.style.height = "100px"; + gridItem.style.backgroundColor = "red"; + var gridElement = document.getElementById("dynamicGrid"); + gridElement.appendChild(gridItem); + gridElement.removeChild(gridItem); +} + +setup({ explicit_done: true }); + +function doTest() { + addRemoveItem(); + checkLayout(".grid"); +} +</script> + +<body onload="document.fonts.ready.then(() => { doTest(); })"> + +<div class="grid min-content" data-expected-width="0" data-expected-height="0"></div> + +<div class="grid min-content gridWithAbsolutePositionedItem" data-expected-width="0" data-expected-height="0"> + <div class="item" data-expected-width="40" data-expected-height="10">XXXX</div> +</div> + +<div id="dynamicGrid" class="grid min-content" data-expected-width="0" data-expected-height="0"></div> + +<div class="grid min-content" style="grid-template-rows: 100px;" data-expected-width="0" data-expected-height="100"></div> +<div class="grid min-content" style="grid-template-rows: auto;" data-expected-width="0" data-expected-height="0"></div> +<div class="grid min-content" style="grid-template-rows: 1fr;" data-expected-width="0" data-expected-height="0"></div> + +<div class="grid min-content" style="grid-template-columns: 100px;" data-expected-width="100" data-expected-height="0"></div> +<div class="grid min-content" style="grid-template-columns: auto;" data-expected-width="0" data-expected-height="0"></div> +<div class="grid min-content" style="grid-template-columns: 1fr;" data-expected-width="0" data-expected-height="0"></div> + +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/anonymous-grid-items-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/anonymous-grid-items-001.html new file mode 100644 index 0000000..f5ddd5c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/anonymous-grid-items-001.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<title>CSS Grid: anonynous grid items.</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items"> +<link rel="match" href="reference/anonymous-grid-items-001-ref.html"> +<meta name="assert" content="This test ensures that anonymous grid items are supported."/> +<body> + <div>The test passes if it has the same output than the reference.</div> + <div style="display: grid;"> + anonymous item + </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-script-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-script-001.html new file mode 100644 index 0000000..323e9ba3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-script-001.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>CSS Grid Layout Test: Insert script as grid item</title> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-item"> +<link rel="stylesheet" href="/css/support/grid.css"/> +<link rel="match" href="../reference/grid-item-script-001-ref.html"> +<meta name="assert" content="This test ensures that inserting a script element as grid item doesn't crash."> +<div class="grid"> +<script> + var grid = document.getElementsByClassName("grid")[0]; + grid.offsetTop; + grid.innerHTML = "Test passes if it doesn't crash."; +</script> +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/column-property-should-not-apply-on-grid-container-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/column-property-should-not-apply-on-grid-container-001.html new file mode 100644 index 0000000..a795362 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/column-property-should-not-apply-on-grid-container-001.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<title>CSS Grid: column-* properties are ignored.</title> +<link rel="author" title="Sunil Ratnu" href="mailto:sunil.ratnu@samsung.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-model"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/1364"> +<link rel="match" href="reference/column-property-should-not-apply-on-grid-container-001-ref.html"> +<meta name="assert" content="This test ensures the column-* properties (in the Multicol module) have no effect on a grid container."/> +<link href="/css/support/grid.css" rel="stylesheet"/> +<style> +.grid, .inline-grid +{ + width: 20em; + column-count: 2; + column-gap: 100px; + font-kerning: none; +} +</style> + +<body> + +<div class='grid'> +AAAAAAAAAA BBBBBBBBBB CCCCCCCCCC DDDDDDDDDD +</div> + +<div class='inline-grid'> +AAAAAAAAAA BBBBBBBBBB CCCCCCCCCC DDDDDDDDDD +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/compute-intrinsic-widths-scrollbar-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/compute-intrinsic-widths-scrollbar-001.html new file mode 100644 index 0000000..d61f7ad1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/compute-intrinsic-widths-scrollbar-001.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<title>CSS Grid: width of grid container with scrollbar.</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#overflow"> +<meta name="assert" content="This test ensures that a grid container scrollbar is computed properly during intrinsic width calculation."/> + +<link href="/css/support/grid.css" rel="stylesheet"/> +<link href="/css/support/width-keyword-classes.css" rel="stylesheet"/> +<style> + .grid { + overflow-y: scroll; + grid-template-columns: repeat(4, 50px); + } +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> + <div class="grid min-content" data-expected-client-width="200"> + item + </div> + <div class="grid max-content" data-expected-client-width="200"> + item + </div> +</body>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/column-property-should-not-apply-on-grid-container-expected.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/reference/column-property-should-not-apply-on-grid-container-001-ref.html similarity index 71% rename from third_party/blink/web_tests/fast/css-grid-layout/column-property-should-not-apply-on-grid-container-expected.html rename to third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/reference/column-property-should-not-apply-on-grid-container-001-ref.html index c8c771f..154cf02 100644 --- a/third_party/blink/web_tests/fast/css-grid-layout/column-property-should-not-apply-on-grid-container-expected.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-model/reference/column-property-should-not-apply-on-grid-container-001-ref.html
@@ -1,11 +1,11 @@ <!DOCTYPE html> <html> -<link href="resources/grid.css" rel="stylesheet"> +<link href="/css/support/grid.css" rel="stylesheet"> <style> .grid, .inline-grid { - width: 20em; - font-kerning: none; + width: 20em; + font-kerning: none; } </style>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/auto-margins-ignored-during-track-sizing.html b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/auto-margins-ignored-during-track-sizing-001.html similarity index 64% rename from third_party/blink/web_tests/fast/css-grid-layout/auto-margins-ignored-during-track-sizing.html rename to third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/auto-margins-ignored-during-track-sizing-001.html index 471d476..2a23b1b 100644 --- a/third_party/blink/web_tests/fast/css-grid-layout/auto-margins-ignored-during-track-sizing.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/auto-margins-ignored-during-track-sizing-001.html
@@ -1,5 +1,10 @@ <!DOCTYPE html> -<link rel="match" href="auto-margins-ignored-during-track-sizing-expected.html"> +<title>CSS Grid: grid items using 'auto' margins.</title> +<link rel="author" title="Javier Fernendez" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#auto-margins"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#layout-algorithm"> +<link rel="match" href="references/auto-margins-ignored-during-track-sizing-001-ref.html"> +<meta name="assert" content="This test ensures that 'auto' margin is treated as 0px during the tracks sizing algorithm."/> <style> body { overflow: hidden; } .grid {
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/auto-margins-ignored-during-track-sizing-expected.html b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/references/auto-margins-ignored-during-track-sizing-001-ref.html similarity index 100% rename from third_party/blink/web_tests/fast/css-grid-layout/auto-margins-ignored-during-track-sizing-expected.html rename to third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/references/auto-margins-ignored-during-track-sizing-001-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/reference/anonymous-grid-items-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/reference/anonymous-grid-items-001-ref.html new file mode 100644 index 0000000..20302c2f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/reference/anonymous-grid-items-001-ref.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<body> + <div>The test passes if it has the same output than the reference.</div> + <div> + <div>anonymous item</div> + </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/reference/grid-item-script-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/reference/grid-item-script-001-ref.html new file mode 100644 index 0000000..2574678 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/reference/grid-item-script-001-ref.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<div style="background: grey;">Test passes if it doesn't crash.</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/reference-mutated.html b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/reference-mutated.html new file mode 100644 index 0000000..09642853 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/reference-mutated.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<title>CSS Masking: SVG clipPath dynamically updated.</title> +<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-clip-path"> +<link rel="match" href="reference/reference-mutated-ref.html"> +<meta name="assert" content="Test ensures that SVG clipPath updates properly when dynamically changed."/> + +<script src="/common/reftest-wait.js"></script> +<script src="/common/rendering-utils.js"></script> + +<style> +#target { + width: 100px; + height: 100px; + background-color: green; + clip-path: url(#clip); +} +</style> +<div id="target"></div> +<svg height="0" width="0"> + <defs> + <clipPath id="clip" clipPathUnits="objectBoundingBox"> + <circle cx="0.5" cy="0.5" r="0.25"></circle> + </clipPath> + </defs> +</svg> +<script> +waitForAtLeastOneFrame().then(function() { + document.querySelector('circle').setAttribute('r', 1); + takeScreenshot(); +}); +</script>
diff --git a/third_party/blink/web_tests/css3/masking/clip-path-reference-mutated-expected.html b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/reference/reference-mutated-ref.html similarity index 100% rename from third_party/blink/web_tests/css3/masking/clip-path-reference-mutated-expected.html rename to third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/reference/reference-mutated-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/appmanifest.idl b/third_party/blink/web_tests/external/wpt/interfaces/appmanifest.idl index 35c491a..2adc370 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/appmanifest.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/appmanifest.idl
@@ -3,26 +3,6 @@ // (https://github.com/tidoust/reffy-reports) // Source: Web App Manifest (https://w3c.github.io/manifest/) -[Exposed=Window] -interface BeforeInstallPromptEvent : Event { - constructor(DOMString type, optional EventInit eventInitDict = {}); - Promise<PromptResponseObject> prompt(); -}; - -dictionary PromptResponseObject { - AppBannerPromptOutcome userChoice; -}; - -enum AppBannerPromptOutcome { - "accepted", - "dismissed" -}; - -partial interface Window { - attribute EventHandler onappinstalled; - attribute EventHandler onbeforeinstallprompt; -}; - dictionary WebAppManifest { TextDirectionType dir = "auto"; DOMString lang;
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/anonymous-grid-items-expected.html b/third_party/blink/web_tests/fast/css-grid-layout/anonymous-grid-items-expected.html deleted file mode 100644 index d73553b..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/anonymous-grid-items-expected.html +++ /dev/null
@@ -1,9 +0,0 @@ -<!DOCTYPE html> -<html> -<body> - <div>Checks that anonymous grid items are supported. This should not crash.</div> - <div style="display: grid;"> - <div>anonymous item</div> - </div> -</body> -</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/anonymous-grid-items.html b/third_party/blink/web_tests/fast/css-grid-layout/anonymous-grid-items.html deleted file mode 100644 index 0b5ca902..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/anonymous-grid-items.html +++ /dev/null
@@ -1,9 +0,0 @@ -<!DOCTYPE html> -<html> -<body> - <div>Checks that anonymous grid items are supported. This should not crash.</div> - <div style="display: grid;"> - anonymous item - </div> -</body> -</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/column-property-should-not-apply-on-grid-container.html b/third_party/blink/web_tests/fast/css-grid-layout/column-property-should-not-apply-on-grid-container.html deleted file mode 100644 index 5edad01..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/column-property-should-not-apply-on-grid-container.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!DOCTYPE html> -<html> -<link href="resources/grid.css" rel="stylesheet"> -<style> -.grid, .inline-grid -{ - width: 20em; - -webkit-column-count: 2; /* Chrome, Safari, Opera */ - -moz-column-count: 2; /* Firefox */ - column-count: 2; - - -webkit-column-gap: 100px; /* Chrome, Safari, Opera */ - -moz-column-gap: 100px; /* Firefox */ - column-gap: 100px; -} -</style> - -<body> - -<div class='grid'> -AAAAAAAAAA BBBBBBBBBB CCCCCCCCCC DDDDDDDDDD -</div> - -<div class='inline-grid'> -AAAAAAAAAA BBBBBBBBBB CCCCCCCCCC DDDDDDDDDD -</div> - -</body> -</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/compute-intrinsic-widths-scrollbar-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/compute-intrinsic-widths-scrollbar-expected.txt deleted file mode 100644 index 3f5cabd..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/compute-intrinsic-widths-scrollbar-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This test checks that grid container scrollbar is computed properly during intrinsic width calculation. - -item -PASS -item -PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/compute-intrinsic-widths-scrollbar.html b/third_party/blink/web_tests/fast/css-grid-layout/compute-intrinsic-widths-scrollbar.html deleted file mode 100644 index 758a962..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/compute-intrinsic-widths-scrollbar.html +++ /dev/null
@@ -1,19 +0,0 @@ -<!DOCTYPE html> -<link href="resources/grid.css" rel="stylesheet"> -<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel=stylesheet> -<style> - .grid { - overflow-y: scroll; - grid-template-columns: repeat(4, 50px); - } -</style> -<script src="../../resources/check-layout.js"></script> -<p>This test checks that grid container scrollbar is computed properly during intrinsic width calculation.</p> -<body onload="checkLayout('.grid')"> - <div class="grid min-content" data-expected-client-width="200"> - item - </div> - <div class="grid max-content" data-expected-client-width="200"> - item - </div> -</body>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/empty-grid-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/empty-grid-expected.txt deleted file mode 100644 index 80edb6e..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/empty-grid-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -This test checks that grids with no in-flow items are actually empty. - -PASS -XXXX -PASS -PASS -PASS -PASS -PASS -PASS -PASS -PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/empty-grid.html b/third_party/blink/web_tests/fast/css-grid-layout/empty-grid.html deleted file mode 100644 index 29ddf19..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/empty-grid.html +++ /dev/null
@@ -1,61 +0,0 @@ -<!DOCTYPE html> -<link href="resources/grid.css" rel="stylesheet"> -<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet"> -<style> -.gridWithAbsolutePositionedItem { - /* Ensures that the grid container is the containing block of the absolutely positioned grid children. */ - position: relative; -} - -.grid { - grid-auto-columns: 200px; - grid-auto-rows: 200px; -} - -.item { - position: absolute; - font: 10px/1 Ahem; -} - -</style> - -<script> -function addRemoveItem() -{ - var gridItem = document.createElement("div"); - gridItem.style.width = "100px"; - gridItem.style.height = "100px"; - gridItem.style.backgroundColor = "red"; - var gridElement = document.getElementById("dynamicGrid"); - gridElement.appendChild(gridItem); - gridElement.removeChild(gridItem); -} - -function doTest() { - addRemoveItem(); - checkLayout(".grid"); -} -</script> -<script src="../../resources/check-layout.js"></script> - -<body onload="doTest()"> - -<p>This test checks that grids with no in-flow items are actually empty.</p> - -<div class="grid min-content" data-expected-width="0" data-expected-height="0"></div> - -<div class="grid min-content gridWithAbsolutePositionedItem" data-expected-width="0" data-expected-height="0"> - <div class="item" data-expected-width="40" data-expected-height="10">XXXX</div> -</div> - -<div id="dynamicGrid" class="grid min-content" data-expected-width="0" data-expected-height="0"></div> - -<div class="grid min-content" style="grid-template-rows: 100px;" data-expected-width="0" data-expected-height="100"></div> -<div class="grid min-content" style="grid-template-rows: auto;" data-expected-width="0" data-expected-height="0"></div> -<div class="grid min-content" style="grid-template-rows: 1fr;" data-expected-width="0" data-expected-height="0"></div> - -<div class="grid min-content" style="grid-template-columns: 100px;" data-expected-width="100" data-expected-height="0"></div> -<div class="grid min-content" style="grid-template-columns: auto;" data-expected-width="0" data-expected-height="0"></div> -<div class="grid min-content" style="grid-template-columns: 1fr;" data-expected-width="0" data-expected-height="0"></div> - -</body>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-element-bad-cast-addchild-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-element-bad-cast-addchild-expected.txt deleted file mode 100644 index 4e5d528..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/grid-element-bad-cast-addchild-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This test checks that inserting a non-LayoutBox grid item doesn't make us crash. - -This test has PASSED if it didn't crash and you see PASSED below. - -PASSED
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-element-bad-cast-addchild.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-element-bad-cast-addchild.html deleted file mode 100644 index dc002e82..0000000 --- a/third_party/blink/web_tests/fast/css-grid-layout/grid-element-bad-cast-addchild.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<link href="resources/grid.css" rel="stylesheet"> -<p>This test checks that inserting a non-LayoutBox grid item doesn't make us crash.</p> -<p>This test has PASSED if it didn't crash and you see PASSED below.</p> -<div class="grid"> -<script> - if (window.testRunner) - testRunner.dumpAsText(); - - var grid = document.getElementsByClassName("grid")[0]; - grid.offsetTop; - grid.innerHTML = "PASSED"; -</script>
diff --git a/third_party/blink/web_tests/http/tests/content_index/content-index.html b/third_party/blink/web_tests/http/tests/content_index/content-index.html index 8fcd42f..c861c02 100644 --- a/third_party/blink/web_tests/http/tests/content_index/content-index.html +++ b/third_party/blink/web_tests/http/tests/content_index/content-index.html
@@ -35,10 +35,10 @@ 'Icon could not be loaded'); await expectTypeErrorWithMessage( - index.add(createDescription({launchUrl: 'https://other-domain.com/'})), + index.add(createDescription({url: 'https://other-domain.com/'})), `Failed to execute 'add' on 'ContentIndex': Service Worker cannot request provided launch URL`); await expectTypeErrorWithMessage( - index.add(createDescription({launchUrl: '/different-scope'})), + index.add(createDescription({url: '/different-scope'})), `Failed to execute 'add' on 'ContentIndex': Launch URL must belong to the Service Worker's scope`); await index.add(createDescription({}));
diff --git a/third_party/blink/web_tests/http/tests/content_index/resources.js b/third_party/blink/web_tests/http/tests/content_index/resources.js index 0c08092..0494ec4e 100644 --- a/third_party/blink/web_tests/http/tests/content_index/resources.js +++ b/third_party/blink/web_tests/http/tests/content_index/resources.js
@@ -21,8 +21,8 @@ function createDescription({id = 'id', title = 'title', description = 'description', category = 'homepage', iconUrl = '/resources/square.png', - launchUrl = scope, includeIcons = true}) { - return {id, title, description, category, icons: includeIcons ? [{src: iconUrl}] : [], launchUrl}; + url = scope, includeIcons = true}) { + return {id, title, description, category, icons: includeIcons ? [{src: iconUrl}] : [], url}; } // Creates a Promise test for |func| given the |description|. The |func| will be
diff --git a/third_party/blink/web_tests/http/tests/content_index/resources/sw.js b/third_party/blink/web_tests/http/tests/content_index/resources/sw.js index 23372d0..a647a2e 100644 --- a/third_party/blink/web_tests/http/tests/content_index/resources/sw.js +++ b/third_party/blink/web_tests/http/tests/content_index/resources/sw.js
@@ -17,7 +17,7 @@ icons: [{ src: '/resources/square.png', }], - launchUrl: 'resources/', + url: 'resources/', }); await postMessageToWindow('Successfully registered'); } catch (e) {
diff --git a/third_party/blink/web_tests/http/tests/loading/trust-tokens/trust-token-fetch.tentative.https.html b/third_party/blink/web_tests/http/tests/loading/trust-tokens/trust-token-fetch.tentative.https.html new file mode 100644 index 0000000..aa30715 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/loading/trust-tokens/trust-token-fetch.tentative.https.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Tests the prototype Trust Token API's functionality through its Fetch interface.</title> +<link rel="help" href="https://github.com/WICG/trust-token-api#trust-token-redemption" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> + 'use strict'; + + promise_test((t) => promise_rejects_dom(t, 'OperationError', + fetch('https://trusttoken.test', { + trustToken: { + type: 'token-request' + } + }), 'Trust Token issuance should error.'), 'Trust Token issuance is not implemented'); + + promise_test((t) => promise_rejects_dom(t, 'OperationError', + fetch('https://trusttoken.test', { + trustToken: { + type: 'srr-token-redemption' + } + }), 'Trust Token redemption should error.'), 'Trust Token redemption is not implemented'); + + promise_test((t) => promise_rejects_dom(t, 'OperationError', + fetch('https://destination.test', { + trustToken: { + type: 'send-srr', + issuer: 'https://issuer.test' + } + }), 'Trust Token signing should error.'), 'Trust Token signing is not implemented'); +</script>
diff --git a/third_party/blink/web_tests/http/tests/loading/trust-tokens/trust-token-xhr.tentative.https.html b/third_party/blink/web_tests/http/tests/loading/trust-tokens/trust-token-xhr.tentative.https.html new file mode 100644 index 0000000..90ad1ef --- /dev/null +++ b/third_party/blink/web_tests/http/tests/loading/trust-tokens/trust-token-xhr.tentative.https.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Tests the prototype Trust Token API's functionality through its XHR interface.</title> +<link rel="help" href="https://github.com/WICG/trust-token-api#trust-token-redemption" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> + 'use strict'; + + async_test((t) => { + let request = new XMLHttpRequest(); + request.open('GET', 'https://trusttoken.test'); + request.setTrustToken({ + type: 'token-request' + }); + request.onerror = t.step_func_done(() => { + assert_equals(request.trustTokenOperationError.name, "OperationError"); + }); + request.send(); + }, 'Trust Token issuance is not implemented'); + + async_test((t) => { + let request = new XMLHttpRequest(); + request.open('GET', 'https://trusttoken.test'); + request.setTrustToken({ + type: 'srr-token-redemption' + }); + request.onerror = t.step_func_done(() => { + assert_equals(request.trustTokenOperationError.name, "OperationError"); + }); + request.send(); + }, 'Trust Token redemption is not implemented'); + + async_test((t) => { + let request = new XMLHttpRequest(); + request.open('GET', 'https://destination.test'); + request.setTrustToken({ + type: 'send-srr', + issuer: 'https://issuer.test' + }); + request.onerror = t.step_func_done(() => { + assert_equals(request.trustTokenOperationError.name, "OperationError"); + }); + request.send(); + }, 'Trust Token signing is not implemented'); +</script>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/report-only-report-uri-missing-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/report-only-report-uri-missing-expected.txt deleted file mode 100644 index 185541ce..0000000 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/report-only-report-uri-missing-expected.txt +++ /dev/null
@@ -1,2 +0,0 @@ -CONSOLE ERROR: The Content Security Policy 'script-src 'unsafe-inline';' was delivered in report-only mode, but does not specify a 'report-uri'; the policy will have no effect. Please either add a 'report-uri' directive, or deliver the policy via the 'Content-Security-Policy' header. -This test passes if a console message is present, warning about the missing 'report-uri' directive.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/report-only-report-uri-missing.php b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/report-only-report-uri-missing.php deleted file mode 100644 index d4b5e21..0000000 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/report-only-report-uri-missing.php +++ /dev/null
@@ -1,19 +0,0 @@ -<?php -header("Content-Security-Policy-Report-Only: script-src 'unsafe-inline';"); -?> -<!DOCTYPE html> -<html> -<head> - <script> - if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.dumpPingLoaderCallbacks(); - } - if (window.internals) - internals.settings.setExperimentalContentSecurityPolicyFeaturesEnabled(false); - </script> -</head> -<body> - <p>This test passes if a console message is present, warning about the missing 'report-uri' directive.</p> -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/sandbox-report-only-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/sandbox-report-only-expected.txt index 5769220..a6b7503 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/sandbox-report-only-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/sandbox-report-only-expected.txt
@@ -1,5 +1,4 @@ CONSOLE ERROR: The Content Security Policy directive 'sandbox' is ignored when delivered in a report-only policy. -CONSOLE ERROR: The Content Security Policy 'sandbox' was delivered in report-only mode, but does not specify a 'report-uri'; the policy will have no effect. Please either add a 'report-uri' directive, or deliver the policy via the 'Content-Security-Policy' header. CONSOLE MESSAGE: line 4: Script executed in iframe. ALERT: PASS: Iframe was not in a unique origin
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/select/menulist-type-ahead-find-original-item-expected.txt b/third_party/blink/web_tests/platform/mac/fast/forms/select/menulist-type-ahead-find-original-item-expected.txt new file mode 100644 index 0000000..ed5b82f7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/fast/forms/select/menulist-type-ahead-find-original-item-expected.txt
@@ -0,0 +1,10 @@ +Verify type ahead selection fires onchange event. +Set focus to select element +Type down arrow twice and type "a" +You see "apple" in select element and "PASS" below select element. +apple +banana +cherry + + +FAIL
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/select/optgroup-clicking-expected.txt b/third_party/blink/web_tests/platform/mac/fast/forms/select/optgroup-clicking-expected.txt new file mode 100644 index 0000000..a5b72aa --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/fast/forms/select/optgroup-clicking-expected.txt
@@ -0,0 +1,42 @@ +Test clicking with optgroup element + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +Click enabled option +PASS $("listbox").selectedIndex is 1 + +Click on optgroup, should not deselect selectedIndex +PASS $("listbox").selectedIndex is 1 + +Click disabled option - doesn't change selectedIndex +PASS $("listbox").selectedIndex is 1 + +Menu list with arrow key. The test is expected to fail on OSX because of a key binding difference. +FAIL $("menulist").selectedIndex should be 8. Was 3. +PASS successfullyParsed is true + +TEST COMPLETE + +One +Two +Three +Four +One +Two +Three +Four + + +One +Two +Three +Four +One +Two +Three +Four +One +Two +Three +Four
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/select/select-popup-pagekeys-expected.txt b/third_party/blink/web_tests/platform/mac/fast/forms/select/select-popup-pagekeys-expected.txt new file mode 100644 index 0000000..4a05f8f --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/fast/forms/select/select-popup-pagekeys-expected.txt
@@ -0,0 +1,72 @@ +This test verifies that the Home/End/PageUp/PageDown keys work correctly for pop-up <select> elements that have focus but are not currently popped-up. + +Output below is a series of PASS or FAIL lines showing expected and actual selection indexes, followed by a single PASS or FAIL for the status of the entire test. + +NOTE: This test will fail on Mac OS, on which these keys are NOT supposed to change the selection of a focused pop-up. + +0 +1 +2 +3 +4 +5 +6 + +0 +1 +2 +3 +4 +5 +6 +7 +FAIL: selectedIndex should be 3 (is 0) after a PageDown from index 0 +FAIL: selectedIndex should be 4 (is 1) after a PageDown from index 1 +FAIL: selectedIndex should be 5 (is 2) after a PageDown from index 2 +FAIL: selectedIndex should be 6 (is 3) after a PageDown from index 3 +FAIL: selectedIndex should be 6 (is 4) after a PageDown from index 4 +FAIL: selectedIndex should be 6 (is 5) after a PageDown from index 5 +FAIL: selectedIndex should be 3 (is 6) after a PageUp from index 6 +FAIL: selectedIndex should be 2 (is 5) after a PageUp from index 5 +FAIL: selectedIndex should be 1 (is 4) after a PageUp from index 4 +FAIL: selectedIndex should be 0 (is 3) after a PageUp from index 3 +FAIL: selectedIndex should be 0 (is 2) after a PageUp from index 2 +FAIL: selectedIndex should be 0 (is 1) after a PageUp from index 1 +FAIL: selectedIndex should be 0 (is 6) after a Home from index 6 +FAIL: selectedIndex should be 0 (is 5) after a Home from index 5 +FAIL: selectedIndex should be 0 (is 4) after a Home from index 4 +FAIL: selectedIndex should be 0 (is 3) after a Home from index 3 +FAIL: selectedIndex should be 0 (is 2) after a Home from index 2 +FAIL: selectedIndex should be 0 (is 1) after a Home from index 1 +FAIL: selectedIndex should be 6 (is 5) after a End from index 5 +FAIL: selectedIndex should be 6 (is 4) after a End from index 4 +FAIL: selectedIndex should be 6 (is 3) after a End from index 3 +FAIL: selectedIndex should be 6 (is 2) after a End from index 2 +FAIL: selectedIndex should be 6 (is 1) after a End from index 1 +FAIL: selectedIndex should be 6 (is 0) after a End from index 0 +FAIL: selectedIndex should be 4 (is 1) after a PageDown from index 1 +FAIL: selectedIndex should be 5 (is 2) after a PageDown from index 2 +FAIL: selectedIndex should be 6 (is 4) after a PageDown from index 4 +FAIL: selectedIndex should be 6 (is 5) after a PageDown from index 5 +FAIL: selectedIndex should be 2 (is 6) after a PageUp from index 6 +FAIL: selectedIndex should be 2 (is 5) after a PageUp from index 5 +FAIL: selectedIndex should be 1 (is 4) after a PageUp from index 4 +FAIL: selectedIndex should be 1 (is 2) after a PageUp from index 2 +FAIL: selectedIndex should be 1 (is 7) after a Home from index 7 +FAIL: selectedIndex should be 1 (is 6) after a Home from index 6 +FAIL: selectedIndex should be 1 (is 5) after a Home from index 5 +FAIL: selectedIndex should be 1 (is 4) after a Home from index 4 +FAIL: selectedIndex should be 1 (is 3) after a Home from index 3 +FAIL: selectedIndex should be 1 (is 2) after a Home from index 2 +FAIL: selectedIndex should be 1 (is 0) after a Home from index 0 +FAIL: selectedIndex should be 6 (is 7) after a End from index 7 +FAIL: selectedIndex should be 6 (is 5) after a End from index 5 +FAIL: selectedIndex should be 6 (is 4) after a End from index 4 +FAIL: selectedIndex should be 6 (is 3) after a End from index 3 +FAIL: selectedIndex should be 6 (is 2) after a End from index 2 +FAIL: selectedIndex should be 6 (is 1) after a End from index 1 +FAIL: selectedIndex should be 6 (is 0) after a End from index 0 + +FAIL: SOME TESTS FAILED (SEE ABOVE) + +
diff --git a/third_party/blink/web_tests/virtual/trust-tokens/README.md b/third_party/blink/web_tests/virtual/trust-tokens/README.md new file mode 100644 index 0000000..34cbc884 --- /dev/null +++ b/third_party/blink/web_tests/virtual/trust-tokens/README.md
@@ -0,0 +1,5 @@ +The prototype Trust Tokens (https://github.com/wicg/trust-token-api) +implementation is going behind an embedder-side flag +(--enable-features=TrustTokens) necessary in addition to the Blink +RuntimeEnabledFeature. This virtual suite allows running the pertinent tests +with the flag on. It can be removed once the flag is enabled by default.
diff --git a/third_party/blink/web_tests/virtual/trust-tokens/http/tests/loading/trust-tokens/README.txt b/third_party/blink/web_tests/virtual/trust-tokens/http/tests/loading/trust-tokens/README.txt new file mode 100644 index 0000000..c981686 --- /dev/null +++ b/third_party/blink/web_tests/virtual/trust-tokens/http/tests/loading/trust-tokens/README.txt
@@ -0,0 +1,3 @@ +Enable the network service side of the Trust Token API +(https://github.com/wicg/trust-token-api) with --enable-features=TrustTokens in +order to test API calls end to end.
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 a387011..86cca4c 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
@@ -3884,6 +3884,7 @@ [Worker] getter status [Worker] getter statusText [Worker] getter timeout +[Worker] getter trustTokenOperationError [Worker] getter upload [Worker] getter withCredentials [Worker] method abort
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 60a024e0..ba924cf 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
@@ -11180,6 +11180,7 @@ getter status getter statusText getter timeout + getter trustTokenOperationError getter upload getter withCredentials method abort
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 99902c4..1d85c1f 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
@@ -3697,6 +3697,7 @@ [Worker] getter status [Worker] getter statusText [Worker] getter timeout +[Worker] getter trustTokenOperationError [Worker] getter upload [Worker] getter withCredentials [Worker] method abort
diff --git a/third_party/custom_tabs_client/BUILD.gn b/third_party/custom_tabs_client/BUILD.gn deleted file mode 100644 index a9dc309..0000000 --- a/third_party/custom_tabs_client/BUILD.gn +++ /dev/null
@@ -1,157 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/rules.gni") - -android_resources("chrome_tabs_client_example_apk_resources") { - sources = [ - "src/Application/src/main/res/anim/slide_in_left.xml", - "src/Application/src/main/res/anim/slide_in_right.xml", - "src/Application/src/main/res/anim/slide_out_left.xml", - "src/Application/src/main/res/anim/slide_out_right.xml", - "src/Application/src/main/res/drawable-hdpi/ic_arrow_back.png", - "src/Application/src/main/res/drawable-hdpi/ic_launcher.png", - "src/Application/src/main/res/drawable-hdpi/ic_notification_icon.png", - "src/Application/src/main/res/drawable-hdpi/ic_play.png", - "src/Application/src/main/res/drawable-hdpi/ic_share.png", - "src/Application/src/main/res/drawable-hdpi/ic_stop.png", - "src/Application/src/main/res/drawable-mdpi/ic_arrow_back.png", - "src/Application/src/main/res/drawable-mdpi/ic_launcher.png", - "src/Application/src/main/res/drawable-mdpi/ic_notification_icon.png", - "src/Application/src/main/res/drawable-mdpi/ic_play.png", - "src/Application/src/main/res/drawable-mdpi/ic_share.png", - "src/Application/src/main/res/drawable-mdpi/ic_stop.png", - "src/Application/src/main/res/drawable-xhdpi/ic_arrow_back.png", - "src/Application/src/main/res/drawable-xhdpi/ic_launcher.png", - "src/Application/src/main/res/drawable-xhdpi/ic_notification_icon.png", - "src/Application/src/main/res/drawable-xhdpi/ic_play.png", - "src/Application/src/main/res/drawable-xhdpi/ic_share.png", - "src/Application/src/main/res/drawable-xhdpi/ic_stop.png", - "src/Application/src/main/res/drawable-xxhdpi/cover.jpg", - "src/Application/src/main/res/drawable-xxhdpi/ic_arrow_back.png", - "src/Application/src/main/res/drawable-xxhdpi/ic_launcher.png", - "src/Application/src/main/res/drawable-xxhdpi/ic_notification_icon.png", - "src/Application/src/main/res/drawable-xxhdpi/ic_play.png", - "src/Application/src/main/res/drawable-xxhdpi/ic_share.png", - "src/Application/src/main/res/drawable-xxhdpi/ic_stop.png", - "src/Application/src/main/res/drawable-xxxhdpi/ic_arrow_back.png", - "src/Application/src/main/res/drawable-xxxhdpi/ic_launcher.png", - "src/Application/src/main/res/drawable-xxxhdpi/ic_share.png", - "src/Application/src/main/res/layout/main.xml", - "src/Application/src/main/res/layout/remote_view.xml", - "src/Application/src/main/res/raw/amazing_grace.mp3", - "src/Application/src/main/res/values/strings.xml", - ] - android_manifest = "src/Application/src/main/AndroidManifest.xml" - custom_package = "org.chromium.customtabsclient" - deps = [ "//third_party/android_deps:android_support_v7_appcompat_java" ] -} - -android_resources("custom_tabs_support_resources") { - sources = [ - "src/customtabs/res/layout/browser_actions_context_menu_page.xml", - "src/customtabs/res/layout/browser_actions_context_menu_row.xml", - "src/customtabs/res/values/colors.xml", - "src/customtabs/res/values/dimens.xml", - "src/customtabs/res/values/strings.xml", - "src/customtabs/res/xml/image_share_filepaths.xml", - ] - android_manifest = "src/customtabs/AndroidManifest.xml" - custom_package = "android.support.customtabs" -} - -android_apk("custom_tabs_client_example_apk") { - skip_jetify = true - sources = [ - "src/Application/src/main/java/org/chromium/customtabsclient/BottomBarManager.java", - "src/Application/src/main/java/org/chromium/customtabsclient/BrowserActionsReceiver.java", - "src/Application/src/main/java/org/chromium/customtabsclient/MainActivity.java", - "src/Application/src/main/java/org/chromium/customtabsclient/SessionHelper.java", - ] - android_manifest = "src/Application/src/main/AndroidManifest.xml" - min_sdk_version = 16 - target_sdk_version = 21 - apk_name = "CustomTabsClientExample" - deps = [ - ":chrome_tabs_client_example_apk_resources", - ":custom_tabs_client_shared_java", - ":custom_tabs_support_java", - "//third_party/android_deps:android_arch_lifecycle_common_java", - "//third_party/android_deps:android_support_v7_appcompat_java", - "//third_party/android_deps:com_android_support_appcompat_v7_java", - "//third_party/android_deps:com_android_support_support_annotations_java", - ] - chromium_code = false -} - -android_library("custom_tabs_client_shared_java") { - skip_jetify = true - sources = [ - "src/shared/src/main/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java", - "src/shared/src/main/java/org/chromium/customtabsclient/shared/KeepAliveService.java", - "src/shared/src/main/java/org/chromium/customtabsclient/shared/ServiceConnection.java", - "src/shared/src/main/java/org/chromium/customtabsclient/shared/ServiceConnectionCallback.java", - ] - - deps = [ ":custom_tabs_support_java" ] - chromium_code = false -} - -android_library("custom_tabs_support_java") { - skip_jetify = true - sources = [ - "src/customtabs/src/android/support/customtabs/CustomTabColorSchemeParams.java", - "src/customtabs/src/android/support/customtabs/CustomTabsCallback.java", - "src/customtabs/src/android/support/customtabs/CustomTabsClient.java", - "src/customtabs/src/android/support/customtabs/CustomTabsIntent.java", - "src/customtabs/src/android/support/customtabs/CustomTabsService.java", - "src/customtabs/src/android/support/customtabs/CustomTabsServiceConnection.java", - "src/customtabs/src/android/support/customtabs/CustomTabsSession.java", - "src/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java", - "src/customtabs/src/android/support/customtabs/PostMessageBackend.java", - "src/customtabs/src/android/support/customtabs/PostMessageService.java", - "src/customtabs/src/android/support/customtabs/PostMessageServiceConnection.java", - "src/customtabs/src/android/support/customtabs/TrustedWebUtils.java", - "src/customtabs/src/android/support/customtabs/browseractions/BrowserActionItem.java", - "src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsFallbackMenuAdapter.java", - "src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsFallbackMenuDialog.java", - "src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsFallbackMenuUi.java", - "src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsFallbackMenuView.java", - "src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java", - "src/customtabs/src/android/support/customtabs/browseractions/BrowserServiceFileProvider.java", - "src/customtabs/src/android/support/customtabs/browseractions/BrowserServiceImageReadTask.java", - "src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityBuilder.java", - "src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityService.java", - "src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityServiceConnectionManager.java", - "src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityServiceWrapper.java", - ] - deps = [ - ":custom_tabs_support_resources", - - # TODO (bjoyce): Restore to android_support_v7_appcompat_java once source - # files are manually written to androidx crbug.com/1047843. - # "//third_party/android_deps:android_support_v7_appcompat_java", - # Remove _temp target once upstream is compatible. - "//third_party/android_deps:com_android_support_appcompat_v7_java_temp", - "//third_party/android_deps:com_android_support_collections_java_orig", - "//third_party/android_deps:com_android_support_interpolator_java", - "//third_party/android_deps:com_android_support_support_annotations_java", - "//third_party/android_deps:com_android_support_support_compat_java", - ] - srcjar_deps = [ ":chrome_custom_tabs_service_aidl" ] - android_manifest_for_lint = "src/customtabs/AndroidManifest.xml" - chromium_code = false -} - -android_aidl("chrome_custom_tabs_service_aidl") { - interface_file = "common.aidl" - - java_in_dir = "src/customtabs/src/android/support/customtabs" - sources = [ - "$java_in_dir/ICustomTabsCallback.aidl", - "$java_in_dir/ICustomTabsService.aidl", - "$java_in_dir/IPostMessageService.aidl", - "$java_in_dir/trusted/ITrustedWebActivityService.aidl", - ] -}
diff --git a/third_party/custom_tabs_client/LICENSE b/third_party/custom_tabs_client/LICENSE deleted file mode 100644 index 67db858..0000000 --- a/third_party/custom_tabs_client/LICENSE +++ /dev/null
@@ -1,175 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability.
diff --git a/third_party/custom_tabs_client/OWNERS b/third_party/custom_tabs_client/OWNERS deleted file mode 100644 index e341d82..0000000 --- a/third_party/custom_tabs_client/OWNERS +++ /dev/null
@@ -1,7 +0,0 @@ -lizeb@chromium.org -peconn@chromium.org -yusufo@chromium.org - -per-file *.aidl=set noparent -per-file *.aidl=file://ipc/SECURITY_OWNERS -# COMPONENT: UI>Browser>Mobile>CustomTabs
diff --git a/third_party/custom_tabs_client/README.chromium b/third_party/custom_tabs_client/README.chromium deleted file mode 100644 index 0bf829b..0000000 --- a/third_party/custom_tabs_client/README.chromium +++ /dev/null
@@ -1,26 +0,0 @@ -Name: Chrome Custom Tabs - Example and Usage -Short Name: Chrome Custom Tabs Client -URL: https://chromium.googlesource.com/external/github.com/GoogleChrome/custom-tabs-client -Version: unknown -License: Apache 2.0 -Security Critical: yes -License Android Compatible: yes - -Description: -This presents an example application using Chrome Custom Tabs, and a possible -usage of both the intent and the background service APIs. It covers UI -customization, callback setup, pre-warming and pre-fetching, and lifecycle -management. Also inside demos there is another application that launches -custom tabs in different modes. - -The example applicaton also presents how to use Browser Actions, including -creating request intent and adding custom items. - -The actual code that Chromium builds from is in -//third_party/android_sdk/androidx_browser, this subdirectory is kept around -for the example app (the custom_tabs_client_example_apk target). - -TODO(peconn): Get rid of src/customtabs and depend instead on -androidx_browser. - -Local Modifications: None
diff --git a/third_party/custom_tabs_client/common.aidl b/third_party/custom_tabs_client/common.aidl deleted file mode 100644 index 5566e8c..0000000 --- a/third_party/custom_tabs_client/common.aidl +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -interface android.support.customtabs.ICustomTabsService; -interface android.support.customtabs.ICustomTabsCallback; -interface android.support.customtabs.IPostMessageService;
diff --git a/third_party/googletest/BUILD.gn b/third_party/googletest/BUILD.gn index a906f07..52c2858 100644 --- a/third_party/googletest/BUILD.gn +++ b/third_party/googletest/BUILD.gn
@@ -171,8 +171,6 @@ "src/googlemock/include/gmock/gmock-cardinalities.h", "src/googlemock/include/gmock/gmock-function-mocker.h", "src/googlemock/include/gmock/gmock-generated-actions.h", - "src/googlemock/include/gmock/gmock-generated-function-mockers.h", - "src/googlemock/include/gmock/gmock-generated-matchers.h", "src/googlemock/include/gmock/gmock-matchers.h", "src/googlemock/include/gmock/gmock-more-actions.h", "src/googlemock/include/gmock/gmock-more-matchers.h",
diff --git a/third_party/sqlite/PRESUBMIT.py b/third_party/sqlite/PRESUBMIT.py index 7be2bbc..950e536e 100644 --- a/third_party/sqlite/PRESUBMIT.py +++ b/third_party/sqlite/PRESUBMIT.py
@@ -8,11 +8,17 @@ def CheckChangeOnUpload(input_api, output_api): - results = [] + results = [] + this_dir = input_api.PresubmitLocalPath() - results += input_api.RunTests( - input_api.canned_checks.GetUnitTests(input_api, output_api, [ - 'scripts/extract_sqlite_api_unittest.py' - ], env=None, run_on_python2=False, run_on_python3=True)) + results += input_api.RunTests( + input_api.canned_checks.GetUnitTestsInDirectory( + input_api, + output_api, + input_api.os_path.join(this_dir, 'scripts'), + whitelist=['.*unittest.py$'], + env=None, + run_on_python2=False, + run_on_python3=True)) - return results + return results
diff --git a/third_party/sqlite/scripts/.style.yapf b/third_party/sqlite/scripts/.style.yapf new file mode 100644 index 0000000..1d02278 --- /dev/null +++ b/third_party/sqlite/scripts/.style.yapf
@@ -0,0 +1,3 @@ +[style] +based_on_style = pep8 +
diff --git a/third_party/sqlite/scripts/.yapfignore b/third_party/sqlite/scripts/.yapfignore new file mode 100644 index 0000000..a278a739 --- /dev/null +++ b/third_party/sqlite/scripts/.yapfignore
@@ -0,0 +1,3 @@ +# TODO(cmumford): Format older files in a future CL. +extract_sqlite_api.py +extract_sqlite_api_unittest.py
diff --git a/third_party/sqlite/scripts/sqlite_cherry_picker.py b/third_party/sqlite/scripts/sqlite_cherry_picker.py index eaef97c..c4d5de8 100755 --- a/third_party/sqlite/scripts/sqlite_cherry_picker.py +++ b/third_party/sqlite/scripts/sqlite_cherry_picker.py
@@ -12,325 +12,361 @@ class UnstagedFiles(Exception): - pass + pass class UnknownHash(Exception): - pass + pass + + +class IncorrectType(Exception): + pass class bcolors: - HEADER = '\033[95m' - OKBLUE = '\033[94m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - ENDC = '\033[0m' + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' def _print_command(cmd): - """Print the command to be executed to the console. + """Print the command to be executed to the console. - Use a different color so that it can be easily seen amongst the output - commands. - """ - if (isinstance(cmd, list)): - cmd = ' '.join(cmd) - print('{}{}{}'.format(bcolors.OKBLUE, cmd, bcolors.ENDC)) + Use a different color so that it can be easily seen amongst the output + commands. + """ + if (isinstance(cmd, list)): + cmd = ' '.join(cmd) + print('{}{}{}'.format(bcolors.OKBLUE, cmd, bcolors.ENDC)) class ManifestEntry(object): - """Represents a single entry in a SQLite manifest.""" + """Represents a single entry in a SQLite manifest.""" - valid_types = ('C', 'D', 'F', 'P', 'R', 'T', 'U', 'Z') + def __init__(self, entry_type, items): + if not len(entry_type) == 1: + raise IncorrectType(entry_type) + self.entry_type = entry_type + self.items = items - def __init__(self, entry_type, items): - assert entry_type in ManifestEntry.valid_types - self.entry_type = entry_type - self.items = items + def get_hash_type(self): + """Return the type of hash used for this entry.""" + last_item = self.items[-1] + if not all(c in string.hexdigits for c in last_item): + print( + '"{}" doesn\'t appear to be a hash.'.format(last_item), + file=sys.stderr) + raise UnknownHash() + elif len(last_item) == 40: + return 'sha1' + elif len(last_item) == 64: + return 'sha3' + else: + raise UnknownHash('Incorrect length {} for {}'.format( + len(last_item), last_item)) - def get_hash_type(self): - """Return the type of hash used for this entry.""" - last_item = self.items[-1] - if not all(c in string.hexdigits for c in last_item): - print( - '"{}" doesn\'t appear to be a hash.'.format(last_item), - file=sys.stderr) - raise UnknownHash() - elif len(last_item) == 40: - return 'sha1' - elif len(last_item) == 64: - return 'sha3' - else: - print( - 'Incorrect length {} for {}'.format(len(last_item), last_item), - file=sys.stderr) - raise UnknownHash() + @staticmethod + def calc_hash(data, method): + """Return the string sha1 or sha3 hash digest for the given data.""" + if method == 'sha3': + h = hashlib.sha3_256() + elif method == 'sha1': + h = hashlib.sha1() + else: + assert False + h.update(data) + return h.hexdigest() - @staticmethod - def calc_hash(fname, method): - """Return the string sha3 hash digest for the given file.""" - with open(fname, 'rb') as input_file: - if method == 'sha3': - h = hashlib.sha3_256() - elif method == 'sha1': - h = hashlib.sha1() - else: - assert False - h.update(input_file.read()) - return h.hexdigest() + @staticmethod + def calc_file_hash(fname, method): + """Return the string sha1 or sha3 hash digest for the given file.""" + with open(fname, 'rb') as input_file: + return ManifestEntry.calc_hash(input_file.read(), method) - def update_file_hash(self): - """Calculates a new file hash for this entry.""" - self.items[1] = ManifestEntry.calc_hash(self.items[0], self.get_hash_type()) + def update_file_hash(self): + """Calculates a new file hash for this entry.""" + self.items[1] = ManifestEntry.calc_file_hash(self.items[0], + self.get_hash_type()) - def __str__(self): - return '{} {}'.format(self.entry_type, ' '.join(self.items)) + def __str__(self): + return '{} {}'.format(self.entry_type, ' '.join(self.items)) class Manifest(object): - """A deserialized SQLite manifest.""" + """A deserialized SQLite manifest.""" - def __init__(self): - self.entries = [] + def __init__(self): + self.entries = [] - def find_file_entry(self, fname): - """Given a file path return the entry. Returns None if none found.""" - for entry in self.entries: - if entry.entry_type == 'F' and entry.items[0] == fname: - return entry - return None + def find_file_entry(self, fname): + """Given a file path return the entry. Returns None if none found.""" + for entry in self.entries: + if entry.entry_type == 'F' and entry.items[0] == fname: + return entry + return None class ManifestSerializer(object): - """De/serialize SQLite manifests.""" + """De/serialize SQLite manifests.""" - @staticmethod - def read(fname): - """Deserialze a manifest file and return a Manifest object.""" - _manifest = Manifest() - with open(fname) as input_file: - for line in input_file.readlines(): - items = line.split() - if not items: - continue - _manifest.entries.append(ManifestEntry(items[0], items[1:])) - return _manifest + @staticmethod + def read_stream(input_stream): + """Deserialize a manifest from an input stream and return a Manifest + object.""" + _manifest = Manifest() + for line in input_stream.readlines(): + items = line.split() + if not items: + continue + _manifest.entries.append(ManifestEntry(items[0], items[1:])) + return _manifest - @staticmethod - def write(fname, manifest): - """Serialize the given manifest to the specified file.""" - with open(fname, 'w') as output_file: - for entry in manifest.entries: - print(str(entry), file=output_file) + @staticmethod + def read_file(fname): + """Deserialize a manifest file and return a Manifest object.""" + with open(fname) as input_stream: + return ManifestSerializer.read_stream(input_stream) + + @staticmethod + def write_stream(manifest, output_stream): + """Serialize the given manifest to the given stream.""" + for entry in manifest.entries: + print(str(entry), file=output_stream) + + @staticmethod + def write_file(manifest, fname): + """Serialize the given manifest to the specified file.""" + with open(fname, 'w') as output_stream: + ManifestSerializer.write_stream(manifest, output_stream) class Git(object): + @staticmethod + def _get_status(): + changes = [] + for line in subprocess.check_output(['git', 'status', + '--porcelain']).splitlines(): + changes.append(line.decode('utf-8')) + return changes - @staticmethod - def _get_status(): - changes = [] - for line in subprocess.check_output(['git', 'status', - '--porcelain']).splitlines(): - changes.append(line.decode('utf-8')) - return changes + @staticmethod + def get_staged_changes(): + changes = [] + for line in Git._get_status(): + entry = line[0:2] + if entry == 'M ': + changes.append(line.split()[1]) + return changes - @staticmethod - def get_staged_changes(): - changes = [] - for line in Git._get_status(): - entry = line[0:2] - if entry == 'M ': - changes.append(line.split()[1]) - return changes + @staticmethod + def get_unstaged_changes(): + changes = [] + for line in Git._get_status(): + entry = line[0:2] + if entry == ' M': + changes.append(line.split()[1]) + return changes - @staticmethod - def get_unstaged_changes(): - changes = [] - for line in Git._get_status(): - entry = line[0:2] - if entry == ' M': - changes.append(line.split()[1]) - return changes - - @staticmethod - def get_unmerged_changes(): - changes = [] - for line in Git._get_status(): - entry = line[0:2] - if entry == 'UU': - changes.append(line.split()[1]) - return changes + @staticmethod + def get_unmerged_changes(): + changes = [] + for line in Git._get_status(): + entry = line[0:2] + if entry == 'UU': + changes.append(line.split()[1]) + return changes class CherryPicker(object): - """Class to cherry pick commits in a SQLite Git repository.""" + """Class to cherry pick commits in a SQLite Git repository.""" - def __init__(self): - self._print_cmds = True - self._update_amangamation = True + # The binary file extenions for files committed to the SQLite repository. + # This is used as a simple way of detecting files that cannot (simply) be + # resolved in a merge conflict. This script will automatically ignore + # all conflicted files with any of these extensions. If, in the future, new + # binary types are added then a conflict will arise during cherry-pick and + # the user will need to resolve it. + binary_extensions = ( + '.data', + '.db', + '.ico', + '.jpg', + '.png', + ) - def _take_head_version(self, file_path): - subprocess.call( - 'git show HEAD:{} > {}'.format(file_path, file_path), shell=True) - subprocess.call('git add {}'.format(file_path), shell=True) + def __init__(self): + self._print_cmds = True + self._update_amangamation = True - @staticmethod - def _is_binary_file(file_path): - _, file_extension = os.path.splitext(file_path) - return file_extension == '.db' + def _take_head_version(self, file_path): + subprocess.call( + 'git show HEAD:{} > {}'.format(file_path, file_path), shell=True) + subprocess.call('git add {}'.format(file_path), shell=True) - @staticmethod - def _append_cherry_pick_comments(comments): - # TODO(cmumford): Figure out how to append comments on cherry picks - pass + @staticmethod + def _is_binary_file(file_path): + _, file_extension = os.path.splitext(file_path) + return file_extension in CherryPicker.binary_extensions - def _cherry_pick_git_commit(self, commit_id): - """Cherry-pick a given Git commit into the current branch.""" - cmd = ['git', 'cherry-pick', '-x', commit_id] - if self._print_cmds: - _print_command(' '.join(cmd)) - returncode = subprocess.call(cmd) - # The manifest and manifest.uuid contain Fossil hashes. Restore to - # HEAD version and update only when all conflicts have been resolved. - comments = None - self._take_head_version('manifest') - self._take_head_version('manifest.uuid') - for unmerged_file in Git.get_unmerged_changes(): - if CherryPicker._is_binary_file(unmerged_file): - print('{} is a binary file, keeping branch version.'.format( - unmerged_file)) - self._take_head_version(unmerged_file) - if not comments: - comments = ['Cherry-pick notes', '=============================='] - comments.append( - '{} is binary file (with conflict). Keeping branch version'.format( - unmerged_file)) - if comments: - CherryPicker._append_cherry_pick_comments(comments) - self.continue_cherry_pick() + @staticmethod + def _append_cherry_pick_comments(comments): + # TODO(cmumford): Figure out how to append comments on cherry picks + pass - @staticmethod - def _is_git_commit_id(commit_id): - return len(commit_id) == 40 + def _cherry_pick_git_commit(self, commit_id): + """Cherry-pick a given Git commit into the current branch.""" + cmd = ['git', 'cherry-pick', '-x', commit_id] + if self._print_cmds: + _print_command(' '.join(cmd)) + returncode = subprocess.call(cmd) + # The manifest and manifest.uuid contain Fossil hashes. Restore to + # HEAD version and update only when all conflicts have been resolved. + comments = None + self._take_head_version('manifest') + self._take_head_version('manifest.uuid') + for unmerged_file in Git.get_unmerged_changes(): + if CherryPicker._is_binary_file(unmerged_file): + print('{} is a binary file, keeping branch version.'.format( + unmerged_file)) + self._take_head_version(unmerged_file) + if not comments: + comments = [ + 'Cherry-pick notes', '==============================' + ] + comments.append( + '{} is binary file (with conflict). Keeping branch version' + .format(unmerged_file)) + if comments: + CherryPicker._append_cherry_pick_comments(comments) + self.continue_cherry_pick() - def _find_git_commit_id(self, fossil_commit_id): - cmd = [ - 'git', '--no-pager', 'log', '--color=never', '--all', - '--pretty=format:%H', '--grep={}'.format(fossil_commit_id), - 'origin/master' - ] - if self._print_cmds: - _print_command(' '.join(cmd)) - for line in subprocess.check_output(cmd).splitlines(): - return line.decode('utf-8') - # Not found. - assert False + @staticmethod + def _is_git_commit_id(commit_id): + return len(commit_id) == 40 - def cherry_pick(self, commit_id): - """Cherry-pick a given commit into the current branch. + def _find_git_commit_id(self, fossil_commit_id): + cmd = [ + 'git', '--no-pager', 'log', '--color=never', '--all', + '--pretty=format:%H', '--grep={}'.format(fossil_commit_id), + 'origin/master' + ] + if self._print_cmds: + _print_command(' '.join(cmd)) + for line in subprocess.check_output(cmd).splitlines(): + return line.decode('utf-8') + # Not found. + assert False + + def cherry_pick(self, commit_id): + """Cherry-pick a given commit into the current branch. Can cherry-pick a given Git or a Fossil commit. - """ - if not CherryPicker._is_git_commit_id(commit_id): - commit_id = self._find_git_commit_id(commit_id) - self._cherry_pick_git_commit(commit_id) + """ + if not CherryPicker._is_git_commit_id(commit_id): + commit_id = self._find_git_commit_id(commit_id) + self._cherry_pick_git_commit(commit_id) - def _generate_amalgamation(self): - for config_name in ['chromium', 'dev']: - generate_amalgamation.make_aggregate(config_name) - generate_amalgamation.extract_sqlite_api(config_name) + def _generate_amalgamation(self): + for config_name in ['chromium', 'dev']: + generate_amalgamation.make_aggregate(config_name) + generate_amalgamation.extract_sqlite_api(config_name) - def _add_amalgamation(self): - os.chdir(generate_amalgamation._SQLITE_SRC_DIR) - for config_name in ['chromium', 'dev']: - cmd = [ - 'git', 'add', - generate_amalgamation.get_amalgamation_dir(config_name) - ] - if self._print_cmds: - _print_command(' '.join(cmd)) - subprocess.check_call(cmd) + def _add_amalgamation(self): + os.chdir(generate_amalgamation._SQLITE_SRC_DIR) + for config_name in ['chromium', 'dev']: + cmd = [ + 'git', 'add', + generate_amalgamation.get_amalgamation_dir(config_name) + ] + if self._print_cmds: + _print_command(' '.join(cmd)) + subprocess.check_call(cmd) - def _update_manifests(self): - """Update the SQLite's Fossil manifest files. + def _update_manifests(self): + """Update the SQLite's Fossil manifest files. - This isn't strictly necessary as the manifest isn't used during - any build, and manifest.uuid is the Fossil commit ID (which - has no meaning in a Git repo). However, keeping these updated - helps make it more obvious that a commit originated in - Git and not Fossil. - """ - manifest = ManifestSerializer.read('manifest') - files_not_in_manifest = ('manifest', 'manifest.uuid') - for fname in Git.get_staged_changes(): - if fname in files_not_in_manifest: - continue - entry = manifest.find_file_entry(fname) - if not entry: - print( - 'Cannot find manifest entry for "{}"'.format(fname), - file=sys.stderr) - sys.exit(1) - manifest.find_file_entry(fname).update_file_hash() - ManifestSerializer.write('manifest', manifest) - cmd = ['git', 'add', 'manifest'] - if self._print_cmds: - _print_command(' '.join(cmd)) - subprocess.check_call(cmd) - # manifest.uuid contains the hash from the Fossil repository which - # doesn't make sense in a Git branch. Just write all zeros. - with open('manifest.uuid', 'w') as output_file: - print('0' * 64, file=output_file) - cmd = ['git', 'add', 'manifest.uuid'] - if self._print_cmds: - _print_command(' '.join(cmd)) - subprocess.check_call(cmd) + This isn't strictly necessary as the manifest isn't used during + any build, and manifest.uuid is the Fossil commit ID (which + has no meaning in a Git repo). However, keeping these updated + helps make it more obvious that a commit originated in + Git and not Fossil. + """ + manifest = ManifestSerializer.read_file('manifest') + files_not_in_manifest = ('manifest', 'manifest.uuid') + for fname in Git.get_staged_changes(): + if fname in files_not_in_manifest: + continue + entry = manifest.find_file_entry(fname) + if not entry: + print( + 'Cannot find manifest entry for "{}"'.format(fname), + file=sys.stderr) + sys.exit(1) + manifest.find_file_entry(fname).update_file_hash() + ManifestSerializer.write_file(manifest, 'manifest') + cmd = ['git', 'add', 'manifest'] + if self._print_cmds: + _print_command(' '.join(cmd)) + subprocess.check_call(cmd) + # manifest.uuid contains the hash from the Fossil repository which + # doesn't make sense in a Git branch. Just write all zeros. + with open('manifest.uuid', 'w') as output_file: + print('0' * 64, file=output_file) + cmd = ['git', 'add', 'manifest.uuid'] + if self._print_cmds: + _print_command(' '.join(cmd)) + subprocess.check_call(cmd) - def continue_cherry_pick(self): - if Git.get_unstaged_changes() or Git.get_unmerged_changes(): - raise UnstagedFiles() - self._update_manifests() - if self._update_amangamation: - self._generate_amalgamation() - self._add_amalgamation() - cmd = ['git', 'cherry-pick', '--continue'] - if self._print_cmds: - _print_command(' '.join(cmd)) - subprocess.check_call(cmd) + def continue_cherry_pick(self): + if Git.get_unstaged_changes() or Git.get_unmerged_changes(): + raise UnstagedFiles() + self._update_manifests() + if self._update_amangamation: + self._generate_amalgamation() + self._add_amalgamation() + cmd = ['git', 'cherry-pick', '--continue'] + if self._print_cmds: + _print_command(' '.join(cmd)) + subprocess.check_call(cmd) if __name__ == '__main__': - desc = 'A script for cherry-picking commits from the SQLite repo.' - parser = argparse.ArgumentParser(description=desc) - parser.add_argument( - 'commit', nargs='*', help='The commit ids to cherry pick (in order)') - parser.add_argument( - '--continue', - dest='cont', - action='store_true', - help='Continue the cherry-pick once conflicts have been resolved') - namespace = parser.parse_args() - cherry_picker = CherryPicker() - if namespace.cont: - try: - cherry_picker.continue_cherry_pick() - sys.exit(0) - except UnstagedFiles: - print('There are still unstaged files to resolve before continuing.') - sys.exit(1) - num_picked = 0 - for commit_id in namespace.commit: - try: - cherry_picker.cherry_pick(commit_id) - num_picked += 1 - except UnstagedFiles: - print('\nThis cherry-pick contains conflicts. Please resolve them ') - print('(e.g git mergetool) and rerun this script ' - '`sqlite_cherry_picker.py --continue`') - print('or `git cherry-pick --abort`.') - if commit_id != namespace.commit[-1]: - msg = ('NOTE: You have only successfully cherry-picked {} out of {} ' - 'commits.') - print(msg.format(num_picked, len(namespace.commit))) - sys.exit(1) + desc = 'A script for cherry-picking commits from the SQLite repo.' + parser = argparse.ArgumentParser(description=desc) + parser.add_argument( + 'commit', nargs='*', help='The commit ids to cherry pick (in order)') + parser.add_argument( + '--continue', + dest='cont', + action='store_true', + help='Continue the cherry-pick once conflicts have been resolved') + namespace = parser.parse_args() + cherry_picker = CherryPicker() + if namespace.cont: + try: + cherry_picker.continue_cherry_pick() + sys.exit(0) + except UnstagedFiles: + print( + 'There are still unstaged files to resolve before continuing.') + sys.exit(1) + num_picked = 0 + for commit_id in namespace.commit: + try: + cherry_picker.cherry_pick(commit_id) + num_picked += 1 + except UnstagedFiles: + print( + '\nThis cherry-pick contains conflicts. Please resolve them ') + print('(e.g git mergetool) and rerun this script ' + '`sqlite_cherry_picker.py --continue`') + print('or `git cherry-pick --abort`.') + if commit_id != namespace.commit[-1]: + msg = ( + 'NOTE: You have only successfully cherry-picked {} out of ' + '{} commits.') + print(msg.format(num_picked, len(namespace.commit))) + sys.exit(1)
diff --git a/third_party/sqlite/scripts/sqlite_cherry_picker_unittest.py b/third_party/sqlite/scripts/sqlite_cherry_picker_unittest.py new file mode 100755 index 0000000..587c7cfa --- /dev/null +++ b/third_party/sqlite/scripts/sqlite_cherry_picker_unittest.py
@@ -0,0 +1,133 @@ +#!/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. +"""Tests for sqlite_cherry_picker.py. + +These tests should be getting picked up by the PRESUBMIT.py in the parent +directory. +""" + +from pathlib import Path +import io +import os +import shutil +import tempfile +import unittest +import sqlite_cherry_picker + +# pylint: disable=W0212,C0103,C0115,C0116 + + +class CherryPickerUnittest(unittest.TestCase): + def setUp(self): + self.test_root = tempfile.mkdtemp() + + def tearDown(self): + if self.test_root: + shutil.rmtree(self.test_root) + + def testManifestEntryConstructor(self): + with self.assertRaises(sqlite_cherry_picker.IncorrectType): + entry = sqlite_cherry_picker.ManifestEntry('DD', [ + 'vsixtest/vsixtest.tcl', + '6a9a6ab600c25a91a7acc6293828957a386a8a93' + ]) + del entry # unused because exception will be raised. + + def testManifestEntryHashType(self): + entry = sqlite_cherry_picker.ManifestEntry('F', [ + 'vsixtest/vsixtest.tcl', '6a9a6ab600c25a91a7acc6293828957a386a8a93' + ]) + self.assertEqual(entry.get_hash_type(), 'sha1') + + entry = sqlite_cherry_picker.ManifestEntry('F', [ + 'tool/warnings-clang.sh', + 'bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7' + ]) + self.assertEqual(entry.get_hash_type(), 'sha3') + + # test a bad hash which is too short and cannot be identified as either + # a sha1 or sha3 hash. + with self.assertRaises(sqlite_cherry_picker.UnknownHash): + entry = sqlite_cherry_picker.ManifestEntry( + 'F', ['file/path.sh', '12345678']) + entry.get_hash_type() + + def testManifestEntryHashCalc(self): + data = 'abcdefghijklmnopqrstuvwxyDEFGHIJKLMUVWXYZ0123456789'.encode( + 'utf-8') + self.assertEqual( + sqlite_cherry_picker.ManifestEntry.calc_hash(data, 'sha1'), + 'e117bfe4bcb1429cf8a0f72f8f4ea322a9a500eb') + self.assertEqual( + sqlite_cherry_picker.ManifestEntry.calc_hash(data, 'sha3'), + '2cb59ee01402c45e7c56008b7ca33d006dbd980a5e222fac3a584f5639a450d7') + + def testManifestFindEntry(self): + manifest = sqlite_cherry_picker.Manifest() + self.assertIsNone(manifest.find_file_entry('nonexistent')) + manifest.entries = [ + sqlite_cherry_picker.ManifestEntry('F', [ + 'tool/warnings-clang.sh', + 'bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7' + ]), + sqlite_cherry_picker.ManifestEntry('T', + ['+bgcolor', '*', '#d0c0ff']) + ] + + entry = manifest.find_file_entry('tool/warnings-clang.sh') + self.assertIsNotNone(entry) + self.assertEqual(entry.items[0], 'tool/warnings-clang.sh') + + # Should only find files. + self.assertIsNone(manifest.find_file_entry('+bgcolor')) + + def testManifestDeserialize(self): + manfest_path = os.path.join( + os.path.dirname(os.path.realpath(__file__)), 'test_data', + 'test_manifest') + manifest_data = Path(manfest_path).read_text() + input_stream = io.StringIO(manifest_data) + manifest = sqlite_cherry_picker.ManifestSerializer.read_stream( + input_stream) + self.assertEqual(len(manifest.entries), 9) + + output_stream = io.StringIO() + sqlite_cherry_picker.ManifestSerializer.write_stream( + manifest, output_stream) + self.assertEqual(output_stream.getvalue(), manifest_data) + + def testGitHash(self): + valid_git_commit_id = '61c3ca1b1c77bbcaa35f9326decf3658bdb5626a' + self.assertTrue( + sqlite_cherry_picker.CherryPicker._is_git_commit_id( + valid_git_commit_id)) + + invalid_git_commit_id = 'f3658bdb5626a' + self.assertFalse( + sqlite_cherry_picker.CherryPicker._is_git_commit_id( + invalid_git_commit_id)) + + def testIsBinaryFile(self): + self.assertTrue( + sqlite_cherry_picker.CherryPicker._is_binary_file( + 'path/test.data')) + self.assertTrue( + sqlite_cherry_picker.CherryPicker._is_binary_file('path/test.db')) + self.assertTrue( + sqlite_cherry_picker.CherryPicker._is_binary_file('path/test.ico')) + self.assertTrue( + sqlite_cherry_picker.CherryPicker._is_binary_file('path/test.jpg')) + self.assertTrue( + sqlite_cherry_picker.CherryPicker._is_binary_file('path/test.png')) + + self.assertFalse( + sqlite_cherry_picker.CherryPicker._is_binary_file('path/test.c')) + self.assertFalse( + sqlite_cherry_picker.CherryPicker._is_binary_file('path/test.h')) + + +if __name__ == '__main__': + unittest.main()
diff --git a/third_party/sqlite/scripts/test_data/test_manifest b/third_party/sqlite/scripts/test_data/test_manifest new file mode 100644 index 0000000..109045e1 --- /dev/null +++ b/third_party/sqlite/scripts/test_data/test_manifest
@@ -0,0 +1,9 @@ +C Version\s3.31.1 +D 2020-01-27T19:55:54.490 +F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 +R bf075f6bcc1758c5c1ecd13052997456 +T +bgcolor * #d0c0ff +T +sym-release * +T +sym-version-3.31.1 * +U drh +Z 7c50801eed3eaef969e028ef5a0a641a
diff --git a/tools/android/avd/OWNERS b/tools/android/avd/OWNERS new file mode 100644 index 0000000..3e81536 --- /dev/null +++ b/tools/android/avd/OWNERS
@@ -0,0 +1 @@ +file://build/android/pylib/local/emulator/OWNERS
diff --git a/tools/android/avd/avd.py b/tools/android/avd/avd.py index 357561f..1098400 100755 --- a/tools/android/avd/avd.py +++ b/tools/android/avd/avd.py
@@ -99,6 +99,12 @@ action='store_true', default=False, help='Enable graphical window display on the emulator.') + start_parser.add_argument( + '--debug-tags', + help='Comma-separated list of debug tags. This can be used to enable or ' + 'disable debug messages from specific parts of the emulator, e.g. ' + 'init, snapshot. See "emulator -help-debug-tags" ' + 'for a full list of tags.') add_common_arguments(start_parser) def start_cmd(args): @@ -106,7 +112,8 @@ inst.Start( read_only=args.read_only, snapshot_save=not args.read_only, - window=args.emulator_window) + window=args.emulator_window, + debug_tags=args.debug_tags) print('%s started (pid: %d)' % (str(inst), inst._emulator_proc.pid)) return 0
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 9fe479a7..5b570dae 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -37550,6 +37550,7 @@ <int value="-2134244069" label="HttpFormWarning:enabled"/> <int value="-2133892372" label="ResamplingInputEvents:disabled"/> <int value="-2133277113" label="CCTModuleCustomHeader:disabled"/> + <int value="-2133276662" label="EduCoexistenceConsentLog:disabled"/> <int value="-2132591642" label="enable-input-view"/> <int value="-2132161378" label="SendTabToSelfHistory:disabled"/> <int value="-2131746498" @@ -38885,6 +38886,7 @@ <int value="-649956990" label="enable-harfbuzz-rendertext"/> <int value="-648925189" label="ExploreSites:enabled"/> <int value="-645455405" label="MacViewsNativeDialogs:enabled"/> + <int value="-643217597" label="EduCoexistenceConsentLog:enabled"/> <int value="-641820371" label="EnableCustomMacPaperSizes:enabled"/> <int value="-641719457" label="disable-compositor-touch-hit-testing"/> <int value="-640191786" label="DesktopPWAsWithoutExtensions:enabled"/>
diff --git a/ui/accessibility/ax_tree_serializer.h b/ui/accessibility/ax_tree_serializer.h index 18fe3aa..b9e6fc36 100644 --- a/ui/accessibility/ax_tree_serializer.h +++ b/ui/accessibility/ax_tree_serializer.h
@@ -180,6 +180,8 @@ // like when Reset() is called. void InternalReset(); + ClientTreeNode* GetClientTreeNodeParent(ClientTreeNode* obj); + // The tree source. AXTreeSource<AXSourceNode, AXNodeData, AXTreeData>* tree_; @@ -269,7 +271,7 @@ std::vector<ClientTreeNode*> client_ancestors; while (client_node) { client_ancestors.push_back(client_node); - client_node = client_node->parent; + client_node = GetClientTreeNodeParent(client_node); } // Start at the root. Keep going until the source ancestor chain and @@ -304,9 +306,12 @@ // that we're inside of an invalid subtree that all needs to be // re-serialized, so the LCA should be higher. ClientTreeNode* client_node = ClientTreeNodeById(tree_->GetId(node)); - while ( - tree_->IsValid(node) && - (!client_node || (client_node->parent && client_node->parent->invalid))) { + while (tree_->IsValid(node)) { + if (client_node) { + ClientTreeNode* parent = GetClientTreeNodeParent(client_node); + if (!parent || !parent->invalid) + break; + } node = tree_->GetParent(node); if (tree_->IsValid(node)) client_node = ClientTreeNodeById(tree_->GetId(node)); @@ -326,12 +331,13 @@ int child_id = tree_->GetId(child); ClientTreeNode* client_child = ClientTreeNodeById(child_id); if (client_child) { - if (!client_child->parent) { + ClientTreeNode* parent = client_child->parent; + if (!parent) { // If the client child has no parent, it must have been the // previous root node, so there is no LCA and we can exit early. *out_lca = tree_->GetNull(); return true; - } else if (client_child->parent->id != id) { + } else if (parent->id != id) { // If the client child's parent is not this node, update the LCA // and return true (reparenting was found). *out_lca = LeastCommonAncestor(*out_lca, client_child); @@ -367,6 +373,19 @@ } template <typename AXSourceNode, typename AXNodeData, typename AXTreeData> +ClientTreeNode* +AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::GetClientTreeNodeParent( + ClientTreeNode* obj) { + ClientTreeNode* parent = obj->parent; +#if DCHECK_IS_ON() + if (!parent) + return nullptr; + DCHECK(ClientTreeNodeById(parent->id)) << "Parent not in id map."; +#endif // DCHECK_IS_ON() + return parent; +} + +template <typename AXSourceNode, typename AXNodeData, typename AXTreeData> bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::SerializeChanges( AXSourceNode node, AXTreeUpdateBase<AXNodeData, AXTreeData>* out_update) { @@ -549,7 +568,7 @@ // above. If this happens, reset and return an error. ClientTreeNode* client_child = ClientTreeNodeById(new_child_id); - if (client_child && client_child->parent != client_node) { + if (client_child && GetClientTreeNodeParent(client_child) != client_node) { DVLOG(1) << "Illegal reparenting detected"; #if defined(ADDRESS_SANITIZER) // Wrapping this in ADDRESS_SANITIZER will cause it to run on
diff --git a/ui/base/cocoa/command_dispatcher.h b/ui/base/cocoa/command_dispatcher.h index 0fca888..91f7d54 100644 --- a/ui/base/cocoa/command_dispatcher.h +++ b/ui/base/cocoa/command_dispatcher.h
@@ -58,6 +58,9 @@ - (void)dispatchUsingKeyModifiers:(id)sender forHandler:(id<UserInterfaceItemCommandHandler>)handler; +// TODO(bokan): Temporary to help debug https://crbug.com/1039833. +- (BOOL)isRedispatchingKeyEvent; + @end // If the NSWindow's firstResponder implements CommandDispatcherTarget, then
diff --git a/ui/base/cocoa/command_dispatcher.mm b/ui/base/cocoa/command_dispatcher.mm index 506ab361..50a0232 100644 --- a/ui/base/cocoa/command_dispatcher.mm +++ b/ui/base/cocoa/command_dispatcher.mm
@@ -250,6 +250,10 @@ [[self bubbleParent] commandDispatchUsingKeyModifiers:sender]; } +- (BOOL)isRedispatchingKeyEvent { + return _isRedispatchingKeyEvent; +} + - (NSWindow<CommandDispatchingWindow>*)bubbleParent { NSWindow* parent = [_owner parentWindow]; if (parent && [parent hasKeyAppearance] &&
diff --git a/ui/display/mojom/BUILD.gn b/ui/display/mojom/BUILD.gn index a759490..41443e6 100644 --- a/ui/display/mojom/BUILD.gn +++ b/ui/display/mojom/BUILD.gn
@@ -21,4 +21,55 @@ "//ui/gfx/geometry/mojom", "//ui/gfx/mojom", ] + + shared_cpp_typemaps = [ + { + types = [ + { + mojom = "display.mojom.Rotation" + cpp = "::display::Display::Rotation" + }, + ] + traits_headers = [ "display_mojom_traits.h" ] + traits_public_deps = [ ":shared_mojom_traits" ] + }, + ] + + cpp_typemaps = [ + { + types = [ + { + mojom = "display.mojom.Display" + cpp = "::display::Display" + }, + { + mojom = "display.mojom.TouchSupport" + cpp = "::display::Display::TouchSupport" + }, + { + mojom = "display.mojom.AccelerometerSupport" + cpp = "::display::Display::AccelerometerSupport" + }, + ] + traits_headers = [ "display_mojom_traits.h" ] + traits_public_deps = [ ":shared_mojom_traits" ] + }, + ] + cpp_typemaps += shared_cpp_typemaps + blink_cpp_typemaps = shared_cpp_typemaps +} + +component("shared_mojom_traits") { + output_name = "display_shared_mojom_traits" + defines = [ "IS_DISPLAY_SHARED_MOJOM_TRAITS_IMPL" ] + sources = [ + "display_mojom_traits.cc", + "display_mojom_traits.h", + ] + public_deps = [ + ":mojom_shared", + "//base", + "//ui/display", + "//ui/gfx/mojom", + ] }
diff --git a/ui/display/mojom/display.typemap b/ui/display/mojom/display.typemap deleted file mode 100644 index a9f2662..0000000 --- a/ui/display/mojom/display.typemap +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//ui/display/mojom/display.mojom" -public_headers = [ "//ui/display/display.h" ] -traits_headers = [ "//ui/display/mojom/display_mojom_traits.h" ] -sources = [ - "//ui/display/mojom/display_mojom_traits.cc", -] -public_deps = [ - "//ui/display", -] -deps = [ - "//ui/gfx/geometry", - "//ui/gfx/geometry/mojom:mojom_traits", -] - -type_mappings = [ - "display.mojom.Display=::display::Display", - "display.mojom.Rotation=::display::Display::Rotation", - "display.mojom.TouchSupport=::display::Display::TouchSupport", - "display.mojom.AccelerometerSupport=::display::Display::AccelerometerSupport", -]
diff --git a/ui/display/mojom/display_mojom_traits.h b/ui/display/mojom/display_mojom_traits.h index 303908e..fbd0f30 100644 --- a/ui/display/mojom/display_mojom_traits.h +++ b/ui/display/mojom/display_mojom_traits.h
@@ -5,23 +5,25 @@ #ifndef UI_DISPLAY_MOJOM_DISPLAY_MOJOM_TRAITS_H_ #define UI_DISPLAY_MOJOM_DISPLAY_MOJOM_TRAITS_H_ +#include "base/component_export.h" #include "ui/display/display.h" -#include "ui/display/mojom/display.mojom.h" +#include "ui/display/mojom/display.mojom-shared.h" #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h" #include "ui/gfx/mojom/display_color_spaces_mojom_traits.h" namespace mojo { template <> -struct EnumTraits<display::mojom::Rotation, display::Display::Rotation> { +struct COMPONENT_EXPORT(DISPLAY_SHARED_MOJOM_TRAITS) + EnumTraits<display::mojom::Rotation, display::Display::Rotation> { static display::mojom::Rotation ToMojom(display::Display::Rotation type); static bool FromMojom(display::mojom::Rotation type, display::Display::Rotation* output); }; template <> -struct EnumTraits<display::mojom::TouchSupport, - display::Display::TouchSupport> { +struct COMPONENT_EXPORT(DISPLAY_SHARED_MOJOM_TRAITS) + EnumTraits<display::mojom::TouchSupport, display::Display::TouchSupport> { static display::mojom::TouchSupport ToMojom( display::Display::TouchSupport type); static bool FromMojom(display::mojom::TouchSupport type, @@ -29,8 +31,9 @@ }; template <> -struct EnumTraits<display::mojom::AccelerometerSupport, - display::Display::AccelerometerSupport> { +struct COMPONENT_EXPORT(DISPLAY_SHARED_MOJOM_TRAITS) + EnumTraits<display::mojom::AccelerometerSupport, + display::Display::AccelerometerSupport> { static display::mojom::AccelerometerSupport ToMojom( display::Display::AccelerometerSupport type); static bool FromMojom(display::mojom::AccelerometerSupport type, @@ -38,7 +41,8 @@ }; template <> -struct StructTraits<display::mojom::DisplayDataView, display::Display> { +struct COMPONENT_EXPORT(DISPLAY_SHARED_MOJOM_TRAITS) + StructTraits<display::mojom::DisplayDataView, display::Display> { static int64_t id(const display::Display& display) { return display.id(); } static const gfx::Rect& bounds(const display::Display& display) {
diff --git a/ui/display/mojom/display_mojom_traits_unittest.cc b/ui/display/mojom/display_mojom_traits_unittest.cc index 5b2f092..dd4e5f96 100644 --- a/ui/display/mojom/display_mojom_traits_unittest.cc +++ b/ui/display/mojom/display_mojom_traits_unittest.cc
@@ -12,6 +12,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/display/display.h" #include "ui/display/display_layout.h" +#include "ui/display/mojom/display.mojom.h" #include "ui/display/mojom/display_layout_mojom_traits.h" #include "ui/display/mojom/display_mode_mojom_traits.h" #include "ui/display/mojom/display_mojom_traits.h"
diff --git a/ui/display/mojom/display_rotation_for_blink.typemap b/ui/display/mojom/display_rotation_for_blink.typemap deleted file mode 100644 index b370d03..0000000 --- a/ui/display/mojom/display_rotation_for_blink.typemap +++ /dev/null
@@ -1,12 +0,0 @@ -# Copyright 2018 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//ui/display/mojom/display.mojom" -public_headers = [ "//ui/display/display.h" ] -traits_headers = [ "//ui/display/mojom/display_mojom_traits.h" ] -public_deps = [ - "//ui/display", - "//ui/display/mojom:mojom", -] -type_mappings = [ "display.mojom.Rotation=::display::Display::Rotation" ]
diff --git a/ui/display/mojom/typemaps.gni b/ui/display/mojom/typemaps.gni index 1cbc47b1..25abdcd 100644 --- a/ui/display/mojom/typemaps.gni +++ b/ui/display/mojom/typemaps.gni
@@ -3,7 +3,6 @@ # found in the LICENSE file. typemaps = [ - "//ui/display/mojom/display.typemap", "//ui/display/mojom/display_constants.typemap", "//ui/display/mojom/display_layout.typemap", "//ui/display/mojom/display_mode.typemap",
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.cc b/ui/events/gestures/blink/web_gesture_curve_impl.cc index a02f80b..fd3f9615 100644 --- a/ui/events/gestures/blink/web_gesture_curve_impl.cc +++ b/ui/events/gestures/blink/web_gesture_curve_impl.cc
@@ -33,7 +33,8 @@ const gfx::Vector2dF& initial_velocity, bool use_mobile_fling_curve, const gfx::PointF& position_in_screen, - const gfx::Size& viewport_size) { + const float boost_multiplier, + const gfx::Size& bounding_size) { if (device_source == blink::WebGestureDevice::kSyntheticAutoscroll) { return std::make_unique<FixedVelocityCurve>(initial_velocity, base::TimeTicks()); @@ -62,7 +63,8 @@ display::win::ScreenWin::GetPixelsPerInch(position_in_screen); #endif // define(OS_WIN) return std::make_unique<PhysicsBasedFlingCurve>( - initial_velocity, base::TimeTicks(), pixels_per_inch, viewport_size); + initial_velocity, base::TimeTicks(), pixels_per_inch, boost_multiplier, + bounding_size); } return std::make_unique<FlingCurve>(initial_velocity, base::TimeTicks()); @@ -79,11 +81,12 @@ bool on_main_thread, bool use_mobile_fling_curve, const gfx::PointF& position_in_screen, + const float boost_multiplier, const gfx::Size& viewport_size) { return std::unique_ptr<WebGestureCurve>(new WebGestureCurveImpl( CreateDefaultPlatformCurve(device_source, initial_velocity, use_mobile_fling_curve, position_in_screen, - viewport_size), + boost_multiplier, viewport_size), initial_offset, on_main_thread ? ThreadType::MAIN : ThreadType::IMPL)); }
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.h b/ui/events/gestures/blink/web_gesture_curve_impl.h index 5d97c047..a5bfc61d 100644 --- a/ui/events/gestures/blink/web_gesture_curve_impl.h +++ b/ui/events/gestures/blink/web_gesture_curve_impl.h
@@ -24,12 +24,19 @@ public: static std::unique_ptr<blink::WebGestureCurve> CreateFromDefaultPlatformCurve( blink::WebGestureDevice device_source, + // Initial velocity has boost_multiplier from fling booster already + // applied const gfx::Vector2dF& initial_velocity, const gfx::Vector2dF& initial_offset, bool on_main_thread, bool use_mobile_fling_curve, const gfx::PointF& position_in_screen, - const gfx::Size& viewport_szie); + // Multiplier for fling distance based on fling boosting. Used in physics + // based fling curve + const float boost_multiplier, + // Maximum fling distance subject to boost_multiplier and default + // bounds multiplier. Used in physics based fling curve + const gfx::Size& bounding_size); static std::unique_ptr<blink::WebGestureCurve> CreateFromUICurveForTesting( std::unique_ptr<GestureCurve> curve, const gfx::Vector2dF& initial_offset);
diff --git a/ui/events/gestures/physics_based_fling_curve.cc b/ui/events/gestures/physics_based_fling_curve.cc index a46f783..c5414cd5 100644 --- a/ui/events/gestures/physics_based_fling_curve.cc +++ b/ui/events/gestures/physics_based_fling_curve.cc
@@ -54,7 +54,7 @@ // generate fling animation curve. gfx::Vector2dF CalculateEndPoint(const gfx::Vector2dF& pixels_per_inch, const gfx::Vector2dF& velocity_pixels_per_ms, - const gfx::Size& viewport) { + const gfx::Size& bounding_size) { // deceleration is in pixels/ ms^2. gfx::Vector2dF deceleration = GetDecelerationInPixelsPerMs2(pixels_per_inch); @@ -66,18 +66,14 @@ GetOffset(velocity_pixels_per_ms.x(), deceleration.x(), duration.x()), GetOffset(velocity_pixels_per_ms.y(), deceleration.y(), duration.y())); - // Upper bound for the scroll distance for a fling - gfx::Vector2dF max_end_point = - gfx::Vector2dF(3 * viewport.width(), 3 * viewport.height()); - - if (std::abs(offset_in_screen_coord_space.x()) > max_end_point.x()) { + if (std::abs(offset_in_screen_coord_space.x()) > bounding_size.width()) { float sign = offset_in_screen_coord_space.x() > 0 ? 1 : -1; - offset_in_screen_coord_space.set_x(max_end_point.x() * sign); + offset_in_screen_coord_space.set_x(bounding_size.width() * sign); } - if (std::abs(offset_in_screen_coord_space.y()) > max_end_point.y()) { + if (std::abs(offset_in_screen_coord_space.y()) > bounding_size.height()) { float sign = offset_in_screen_coord_space.y() > 0 ? 1 : -1; - offset_in_screen_coord_space.set_y(max_end_point.y() * sign); + offset_in_screen_coord_space.set_y(bounding_size.height() * sign); } return offset_in_screen_coord_space; @@ -91,13 +87,16 @@ const gfx::Vector2dF& velocity, base::TimeTicks start_timestamp, const gfx::Vector2dF& pixels_per_inch, - const gfx::Size& viewport) + const float boost_multiplier, + const gfx::Size& bounding_size) : start_timestamp_(start_timestamp), p1_(gfx::PointF(kDefaultP1X, kDefaultP1Y)), p2_(gfx::PointF(kDefaultP2X, kDefaultP2Y)), - distance_(CalculateEndPoint(pixels_per_inch, - gfx::ScaleVector2d(velocity, 1 / 1000.0f), - viewport)), + distance_(CalculateEndPoint( + pixels_per_inch, + gfx::ScaleVector2d(velocity, 1 / 1000.0f), + ScaleToFlooredSize(bounding_size, + boost_multiplier * kDefaultBoundsMultiplier))), curve_duration_(CalculateDurationAndConfigureControlPoints(velocity)), bezier_(p1_.x(), p1_.y(), p2_.x(), p2_.y()), previous_time_delta_(base::TimeDelta()) {
diff --git a/ui/events/gestures/physics_based_fling_curve.h b/ui/events/gestures/physics_based_fling_curve.h index 38af2bf..4d4bfc7 100644 --- a/ui/events/gestures/physics_based_fling_curve.h +++ b/ui/events/gestures/physics_based_fling_curve.h
@@ -21,10 +21,15 @@ // suitable for touch screen-based flings. class EVENTS_BASE_EXPORT PhysicsBasedFlingCurve : public GestureCurve { public: - PhysicsBasedFlingCurve(const gfx::Vector2dF& velocity, - base::TimeTicks start_timestamp, - const gfx::Vector2dF& pixels_per_inch, - const gfx::Size& viewport); + PhysicsBasedFlingCurve( + const gfx::Vector2dF& velocity, + base::TimeTicks start_timestamp, + const gfx::Vector2dF& pixels_per_inch, + // Multiplier for fling distance based on fling boosting + const float boost_multiplier, + // Maximum fling distance subject to boost_multiplier and default + // bounds multiplier + const gfx::Size& bounding_size); ~PhysicsBasedFlingCurve() override; // GestureCurve implementation. @@ -35,6 +40,9 @@ float curve_duration() const { return curve_duration_; } const gfx::PointF& p1_for_testing() const { return p1_; } const gfx::PointF& p2_for_testing() const { return p2_; } + static int default_bounds_multiplier_for_testing() { + return kDefaultBoundsMultiplier; + } private: // Time when fling curve is generated. @@ -50,6 +58,12 @@ // crrev.com/c/1865928 is merged. // crbug.com/1028501 const float curve_duration_; + + // Default value used to scale the viewport when it is passed in as a + // parameter in the generation of a physics based fling curve. This value + // increases the upper bound of the scroll distance for a fling. + constexpr static int kDefaultBoundsMultiplier = 3; + const gfx::CubicBezier bezier_; base::TimeDelta previous_time_delta_; gfx::Vector2dF cumulative_scroll_;
diff --git a/ui/events/gestures/physics_based_fling_curve_unittest.cc b/ui/events/gestures/physics_based_fling_curve_unittest.cc index f954d6d0..010da57 100644 --- a/ui/events/gestures/physics_based_fling_curve_unittest.cc +++ b/ui/events/gestures/physics_based_fling_curve_unittest.cc
@@ -9,6 +9,7 @@ namespace ui { const float kDefaultPixelsPerInch = 96.f; +const float kBoostMultiplierUnboosted = 1.f; TEST(PhysicsBasedFlingCurveTest, BasicFlingTestVelocityY) { const gfx::Vector2dF fling_velocity(0, 5000); @@ -17,7 +18,8 @@ kDefaultPixelsPerInch); const gfx::Size viewport(1920, 1080); - PhysicsBasedFlingCurve curve(fling_velocity, now, pixels_per_inch, viewport); + PhysicsBasedFlingCurve curve(fling_velocity, now, pixels_per_inch, + kBoostMultiplierUnboosted, viewport); gfx::Vector2dF offset; gfx::Vector2dF velocity; @@ -66,7 +68,8 @@ kDefaultPixelsPerInch); const gfx::Size viewport(1920, 1080); - PhysicsBasedFlingCurve curve(fling_velocity, now, pixels_per_inch, viewport); + PhysicsBasedFlingCurve curve(fling_velocity, now, pixels_per_inch, + kBoostMultiplierUnboosted, viewport); gfx::Vector2dF offset; gfx::Vector2dF velocity; @@ -114,7 +117,8 @@ kDefaultPixelsPerInch); const gfx::Size viewport(1920, 1080); - PhysicsBasedFlingCurve curve(fling_velocity, now, pixels_per_inch, viewport); + PhysicsBasedFlingCurve curve(fling_velocity, now, pixels_per_inch, + kBoostMultiplierUnboosted, viewport); gfx::Vector2dF offset; gfx::Vector2dF velocity; @@ -162,7 +166,8 @@ kDefaultPixelsPerInch); const gfx::Size viewport(1920, 1080); - PhysicsBasedFlingCurve curve(velocity, now, pixels_per_inch, viewport); + PhysicsBasedFlingCurve curve(velocity, now, pixels_per_inch, + kBoostMultiplierUnboosted, viewport); EXPECT_EQ(0.20f, curve.p1_for_testing().x()); EXPECT_NEAR(curve.p1_for_testing().y(), 0.43f, 0.01f); @@ -177,7 +182,8 @@ kDefaultPixelsPerInch); const gfx::Size viewport(1920, 1080); - PhysicsBasedFlingCurve curve(velocity, now, pixels_per_inch, viewport); + PhysicsBasedFlingCurve curve(velocity, now, pixels_per_inch, + kBoostMultiplierUnboosted, viewport); EXPECT_NEAR(curve.p1_for_testing().x(), 0.19f, 0.01f); EXPECT_EQ(curve.p1_for_testing().y(), 1.0f);
diff --git a/ui/gfx/geometry/mojom/BUILD.gn b/ui/gfx/geometry/mojom/BUILD.gn index 4731f08..5bb3781 100644 --- a/ui/gfx/geometry/mojom/BUILD.gn +++ b/ui/gfx/geometry/mojom/BUILD.gn
@@ -11,6 +11,72 @@ sources = [ "geometry.mojom" ] check_includes_blink = false + + shared_cpp_typemap = { + types = [ + { + mojom = "gfx.mojom.Point" + cpp = "::gfx::Point" + }, + { + mojom = "gfx.mojom.PointF" + cpp = "::gfx::PointF" + }, + { + mojom = "gfx.mojom.Point3F" + cpp = "::gfx::Point3F" + }, + { + mojom = "gfx.mojom.Size" + cpp = "::gfx::Size" + }, + { + mojom = "gfx.mojom.SizeF" + cpp = "::gfx::SizeF" + }, + { + mojom = "gfx.mojom.Rect" + cpp = "::gfx::Rect" + }, + { + mojom = "gfx.mojom.RectF" + cpp = "::gfx::RectF" + }, + { + mojom = "gfx.mojom.Insets" + cpp = "::gfx::Insets" + }, + { + mojom = "gfx.mojom.InsetsF" + cpp = "::gfx::InsetsF" + }, + { + mojom = "gfx.mojom.Quaternion" + cpp = "::gfx::Quaternion" + }, + { + mojom = "gfx.mojom.Vector2d" + cpp = "::gfx::Vector2d" + }, + { + mojom = "gfx.mojom.Vector2dF" + cpp = "::gfx::Vector2dF" + }, + { + mojom = "gfx.mojom.Vector3dF" + cpp = "::gfx::Vector3dF" + }, + { + mojom = "gfx.mojom.ScrollOffset" + cpp = "::gfx::ScrollOffset" + }, + ] + + traits_headers = [ "geometry_mojom_traits.h" ] + traits_public_deps = [ ":mojom_traits" ] + } + cpp_typemaps = [ shared_cpp_typemap ] + blink_cpp_typemaps = [ shared_cpp_typemap ] } mojom("test_interfaces") { @@ -37,7 +103,7 @@ source_set("mojom_traits") { sources = [ "geometry_mojom_traits.h" ] public_deps = [ - ":mojom_shared_cpp_sources", + ":mojom_shared", "//ui/gfx/geometry", ] }
diff --git a/ui/gfx/geometry/mojom/geometry.typemap b/ui/gfx/geometry/mojom/geometry.typemap deleted file mode 100644 index 7897c92..0000000 --- a/ui/gfx/geometry/mojom/geometry.typemap +++ /dev/null
@@ -1,40 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//ui/gfx/geometry/mojom/geometry.mojom" -public_headers = [ - "//ui/gfx/geometry/point.h", - "//ui/gfx/geometry/point_f.h", - "//ui/gfx/geometry/point3_f.h", - "//ui/gfx/geometry/size.h", - "//ui/gfx/geometry/rect.h", - "//ui/gfx/geometry/rect_f.h", - "//ui/gfx/geometry/safe_integer_conversions.h", - "//ui/gfx/geometry/scroll_offset.h", - "//ui/gfx/geometry/insets.h", - "//ui/gfx/geometry/quaternion.h", - "//ui/gfx/geometry/vector2d.h", - "//ui/gfx/geometry/vector2d_f.h", - "//ui/gfx/geometry/vector3d_f.h", -] -traits_headers = [ "//ui/gfx/geometry/mojom/geometry_mojom_traits.h" ] -public_deps = [ - "//ui/gfx/geometry/mojom:mojom_traits", -] -type_mappings = [ - "gfx.mojom.Point=::gfx::Point", - "gfx.mojom.PointF=::gfx::PointF", - "gfx.mojom.Point3F=::gfx::Point3F", - "gfx.mojom.Size=::gfx::Size", - "gfx.mojom.SizeF=::gfx::SizeF", - "gfx.mojom.Rect=::gfx::Rect", - "gfx.mojom.RectF=::gfx::RectF", - "gfx.mojom.Insets=::gfx::Insets", - "gfx.mojom.InsetsF=::gfx::InsetsF", - "gfx.mojom.Quaternion=::gfx::Quaternion", - "gfx.mojom.Vector2d=::gfx::Vector2d", - "gfx.mojom.Vector2dF=::gfx::Vector2dF", - "gfx.mojom.Vector3dF=::gfx::Vector3dF", - "gfx.mojom.ScrollOffset=::gfx::ScrollOffset", -]
diff --git a/ui/gfx/mojom/BUILD.gn b/ui/gfx/mojom/BUILD.gn index f6fffd3..cd30b12 100644 --- a/ui/gfx/mojom/BUILD.gn +++ b/ui/gfx/mojom/BUILD.gn
@@ -29,43 +29,76 @@ "//ui/gfx/geometry/mojom", ] - buffer_types_shared_cpp_typemap = { - types = [ - { - mojom = "gfx.mojom.BufferFormat" - cpp = "::gfx::BufferFormat" - }, - { - mojom = "gfx.mojom.BufferUsage" - cpp = "::gfx::BufferUsage" - }, - { - mojom = "gfx.mojom.BufferUsageAndFormat" - cpp = "::gfx::BufferUsageAndFormat" - }, - { - mojom = "gfx.mojom.GpuMemoryBufferHandle" - cpp = "::gfx::GpuMemoryBufferHandle" - move_only = true - nullable_is_same_type = true - }, - { - mojom = "gfx.mojom.GpuMemoryBufferId" - cpp = "::gfx::GpuMemoryBufferId" - copyable_pass_by_value = true - }, - { - mojom = "gfx.mojom.GpuMemoryBufferType" - cpp = "::gfx::GpuMemoryBufferType" - }, - ] + shared_cpp_typemaps = [ + { + types = [ + { + mojom = "gfx.mojom.BufferFormat" + cpp = "::gfx::BufferFormat" + }, + { + mojom = "gfx.mojom.BufferUsage" + cpp = "::gfx::BufferUsage" + }, + { + mojom = "gfx.mojom.BufferUsageAndFormat" + cpp = "::gfx::BufferUsageAndFormat" + }, + { + mojom = "gfx.mojom.GpuMemoryBufferHandle" + cpp = "::gfx::GpuMemoryBufferHandle" + move_only = true + nullable_is_same_type = true + }, + { + mojom = "gfx.mojom.GpuMemoryBufferId" + cpp = "::gfx::GpuMemoryBufferId" + copyable_pass_by_value = true + }, + { + mojom = "gfx.mojom.GpuMemoryBufferType" + cpp = "::gfx::GpuMemoryBufferType" + }, + ] - traits_headers = [ "buffer_types_mojom_traits.h" ] - traits_public_deps = [ ":shared_mojom_traits" ] - } + traits_headers = [ "buffer_types_mojom_traits.h" ] + traits_public_deps = [ ":shared_mojom_traits" ] + }, + { + types = [ + { + mojom = "gfx.mojom.ColorSpace" + cpp = "::gfx::ColorSpace" + }, + ] + traits_headers = [ "color_space_mojom_traits.h" ] + traits_public_deps = [ ":color_space_mojom_support" ] + }, + { + types = [ + { + mojom = "gfx.mojom.GpuFenceHandle" + cpp = "::gfx::GpuFenceHandle" + }, + ] + traits_headers = [ "gpu_fence_handle_mojom_traits.h" ] + traits_public_deps = [ ":shared_mojom_traits" ] + }, + { + types = [ + { + mojom = "gfx.mojom.Transform" + cpp = "::gfx::Transform" + }, + ] + traits_headers = [ "transform_mojom_traits.h" ] + traits_public_deps = [ "//ui/gfx" ] + }, + ] - cpp_typemaps = [ buffer_types_shared_cpp_typemap ] - blink_cpp_typemaps = [ buffer_types_shared_cpp_typemap ] + cpp_typemaps = [] + cpp_typemaps = shared_cpp_typemaps + blink_cpp_typemaps = shared_cpp_typemaps } mojom("native_handle_types") { @@ -136,6 +169,8 @@ sources = [ "buffer_types_mojom_traits.cc", "buffer_types_mojom_traits.h", + "gpu_fence_handle_mojom_traits.cc", + "gpu_fence_handle_mojom_traits.h", ] public_deps = [ ":mojom_shared",
diff --git a/ui/gfx/mojom/color_space.typemap b/ui/gfx/mojom/color_space.typemap deleted file mode 100644 index 79ec50a..0000000 --- a/ui/gfx/mojom/color_space.typemap +++ /dev/null
@@ -1,9 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//ui/gfx/mojom/color_space.mojom" -public_headers = [ "//ui/gfx/color_space.h" ] -traits_headers = [ "//ui/gfx/mojom/color_space_mojom_traits.h" ] -public_deps = [ "//ui/gfx/mojom:color_space_mojom_support" ] -type_mappings = [ "gfx.mojom.ColorSpace=::gfx::ColorSpace" ]
diff --git a/ui/gfx/mojom/gpu_fence_handle.typemap b/ui/gfx/mojom/gpu_fence_handle.typemap deleted file mode 100644 index ef97ab51..0000000 --- a/ui/gfx/mojom/gpu_fence_handle.typemap +++ /dev/null
@@ -1,14 +0,0 @@ -# Copyright 2017 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//ui/gfx/mojom/gpu_fence_handle.mojom" -public_headers = [ "//ui/gfx/gpu_fence_handle.h" ] -traits_headers = [ "//ui/gfx/mojom/gpu_fence_handle_mojom_traits.h" ] -sources = [ - "//ui/gfx/mojom/gpu_fence_handle_mojom_traits.cc", -] -deps = [ - "//ui/gfx", -] -type_mappings = [ "gfx.mojom.GpuFenceHandle=::gfx::GpuFenceHandle" ]
diff --git a/ui/gfx/mojom/gpu_fence_handle_for_blink.typemap b/ui/gfx/mojom/gpu_fence_handle_for_blink.typemap deleted file mode 100644 index c6540e8..0000000 --- a/ui/gfx/mojom/gpu_fence_handle_for_blink.typemap +++ /dev/null
@@ -1,12 +0,0 @@ -# Copyright 2017 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//ui/gfx/mojom/gpu_fence_handle.mojom" -public_headers = [ "//ui/gfx/gpu_fence_handle.h" ] -traits_headers = [ "//ui/gfx/mojom/gpu_fence_handle_mojom_traits.h" ] -public_deps = [ - "//mojo/public/cpp/bindings", - "//ui/gfx/mojom", -] -type_mappings = [ "gfx.mojom.GpuFenceHandle=::gfx::GpuFenceHandle" ]
diff --git a/ui/gfx/mojom/gpu_fence_handle_mojom_traits.h b/ui/gfx/mojom/gpu_fence_handle_mojom_traits.h index 74ef6032..f688b2cb 100644 --- a/ui/gfx/mojom/gpu_fence_handle_mojom_traits.h +++ b/ui/gfx/mojom/gpu_fence_handle_mojom_traits.h
@@ -5,13 +5,15 @@ #ifndef UI_GFX_MOJOM_GPU_FENCE_HANDLE_MOJOM_TRAITS_H_ #define UI_GFX_MOJOM_GPU_FENCE_HANDLE_MOJOM_TRAITS_H_ +#include "base/component_export.h" #include "ui/gfx/gpu_fence_handle.h" -#include "ui/gfx/mojom/gpu_fence_handle.mojom.h" +#include "ui/gfx/mojom/gpu_fence_handle.mojom-shared.h" namespace mojo { template <> -struct EnumTraits<gfx::mojom::GpuFenceHandleType, gfx::GpuFenceHandleType> { +struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS) + EnumTraits<gfx::mojom::GpuFenceHandleType, gfx::GpuFenceHandleType> { static gfx::mojom::GpuFenceHandleType ToMojom(gfx::GpuFenceHandleType type) { switch (type) { case gfx::GpuFenceHandleType::kEmpty: @@ -38,7 +40,8 @@ }; template <> -struct StructTraits<gfx::mojom::GpuFenceHandleDataView, gfx::GpuFenceHandle> { +struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS) + StructTraits<gfx::mojom::GpuFenceHandleDataView, gfx::GpuFenceHandle> { static gfx::GpuFenceHandleType type(const gfx::GpuFenceHandle& handle) { return handle.type; }
diff --git a/ui/gfx/mojom/transform.typemap b/ui/gfx/mojom/transform.typemap deleted file mode 100644 index ff2bf8a..0000000 --- a/ui/gfx/mojom/transform.typemap +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//ui/gfx/mojom/transform.mojom" -public_headers = [ "//ui/gfx/transform.h" ] -traits_headers = [ "//ui/gfx/mojom/transform_mojom_traits.h" ] -type_mappings = [ "gfx.mojom.Transform=::gfx::Transform" ]
diff --git a/ui/gfx/typemaps.gni b/ui/gfx/typemaps.gni index 4646e0cb..7b7f550 100644 --- a/ui/gfx/typemaps.gni +++ b/ui/gfx/typemaps.gni
@@ -3,20 +3,16 @@ # found in the LICENSE file. typemaps = [ - "//ui/gfx/geometry/mojom/geometry.typemap", "//ui/gfx/image/mojom/image.typemap", "//ui/gfx/mojom/accelerated_widget.typemap", "//ui/gfx/mojom/ca_layer_params.typemap", - "//ui/gfx/mojom/color_space.typemap", "//ui/gfx/mojom/display_color_spaces.typemap", "//ui/gfx/mojom/font_render_params.typemap", - "//ui/gfx/mojom/gpu_fence_handle.typemap", "//ui/gfx/mojom/overlay_transform.typemap", "//ui/gfx/mojom/presentation_feedback.typemap", "//ui/gfx/mojom/rrect_f.typemap", "//ui/gfx/mojom/selection_bound.typemap", "//ui/gfx/mojom/swap_result.typemap", "//ui/gfx/mojom/swap_timings.typemap", - "//ui/gfx/mojom/transform.typemap", "//ui/gfx/range/mojom/range.typemap", ]
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc index 01da559..a04aa78e 100644 --- a/ui/views/controls/tree/tree_view.cc +++ b/ui/views/controls/tree/tree_view.cc
@@ -895,7 +895,7 @@ } else { // !IsRoot(node)) && node->parent() != nullptr. - if (node->parent()->is_expanded()) { + if (IsExpanded(node->parent()->model_node())) { int depth = 0; row = GetRowForInternalNode(node, &depth); if (depth >= 0) {
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc index b1369d7..8e8efbc3 100644 --- a/ui/views/widget/widget_interactive_uitest.cc +++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -307,10 +307,10 @@ // Create widget 1 and expect the active window to be its window. View* focusable_view1 = new View; focusable_view1->SetFocusBehavior(View::FocusBehavior::ALWAYS); - Widget* widget1 = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget1(CreateTopLevelNativeWidget()); widget1->GetContentsView()->AddChildView(focusable_view1); widget1->Show(); - aura::Window* root_window1 = GetRootWindow(widget1); + aura::Window* root_window1 = GetRootWindow(widget1.get()); focusable_view1->RequestFocus(); EXPECT_TRUE(root_window1 != nullptr); @@ -321,12 +321,12 @@ // Create widget 2 and expect the active window to be its window. View* focusable_view2 = new View; - Widget* widget2 = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget2(CreateTopLevelNativeWidget()); widget1->GetContentsView()->AddChildView(focusable_view2); widget2->Show(); - aura::Window* root_window2 = GetRootWindow(widget2); + aura::Window* root_window2 = GetRootWindow(widget2.get()); focusable_view2->RequestFocus(); - ActivatePlatformWindow(widget2); + ActivatePlatformWindow(widget2.get()); wm::ActivationClient* activation_client2 = wm::GetActivationClient(root_window2); @@ -338,18 +338,15 @@ // Now set focus back to widget 1 and expect the active window to be its // window. focusable_view1->RequestFocus(); - ActivatePlatformWindow(widget1); + ActivatePlatformWindow(widget1.get()); EXPECT_EQ(activation_client2->GetActiveWindow(), reinterpret_cast<aura::Window*>(NULL)); EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView()); - - widget2->CloseNow(); - widget1->CloseNow(); } // Verifies bubbles result in a focus lost when shown. TEST_F(DesktopWidgetTestInteractive, FocusChangesOnBubble) { - Widget* widget = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); View* focusable_view = widget->GetContentsView()->AddChildView(std::make_unique<View>()); focusable_view->SetFocusBehavior(View::FocusBehavior::ALWAYS); @@ -376,8 +373,6 @@ // Closing the bubble should result in focus going back to the contents view. EXPECT_TRUE(focusable_view->HasFocus()); - - widget->CloseNow(); } class TouchEventHandler : public ui::EventHandler { @@ -433,210 +428,23 @@ View* focusable_view = new View; focusable_view->SetFocusBehavior(View::FocusBehavior::ALWAYS); - Widget* widget = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); widget->GetContentsView()->AddChildView(focusable_view); widget->Show(); { - TouchEventHandler touch_event_handler(widget); + TouchEventHandler touch_event_handler(widget.get()); ASSERT_TRUE(ui_controls::SendTouchEvents(ui_controls::PRESS, 1, 100, 100)); touch_event_handler.WaitForEvents(); } - - widget->CloseNow(); } #endif // defined(OS_WIN) -TEST_F(WidgetTestInteractive, CaptureAutoReset) { - Widget* toplevel = CreateTopLevelFramelessPlatformWidget(); - View* container = new View; - toplevel->SetContentsView(container); - - EXPECT_FALSE(toplevel->HasCapture()); - toplevel->SetCapture(nullptr); - EXPECT_TRUE(toplevel->HasCapture()); - - // By default, mouse release removes capture. - gfx::Point click_location(45, 15); - ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location, - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&release); - EXPECT_FALSE(toplevel->HasCapture()); - - // Now a mouse release shouldn't remove capture. - toplevel->set_auto_release_capture(false); - toplevel->SetCapture(nullptr); - EXPECT_TRUE(toplevel->HasCapture()); - toplevel->OnMouseEvent(&release); - EXPECT_TRUE(toplevel->HasCapture()); - toplevel->ReleaseCapture(); - EXPECT_FALSE(toplevel->HasCapture()); - - toplevel->Close(); - RunPendingMessages(); -} - -TEST_F(WidgetTestInteractive, ResetCaptureOnGestureEnd) { - Widget* toplevel = CreateTopLevelFramelessPlatformWidget(); - View* container = new View; - toplevel->SetContentsView(container); - - View* gesture = new GestureCaptureView; - gesture->SetBounds(0, 0, 30, 30); - container->AddChildView(gesture); - - MouseView* mouse = new MouseView; - mouse->SetBounds(30, 0, 30, 30); - container->AddChildView(mouse); - - toplevel->SetSize(gfx::Size(100, 100)); - toplevel->Show(); - - // Start a gesture on |gesture|. - ui::GestureEvent tap_down(15, 15, 0, base::TimeTicks(), - ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN)); - ui::GestureEvent end(15, 15, 0, base::TimeTicks(), - ui::GestureEventDetails(ui::ET_GESTURE_END)); - toplevel->OnGestureEvent(&tap_down); - - // Now try to click on |mouse|. Since |gesture| will have capture, |mouse| - // will not receive the event. - gfx::Point click_location(45, 15); - - ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location, - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON); - ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location, - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON); - - EXPECT_TRUE(toplevel->HasCapture()); - - toplevel->OnMouseEvent(&press); - toplevel->OnMouseEvent(&release); - EXPECT_EQ(0, mouse->pressed()); - - EXPECT_FALSE(toplevel->HasCapture()); - - // The end of the gesture should release the capture, and pressing on |mouse| - // should now reach |mouse|. - toplevel->OnGestureEvent(&end); - toplevel->OnMouseEvent(&press); - toplevel->OnMouseEvent(&release); - EXPECT_EQ(1, mouse->pressed()); - - toplevel->Close(); - RunPendingMessages(); -} - -// Checks that if a mouse-press triggers a capture on a different widget (which -// consumes the mouse-release event), then the target of the press does not have -// capture. -TEST_F(WidgetTestInteractive, DisableCaptureWidgetFromMousePress) { - // The test creates two widgets: |first| and |second|. - // The View in |first| makes |second| visible, sets capture on it, and starts - // a nested loop (like a menu does). The View in |second| terminates the - // nested loop and closes the widget. - // The test sends a mouse-press event to |first|, and posts a task to send a - // release event to |second|, to make sure that the release event is - // dispatched after the nested loop starts. - - Widget* first = CreateTopLevelFramelessPlatformWidget(); - Widget* second = CreateTopLevelFramelessPlatformWidget(); - - NestedLoopCaptureView* container = new NestedLoopCaptureView(second); - first->SetContentsView(container); - - second->SetContentsView(new ExitLoopOnRelease(container->GetQuitClosure())); - - first->SetSize(gfx::Size(100, 100)); - first->Show(); - - gfx::Point location(20, 20); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - &Widget::OnMouseEvent, base::Unretained(second), - base::Owned(new ui::MouseEvent( - ui::ET_MOUSE_RELEASED, location, location, ui::EventTimeForNow(), - ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)))); - ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location, - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON); - first->OnMouseEvent(&press); - EXPECT_FALSE(first->HasCapture()); - first->Close(); - RunPendingMessages(); -} - -// Tests some grab/ungrab events. -// TODO(estade): can this be enabled now that this is an interactive ui test? -TEST_F(WidgetTestInteractive, DISABLED_GrabUngrab) { - Widget* toplevel = CreateTopLevelPlatformWidget(); - Widget* child1 = CreateChildNativeWidgetWithParent(toplevel); - Widget* child2 = CreateChildNativeWidgetWithParent(toplevel); - - toplevel->SetBounds(gfx::Rect(0, 0, 500, 500)); - - child1->SetBounds(gfx::Rect(10, 10, 300, 300)); - View* view = new MouseView(); - view->SetBounds(0, 0, 300, 300); - child1->GetRootView()->AddChildView(view); - - child2->SetBounds(gfx::Rect(200, 10, 200, 200)); - view = new MouseView(); - view->SetBounds(0, 0, 200, 200); - child2->GetRootView()->AddChildView(view); - - toplevel->Show(); - RunPendingMessages(); - - // Click on child1 - gfx::Point p1(45, 45); - ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1, ui::EventTimeForNow(), - ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&pressed); - - EXPECT_TRUE(toplevel->HasCapture()); - EXPECT_TRUE(child1->HasCapture()); - EXPECT_FALSE(child2->HasCapture()); - - ui::MouseEvent released(ui::ET_MOUSE_RELEASED, p1, p1, ui::EventTimeForNow(), - ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&released); - - EXPECT_FALSE(toplevel->HasCapture()); - EXPECT_FALSE(child1->HasCapture()); - EXPECT_FALSE(child2->HasCapture()); - - RunPendingMessages(); - - // Click on child2 - gfx::Point p2(315, 45); - ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED, p2, p2, ui::EventTimeForNow(), - ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&pressed2); - EXPECT_TRUE(pressed2.handled()); - EXPECT_TRUE(toplevel->HasCapture()); - EXPECT_TRUE(child2->HasCapture()); - EXPECT_FALSE(child1->HasCapture()); - - ui::MouseEvent released2(ui::ET_MOUSE_RELEASED, p2, p2, ui::EventTimeForNow(), - ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&released2); - EXPECT_FALSE(toplevel->HasCapture()); - EXPECT_FALSE(child1->HasCapture()); - EXPECT_FALSE(child2->HasCapture()); - - toplevel->CloseNow(); -} - // Tests mouse move outside of the window into the "resize controller" and back // will still generate an OnMouseEntered and OnMouseExited event.. TEST_F(WidgetTestInteractive, CheckResizeControllerEvents) { - Widget* toplevel = CreateTopLevelFramelessPlatformWidget(); + WidgetAutoclosePtr toplevel(CreateTopLevelFramelessPlatformWidget()); toplevel->SetBounds(gfx::Rect(0, 0, 100, 100)); @@ -678,20 +486,16 @@ toplevel->OnMouseEvent(&moved_over); EXPECT_EQ(1, view->EnteredCalls()); EXPECT_EQ(0, view->ExitedCalls()); - - RunPendingMessages(); - - toplevel->CloseNow(); } // Test view focus restoration when a widget is deactivated and re-activated. TEST_F(WidgetTestInteractive, ViewFocusOnWidgetActivationChanges) { - Widget* widget1 = CreateTopLevelPlatformWidget(); + WidgetAutoclosePtr widget1(CreateTopLevelPlatformWidget()); View* view1 = new View; view1->SetFocusBehavior(View::FocusBehavior::ALWAYS); widget1->GetContentsView()->AddChildView(view1); - Widget* widget2 = CreateTopLevelPlatformWidget(); + WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget()); View* view2a = new View; View* view2b = new View; view2a->SetFocusBehavior(View::FocusBehavior::ALWAYS); @@ -699,12 +503,12 @@ widget2->GetContentsView()->AddChildView(view2a); widget2->GetContentsView()->AddChildView(view2b); - ShowSync(widget1); + ShowSync(widget1.get()); EXPECT_TRUE(widget1->IsActive()); view1->RequestFocus(); EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView()); - ShowSync(widget2); + ShowSync(widget2.get()); EXPECT_TRUE(widget2->IsActive()); EXPECT_FALSE(widget1->IsActive()); EXPECT_EQ(nullptr, widget1->GetFocusManager()->GetFocusedView()); @@ -713,20 +517,17 @@ view2b->RequestFocus(); EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView()); - ActivateSync(widget1); + ActivateSync(widget1.get()); EXPECT_TRUE(widget1->IsActive()); EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView()); EXPECT_FALSE(widget2->IsActive()); EXPECT_EQ(nullptr, widget2->GetFocusManager()->GetFocusedView()); - ActivateSync(widget2); + ActivateSync(widget2.get()); EXPECT_TRUE(widget2->IsActive()); EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView()); EXPECT_FALSE(widget1->IsActive()); EXPECT_EQ(nullptr, widget1->GetFocusManager()->GetFocusedView()); - - widget1->CloseNow(); - widget2->CloseNow(); } // Test z-order of child widgets relative to their parent. @@ -801,7 +602,7 @@ // Test view focus retention when a widget's HWND is disabled and re-enabled. TEST_F(WidgetTestInteractive, ViewFocusOnHWNDEnabledChanges) { - Widget* widget = CreateTopLevelFramelessPlatformWidget(); + WidgetAutoclosePtr widget(CreateTopLevelFramelessPlatformWidget()); widget->SetContentsView(new View); for (size_t i = 0; i < 2; ++i) { auto child = std::make_unique<View>(); @@ -811,7 +612,7 @@ widget->Show(); widget->GetNativeWindow()->GetHost()->Show(); - const HWND hwnd = HWNDForWidget(widget); + const HWND hwnd = HWNDForWidget(widget.get()); EXPECT_TRUE(::IsWindow(hwnd)); EXPECT_TRUE(::IsWindowEnabled(hwnd)); EXPECT_EQ(hwnd, ::GetActiveWindow()); @@ -836,8 +637,6 @@ EXPECT_TRUE(widget->IsActive()); EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView()); } - - widget->CloseNow(); } // This class subclasses the Widget class to listen for activation change @@ -1089,61 +888,6 @@ } #endif -// Disabled on Mac. Desktop Mac doesn't have system modal windows since Carbon -// was deprecated. It does have application modal windows, but only Ash requests -// those. -#if defined(OS_MACOSX) -#define MAYBE_SystemModalWindowReleasesCapture \ - DISABLED_SystemModalWindowReleasesCapture -#elif defined(OS_CHROMEOS) -// Investigate enabling for Chrome OS. It probably requires help from the window -// service. -#define MAYBE_SystemModalWindowReleasesCapture \ - DISABLED_SystemModalWindowReleasesCapture -#else -#define MAYBE_SystemModalWindowReleasesCapture SystemModalWindowReleasesCapture -#endif - -// Test that when opening a system-modal window, capture is released. -TEST_F(DesktopWidgetTestInteractive, MAYBE_SystemModalWindowReleasesCapture) { - TestWidgetFocusChangeListener focus_listener; - WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener); - - // Create a top level widget. - Widget top_level_widget; - Widget::InitParams init_params = - CreateParams(Widget::InitParams::TYPE_WINDOW); - init_params.show_state = ui::SHOW_STATE_NORMAL; - gfx::Rect initial_bounds(0, 0, 500, 500); - init_params.bounds = initial_bounds; - init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - top_level_widget.Init(std::move(init_params)); - ShowSync(&top_level_widget); - - ASSERT_FALSE(focus_listener.focus_changes().empty()); - EXPECT_EQ(top_level_widget.GetNativeView(), - focus_listener.focus_changes().back()); - - EXPECT_FALSE(top_level_widget.HasCapture()); - top_level_widget.SetCapture(nullptr); - EXPECT_TRUE(top_level_widget.HasCapture()); - - // Create a modal dialog. - ModalDialogDelegate* dialog_delegate = - new ModalDialogDelegate(ui::MODAL_TYPE_SYSTEM); - - Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget( - dialog_delegate, nullptr, top_level_widget.GetNativeView()); - modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200)); - ShowSync(modal_dialog_widget); - - EXPECT_FALSE(top_level_widget.HasCapture()); - - modal_dialog_widget->CloseNow(); - top_level_widget.CloseNow(); - WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener); -} - TEST_F(DesktopWidgetTestInteractive, CanActivateFlagIsHonored) { Widget widget; Widget::InitParams init_params = @@ -1171,7 +915,7 @@ // Test that touch selection quick menu is not activated when opened. TEST_F(DesktopWidgetTestInteractive, MAYBE_TouchSelectionQuickMenuIsNotActivated) { - Widget* widget = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); widget->SetBounds(gfx::Rect(0, 0, 200, 200)); Textfield* textfield = new Textfield; @@ -1186,7 +930,7 @@ RunPendingMessages(); - ui::test::EventGenerator generator(GetRootWindow(widget)); + ui::test::EventGenerator generator(GetRootWindow(widget.get())); generator.GestureTapAt(textfield->GetBoundsInScreen().origin() + gfx::Vector2d(10, 10)); static_cast<TouchSelectionControllerImpl*>( @@ -1196,7 +940,6 @@ EXPECT_TRUE(textfield->HasFocus()); EXPECT_TRUE(widget->IsActive()); EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()); - widget->CloseNow(); } #endif // defined(USE_AURA) @@ -1255,90 +998,76 @@ } // namespace test TEST_F(WidgetTestInteractive, ShowCreatesActiveWindow) { - Widget* widget = CreateTopLevelPlatformWidget(); + WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); - ShowSync(widget); - EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL); - - widget->CloseNow(); + ShowSync(widget.get()); + EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL); } TEST_F(WidgetTestInteractive, ShowInactive) { WidgetTest::WaitForSystemAppActivation(); - Widget* widget = CreateTopLevelPlatformWidget(); + WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); - ShowInactiveSync(widget); - EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_INACTIVE); - - widget->CloseNow(); + ShowInactiveSync(widget.get()); + EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_INACTIVE); } TEST_F(WidgetTestInteractive, InactiveBeforeShow) { - Widget* widget = CreateTopLevelPlatformWidget(); + WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); EXPECT_FALSE(widget->IsActive()); EXPECT_FALSE(widget->IsVisible()); - ShowSync(widget); + ShowSync(widget.get()); EXPECT_TRUE(widget->IsActive()); EXPECT_TRUE(widget->IsVisible()); - - widget->CloseNow(); } TEST_F(WidgetTestInteractive, ShowInactiveAfterShow) { // Create 2 widgets to ensure window layering does not change. - Widget* widget = CreateTopLevelPlatformWidget(); - Widget* widget2 = CreateTopLevelPlatformWidget(); + WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); + WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget()); - ShowSync(widget2); + ShowSync(widget2.get()); EXPECT_FALSE(widget->IsActive()); EXPECT_TRUE(widget2->IsVisible()); EXPECT_TRUE(widget2->IsActive()); - ShowSync(widget); + ShowSync(widget.get()); EXPECT_TRUE(widget->IsActive()); EXPECT_FALSE(widget2->IsActive()); - ShowInactiveSync(widget); + ShowInactiveSync(widget.get()); EXPECT_TRUE(widget->IsActive()); EXPECT_FALSE(widget2->IsActive()); - EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL); - - widget2->CloseNow(); - widget->CloseNow(); + EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL); } TEST_F(WidgetTestInteractive, ShowAfterShowInactive) { - Widget* widget = CreateTopLevelPlatformWidget(); + WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); widget->SetBounds(gfx::Rect(100, 100, 100, 100)); - ShowInactiveSync(widget); - ShowSync(widget); - EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL); - - widget->CloseNow(); + ShowInactiveSync(widget.get()); + ShowSync(widget.get()); + EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL); } #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MACOSX) TEST_F(WidgetTestInteractive, InactiveWidgetDoesNotGrabActivation) { - Widget* widget = CreateTopLevelPlatformWidget(); - ShowSync(widget); - EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL); + WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); + ShowSync(widget.get()); + EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL); - Widget widget2; + WidgetAutoclosePtr widget2(new Widget()); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - widget2.Init(std::move(params)); - widget2.Show(); + widget2->Init(std::move(params)); + widget2->Show(); RunPendingMessagesForActiveStatusChange(); - EXPECT_EQ(GetWidgetShowState(&widget2), ui::SHOW_STATE_INACTIVE); - EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL); - - widget->CloseNow(); - widget2.CloseNow(); + EXPECT_EQ(GetWidgetShowState(widget2.get()), ui::SHOW_STATE_INACTIVE); + EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL); } #endif // BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MACOSX) @@ -1354,37 +1083,33 @@ // Test that window state is not changed after getting out of full screen. TEST_F(WidgetTestInteractive, MAYBE_ExitFullscreenRestoreState) { - Widget* toplevel = CreateTopLevelPlatformWidget(); + WidgetAutoclosePtr toplevel(CreateTopLevelPlatformWidget()); toplevel->Show(); RunPendingMessages(); // This should be a normal state window. - EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel)); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel.get())); toplevel->SetFullscreen(true); - EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel)); + EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel.get())); toplevel->SetFullscreen(false); - EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel)); + EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel.get())); // And it should still be in normal state after getting out of full screen. - EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel)); + EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel.get())); // Now, make it maximized. toplevel->Maximize(); - EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel)); + EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel.get())); toplevel->SetFullscreen(true); - EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel)); + EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel.get())); toplevel->SetFullscreen(false); - EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel)); + EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel.get())); // And it stays maximized after getting out of full screen. - EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel)); - - // Clean up. - toplevel->Close(); - RunPendingMessages(); + EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel.get())); } // Testing initial focus is assigned properly for normal top-level widgets, @@ -1414,23 +1139,21 @@ } TEST_F(DesktopWidgetTestInteractive, RestoreAfterMinimize) { - Widget* widget = CreateTopLevelNativeWidget(); - ShowSync(widget); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); + ShowSync(widget.get()); ASSERT_FALSE(widget->IsMinimized()); PropertyWaiter minimize_waiter( - base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget)), + base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())), true); widget->Minimize(); EXPECT_TRUE(minimize_waiter.Wait()); PropertyWaiter restore_waiter( - base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget)), + base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())), false); widget->Restore(); EXPECT_TRUE(restore_waiter.Wait()); - - widget->CloseNow(); } #if defined(OS_WIN) @@ -1439,14 +1162,14 @@ // Tests that root window visibility toggles correctly when the desktop widget // is minimized and maximized on Windows, and the Widget remains visible. TEST_F(DesktopWidgetTestInteractive, RestoreAndMinimizeVisibility) { - Widget* widget = CreateTopLevelNativeWidget(); - aura::Window* root_window = GetRootWindow(widget); - ShowSync(widget); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); + aura::Window* root_window = GetRootWindow(widget.get()); + ShowSync(widget.get()); ASSERT_FALSE(widget->IsMinimized()); EXPECT_TRUE(root_window->IsVisible()); PropertyWaiter minimize_widget_waiter( - base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget)), + base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())), true); widget->Minimize(); EXPECT_TRUE(minimize_widget_waiter.Wait()); @@ -1454,22 +1177,21 @@ EXPECT_FALSE(root_window->IsVisible()); PropertyWaiter restore_widget_waiter( - base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget)), + base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())), false); widget->Restore(); EXPECT_TRUE(restore_widget_waiter.Wait()); EXPECT_TRUE(widget->IsVisible()); EXPECT_TRUE(root_window->IsVisible()); - widget->CloseNow(); } // Test that focus is restored to the widget after a minimized window // is activated. TEST_F(DesktopWidgetTestInteractive, MinimizeAndActivateFocus) { - Widget* widget = CreateTopLevelNativeWidget(); - aura::Window* root_window = GetRootWindow(widget); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); + aura::Window* root_window = GetRootWindow(widget.get()); auto* widget_window = widget->GetNativeWindow(); - ShowSync(widget); + ShowSync(widget.get()); ASSERT_FALSE(widget->IsMinimized()); EXPECT_TRUE(root_window->IsVisible()); widget_window->Focus(); @@ -1479,7 +1201,7 @@ EXPECT_TRUE(widget->GetContentsView()->HasFocus()); PropertyWaiter minimize_widget_waiter( - base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget)), + base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())), true); widget->Minimize(); EXPECT_TRUE(minimize_widget_waiter.Wait()); @@ -1487,7 +1209,7 @@ EXPECT_FALSE(root_window->IsVisible()); PropertyWaiter restore_widget_waiter( - base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget)), + base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())), false); widget->Activate(); EXPECT_TRUE(widget->GetContentsView()->HasFocus()); @@ -1495,7 +1217,6 @@ EXPECT_TRUE(widget->IsVisible()); EXPECT_TRUE(root_window->IsVisible()); EXPECT_TRUE(widget_window->CanFocus()); - widget->CloseNow(); } #endif // defined(OS_WIN) @@ -1504,8 +1225,8 @@ // Tests that minimizing a widget causes the gesture_handler // to be cleared when the widget is minimized. TEST_F(DesktopWidgetTestInteractive, EventHandlersClearedOnWidgetMinimize) { - Widget* widget = CreateTopLevelNativeWidget(); - ShowSync(widget); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); + ShowSync(widget.get()); ASSERT_FALSE(widget->IsMinimized()); View mouse_handler_view; internal::RootView* root_view = @@ -1517,8 +1238,6 @@ widget->Minimize(); EXPECT_FALSE(GetGestureHandler(root_view)); - - widget->CloseNow(); } #endif @@ -1529,16 +1248,16 @@ TEST_F(DesktopWidgetTestInteractive, DesktopNativeWidgetWithModalTransientChild) { // Create a desktop native Widget for Widget::Deactivate(). - Widget* deactivate_widget = CreateTopLevelNativeWidget(); - ShowSync(deactivate_widget); + WidgetAutoclosePtr deactivate_widget(CreateTopLevelNativeWidget()); + ShowSync(deactivate_widget.get()); // Create a top level desktop native widget. - Widget* top_level = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr top_level(CreateTopLevelNativeWidget()); Textfield* textfield = new Textfield; textfield->SetBounds(0, 0, 200, 20); top_level->GetRootView()->AddChildView(textfield); - ShowSync(top_level); + ShowSync(top_level.get()); textfield->RequestFocus(); EXPECT_TRUE(textfield->HasFocus()); @@ -1559,18 +1278,15 @@ EXPECT_TRUE(dialog_textfield->HasFocus()); EXPECT_FALSE(textfield->HasFocus()); - DeactivateSync(top_level); + DeactivateSync(top_level.get()); EXPECT_FALSE(dialog_textfield->HasFocus()); EXPECT_FALSE(textfield->HasFocus()); // After deactivation and activation of top level widget, only modal dialog // should restore focused view. - ActivateSync(top_level); + ActivateSync(top_level.get()); EXPECT_TRUE(dialog_textfield->HasFocus()); EXPECT_FALSE(textfield->HasFocus()); - - top_level->CloseNow(); - deactivate_widget->CloseNow(); } #endif // defined(OS_LINUX) && BUILDFLAG(ENABLE_DESKTOP_AURA) @@ -1762,6 +1478,236 @@ EXPECT_TRUE(mouse_view2->pressed()); } +TEST_F(WidgetCaptureTest, CaptureAutoReset) { + WidgetAutoclosePtr toplevel(CreateTopLevelFramelessPlatformWidget()); + View* container = new View; + toplevel->SetContentsView(container); + + EXPECT_FALSE(toplevel->HasCapture()); + toplevel->SetCapture(nullptr); + EXPECT_TRUE(toplevel->HasCapture()); + + // By default, mouse release removes capture. + gfx::Point click_location(45, 15); + ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location, + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&release); + EXPECT_FALSE(toplevel->HasCapture()); + + // Now a mouse release shouldn't remove capture. + toplevel->set_auto_release_capture(false); + toplevel->SetCapture(nullptr); + EXPECT_TRUE(toplevel->HasCapture()); + toplevel->OnMouseEvent(&release); + EXPECT_TRUE(toplevel->HasCapture()); + toplevel->ReleaseCapture(); + EXPECT_FALSE(toplevel->HasCapture()); +} + +TEST_F(WidgetCaptureTest, ResetCaptureOnGestureEnd) { + WidgetAutoclosePtr toplevel(CreateTopLevelFramelessPlatformWidget()); + View* container = new View; + toplevel->SetContentsView(container); + + View* gesture = new GestureCaptureView; + gesture->SetBounds(0, 0, 30, 30); + container->AddChildView(gesture); + + MouseView* mouse = new MouseView; + mouse->SetBounds(30, 0, 30, 30); + container->AddChildView(mouse); + + toplevel->SetSize(gfx::Size(100, 100)); + toplevel->Show(); + + // Start a gesture on |gesture|. + ui::GestureEvent tap_down(15, 15, 0, base::TimeTicks(), + ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN)); + ui::GestureEvent end(15, 15, 0, base::TimeTicks(), + ui::GestureEventDetails(ui::ET_GESTURE_END)); + toplevel->OnGestureEvent(&tap_down); + + // Now try to click on |mouse|. Since |gesture| will have capture, |mouse| + // will not receive the event. + gfx::Point click_location(45, 15); + + ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location, + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location, + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + + EXPECT_TRUE(toplevel->HasCapture()); + + toplevel->OnMouseEvent(&press); + toplevel->OnMouseEvent(&release); + EXPECT_EQ(0, mouse->pressed()); + + EXPECT_FALSE(toplevel->HasCapture()); + + // The end of the gesture should release the capture, and pressing on |mouse| + // should now reach |mouse|. + toplevel->OnGestureEvent(&end); + toplevel->OnMouseEvent(&press); + toplevel->OnMouseEvent(&release); + EXPECT_EQ(1, mouse->pressed()); +} + +// Checks that if a mouse-press triggers a capture on a different widget (which +// consumes the mouse-release event), then the target of the press does not have +// capture. +TEST_F(WidgetCaptureTest, DisableCaptureWidgetFromMousePress) { + // The test creates two widgets: |first| and |second|. + // The View in |first| makes |second| visible, sets capture on it, and starts + // a nested loop (like a menu does). The View in |second| terminates the + // nested loop and closes the widget. + // The test sends a mouse-press event to |first|, and posts a task to send a + // release event to |second|, to make sure that the release event is + // dispatched after the nested loop starts. + + WidgetAutoclosePtr first(CreateTopLevelFramelessPlatformWidget()); + Widget* second = CreateTopLevelFramelessPlatformWidget(); + + NestedLoopCaptureView* container = new NestedLoopCaptureView(second); + first->SetContentsView(container); + + second->SetContentsView(new ExitLoopOnRelease(container->GetQuitClosure())); + + first->SetSize(gfx::Size(100, 100)); + first->Show(); + + gfx::Point location(20, 20); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + &Widget::OnMouseEvent, base::Unretained(second), + base::Owned(new ui::MouseEvent( + ui::ET_MOUSE_RELEASED, location, location, ui::EventTimeForNow(), + ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)))); + ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location, + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + first->OnMouseEvent(&press); + EXPECT_FALSE(first->HasCapture()); +} + +// Tests some grab/ungrab events. +// TODO(estade): can this be enabled now that this is an interactive ui test? +TEST_F(WidgetCaptureTest, DISABLED_GrabUngrab) { + WidgetAutoclosePtr toplevel(CreateTopLevelPlatformWidget()); + Widget* child1 = CreateChildNativeWidgetWithParent(toplevel.get()); + Widget* child2 = CreateChildNativeWidgetWithParent(toplevel.get()); + + toplevel->SetBounds(gfx::Rect(0, 0, 500, 500)); + + child1->SetBounds(gfx::Rect(10, 10, 300, 300)); + View* view = new MouseView(); + view->SetBounds(0, 0, 300, 300); + child1->GetRootView()->AddChildView(view); + + child2->SetBounds(gfx::Rect(200, 10, 200, 200)); + view = new MouseView(); + view->SetBounds(0, 0, 200, 200); + child2->GetRootView()->AddChildView(view); + + toplevel->Show(); + RunPendingMessages(); + + // Click on child1 + gfx::Point p1(45, 45); + ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1, ui::EventTimeForNow(), + ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&pressed); + + EXPECT_TRUE(toplevel->HasCapture()); + EXPECT_TRUE(child1->HasCapture()); + EXPECT_FALSE(child2->HasCapture()); + + ui::MouseEvent released(ui::ET_MOUSE_RELEASED, p1, p1, ui::EventTimeForNow(), + ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&released); + + EXPECT_FALSE(toplevel->HasCapture()); + EXPECT_FALSE(child1->HasCapture()); + EXPECT_FALSE(child2->HasCapture()); + + RunPendingMessages(); + + // Click on child2 + gfx::Point p2(315, 45); + ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED, p2, p2, ui::EventTimeForNow(), + ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&pressed2); + EXPECT_TRUE(pressed2.handled()); + EXPECT_TRUE(toplevel->HasCapture()); + EXPECT_TRUE(child2->HasCapture()); + EXPECT_FALSE(child1->HasCapture()); + + ui::MouseEvent released2(ui::ET_MOUSE_RELEASED, p2, p2, ui::EventTimeForNow(), + ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&released2); + EXPECT_FALSE(toplevel->HasCapture()); + EXPECT_FALSE(child1->HasCapture()); + EXPECT_FALSE(child2->HasCapture()); +} + +// Disabled on Mac. Desktop Mac doesn't have system modal windows since Carbon +// was deprecated. It does have application modal windows, but only Ash requests +// those. +#if defined(OS_MACOSX) +#define MAYBE_SystemModalWindowReleasesCapture \ + DISABLED_SystemModalWindowReleasesCapture +#elif defined(OS_CHROMEOS) +// Investigate enabling for Chrome OS. It probably requires help from the window +// service. +#define MAYBE_SystemModalWindowReleasesCapture \ + DISABLED_SystemModalWindowReleasesCapture +#else +#define MAYBE_SystemModalWindowReleasesCapture SystemModalWindowReleasesCapture +#endif + +// Test that when opening a system-modal window, capture is released. +TEST_F(WidgetCaptureTest, MAYBE_SystemModalWindowReleasesCapture) { + TestWidgetFocusChangeListener focus_listener; + WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener); + + // Create a top level widget. + Widget top_level_widget; + Widget::InitParams init_params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + init_params.show_state = ui::SHOW_STATE_NORMAL; + gfx::Rect initial_bounds(0, 0, 500, 500); + init_params.bounds = initial_bounds; + init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + top_level_widget.Init(std::move(init_params)); + ShowSync(&top_level_widget); + + ASSERT_FALSE(focus_listener.focus_changes().empty()); + EXPECT_EQ(top_level_widget.GetNativeView(), + focus_listener.focus_changes().back()); + + EXPECT_FALSE(top_level_widget.HasCapture()); + top_level_widget.SetCapture(nullptr); + EXPECT_TRUE(top_level_widget.HasCapture()); + + // Create a modal dialog. + ModalDialogDelegate* dialog_delegate = + new ModalDialogDelegate(ui::MODAL_TYPE_SYSTEM); + + Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget( + dialog_delegate, nullptr, top_level_widget.GetNativeView()); + modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200)); + ShowSync(modal_dialog_widget); + + EXPECT_FALSE(top_level_widget.HasCapture()); + + modal_dialog_widget->CloseNow(); + top_level_widget.CloseNow(); + WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener); +} + // Regression test for http://crbug.com/382421 (Linux-Aura issue). // TODO(pkotwicz): Make test pass on CrOS and Windows. // TODO(tapted): Investigate for toolkit-views on Mac http;//crbug.com/441064. @@ -1971,33 +1917,32 @@ #endif // Test input method focus changes affected by top window activaction. TEST_F(WidgetInputMethodInteractiveTest, MAYBE_Activation) { - Widget* widget = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); Textfield* textfield = new Textfield; widget->GetRootView()->AddChildView(textfield); textfield->RequestFocus(); - ShowSync(widget); + ShowSync(widget.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, widget->GetInputMethod()->GetTextInputType()); - DeactivateSync(widget); + DeactivateSync(widget.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, widget->GetInputMethod()->GetTextInputType()); - widget->CloseNow(); } // Test input method focus changes affected by focus changes within 1 window. TEST_F(WidgetInputMethodInteractiveTest, OneWindow) { - Widget* widget = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); Textfield* textfield1 = new Textfield; Textfield* textfield2 = new Textfield; textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); widget->GetRootView()->AddChildView(textfield1); widget->GetRootView()->AddChildView(textfield2); - ShowSync(widget); + ShowSync(widget.get()); textfield1->RequestFocus(); EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, @@ -2011,31 +1956,30 @@ // DNWA (which just activates the last active window) and involves the // AuraTestHelper which sets the input method as DummyInputMethod. #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MACOSX) - DeactivateSync(widget); + DeactivateSync(widget.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, widget->GetInputMethod()->GetTextInputType()); - ActivateSync(widget); + ActivateSync(widget.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, widget->GetInputMethod()->GetTextInputType()); - DeactivateSync(widget); + DeactivateSync(widget.get()); textfield1->RequestFocus(); - ActivateSync(widget); + ActivateSync(widget.get()); EXPECT_TRUE(widget->IsActive()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, widget->GetInputMethod()->GetTextInputType()); #endif - widget->CloseNow(); } // Test input method focus changes affected by focus changes cross 2 windows // which shares the same top window. TEST_F(WidgetInputMethodInteractiveTest, TwoWindows) { - Widget* parent = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr parent(CreateTopLevelNativeWidget()); parent->SetBounds(gfx::Rect(100, 100, 100, 100)); - Widget* child = CreateChildNativeWidgetWithParent(parent); + Widget* child = CreateChildNativeWidgetWithParent(parent.get()); child->SetBounds(gfx::Rect(0, 0, 50, 50)); child->Show(); @@ -2044,7 +1988,7 @@ textfield_parent->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); parent->GetRootView()->AddChildView(textfield_parent); child->GetRootView()->AddChildView(textfield_child); - ShowSync(parent); + ShowSync(parent.get()); EXPECT_EQ(parent->GetInputMethod(), child->GetInputMethod()); @@ -2060,33 +2004,31 @@ // DNWA (which just activates the last active window) and involves the // AuraTestHelper which sets the input method as DummyInputMethod. #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MACOSX) - DeactivateSync(parent); + DeactivateSync(parent.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, parent->GetInputMethod()->GetTextInputType()); - ActivateSync(parent); + ActivateSync(parent.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, parent->GetInputMethod()->GetTextInputType()); textfield_parent->RequestFocus(); - DeactivateSync(parent); + DeactivateSync(parent.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, parent->GetInputMethod()->GetTextInputType()); - ActivateSync(parent); + ActivateSync(parent.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, parent->GetInputMethod()->GetTextInputType()); #endif - - parent->CloseNow(); } // Test input method focus changes affected by textfield's state changes. TEST_F(WidgetInputMethodInteractiveTest, TextField) { - Widget* widget = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); Textfield* textfield = new Textfield; widget->GetRootView()->AddChildView(textfield); - ShowSync(widget); + ShowSync(widget.get()); EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, widget->GetInputMethod()->GetTextInputType()); @@ -2105,15 +2047,14 @@ textfield->SetReadOnly(true); EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, widget->GetInputMethod()->GetTextInputType()); - widget->CloseNow(); } // Test input method should not work for accelerator. TEST_F(WidgetInputMethodInteractiveTest, AcceleratorInTextfield) { - Widget* widget = CreateTopLevelNativeWidget(); + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); Textfield* textfield = new Textfield; widget->GetRootView()->AddChildView(textfield); - ShowSync(widget); + ShowSync(widget.get()); textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT); textfield->RequestFocus(); @@ -2130,8 +2071,6 @@ ui::KeyEvent key_event2(key_event); widget->OnKeyEvent(&key_event2); EXPECT_FALSE(key_event2.stopped_propagation()); - - widget->CloseNow(); } } // namespace test
diff --git a/weblayer/browser/android/javatests/BUILD.gn b/weblayer/browser/android/javatests/BUILD.gn index bb5a6da8..5770eba 100644 --- a/weblayer/browser/android/javatests/BUILD.gn +++ b/weblayer/browser/android/javatests/BUILD.gn
@@ -130,3 +130,30 @@ deps = [ ":weblayer_private_java_tests" ] } + +# Runs WebLayer instrumentation tests against arbitrary versions of tests, the +# client, and the implementation. +# +# Example usage, testing M80 tests and client against master implementation: +# autoninja -C out/Release weblayer_instrumentation_test_versions_apk +# cipd install --root /tmp/M80 chromium/testing/weblayer-x86 m80 +# out/Release/bin/run_weblayer_instrumentation_tests_versions_apk \ +# --tests-outdir /tmp/M80/out/Release +# --client-outdir /tmp/M80/out/Release +# --implementation-outdir out/Release +copy("weblayer_instrumentation_test_versions_apk") { + testonly = true + + sources = [ "weblayer_instrumentation_test_versions.py" ] + + outputs = + [ "$root_build_dir/bin/run_weblayer_instrumentation_test_versions_apk" ] + + # Also explicitly list the output as data so it gets isolated on bots. + data = + [ "$root_build_dir/bin/run_weblayer_instrumentation_test_versions_apk" ] + + deps = [ ":weblayer_instrumentation_test_apk" ] + + data_deps = [ ":weblayer_instrumentation_test_apk" ] +}
diff --git a/weblayer/browser/android/javatests/weblayer_instrumentation_test_versions.py b/weblayer/browser/android/javatests/weblayer_instrumentation_test_versions.py new file mode 100755 index 0000000..bfde31e --- /dev/null +++ b/weblayer/browser/android/javatests/weblayer_instrumentation_test_versions.py
@@ -0,0 +1,92 @@ +#!/usr/bin/env vpython +# +# 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. +# +# Runs WebLayer instrumentation tests against arbitrary versions of tests, the +# client, and the implementation. +# +# Example usage, testing M80 tests and client against master implementation: +# autoninja -C out/Release weblayer_instrumentation_test_versions_apk +# cipd install --root /tmp/M80 chromium/testing/weblayer-x86 m80 +# out/Release/bin/run_weblayer_instrumentation_tests_versions_apk \ +# --tests-outdir /tmp/M80/out/Release +# --client-outdir /tmp/M80/out/Release +# --implementation-outdir out/Release + +import argparse +import logging +import os +import re +import subprocess +import sys + + +def main(): + """Wrapper to call weblayer instrumentation tests with different versions.""" + + parser = argparse.ArgumentParser( + description='Run weblayer instrumentation tests at different versions.') + parser.add_argument( + '--tests-outdir', + required=True, + help=('Build output directory from which to find tests and test ' + + 'support files. Since test dependencies can reside in both ' + + 'the build output directory and the source directory, this ' + + 'script will look two directories up for source files unless ' + + '--test-srcdir is also set.')) + parser.add_argument( + '--tests-srcdir', + required=False, + default='', + help=('Source directory from which to find test data. If unset the ' + + 'script will use two directories above --test-outdir.')) + parser.add_argument( + '--client-outdir', + required=True, + help='Build output directory for WebLayer client.') + parser.add_argument( + '--implementation-outdir', + required=True, + help='Build output directory for WebLayer implementation.') + args = parser.parse_args() + + logging.basicConfig(level=logging.INFO) + + # The command line is derived from the resulting command line from + # run_weblayer_instrumentation_test_apk but with parameterized tests, client, + # and implementation. + if args.tests_srcdir: + tests_srcdir = args.tests_srcdir + else: + tests_srcdir = os.path.normpath(os.path.join(args.tests_outdir, '..', '..')) + executable_path = os.path.join(tests_srcdir, 'build/android/test_runner.py') + executable_args = [ + 'instrumentation', + '--output-directory', + args.tests_outdir, + '--runtime-deps-path', + os.path.join(args.tests_outdir, + ('gen.runtime/weblayer/browser/android/javatests/' + + 'weblayer_instrumentation_test_apk.runtime_deps')), + '--test-apk', + os.path.join(args.tests_outdir, 'apks/WebLayerInstrumentationTest.apk'), + '--test-jar', + os.path.join(args.tests_outdir, + 'test.lib.java/WebLayerInstrumentationTest.jar'), + '--apk-under-test', + os.path.join(args.client_outdir, 'apks/WebLayerShellSystemWebView.apk'), + '--use-webview-provider', + os.path.join(args.implementation_outdir, 'apks/SystemWebView.apk'), + '--additional-apk', + os.path.join(args.tests_outdir, 'apks/ChromiumNetTestSupport.apk')] + + cmd = [executable_path] + executable_args + cmd = [sys.executable] + cmd + logging.info(' '.join(cmd)) + return subprocess.call(cmd) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/weblayer/browser/profile_disk_operations.cc b/weblayer/browser/profile_disk_operations.cc index ae062a12..3b1a58d 100644 --- a/weblayer/browser/profile_disk_operations.cc +++ b/weblayer/browser/profile_disk_operations.cc
@@ -107,6 +107,10 @@ CHECK(data_root_path.AppendRelativePath(info.data_path, &marker_path)); base::File file(marker_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); + if (!base::PathExists(marker_path)) { + LOG(WARNING) << "Failure in deleting profile data. Profile:" << info.name + << " error:" << static_cast<int>(file.error_details()); + } } void TryNukeProfileFromDisk(const ProfileInfo& info) {