diff --git a/DEPS b/DEPS index d82411c..068a4339 100644 --- a/DEPS +++ b/DEPS
@@ -121,11 +121,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'eceb19f37e0ab68a77618239c33e163ea697bb04', + 'skia_revision': 'd8a90f9be1f068dd8231cc6c9e9d490d17e7ece6', # 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': '6bf2d7999b7d4193221f058a70962b181abf58d3', + 'v8_revision': '6e89f8f552fe46cbf81a5bbb40066f881b2e7e65', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -133,7 +133,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '4c94788c9c8533ae40aeb87f26d45fd7ca112f23', + 'angle_revision': '0f073667daf00e894e17cbe7d40187c881552648', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -145,7 +145,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'b600f15d3895afac7e6a39b309d59c4229b177f3', + 'pdfium_revision': '57a2246b527fcdcd434aad381067c62fd9d583af', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -181,11 +181,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '556d7714fda3de581bcc7b18e612a4aa63fdd244', + 'catapult_revision': 'eae881c2a8ba3cea65d9e610ce347373486f91b4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. - 'libfuzzer_revision': 'ee7a5b85c7cf017a138920ae4fe8cc65cb2b5625', + 'libfuzzer_revision': '6134addcf3523f4fda9e3add9fa1850f8a3ee48b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-node-modules # and whatever else without interference from each other. @@ -245,7 +245,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '1c0b0474c1a01a88e7e51a0b5a18771d96aacf88', + 'dawn_revision': '79ff8bead9091f8041f623c1109c290154211f21', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -679,7 +679,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd403a66dc72a6484c0a6e8693be9c44eea2c0d26', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '2900d34d5975cc467e393fcf26bad649706e858c', 'condition': 'checkout_linux', }, @@ -704,7 +704,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b19e8dff155d6bb50ddbb8b7ddd12b4b28fec7b4', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3f812d07b2aa257fcdb7860e6cdd53e24b283bca', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1240,7 +1240,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6ca723bad79bad35876ae2fa540536f51b14084a', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@56f3eeaa1714342e2fed47845f821dfa923a5d28', 'condition': 'checkout_src_internal', },
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 7e2302fd..afa1de18 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1518,7 +1518,6 @@ deps = [ ":ash_shell_lib", - ":manifest", ":test_support", "//ash/components/quick_launch:lib", "//ash/components/quick_launch:manifest", @@ -1530,6 +1529,8 @@ "//ash/components/tap_visualizer:manifest", "//ash/components/tap_visualizer/public/mojom", "//ash/public/cpp", + "//ash/public/cpp:manifest", + "//ash/public/cpp:manifest_for_tests", "//base:i18n", "//chrome:packed_resources", "//chromeos", @@ -1892,7 +1893,6 @@ deps = [ ":ash", ":ash_service_resources", - ":manifest", ":test_support", "//ash/app_list:test_support", "//ash/app_list/presenter", @@ -1908,6 +1908,8 @@ "//ash/components/tap_visualizer:unit_tests", "//ash/keyboard/arc", "//ash/public/cpp", + "//ash/public/cpp:manifest", + "//ash/public/cpp:manifest_for_tests", "//ash/public/cpp:test_support", "//ash/public/cpp:unit_tests", "//ash/public/cpp/vector_icons", @@ -2288,12 +2290,6 @@ ] } -service_manifest("manifest") { - name = "ash" - source = "manifest.json" - packaged_services = [ "//services/ws:manifest" ] -} - # TODO: Load locale-specific strings. # TODO: Avoid duplication between Mash and Chrome pak files: crbug.com/628715. repack("ash_service_resources") {
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 5f85b081..18a7ba8 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -943,7 +943,7 @@ namespace { -// Tests the four combinations of the TOGGLE_CAPS_LOCK accelerator. +// Tests the TOGGLE_CAPS_LOCK accelerator. TEST_F(AcceleratorControllerTest, ToggleCapsLockAccelerators) { ImeController* controller = Shell::Get()->ime_controller(); @@ -1041,6 +1041,20 @@ EXPECT_TRUE(controller->IsCapsLockEnabled()); controller->UpdateCapsLockState(false); } + + // 7. Toggle CapsLock shortcut should still work after fake events generated. + // (https://crbug.com/918317). + generator->PressKey(ui::VKEY_PROCESSKEY, ui::EF_IME_FABRICATED_KEY); + generator->ReleaseKey(ui::VKEY_UNKNOWN, ui::EF_IME_FABRICATED_KEY); + + // Press Search, Press Alt, Release Search, Release Alt. CapsLock should be + // triggered. + EXPECT_FALSE(ProcessInController(press_search_then_alt)); + EXPECT_TRUE(ProcessInController(release_search_before_alt)); + controller->FlushMojoForTesting(); + EXPECT_EQ(6, client.set_caps_lock_count_); + EXPECT_TRUE(controller->IsCapsLockEnabled()); + controller->UpdateCapsLockState(false); } class PreferredReservedAcceleratorsTest : public AshTestBase {
diff --git a/ash/accelerators/exit_warning_handler.h b/ash/accelerators/exit_warning_handler.h index c678f84d..75884c8a 100644 --- a/ash/accelerators/exit_warning_handler.h +++ b/ash/accelerators/exit_warning_handler.h
@@ -56,6 +56,7 @@ private: friend class AcceleratorControllerTest; + friend class OverviewSessionTest; enum State { IDLE, WAIT_FOR_DOUBLE_PRESS, EXITING };
diff --git a/ash/accessibility/accessibility_focus_ring_controller.cc b/ash/accessibility/accessibility_focus_ring_controller.cc index 66e9880..abc3a496 100644 --- a/ash/accessibility/accessibility_focus_ring_controller.cc +++ b/ash/accessibility/accessibility_focus_ring_controller.cc
@@ -66,14 +66,14 @@ SkColor color, const std::string& caller_id) { AccessibilityFocusRingGroup* focus_ring_group = - GetFocusRingGroupForCallerId(caller_id, /* Create if missing */ true); + GetFocusRingGroupForCallerId(caller_id, true /* Create if missing */); focus_ring_group->SetColor(color, this); } void AccessibilityFocusRingController::ResetFocusRingColor( const std::string& caller_id) { AccessibilityFocusRingGroup* focus_ring_group = - GetFocusRingGroupForCallerId(caller_id, /* Do not create */ false); + GetFocusRingGroupForCallerId(caller_id, false /* Do not create */); if (!focus_ring_group) return; focus_ring_group->ResetColor(this); @@ -84,7 +84,7 @@ mojom::FocusRingBehavior focus_ring_behavior, const std::string& caller_id) { AccessibilityFocusRingGroup* focus_ring_group = - GetFocusRingGroupForCallerId(caller_id, /* Create if missing */ true); + GetFocusRingGroupForCallerId(caller_id, true /* Create if missing */); if (focus_ring_group->SetFocusRectsAndBehavior(rects, focus_ring_behavior, this)) OnLayerChange(focus_ring_group->focus_animation_info()); @@ -93,7 +93,7 @@ void AccessibilityFocusRingController::HideFocusRing( const std::string& caller_id) { AccessibilityFocusRingGroup* focus_ring_group = - GetFocusRingGroupForCallerId(caller_id, /* Do not create */ false); + GetFocusRingGroupForCallerId(caller_id, false /* Do not create */); if (!focus_ring_group) return; focus_ring_group->ClearFocusRects(this); @@ -114,6 +114,23 @@ UpdateHighlightFromHighlightRects(); } +void AccessibilityFocusRingController::EnableDoubleFocusRing( + SkColor color, + const std::string& caller_id) { + AccessibilityFocusRingGroup* focus_ring_group = + GetFocusRingGroupForCallerId(caller_id, true /* Create if missing */); + focus_ring_group->EnableDoubleFocusRing(color, this); +} + +void AccessibilityFocusRingController::DisableDoubleFocusRing( + const std::string& caller_id) { + AccessibilityFocusRingGroup* focus_ring_group = + GetFocusRingGroupForCallerId(caller_id, false /* Do not create */); + if (!focus_ring_group) + return; + focus_ring_group->DisableDoubleFocusRing(this); +} + void AccessibilityFocusRingController::UpdateHighlightFromHighlightRects() { if (!highlight_layer_) highlight_layer_ = std::make_unique<AccessibilityHighlightLayer>(this);
diff --git a/ash/accessibility/accessibility_focus_ring_controller.h b/ash/accessibility/accessibility_focus_ring_controller.h index 0cf323cf4..a7464bf 100644 --- a/ash/accessibility/accessibility_focus_ring_controller.h +++ b/ash/accessibility/accessibility_focus_ring_controller.h
@@ -49,6 +49,9 @@ void SetHighlights(const std::vector<gfx::Rect>& rects, SkColor color) override; void HideHighlights() override; + void EnableDoubleFocusRing(SkColor color, + const std::string& caller_id) override; + void DisableDoubleFocusRing(const std::string& caller_id) override; // Draw a ring around the mouse cursor. It fades out automatically. void SetCursorRing(const gfx::Point& location);
diff --git a/ash/accessibility/accessibility_focus_ring_group.cc b/ash/accessibility/accessibility_focus_ring_group.cc index 1cda6af1..ffd7811 100644 --- a/ash/accessibility/accessibility_focus_ring_group.cc +++ b/ash/accessibility/accessibility_focus_ring_group.cc
@@ -67,6 +67,19 @@ UpdateFocusRingsFromFocusRects(delegate); } +void AccessibilityFocusRingGroup::EnableDoubleFocusRing( + SkColor color, + AccessibilityLayerDelegate* delegate) { + focus_ring_secondary_color_ = color; + UpdateFocusRingsFromFocusRects(delegate); +} + +void AccessibilityFocusRingGroup::DisableDoubleFocusRing( + AccessibilityLayerDelegate* delegate) { + focus_ring_secondary_color_.reset(); + UpdateFocusRingsFromFocusRects(delegate); +} + void AccessibilityFocusRingGroup::UpdateFocusRingsFromFocusRects( AccessibilityLayerDelegate* delegate) { previous_focus_rings_.swap(focus_rings_); @@ -96,10 +109,15 @@ } for (size_t i = 0; i < focus_rings_.size(); ++i) { - if (focus_ring_color_) { + if (focus_ring_color_) focus_layers_[i]->SetColor(*(focus_ring_color_)); - } else + else focus_layers_[i]->ResetColor(); + + if (focus_ring_secondary_color_) + focus_layers_[i]->EnableDoubleFocusRing(*(focus_ring_secondary_color_)); + else + focus_layers_[i]->DisableDoubleFocusRing(); } }
diff --git a/ash/accessibility/accessibility_focus_ring_group.h b/ash/accessibility/accessibility_focus_ring_group.h index 7f1c3ae..e74895e0 100644 --- a/ash/accessibility/accessibility_focus_ring_group.h +++ b/ash/accessibility/accessibility_focus_ring_group.h
@@ -31,6 +31,10 @@ void SetColor(SkColor color, AccessibilityLayerDelegate* delegate); void ResetColor(AccessibilityLayerDelegate* delegate); + void EnableDoubleFocusRing(SkColor secondary_color, + AccessibilityLayerDelegate* delegate); + void DisableDoubleFocusRing(AccessibilityLayerDelegate* delegate); + void UpdateFocusRingsFromFocusRects(AccessibilityLayerDelegate* delegate); bool CanAnimate() const; void AnimateFocusRings(base::TimeTicks timestamp); @@ -77,6 +81,7 @@ std::vector<gfx::Rect> focus_rects_; base::Optional<SkColor> focus_ring_color_; + base::Optional<SkColor> focus_ring_secondary_color_; std::vector<AccessibilityFocusRing> previous_focus_rings_; std::vector<std::unique_ptr<AccessibilityFocusRingLayer>> focus_layers_; std::vector<AccessibilityFocusRing> focus_rings_;
diff --git a/ash/app_launch_unittest.cc b/ash/app_launch_unittest.cc index 8813629..cad40f3 100644 --- a/ash/app_launch_unittest.cc +++ b/ash/app_launch_unittest.cc
@@ -4,7 +4,8 @@ #include "ash/components/quick_launch/manifest.h" #include "ash/components/quick_launch/public/mojom/constants.mojom.h" -#include "ash/manifest.h" +#include "ash/public/cpp/manifest.h" +#include "ash/public/cpp/test_manifest.h" #include "ash/public/interfaces/constants.mojom.h" #include "base/bind.h" #include "base/command_line.h" @@ -32,7 +33,9 @@ public: AppLaunchTest() : test_service_manager_( - {GetManifest(), quick_launch_app::GetManifest(), + {service_manager::Manifest(GetManifest()) + .Amend(GetManifestOverlayForTesting()), + quick_launch_app::GetManifest(), service_manager::ManifestBuilder() .WithServiceName(kTestServiceName) .RequireCapability(mojom::kServiceName, "")
diff --git a/ash/ash_service_unittest.cc b/ash/ash_service_unittest.cc index 92c20b9..9bd86bd 100644 --- a/ash/ash_service_unittest.cc +++ b/ash/ash_service_unittest.cc
@@ -6,7 +6,8 @@ #include <memory> #include <vector> -#include "ash/manifest.h" +#include "ash/public/cpp/manifest.h" +#include "ash/public/cpp/test_manifest.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/public/interfaces/window_properties.mojom.h" @@ -78,7 +79,8 @@ public: AshServiceTest() : test_service_manager_( - {GetManifest(), + {service_manager::Manifest(GetManifest()) + .Amend(GetManifestOverlayForTesting()), service_manager::ManifestBuilder() .WithServiceName(kTestServiceName) .RequireCapability(ws::mojom::kServiceName, "app")
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 06d8fd3..c16bd1e 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1268,9 +1268,6 @@ <message name="IDS_ASH_DISPLAY_FAILURE_SEND_FEEDBACK" desc="Button text below error report to allow user to send feedback report."> Send feedback </message> - <message name="IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED" desc="A message used to explain that mirroring with more than two displays is not supported."> - Mirroring with more than two displays is not supported. - </message> <message name="IDS_ASH_DISPLAY_RESOLUTION_CHANGE_ACCEPT" desc="A button label shown in the notification for the resolution change to accept the change"> Accept </message>
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc index 6e3a85b8..a8e65c5 100644 --- a/ash/display/cursor_window_controller.cc +++ b/ash/display/cursor_window_controller.cc
@@ -133,8 +133,7 @@ // early outing when there isn't a PrefService yet. Shell* shell = Shell::Get(); display::DisplayManager* display_manager = shell->display_manager(); - if ((display_manager->is_multi_mirroring_enabled() && - display_manager->IsInSoftwareMirrorMode()) || + if ((display_manager->IsInSoftwareMirrorMode()) || display_manager->IsInUnifiedMode() || display_manager->screen_capture_is_active()) { return true;
diff --git a/ash/display/display_configuration_controller.cc b/ash/display/display_configuration_controller.cc index 7ad578a..ec6f43e 100644 --- a/ash/display/display_configuration_controller.cc +++ b/ash/display/display_configuration_controller.cc
@@ -130,13 +130,6 @@ } void DisplayConfigurationController::SetMirrorMode(bool mirror, bool throttle) { - if (!display_manager_->is_multi_mirroring_enabled() && - display_manager_->num_connected_displays() > 2) { - ShowDisplayErrorNotification( - l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED), - false); - return; - } if (display_manager_->num_connected_displays() <= 1 || display_manager_->IsInMirrorMode() == mirror || (throttle && IsLimited())) {
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index 7d0fce9..bb19f75 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc
@@ -183,22 +183,6 @@ DISALLOW_COPY_AND_ASSIGN(DisplayManagerTest); }; -class DisplayManagerTestDisableMultiMirroring : public DisplayManagerTest { - public: - DisplayManagerTestDisableMultiMirroring() = default; - ~DisplayManagerTestDisableMultiMirroring() override = default; - - // DisplayManagerTest: - void SetUp() override { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - ::switches::kDisableMultiMirroring); - DisplayManagerTest::SetUp(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(DisplayManagerTestDisableMultiMirroring); -}; - TEST_F(DisplayManagerTest, UpdateDisplayTest) { EXPECT_EQ(1U, display_manager()->GetNumDisplays()); @@ -1032,17 +1016,6 @@ EXPECT_TRUE(layout.HasSamePlacementList(*(expected_layout_builder.Build()))); } -// TODO(weidongg/774795) Remove test when multi mirroring is enabled by default. -TEST_F(DisplayManagerTestDisableMultiMirroring, NoMirrorInThreeDisplays) { - UpdateDisplay("640x480,320x200,400x300"); - ash::Shell::Get()->display_configuration_controller()->SetMirrorMode(true, - false); - EXPECT_FALSE(display_manager()->IsInMirrorMode()); - EXPECT_EQ(3u, display_manager()->GetNumDisplays()); - EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED), - GetDisplayErrorNotificationMessageForTest()); -} - TEST_F(DisplayManagerTest, OverscanInsetsTest) { UpdateDisplay("0+0-500x500,0+501-400x400"); reset(); @@ -2240,41 +2213,6 @@ SetSoftwareMirrorMode(false); } -// TODO(weidongg/774795) Remove test when multi mirroring is enabled by default. -// Make sure this does not cause any crashes. See http://crbug.com/412910 -TEST_F(DisplayManagerTestDisableMultiMirroring, - SoftwareMirroringWithCompositingCursor) { - UpdateDisplay("300x400,400x500"); - - MirrorWindowTestApi test_api; - EXPECT_TRUE(test_api.GetHosts().empty()); - - display::ManagedDisplayInfo secondary_info = - display_manager()->GetDisplayInfo( - display_manager()->GetSecondaryDisplay().id()); - - display_manager()->SetSoftwareMirroring(true); - display_manager()->UpdateDisplays(); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_FALSE(root_windows[0]->Contains(test_api.GetCursorWindow())); - - Shell::Get()->SetCursorCompositingEnabled(true); - - EXPECT_TRUE(root_windows[0]->Contains(test_api.GetCursorWindow())); - - // Removes the first display and keeps the second one. - display_manager()->SetSoftwareMirroring(false); - std::vector<display::ManagedDisplayInfo> new_info_list; - new_info_list.push_back(secondary_info); - display_manager()->OnNativeDisplaysChanged(new_info_list); - - root_windows = Shell::GetAllRootWindows(); - EXPECT_TRUE(root_windows[0]->Contains(test_api.GetCursorWindow())); - - Shell::Get()->SetCursorCompositingEnabled(false); -} - TEST_F(DisplayManagerTest, InvertLayout) { EXPECT_EQ("left, 0", display::DisplayPlacement(display::DisplayPlacement::RIGHT, 0)
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc index d039ad6..217055a 100644 --- a/ash/display/window_tree_host_manager.cc +++ b/ash/display/window_tree_host_manager.cc
@@ -782,8 +782,7 @@ // Enable cursor compositing, so that cursor could be mirrored to destination // displays along with other display content through reflector. - if (display_manager->is_multi_mirroring_enabled()) - Shell::Get()->UpdateCursorCompositingEnabled(); + Shell::Get()->UpdateCursorCompositingEnabled(); } display::DisplayConfigurator* WindowTreeHostManager::display_configurator() {
diff --git a/ash/keyboard/ash_keyboard_controller.cc b/ash/keyboard/ash_keyboard_controller.cc index 73997f2a..4a437fa 100644 --- a/ash/keyboard/ash_keyboard_controller.cc +++ b/ash/keyboard/ash_keyboard_controller.cc
@@ -53,10 +53,6 @@ keyboard_ui_factory_ ? keyboard_ui_factory_->CreateKeyboardUI() : std::make_unique<AshKeyboardUI>(this), virtual_keyboard_controller_.get()); - - // Start preloading the virtual keyboard UI in the background, so that it - // shows up faster when needed. - keyboard_controller_->LoadKeyboardWindowInBackground(); } void AshKeyboardController::DisableKeyboard() {
diff --git a/ash/keyboard/virtual_keyboard_controller_unittest.cc b/ash/keyboard/virtual_keyboard_controller_unittest.cc index 81a3a64b..fec9ece 100644 --- a/ash/keyboard/virtual_keyboard_controller_unittest.cc +++ b/ash/keyboard/virtual_keyboard_controller_unittest.cc
@@ -593,11 +593,6 @@ ShowKeyboardInSecondaryDisplay) { UpdateDisplay("500x500,500x500"); - // Load in the primary display. - keyboard_controller_->LoadKeyboardWindowInBackground(); - // Wait for the keyboard window to load. - base::RunLoop().RunUntilIdle(); - // Show in secondary display. keyboard_controller_->ShowKeyboardInDisplay(GetSecondaryDisplay()); EXPECT_EQ(GetSecondaryRootWindow(), keyboard_controller_->GetRootWindow());
diff --git a/ash/manifest.json b/ash/manifest.json deleted file mode 100644 index 390317b6..0000000 --- a/ash/manifest.json +++ /dev/null
@@ -1,93 +0,0 @@ -{ - "name": "ash", - "display_name": "Ash Window Manager and Shell", - "sandbox_type": "none", - "options" : { - "instance_sharing" : "singleton" - }, - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - // Modifications here should correspond with changes to - // chrome_content_browser_manifest_overlay.json. - "system_ui": [ - "app_list.mojom.AppList", - "ash.mojom.AcceleratorController", - "ash.mojom.AccessibilityController", - "ash.mojom.AccessibilityFocusRingController", - "ash.mojom.AppListController", - "ash.mojom.AshMessageCenterController", - "ash.mojom.AssistantAlarmTimerController", - "ash.mojom.AssistantController", - "ash.mojom.AssistantNotificationController", - "ash.mojom.AssistantScreenContextController", - "ash.mojom.AssistantSetupController", - "ash.mojom.AssistantVolumeControl", - "ash.mojom.CastConfig", - "ash.mojom.ContainedShellController", - "ash.mojom.CrosDisplayConfigController", - "ash.mojom.DockedMagnifierController", - "ash.mojom.EventRewriterController", - "ash.mojom.FirstRunHelper", - "ash.mojom.HighlighterController", - "ash.mojom.ImeController", - "ash.mojom.KeyboardController", - "ash.mojom.LocaleUpdateController", - "ash.mojom.LoginScreen", - "ash.mojom.MediaController", - "ash.mojom.NewWindowController", - "ash.mojom.NightLightController", - "ash.mojom.NoteTakingController", - "ash.mojom.ProcessCreationTimeRecorder", - "ash.mojom.SessionController", - "ash.mojom.ShelfController", - "ash.mojom.ShellState", - "ash.mojom.ShutdownController", - "ash.mojom.SplitViewController", - "ash.mojom.SystemTray", - "ash.mojom.TabletModeController", - "ash.mojom.TrayAction", - "ash.mojom.VoiceInteractionController", - "ash.mojom.VpnList", - "ash.mojom.WallpaperController" - ], - // Test-only interfaces. - "test": [ - "ash.mojom.LoginScreenTestApi", - "ash.mojom.ShelfTestApi", - "ash.mojom.ShellTestApi", - "ash.mojom.StatusAreaWidgetTestApi", - "ash.mojom.SystemTrayTestApi", - "ash.mojom.TimeToFirstPresentRecorderTestApi" - ], - // Only chrome is allowed to use this (required as dbus runs in Chrome). - "display": [ - "ash.mojom.AshDisplayController", - "ash.mojom.DisplayOutputProtection" - ], - "mus:window_manager": [ "ui.mojom.AcceleratorRegistrar" ], - "service_manager:service_factory": [ - "service_manager.mojom.ServiceFactory" - ] - }, - "requires": { - "*": [ "accessibility", "app" ], - "ash_pref_connector": [ "pref_connector" ], - "catalog": [ "directory" ], - "content": [ "navigation" ], - "device": [ - "device:bluetooth_system", - "device:fingerprint" - ], - "local_state": [ "pref_client" ], - "multidevice_setup": [ "multidevice_setup" ], - "ui": [ - "ozone", - "window_manager" - ], - "data_decoder": [ "image_decoder" ], - "viz": [ "viz_host" ] - } - } - } -}
diff --git a/ash/media/media_controller.cc b/ash/media/media_controller.cc index b3bb505c..3a36b3f6 100644 --- a/ash/media/media_controller.cc +++ b/ash/media/media_controller.cc
@@ -117,7 +117,7 @@ void MediaController::SetMediaSessionControllerForTest( media_session::mojom::MediaControllerPtr controller) { media_session_controller_ptr_ = std::move(controller); - BindMediaSessionObserver(); + BindMediaControllerObserver(); } void MediaController::FlushForTesting() { @@ -139,7 +139,7 @@ base::BindRepeating(&MediaController::OnMediaSessionControllerError, base::Unretained(this))); - BindMediaSessionObserver(); + BindMediaControllerObserver(); } return media_session_controller_ptr_.get(); @@ -150,12 +150,12 @@ supported_media_session_action_ = false; } -void MediaController::BindMediaSessionObserver() { +void MediaController::BindMediaControllerObserver() { if (!media_session_controller_ptr_.is_bound()) return; - media_session::mojom::MediaSessionObserverPtr observer; - media_session_observer_binding_.Bind(mojo::MakeRequest(&observer)); + media_session::mojom::MediaControllerObserverPtr observer; + media_controller_observer_binding_.Bind(mojo::MakeRequest(&observer)); media_session_controller_ptr_->AddObserver(std::move(observer)); }
diff --git a/ash/media/media_controller.h b/ash/media/media_controller.h index ac5c3ef..16a706e7 100644 --- a/ash/media/media_controller.h +++ b/ash/media/media_controller.h
@@ -13,7 +13,6 @@ #include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/media_session/public/mojom/media_controller.mojom.h" -#include "services/media_session/public/mojom/media_session.mojom.h" namespace service_manager { class Connector; @@ -38,7 +37,7 @@ // been provided to us. class ASH_EXPORT MediaController : public mojom::MediaController, - public media_session::mojom::MediaSessionObserver { + public media_session::mojom::MediaControllerObserver { public: // |connector| can be null in tests. explicit MediaController(service_manager::Connector* connector); @@ -66,7 +65,7 @@ void RequestCaptureState(); void SuspendMediaSessions(); - // media_session::mojom::MediaSessionObserver: + // media_session::mojom::MediaControllerObserver: void MediaSessionInfoChanged( media_session::mojom::MediaSessionInfoPtr session_info) override {} void MediaSessionMetadataChanged( @@ -99,7 +98,7 @@ void OnMediaSessionControllerError(); - void BindMediaSessionObserver(); + void BindMediaControllerObserver(); // Returns true if we should use the media session service for key handling. bool ShouldUseMediaSession(); @@ -113,8 +112,8 @@ service_manager::Connector* const connector_; - mojo::Binding<media_session::mojom::MediaSessionObserver> - media_session_observer_binding_{this}; + mojo::Binding<media_session::mojom::MediaControllerObserver> + media_controller_observer_binding_{this}; // Bindings for users of the mojo interface. mojo::BindingSet<mojom::MediaController> bindings_;
diff --git a/ash/media/media_notification_item.cc b/ash/media/media_notification_item.cc index 6ebc4c4..f044267b 100644 --- a/ash/media/media_notification_item.cc +++ b/ash/media/media_notification_item.cc
@@ -40,9 +40,9 @@ session_info_(std::move(session_info)) { // Bind an observer to the associated media session. if (media_controller_ptr_.is_bound()) { - media_session::mojom::MediaSessionObserverPtr media_session_observer; - observer_binding_.Bind(mojo::MakeRequest(&media_session_observer)); - media_controller_ptr_->AddObserver(std::move(media_session_observer)); + media_session::mojom::MediaControllerObserverPtr media_controller_observer; + observer_binding_.Bind(mojo::MakeRequest(&media_controller_observer)); + media_controller_ptr_->AddObserver(std::move(media_controller_observer)); } MaybeHideOrShowNotification();
diff --git a/ash/media/media_notification_item.h b/ash/media/media_notification_item.h index 6b5b2781..38ea5f3 100644 --- a/ash/media/media_notification_item.h +++ b/ash/media/media_notification_item.h
@@ -21,14 +21,14 @@ // MediaNotificationItem manages hiding/showing a media notification and // updating the metadata for a single media session. class ASH_EXPORT MediaNotificationItem - : public media_session::mojom::MediaSessionObserver { + : public media_session::mojom::MediaControllerObserver { public: MediaNotificationItem(const std::string& id, media_session::mojom::MediaControllerPtr controller, media_session::mojom::MediaSessionInfoPtr session_info); ~MediaNotificationItem() override; - // media_session::mojom::MediaSessionObserver: + // media_session::mojom::MediaControllerObserver: void MediaSessionInfoChanged( media_session::mojom::MediaSessionInfoPtr session_info) override; void MediaSessionMetadataChanged( @@ -69,8 +69,8 @@ std::set<media_session::mojom::MediaSessionAction> session_actions_; - mojo::Binding<media_session::mojom::MediaSessionObserver> observer_binding_{ - this}; + mojo::Binding<media_session::mojom::MediaControllerObserver> + observer_binding_{this}; base::WeakPtrFactory<MediaNotificationItem> weak_ptr_factory_{this};
diff --git a/ash/metrics/demo_session_metrics_recorder.cc b/ash/metrics/demo_session_metrics_recorder.cc index f27ee656..4378eb6d 100644 --- a/ash/metrics/demo_session_metrics_recorder.cc +++ b/ash/metrics/demo_session_metrics_recorder.cc
@@ -4,6 +4,7 @@ #include "ash/metrics/demo_session_metrics_recorder.h" +#include <iostream> #include <string> #include <utility> @@ -12,6 +13,7 @@ #include "ash/shelf/shelf_window_watcher.h" #include "ash/shell.h" #include "base/metrics/histogram_macros.h" +#include "base/scoped_observer.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "extensions/common/constants.h" @@ -20,6 +22,7 @@ #include "ui/aura/window.h" #include "ui/base/ui_base_features.h" #include "ui/base/user_activity/user_activity_detector.h" +#include "ui/wm/core/focus_controller.h" #include "ui/wm/public/activation_client.h" namespace ash { @@ -46,6 +49,13 @@ return DemoModeApp::kHighlights; } + // Each version of the Screensaver app is bucketed into the same value. + if (app_id == extension_misc::kScreensaverAppId || + app_id == extension_misc::kScreensaverAlt1AppId || + app_id == extension_misc::kScreensaverAlt2AppId) { + return DemoModeApp::kScreensaver; + } + if (app_id == extension_misc::kCameraAppId) return DemoModeApp::kCamera; if (app_id == extension_misc::kFilesManagerAppId) @@ -86,21 +96,30 @@ return DemoModeApp::kOtherArcApp; } +const std::string* GetArcPackageName(const aura::Window* window) { + return window->GetProperty(kArcPackageNameKey); +} + +const ShelfID GetShelfID(const aura::Window* window) { + return ShelfID::Deserialize(window->GetProperty(kShelfIDKey)); +} + +AppType GetAppType(const aura::Window* window) { + return static_cast<AppType>(window->GetProperty(aura::client::kAppType)); +} + // Maps the app-like thing in |window| to a DemoModeApp value for metrics. DemoModeApp GetAppFromWindow(const aura::Window* window) { - ash::AppType app_type = - static_cast<ash::AppType>(window->GetProperty(aura::client::kAppType)); - if (app_type == ash::AppType::ARC_APP) { + AppType app_type = GetAppType(window); + if (app_type == AppType::ARC_APP) { // The ShelfID app id isn't used to identify ARC++ apps since it's a hash of // both the package name and the activity. - const std::string* package_name = - static_cast<std::string*>(window->GetProperty(kArcPackageNameKey)); + const std::string* package_name = GetArcPackageName(window); return package_name ? GetAppFromPackageName(*package_name) : DemoModeApp::kOtherArcApp; } - std::string app_id = - ShelfID::Deserialize(window->GetProperty(kShelfIDKey)).app_id; + std::string app_id = GetShelfID(window).app_id; // The Chrome "app" in the shelf is just the browser. if (app_id == extension_misc::kChromeAppId) @@ -116,33 +135,141 @@ // If the window is the "browser" type, having an app ID other than the // default indicates a hosted/bookmark app. - if (app_type == ash::AppType::CHROME_APP || - (app_type == ash::AppType::BROWSER && !is_default(app_id))) { + if (app_type == AppType::CHROME_APP || + (app_type == AppType::BROWSER && !is_default(app_id))) { return GetAppFromAppId(app_id); } - if (app_type == ash::AppType::BROWSER) + if (app_type == AppType::BROWSER) return DemoModeApp::kBrowser; return DemoModeApp::kOtherWindow; } } // namespace +// Observes for changes in a window's ArcPackageName property for the purpose of +// logging of unique launches of ARC apps. +class DemoSessionMetricsRecorder::UniqueAppsLaunchedArcPackageNameObserver + : public aura::WindowObserver { + public: + explicit UniqueAppsLaunchedArcPackageNameObserver( + DemoSessionMetricsRecorder* metrics_recorder) + : metrics_recorder_(metrics_recorder), scoped_observer_(this) {} + + // aura::WindowObserver + void OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) override { + if (key != kArcPackageNameKey) + return; + + const std::string* package_name = GetArcPackageName(window); + + if (package_name != nullptr) + metrics_recorder_->RecordAppLaunch(*package_name); + else + VLOG(1) << "Got null ARC package name"; + + window->RemoveObserver(this); + } + + void ObserveWindow(aura::Window* window) { scoped_observer_.Add(window); } + + void OnWindowDestroyed(aura::Window* window) override { + window->RemoveObserver(this); + } + + private: + DemoSessionMetricsRecorder* metrics_recorder_; + ScopedObserver<aura::Window, UniqueAppsLaunchedArcPackageNameObserver> + scoped_observer_; + + DISALLOW_COPY_AND_ASSIGN(UniqueAppsLaunchedArcPackageNameObserver); +}; + DemoSessionMetricsRecorder::DemoSessionMetricsRecorder( std::unique_ptr<base::RepeatingTimer> timer) - : timer_(std::move(timer)), observer_(this) { + : timer_(std::move(timer)), + observer_(this), + unique_apps_arc_package_name_observer_( + std::make_unique<UniqueAppsLaunchedArcPackageNameObserver>(this)) { // Outside of tests, use a normal repeating timer. if (!timer_.get()) timer_ = std::make_unique<base::RepeatingTimer>(); StartRecording(); observer_.Add(ui::UserActivityDetector::Get()); + + // Subscribe to window activation updates. Even though this gets us + // notifications for all window activations, we ignore the ARC + // notifications because they don't contain the app_id. We handle + // accounting for ARC windows with OnTaskCreated. + if (Shell::Get()->GetPrimaryRootWindow()) { + activation_client_ = Shell::Get()->focus_controller(); + activation_client_->AddObserver(this); + } } DemoSessionMetricsRecorder::~DemoSessionMetricsRecorder() { // Report any remaining stored samples on exit. (If the user went idle, there // won't be any.) ReportSamples(); + + // Unsubscribe from window activation events. + activation_client_->RemoveObserver(this); + + ReportUniqueAppsLaunched(); +} + +// This method will only record 1 launch for each unique app_id, regardless of +// how many times it is called with that app_id. +void DemoSessionMetricsRecorder::RecordAppLaunch(const std::string& app_id) { + if (unique_apps_launched_recording_enabled_ && + GetAppFromAppId(app_id) != DemoModeApp::kHighlights && + GetAppFromAppId(app_id) != DemoModeApp::kScreensaver) { + unique_apps_launched_.insert(app_id); + } +} + +void DemoSessionMetricsRecorder::OnWindowActivated(ActivationReason reason, + aura::Window* gained_active, + aura::Window* lost_active) { + if (!gained_active) + return; + + // Don't count popup windows. + if (gained_active->type() != aura::client::WINDOW_TYPE_NORMAL) + return; + + AppType app_type = GetAppType(gained_active); + + std::string app_id; + if (app_type == AppType::ARC_APP) { + const std::string* package_name = GetArcPackageName(gained_active); + + if (!package_name) { + // The package name property for the window has not been set yet. + // Listen for changes to the window properties so we can + // be informed when the package name gets set. + if (!gained_active->HasObserver( + unique_apps_arc_package_name_observer_.get())) { + unique_apps_arc_package_name_observer_->ObserveWindow(gained_active); + } + return; + } + app_id = *package_name; + } else { + // This is a non-ARC window, so we just get the shelf ID, which should + // be unique per app. + app_id = GetShelfID(gained_active).app_id; + } + + // Some app_ids are empty, i.e the "You will be signed out + // in X seconds" modal dialog in Demo Mode, so skip those. + if (app_id.empty()) + return; + + RecordAppLaunch(app_id); } void DemoSessionMetricsRecorder::OnUserActivity(const ui::Event* event) { @@ -156,6 +283,7 @@ } void DemoSessionMetricsRecorder::StartRecording() { + unique_apps_launched_recording_enabled_ = true; timer_->Start(FROM_HERE, kSamplePeriod, this, &DemoSessionMetricsRecorder::TakeSampleOrPause); } @@ -170,7 +298,7 @@ } const aura::Window* window = - ash::Shell::Get()->activation_client()->GetActiveWindow(); + Shell::Get()->activation_client()->GetActiveWindow(); if (!window) return; @@ -186,4 +314,12 @@ unreported_samples_.clear(); } +void DemoSessionMetricsRecorder::ReportUniqueAppsLaunched() { + if (unique_apps_launched_recording_enabled_) + UMA_HISTOGRAM_COUNTS_100("DemoMode.UniqueAppsLaunched", + unique_apps_launched_.size()); + + unique_apps_launched_.clear(); +} + } // namespace ash
diff --git a/ash/metrics/demo_session_metrics_recorder.h b/ash/metrics/demo_session_metrics_recorder.h index d21fbd0..635bafaf 100644 --- a/ash/metrics/demo_session_metrics_recorder.h +++ b/ash/metrics/demo_session_metrics_recorder.h
@@ -6,12 +6,17 @@ #define ASH_METRICS_DEMO_SESSION_METRICS_RECORDER_H_ #include <memory> +#include <string> #include <vector> #include "ash/ash_export.h" +#include "base/containers/flat_set.h" #include "base/macros.h" #include "base/scoped_observer.h" +#include "ui/aura/window_observer.h" #include "ui/base/user_activity/user_activity_observer.h" +#include "ui/wm/public/activation_change_observer.h" +#include "ui/wm/public/activation_client.h" namespace base { class RepeatingTimer; @@ -25,7 +30,9 @@ // A metrics recorder for demo sessions that samples the active window's app or // window type. Only used when the device is in Demo Mode. -class ASH_EXPORT DemoSessionMetricsRecorder : public ui::UserActivityObserver { +class ASH_EXPORT DemoSessionMetricsRecorder + : public ui::UserActivityObserver, + public wm::ActivationChangeObserver { public: // These apps are preinstalled in Demo Mode. This list is not exhaustive, and // includes first- and third-party Chrome and ARC apps. @@ -52,9 +59,10 @@ kSquid = 16, // Android note-taking app. kWebStore = 17, kYouTube = 18, + kScreensaver = 19, // Demo Mode screensaver app. // Add future entries above this comment, in sync with enums.xml. // Update kMaxValue to the last value. - kMaxValue = kYouTube, + kMaxValue = kScreensaver, }; // The recorder will create a normal timer by default. Tests should provide a @@ -66,6 +74,11 @@ // ui::UserActivityObserver: void OnUserActivity(const ui::Event* event) override; + // wm::ActivationChangeObserver: + void OnWindowActivated(wm::ActivationChangeObserver::ActivationReason reason, + aura::Window* gained_active, + aura::Window* lost_active) override; + private: // Starts the timer for periodic sampling. void StartRecording(); @@ -77,10 +90,30 @@ // Emits histograms for recorded samples. void ReportSamples(); + // Indicates whether the specified app_id should be recorded for + // the unique-apps-launched stat. + bool ShouldRecordAppLaunch(const std::string& app_id); + + // Records the specified app_id's launch, subject to the + // restrictions of ShouldRecordAppLaunch(). + void RecordAppLaunch(const std::string& app_id); + + // Emits histograms for the number of unique apps launched. + void ReportUniqueAppsLaunched(); + // Stores samples as they are collected. Report to UMA if we see user // activity soon after. Guaranteed not to grow too large. std::vector<DemoModeApp> unreported_samples_; + // Indicates whether the unique-app-launch stats recording has been enabled. + bool unique_apps_launched_recording_enabled_ = false; + + // Tracks the ids of apps that have been launched in Demo Mode. + base::flat_set<std::string> unique_apps_launched_; + + // Used for subscribing to window activation events. + wm::ActivationClient* activation_client_ = nullptr; + // How many periods have elapsed since the last user activity. int periods_since_activity_ = 0; @@ -89,9 +122,14 @@ ScopedObserver<ui::UserActivityDetector, DemoSessionMetricsRecorder> observer_; + class UniqueAppsLaunchedArcPackageNameObserver; + + std::unique_ptr<UniqueAppsLaunchedArcPackageNameObserver> + unique_apps_arc_package_name_observer_; + DISALLOW_COPY_AND_ASSIGN(DemoSessionMetricsRecorder); }; } // namespace ash -#endif // ASH_METRICS_POINTER_METRICS_RECORDER_H_ +#endif // ASH_METRICS_DEMO_SESSION_METRICS_RECORDER_H_
diff --git a/ash/metrics/demo_session_metrics_recorder_unittest.cc b/ash/metrics/demo_session_metrics_recorder_unittest.cc index ad50a8d4..71a4628 100644 --- a/ash/metrics/demo_session_metrics_recorder_unittest.cc +++ b/ash/metrics/demo_session_metrics_recorder_unittest.cc
@@ -129,7 +129,8 @@ window->SetProperty( kShelfIDKey, new std::string(ShelfID(app_id, std::string()).Serialize())); - window->SetProperty(kArcPackageNameKey, new std::string(package_name)); + if (!package_name.empty()) + window->SetProperty(kArcPackageNameKey, new std::string(package_name)); return window; } @@ -445,5 +446,79 @@ histogram_tester_->ExpectTotalCount("DemoMode.ActiveApp", 0); } +TEST_F(DemoSessionMetricsRecorderTest, UniqueAppsLaunchedOnDeletion) { + // Activate each window twice. Despite activating each twice, + // the count should only be incremented once per unique app. + auto chrome_app_window = CreateChromeAppWindow(extension_misc::kCameraAppId); + wm::ActivateWindow(chrome_app_window.get()); + wm::DeactivateWindow(chrome_app_window.get()); + wm::ActivateWindow(chrome_app_window.get()); + + auto chrome_browser_window = + CreateChromeAppWindow(extension_misc::kChromeAppId); + wm::ActivateWindow(chrome_browser_window.get()); + wm::DeactivateWindow(chrome_browser_window.get()); + wm::ActivateWindow(chrome_browser_window.get()); + + auto arc_window_1 = CreateArcWindow("com.google.Photos"); + wm::ActivateWindow(arc_window_1.get()); + wm::DeactivateWindow(arc_window_1.get()); + wm::ActivateWindow(arc_window_1.get()); + + auto arc_window_2 = CreateArcWindow("com.google.Maps"); + wm::ActivateWindow(arc_window_2.get()); + wm::DeactivateWindow(arc_window_2.get()); + wm::ActivateWindow(arc_window_2.get()); + + // Popup windows shouldn't be counted at all. + auto popup_window = CreatePopupWindow(); + wm::ActivateWindow(popup_window.get()); + wm::DeactivateWindow(popup_window.get()); + wm::ActivateWindow(popup_window.get()); + + DeleteMetricsRecorder(); + + histogram_tester_->ExpectUniqueSample("DemoMode.UniqueAppsLaunched", 4, 1); +} + +TEST_F(DemoSessionMetricsRecorderTest, + NoUniqueAppsLaunchedOnMissingArcPackageName) { + // Create an ARC window with no package name set yet + auto arc_window_1 = CreateArcWindow(""); + wm::ActivateWindow(arc_window_1.get()); + + DeleteMetricsRecorder(); + + // There shuld be no unique apps reported if there was no package name. + histogram_tester_->ExpectUniqueSample("DemoMode.UniqueAppsLaunched", 0, 1); +} + +TEST_F(DemoSessionMetricsRecorderTest, + UniqueAppsLaunchedOnDelayedArcPackageName) { + // Create an ARC window with no package name set yet. + auto arc_window_1 = CreateArcWindow(""); + wm::ActivateWindow(arc_window_1.get()); + + // Set the package name after window creation/activation. + arc_window_1->SetProperty(kArcPackageNameKey, + new std::string("com.google.Photos")); + + auto arc_window_2 = CreateArcWindow("com.google.Maps"); + wm::ActivateWindow(arc_window_2.get()); + + DeleteMetricsRecorder(); + + // There should be 2 unique apps reported. + histogram_tester_->ExpectUniqueSample("DemoMode.UniqueAppsLaunched", 2, 1); +} + +TEST_F(DemoSessionMetricsRecorderTest, NoUniqueAppsLaunchedOnDeletion) { + DeleteMetricsRecorder(); + + // There should be no samples if the recorder is deleted with 0 unique apps + // launched. + histogram_tester_->ExpectUniqueSample("DemoMode.UniqueAppsLaunched", 0, 1); +} + } // namespace } // namespace ash
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index 735660b5..4adb466 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -158,6 +158,46 @@ output_name = "ash_public_cpp" } +source_set("manifest") { + sources = [ + "manifest.cc", + "manifest.h", + ] + + deps = [ + "//ash/public/interfaces:interfaces_internal", + "//base", + "//chromeos/services/multidevice_setup/public/mojom", + "//services/catalog/public/mojom", + "//services/content/public/mojom", + "//services/data_decoder/public/mojom", + "//services/device/public/mojom", + "//services/preferences/public/mojom", + "//services/service_manager/public/cpp", + "//services/service_manager/public/mojom", + "//services/viz/public/interfaces", + "//services/ws:manifest", + "//services/ws/public/mojom", + ] +} + +source_set("manifest_for_tests") { + testonly = true + + sources = [ + "test_manifest.cc", + "test_manifest.h", + ] + + deps = [ + ":manifest", + "//ash/public/interfaces:test_interfaces", + "//base", + "//services/service_manager/public/cpp", + "//services/service_manager/public/mojom", + ] +} + # Using a test service because the traits need to pass handles around. Revisit # this after Deserialize(Serialize()) API works with handles. mojom("test_interfaces") {
diff --git a/ash/public/cpp/DEPS b/ash/public/cpp/DEPS index dab1430..5465f0b 100644 --- a/ash/public/cpp/DEPS +++ b/ash/public/cpp/DEPS
@@ -1,5 +1,8 @@ include_rules = [ "+components/prefs", + "+services/catalog/public", + "+services/data_decoder/public", + "+services/device/public", "+skia/public/interfaces", "+ui/display", ]
diff --git a/ash/public/cpp/OWNERS b/ash/public/cpp/OWNERS index 09b138f0..978703ff 100644 --- a/ash/public/cpp/OWNERS +++ b/ash/public/cpp/OWNERS
@@ -1,3 +1,8 @@ +per-file manifest.cc=set noparent +per-file manifest.cc=file://ipc/SECURITY_OWNERS +per-file manifest.h=set noparent +per-file manifest.h=file://ipc/SECURITY_OWNERS + per-file *shelf*=file://ash/shelf/OWNERS per-file *.mojom=set noparent
diff --git a/ash/public/cpp/manifest.cc b/ash/public/cpp/manifest.cc new file mode 100644 index 0000000..03989db --- /dev/null +++ b/ash/public/cpp/manifest.cc
@@ -0,0 +1,134 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/public/cpp/manifest.h" + +#include "ash/public/interfaces/accelerator_controller.mojom.h" +#include "ash/public/interfaces/accessibility_controller.mojom.h" +#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h" +#include "ash/public/interfaces/app_list.mojom.h" +#include "ash/public/interfaces/ash_display_controller.mojom.h" +#include "ash/public/interfaces/ash_message_center_controller.mojom.h" +#include "ash/public/interfaces/assistant_controller.mojom.h" +#include "ash/public/interfaces/assistant_volume_control.mojom.h" +#include "ash/public/interfaces/cast_config.mojom.h" +#include "ash/public/interfaces/constants.mojom.h" +#include "ash/public/interfaces/contained_shell.mojom.h" +#include "ash/public/interfaces/cros_display_config.mojom.h" +#include "ash/public/interfaces/display_output_protection.mojom.h" +#include "ash/public/interfaces/docked_magnifier_controller.mojom.h" +#include "ash/public/interfaces/event_rewriter_controller.mojom.h" +#include "ash/public/interfaces/first_run_helper.mojom.h" +#include "ash/public/interfaces/highlighter_controller.mojom.h" +#include "ash/public/interfaces/ime_controller.mojom.h" +#include "ash/public/interfaces/keyboard_controller.mojom.h" +#include "ash/public/interfaces/locale.mojom.h" +#include "ash/public/interfaces/login_screen.mojom.h" +#include "ash/public/interfaces/media.mojom.h" +#include "ash/public/interfaces/new_window.mojom.h" +#include "ash/public/interfaces/night_light_controller.mojom.h" +#include "ash/public/interfaces/note_taking_controller.mojom.h" +#include "ash/public/interfaces/pref_connector.mojom.h" +#include "ash/public/interfaces/process_creation_time_recorder.mojom.h" +#include "ash/public/interfaces/session_controller.mojom.h" +#include "ash/public/interfaces/shelf.mojom.h" +#include "ash/public/interfaces/shutdown.mojom.h" +#include "ash/public/interfaces/split_view.mojom.h" +#include "ash/public/interfaces/system_tray.mojom.h" +#include "ash/public/interfaces/tablet_mode.mojom.h" +#include "ash/public/interfaces/tray_action.mojom.h" +#include "ash/public/interfaces/voice_interaction_controller.mojom.h" +#include "ash/public/interfaces/vpn_list.mojom.h" +#include "ash/public/interfaces/wallpaper.mojom.h" +#include "base/no_destructor.h" +#include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h" +#include "services/catalog/public/mojom/constants.mojom.h" +#include "services/content/public/mojom/constants.mojom.h" +#include "services/data_decoder/public/mojom/constants.mojom.h" +#include "services/device/public/mojom/constants.mojom.h" +#include "services/preferences/public/mojom/preferences.mojom.h" +#include "services/service_manager/public/cpp/manifest_builder.h" +#include "services/service_manager/public/mojom/service_factory.mojom.h" +#include "services/viz/public/interfaces/constants.mojom.h" +#include "services/ws/manifest.h" +#include "services/ws/public/mojom/constants.mojom.h" + +namespace ash { + +service_manager::Manifest& GetAmendmentForTesting() { + static base::NoDestructor<service_manager::Manifest> amendment; + return *amendment; +} + +const service_manager::Manifest& GetManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .WithServiceName(mojom::kServiceName) + .WithDisplayName("Ash Window Manager and Shell") + .WithOptions(service_manager::ManifestOptionsBuilder() + .WithSandboxType("none") + .WithInstanceSharingPolicy( + service_manager::Manifest:: + InstanceSharingPolicy::kSingleton) + .Build()) + .ExposeCapability("service_manager:service_factory", + service_manager::Manifest::InterfaceList< + service_manager::mojom::ServiceFactory>()) + .ExposeCapability( + "system_ui", + service_manager::Manifest::InterfaceList< + mojom::AcceleratorController, mojom::AccessibilityController, + mojom::AccessibilityFocusRingController, + mojom::AppListController, mojom::AshMessageCenterController, + mojom::AssistantAlarmTimerController, + mojom::AssistantController, + mojom::AssistantNotificationController, + mojom::AssistantScreenContextController, + mojom::AssistantSetupController, + mojom::AssistantVolumeControl, mojom::CastConfig, + mojom::ContainedShellController, + mojom::CrosDisplayConfigController, + mojom::DockedMagnifierController, + mojom::EventRewriterController, mojom::FirstRunHelper, + mojom::HighlighterController, mojom::ImeController, + mojom::KeyboardController, mojom::LocaleUpdateController, + mojom::LoginScreen, mojom::MediaController, + mojom::NewWindowController, mojom::NightLightController, + mojom::NoteTakingController, + mojom::ProcessCreationTimeRecorder, mojom::SessionController, + mojom::ShelfController, mojom::ShutdownController, + mojom::SplitViewController, mojom::SystemTray, + mojom::TabletModeController, mojom::TrayAction, + mojom::VoiceInteractionController, mojom::VpnList, + mojom::WallpaperController>()) + .ExposeCapability("display", service_manager::Manifest::InterfaceList< + mojom::AshDisplayController, + mojom::DisplayOutputProtection>()) + .RequireCapability("*", "accessibility") + .RequireCapability("*", "app") + .RequireCapability(prefs::mojom::kLocalStateServiceName, + "pref_client") + .RequireCapability(content::mojom::kServiceName, "navigation") + .RequireCapability(data_decoder::mojom::kServiceName, "image_decoder") + .RequireCapability(mojom::kPrefConnectorServiceName, "pref_connector") + .RequireCapability(viz::mojom::kVizServiceName, "viz_host") + .RequireCapability(catalog::mojom::kServiceName, "directory") + .RequireCapability(ws::mojom::kServiceName, "ozone") + .RequireCapability(ws::mojom::kServiceName, "window_manager") + .RequireCapability(device::mojom::kServiceName, + "device:bluetooth_system") + .RequireCapability(device::mojom::kServiceName, "device:fingerprint") + .RequireCapability(chromeos::multidevice_setup::mojom::kServiceName, + "multidevice_setup") + .PackageService(ui::GetManifest()) + .Build() + .Amend(GetAmendmentForTesting())}; + return *manifest; +} + +void AmendManifestForTesting(const service_manager::Manifest& amendment) { + GetAmendmentForTesting() = amendment; +} + +} // namespace ash
diff --git a/ash/public/cpp/manifest.h b/ash/public/cpp/manifest.h new file mode 100644 index 0000000..124306b --- /dev/null +++ b/ash/public/cpp/manifest.h
@@ -0,0 +1,25 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_PUBLIC_CPP_MANIFEST_H_ +#define ASH_PUBLIC_CPP_MANIFEST_H_ + +#include "services/service_manager/public/cpp/manifest.h" + +namespace ash { + +// Returns the service manifest used for the ash service in a production +// environment. +const service_manager::Manifest& GetManifest(); + +// Sets a global overlay with which to amend the manifest returned by +// |GetManifest()|. Must be called before the first call to |GetManifest()| in +// order to have any effect. This is useful for e.g. browser test environments +// where |GetManifest()| is called by production code and the test environment +// needs to affect its behavior with test-only dependencies. +void AmendManifestForTesting(const service_manager::Manifest& amendment); + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_MANIFEST_H_
diff --git a/ash/public/cpp/test_manifest.cc b/ash/public/cpp/test_manifest.cc new file mode 100644 index 0000000..6bacb0f1e0 --- /dev/null +++ b/ash/public/cpp/test_manifest.cc
@@ -0,0 +1,31 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/public/cpp/test_manifest.h" + +#include "ash/public/interfaces/login_screen_test_api.test-mojom.h" +#include "ash/public/interfaces/shelf_test_api.test-mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" +#include "ash/public/interfaces/status_area_widget_test_api.test-mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" +#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom.h" +#include "base/no_destructor.h" +#include "services/service_manager/public/cpp/manifest_builder.h" + +namespace ash { + +const service_manager::Manifest& GetManifestOverlayForTesting() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .ExposeCapability( + "test", service_manager::Manifest::InterfaceList< + mojom::LoginScreenTestApi, mojom::ShelfTestApi, + mojom::ShellTestApi, mojom::StatusAreaWidgetTestApi, + mojom::SystemTrayTestApi, + mojom::TimeToFirstPresentRecorderTestApi>()) + .Build()}; + return *manifest; +} + +} // namespace ash
diff --git a/ash/public/cpp/test_manifest.h b/ash/public/cpp/test_manifest.h new file mode 100644 index 0000000..d67a307 --- /dev/null +++ b/ash/public/cpp/test_manifest.h
@@ -0,0 +1,21 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_PUBLIC_CPP_TEST_MANIFEST_H_ +#define ASH_PUBLIC_CPP_TEST_MANIFEST_H_ + +#include "services/service_manager/public/cpp/manifest.h" + +namespace ash { + +// A manifest for the ash service with additional capabilities exposed for +// testing APIs. This can be amended to the normal manifest by passing it to +// ash::AmendManifestForTesting (in manifest.h) in a test environment before +// initializing the Service Manager, or by explicitly a mending a copy of the +// normal manifest (in e.g. unit tests using TestServiceManager). +const service_manager::Manifest& GetManifestOverlayForTesting(); + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_MANIFEST_H_
diff --git a/ash/public/interfaces/accessibility_focus_ring_controller.mojom b/ash/public/interfaces/accessibility_focus_ring_controller.mojom index 3cd96ce1..ae4ff29 100644 --- a/ash/public/interfaces/accessibility_focus_ring_controller.mojom +++ b/ash/public/interfaces/accessibility_focus_ring_controller.mojom
@@ -38,4 +38,10 @@ // Hides highlight on screen. // TODO(katie): Add |caller_id| to highlights as well. HideHighlights(); + + // Enables double focus rings and sets the second color for the given caller. + EnableDoubleFocusRing(uint32 skcolor, string caller_id); + + // Disables double focus rings for the given caller. + DisableDoubleFocusRing(string caller_id); };
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc index 4914a797..4aa542ee 100644 --- a/ash/rotator/screen_rotation_animator.cc +++ b/ash/rotator/screen_rotation_animator.cc
@@ -27,6 +27,7 @@ #include "ui/compositor/layer_animator.h" #include "ui/compositor/layer_owner.h" #include "ui/compositor/layer_tree_owner.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/display/display.h" #include "ui/display/manager/display_manager.h" #include "ui/display/manager/managed_display_info.h" @@ -292,6 +293,12 @@ old_layer_tree_owner_ = CopyLayerTree(std::move(result)); AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root()); + + // TODO(oshima): We need a better way to control animation and other + // activities during system wide animation. + animation_scale_mode_ = + std::make_unique<ui::ScopedAnimationDurationScaleMode>( + ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); SetRotation(rotation_request->display_id, rotation_request->old_rotation, rotation_request->new_rotation, rotation_request->source); @@ -304,6 +311,7 @@ void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation( std::unique_ptr<ScreenRotationRequest> rotation_request, std::unique_ptr<viz::CopyOutputResult> result) { + animation_scale_mode_.reset(); if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) return; // In the following cases, abort animation:
diff --git a/ash/rotator/screen_rotation_animator.h b/ash/rotator/screen_rotation_animator.h index d17e454..d11aa37 100644 --- a/ash/rotator/screen_rotation_animator.h +++ b/ash/rotator/screen_rotation_animator.h
@@ -6,6 +6,7 @@ #define ASH_ROTATOR_SCREEN_ROTATION_ANIMATOR_H_ #include <stdint.h> +#include <memory> #include "ash/ash_export.h" #include "ash/display/display_configuration_controller.h" @@ -28,6 +29,7 @@ namespace ui { class AnimationMetricsReporter; class LayerTreeOwner; +class ScopedAnimationDurationScaleMode; } // namespace ui namespace ash { @@ -189,6 +191,7 @@ std::unique_ptr<ScreenRotationRequest> last_pending_request_; base::Optional<ScreenRotationRequest> current_async_rotation_request_; display::Display::Rotation target_rotation_ = display::Display::ROTATE_0; + std::unique_ptr<ui::ScopedAnimationDurationScaleMode> animation_scale_mode_; base::WeakPtrFactory<ScreenRotationAnimator> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimator);
diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc index d27fa6fb..b813596 100644 --- a/ash/shelf/shelf_widget_unittest.cc +++ b/ash/shelf/shelf_widget_unittest.cc
@@ -521,10 +521,7 @@ keyboard::switches::kEnableVirtualKeyboard); AshTestBase::SetUp(); ASSERT_TRUE(keyboard::IsKeyboardEnabled()); - - keyboard_controller()->LoadKeyboardWindowInBackground(); - // Wait for the keyboard window to load. - base::RunLoop().RunUntilIdle(); + keyboard::test::WaitUntilLoaded(); // These tests only apply to the floating virtual keyboard, as it is the // only case where both the virtual keyboard and the shelf are visible.
diff --git a/ash/shell/content/client/shell_content_browser_client.cc b/ash/shell/content/client/shell_content_browser_client.cc index ce8fe44..5b289a8d 100644 --- a/ash/shell/content/client/shell_content_browser_client.cc +++ b/ash/shell/content/client/shell_content_browser_client.cc
@@ -13,7 +13,8 @@ #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h" #include "ash/components/tap_visualizer/manifest.h" #include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" -#include "ash/manifest.h" +#include "ash/public/cpp/manifest.h" +#include "ash/public/cpp/test_manifest.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/shell.h" @@ -59,7 +60,8 @@ const service_manager::Manifest& GetAshShellPackagedServicesOverlayManifest() { static base::NoDestructor<service_manager::Manifest> manifest{ service_manager::ManifestBuilder() - .PackageService(ash::GetManifest()) + .PackageService(service_manager::Manifest(ash::GetManifest()) + .Amend(ash::GetManifestOverlayForTesting())) .PackageService(quick_launch_app::GetManifest()) .PackageService(shortcut_viewer_app::GetManifest()) .PackageService(tap_visualizer_app::GetManifest())
diff --git a/ash/system/cast/tray_cast.cc b/ash/system/cast/tray_cast.cc index 47baa65..4644ee4 100644 --- a/ash/system/cast/tray_cast.cc +++ b/ash/system/cast/tray_cast.cc
@@ -80,16 +80,6 @@ CastDetailedView::~CastDetailedView() = default; -void CastDetailedView::SimulateViewClickedForTest( - const std::string& receiver_id) { - for (const auto& it : view_to_sink_map_) { - if (it.second->id == receiver_id) { - HandleViewClicked(it.first); - break; - } - } -} - void CastDetailedView::CreateItems() { CreateScrollableList(); CreateTitleRow(IDS_ASH_STATUS_TRAY_CAST);
diff --git a/ash/system/cast/tray_cast.h b/ash/system/cast/tray_cast.h index d82f3f7..0803d80 100644 --- a/ash/system/cast/tray_cast.h +++ b/ash/system/cast/tray_cast.h
@@ -25,10 +25,6 @@ const std::vector<mojom::SinkAndRoutePtr>& sinks_and_routes); ~CastDetailedView() override; - // Makes the detail view think the view associated with the given receiver_id - // was clicked. This will start a cast. - void SimulateViewClickedForTest(const std::string& receiver_id); - // Updates the list of available receivers. void UpdateReceiverList( const std::vector<mojom::SinkAndRoutePtr>& sinks_routes);
diff --git a/ash/system/screen_layout_observer.cc b/ash/system/screen_layout_observer.cc index 0d950d3..2d724820 100644 --- a/ash/system/screen_layout_observer.cc +++ b/ash/system/screen_layout_observer.cc
@@ -411,39 +411,9 @@ bool ScreenLayoutObserver::GetExitMirrorModeMessage( base::string16* out_message, base::string16* out_additional_message) { - if (GetDisplayManager()->is_multi_mirroring_enabled()) { - *out_message = - l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT); - return true; - } - switch (current_display_mode_) { - case DisplayMode::EXTENDED_3_PLUS: - // Mirror mode was turned off due to having more than two displays. - // Show a message that mirror mode for 3+ displays is not supported. - *out_message = - l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED); - return true; - - case DisplayMode::DOCKED: - // Handle disabling mirror mode as a result of going to docked mode - // when we only have a single display (this means we actually have two - // physical displays, one of which is the internal display, but they - // were in mirror mode, and hence considered as one. Closing the - // internal display disables mirror mode and we still have a single - // active display). - // Falls through. - case DisplayMode::SINGLE: - // We're exiting mirror mode because we removed one of the two - // displays. - *out_message = - l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT); - return true; - - default: - // Mirror mode was turned off; other messages should be shown e.g. - // extended mode is on, ... etc. - return false; - } + *out_message = + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT); + return true; } } // namespace ash
diff --git a/ash/system/screen_layout_observer_unittest.cc b/ash/system/screen_layout_observer_unittest.cc index dd44960..e5ec071c 100644 --- a/ash/system/screen_layout_observer_unittest.cc +++ b/ash/system/screen_layout_observer_unittest.cc
@@ -128,34 +128,7 @@ return nullptr; } -class ScreenLayoutObserverTestMultiMirroring - : public ScreenLayoutObserverTest, - public testing::WithParamInterface<bool> { - public: - ScreenLayoutObserverTestMultiMirroring() = default; - ~ScreenLayoutObserverTestMultiMirroring() override = default; - - protected: - void SetUp() override { - bool should_disable_multi_mirroring = GetParam(); - if (should_disable_multi_mirroring) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - ::switches::kDisableMultiMirroring); - } - ScreenLayoutObserverTest::SetUp(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(ScreenLayoutObserverTestMultiMirroring); -}; - -// Instantiate the boolean which is used to enable/disable multi-mirroring in -// the parameterized tests. -INSTANTIATE_TEST_CASE_P(, - ScreenLayoutObserverTestMultiMirroring, - testing::Bool()); - -TEST_P(ScreenLayoutObserverTestMultiMirroring, DisplayNotifications) { +TEST_F(ScreenLayoutObserverTest, DisplayNotifications) { Shell::Get()->screen_layout_observer()->set_show_notifications_for_testing( true); @@ -235,15 +208,8 @@ // Turn off mirror mode. CloseNotification(); display_manager()->SetMirrorMode(display::MirrorMode::kOff, base::nullopt); - if (display_manager()->is_multi_mirroring_enabled()) { - EXPECT_EQ( - l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), - GetDisplayNotificationText()); - } else { - EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, - GetSecondDisplayName()), - GetDisplayNotificationText()); - } + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), + GetDisplayNotificationText()); EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); // Rotate the second. @@ -395,37 +361,6 @@ GetDisplayNotificationText()); } -// TODO(crbug.com/774795) Remove this test when multi mirroring is enabled by -// default. -// Tests that exiting mirror mode because of adding a third display shows the -// correct "3+ displays mirror mode is not supported" message. -TEST_P(ScreenLayoutObserverTestMultiMirroring, - ExitMirrorModeBecauseOfThirdDisplayMessage) { - if (display_manager()->is_multi_mirroring_enabled()) { - // This test is not neccessary when mirroring across 3+ displays is - // supported. - return; - } - Shell::Get()->screen_layout_observer()->set_show_notifications_for_testing( - true); - UpdateDisplay("400x400,200x200"); - display::Display::SetInternalDisplayId( - display_manager()->GetSecondaryDisplay().id()); - - // Mirroring. - UpdateDisplay("400x400,200x200"); - display_manager()->SetMirrorMode(display::MirrorMode::kNormal, base::nullopt); - EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, - GetMirroringDisplayNames()), - GetDisplayNotificationText()); - - // Adding a third display. Mirror mode for 3+ displays is not supported. - CloseNotification(); - UpdateDisplay("400x400,200x200,100x100"); - EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED), - GetDisplayNotificationText()); -} - // Special case: tests that exiting mirror mode by removing a display shows the // correct message. TEST_F(ScreenLayoutObserverTest,
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc index 1457fa9c..64f3de5 100644 --- a/ash/system/status_area_widget_unittest.cc +++ b/ash/system/status_area_widget_unittest.cc
@@ -250,10 +250,7 @@ keyboard::switches::kEnableVirtualKeyboard); AshTestBase::SetUp(); ASSERT_TRUE(keyboard::IsKeyboardEnabled()); - - keyboard_controller()->LoadKeyboardWindowInBackground(); - // Wait for the keyboard window to load. - base::RunLoop().RunUntilIdle(); + keyboard::test::WaitUntilLoaded(); // These tests only apply to the floating virtual keyboard, as it is the // only case where both the virtual keyboard and the shelf are visible.
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc b/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc index d5c13c0..811e5fee 100644 --- a/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc +++ b/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc
@@ -23,12 +23,10 @@ keyboard::switches::kEnableVirtualKeyboard); AshTestBase::SetUp(); ASSERT_TRUE(keyboard::IsKeyboardEnabled()); + keyboard::test::WaitUntilLoaded(); // These tests only apply to the floating virtual keyboard, as it is the // only case where both the virtual keyboard and the shelf are visible. - keyboard_controller()->LoadKeyboardWindowInBackground(); - // Wait for the keyboard window to load. - base::RunLoop().RunUntilIdle(); keyboard_controller()->SetContainerType( keyboard::mojom::ContainerType::kFloating, base::nullopt, base::DoNothing());
diff --git a/ash/utility/screenshot_controller.cc b/ash/utility/screenshot_controller.cc index ef07130..7941420 100644 --- a/ash/utility/screenshot_controller.cc +++ b/ash/utility/screenshot_controller.cc
@@ -24,6 +24,7 @@ #include "ui/events/event_handler.h" #include "ui/gfx/canvas.h" #include "ui/views/widget/widget.h" +#include "ui/wm/core/accelerator_filter.h" #include "ui/wm/core/cursor_manager.h" namespace ash { @@ -464,8 +465,7 @@ // Key event is blocked. So have to record current accelerator here. if (event->stopped_propagation()) { - // Filter accelerators in the same way with AcceleratorFilter::OnKeyEvent. - if (event->is_char() || !event->target()) + if (::wm::AcceleratorFilter::ShouldFilter(event)) return; ui::Accelerator accelerator(*event);
diff --git a/ash/wm/overview/overview_controller_unittest.cc b/ash/wm/overview/overview_controller_unittest.cc index a834e99..c1f8be66 100644 --- a/ash/wm/overview/overview_controller_unittest.cc +++ b/ash/wm/overview/overview_controller_unittest.cc
@@ -378,8 +378,8 @@ TabletModeControllerTestApi().EnterTabletMode(); base::RunLoop().RunUntilIdle(); ASSERT_TRUE(keyboard::IsKeyboardEnabled()); + keyboard::test::WaitUntilLoaded(); - keyboard_controller()->LoadKeyboardWindowInBackground(); keyboard_controller()->GetKeyboardWindow()->SetBounds( keyboard::KeyboardBoundsFromRootBounds( Shell::GetPrimaryRootWindow()->bounds(), 100));
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index fa59fd9..8357e06c 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -432,7 +432,7 @@ bool animate, OverviewItem* ignored_item, OverviewSession::OverviewTransition transition) { - if (!overview_session_) + if (!overview_session_ || suspend_reposition_) return; DCHECK_NE(transition, OverviewSession::OverviewTransition::kExit);
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h index 54f7cea8..b2cbe74 100644 --- a/ash/wm/overview/overview_grid.h +++ b/ash/wm/overview/overview_grid.h
@@ -237,6 +237,8 @@ return drop_target_widget_.get(); } + void set_suspend_reposition(bool value) { suspend_reposition_ = value; } + private: class ShieldView; class TargetWindowObserver; @@ -371,6 +373,10 @@ // non-empty if a nudge is in progress. std::vector<NudgeData> nudge_data_; + // True to skip |PositionWindows()|. Used to avoid O(n^2) layout + // when reposition windows in tablet overview mode. + bool suspend_reposition_ = false; + DISALLOW_COPY_AND_ASSIGN(OverviewGrid); };
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc index bfdfeeb..8159a59 100644 --- a/ash/wm/overview/overview_session.cc +++ b/ash/wm/overview/overview_session.cc
@@ -646,6 +646,16 @@ return nullptr; } +void OverviewSession::SuspendReposition() { + for (auto& grid : grid_list_) + grid->set_suspend_reposition(true); +} + +void OverviewSession::ResumeReposition() { + for (auto& grid : grid_list_) + grid->set_suspend_reposition(false); +} + void OverviewSession::OnDisplayRemoved(const display::Display& display) { // TODO(flackr): Keep window selection active on remaining displays. CancelSelection(); @@ -755,7 +765,7 @@ SelectWindow(grid_list_[selected_grid_index_]->SelectedWindow()); break; default: - break; + return; } event->SetHandled();
diff --git a/ash/wm/overview/overview_session.h b/ash/wm/overview/overview_session.h index d1f1c745..7f21b8e7 100644 --- a/ash/wm/overview/overview_session.h +++ b/ash/wm/overview/overview_session.h
@@ -221,6 +221,10 @@ // Gets the window which keeps focus for the duration of overview mode. aura::Window* GetOverviewFocusWindow(); + // Suspends/Resumes window re-positiong in overview. + void SuspendReposition(); + void ResumeReposition(); + OverviewDelegate* delegate() { return delegate_; } SplitViewDragIndicators* split_view_drag_indicators() {
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 92d92bc00..711d078 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -6,6 +6,8 @@ #include <memory> #include <vector> +#include "ash/accelerators/accelerator_controller.h" +#include "ash/accelerators/exit_warning_handler.h" #include "ash/accessibility/accessibility_controller.h" #include "ash/accessibility/test_accessibility_controller_client.h" #include "ash/app_list/app_list_controller_impl.h" @@ -321,6 +323,11 @@ return !!item->transform_window_.mask_; } + static void StubForTest(ExitWarningHandler* ewh) { + ewh->stub_timer_for_test_ = true; + } + static bool is_ui_shown(ExitWarningHandler* ewh) { return !!ewh->widget_; } + private: std::unique_ptr<ShelfViewTestAPI> shelf_view_test_api_; @@ -1204,6 +1211,22 @@ EXPECT_EQ(GetSelectedWindow(), overview_windows[0]->GetWindow()); } +TEST_F(OverviewSessionTest, AcceleratorInOverviewSession) { + ToggleOverview(); + auto* accelerator_controller = Shell::Get()->accelerator_controller(); + auto* ewh = accelerator_controller->GetExitWarningHandlerForTest(); + ASSERT_TRUE(ewh); + StubForTest(ewh); + EXPECT_FALSE(is_ui_shown(ewh)); + + ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow()); + event_generator.PressKey(ui::VKEY_Q, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN); + event_generator.ReleaseKey(ui::VKEY_Q, + ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN); + + EXPECT_TRUE(is_ui_shown(ewh)); +} + // Tests that pressing Ctrl+W while a window is selected in overview closes it. TEST_F(OverviewSessionTest, CloseWindowWithKey) { std::unique_ptr<views::Widget> widget(CreateTestWidget());
diff --git a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc index fdf6d6f5..8cec93b 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
@@ -12,6 +12,7 @@ #include "ash/accelerometer/accelerometer_types.h" #include "ash/app_list/app_list_controller_impl.h" #include "ash/display/screen_orientation_controller.h" +#include "ash/public/cpp/app_types.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/tablet_mode.h" #include "ash/shell.h" @@ -27,6 +28,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_power_manager_client.h" #include "services/ws/public/cpp/input_devices/input_device_client_test_api.h" +#include "ui/aura/client/aura_constants.h" #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" #include "ui/display/test/display_manager_test_api.h" @@ -1138,6 +1140,47 @@ EXPECT_FALSE(Shell::Get()->overview_controller()->IsSelecting()); } +// Test that if before tablet mode, the active window is an ARC window snapped +// on the left and the previous window is snapped on the right, then split view +// is not activated. +TEST_F(TabletModeControllerTest, + StartTabletActiveArcLeftSnapPreviousRightSnap) { + SplitViewController* split_view_controller = + Shell::Get()->split_view_controller(); + std::unique_ptr<aura::Window> left_window = CreateDesktopWindowSnappedLeft(); + left_window->SetProperty(aura::client::kAppType, + static_cast<int>(AppType::ARC_APP)); + std::unique_ptr<aura::Window> right_window = + CreateDesktopWindowSnappedRight(); + ::wm::ActivateWindow(left_window.get()); + tablet_mode_controller()->EnableTabletModeWindowManager(true); + EXPECT_EQ(SplitViewController::NO_SNAP, split_view_controller->state()); + EXPECT_FALSE(Shell::Get()->overview_controller()->IsSelecting()); +} + +// Test that if before tablet mode, the active window is snapped on the left, +// the previous window is an ARC window snapped on the right, and the third +// window is snapped on the right (just to test that it is ignored after the ARC +// window), then split view is activated with the active window on the left. +TEST_F(TabletModeControllerTest, + StartTabletActiveLeftSnapPreviousArcRightSnap) { + SplitViewController* split_view_controller = + Shell::Get()->split_view_controller(); + std::unique_ptr<aura::Window> left_window = CreateDesktopWindowSnappedLeft(); + std::unique_ptr<aura::Window> right_window = + CreateDesktopWindowSnappedRight(); + right_window->SetProperty(aura::client::kAppType, + static_cast<int>(AppType::ARC_APP)); + std::unique_ptr<aura::Window> extra_right_window = + CreateDesktopWindowSnappedRight(); + ::wm::ActivateWindow(right_window.get()); + ::wm::ActivateWindow(left_window.get()); + tablet_mode_controller()->EnableTabletModeWindowManager(true); + EXPECT_EQ(SplitViewController::LEFT_SNAPPED, split_view_controller->state()); + EXPECT_EQ(left_window.get(), split_view_controller->left_window()); + EXPECT_TRUE(Shell::Get()->overview_controller()->IsSelecting()); +} + // Test that if overview is triggered on entering tablet mode, then the app list // can still be successfully shown and actually seen. TEST_F(TabletModeControllerTest, AppListWorksAfterEnteringTabletForOverview) {
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.cc b/ash/wm/tablet_mode/tablet_mode_window_manager.cc index 52978d4e..daa265a8 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
@@ -6,12 +6,14 @@ #include <memory> +#include "ash/public/cpp/app_types.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" #include "ash/shell.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/overview_controller.h" +#include "ash/wm/overview/overview_session.h" #include "ash/wm/tablet_mode/scoped_skip_user_session_blocked_check.h" #include "ash/wm/tablet_mode/tablet_mode_backdrop_delegate_impl.h" #include "ash/wm/tablet_mode/tablet_mode_event_handler.h" @@ -202,11 +204,18 @@ ui::PropertyChangeReason reason) { if (!IsContainerWindow(window)) return; + + auto* session = Shell::Get()->overview_controller()->overview_session(); + if (session) + session->SuspendReposition(); + // Reposition all non maximizeable windows. for (auto& pair : window_state_map_) { pair.second->UpdateWindowPosition(wm::GetWindowState(pair.first), /*animate=*/false); } + if (session) + session->ResumeReposition(); } void TabletModeWindowManager::OnWindowVisibilityChanged(aura::Window* window, @@ -299,9 +308,11 @@ const mojom::WindowStateType active_window_state_type = wm::GetWindowState(windows[0])->GetStateType(); - // If the active window is not snapped, then just maximize all windows. - if (active_window_state_type != mojom::WindowStateType::LEFT_SNAPPED && - active_window_state_type != mojom::WindowStateType::RIGHT_SNAPPED) { + // If the active window is ARC or not snapped, then just maximize all windows. + if (static_cast<ash::AppType>(windows[0]->GetProperty( + aura::client::kAppType)) == AppType::ARC_APP || + (active_window_state_type != mojom::WindowStateType::LEFT_SNAPPED && + active_window_state_type != mojom::WindowStateType::RIGHT_SNAPPED)) { for (auto* window : windows) MaximizeAndTrackWindow(window); return; @@ -310,6 +321,9 @@ // The snapped active window will be represented by split view, which will be // activated after maximizing all windows. The split view layout is decided // here by examining window states before all those states become maximized. + const bool prev_win_not_arc = + windows.size() > 1u && static_cast<ash::AppType>(windows[1]->GetProperty( + aura::client::kAppType)) != AppType::ARC_APP; SplitViewController::SnapPosition curr_win_snap_pos = SplitViewController::NONE; SplitViewController::SnapPosition prev_win_snap_pos = @@ -318,8 +332,8 @@ // The active window snapped on the left shall go there in split view. curr_win_snap_pos = SplitViewController::LEFT; - if (windows.size() > 1u && wm::GetWindowState(windows[1])->GetStateType() == - mojom::WindowStateType::RIGHT_SNAPPED) { + if (prev_win_not_arc && wm::GetWindowState(windows[1])->GetStateType() == + mojom::WindowStateType::RIGHT_SNAPPED) { // The previous window snapped on the right shall go there in split view. prev_win_snap_pos = SplitViewController::RIGHT; } @@ -329,8 +343,8 @@ // The active window snapped on the right shall go there in split view. curr_win_snap_pos = SplitViewController::RIGHT; - if (windows.size() > 1u && wm::GetWindowState(windows[1])->GetStateType() == - mojom::WindowStateType::LEFT_SNAPPED) { + if (prev_win_not_arc && wm::GetWindowState(windows[1])->GetStateType() == + mojom::WindowStateType::LEFT_SNAPPED) { // The previous window snapped on the left shall go there in split view. prev_win_snap_pos = SplitViewController::LEFT; }
diff --git a/base/android/scoped_hardware_buffer_fence_sync.h b/base/android/scoped_hardware_buffer_fence_sync.h index 74e0499b..2bd2cfb 100644 --- a/base/android/scoped_hardware_buffer_fence_sync.h +++ b/base/android/scoped_hardware_buffer_fence_sync.h
@@ -26,6 +26,12 @@ ScopedHardwareBufferHandle TakeBuffer(); ScopedFD TakeFence(); + // Provides fence which is signaled when the reads for this buffer are done + // and it can be reused. The method assumes a current GLContext and will only + // synchronize the reads with this context. + // Must only be called once. + virtual void SetReadFence(base::ScopedFD fence_fd) = 0; + private: ScopedHardwareBufferHandle handle_; ScopedFD fence_fd_;
diff --git a/base/files/file_descriptor_watcher_posix_unittest.cc b/base/files/file_descriptor_watcher_posix_unittest.cc index a2f657f..b2191e35 100644 --- a/base/files/file_descriptor_watcher_posix_unittest.cc +++ b/base/files/file_descriptor_watcher_posix_unittest.cc
@@ -301,12 +301,12 @@ controller = nullptr; } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MessagePumpForIOOnMainThread, FileDescriptorWatcherTest, ::testing::Values( FileDescriptorWatcherTestType::MESSAGE_PUMP_FOR_IO_ON_MAIN_THREAD)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MessagePumpForIOOnOtherThread, FileDescriptorWatcherTest, ::testing::Values(
diff --git a/base/memory/platform_shared_memory_region_fuchsia.cc b/base/memory/platform_shared_memory_region_fuchsia.cc index 3fcf584..049d8cf2a 100644 --- a/base/memory/platform_shared_memory_region_fuchsia.cc +++ b/base/memory/platform_shared_memory_region_fuchsia.cc
@@ -112,9 +112,9 @@ void** memory, size_t* mapped_size) const { uintptr_t addr; - zx_vm_option_t options = ZX_VM_REQUIRE_NON_RESIZABLE | ZX_VM_FLAG_PERM_READ; + zx_vm_option_t options = ZX_VM_REQUIRE_NON_RESIZABLE | ZX_VM_PERM_READ; if (mode_ != Mode::kReadOnly) - options |= ZX_VM_FLAG_PERM_WRITE; + options |= ZX_VM_PERM_WRITE; zx_status_t status = zx::vmar::root_self()->map( /*vmar_offset=*/0, handle_, offset, size, options, &addr); if (status != ZX_OK) {
diff --git a/base/memory/platform_shared_memory_region_unittest.cc b/base/memory/platform_shared_memory_region_unittest.cc index 13a82e9..3193993 100644 --- a/base/memory/platform_shared_memory_region_unittest.cc +++ b/base/memory/platform_shared_memory_region_unittest.cc
@@ -272,9 +272,9 @@ DWORD old_protection; return VirtualProtect(addr, len, PAGE_READWRITE, &old_protection); #elif defined(OS_FUCHSIA) - zx_status_t status = zx::vmar::root_self()->protect( - reinterpret_cast<uintptr_t>(addr), len, - ZX_VM_FLAG_PERM_READ | ZX_VM_FLAG_PERM_WRITE); + zx_status_t status = + zx::vmar::root_self()->protect(reinterpret_cast<uintptr_t>(addr), len, + ZX_VM_PERM_READ | ZX_VM_PERM_WRITE); return status == ZX_OK; #else return false;
diff --git a/base/memory/shared_memory_fuchsia.cc b/base/memory/shared_memory_fuchsia.cc index e27752d..9cef989 100644 --- a/base/memory/shared_memory_fuchsia.cc +++ b/base/memory/shared_memory_fuchsia.cc
@@ -85,9 +85,9 @@ if (memory_) return false; - zx_vm_option_t options = ZX_VM_REQUIRE_NON_RESIZABLE | ZX_VM_FLAG_PERM_READ; + zx_vm_option_t options = ZX_VM_REQUIRE_NON_RESIZABLE | ZX_VM_PERM_READ; if (!read_only_) - options |= ZX_VM_FLAG_PERM_WRITE; + options |= ZX_VM_PERM_WRITE; uintptr_t addr; zx_status_t status = zx::vmar::root_self()->map( /*vmar_offset=*/0, *zx::unowned_vmo(shm_.GetHandle()), offset, bytes,
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc index ae6bcd2..f958c264 100644 --- a/base/memory/shared_memory_unittest.cc +++ b/base/memory/shared_memory_unittest.cc
@@ -416,7 +416,7 @@ uintptr_t addr; EXPECT_NE(ZX_OK, zx::vmar::root_self()->map( 0, *zx::unowned_vmo(handle.GetHandle()), 0, - contents.size(), ZX_VM_FLAG_PERM_WRITE, &addr)) + contents.size(), ZX_VM_PERM_WRITE, &addr)) << "Shouldn't be able to map as writable."; zx::vmo duped_handle;
diff --git a/base/message_loop/message_loop_perftest.cc b/base/message_loop/message_loop_perftest.cc index 867e8fe..b45db66b 100644 --- a/base/message_loop/message_loop_perftest.cc +++ b/base/message_loop/message_loop_perftest.cc
@@ -247,8 +247,8 @@ "us/task", true); } -INSTANTIATE_TEST_CASE_P(, - MessageLoopPerfTest, - ::testing::Values(1, 5, 10), - MessageLoopPerfTest::ParamInfoToString); +INSTANTIATE_TEST_SUITE_P(, + MessageLoopPerfTest, + ::testing::Values(1, 5, 10), + MessageLoopPerfTest::ParamInfoToString); } // namespace base
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc index c766cc2f..20d07a280 100644 --- a/base/message_loop/message_loop_unittest.cc +++ b/base/message_loop/message_loop_unittest.cc
@@ -1564,7 +1564,7 @@ EXPECT_TRUE(loop->IsIdleForTesting()); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( , MessageLoopTypedTest, ::testing::Values(TestType{MessageLoop::TYPE_DEFAULT,
diff --git a/base/message_loop/message_pump_unittest.cc b/base/message_loop/message_pump_unittest.cc index 66bd710..14250f0 100644 --- a/base/message_loop/message_pump_unittest.cc +++ b/base/message_loop/message_pump_unittest.cc
@@ -165,11 +165,11 @@ message_pump_->Run(&delegate); } -INSTANTIATE_TEST_CASE_P(, - MessagePumpTest, - ::testing::Values(MessageLoop::TYPE_DEFAULT, - MessageLoop::TYPE_UI, - MessageLoop::TYPE_IO)); +INSTANTIATE_TEST_SUITE_P(, + MessagePumpTest, + ::testing::Values(MessageLoop::TYPE_DEFAULT, + MessageLoop::TYPE_UI, + MessageLoop::TYPE_IO)); } // namespace } // namespace base \ No newline at end of file
diff --git a/base/run_loop_unittest.cc b/base/run_loop_unittest.cc index fcc59fe..0431601 100644 --- a/base/run_loop_unittest.cc +++ b/base/run_loop_unittest.cc
@@ -559,12 +559,12 @@ run_loop_.RunUntilIdle(); } -INSTANTIATE_TEST_CASE_P(Real, - RunLoopTest, - testing::Values(RunLoopTestType::kRealEnvironment)); -INSTANTIATE_TEST_CASE_P(Mock, - RunLoopTest, - testing::Values(RunLoopTestType::kTestDelegate)); +INSTANTIATE_TEST_SUITE_P(Real, + RunLoopTest, + testing::Values(RunLoopTestType::kRealEnvironment)); +INSTANTIATE_TEST_SUITE_P(Mock, + RunLoopTest, + testing::Values(RunLoopTestType::kTestDelegate)); TEST(ScopedRunTimeoutForTestTest, TimesOut) { test::ScopedTaskEnvironment task_environment;
diff --git a/base/synchronization/waitable_event_watcher_unittest.cc b/base/synchronization/waitable_event_watcher_unittest.cc index c1cb720..5acb5e16 100644 --- a/base/synchronization/waitable_event_watcher_unittest.cc +++ b/base/synchronization/waitable_event_watcher_unittest.cc
@@ -419,11 +419,11 @@ EXPECT_FALSE(did_callback); } -INSTANTIATE_TEST_CASE_P(, - WaitableEventWatcherTest, - testing::ValuesIn(testing_main_threads)); +INSTANTIATE_TEST_SUITE_P(, + WaitableEventWatcherTest, + testing::ValuesIn(testing_main_threads)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( , WaitableEventWatcherDeletionTest, testing::Combine(testing::ValuesIn(testing_main_threads), testing::Bool()));
diff --git a/base/test/scoped_task_environment_unittest.cc b/base/test/scoped_task_environment_unittest.cc index ce2bbcb..c1c0441 100644 --- a/base/test/scoped_task_environment_unittest.cc +++ b/base/test/scoped_task_environment_unittest.cc
@@ -384,27 +384,27 @@ EXPECT_EQ(RunLoop::ScopedRunTimeoutForTest::Current(), old_run_timeout); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadDefault, ScopedTaskEnvironmentTest, ::testing::Values(ScopedTaskEnvironment::MainThreadType::DEFAULT)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadMockTime, ScopedTaskEnvironmentTest, ::testing::Values(ScopedTaskEnvironment::MainThreadType::MOCK_TIME)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadUIMockTime, ScopedTaskEnvironmentTest, ::testing::Values(ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadUI, ScopedTaskEnvironmentTest, ::testing::Values(ScopedTaskEnvironment::MainThreadType::UI)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadIO, ScopedTaskEnvironmentTest, ::testing::Values(ScopedTaskEnvironment::MainThreadType::IO)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadIOMockTime, ScopedTaskEnvironmentTest, ::testing::Values(ScopedTaskEnvironment::MainThreadType::IO_MOCK_TIME)); @@ -628,15 +628,15 @@ EXPECT_EQ(TimeTicks::Now(), start_time + delay); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadMockTime, ScopedTaskEnvironmentMockedTime, ::testing::Values(ScopedTaskEnvironment::MainThreadType::MOCK_TIME)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadUIMockTime, ScopedTaskEnvironmentMockedTime, ::testing::Values(ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MainThreadIOMockTime, ScopedTaskEnvironmentMockedTime, ::testing::Values(ScopedTaskEnvironment::MainThreadType::IO_MOCK_TIME));
diff --git a/base/test/sequenced_task_runner_test_template.h b/base/test/sequenced_task_runner_test_template.h index a510030..96c7bf8 100644 --- a/base/test/sequenced_task_runner_test_template.h +++ b/base/test/sequenced_task_runner_test_template.h
@@ -122,7 +122,7 @@ TaskRunnerTestDelegate delegate_; }; -TYPED_TEST_CASE_P(SequencedTaskRunnerTest); +TYPED_TEST_SUITE_P(SequencedTaskRunnerTest); // This test posts N non-nestable tasks in sequence, and expects them to run // in FIFO order, with no part of any two tasks' execution @@ -303,20 +303,20 @@ // The SequencedTaskRunnerTest test case verifies behaviour that is expected // from a sequenced task runner in order to be conformant. -REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest, - SequentialNonNestable, - SequentialNestable, - SequentialDelayedNonNestable, - NonNestablePostFromNonNestableTask, - DelayedTasksSameDelay, - DelayedTaskAfterLongTask, - DelayedTaskAfterManyLongTasks); +REGISTER_TYPED_TEST_SUITE_P(SequencedTaskRunnerTest, + SequentialNonNestable, + SequentialNestable, + SequentialDelayedNonNestable, + NonNestablePostFromNonNestableTask, + DelayedTasksSameDelay, + DelayedTaskAfterLongTask, + DelayedTaskAfterManyLongTasks); template <typename TaskRunnerTestDelegate> class SequencedTaskRunnerDelayedTest : public SequencedTaskRunnerTest<TaskRunnerTestDelegate> {}; -TYPED_TEST_CASE_P(SequencedTaskRunnerDelayedTest); +TYPED_TEST_SUITE_P(SequencedTaskRunnerDelayedTest); // This test posts a delayed task, and checks that the task is run later than // the specified time. @@ -343,7 +343,7 @@ // SequencedTaskRunnerDelayedTest tests that the |delay| parameter of // is used to actually wait for |delay| ms before executing the task. // This is not mandatory for a SequencedTaskRunner to be compliant. -REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerDelayedTest, DelayedTaskBasic); +REGISTER_TYPED_TEST_SUITE_P(SequencedTaskRunnerDelayedTest, DelayedTaskBasic); } // namespace base
diff --git a/base/test/task_runner_test_template.h b/base/test/task_runner_test_template.h index 4670522..09d707b 100644 --- a/base/test/task_runner_test_template.h +++ b/base/test/task_runner_test_template.h
@@ -39,7 +39,7 @@ // Then you simply #include this file as well as gtest.h and add the // following statement to my_task_runner_unittest.cc: // -// INSTANTIATE_TYPED_TEST_CASE_P( +// INSTANTIATE_TYPED_TEST_SUITE_P( // MyTaskRunner, TaskRunnerTest, MyTaskRunnerTestDelegate); // // Easy! @@ -47,10 +47,9 @@ // The optional test harnesses TaskRunnerAffinityTest can be // instanciated in the same way, using the same delegate: // -// INSTANTIATE_TYPED_TEST_CASE_P( +// INSTANTIATE_TYPED_TEST_SUITE_P( // MyTaskRunner, TaskRunnerAffinityTest, MyTaskRunnerTestDelegate); - #ifndef BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_ #define BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_ @@ -115,7 +114,7 @@ TaskRunnerTestDelegate delegate_; }; -TYPED_TEST_CASE_P(TaskRunnerTest); +TYPED_TEST_SUITE_P(TaskRunnerTest); // We can't really test much, since TaskRunner provides very few // guarantees. @@ -168,7 +167,7 @@ // The TaskRunnerTest test case verifies behaviour that is expected from a // task runner in order to be conformant. -REGISTER_TYPED_TEST_CASE_P(TaskRunnerTest, Basic, Delayed); +REGISTER_TYPED_TEST_SUITE_P(TaskRunnerTest, Basic, Delayed); namespace test { @@ -182,7 +181,7 @@ template <typename TaskRunnerTestDelegate> class TaskRunnerAffinityTest : public TaskRunnerTest<TaskRunnerTestDelegate> {}; -TYPED_TEST_CASE_P(TaskRunnerAffinityTest); +TYPED_TEST_SUITE_P(TaskRunnerAffinityTest); // Post a bunch of tasks to the task runner as well as to a separate // thread, each checking the value of RunsTasksInCurrentSequence(), @@ -223,7 +222,7 @@ // TaskRunnerAffinityTest tests that the TaskRunner implementation // can determine if tasks will never be run on a specific thread. -REGISTER_TYPED_TEST_CASE_P(TaskRunnerAffinityTest, RunsTasksInCurrentSequence); +REGISTER_TYPED_TEST_SUITE_P(TaskRunnerAffinityTest, RunsTasksInCurrentSequence); } // namespace base
diff --git a/base/test/test_shared_memory_util.cc b/base/test/test_shared_memory_util.cc index 5093e67c..82b695a 100644 --- a/base/test/test_shared_memory_util.cc +++ b/base/test/test_shared_memory_util.cc
@@ -71,7 +71,7 @@ #if defined(OS_FUCHSIA) // Fuchsia specific implementation. bool CheckReadOnlySharedMemoryFuchsiaHandle(zx::unowned_vmo handle) { - const uint32_t flags = ZX_VM_FLAG_PERM_READ | ZX_VM_FLAG_PERM_WRITE; + const uint32_t flags = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE; uintptr_t addr; const zx_status_t status = zx::vmar::root_self()->map(0, *handle, 0U, kDataSize, flags, &addr);
diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc index bcfde1c..ed0c1ee 100644 --- a/base/timer/timer_unittest.cc +++ b/base/timer/timer_unittest.cc
@@ -700,8 +700,8 @@ } } -INSTANTIATE_TEST_CASE_P(, - TimerTestWithThreadType, - testing::ValuesIn(testing_main_threads)); +INSTANTIATE_TEST_SUITE_P(, + TimerTestWithThreadType, + testing::ValuesIn(testing_main_threads)); } // namespace base
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn index e07318e..ffa036e 100644 --- a/build/config/BUILD.gn +++ b/build/config/BUILD.gn
@@ -293,6 +293,10 @@ if (is_win && generate_order_files && !is_nacl) { public_deps += [ "//tools/cygprofile_win" ] } + + if (is_fuchsia) { + public_deps += [ "//third_party/fuchsia-sdk:runtime_library" ] + } } group("executable_deps") {
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index 817efb4..5b60633c 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -171,9 +171,11 @@ declare_args() { # Set to true to use lld, the LLVM linker. # https://crbug.com/911658 for using lld on 32-bit linux. + # https://crbug.com/917504 for arm chromeos use_lld = is_clang && (is_win || is_fuchsia || is_android || - (is_linux && target_os != "chromeos" && current_cpu != "x86")) + (is_linux && target_os != "chromeos" && current_cpu != "x86") || + (target_os == "chromeos" && current_cpu != "arm")) } declare_args() {
diff --git a/build/config/fuchsia/build_manifest.py b/build/config/fuchsia/build_manifest.py index 0fac7f88..ee13568 100644 --- a/build/config/fuchsia/build_manifest.py +++ b/build/config/fuchsia/build_manifest.py
@@ -13,73 +13,13 @@ import tempfile -def ReadDynamicLibDeps(paths): - """Returns a list of NEEDED libraries read from a binary's ELF header.""" - - LIBRARY_RE = re.compile(r'.*\(NEEDED\)\s+Shared library: \[(?P<lib>.*)\]') - elfinfo = subprocess.check_output(['readelf', '-d'] + paths, - stderr=open(os.devnull, 'w')) - libs = [] - for line in elfinfo.split('\n'): - match = LIBRARY_RE.match(line.rstrip()) - if match: - lib = match.group('lib') - - # libc.so is an alias for ld.so.1 . - if lib == 'libc.so': - lib = 'ld.so.1' - - # Skip libzircon.so, as it is supplied by the OS loader. - if lib != 'libzircon.so': - libs.append(lib) - - return libs - - -def ComputeTransitiveLibDeps(executable_path, available_libs): - """Returns a set representing the library dependencies of |executable_path|, - the dependencies of its dependencies, and so on. - - A list of candidate library filesystem paths is passed using |available_libs| - to help with resolving full paths from the short ELF header filenames.""" - - # Stack of binaries (libraries, executables) awaiting traversal. - to_visit = [executable_path] - - # The computed set of visited transitive dependencies. - deps = set() - - while to_visit: - deps = deps.union(to_visit) - - # Resolve the full paths for all of |cur_path|'s NEEDED libraries. - dep_paths = {available_libs[dep] - for dep in ReadDynamicLibDeps(list(to_visit))} - - # Add newly discovered dependencies to the pending traversal stack. - to_visit = dep_paths.difference(deps) - - return deps - - -def EnumerateDirectoryFiles(path): - """Returns a flattened list of all files contained under |path|.""" - - output = set() - for dirname, _, files in os.walk(path): - output = output.union({os.path.join(dirname, f) for f in files}) - return output - - def MakePackagePath(file_path, roots): """Computes a path for |file_path| that is relative to one of the directory paths in |roots|. - file_path: The absolute file path to relativize. - roots: A list of absolute directory paths which may serve as a relative root - for |file_path|. At least one path must contain |file_path|. - Overlapping roots are permitted; the deepest matching root will be - chosen. + file_path: The file path to relativize. + roots: A list of directory paths which may serve as a relative root + for |file_path|. Examples: @@ -104,28 +44,17 @@ if file_path.startswith(next_root): relative_path = file_path[len(next_root):] - # Move all dynamic libraries (ending in .so or .so.<number>) to lib/. - if re.search('.*\.so(\.\d+)?$', file_path): - relative_path = 'lib/' + os.path.basename(relative_path) - return relative_path - raise Exception('Error: no matching root paths found for \'%s\'.' % file_path) + return file_path def _GetStrippedPath(bin_path): """Finds the stripped version of the binary |bin_path| in the build output directory.""" - # Skip the resolution step for binaries that don't have stripped counterparts, - # like system libraries or other libraries built outside the Chromium build. - if not '.unstripped' in bin_path: - return bin_path - - return os.path.normpath(os.path.join(bin_path, - os.path.pardir, - os.path.pardir, - os.path.basename(bin_path))) + return bin_path.replace('lib.unstripped/', 'lib/').replace( + 'exe.unstripped/', '') def _IsBinary(path): @@ -141,9 +70,9 @@ with open(args.output_path, 'w') as manifest, \ open(args.depfile_path, 'w') as depfile: # Process the runtime deps file for file paths, recursively walking - # directories as needed. File paths are stored in absolute form, - # so that MakePackagePath() may relativize to either the source root or - # output directory. + # directories as needed. + # MakePackagePath() may relativize to either the source root or output + # directory. # runtime_deps may contain duplicate paths, so use a set for # de-duplication. expanded_files = set() @@ -154,37 +83,20 @@ for current_file in files: if current_file.startswith('.'): continue - expanded_files.add(os.path.abspath( - os.path.join(root, current_file))) + expanded_files.add( + os.path.join(root, current_file)) else: - expanded_files.add(os.path.abspath(next_path)) - - # Get set of dist libraries available for dynamic linking. - dist_libs = set() - for next_dir in args.dynlib_path: - dist_libs = dist_libs.union(EnumerateDirectoryFiles(next_dir)) - - # Compute the set of dynamic libraries used by the application or its - # transitive dependencies (dist libs and components), and merge the result - # with |expanded_files| so that they are included in the manifest. - # - # TODO(crbug.com/861931): Make sure that deps of the files in data_deps - # (binaries and libraries) are included as well. - expanded_files = expanded_files.union( - ComputeTransitiveLibDeps( - args.app_filename, - {os.path.basename(f): f for f in expanded_files.union(dist_libs)})) + expanded_files.add(next_path) # Format and write out the manifest contents. - gen_dir = os.path.join(args.out_dir, "gen") + gen_dir = os.path.normpath(os.path.join(args.out_dir, "gen")) app_found = False excluded_files_set = set(args.exclude_file) for current_file in expanded_files: if _IsBinary(current_file): current_file = _GetStrippedPath(current_file) - absolute_file_path = os.path.join(args.out_dir, current_file) - in_package_path = MakePackagePath(absolute_file_path, + in_package_path = MakePackagePath(current_file, [gen_dir, args.root_dir, args.out_dir]) if in_package_path == args.app_filename: app_found = True @@ -193,11 +105,7 @@ excluded_files_set.remove(in_package_path) continue - # The source path is relativized so that it can be used on multiple - # environments with differing parent directory structures, - # e.g. builder bots and swarming clients. - manifest.write('%s=%s\n' % (in_package_path, - os.path.relpath(current_file, args.out_dir))) + manifest.write('%s=%s\n' % (in_package_path, current_file)) if len(excluded_files_set) > 0: raise Exception('Some files were excluded with --exclude-file, but ' @@ -249,8 +157,6 @@ help='Path to write GN deps file.') parser.add_argument('--exclude-file', action='append', default=[], help='Package-relative file path to exclude from the package.') - parser.add_argument('--dynlib-path', action='append', default=[], - help='Paths for the dynamic libraries relative to the output dir.') parser.add_argument('--output-path', required=True, help='Output file path.') args = parser.parse_args()
diff --git a/build/config/fuchsia/config.gni b/build/config/fuchsia/config.gni index 165153b..cdf684e2 100644 --- a/build/config/fuchsia/config.gni +++ b/build/config/fuchsia/config.gni
@@ -11,9 +11,9 @@ # Compute the arch-specific path to packages' dynamic library dependencies. if (current_cpu == "arm64") { - dist_libroot = fuchsia_sdk + "/arch/arm64/dist/" + dist_libroot = fuchsia_sdk + "/arch/arm64/dist" } else if (current_cpu == "x64") { - dist_libroot = fuchsia_sdk + "/arch/x64/dist/" + dist_libroot = fuchsia_sdk + "/arch/x64/dist" } else { assert(false, "No libraries available for architecture: $current_cpu") }
diff --git a/build/config/fuchsia/package.gni b/build/config/fuchsia/package.gni index 2e71029..924eb0a 100644 --- a/build/config/fuchsia/package.gni +++ b/build/config/fuchsia/package.gni
@@ -85,25 +85,21 @@ args = [ "--root-dir", - rebase_path("//"), + rebase_path("//", root_build_dir), "--out-dir", - rebase_path(root_out_dir), + rebase_path(root_out_dir, root_build_dir), "--app-name", pkg.package_name, "--app-filename", get_label_info(pkg.binary, "name"), "--sandbox-policy-path", - rebase_path(pkg.sandbox_policy), + rebase_path(pkg.sandbox_policy, root_build_dir), "--runtime-deps-file", - rebase_path(_runtime_deps_file), + rebase_path(_runtime_deps_file, root_build_dir), "--depfile-path", - rebase_path(_depfile), - "--dynlib-path", - rebase_path(dist_libroot), - "--dynlib-path", - rebase_path("${sysroot}/dist"), + rebase_path(_depfile, root_build_dir), "--output-path", - rebase_path(_archive_manifest), + rebase_path(_archive_manifest, root_build_dir), ] if (defined(pkg.excluded_files)) {
diff --git a/build/toolchain/fuchsia/BUILD.gn b/build/toolchain/fuchsia/BUILD.gn index 7ab3a2d0..654073b 100644 --- a/build/toolchain/fuchsia/BUILD.gn +++ b/build/toolchain/fuchsia/BUILD.gn
@@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/toolchain/gcc_toolchain.gni") import("//build/config/fuchsia/config.gni") +import("//build/toolchain/gcc_toolchain.gni") # Fuchsia builds using the Clang toolchain, with most parameters common across # the different target architectures. @@ -21,6 +21,8 @@ use_unstripped_as_runtime_outputs = true } + default_shlib_subdir = "/lib" + toolchain_args = invoker.toolchain_args toolchain_args.current_os = "fuchsia" }
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni index d3bf0ae0..42686fb 100644 --- a/build/toolchain/gcc_toolchain.gni +++ b/build/toolchain/gcc_toolchain.gni
@@ -241,6 +241,12 @@ default_shlib_extension = shlib_extension } + if (defined(invoker.default_shlib_subdir)) { + default_shlib_subdir = invoker.default_shlib_subdir + } else { + default_shlib_subdir = "" + } + if (defined(invoker.executable_extension)) { default_executable_extension = invoker.executable_extension } else { @@ -434,7 +440,7 @@ # specifies). default_output_extension = default_shlib_extension - default_output_dir = "{{root_out_dir}}" + default_output_dir = "{{root_out_dir}}${default_shlib_subdir}" output_prefix = "lib" @@ -494,7 +500,7 @@ default_output_extension = default_shlib_extension } - default_output_dir = "{{root_out_dir}}" + default_output_dir = "{{root_out_dir}}${default_shlib_subdir}" output_prefix = "lib" @@ -622,6 +628,7 @@ [ "strip", "is_clang_analysis_supported", + "default_shlib_subdir", "enable_linker_map", "use_unstripped_as_runtime_outputs", ])
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni index c0e1dbe..f9fb7e7 100644 --- a/build/toolchain/toolchain.gni +++ b/build/toolchain/toolchain.gni
@@ -78,6 +78,13 @@ shlib_prefix = "" } +# Directory for shared library files. +if (is_fuchsia) { + shlib_subdir = "/lib" +} else { + shlib_subdir = "" +} + # While other "tool"s in a toolchain are specific to the target of that # toolchain, the "stamp" and "copy" tools are really generic to the host; # but each toolchain must define them separately. GN doesn't allow a
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 7943fd4..a1bf3e6 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -439,11 +439,10 @@ test_hooks_->BeginMainFrame(args); } + void RecordStartOfFrameMetrics() override {} void RecordEndOfFrameMetrics(base::TimeTicks) override {} - void UpdateLayerTreeHost(bool record_main_frame_metrics) override { - test_hooks_->UpdateLayerTreeHost(); - } + void UpdateLayerTreeHost() override { test_hooks_->UpdateLayerTreeHost(); } void ApplyViewportChanges(const ApplyViewportChangesArgs& args) override { test_hooks_->ApplyViewportChanges(args);
diff --git a/cc/test/stub_layer_tree_host_client.h b/cc/test/stub_layer_tree_host_client.h index 021d747a..47c43574 100644 --- a/cc/test/stub_layer_tree_host_client.h +++ b/cc/test/stub_layer_tree_host_client.h
@@ -18,10 +18,11 @@ void WillBeginMainFrame() override {} void DidBeginMainFrame() override {} void BeginMainFrame(const viz::BeginFrameArgs& args) override {} + void RecordStartOfFrameMetrics() override {} void RecordEndOfFrameMetrics(base::TimeTicks) override {} void BeginMainFrameNotExpectedSoon() override {} void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override {} - void UpdateLayerTreeHost(bool record_main_frame_metrics) override {} + void UpdateLayerTreeHost() override {} void ApplyViewportChanges(const ApplyViewportChangesArgs&) override {} void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel, bool has_scrolled_by_touch) override {}
diff --git a/cc/tiles/paint_worklet_image_cache.cc b/cc/tiles/paint_worklet_image_cache.cc index 47f7773..791cbb3f 100644 --- a/cc/tiles/paint_worklet_image_cache.cc +++ b/cc/tiles/paint_worklet_image_cache.cc
@@ -50,12 +50,13 @@ // then there is no need to call the Paint() function. void PaintWorkletImageCache::PaintImageInTask(const PaintImage& paint_image) { sk_sp<PaintRecord> record = painter_->Paint(); - records_[paint_image.paint_worklet_input()] = record; + records_[paint_image.paint_worklet_input()] = + std::make_pair(std::move(record), 0); } PaintRecord* PaintWorkletImageCache::GetPaintRecordForTest( PaintWorkletInput* input) { - return records_[input].get(); + return records_[input].first.get(); } } // namespace cc
diff --git a/cc/tiles/paint_worklet_image_cache.h b/cc/tiles/paint_worklet_image_cache.h index d857dc3..7b7b23df 100644 --- a/cc/tiles/paint_worklet_image_cache.h +++ b/cc/tiles/paint_worklet_image_cache.h
@@ -5,6 +5,8 @@ #ifndef CC_TILES_PAINT_WORKLET_IMAGE_CACHE_H_ #define CC_TILES_PAINT_WORKLET_IMAGE_CACHE_H_ +#include <utility> + #include "base/containers/flat_map.h" #include "cc/cc_export.h" #include "cc/paint/draw_image.h" @@ -32,15 +34,19 @@ void PaintImageInTask(const PaintImage& paint_image); PaintRecord* GetPaintRecordForTest(PaintWorkletInput* input); - const base::flat_map<PaintWorkletInput*, sk_sp<PaintRecord>>& + const base::flat_map<PaintWorkletInput*, + std::pair<sk_sp<PaintRecord>, size_t>>& GetRecordsForTest() { return records_; } private: - // The PaintRecord is produced by PaintWorkletLayerPainter::Paint(), and used - // for raster. - base::flat_map<PaintWorkletInput*, sk_sp<PaintRecord>> records_; + // This is a map of paint worklet inputs to a pair of paint record and a + // reference count. The paint record is the representation of the worklet + // output based on the input, and the reference count is the number of times + // that it is used for tile rasterization. + base::flat_map<PaintWorkletInput*, std::pair<sk_sp<PaintRecord>, size_t>> + records_; // The PaintWorkletImageCache is owned by ImageController, which has the same // life time as the LayerTreeHostImpl, that guarantees that the painter will // live as long as the LayerTreeHostImpl.
diff --git a/cc/tiles/paint_worklet_image_cache_unittest.cc b/cc/tiles/paint_worklet_image_cache_unittest.cc index 18355d4..5b448d6 100644 --- a/cc/tiles/paint_worklet_image_cache_unittest.cc +++ b/cc/tiles/paint_worklet_image_cache_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "cc/tiles/paint_worklet_image_cache.h" #include "cc/paint/draw_image.h" @@ -87,15 +89,17 @@ TestTileTaskRunner::ProcessTask(task1.get()); TestTileTaskRunner::ProcessTask(task2.get()); - base::flat_map<PaintWorkletInput*, sk_sp<PaintRecord>> records = - cache.GetRecordsForTest(); + base::flat_map<PaintWorkletInput*, std::pair<sk_sp<PaintRecord>, size_t>> + records = cache.GetRecordsForTest(); EXPECT_EQ(records.size(), 2u); - PaintRecord* record1 = records[paint_image1.paint_worklet_input()].get(); + PaintRecord* record1 = + records[paint_image1.paint_worklet_input()].first.get(); EXPECT_TRUE(record1); TestPaintRecord(record1); - PaintRecord* record2 = records[paint_image2.paint_worklet_input()].get(); + PaintRecord* record2 = + records[paint_image2.paint_worklet_input()].first.get(); EXPECT_TRUE(record2); TestPaintRecord(record2); }
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 7e0328a..5aca1c6 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -277,8 +277,8 @@ return debug_state_; } -void LayerTreeHost::RequestMainFrameUpdate(bool record_main_frame_metrics) { - client_->UpdateLayerTreeHost(record_main_frame_metrics); +void LayerTreeHost::RequestMainFrameUpdate() { + client_->UpdateLayerTreeHost(); } // This function commits the LayerTreeHost to an impl tree. When modifying @@ -644,7 +644,7 @@ DCHECK(IsSingleThreaded()); // This function is only valid when not using the scheduler. DCHECK(!settings_.single_thread_proxy_scheduler); - RequestMainFrameUpdate(false /* record_main_frame_metrics */); + RequestMainFrameUpdate(); UpdateLayers(); } @@ -942,6 +942,10 @@ RecordWheelAndTouchScrollingCount(*info); } +void LayerTreeHost::RecordStartOfFrameMetrics() { + client_->RecordStartOfFrameMetrics(); +} + void LayerTreeHost::RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) { client_->RecordEndOfFrameMetrics(frame_begin_time); }
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index d98608d..fdfbdad 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -578,7 +578,7 @@ void BeginMainFrameNotExpectedSoon(); void BeginMainFrameNotExpectedUntil(base::TimeTicks time); void AnimateLayers(base::TimeTicks monotonic_frame_begin_time); - void RequestMainFrameUpdate(bool record_main_frame_metrics); + void RequestMainFrameUpdate(); void FinishCommitOnImplThread(LayerTreeHostImpl* host_impl); void WillCommit(); void CommitComplete(); @@ -602,6 +602,7 @@ // Called when the compositor completed page scale animation. void DidCompletePageScaleAnimation(); void ApplyScrollAndScale(ScrollAndScaleSet* info); + void RecordStartOfFrameMetrics(); void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time); LayerTreeHostClient* client() { return client_; }
diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h index a282dae8..9ac8155a 100644 --- a/cc/trees/layer_tree_host_client.h +++ b/cc/trees/layer_tree_host_client.h
@@ -91,11 +91,8 @@ // (Blink's notions of) style, layout, paint invalidation and compositing // state. (The "compositing state" will result in a mutated layer tree on the // LayerTreeHost via additional interface indirections which lead back to - // mutations on the LayerTreeHost.) The |record_main_frame_metrics| flag - // determines whether Blink will compute metrics related to main frame update - // time. If true, the caller must ensure that RecordEndOfFrameMetrics is - // called when this method returns and the total main frame time is known. - virtual void UpdateLayerTreeHost(bool record_main_frame_metrics) = 0; + // mutations on the LayerTreeHost.) + virtual void UpdateLayerTreeHost() = 0; // Notifies the client of viewport-related changes that occured in the // LayerTreeHost since the last commit. This typically includes things @@ -129,8 +126,9 @@ virtual void DidPresentCompositorFrame( uint32_t frame_token, const gfx::PresentationFeedback& feedback) = 0; - // Record UMA and UKM metrics that require the time from the start of - // BeginMainFrame to the Commit, or early out. + // Mark the frame start and end time for UMA and UKM metrics that require + // the time from the start of BeginMainFrame to the Commit, or early out. + virtual void RecordStartOfFrameMetrics() = 0; virtual void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) = 0; virtual void DidGenerateLocalSurfaceIdAllocation( const viz::LocalSurfaceIdAllocation& allocation) = 0;
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc index bce8661..2459f4a 100644 --- a/cc/trees/proxy_main.cc +++ b/cc/trees/proxy_main.cc
@@ -207,6 +207,7 @@ begin_main_frame_state->scroll_info.get()); layer_tree_host_->WillBeginMainFrame(); + layer_tree_host_->RecordStartOfFrameMetrics(); // See LayerTreeHostClient::BeginMainFrame for more documentation on // what this does. @@ -225,8 +226,7 @@ // See LayerTreeHostClient::MainFrameUpdate for more documentation on // what this does. - layer_tree_host_->RequestMainFrameUpdate( - true /* record_main_frame_metrics */); + layer_tree_host_->RequestMainFrameUpdate(); // TODO(schenney) This will be changed to defer_commits_ when we introduce // the separation between deferring of main frame updates and deferring of
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 68986683..9518bbc 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc
@@ -809,8 +809,7 @@ layer_tree_host_->WillBeginMainFrame(); layer_tree_host_->BeginMainFrame(begin_frame_args); layer_tree_host_->AnimateLayers(begin_frame_args.frame_time); - layer_tree_host_->RequestMainFrameUpdate( - false /* record_main_frame_metrics */); + layer_tree_host_->RequestMainFrameUpdate(); } void SingleThreadProxy::DoPainting() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java index 1ab95f71..a05f950 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java
@@ -203,8 +203,8 @@ public boolean onInfoBarButtonClicked(boolean isPrimary) { try { assert sRequestInstallInstance == null; - ArCoreShim.InstallStatus installStatus = - getArCoreShimInstance().requestInstall(activity, true); + @ArCoreShim.InstallStatus + int installStatus = getArCoreShimInstance().requestInstall(activity, true); if (installStatus == ArCoreShim.InstallStatus.INSTALL_REQUESTED) { // Install flow will resume in onArCoreRequestInstallReturned, mark that
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShim.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShim.java index 2f26a8c0..04c5deb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShim.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShim.java
@@ -24,7 +24,12 @@ * For detailed description, please see: * https://developers.google.com/ar/reference/java/arcore/reference/com/google/ar/core/ArCoreApk.InstallStatus */ - public enum InstallStatus { INSTALLED, INSTALL_REQUESTED } + @IntDef({InstallStatus.INSTALLED, InstallStatus.INSTALL_REQUESTED}) + @Retention(RetentionPolicy.SOURCE) + public @interface InstallStatus { + int INSTALLED = 0; + int INSTALL_REQUESTED = 1; + } /** * Equivalent of ArCoreApk.Availability enum. @@ -55,7 +60,7 @@ /** * Equivalent of ArCoreApk.requestInstall. */ - public InstallStatus requestInstall(Activity activity, boolean userRequestedInstall) + public @InstallStatus int requestInstall(Activity activity, boolean userRequestedInstall) throws UnavailableDeviceNotCompatibleException, UnavailableUserDeclinedInstallationException;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShimImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShimImpl.java index 901945f..1b6696f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShimImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShimImpl.java
@@ -19,7 +19,7 @@ public ArCoreShimImpl() {} @Override - public InstallStatus requestInstall(Activity activity, boolean userRequestedInstall) + public @InstallStatus int requestInstall(Activity activity, boolean userRequestedInstall) throws UnavailableDeviceNotCompatibleException, UnavailableUserDeclinedInstallationException { try { @@ -40,7 +40,7 @@ return mapArCoreApkAvailability(availability); } - private InstallStatus mapArCoreApkInstallStatus(ArCoreApk.InstallStatus installStatus) { + private @InstallStatus int mapArCoreApkInstallStatus(ArCoreApk.InstallStatus installStatus) { switch (installStatus) { case INSTALLED: return InstallStatus.INSTALLED;
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn index 9fcd111..f7320581 100644 --- a/chrome/app/BUILD.gn +++ b/chrome/app/BUILD.gn
@@ -9,7 +9,6 @@ import("//device/vr/buildflags/buildflags.gni") import("//ppapi/buildflags/buildflags.gni") import("//printing/buildflags/buildflags.gni") -import("//services/catalog/public/tools/catalog.gni") import("//services/service_manager/public/service_manifest.gni") import("//tools/grit/grit_rule.gni") import("//tools/ipc_fuzzer/ipc_fuzzer.gni") @@ -589,10 +588,10 @@ if (is_chromeos) { deps += [ - "//ash:manifest", "//ash/components/quick_launch:manifest", "//ash/components/shortcut_viewer:manifest", "//ash/components/tap_visualizer:manifest", + "//ash/public/cpp:manifest", "//chrome/browser/chromeos:ash_pref_connector_manifest", "//chrome/services/cups_ipp_parser:manifest", "//chromeos/services/ime:manifest",
diff --git a/chrome/app/DEPS b/chrome/app/DEPS index 376ea29..8902a820 100644 --- a/chrome/app/DEPS +++ b/chrome/app/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+ash/components/quick_launch/public", + "+ash/public", "+chrome/browser", "+chrome/child", "+chrome/chrome_watcher", @@ -79,7 +80,6 @@ "+ash/components/quick_launch", "+ash/components/shortcut_viewer", "+ash/components/tap_visualizer", - "+ash/manifest.h", "+chrome/services/cups_ipp_parser", "+chrome/services/file_util", "+chrome/services/isolated_xr_device",
diff --git a/chrome/app/chrome_packaged_service_manifests.cc b/chrome/app/chrome_packaged_service_manifests.cc index c25964a..114bced 100644 --- a/chrome/app/chrome_packaged_service_manifests.cc +++ b/chrome/app/chrome_packaged_service_manifests.cc
@@ -25,7 +25,7 @@ #include "ash/components/quick_launch/manifest.h" #include "ash/components/shortcut_viewer/manifest.h" #include "ash/components/tap_visualizer/manifest.h" -#include "ash/manifest.h" +#include "ash/public/cpp/manifest.h" #include "chrome/browser/chromeos/ash_pref_connector_manifest.h" #include "chrome/services/cups_ipp_parser/manifest.h" #include "chromeos/services/ime/manifest.h"
diff --git a/chrome/app/printing_strings.grdp b/chrome/app/printing_strings.grdp index 6abc12c..71329f5f 100644 --- a/chrome/app/printing_strings.grdp +++ b/chrome/app/printing_strings.grdp
@@ -208,7 +208,7 @@ Manage </message> <message name="IDS_PRINT_PREVIEW_SEE_MORE" desc="Dropdown option to view more print destinations in a dialog." meaning="Label text"> - See more + See more... </message> <message name="IDS_PRINT_PREVIEW_SEE_MORE_DESTINATIONS_LABEL" desc="Aria label for the dropdown option to view more print destinations in a dialog. Expansion of SEE_MORE above to add context for screen readers." meaning="Label text"> See more destinations
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index bc57528..1d1207c 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -3658,6 +3658,12 @@ <message name="IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC" desc="The label of button that allows user to cancel sync."> Cancel sync </message> + <message name="IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_TITLE" desc="The title of the dialog to confirm the sync cancellation."> + Cancel sync? + </message> + <message name="IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_BODY" desc="The body text of the dialog to confirm the sync cancellation."> + You can turn on sync anytime in settings + </message> </if> <message name="IDS_SETTINGS_SYNC_TIMEOUT" desc="Text explaining what to do if sync times out."> Check your internet connection. If the problem continues, try signing out and signing in again.
diff --git a/chrome/app/vector_icons/trash_can.icon b/chrome/app/vector_icons/trash_can.icon index 1ac9ed1..0b6316b 100644 --- a/chrome/app/vector_icons/trash_can.icon +++ b/chrome/app/vector_icons/trash_can.icon
@@ -1,21 +1,21 @@ -// 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. - -CANVAS_DIMENSIONS, 16, -MOVE_TO, 4, 12.67f, -CUBIC_TO, 4, 13.4f, 4.6f, 14, 5.33f, 14, -R_H_LINE_TO, 5.33f, -CUBIC_TO, 11.4f, 14, 12, 13.4f, 12, 12.67f, -R_V_LINE_TO, -8, -H_LINE_TO, 4, -CLOSE, -R_MOVE_TO, 8.67f, -10, -R_H_LINE_TO, -2.33f, -LINE_TO, 9.67f, 2, -H_LINE_TO, 6.33f, -R_LINE_TO, -0.67f, 0.67f, -H_LINE_TO, 3.33f, -V_LINE_TO, 4, -R_H_LINE_TO, 9.33f, -CLOSE +// 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. + +CANVAS_DIMENSIONS, 16, +MOVE_TO, 4, 12.67f, +CUBIC_TO, 4, 13.4f, 4.6f, 14, 5.33f, 14, +R_H_LINE_TO, 5.33f, +CUBIC_TO, 11.4f, 14, 12, 13.4f, 12, 12.67f, +R_V_LINE_TO, -8, +H_LINE_TO, 4, +CLOSE, +R_MOVE_TO, 8.67f, -10, +R_H_LINE_TO, -2.33f, +LINE_TO, 9.67f, 2, +H_LINE_TO, 6.33f, +R_LINE_TO, -0.67f, 0.67f, +H_LINE_TO, 3.33f, +V_LINE_TO, 4, +R_H_LINE_TO, 9.33f, +CLOSE
diff --git a/chrome/app/vector_icons/vr_headset.icon b/chrome/app/vector_icons/vr_headset.icon index 91ccffb..1a43c384 100644 --- a/chrome/app/vector_icons/vr_headset.icon +++ b/chrome/app/vector_icons/vr_headset.icon
@@ -1,79 +1,79 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 20, -MOVE_TO, 17.4f, 5.57f, -ARC_TO, 2.12f, 2.12f, 0, 0, 0, 15.94f, 5, -H_LINE_TO, 4.06f, -R_CUBIC_TO, -0.55f, 0, -1.07f, 0.2f, -1.46f, 0.56f, -R_CUBIC_TO, -0.39f, 0.37f, -0.6f, 0.85f, -0.6f, 1.36f, -R_V_LINE_TO, 6.14f, -R_CUBIC_TO, 0, 0.52f, 0.21f, 1, 0.6f, 1.36f, -R_CUBIC_TO, 0.39f, 0.37f, 0.91f, 0.56f, 1.46f, 0.56f, -R_H_LINE_TO, 2.85f, -R_CUBIC_TO, 0.37f, 0, 0.74f, -0.09f, 1.06f, -0.28f, -R_CUBIC_TO, 0.32f, -0.18f, 0.58f, -0.43f, 0.76f, -0.74f, -R_LINE_TO, 0.81f, -1.4f, -R_ARC_TO, 0.48f, 0.48f, 0, 0, 1, 0.13f, -0.62f, -R_ARC_TO, 0.56f, 0.56f, 0, 0, 1, 0.67f, 0, -R_CUBIC_TO, 0.2f, 0.15f, 0.25f, 0.41f, 0.13f, 0.62f, -R_LINE_TO, 0.81f, 1.4f, -R_CUBIC_TO, 0.18f, 0.3f, 0.44f, 0.56f, 0.76f, 0.74f, -R_CUBIC_TO, 0.32f, 0.18f, 0.68f, 0.28f, 1.06f, 0.28f, -R_H_LINE_TO, 2.85f, -R_CUBIC_TO, 0.55f, 0, 1.07f, -0.2f, 1.46f, -0.56f, -R_CUBIC_TO, 0.39f, -0.36f, 0.6f, -0.85f, 0.6f, -1.36f, -V_LINE_TO, 6.93f, -R_CUBIC_TO, 0, -0.51f, -0.21f, -1, -0.6f, -1.36f, -CLOSE, -MOVE_TO, 6.5f, 11.5f, -R_CUBIC_TO, -1.11f, 0, -2, -0.9f, -2, -2, -R_CUBIC_TO, 0, -1.1f, 0.9f, -2, 2, -2, -R_CUBIC_TO, 1.1f, 0, 2, 0.9f, 2, 2, -R_CUBIC_TO, 0, 1.1f, -0.89f, 2, -2, 2, -CLOSE, -R_MOVE_TO, 7, 0, -R_CUBIC_TO, -1.11f, 0, -2, -0.9f, -2, -2, -R_CUBIC_TO, 0, -1.1f, 0.9f, -2, 2, -2, -R_CUBIC_TO, 1.1f, 0, 2, 0.9f, 2, 2, -R_CUBIC_TO, 0, 1.1f, -0.89f, 2, -2, 2, -CLOSE - -CANVAS_DIMENSIONS, 16, -MOVE_TO, 14.47f, 4.45f, -ARC_TO, 1.95f, 1.95f, 0, 0, 0, 13.2f, 4, -H_LINE_TO, 2.8f, -R_CUBIC_TO, -0.48f, 0, -0.93f, 0.16f, -1.27f, 0.45f, -R_CUBIC_TO, -0.34f, 0.29f, -0.53f, 0.68f, -0.53f, 1.09f, -R_V_LINE_TO, 4.91f, -R_CUBIC_TO, 0, 0.41f, 0.19f, 0.8f, 0.53f, 1.09f, -R_CUBIC_TO, 0.34f, 0.29f, 0.79f, 0.45f, 1.27f, 0.45f, -R_H_LINE_TO, 2.5f, -R_CUBIC_TO, 0.33f, 0, 0.64f, -0.08f, 0.92f, -0.22f, -R_CUBIC_TO, 0.28f, -0.14f, 0.51f, -0.35f, 0.66f, -0.6f, -R_LINE_TO, 0.7f, -1.12f, -R_CUBIC_TO, -0.1f, -0.17f, -0.05f, -0.37f, 0.12f, -0.49f, -R_ARC_TO, 0.53f, 0.53f, 0, 0, 1, 0.59f, 0, -R_CUBIC_TO, 0.17f, 0.12f, 0.22f, 0.33f, 0.12f, 0.49f, -R_LINE_TO, 0.7f, 1.12f, -R_CUBIC_TO, 0.15f, 0.24f, 0.38f, 0.45f, 0.66f, 0.6f, -R_CUBIC_TO, 0.28f, 0.14f, 0.6f, 0.22f, 0.92f, 0.22f, -R_H_LINE_TO, 2.5f, -R_CUBIC_TO, 0.48f, 0, 0.93f, -0.16f, 1.27f, -0.45f, -R_CUBIC_TO, 0.34f, -0.29f, 0.53f, -0.68f, 0.53f, -1.09f, -V_LINE_TO, 5.54f, -R_CUBIC_TO, 0, -0.41f, -0.19f, -0.8f, -0.53f, -1.09f, -CLOSE, -MOVE_TO, 5, 9, -R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f, -CUBIC_TO_SHORTHAND, 4.18f, 6, 5, 6, -R_CUBIC_TO, 0.82f, 0, 1.5f, 0.68f, 1.5f, 1.5f, -CUBIC_TO_SHORTHAND, 5.83f, 9, 5, 9, -CLOSE, -R_MOVE_TO, 6, 0, -R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f, -CUBIC_TO_SHORTHAND, 10.18f, 6, 11, 6, -R_CUBIC_TO, 0.82f, 0, 1.5f, 0.68f, 1.5f, 1.5f, -CUBIC_TO_SHORTHAND, 11.83f, 9, 11, 9, -CLOSE +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 17.4f, 5.57f, +ARC_TO, 2.12f, 2.12f, 0, 0, 0, 15.94f, 5, +H_LINE_TO, 4.06f, +R_CUBIC_TO, -0.55f, 0, -1.07f, 0.2f, -1.46f, 0.56f, +R_CUBIC_TO, -0.39f, 0.37f, -0.6f, 0.85f, -0.6f, 1.36f, +R_V_LINE_TO, 6.14f, +R_CUBIC_TO, 0, 0.52f, 0.21f, 1, 0.6f, 1.36f, +R_CUBIC_TO, 0.39f, 0.37f, 0.91f, 0.56f, 1.46f, 0.56f, +R_H_LINE_TO, 2.85f, +R_CUBIC_TO, 0.37f, 0, 0.74f, -0.09f, 1.06f, -0.28f, +R_CUBIC_TO, 0.32f, -0.18f, 0.58f, -0.43f, 0.76f, -0.74f, +R_LINE_TO, 0.81f, -1.4f, +R_ARC_TO, 0.48f, 0.48f, 0, 0, 1, 0.13f, -0.62f, +R_ARC_TO, 0.56f, 0.56f, 0, 0, 1, 0.67f, 0, +R_CUBIC_TO, 0.2f, 0.15f, 0.25f, 0.41f, 0.13f, 0.62f, +R_LINE_TO, 0.81f, 1.4f, +R_CUBIC_TO, 0.18f, 0.3f, 0.44f, 0.56f, 0.76f, 0.74f, +R_CUBIC_TO, 0.32f, 0.18f, 0.68f, 0.28f, 1.06f, 0.28f, +R_H_LINE_TO, 2.85f, +R_CUBIC_TO, 0.55f, 0, 1.07f, -0.2f, 1.46f, -0.56f, +R_CUBIC_TO, 0.39f, -0.36f, 0.6f, -0.85f, 0.6f, -1.36f, +V_LINE_TO, 6.93f, +R_CUBIC_TO, 0, -0.51f, -0.21f, -1, -0.6f, -1.36f, +CLOSE, +MOVE_TO, 6.5f, 11.5f, +R_CUBIC_TO, -1.11f, 0, -2, -0.9f, -2, -2, +R_CUBIC_TO, 0, -1.1f, 0.9f, -2, 2, -2, +R_CUBIC_TO, 1.1f, 0, 2, 0.9f, 2, 2, +R_CUBIC_TO, 0, 1.1f, -0.89f, 2, -2, 2, +CLOSE, +R_MOVE_TO, 7, 0, +R_CUBIC_TO, -1.11f, 0, -2, -0.9f, -2, -2, +R_CUBIC_TO, 0, -1.1f, 0.9f, -2, 2, -2, +R_CUBIC_TO, 1.1f, 0, 2, 0.9f, 2, 2, +R_CUBIC_TO, 0, 1.1f, -0.89f, 2, -2, 2, +CLOSE + +CANVAS_DIMENSIONS, 16, +MOVE_TO, 14.47f, 4.45f, +ARC_TO, 1.95f, 1.95f, 0, 0, 0, 13.2f, 4, +H_LINE_TO, 2.8f, +R_CUBIC_TO, -0.48f, 0, -0.93f, 0.16f, -1.27f, 0.45f, +R_CUBIC_TO, -0.34f, 0.29f, -0.53f, 0.68f, -0.53f, 1.09f, +R_V_LINE_TO, 4.91f, +R_CUBIC_TO, 0, 0.41f, 0.19f, 0.8f, 0.53f, 1.09f, +R_CUBIC_TO, 0.34f, 0.29f, 0.79f, 0.45f, 1.27f, 0.45f, +R_H_LINE_TO, 2.5f, +R_CUBIC_TO, 0.33f, 0, 0.64f, -0.08f, 0.92f, -0.22f, +R_CUBIC_TO, 0.28f, -0.14f, 0.51f, -0.35f, 0.66f, -0.6f, +R_LINE_TO, 0.7f, -1.12f, +R_CUBIC_TO, -0.1f, -0.17f, -0.05f, -0.37f, 0.12f, -0.49f, +R_ARC_TO, 0.53f, 0.53f, 0, 0, 1, 0.59f, 0, +R_CUBIC_TO, 0.17f, 0.12f, 0.22f, 0.33f, 0.12f, 0.49f, +R_LINE_TO, 0.7f, 1.12f, +R_CUBIC_TO, 0.15f, 0.24f, 0.38f, 0.45f, 0.66f, 0.6f, +R_CUBIC_TO, 0.28f, 0.14f, 0.6f, 0.22f, 0.92f, 0.22f, +R_H_LINE_TO, 2.5f, +R_CUBIC_TO, 0.48f, 0, 0.93f, -0.16f, 1.27f, -0.45f, +R_CUBIC_TO, 0.34f, -0.29f, 0.53f, -0.68f, 0.53f, -1.09f, +V_LINE_TO, 5.54f, +R_CUBIC_TO, 0, -0.41f, -0.19f, -0.8f, -0.53f, -1.09f, +CLOSE, +MOVE_TO, 5, 9, +R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f, +CUBIC_TO_SHORTHAND, 4.18f, 6, 5, 6, +R_CUBIC_TO, 0.82f, 0, 1.5f, 0.68f, 1.5f, 1.5f, +CUBIC_TO_SHORTHAND, 5.83f, 9, 5, 9, +CLOSE, +R_MOVE_TO, 6, 0, +R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f, +CUBIC_TO_SHORTHAND, 10.18f, 6, 11, 6, +R_CUBIC_TO, 0.82f, 0, 1.5f, 0.68f, 1.5f, 1.5f, +CUBIC_TO_SHORTHAND, 11.83f, 9, 11, 9, +CLOSE
diff --git a/chrome/app_shim/chrome_main_app_mode_mac.mm b/chrome/app_shim/chrome_main_app_mode_mac.mm index bc20426c..026678d 100644 --- a/chrome/app_shim/chrome_main_app_mode_mac.mm +++ b/chrome/app_shim/chrome_main_app_mode_mac.mm
@@ -49,6 +49,14 @@ } // namespace +// The NSApplication for app shims is a vanilla NSApplication, but sub-class it +// so that we can DCHECK that we know precisely when it is initialized. +@interface AppShimApplication : NSApplication +@end + +@implementation AppShimApplication +@end + // A ReplyEventHandler is a helper class to send an Apple Event to a process // and call a callback when the reply returns. // @@ -165,6 +173,12 @@ } // extern "C" +void PostRepeatingDelayedTask() { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::BindOnce(&PostRepeatingDelayedTask), + base::TimeDelta::FromDays(1)); +} + int ChromeAppModeStart_v5(const app_mode::ChromeAppModeInfo* info) { base::CommandLine::Init(info->argc, info->argv); @@ -254,11 +268,24 @@ pid = [[existing_chrome objectAtIndex:0] processIdentifier]; } + // Initialize the NSApplication (and ensure that it was not previously + // initialized). + [AppShimApplication sharedApplication]; + CHECK([NSApp isKindOfClass:[AppShimApplication class]]); + base::MessageLoopForUI main_message_loop; ui::WindowResizeHelperMac::Get()->Init(main_message_loop.task_runner()); base::PlatformThread::SetName("CrAppShimMain"); AppShimController controller(info); + // TODO(https://crbug.com/925998): This workaround ensures that there is + // always delayed work enqueued. If there is ever not enqueued delayed work, + // then NSMenus and NSAlerts can start misbehaving (see + // https://crbug.com/920795 for examples). This workaround is not an + // appropriate solution to the problem, and should be replaced by a fix in + // the relevant message pump code. + PostRepeatingDelayedTask(); + // In tests, launching Chrome does nothing, and we won't get a ping response, // so just assume the socket exists. if (pid == -1 &&
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index c0710bf..8b98f6fb 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3049,6 +3049,12 @@ "search/search_suggest/search_suggest_service_factory.cc", "search/search_suggest/search_suggest_service_factory.h", "search/search_suggest/search_suggest_service_observer.h", + "serial/chrome_serial_delegate.cc", + "serial/chrome_serial_delegate.h", + "serial/serial_chooser_context.cc", + "serial/serial_chooser_context.h", + "serial/serial_chooser_context_factory.cc", + "serial/serial_chooser_context_factory.h", "signin/signin_promo.cc", "signin/signin_promo.h", "signin/signin_ui_util.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 4556bda..6180851 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3431,12 +3431,6 @@ flag_descriptions::kEnableNetworkLoggingToFileDescription, kOsAll, SINGLE_VALUE_TYPE(network::switches::kLogNetLog)}, -#if defined(OS_CHROMEOS) - {"disable-multi-mirroring", flag_descriptions::kDisableMultiMirroringName, - flag_descriptions::kDisableMultiMirroringDescription, kOsCrOS, - SINGLE_VALUE_TYPE(switches::kDisableMultiMirroring)}, -#endif // defined(OS_CHROMEOS) - #if defined(OS_ANDROID) {"grant-notifications-to-dse", flag_descriptions::kGrantNotificationsToDSEName,
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc index e841cbd..056cc1c 100644 --- a/chrome/browser/apps/app_service/app_service_proxy.cc +++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -108,6 +108,13 @@ }); } +void AppServiceProxy::Shutdown() { +#if defined(OS_CHROMEOS) + extension_apps_.Shutdown(); + extension_web_apps_.Shutdown(); +#endif // OS_CHROMEOS +} + void AppServiceProxy::OnApps(std::vector<apps::mojom::AppPtr> deltas) { cache_.OnApps(std::move(deltas)); }
diff --git a/chrome/browser/apps/app_service/app_service_proxy.h b/chrome/browser/apps/app_service/app_service_proxy.h index 264676f..2efc254 100644 --- a/chrome/browser/apps/app_service/app_service_proxy.h +++ b/chrome/browser/apps/app_service/app_service_proxy.h
@@ -56,6 +56,9 @@ void OpenNativeSettings(const std::string& app_id); private: + // KeyedService overrides. + void Shutdown() override; + // apps::mojom::Subscriber overrides. void OnApps(std::vector<apps::mojom::AppPtr> deltas) override; void Clone(apps::mojom::SubscriberRequest request) override;
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index 0728843e..d52cb379 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -18,9 +18,11 @@ #include "chrome/browser/ui/app_list/arc/arc_app_icon_descriptor.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/grit/component_extension_resources.h" +#include "components/arc/app_permissions/arc_app_permissions_bridge.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service_manager.h" #include "components/arc/common/app.mojom.h" +#include "components/arc/common/app_permissions.mojom.h" #include "content/public/common/service_manager_connection.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "services/data_decoder/public/cpp/decode_image.h" @@ -221,7 +223,38 @@ void ArcApps::SetPermission(const std::string& app_id, apps::mojom::PermissionPtr permission) { - NOTIMPLEMENTED(); + const std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = + prefs_->GetApp(app_id); + if (!app_info) { + LOG(ERROR) << "SetPermission failed, could not find app with id " << app_id; + return; + } + + auto* arc_service_manager = arc::ArcServiceManager::Get(); + if (!arc_service_manager) { + LOG(WARNING) << "SetPermission failed, ArcServiceManager not available."; + return; + } + + auto permission_type = + static_cast<arc::mojom::AppPermission>(permission->permission_id); + if (permission->value) { + auto* permissions_instance = ARC_GET_INSTANCE_FOR_METHOD( + arc_service_manager->arc_bridge_service()->app_permissions(), + GrantPermission); + if (permissions_instance) { + permissions_instance->GrantPermission(app_info->package_name, + permission_type); + } + } else { + auto* permissions_instance = ARC_GET_INSTANCE_FOR_METHOD( + arc_service_manager->arc_bridge_service()->app_permissions(), + RevokePermission); + if (permissions_instance) { + permissions_instance->RevokePermission(app_info->package_name, + permission_type); + } + } } void ArcApps::Uninstall(const std::string& app_id) {
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc index 61ce1fc..b1230ef 100644 --- a/chrome/browser/apps/app_service/extension_apps.cc +++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/apps/app_service/extension_apps.h" +#include <memory> #include <utility> #include <vector> @@ -24,6 +25,8 @@ #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/services/app_service/public/mojom/types.mojom.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/content_settings_types.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "mojo/public/cpp/bindings/interface_request.h" @@ -93,8 +96,15 @@ app_service->RegisterPublisher(std::move(publisher), app_type_); profile_ = profile; + DCHECK(profile_); + observer_.Add(extensions::ExtensionRegistry::Get(profile_)); + HostContentSettingsMapFactory::GetForProfile(profile_)->AddObserver(this); +} + +void ExtensionApps::Shutdown() { if (profile_) { - observer_.Add(extensions::ExtensionRegistry::Get(profile_)); + HostContentSettingsMapFactory::GetForProfile(profile_)->RemoveObserver( + this); } } @@ -292,6 +302,43 @@ } } +void ExtensionApps::OnContentSettingChanged( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier) { + // If content_type is not one of the supported permissions, do nothing. + if (!base::ContainsValue(kSupportedPermissionTypes, content_type)) { + return; + } + + DCHECK(profile_); + + extensions::ExtensionRegistry* registry = + extensions::ExtensionRegistry::Get(profile_); + + std::unique_ptr<extensions::ExtensionSet> extensions = + registry->GenerateInstalledExtensionsSet( + extensions::ExtensionRegistry::ENABLED | + extensions::ExtensionRegistry::DISABLED | + extensions::ExtensionRegistry::TERMINATED); + + for (const auto& extension : *extensions) { + const GURL url = + extensions::AppLaunchInfo::GetFullLaunchURL(extension.get()); + + if (extension->from_bookmark() && primary_pattern.Matches(url) && + Accepts(extension.get())) { + apps::mojom::AppPtr app = apps::mojom::App::New(); + app->app_type = apps::mojom::AppType::kWeb; + app->app_id = extension->id(); + PopulatePermissions(extension.get(), &app->permissions); + + Publish(std::move(app)); + } + } +} + void ExtensionApps::OnExtensionInstalled( content::BrowserContext* browser_context, const extensions::Extension* extension, @@ -303,13 +350,7 @@ // TODO(crbug.com/826982): Does the is_update case need to be handled // differently? E.g. by only passing through fields that have changed. - apps::mojom::AppPtr app = Convert(extension, apps::mojom::Readiness::kReady); - - subscribers_.ForAllPtrs([&app](apps::mojom::Subscriber* subscriber) { - std::vector<apps::mojom::AppPtr> apps; - apps.push_back(app.Clone()); - subscriber->OnApps(std::move(apps)); - }); + Publish(Convert(extension, apps::mojom::Readiness::kReady)); } void ExtensionApps::OnExtensionUninstalled( @@ -328,6 +369,10 @@ app->app_id = extension->id(); app->readiness = apps::mojom::Readiness::kUninstalledByUser; + Publish(std::move(app)); +} + +void ExtensionApps::Publish(apps::mojom::AppPtr app) { subscribers_.ForAllPtrs([&app](apps::mojom::Subscriber* subscriber) { std::vector<apps::mojom::AppPtr> apps; apps.push_back(app.Clone()); @@ -357,6 +402,44 @@ return app_id == arc::kPlayStoreAppId; } +void ExtensionApps::PopulatePermissions( + const extensions::Extension* extension, + std::vector<mojom::PermissionPtr>* target) { + const GURL url = extensions::AppLaunchInfo::GetFullLaunchURL(extension); + + auto* host_content_settings_map = + HostContentSettingsMapFactory::GetForProfile(profile_); + DCHECK(host_content_settings_map); + + for (ContentSettingsType type : kSupportedPermissionTypes) { + ContentSetting setting = host_content_settings_map->GetContentSetting( + url, url, type, std::string() /* resource_identifier */); + + // Map ContentSettingsType to an apps::mojom::TriState value + apps::mojom::TriState setting_val; + switch (setting) { + case CONTENT_SETTING_ALLOW: + setting_val = apps::mojom::TriState::kAllow; + break; + case CONTENT_SETTING_ASK: + setting_val = apps::mojom::TriState::kAsk; + break; + case CONTENT_SETTING_BLOCK: + setting_val = apps::mojom::TriState::kBlock; + break; + default: + setting_val = apps::mojom::TriState::kAsk; + } + + auto permission = apps::mojom::Permission::New(); + permission->permission_id = static_cast<uint32_t>(type); + permission->value_type = apps::mojom::PermissionValueType::kTriState; + permission->value = static_cast<uint32_t>(setting_val); + + target->push_back(std::move(permission)); + } +} + apps::mojom::AppPtr ExtensionApps::Convert( const extensions::Extension* extension, apps::mojom::Readiness readiness) { @@ -375,38 +458,7 @@ // Extensions where |from_bookmark| is true wrap websites and use web // permissions. if (extension->from_bookmark()) { - const GURL url = extensions::AppLaunchInfo::GetFullLaunchURL(extension); - auto* host_content_settings_map = - HostContentSettingsMapFactory::GetForProfile(profile_); - DCHECK(host_content_settings_map); - - for (ContentSettingsType type : kSupportedPermissionTypes) { - ContentSetting setting = host_content_settings_map->GetContentSetting( - url, url, type, std::string() /* resource_identifier */); - - // Map ContentSettingsType to an apps::mojom::TriState value - apps::mojom::TriState setting_val; - switch (setting) { - case CONTENT_SETTING_ALLOW: - setting_val = apps::mojom::TriState::kAllow; - break; - case CONTENT_SETTING_ASK: - setting_val = apps::mojom::TriState::kAsk; - break; - case CONTENT_SETTING_BLOCK: - setting_val = apps::mojom::TriState::kBlock; - break; - default: - setting_val = apps::mojom::TriState::kAsk; - } - - auto permission = apps::mojom::Permission::New(); - permission->permission_id = static_cast<uint32_t>(type); - permission->value_type = apps::mojom::PermissionValueType::kTriState; - permission->value = static_cast<uint32_t>(setting_val); - - app->permissions.push_back(std::move(permission)); - } + PopulatePermissions(extension, &app->permissions); } // TODO(crbug.com/826982): does this catch default installed web apps?
diff --git a/chrome/browser/apps/app_service/extension_apps.h b/chrome/browser/apps/app_service/extension_apps.h index 6079d84a..51477ef2 100644 --- a/chrome/browser/apps/app_service/extension_apps.h +++ b/chrome/browser/apps/app_service/extension_apps.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/scoped_observer.h" #include "chrome/services/app_service/public/mojom/app_service.mojom.h" +#include "components/content_settings/core/browser/content_settings_observer.h" #include "extensions/browser/extension_registry_observer.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" @@ -30,7 +31,8 @@ // // See chrome/services/app_service/README.md. class ExtensionApps : public apps::mojom::Publisher, - public extensions::ExtensionRegistryObserver { + public extensions::ExtensionRegistryObserver, + public content_settings::Observer { public: ExtensionApps(); ~ExtensionApps() override; @@ -38,6 +40,7 @@ void Initialize(const apps::mojom::AppServicePtr& app_service, Profile* profile, apps::mojom::AppType type); + void Shutdown(); private: // Determines whether the given extension should be treated as type app_type_, @@ -61,6 +64,12 @@ void Uninstall(const std::string& app_id) override; void OpenNativeSettings(const std::string& app_id) override; + // content_settings::Observer overrides. + void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier) override; + // extensions::ExtensionRegistryObserver overrides. void OnExtensionInstalled(content::BrowserContext* browser_context, const extensions::Extension* extension, @@ -69,12 +78,16 @@ const extensions::Extension* extension, extensions::UninstallReason reason) override; + void Publish(apps::mojom::AppPtr app); + // Checks if extension is disabled and if enable flow should be started. // Returns true if extension enable flow is started or there is already one // running. bool RunExtensionEnableFlow(const std::string& app_id); static bool IsBlacklisted(const std::string& app_id); + void PopulatePermissions(const extensions::Extension* extension, + std::vector<mojom::PermissionPtr>* target); apps::mojom::AppPtr Convert(const extensions::Extension* extension, apps::mojom::Readiness readiness); void ConvertVector(const extensions::ExtensionSet& extensions,
diff --git a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc index 15fb04b..eabd3a2a 100644 --- a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc +++ b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
@@ -15,6 +15,7 @@ #include "extensions/browser/app_window/native_app_window.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/result_catcher.h" +#include "ui/base/ui_base_features.h" #if defined(OS_MACOSX) #include "base/mac/mac_util.h" @@ -457,6 +458,9 @@ #define MAYBE_TestFullscreen TestFullscreen #endif IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, MAYBE_TestFullscreen) { + // Flaky on CrOS + IsUsingWindowService. https://crbug.com/926007 + if (features::IsUsingWindowService()) + return; ASSERT_TRUE(RunAppWindowInteractiveTest("testFullscreen")) << message_; }
diff --git a/chrome/browser/autofill/autofill_uitest_util.cc b/chrome/browser/autofill/autofill_uitest_util.cc index b4dd07b..eb515840 100644 --- a/chrome/browser/autofill/autofill_uitest_util.cc +++ b/chrome/browser/autofill/autofill_uitest_util.cc
@@ -90,6 +90,15 @@ observer.Wait(); } +void AddTestServerCreditCard(Browser* browser, const CreditCard& card) { + PdmChangeWaiter observer(browser); + GetPersonalDataManager(browser->profile())->AddFullServerCreditCard(card); + + // AddCreditCard is asynchronous. Wait for it to finish before continuing the + // tests. + observer.Wait(); +} + void AddTestAutofillData(Browser* browser, const AutofillProfile& profile, const CreditCard& card) {
diff --git a/chrome/browser/autofill/autofill_uitest_util.h b/chrome/browser/autofill/autofill_uitest_util.h index 6140db1c..89ce6d15 100644 --- a/chrome/browser/autofill/autofill_uitest_util.h +++ b/chrome/browser/autofill/autofill_uitest_util.h
@@ -18,6 +18,7 @@ void SetTestProfile(Browser* browser, const AutofillProfile& profile); void SetTestProfiles(Browser* browser, std::vector<AutofillProfile>* profiles); void AddTestCreditCard(Browser* browser, const CreditCard& card); +void AddTestServerCreditCard(Browser* browser, const CreditCard& card); void AddTestAutofillData(Browser* browser, const AutofillProfile& profile, const CreditCard& card);
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index cbfe25d..3ebfb6d 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -690,6 +690,10 @@ content::HostZoomMap* zoom_map = content::HostZoomMap::GetDefaultForBrowserContext(profile_); zoom_map->ClearZoomLevels(delete_begin_, delete_end_); + + host_content_settings_map_->ClearSettingsForOneTypeWithPredicate( + CONTENT_SETTINGS_TYPE_SERIAL_CHOOSER_DATA, delete_begin_, delete_end_, + HostContentSettingsMap::PatternSourcePredicate()); #else // Reset the Default Search Engine permissions to their default. SearchPermissionsService* search_permissions_service =
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index c75d5088..99e16d50 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -116,6 +116,7 @@ #include "chrome/browser/safe_browsing/ui_manager.h" #include "chrome/browser/safe_browsing/url_checker_delegate_impl.h" #include "chrome/browser/search/search.h" +#include "chrome/browser/serial/chrome_serial_delegate.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h" #include "chrome/browser/signin/chrome_signin_url_loader_throttle.h" @@ -4922,6 +4923,14 @@ tab_helper->CreateWebUsbService(render_frame_host, std::move(request)); } +#if !defined(OS_ANDROID) +content::SerialDelegate* ChromeContentBrowserClient::GetSerialDelegate() { + if (!serial_delegate_) + serial_delegate_ = std::make_unique<ChromeSerialDelegate>(); + return serial_delegate_.get(); +} +#endif + std::unique_ptr<content::AuthenticatorRequestClientDelegate> ChromeContentBrowserClient::GetWebAuthenticationRequestDelegate( content::RenderFrameHost* render_frame_host) {
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 18ff27e7e..b2fd7010 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -74,6 +74,8 @@ class Origin; } +class ChromeSerialDelegate; + // Returns the user agent of Chrome. std::string GetUserAgent(); @@ -490,6 +492,9 @@ void CreateWebUsbService( content::RenderFrameHost* render_frame_host, mojo::InterfaceRequest<blink::mojom::WebUsbService> request) override; +#if !defined(OS_ANDROID) + content::SerialDelegate* GetSerialDelegate() override; +#endif bool ShowPaymentHandlerWindow( content::BrowserContext* browser_context, const GURL& url, @@ -642,6 +647,10 @@ ChromeFeatureListCreator* chrome_feature_list_creator_; +#if !defined(OS_ANDROID) + std::unique_ptr<ChromeSerialDelegate> serial_delegate_; +#endif + base::WeakPtrFactory<ChromeContentBrowserClient> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ChromeContentBrowserClient);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index eb4c973..085d7c1c 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -2046,6 +2046,8 @@ testonly = true sources = [ + "accessibility/test_accessibility_focus_ring_controller.cc", + "accessibility/test_accessibility_focus_ring_controller.h", "android_sms/fake_android_sms_app_manager.cc", "android_sms/fake_android_sms_app_manager.h", "android_sms/fake_android_sms_app_setup_controller.cc", @@ -2322,6 +2324,7 @@ "login/error_screens_histogram_helper_unittest.cc", "login/existing_user_controller_auto_login_unittest.cc", "login/hwid_checker_unittest.cc", + "login/lock/screen_locker_unittest.cc", "login/profile_auth_data_unittest.cc", "login/quick_unlock/fingerprint_storage_unittest.cc", "login/quick_unlock/pin_storage_prefs_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc new file mode 100644 index 0000000..d59c8f8 --- /dev/null +++ b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc
@@ -0,0 +1,66 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h" + +#include <utility> + +#include "ash/public/interfaces/constants.mojom.h" +#include "content/public/common/service_manager_connection.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/service_filter.h" + +TestAccessibilityFocusRingController::TestAccessibilityFocusRingController() { + CHECK(content::ServiceManagerConnection::GetForProcess()) + << "ServiceManager is uninitialized. Did you forget to create a " + "content::TestServiceManagerContext?"; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->OverrideBinderForTesting( + service_manager::ServiceFilter::ByName(ash::mojom::kServiceName), + ash::mojom::AccessibilityFocusRingController::Name_, + base::BindRepeating(&TestAccessibilityFocusRingController::Bind, + base::Unretained(this))); +} + +TestAccessibilityFocusRingController::~TestAccessibilityFocusRingController() { + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->ClearBinderOverrideForTesting( + service_manager::ServiceFilter::ByName(ash::mojom::kServiceName), + ash::mojom::AccessibilityFocusRingController::Name_); +} + +void TestAccessibilityFocusRingController::SetFocusRingColor( + uint32_t skcolor, + const std::string& caller_id) {} + +void TestAccessibilityFocusRingController::ResetFocusRingColor( + const std::string& caller_id) {} + +void TestAccessibilityFocusRingController::SetFocusRing( + const std::vector<gfx::Rect>& rects_in_screen, + ash::mojom::FocusRingBehavior focus_ring_behavior, + const std::string& caller_id) {} + +void TestAccessibilityFocusRingController::HideFocusRing( + const std::string& caller_id) {} + +void TestAccessibilityFocusRingController::SetHighlights( + const std::vector<gfx::Rect>& rects_in_screen, + uint32_t skcolor) {} + +void TestAccessibilityFocusRingController::HideHighlights() {} + +void TestAccessibilityFocusRingController::Bind( + mojo::ScopedMessagePipeHandle handle) { + binding_.Bind( + ash::mojom::AccessibilityFocusRingControllerRequest(std::move(handle))); +} +void TestAccessibilityFocusRingController::EnableDoubleFocusRing( + uint32_t skcolor, + const std::string& caller_id) {} + +void TestAccessibilityFocusRingController::DisableDoubleFocusRing( + const std::string& caller_id) {}
diff --git a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h new file mode 100644 index 0000000..173b7f2a --- /dev/null +++ b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h
@@ -0,0 +1,50 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_TEST_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_ +#define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_TEST_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_ + +#include <string> +#include <vector> + +#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" + +// Test implementation of ash's mojo AccessibilityFocusRingController interface. +// +// Registers itself to ServiceManager on construction and deregisters +// on destruction. +// +// Note: A ServiceManagerConnection must be initialized before constructing this +// object. Consider using content::TestServiceManagerContext on your tests. +class TestAccessibilityFocusRingController + : public ash::mojom::AccessibilityFocusRingController { + public: + TestAccessibilityFocusRingController(); + ~TestAccessibilityFocusRingController() override; + + // ash::mojom::AccessibilityFocusRingController: + void SetFocusRingColor(uint32_t skcolor, + const std::string& caller_id) override; + void ResetFocusRingColor(const std::string& caller_id) override; + void SetFocusRing(const std::vector<gfx::Rect>& rects_in_screen, + ash::mojom::FocusRingBehavior focus_ring_behavior, + const std::string& caller_id) override; + void HideFocusRing(const std::string& caller_id) override; + void SetHighlights(const std::vector<gfx::Rect>& rects_in_screen, + uint32_t skcolor) override; + void HideHighlights() override; + void EnableDoubleFocusRing(uint32_t skcolor, + const std::string& caller_id) override; + void DisableDoubleFocusRing(const std::string& caller_id) override; + + private: + void Bind(mojo::ScopedMessagePipeHandle handle); + mojo::Binding<ash::mojom::AccessibilityFocusRingController> binding_{this}; + + DISALLOW_COPY_AND_ASSIGN(TestAccessibilityFocusRingController); +}; + +#endif // CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_TEST_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/android_sms/android_sms_service_factory.cc b/chrome/browser/chromeos/android_sms/android_sms_service_factory.cc index a9213c0..6982d723 100644 --- a/chrome/browser/chromeos/android_sms/android_sms_service_factory.cc +++ b/chrome/browser/chromeos/android_sms/android_sms_service_factory.cc
@@ -9,8 +9,10 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/notifications/notification_display_service_factory.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" #include "chrome/browser/web_applications/web_app_provider_factory.h" +#include "chrome/browser/web_applications/web_app_utils.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/services/multidevice_setup/public/cpp/prefs.h" #include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" @@ -23,10 +25,29 @@ namespace { -bool IsFeatureAllowed(content::BrowserContext* context) { - return multidevice_setup::IsFeatureAllowed( - multidevice_setup::mojom::Feature::kMessages, - Profile::FromBrowserContext(context)->GetPrefs()); +bool ShouldStartAndroidSmsService(Profile* profile) { + const bool multidevice_feature_allowed = multidevice_setup::IsFeatureAllowed( + multidevice_setup::mojom::Feature::kMessages, profile->GetPrefs()); + + const bool android_messages_integration_enabled = + base::FeatureList::IsEnabled( + chromeos::features::kAndroidMessagesIntegration); + + const bool has_user_for_profile = + !!ProfileHelper::Get()->GetUserByProfile(profile); + + return web_app::AreWebAppsEnabled(profile) && !profile->IsGuestSession() && + multidevice_feature_allowed && android_messages_integration_enabled && + has_user_for_profile; +} + +content::BrowserContext* GetBrowserContextForAndroidSms( + content::BrowserContext* context) { + // Use original profile to create only one KeyedService instance. + Profile* original_profile = + Profile::FromBrowserContext(context)->GetOriginalProfile(); + return ShouldStartAndroidSmsService(original_profile) ? original_profile + : nullptr; } } // namespace @@ -61,15 +82,7 @@ KeyedService* AndroidSmsServiceFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - if (!IsFeatureAllowed(context) || - !base::FeatureList::IsEnabled( - chromeos::features::kAndroidMessagesIntegration)) { - return nullptr; - } - Profile* profile = Profile::FromBrowserContext(context); - if (ProfileHelper::Get()->GetUserByProfile(profile) == nullptr) - return nullptr; return new AndroidSmsService( profile, HostContentSettingsMapFactory::GetForProfile(profile), @@ -79,6 +92,11 @@ app_list::AppListSyncableServiceFactory::GetForProfile(profile)); } +content::BrowserContext* AndroidSmsServiceFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return GetBrowserContextForAndroidSms(context); +} + bool AndroidSmsServiceFactory::ServiceIsCreatedWithBrowserContext() const { return true; }
diff --git a/chrome/browser/chromeos/android_sms/android_sms_service_factory.h b/chrome/browser/chromeos/android_sms/android_sms_service_factory.h index f584067..daabe7a 100644 --- a/chrome/browser/chromeos/android_sms/android_sms_service_factory.h +++ b/chrome/browser/chromeos/android_sms/android_sms_service_factory.h
@@ -33,6 +33,8 @@ // BrowserContextKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; bool ServiceIsCreatedWithBrowserContext() const override; bool ServiceIsNULLWhileTesting() const override; void RegisterProfilePrefs(
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc index bf1efc2..aa30d8d 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc
@@ -32,6 +32,7 @@ case mojom::AccessibilityEventType::VIEW_SCROLLED: return ax::mojom::Event::kScrollPositionChanged; case mojom::AccessibilityEventType::VIEW_SELECTED: + return ax::mojom::Event::kValueChanged; case mojom::AccessibilityEventType::VIEW_HOVER_EXIT: case mojom::AccessibilityEventType::TOUCH_EXPLORATION_GESTURE_START: case mojom::AccessibilityEventType::TOUCH_EXPLORATION_GESTURE_END:
diff --git a/chrome/browser/chromeos/dbus/org.chromium.ChromeFeaturesService.conf b/chrome/browser/chromeos/dbus/org.chromium.ChromeFeaturesService.conf index 9048bde..bf11685 100644 --- a/chrome/browser/chromeos/dbus/org.chromium.ChromeFeaturesService.conf +++ b/chrome/browser/chromeos/dbus/org.chromium.ChromeFeaturesService.conf
@@ -6,13 +6,14 @@ found in the LICENSE file. --> <busconfig> + <!-- vmc runs as chronos --> <policy user="chronos"> <allow own="org.chromium.ChromeFeaturesService"/> </policy> - <!-- vmc runs as chronos --> - <policy user="chronos"> + <!-- upstart and tast run as root --> + <policy user="root"> <allow send_destination="org.chromium.ChromeFeaturesService" - send_interface="org.chromium.ChromeFeaturesService"/> + send_interface="org.chromium.ChromeFeaturesServiceInterface"/> </policy> </busconfig>
diff --git a/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc b/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc index 771b96a..ed9852c7 100644 --- a/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h" +#include "base/test/scoped_feature_list.h" +#include "media/base/media_switches.h" + namespace file_manager { template <GuestMode MODE> @@ -79,12 +82,12 @@ StartTest(); } -#if defined(OS_CHROMEOS) && defined(MEMORY_SANITIZER) -#define MAYBE_NativeMediaKey DISABLED_NativeMediaKey -#else -#define MAYBE_NativeMediaKey NativeMediaKey -#endif -IN_PROC_BROWSER_TEST_F(AudioPlayerBrowserTest, MAYBE_NativeMediaKey) { +IN_PROC_BROWSER_TEST_F(AudioPlayerBrowserTest, NativeMediaKey) { + // The HardwareMediaKeyHandling feature makes key handling flaky. + // See https://crbug.com/902519. + base::test::ScopedFeatureList disable_media_key_handling; + disable_media_key_handling.InitAndDisableFeature( + media::kHardwareMediaKeyHandling); set_test_case_name("mediaKeyNative"); StartTest(); }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 0bc3831..67cab0d 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -493,6 +493,8 @@ #if !defined(MEMORY_SANITIZER) TestCase("openQuickViewPdf"), #endif + TestCase("openQuickViewKeyboardUpDownChangesView"), + TestCase("openQuickViewKeyboardLeftRightChangesView"), TestCase("openQuickViewScrollText"), TestCase("openQuickViewScrollHtml"), TestCase("openQuickViewBackgroundColorText"), @@ -583,6 +585,8 @@ ::testing::Values( TestCase("transferFromDriveToDownloads").DisableDriveFs(), TestCase("transferFromDriveToDownloads").EnableDriveFs(), + TestCase("transferFromDownloadsToMyFiles").EnableMyFilesVolume(), + TestCase("transferFromDownloadsToMyFilesMove").EnableMyFilesVolume(), TestCase("transferFromDownloadsToDrive").DisableDriveFs(), TestCase("transferFromDownloadsToDrive").EnableDriveFs(), TestCase("transferFromSharedToDownloads").DisableDriveFs(),
diff --git a/chrome/browser/chromeos/file_manager/video_player_browsertest.cc b/chrome/browser/chromeos/file_manager/video_player_browsertest.cc index 9dad913..53f0719 100644 --- a/chrome/browser/chromeos/file_manager/video_player_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/video_player_browsertest.cc
@@ -4,7 +4,9 @@ #include "chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h" +#include "base/test/scoped_feature_list.h" #include "chromeos/constants/chromeos_switches.h" +#include "media/base/media_switches.h" namespace file_manager { @@ -73,8 +75,14 @@ StartTest(); } -// Flaky see https://crbug.com/921418. +// Flaky. Suspect due to a race when loading Chromecast integration. +// See https://crbug.com/926035. IN_PROC_BROWSER_TEST_F(VideoPlayerBrowserTest, DISABLED_NativeMediaKey) { + // The HardwareMediaKeyHandling feature makes key handling flaky. + // See https://crbug.com/902519. + base::test::ScopedFeatureList disable_media_key_handling; + disable_media_key_handling.InitAndDisableFeature( + media::kHardwareMediaKeyHandling); set_test_case_name("mediaKeyNative"); StartTest(); }
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc b/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc new file mode 100644 index 0000000..2ad1344 --- /dev/null +++ b/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
@@ -0,0 +1,138 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/lock/screen_locker.h" + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" +#include "chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h" +#include "chrome/browser/chromeos/input_method/mock_input_method_manager_impl.h" +#include "chrome/browser/chromeos/lock_screen_apps/state_controller.h" +#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/chromeos/settings/device_settings_test_helper.h" +#include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h" +#include "chrome/browser/chromeos/settings/stub_install_attributes.h" +#include "chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h" +#include "chrome/browser/ui/ash/login_screen_client.h" +#include "chrome/browser/ui/ash/session_controller_client.h" +#include "chrome/browser/ui/ash/test_login_screen.h" +#include "chrome/browser/ui/ash/test_session_controller.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/audio/cras_audio_handler.h" +#include "chromeos/cryptohome/system_salt_getter.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/login/login_state/login_state.h" +#include "chromeos/system/fake_statistics_provider.h" +#include "components/account_id/account_id.h" +#include "components/session_manager/core/session_manager.h" +#include "components/user_manager/scoped_user_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_service_manager_context.h" +#include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "media/audio/audio_manager.h" +#include "media/audio/sounds/sounds_manager.h" +#include "media/audio/test_audio_thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +class ScreenLockerUnitTest : public testing::Test { + public: + ScreenLockerUnitTest() = default; + ~ScreenLockerUnitTest() override = default; + + void SetUp() override { + DBusThreadManager::Initialize(); + + // MojoSystemInfoDispatcher dependency: + bluez::BluezDBusManager::GetSetterForTesting(); + + // Initialize SessionControllerClient and dependencies: + chromeos::LoginState::Initialize(); + CHECK(testing_profile_manager_.SetUp()); + session_controller_client_ = std::make_unique<SessionControllerClient>(); + session_controller_client_->Init(); + + // Initialize AccessibilityManager and dependencies: + media::SoundsManager::Create(); + input_method::InputMethodManager::Initialize( + // Owned by InputMethodManager + new input_method::MockInputMethodManagerImpl()); + CrasAudioHandler::InitializeForTesting(); + chromeos::AccessibilityManager::Initialize(); + + // Initialize ScreenLocker dependencies: + SystemSaltGetter::Initialize(); + const AccountId account_id = + AccountId::FromUserEmail("testemail@example.com"); + fake_user_manager_->AddUser(account_id); + fake_user_manager_->LoginUser(account_id); + CHECK(user_manager::UserManager::Get()->GetPrimaryUser()); + session_manager::SessionManager::Get()->CreateSession( + account_id, account_id.GetUserEmail(), false); + } + + void TearDown() override { + input_method::InputMethodManager::Shutdown(); + media::SoundsManager::Shutdown(); + media::AudioManager::Get()->Shutdown(); + session_controller_client_.reset(); + chromeos::LoginState::Shutdown(); + } + + protected: + // Needed for main loop and posting async tasks. + content::TestBrowserThreadBundle thread_bundle_; + + // Needed to set up Service Manager and create mojo fakes. + content::TestServiceManagerContext context_; + + // ViewsScreenLocker dependencies: + lock_screen_apps::StateController state_controller_; + // * MojoSystemInfoDispatcher dependencies: + ScopedTestingCrosSettings scoped_testing_cros_settings_; + system::ScopedFakeStatisticsProvider fake_statictics_provider_; + // * ChromeUserSelectionScreen dependencies: + chromeos::ScopedStubInstallAttributes test_install_attributes_; + + // ScreenLocker dependencies: + // * AccessibilityManager dependencies: + FakeAccessibilityController fake_accessibility_controller_; + TestAccessibilityFocusRingController + test_accessibility_focus_ring_controller_; + std::unique_ptr<media::AudioManager> audio_manager_{ + media::AudioManager::CreateForTesting( + std::make_unique<media::TestAudioThread>())}; + // * LoginScreenClient dependencies: + session_manager::SessionManager session_manager_; + TestLoginScreen test_login_screen_; + LoginScreenClient login_screen_client_; + // * SessionControllerClient dependencies: + FakeChromeUserManager* fake_user_manager_{new FakeChromeUserManager()}; + user_manager::ScopedUserManager scoped_user_manager_{ + base::WrapUnique(fake_user_manager_)}; + TestingProfileManager testing_profile_manager_{ + TestingBrowserProcess::GetGlobal()}; + ScopedDeviceSettingsTestHelper device_settings_test_helper_; + TestSessionController test_session_controller_; + std::unique_ptr<SessionControllerClient> session_controller_client_; + + DISALLOW_COPY_AND_ASSIGN(ScreenLockerUnitTest); +}; + +// Chrome notifies Ash when screen is locked. Ash is responsible for suspending +// the device. +TEST_F(ScreenLockerUnitTest, VerifyAshIsNotifiedOfScreenLocked) { + EXPECT_EQ(0, test_session_controller_.lock_animation_complete_call_count()); + ScreenLocker::Show(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, test_session_controller_.lock_animation_complete_call_count()); + ScreenLocker::Hide(); + // Needed to perform internal cleanup scheduled in ScreenLocker::Hide() + base::RunLoop().RunUntilIdle(); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_manager_test.cc b/chrome/browser/chromeos/login/login_manager_test.cc index 8a242db..417bb707 100644 --- a/chrome/browser/chromeos/login/login_manager_test.cc +++ b/chrome/browser/chromeos/login/login_manager_test.cc
@@ -96,11 +96,11 @@ ASSERT_TRUE(gaia_https_forwarder_.Initialize( kGAIAHost, embedded_test_server()->base_url())); - MixinBasedBrowserTest::SetUp(); + MixinBasedInProcessBrowserTest::SetUp(); } void LoginManagerTest::TearDownOnMainThread() { - MixinBasedBrowserTest::TearDownOnMainThread(); + MixinBasedInProcessBrowserTest::TearDownOnMainThread(); EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); } @@ -117,7 +117,7 @@ fake_gaia_.Initialize(); - MixinBasedBrowserTest::SetUpCommandLine(command_line); + MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line); } void LoginManagerTest::SetUpOnMainThread() { @@ -153,7 +153,7 @@ should_launch_browser_); session_manager_test_api.SetShouldObtainTokenHandleInTests(false); - MixinBasedBrowserTest::SetUpOnMainThread(); + MixinBasedInProcessBrowserTest::SetUpOnMainThread(); } void LoginManagerTest::RegisterUser(const AccountId& account_id) {
diff --git a/chrome/browser/chromeos/login/login_manager_test.h b/chrome/browser/chromeos/login/login_manager_test.h index a527e85..45742d5 100644 --- a/chrome/browser/chromeos/login/login_manager_test.h +++ b/chrome/browser/chromeos/login/login_manager_test.h
@@ -8,7 +8,7 @@ #include <string> #include "base/macros.h" -#include "chrome/browser/chromeos/login/mixin_based_browser_test.h" +#include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h" #include "chrome/browser/chromeos/login/test/https_forwarder.h" #include "chrome/browser/chromeos/login/test/js_checker.h" #include "google_apis/gaia/fake_gaia.h" @@ -25,7 +25,7 @@ // out-of-box as completed. // Guarantees that WebUI has been initialized by waiting for // NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE notification. -class LoginManagerTest : public MixinBasedBrowserTest { +class LoginManagerTest : public MixinBasedInProcessBrowserTest { public: LoginManagerTest(bool should_launch_browser, bool should_initialize_webui);
diff --git a/chrome/browser/chromeos/login/login_ui_browsertest.cc b/chrome/browser/chromeos/login/login_ui_browsertest.cc index c2247d6..af44f5b 100644 --- a/chrome/browser/chromeos/login/login_ui_browsertest.cc +++ b/chrome/browser/chromeos/login/login_ui_browsertest.cc
@@ -42,18 +42,18 @@ kTestUsers[i].email, kTestUsers[i].gaia_id)); } - screenshot_testing_ = new ScreenshotTestingMixin; - screenshot_testing_->IgnoreArea(areas::kClockArea); - screenshot_testing_->IgnoreArea(areas::kFirstUserpod); - screenshot_testing_->IgnoreArea(areas::kSecondUserpod); - AddMixin(base::WrapUnique(screenshot_testing_)); + screenshot_testing_.IgnoreArea(areas::kClockArea); + screenshot_testing_.IgnoreArea(areas::kFirstUserpod); + screenshot_testing_.IgnoreArea(areas::kSecondUserpod); } ~LoginUITest() override {} protected: std::vector<AccountId> test_users_; - ScreenshotTestingMixin* screenshot_testing_; + ScreenshotTestingMixin screenshot_testing_{&mixin_host_}; + + DISALLOW_COPY_AND_ASSIGN(LoginUITest); }; IN_PROC_BROWSER_TEST_F(LoginUITest, PRE_LoginUIVisible) { @@ -77,7 +77,7 @@ "document.querySelectorAll('.pod:not(#user-pod-template)')[1]" ".user.emailAddress == '" + test_users_[1].GetUserEmail() + "'"); - screenshot_testing_->RunScreenshotTesting("LoginUITest-LoginUIVisible"); + screenshot_testing_.RunScreenshotTesting("LoginUITest-LoginUIVisible"); } IN_PROC_BROWSER_TEST_F(LoginUITest, PRE_InterruptedAutoStartEnrollment) {
diff --git a/chrome/browser/chromeos/login/mixin_based_browser_test.cc b/chrome/browser/chromeos/login/mixin_based_browser_test.cc deleted file mode 100644 index 7847cdc4..0000000 --- a/chrome/browser/chromeos/login/mixin_based_browser_test.cc +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/login/mixin_based_browser_test.h" - -#include <utility> - -#include "base/containers/adapters.h" - -namespace chromeos { - -MixinBasedBrowserTest::MixinBasedBrowserTest() : setup_was_launched_(false) {} - -MixinBasedBrowserTest::~MixinBasedBrowserTest() {} - -void MixinBasedBrowserTest::SetUpCommandLine(base::CommandLine* command_line) { - setup_was_launched_ = true; - for (const auto& mixin : mixins_) - mixin->SetUpCommandLine(command_line); -} - -void MixinBasedBrowserTest::SetUpInProcessBrowserTestFixture() { - setup_was_launched_ = true; - for (const auto& mixin : mixins_) - mixin->SetUpInProcessBrowserTestFixture(); -} - -void MixinBasedBrowserTest::SetUpOnMainThread() { - setup_was_launched_ = true; - for (const auto& mixin : mixins_) - mixin->SetUpOnMainThread(); -} - -void MixinBasedBrowserTest::TearDownOnMainThread() { - for (const auto& mixin : base::Reversed(mixins_)) - mixin->TearDownInProcessBrowserTestFixture(); -} - -void MixinBasedBrowserTest::TearDownInProcessBrowserTestFixture() { - for (const auto& mixin : base::Reversed(mixins_)) - mixin->TearDownInProcessBrowserTestFixture(); -} - -void MixinBasedBrowserTest::AddMixin(std::unique_ptr<Mixin> mixin) { - CHECK(!setup_was_launched_) - << "You are trying to add a mixin after setting up has already started."; - mixins_.push_back(std::move(mixin)); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/mixin_based_browser_test.h b/chrome/browser/chromeos/login/mixin_based_browser_test.h deleted file mode 100644 index 9d32795..0000000 --- a/chrome/browser/chromeos/login/mixin_based_browser_test.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MIXIN_BASED_BROWSER_TEST_H_ -#define CHROME_BROWSER_CHROMEOS_LOGIN_MIXIN_BASED_BROWSER_TEST_H_ - -#include <memory> -#include <vector> - -#include "chrome/test/base/in_process_browser_test.h" - -namespace chromeos { - -class MixinBasedBrowserTest : public InProcessBrowserTest { - public: - // A class that can be used to add some features not related directly to the - // testing process in order not to make the test class too complicated and to - // set up them in a proper time (at the same time when the corresponding set - // ups for the main test are run). - // - // To used this you need to derive a class from from - // MixinBasedBrowserTest::Mixin, e.g. MixinYouWantToUse, and declare all - // the methods you'd like in this new class. You also can reload setups and - // teardowns if you need so. Test which wants to use some mixin should call - // AddMixin(mixin_) from its constructor, where mixin_ should be an instance - // of MixinYouWantToUse. - // - // All methods in Mixin are complete analogs of those in InProcessBrowserTest, - // so if some usecases are unclear, take a look at in_process_browser_test.h - class Mixin { - public: - Mixin() {} - virtual ~Mixin() {} - - // Is called before creating the browser and running - // SetUpInProcessBrowserTestFixture. - // Should be used for setting up the command line. - virtual void SetUpCommandLine(base::CommandLine* command_line) {} - - // Is called before creating the browser. - // Should be used to set up the environment for running the browser. - virtual void SetUpInProcessBrowserTestFixture() {} - - // Is called after creating the browser and before executing test code. - // Should be used for setting up things related to the browser object. - virtual void SetUpOnMainThread() {} - - // Is called after executing the test code and before the browser is torn - // down. - // Should be used to do the necessary cleanup on the working browser. - virtual void TearDownOnMainThread() {} - - // Is called after the browser is torn down. - // Should be used to do the remaining cleanup. - virtual void TearDownInProcessBrowserTestFixture() {} - }; - - MixinBasedBrowserTest(); - ~MixinBasedBrowserTest() override; - - // Override from InProcessBrowserTest. - void SetUpCommandLine(base::CommandLine* command_line) override; - void SetUpInProcessBrowserTestFixture() override; - void SetUpOnMainThread() override; - void TearDownOnMainThread() override; - void TearDownInProcessBrowserTestFixture() override; - - protected: - // Adds |mixin| as an mixin for this test, passing ownership - // for it to MixinBasedBrowserTest. - // Should be called in constructor of the test (should be already completed - // before running set ups). - void AddMixin(std::unique_ptr<Mixin> mixin); - - private: - // Keeps all the mixins for this test, - std::vector<std::unique_ptr<Mixin>> mixins_; - - // Is false initially, becomes true when any of SetUp* methods is called. - // Required to check that AddMixin is always called before setting up. - bool setup_was_launched_; -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_LOGIN_MIXIN_BASED_BROWSER_TEST_H_
diff --git a/chrome/browser/chromeos/login/mixin_based_in_process_browser_test.cc b/chrome/browser/chromeos/login/mixin_based_in_process_browser_test.cc new file mode 100644 index 0000000..e181424 --- /dev/null +++ b/chrome/browser/chromeos/login/mixin_based_in_process_browser_test.cc
@@ -0,0 +1,130 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h" + +#include <utility> + +#include "base/containers/adapters.h" + +namespace chromeos { + +InProcessBrowserTestMixin::InProcessBrowserTestMixin( + InProcessBrowserTestMixinHost* host) { + host->mixins_.push_back(this); +} + +InProcessBrowserTestMixin::~InProcessBrowserTestMixin() = default; + +void InProcessBrowserTestMixin::SetUp() {} + +void InProcessBrowserTestMixin::SetUpCommandLine( + base::CommandLine* command_line) {} + +void InProcessBrowserTestMixin::SetUpDefaultCommandLine( + base::CommandLine* command_line) {} + +void InProcessBrowserTestMixin::SetUpInProcessBrowserTestFixture() {} + +void InProcessBrowserTestMixin::SetUpOnMainThread() {} + +void InProcessBrowserTestMixin::TearDownOnMainThread() {} + +void InProcessBrowserTestMixin::TearDownInProcessBrowserTestFixture() {} + +void InProcessBrowserTestMixin::TearDown() {} + +InProcessBrowserTestMixinHost::InProcessBrowserTestMixinHost() = default; + +InProcessBrowserTestMixinHost::~InProcessBrowserTestMixinHost() = default; + +void InProcessBrowserTestMixinHost::SetUp() { + for (InProcessBrowserTestMixin* mixin : mixins_) + mixin->SetUp(); +} + +void InProcessBrowserTestMixinHost::SetUpCommandLine( + base::CommandLine* command_line) { + for (InProcessBrowserTestMixin* mixin : mixins_) + mixin->SetUpCommandLine(command_line); +} + +void InProcessBrowserTestMixinHost::SetUpDefaultCommandLine( + base::CommandLine* command_line) { + for (InProcessBrowserTestMixin* mixin : mixins_) + mixin->SetUpDefaultCommandLine(command_line); +} + +void InProcessBrowserTestMixinHost::SetUpInProcessBrowserTestFixture() { + for (InProcessBrowserTestMixin* mixin : mixins_) + mixin->SetUpInProcessBrowserTestFixture(); +} + +void InProcessBrowserTestMixinHost::SetUpOnMainThread() { + for (InProcessBrowserTestMixin* mixin : mixins_) + mixin->SetUpOnMainThread(); +} + +void InProcessBrowserTestMixinHost::TearDownOnMainThread() { + for (InProcessBrowserTestMixin* mixin : base::Reversed(mixins_)) + mixin->TearDownOnMainThread(); +} + +void InProcessBrowserTestMixinHost::TearDownInProcessBrowserTestFixture() { + for (InProcessBrowserTestMixin* mixin : base::Reversed(mixins_)) + mixin->TearDownInProcessBrowserTestFixture(); +} + +void InProcessBrowserTestMixinHost::TearDown() { + for (InProcessBrowserTestMixin* mixin : base::Reversed(mixins_)) + mixin->TearDown(); +} + +MixinBasedInProcessBrowserTest::MixinBasedInProcessBrowserTest() = default; + +MixinBasedInProcessBrowserTest::~MixinBasedInProcessBrowserTest() = default; + +void MixinBasedInProcessBrowserTest::SetUp() { + mixin_host_.SetUp(); + InProcessBrowserTest::SetUp(); +} + +void MixinBasedInProcessBrowserTest::SetUpCommandLine( + base::CommandLine* command_line) { + mixin_host_.SetUpCommandLine(command_line); + InProcessBrowserTest::SetUpCommandLine(command_line); +} + +void MixinBasedInProcessBrowserTest::SetUpDefaultCommandLine( + base::CommandLine* command_line) { + mixin_host_.SetUpDefaultCommandLine(command_line); + InProcessBrowserTest::SetUpDefaultCommandLine(command_line); +} + +void MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture() { + mixin_host_.SetUpInProcessBrowserTestFixture(); + InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); +} + +void MixinBasedInProcessBrowserTest::SetUpOnMainThread() { + mixin_host_.SetUpOnMainThread(); + InProcessBrowserTest::SetUpOnMainThread(); +} + +void MixinBasedInProcessBrowserTest::TearDownOnMainThread() { + mixin_host_.TearDownOnMainThread(); + InProcessBrowserTest::TearDownOnMainThread(); +} + +void MixinBasedInProcessBrowserTest::TearDownInProcessBrowserTestFixture() { + mixin_host_.TearDownInProcessBrowserTestFixture(); + InProcessBrowserTest::TearDownInProcessBrowserTestFixture(); +} + +void MixinBasedInProcessBrowserTest::TearDown() { + mixin_host_.TearDown(); + InProcessBrowserTest::TearDown(); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h b/chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h new file mode 100644 index 0000000..f3089439 --- /dev/null +++ b/chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h
@@ -0,0 +1,146 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MIXIN_BASED_IN_PROCESS_BROWSER_TEST_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_MIXIN_BASED_IN_PROCESS_BROWSER_TEST_H_ + +#include <memory> +#include <vector> + +#include "chrome/test/base/in_process_browser_test.h" + +namespace chromeos { + +// +// InProcessBrowserTestMixin enables writing isolated test helpers which depend +// on the standard test lifecycle but should not be test bases. +// +// A new mixin is created by deriving from InProcessBrowserTestMixin and +// overriding methods as needed. +// +// class MyMixin : public InProcessBrowserTestMixin { +// public: +// explicit MyMixin(InProcessBrowserTestMixinHost* host) +// : InProcessBrowserTestMixin(host) {} +// ~MyMixin() override = default; +// +// // InProcessBrowserTestMixin: +// void SetUpCommandLine(base::CommandLine* command_line) { /* ... */ } +// +// private: +// DISALLOW_COPY_AND_ASSIGN(MyMixin); +// }; +// +// +// To use the mixin, declare it as a member variable on the class and call the +// constructor with the InProcessBrowserTestMixinHost also declared on the class +// (or parent class). The mixin will register itself with the host and the host +// will invoke all registered mixin methods. +// +// For example, here is how to use MixinBasedInProcessBrowserTest: +// +// class SimpleUsage : public MixinBasedInProcessBrowserTest { +// public: +// SimpleUsage() = default; +// ~SimpleUsage() override = default; +// +// private: +// MyMixin my_mixin_{&mixin_host_}; +// SomeOtherMixin some_other_mixin_{&mixin_host_}; +// +// DISALLOW_COPY_AND_ASSIGN(SimpleUsage); +// }; +// +// +// See WizardInProcessBrowserTest for an example of how to correctly embed a +// mixin host. +// + +class InProcessBrowserTestMixinHost; + +// Derive from this type to create a class which depends on the test lifecycle +// without also becoming a test base. +class InProcessBrowserTestMixin { + public: + explicit InProcessBrowserTestMixin(InProcessBrowserTestMixinHost* host); + virtual ~InProcessBrowserTestMixin(); + + // See InProcessBrowserTest for docs. The call order is: + // + // SetUp + // SetUpCommandLine + // SetUpDefaultCommandLine + // SetUpInProcessBrowserTestFixture + // SetUpOnMainThread + // TearDownOnMainThread + // TearDownInProcessBrowserTestFixture + // TearDown + // + // SetUp is the function which calls SetUpCommandLine, + // SetUpDefaultCommandLine, etc. + virtual void SetUp(); + virtual void SetUpCommandLine(base::CommandLine* command_line); + virtual void SetUpDefaultCommandLine(base::CommandLine* command_line); + virtual void SetUpInProcessBrowserTestFixture(); + virtual void SetUpOnMainThread(); + virtual void TearDownOnMainThread(); + virtual void TearDownInProcessBrowserTestFixture(); + virtual void TearDown(); + + private: + DISALLOW_COPY_AND_ASSIGN(InProcessBrowserTestMixin); +}; + +// The mixin host executes the callbacks on the mixin instances. +class InProcessBrowserTestMixinHost final { + public: + InProcessBrowserTestMixinHost(); + ~InProcessBrowserTestMixinHost(); + + void SetUp(); + void SetUpCommandLine(base::CommandLine* command_line); + void SetUpDefaultCommandLine(base::CommandLine* command_line); + void SetUpInProcessBrowserTestFixture(); + void SetUpOnMainThread(); + void TearDownOnMainThread(); + void TearDownInProcessBrowserTestFixture(); + void TearDown(); + + private: + // The constructor of InProcessBrowserTestMixin injects itself directly into + // mixins_. This is done instead of an explicit AddMixin to make API usage + // simpler. + friend class InProcessBrowserTestMixin; + + std::vector<InProcessBrowserTestMixin*> mixins_; + + DISALLOW_COPY_AND_ASSIGN(InProcessBrowserTestMixinHost); +}; + +// An InProcessBrowserTest which supports mixins. +class MixinBasedInProcessBrowserTest : public InProcessBrowserTest { + public: + MixinBasedInProcessBrowserTest(); + ~MixinBasedInProcessBrowserTest() override; + + // InProcessBrowserTest: + void SetUp() override; + void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpDefaultCommandLine(base::CommandLine* command_line) override; + void SetUpInProcessBrowserTestFixture() override; + void SetUpOnMainThread() override; + void TearDownOnMainThread() override; + void TearDownInProcessBrowserTestFixture() override; + void TearDown() override; + + protected: + InProcessBrowserTestMixinHost mixin_host_; + + private: + DISALLOW_COPY_AND_ASSIGN(MixinBasedInProcessBrowserTest); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_MIXIN_BASED_IN_PROCESS_BROWSER_TEST_H_
diff --git a/chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.cc b/chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.cc index 0817afb..88a009a 100644 --- a/chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.cc +++ b/chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.cc
@@ -16,20 +16,11 @@ namespace chromeos { -ScreenshotTestingMixin::ScreenshotTestingMixin() - : enable_test_screenshots_(false) {} +ScreenshotTestingMixin::ScreenshotTestingMixin( + InProcessBrowserTestMixinHost* host) + : InProcessBrowserTestMixin(host) {} -ScreenshotTestingMixin::~ScreenshotTestingMixin() {} - -void ScreenshotTestingMixin::SetUpInProcessBrowserTestFixture() { - enable_test_screenshots_ = screenshot_tester_.TryInitialize(); -} - -void ScreenshotTestingMixin::SetUpCommandLine(base::CommandLine* command_line) { - if (enable_test_screenshots_) { - command_line->AppendSwitch(switches::kEnablePixelOutputInTests); - } -} +ScreenshotTestingMixin::~ScreenshotTestingMixin() = default; void ScreenshotTestingMixin::RunScreenshotTesting( const std::string& test_name) { @@ -43,6 +34,16 @@ screenshot_tester_.IgnoreArea(area); } +void ScreenshotTestingMixin::SetUpInProcessBrowserTestFixture() { + enable_test_screenshots_ = screenshot_tester_.TryInitialize(); +} + +void ScreenshotTestingMixin::SetUpCommandLine(base::CommandLine* command_line) { + if (enable_test_screenshots_) { + command_line->AppendSwitch(switches::kEnablePixelOutputInTests); + } +} + // Current implementation is a mockup. // It simply waits for 5 seconds, assuming that this time is enough for // animation to load completely.
diff --git a/chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.h b/chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.h index b8cdd8b..e93e27a 100644 --- a/chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.h +++ b/chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.h
@@ -9,7 +9,7 @@ #include "base/command_line.h" #include "base/timer/timer.h" -#include "chrome/browser/chromeos/login/mixin_based_browser_test.h" +#include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h" #include "chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h" #include "content/public/test/browser_test_base.h" @@ -19,23 +19,18 @@ // Sets up everything required for taking screenshots. // Provides functionality to deal with animation load: screenshots // should be taken only when all the animation is loaded. -class ScreenshotTestingMixin : public MixinBasedBrowserTest::Mixin { +class ScreenshotTestingMixin : public InProcessBrowserTestMixin { public: - ScreenshotTestingMixin(); + explicit ScreenshotTestingMixin(InProcessBrowserTestMixinHost* host); ~ScreenshotTestingMixin() override; - // Override from BrowsertestBase::Mixin. - void SetUpInProcessBrowserTestFixture() override; - - // Override from BrowsertestBase::Mixin. - void SetUpCommandLine(base::CommandLine* command_line) override; - - // Runs screenshot testing if it is turned on by command line switches. void RunScreenshotTesting(const std::string& test_name); - - // Remembers that area |area| should be ignored during comparison. void IgnoreArea(const SkIRect& area); + // InProcessBrowserTestMixin: + void SetUpInProcessBrowserTestFixture() override; + void SetUpCommandLine(base::CommandLine* command_line) override; + private: // It turns out that it takes some more time for the animation // to finish loading even after all the notifications have been sent. @@ -54,11 +49,13 @@ base::Closure animation_waiter_quitter_; // Is true if testing with screenshots is turned on with all proper switches. - bool enable_test_screenshots_; + bool enable_test_screenshots_ = false; // |screenshot_tester_ | does everything connected with taking, loading and // comparing screenshots ScreenshotTester screenshot_tester_; + + DISALLOW_COPY_AND_ASSIGN(ScreenshotTestingMixin); }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc index 5f401e9..608276b 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.cc +++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -83,15 +83,45 @@ // SetUpCommandLine(). InitHttpsForwarders(); + mixin_host_.SetUp(); extensions::ExtensionApiTest::SetUp(); } +void OobeBaseTest::SetUpCommandLine(base::CommandLine* command_line) { + extensions::ExtensionApiTest::SetUpCommandLine(command_line); + mixin_host_.SetUpCommandLine(command_line); + + if (ShouldForceWebUiLogin()) + command_line->AppendSwitch(ash::switches::kShowWebUiLogin); + command_line->AppendSwitch(chromeos::switches::kLoginManager); + command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); + if (!needs_background_networking_) + command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); + command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); + + GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost(std::string()); + command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec()); + command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec()); + command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, gaia_url.spec()); + command_line->AppendSwitchASCII(::switches::kOAuthAccountManagerUrl, + gaia_url.spec()); + + fake_gaia_->Initialize(); + fake_gaia_->set_issue_oauth_code_cookie(true); +} + +void OobeBaseTest::SetUpDefaultCommandLine(base::CommandLine* command_line) { + mixin_host_.SetUpDefaultCommandLine(command_line); + extensions::ExtensionApiTest::SetUpDefaultCommandLine(command_line); +} + void OobeBaseTest::SetUpInProcessBrowserTestFixture() { network_portal_detector_ = new NetworkPortalDetectorTestImpl(); network_portal_detector::InitializeForTesting(network_portal_detector_); network_portal_detector_->SetDefaultNetworkForTesting( FakeShillManagerClient::kFakeEthernetNetworkGuid); + mixin_host_.SetUpInProcessBrowserTestFixture(); extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture(); } @@ -123,35 +153,25 @@ run_loop.Run(); } + mixin_host_.SetUpOnMainThread(); extensions::ExtensionApiTest::SetUpOnMainThread(); } void OobeBaseTest::TearDownOnMainThread() { EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); + mixin_host_.TearDownOnMainThread(); extensions::ExtensionApiTest::TearDownOnMainThread(); } -void OobeBaseTest::SetUpCommandLine(base::CommandLine* command_line) { - extensions::ExtensionApiTest::SetUpCommandLine(command_line); +void OobeBaseTest::TearDownInProcessBrowserTestFixture() { + mixin_host_.TearDownInProcessBrowserTestFixture(); + extensions::ExtensionApiTest::TearDownInProcessBrowserTestFixture(); +} - if (ShouldForceWebUiLogin()) - command_line->AppendSwitch(ash::switches::kShowWebUiLogin); - command_line->AppendSwitch(chromeos::switches::kLoginManager); - command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); - if (!needs_background_networking_) - command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); - command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); - - GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost(std::string()); - command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec()); - command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec()); - command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, gaia_url.spec()); - command_line->AppendSwitchASCII(::switches::kOAuthAccountManagerUrl, - gaia_url.spec()); - - fake_gaia_->Initialize(); - fake_gaia_->set_issue_oauth_code_cookie(true); +void OobeBaseTest::TearDown() { + mixin_host_.TearDown(); + extensions::ExtensionApiTest::TearDown(); } void OobeBaseTest::InitHttpsForwarders() {
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h index 224a3752..0276090d 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.h +++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/command_line.h" #include "base/macros.h" +#include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h" #include "chrome/browser/chromeos/login/test/https_forwarder.h" #include "chrome/browser/chromeos/login/test/js_checker.h" #include "chrome/browser/extensions/extension_apitest.h" @@ -49,12 +50,15 @@ virtual void RegisterAdditionalRequestHandlers(); protected: - // InProcessBrowserTest overrides. + // InProcessBrowserTest: void SetUp() override; + void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpDefaultCommandLine(base::CommandLine* command_line) override; void SetUpInProcessBrowserTestFixture() override; void SetUpOnMainThread() override; void TearDownOnMainThread() override; - void SetUpCommandLine(base::CommandLine* command_line) override; + void TearDownInProcessBrowserTestFixture() override; + void TearDown() override; virtual void InitHttpsForwarders(); @@ -102,6 +106,8 @@ const std::string& gaia_id, const std::string& refresh_token); + InProcessBrowserTestMixinHost mixin_host_; + std::unique_ptr<FakeGaia> fake_gaia_; NetworkPortalDetectorTestImpl* network_portal_detector_ = nullptr;
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc index e9fb591..0ca250f0 100644 --- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -9,6 +9,7 @@ #include <cstddef> #include <set> #include <utility> +#include <vector> #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/interfaces/constants.mojom.h" @@ -847,9 +848,23 @@ } void ChromeUserManagerImpl::PerformPostUserListLoadingActions() { - for (user_manager::UserList::iterator ui = users_.begin(), ue = users_.end(); - ui != ue; ++ui) { - GetUserImageManager((*ui)->GetAccountId())->LoadUserImage(); + std::vector<user_manager::User*> users_to_remove; + + for (user_manager::User* user : users_) { + // TODO(http://crbug/866790): Remove supervised user accounts. After we have + // enough confidence that there are no more supervised users on devices in + // the wild, remove this. + if (base::FeatureList::IsEnabled( + features::kRemoveSupervisedUsersOnStartup) && + user->IsSupervised()) { + users_to_remove.push_back(user); + } else { + GetUserImageManager(user->GetAccountId())->LoadUserImage(); + } + } + + for (user_manager::User* user : users_to_remove) { + RemoveUser(user->GetAccountId(), nullptr); } }
diff --git a/chrome/browser/chromeos/login/users/remove_supervised_users_browsertest.cc b/chrome/browser/chromeos/login/users/remove_supervised_users_browsertest.cc new file mode 100644 index 0000000..b15f6f7 --- /dev/null +++ b/chrome/browser/chromeos/login/users/remove_supervised_users_browsertest.cc
@@ -0,0 +1,122 @@ +// 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 <memory> +#include <vector> + +#include "base/macros.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/chromeos/login/login_manager_test.h" +#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" +#include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h" +#include "chrome/common/chrome_features.h" +#include "components/account_id/account_id.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/user_manager.h" +#include "components/user_manager/user_manager_base.h" + +namespace chromeos { + +namespace { + +struct { + const char* email; + const char* gaia_id; +} const kTestUsers[] = { + {"test-user1@gmail.com", "1111111111"}, + {"test-user2@gmail.com", "2222222222"}, + // Test Supervised User. + // The domain is defined in user_manager::kSupervisedUserDomain. + // That const isn't directly referenced here to keep this code readable by + // avoiding std::string concatenations. + {"test-superviseduser@locally-managed.localhost", "3333333333"}, +}; + +} // namespace + +class RemoveSupervisedUsersBrowserTest : public LoginManagerTest { + public: + RemoveSupervisedUsersBrowserTest() : LoginManagerTest(false, false) {} + + ~RemoveSupervisedUsersBrowserTest() override = default; + + void SetUpOnMainThread() override { + LoginManagerTest::SetUpOnMainThread(); + InitializeTestUsers(); + } + + void TearDownOnMainThread() override { + LoginManagerTest::TearDownOnMainThread(); + scoped_user_manager_.reset(); + } + + protected: + std::vector<AccountId> test_users_; + + private: + void InitializeTestUsers() { + for (size_t i = 0; i < base::size(kTestUsers); ++i) { + test_users_.emplace_back(AccountId::FromUserEmailGaiaId( + kTestUsers[i].email, kTestUsers[i].gaia_id)); + RegisterUser(test_users_[i]); + } + + // Setup a scoped real ChromeUserManager, since this is an end-to-end + // test. This will read the users registered to the local state just + // before this in RegisterUser. + scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( + chromeos::ChromeUserManagerImpl::CreateChromeUserManager()); + } + + std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; + ScopedTestingCrosSettings scoped_testing_cros_settings_; + + DISALLOW_COPY_AND_ASSIGN(RemoveSupervisedUsersBrowserTest); +}; + +class RemoveSupervisedUsersBrowserEnabledTest + : public RemoveSupervisedUsersBrowserTest { + protected: + void SetUpInProcessBrowserTestFixture() override { + scoped_feature_list_.InitAndEnableFeature( + features::kRemoveSupervisedUsersOnStartup); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +class RemoveSupervisedUsersBrowserDisabledTest + : public RemoveSupervisedUsersBrowserTest { + protected: + void SetUpInProcessBrowserTestFixture() override { + scoped_feature_list_.InitAndDisableFeature( + features::kRemoveSupervisedUsersOnStartup); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(RemoveSupervisedUsersBrowserEnabledTest, + SupervisedUserRemoved) { + // When Supervised users are removed, only 2 test users should be returned. + EXPECT_EQ(2U, user_manager::UserManager::Get()->GetUsers().size()); + + // None of the non-supervised users should have been removed. + for (user_manager::User* user : + user_manager::UserManager::Get()->GetUsers()) { + EXPECT_EQ(false, user->IsSupervised()); + } +} + +IN_PROC_BROWSER_TEST_F(RemoveSupervisedUsersBrowserDisabledTest, + SupervisedUserNotRemoved) { + // When Supervised users are not removed, all 3 test users should be returned. + EXPECT_EQ(3U, user_manager::UserManager::Get()->GetUsers().size()); +} + +} // namespace chromeos
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc index e6e3a9f..a9ca97ae 100644 --- a/chrome/browser/extensions/api/identity/identity_apitest.cc +++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -32,7 +32,6 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/account_fetcher_service_factory.h" -#include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/ui/browser.h" @@ -467,20 +466,6 @@ return account_info.account_id; } - std::string AddAccount(const std::string& email) { - std::string account_id = SeedAccountInfo(email); - identity_test_env()->SetRefreshTokenForAccount(account_id); - return account_id; - } - - std::string SeedAccountInfo(const std::string& email) { - std::string gaia = "gaia_id_for_" + email; - std::replace(gaia.begin(), gaia.end(), '@', '_'); - AccountTrackerService* account_tracker = - AccountTrackerServiceFactory::GetForProfile(profile()); - return account_tracker->SeedAccountInfo(gaia, email); - } - IdentityAPI* id_api() { return IdentityAPI::GetFactoryInstance()->Get(browser()->profile()); } @@ -589,7 +574,7 @@ } IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, NoPrimaryAccount) { - AddAccount("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); EXPECT_TRUE(ExpectGetAccounts({})); } @@ -608,7 +593,7 @@ IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, TwoAccountsSignedIn) { SignIn("primary@example.com"); - AddAccount("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); if (!id_api()->AreExtensionsRestrictedToPrimaryAccount()) { EXPECT_TRUE(ExpectGetAccounts({"gaia_id_for_primary_example.com", "gaia_id_for_secondary_example.com"})); @@ -639,7 +624,7 @@ IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest, TwoAccountsSignedIn) { SignIn("primary@example.com"); - AddAccount("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); EXPECT_TRUE(ExpectGetAccounts({"gaia_id_for_primary_example.com"})); } @@ -1706,7 +1691,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiDefaultUserManuallyIssueToken) { std::string primary_account_id = SignIn("primary@example.com"); - SeedAccountInfo("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1734,7 +1719,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiPrimaryUserManuallyIssueToken) { std::string primary_account_id = SignIn("primary@example.com"); - AddAccount("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1768,7 +1753,10 @@ return; std::string primary_account_id = SignIn("primary@example.com"); - std::string secondary_account_id = AddAccount("secondary@example.com"); + std::string secondary_account_id = + identity_test_env() + ->MakeAccountAvailable("secondary@example.com") + .account_id; scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1798,7 +1786,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiUnknownUserGetTokenFromTokenServiceFailure) { SignIn("primary@example.com"); - AddAccount("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1818,7 +1806,7 @@ return; SignIn("primary@example.com"); - AddAccount("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); func->set_extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1840,7 +1828,7 @@ return; SignIn("primary@example.com"); - AddAccount("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); func->set_extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1860,7 +1848,7 @@ return; SignIn("primary@example.com"); - AddAccount("secondary@example.com"); + identity_test_env()->MakeAccountAvailable("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); func->set_extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -2361,10 +2349,8 @@ account_info.id = "gaia_id_for_primary_example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); - // Make the primary account's refresh token available and check that the - // callback fires. Note that we must call AddAccount() here as the account's - // information must be present in the AccountTrackerService as well. - AddAccount("primary@example.com"); + // Make the primary account available again and check that the callback fires. + identity_test_env()->MakeAccountAvailable("primary@example.com"); EXPECT_FALSE(HasExpectedEvent()); } @@ -2378,10 +2364,11 @@ account_info.id = "gaia_id_for_secondary_example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); - // Make a secondary account's refresh token available and check that the - // callback fires. Note that we must call AddAccount() here as the account's - // information must be present in the AccountTrackerService as well. - std::string secondary_account_id = AddAccount("secondary@example.com"); + // Make a secondary account available again and check that the callback fires. + std::string secondary_account_id = + identity_test_env() + ->MakeAccountAvailable("secondary@example.com") + .account_id; EXPECT_FALSE(HasExpectedEvent()); // Revoke the secondary account's refresh token and check that the callback
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc index 63f04e32..89cd9cf4 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
@@ -271,9 +271,9 @@ // Note: First argument is optional and intentionally left blank. // (it's a prefix for the generated test cases) -INSTANTIATE_TEST_CASE_P(, - TabCapturePerformanceTest, - testing::Values(0, - kUseGpu, - kTestThroughWebRTC, - kTestThroughWebRTC | kUseGpu)); +INSTANTIATE_TEST_SUITE_P(, + TabCapturePerformanceTest, + testing::Values(0, + kUseGpu, + kTestThroughWebRTC, + kTestThroughWebRTC | kUseGpu));
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index cfb4f59..03349c6 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -659,11 +659,6 @@ "If enabled, the chrome://policy-tool URL loads a page for managing " "policies."; -const char kDisableMultiMirroringName[] = - "Display mirroring across multiple displays."; -const char kDisableMultiMirroringDescription[] = - "Disable Display mirroring across multiple displays."; - const char kEnableNavigationTracingName[] = "Enable navigation tracing"; const char kEnableNavigationTracingDescription[] = "This is to be used in conjunction with the trace-upload-url flag. "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index d03fab1..22703094 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -427,9 +427,6 @@ extern const char kEnablePolicyToolName[]; extern const char kEnablePolicyToolDescription[]; -extern const char kDisableMultiMirroringName[]; -extern const char kDisableMultiMirroringDescription[]; - extern const char kEnableNavigationTracingName[]; extern const char kEnableNavigationTracingDescription[];
diff --git a/chrome/browser/media/cast_remoting_connector_unittest.cc b/chrome/browser/media/cast_remoting_connector_unittest.cc index fe6d0d8..3008d9b 100644 --- a/chrome/browser/media/cast_remoting_connector_unittest.cc +++ b/chrome/browser/media/cast_remoting_connector_unittest.cc
@@ -625,13 +625,13 @@ } } -INSTANTIATE_TEST_CASE_P(, - CastRemotingConnectorFullSessionTest, - ::testing::Values(SOURCE_TERMINATES, - MOJO_PIPE_CLOSES, - ROUTE_TERMINATES, - EXTERNAL_FAILURE, - USER_DISABLED)); +INSTANTIATE_TEST_SUITE_P(, + CastRemotingConnectorFullSessionTest, + ::testing::Values(SOURCE_TERMINATES, + MOJO_PIPE_CLOSES, + ROUTE_TERMINATES, + EXTERNAL_FAILURE, + USER_DISABLED)); // TODO(xjz): Remove the following tests after Mirroring Service is launched. TEST_F(CastRemotingConnectorTest, @@ -936,10 +936,10 @@ } } -INSTANTIATE_TEST_CASE_P(, - DeprecatedCastRemotingConnectorFullSessionTest, - ::testing::Values(SOURCE_TERMINATES, - MOJO_PIPE_CLOSES, - ROUTE_TERMINATES, - EXTERNAL_FAILURE, - USER_DISABLED)); +INSTANTIATE_TEST_SUITE_P(, + DeprecatedCastRemotingConnectorFullSessionTest, + ::testing::Values(SOURCE_TERMINATES, + MOJO_PIPE_CLOSES, + ROUTE_TERMINATES, + EXTERNAL_FAILURE, + USER_DISABLED));
diff --git a/chrome/browser/media/webrtc/webrtc_text_log_handler.cc b/chrome/browser/media/webrtc/webrtc_text_log_handler.cc index 361d8697..f6d5c88 100644 --- a/chrome/browser/media/webrtc/webrtc_text_log_handler.cc +++ b/chrome/browser/media/webrtc/webrtc_text_log_handler.cc
@@ -27,6 +27,7 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/gpu_data_manager.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/webrtc_log.h" #include "content/public/common/content_features.h" @@ -36,6 +37,7 @@ #include "net/base/ip_address.h" #include "net/base/network_change_notifier.h" #include "net/base/network_interfaces.h" +#include "services/network/public/mojom/network_service.mojom.h" #include "services/service_manager/sandbox/features.h" #if defined(OS_LINUX) @@ -100,13 +102,6 @@ #endif } -net::NetworkInterfaceList GetNetworkInterfaceList() { - net::NetworkInterfaceList network_list; - net::GetNetworkList(&network_list, - net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES); - return network_list; -} - } // namespace WebRtcLogBuffer::WebRtcLogBuffer() @@ -224,11 +219,10 @@ if (!meta_data_) meta_data_.reset(new MetaDataMap()); - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, - base::BindOnce(&GetNetworkInterfaceList), - base::BindOnce(&WebRtcTextLogHandler::LogInitialInfoOnIOThread, this, - callback)); + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&WebRtcTextLogHandler::GetNetworkInterfaceListOnUIThread, + this, std::move(callback))); return true; } @@ -420,6 +414,26 @@ web_app_id_ = web_app_id; } +void WebRtcTextLogHandler::GetNetworkInterfaceListOnUIThread( + const GenericDoneCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::GetNetworkService()->GetNetworkList( + net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, + base::BindOnce(&WebRtcTextLogHandler::OnGetNetworkInterfaceList, this, + std::move(callback))); +} + +void WebRtcTextLogHandler::OnGetNetworkInterfaceList( + const GenericDoneCallback& callback, + const base::Optional<net::NetworkInterfaceList>& networks) { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce( + &WebRtcTextLogHandler::LogInitialInfoOnIOThread, this, + std::move(callback), + networks.has_value() ? *networks : net::NetworkInterfaceList())); +} + void WebRtcTextLogHandler::LogInitialInfoOnIOThread( const GenericDoneCallback& callback, const net::NetworkInterfaceList& network_list) {
diff --git a/chrome/browser/media/webrtc/webrtc_text_log_handler.h b/chrome/browser/media/webrtc/webrtc_text_log_handler.h index 3e03eee..23d66812 100644 --- a/chrome/browser/media/webrtc/webrtc_text_log_handler.h +++ b/chrome/browser/media/webrtc/webrtc_text_log_handler.h
@@ -144,6 +144,12 @@ void LogToCircularBuffer(const std::string& message); + void GetNetworkInterfaceListOnUIThread(const GenericDoneCallback& callback); + + void OnGetNetworkInterfaceList( + const GenericDoneCallback& callback, + const base::Optional<net::NetworkInterfaceList>& networks); + void LogInitialInfoOnIOThread(const GenericDoneCallback& callback, const net::NetworkInterfaceList& network_list);
diff --git a/chrome/browser/profiling_host/memlog_browsertest.cc b/chrome/browser/profiling_host/memlog_browsertest.cc index 74da3ad..09f81a1 100644 --- a/chrome/browser/profiling_host/memlog_browsertest.cc +++ b/chrome/browser/profiling_host/memlog_browsertest.cc
@@ -174,9 +174,9 @@ return params; } -INSTANTIATE_TEST_CASE_P(Memlog, - MemlogBrowserTest, - ::testing::ValuesIn(GetParams())); +INSTANTIATE_TEST_SUITE_P(Memlog, + MemlogBrowserTest, + ::testing::ValuesIn(GetParams())); } // namespace heap_profiling
diff --git a/chrome/browser/resources/app_management/BUILD.gn b/chrome/browser/resources/app_management/BUILD.gn index 9be310c..99daf0e 100644 --- a/chrome/browser/resources/app_management/BUILD.gn +++ b/chrome/browser/resources/app_management/BUILD.gn
@@ -117,6 +117,7 @@ ":browser_proxy", ":constants", ":fake_page_handler", + ":store_client", ":types", ] } @@ -125,12 +126,15 @@ deps = [ ":app_item", ":fake_page_handler", + ":store_client", ] } js_library("permission_item") { deps = [ ":fake_page_handler", + ":store_client", + ":util", ] }
diff --git a/chrome/browser/resources/app_management/api_listener.html b/chrome/browser/resources/app_management/api_listener.html index 0320371..751d6c4 100644 --- a/chrome/browser/resources/app_management/api_listener.html +++ b/chrome/browser/resources/app_management/api_listener.html
@@ -2,4 +2,4 @@ <link rel="import" href="actions.html"> <link rel="import" href="store.html"> <link rel="import" href="util.html"> -<script src="chrome://apps/api_listener.js"></script> +<script src="api_listener.js"></script>
diff --git a/chrome/browser/resources/app_management/app.html b/chrome/browser/resources/app_management/app.html index 4a71ef5..6078b89 100644 --- a/chrome/browser/resources/app_management/app.html +++ b/chrome/browser/resources/app_management/app.html
@@ -11,7 +11,7 @@ <link rel="import" href="store_client.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html"> -<link rel="import" href="chrome://apps/api_listener.html"> +<link rel="import" href="api_listener.html"> <dom-module id="app-management-app"> <template>
diff --git a/chrome/browser/resources/app_management/chrome_app_permission_view.html b/chrome/browser/resources/app_management/chrome_app_permission_view.html index bd9ab947..b79cf5b 100644 --- a/chrome/browser/resources/app_management/chrome_app_permission_view.html +++ b/chrome/browser/resources/app_management/chrome_app_permission_view.html
@@ -30,7 +30,7 @@ padding-inline-start: 24px; } </style> - <app-management-permission-view-header app="[[app_]]"> + <app-management-permission-view-header> </app-management-permission-view-header> <div class="card-container"> <div id="app-info">
diff --git a/chrome/browser/resources/app_management/chrome_app_permission_view.js b/chrome/browser/resources/app_management/chrome_app_permission_view.js index 01697a6d..e6eff99 100644 --- a/chrome/browser/resources/app_management/chrome_app_permission_view.js +++ b/chrome/browser/resources/app_management/chrome_app_permission_view.js
@@ -24,26 +24,11 @@ }, attached: function() { - this.watch('app_', (state) => { - const selectedAppId = state.currentPage.selectedAppId; - if (selectedAppId) { - return state.apps[selectedAppId]; - } - }); - + this.watch('app_', state => app_management.util.getSelectedApp(state)); this.updateFromStore(); }, /** - * @param {App} app - * @return {string} - * @private - */ - iconUrlFromId_: function(app) { - return app_management.util.getAppIcon(app); - }, - - /** * @private */ onAppChanged_: async function() {
diff --git a/chrome/browser/resources/app_management/fake_page_handler.js b/chrome/browser/resources/app_management/fake_page_handler.js index b21bd5e..2d62f96 100644 --- a/chrome/browser/resources/app_management/fake_page_handler.js +++ b/chrome/browser/resources/app_management/fake_page_handler.js
@@ -9,15 +9,15 @@ class FakePageHandler { /** * @param {number} permissionId - * @param {Object=} config + * @param {Object=} optConfig * @return {!Permission} */ - static createPermission(permissionId, config) { + static createPermission(permissionId, optConfig) { const permission = app_management.util.createPermission( permissionId, PermissionValueType.kTriState, TriState.kBlock); - if (config) { - Object.assign(permission, config); + if (optConfig) { + Object.assign(permission, optConfig); } return permission; @@ -25,10 +25,10 @@ /** * @param {string} id - * @param {Object=} config + * @param {Object=} optConfig * @return {!App} */ - static createApp(id, config) { + static createApp(id, optConfig) { const permissionIds = [ PwaPermissionType.CONTENT_SETTINGS_TYPE_GEOLOCATION, PwaPermissionType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS, @@ -46,24 +46,25 @@ id: id, type: apps.mojom.AppType.kWeb, title: 'App Title', + description: '', version: '5.1', size: '9.0MB', - isPinned: apps.mojom.OptionalBool.kUnknown, + isPinned: apps.mojom.OptionalBool.kFalse, permissions: permissions, }; - if (config) { - Object.assign(app, config); + if (optConfig) { + Object.assign(app, optConfig); } return app; } /** - * @param {appManagement.mojom.PageInterface} page + * @param {appManagement.mojom.PageProxy} page */ constructor(page) { - /** @type {appManagement.mojom.PageInterface} */ + /** @type {appManagement.mojom.PageProxy} */ this.page = page; /** @type {!Array<App>} */ @@ -128,6 +129,31 @@ * @param {string} appId */ openNativeSettings(appId) {} + + /** + * @param {string} id + * @param {Object=} optConfig + */ + async addApp(id, optConfig) { + this.page.onAppAdded(FakePageHandler.createApp(id, optConfig)); + await this.flushForTesting(); + } + + /** + * Takes an app id and an object mapping app fields to the values they + * should be changed to, and dispatches an action to carry out these + * changes. + * @param {string} id + * @param {Object} changes + */ + async changeApp(id, changes) { + this.page.onAppChanged(FakePageHandler.createApp(id, changes)); + await this.flushForTesting(); + } + + async flushForTesting() { + await this.page.flushForTesting(); + } } return {FakePageHandler: FakePageHandler};
diff --git a/chrome/browser/resources/app_management/metadata_view.html b/chrome/browser/resources/app_management/metadata_view.html index 8ada6e7d..9ca5003 100644 --- a/chrome/browser/resources/app_management/metadata_view.html +++ b/chrome/browser/resources/app_management/metadata_view.html
@@ -36,19 +36,20 @@ justify-content: space-around; } </style> - <template is="dom-if" if="[[pinToShelfToggleVisible_(app)]]"> + <template is="dom-if" if="[[pinToShelfToggleVisible_(app_)]]"> <div id="shelf-switch-row"> <span id="shelf-switch" class="header-text"> $i18n{pinToShelf} - <cr-toggle checked="[[isPinned_(app)]]" on-change="togglePinned_"> + <cr-toggle id="pin-to-shelf-toggle" checked="[[isPinned_(app_)]]" + on-change="togglePinned_"> </cr-toggle> </span> </div> </template> <div id="metadata-overview" class="secondary-text"> - <span>[[versionString_(app)]]</span> - <span>[[sizeString_(app)]]</span> + <span>[[versionString_(app_)]]</span> + <span>[[sizeString_(app_)]]</span> <!--TODO(ceciliani): Placeholder for legal declaration--> </div> </template>
diff --git a/chrome/browser/resources/app_management/metadata_view.js b/chrome/browser/resources/app_management/metadata_view.js index 891c13d..8914ee5 100644 --- a/chrome/browser/resources/app_management/metadata_view.js +++ b/chrome/browser/resources/app_management/metadata_view.js
@@ -5,20 +5,29 @@ Polymer({ is: 'app-management-metadata-view', + behaviors: [ + app_management.StoreClient, + ], + properties: { /** @type {App} */ - app: { + app_: { type: Object, }, }, + attached: function() { + this.watch('app_', state => app_management.util.getSelectedApp(state)); + this.updateFromStore(); + }, + /** * @param {App} app * @return bool * @private */ pinToShelfToggleVisible_: function(app) { - return !(app.isPinned === OptionalBool.kUnknown); + return app.isPinned !== OptionalBool.kUnknown; }, /** @@ -33,11 +42,9 @@ }, togglePinned_: function() { - assert(this.app); - let newPinnedValue; - switch (this.app.isPinned) { + switch (this.app_.isPinned) { case OptionalBool.kFalse: newPinnedValue = OptionalBool.kTrue; break; @@ -49,12 +56,12 @@ } app_management.BrowserProxy.getInstance().handler.setPinned( - this.app.id, newPinnedValue); + this.app_.id, newPinnedValue); }, /** * @param {App} app - * @return {string?} + * @return {?string} * @private */ versionString_: function(app) { @@ -67,7 +74,7 @@ /** * @param {App} app - * @return {string?} + * @return {?string} * @private */ sizeString_: function(app) {
diff --git a/chrome/browser/resources/app_management/permission_item.js b/chrome/browser/resources/app_management/permission_item.js index aa31805..1a885f5 100644 --- a/chrome/browser/resources/app_management/permission_item.js +++ b/chrome/browser/resources/app_management/permission_item.js
@@ -4,6 +4,10 @@ Polymer({ is: 'app-management-permission-item', + behaviors: [ + app_management.StoreClient, + ], + properties: { /** * The name of the permission, to be displayed to the user. @@ -21,14 +25,14 @@ /** * @type {App} */ - app: Object, + app_: Object, /** * @private {PermissionValueType} */ permissionValueType_: { type: Number, - computed: 'getPermissionValueType_(app)', + computed: 'getPermissionValueType_(app_)', }, /** @@ -38,13 +42,18 @@ */ permissionValue_: { type: Number, - computed: 'getPermissionValue_(app, permissionType)', + computed: 'getPermissionValue_(app_, permissionType)', }, /** @type {string} */ icon: String, }, + attached: function() { + this.watch('app_', state => app_management.util.getSelectedApp(state)); + this.updateFromStore(); + }, + /** * @param {App} app * @return {number} @@ -112,7 +121,7 @@ } app_management.BrowserProxy.getInstance().handler.setPermission( - this.app.id, newPermission); + this.app_.id, newPermission); }, /** @@ -154,7 +163,11 @@ newPermissionValue = TriState.kAllow; break; case TriState.kAllow: - newPermissionValue = TriState.kAsk; + // TODO(rekanorman): Eventually TriState.kAsk, but currently changing a + // permission to kAsk then opening the site settings page for the app + // produces the error: + // "Only extensions or enterprise policy can change the setting to ASK." + newPermissionValue = TriState.kBlock; break; default: assertNotReached();
diff --git a/chrome/browser/resources/app_management/permission_view_header.html b/chrome/browser/resources/app_management/permission_view_header.html index d541c4f1..7a35bad 100644 --- a/chrome/browser/resources/app_management/permission_view_header.html +++ b/chrome/browser/resources/app_management/permission_view_header.html
@@ -43,8 +43,8 @@ <paper-ripple class="circle"></paper-ripple> </button> </paper-icon-button-light> - <img id="permission-view-header-icon" src="[[iconUrlFromId_(app)]]"> - <div class="page-title">[[app.title]]</div> + <img id="permission-view-header-icon" src="[[iconUrlFromId_(app_)]]"> + <div class="page-title">[[app_.title]]</div> <slot name="extra-right-buttons"></slot> <paper-button id="uninstall-button" on-click="onClickUninstallButton_"> $i18n{uninstall}
diff --git a/chrome/browser/resources/app_management/permission_view_header.js b/chrome/browser/resources/app_management/permission_view_header.js index aa20efc..248478a 100644 --- a/chrome/browser/resources/app_management/permission_view_header.js +++ b/chrome/browser/resources/app_management/permission_view_header.js
@@ -10,19 +10,13 @@ properties: { /** @type {App} */ - app: { + app_: { type: Object, }, }, attached: function() { - this.watch('app', (state) => { - const selectedAppId = state.currentPage.selectedAppId; - if (selectedAppId) { - return state.apps[selectedAppId]; - } - }); - + this.watch('app_', state => app_management.util.getSelectedApp(state)); this.updateFromStore(); }, @@ -50,6 +44,6 @@ * @private */ onClickUninstallButton_: function() { - app_management.BrowserProxy.getInstance().handler.uninstall(this.app.id); + app_management.BrowserProxy.getInstance().handler.uninstall(this.app_.id); }, });
diff --git a/chrome/browser/resources/app_management/pwa_permission_view.html b/chrome/browser/resources/app_management/pwa_permission_view.html index 459cb63..95139ce 100644 --- a/chrome/browser/resources/app_management/pwa_permission_view.html +++ b/chrome/browser/resources/app_management/pwa_permission_view.html
@@ -59,7 +59,7 @@ margin-inline-end: 16px; } </style> - <app-management-permission-view-header app="[[app_]]"> + <app-management-permission-view-header> <div slot="extra-right-buttons" id="extra-button"> <paper-button id="site-settings-button" class="secondary-text" @@ -76,7 +76,6 @@ <div id="permission-list" class="card-container"> <app-management-permission-item class="permission-card-row separated-row header-text" - app="[[app_]]" permission-label="$i18n{notifications}" permission-type="CONTENT_SETTINGS_TYPE_NOTIFICATIONS"> </app-management-permission-item> @@ -100,21 +99,18 @@ <iron-collapse opened="[[listExpanded_]]"> <app-management-permission-item class="subpermission-row" - app="[[app_]]" icon="cr:location-on" permission-label="$i18n{location}" permission-type="CONTENT_SETTINGS_TYPE_GEOLOCATION"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" - app="[[app_]]" icon="cr:videocam" permission-label="$i18n{camera}" permission-type="CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" - app="[[app_]]" icon="cr:mic" permission-label="$i18n{microphone}" permission-type="CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC">
diff --git a/chrome/browser/resources/app_management/pwa_permission_view.js b/chrome/browser/resources/app_management/pwa_permission_view.js index 425f9176..ab676853 100644 --- a/chrome/browser/resources/app_management/pwa_permission_view.js +++ b/chrome/browser/resources/app_management/pwa_permission_view.js
@@ -24,13 +24,7 @@ }, attached: function() { - this.watch('app_', (state) => { - const selectedAppId = state.currentPage.selectedAppId; - if (selectedAppId) { - return state.apps[selectedAppId]; - } - }); - + this.watch('app_', state => app_management.util.getSelectedApp(state)); this.updateFromStore(); },
diff --git a/chrome/browser/resources/app_management/reducers.js b/chrome/browser/resources/app_management/reducers.js index 15c5b54..2263e85 100644 --- a/chrome/browser/resources/app_management/reducers.js +++ b/chrome/browser/resources/app_management/reducers.js
@@ -18,6 +18,8 @@ * @return {AppMap} */ AppState.addApp = function(apps, action) { + assert(!apps[action.app.id]); + const newAppEntry = {}; newAppEntry[action.app.id] = action.app; return Object.assign({}, apps, newAppEntry);
diff --git a/chrome/browser/resources/app_management/router.html b/chrome/browser/resources/app_management/router.html index d7c67f0..0e404f2 100644 --- a/chrome/browser/resources/app_management/router.html +++ b/chrome/browser/resources/app_management/router.html
@@ -13,5 +13,5 @@ <iron-query-params params-string="{{query_}}" params-object="{{queryParams_}}"></iron-query-params> </template> - <script src="chrome://apps/router.js"></script> + <script src="router.js"></script> </dom-module>
diff --git a/chrome/browser/resources/app_management/util.js b/chrome/browser/resources/app_management/util.js index 445da94..6e381888 100644 --- a/chrome/browser/resources/app_management/util.js +++ b/chrome/browser/resources/app_management/util.js
@@ -56,10 +56,24 @@ return `chrome://extension-icon/${app.id}/128/1`; } + /** + * If there is no selected app, returns undefined so that Polymer bindings + * won't be updated. + * @param {AppManagementPageState} state + * @return {App|undefined} + */ + function getSelectedApp(state) { + const selectedAppId = state.currentPage.selectedAppId; + if (selectedAppId) { + return state.apps[selectedAppId]; + } + } + return { createEmptyState: createEmptyState, createInitialState: createInitialState, createPermission: createPermission, getAppIcon: getAppIcon, + getSelectedApp: getSelectedApp, }; });
diff --git a/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager.js b/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager.js index 953913e..3cab81d 100644 --- a/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager.js +++ b/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager.js
@@ -176,12 +176,7 @@ */ finishPairing: function(display, pincode) { chrome.bluetoothPrivate.setPairingResponse( - { - response: chrome.bluetoothPrivate.PairingResponse.CONFIRM, - device: display, - pincode: pincode - }, - () => {}); + {response: 'confirm', device: display, pincode: pincode}, () => {}); }, /**
diff --git a/chrome/browser/resources/chromeos/chromevox/tools/check_chromevox.py b/chrome/browser/resources/chromeos/chromevox/tools/check_chromevox.py index c7d2d80..0dab9310 100755 --- a/chrome/browser/resources/chromeos/chromevox/tools/check_chromevox.py +++ b/chrome/browser/resources/chromeos/chromevox/tools/check_chromevox.py
@@ -54,10 +54,6 @@ _AUTOMATION_EXTERNS = ( ChromeRootPath('third_party/closure_compiler/externs/automation.js')) -# BluetoothPrivate externs file. -_BLUETOOTH_PRIVATE_EXTERNS = ( - ChromeRootPath('third_party/closure_compiler/externs/bluetooth_private.js')) - # MetricsPrivate externs file. _METRICS_PRIVATE_EXTERNS = ( ChromeRootPath('third_party/closure_compiler/externs/metrics_private.js')) @@ -89,7 +85,6 @@ _ACCESSIBILITY_PRIVATE_EXTERNS, _AUDIO_EXTERNS, _AUTOMATION_EXTERNS, - _BLUETOOTH_PRIVATE_EXTERNS, _CHROME_EXTERNS, _CHROME_EXTENSIONS_EXTERNS, _COMMANDLINE_PRIVATE_EXTERNS,
diff --git a/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn b/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn index 6370746..0abf4a5 100644 --- a/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn +++ b/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn
@@ -3,10 +3,10 @@ # found in the LICENSE file. import("//build/config/features.gni") -import("//chrome/common/features.gni") -import("//testing/test.gni") -import("//chrome/test/base/js2gtest.gni") import("//chrome/browser/resources/chromeos/chromevox/run_jsbundler.gni") +import("//chrome/common/features.gni") +import("//chrome/test/base/js2gtest.gni") +import("//testing/test.gni") import("//third_party/closure_compiler/compile_js.gni") assert(is_chromeos) @@ -194,6 +194,7 @@ "$externs_path/chrome_extensions.js", "$externs_path/clipboard.js", "$externs_path/command_line_private.js", + "$externs_path/pending.js", ] }
diff --git a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js index 38ad21d..1ad5afd 100644 --- a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js +++ b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js
@@ -75,7 +75,11 @@ /** @private {number} */ this.currentNodeGroupIndex_ = -1; - /** @private {?Object} */ + /** + * The indexes within the current node representing the word currently being + * spoken. Only updated if word highlighting is enabled. + * @private {?Object} + */ this.currentNodeWord_ = null; /** @private {?AutomationNode} */ @@ -621,42 +625,8 @@ if (isLast) this.onStateChanged_(SelectToSpeakState.INACTIVE); } else if (event.type == 'word') { - console.debug(nodeGroup.text + ' (index ' + event.charIndex + ')'); - console.debug('-'.repeat(event.charIndex) + '^'); - if (this.currentNodeGroupIndex_ + 1 < nodeGroup.nodes.length) { - let next = nodeGroup.nodes[this.currentNodeGroupIndex_ + 1]; - let nodeUpdated = false; - // Check if we've reached this next node yet using the - // character index of the event. Add 1 for the space character - // between node names, and another to make it to the start of the - // next node name. - while (event.charIndex + 2 >= next.startChar && - this.currentNodeGroupIndex_ + 1 < nodeGroup.nodes.length) { - // Move to the next node. - this.currentNodeGroupIndex_ += 1; - this.currentNode_ = next; - this.currentNodeWord_ = null; - nodeUpdated = true; - if (this.currentNodeGroupIndex_ + 1 >= nodeGroup.nodes.length) - break; - next = nodeGroup.nodes[this.currentNodeGroupIndex_ + 1]; - } - if (nodeUpdated) { - if (!this.prefsManager_.wordHighlightingEnabled()) { - // If we are doing a per-word highlight, we will test the - // node after figuring out what the currently highlighted - // word is. - this.testCurrentNode_(); - } - } - } - if (this.prefsManager_.wordHighlightingEnabled()) { - this.updateNodeHighlight_( - nodeGroup.text, event.charIndex, undefined, - isLast ? opt_endIndex : undefined); - } else { - this.currentNodeWord_ = null; - } + this.onTtsWordEvent_( + event, nodeGroup, isLast ? opt_endIndex : undefined); } }; chrome.tts.speak(nodeGroup.text || '', options); @@ -678,6 +648,109 @@ }, /** + * Uses the 'word' speech event to determine which node is currently beings + * spoken, and prepares for highlight if enabled. + * @param {!TtsEvent} event The event to use for updates. + * @param {ParagraphUtils.NodeGroup} nodeGroup The node group for this + * utterance. + * @param {number=} opt_endIndex The last index for speech, if applicable. + * @private + */ + onTtsWordEvent_: function(event, nodeGroup, opt_endIndex) { + // Not all speech engines include length in the ttsEvent object. If the + // engine does have it, it makes word highlighting easier and more + // accurate. + let hasLength = event.length !== undefined && event.length >= 0; + console.debug(nodeGroup.text + ' (index ' + event.charIndex + ')'); + let debug = '-'.repeat(event.charIndex); + if (hasLength) + debug += '^'.repeat(event.length); + else + debug += '^'; + console.debug(debug); + + // First determine which node contains the word currently being spoken, + // and update this.currentNode_, this.currentNodeWord_, and + // this.currentNodeGroupIndex_ to match. + if (this.currentNodeGroupIndex_ + 1 < nodeGroup.nodes.length) { + let next = nodeGroup.nodes[this.currentNodeGroupIndex_ + 1]; + let nodeUpdated = false; + // TODO(katie): For something like a date, the start and end + // node group nodes can actually be different. Example: + // "<span>Tuesday,</span> December 18, 2018". + if (hasLength) { + while (next && event.charIndex >= next.startChar && + this.currentNodeGroupIndex_ + 1 < nodeGroup.nodes.length) { + next = this.incrementCurrentNodeAndGetNext_(nodeGroup); + nodeUpdated = true; + } + + // Check if we've reached this next node yet using the + // character index of the event. Add 1 for the space character + // between node names, and another to make it to the start of the + // next node name. + // TODO: Do not use next.name.length instead use the next-next startChar + while (next && + event.charIndex + event.length + 2 >= + next.startChar + next.node.name.length && + this.currentNodeGroupIndex_ + 1 < nodeGroup.nodes.length) { + next = this.incrementCurrentNodeAndGetNext_(nodeGroup); + nodeUpdated = true; + } + } else { + while (next && event.charIndex + 2 >= next.startChar && + this.currentNodeGroupIndex_ + 1 < nodeGroup.nodes.length) { + next = this.incrementCurrentNodeAndGetNext_(nodeGroup); + nodeUpdated = true; + } + } + if (nodeUpdated) { + if (!this.prefsManager_.wordHighlightingEnabled()) { + // If we are doing a per-word highlight, we will test the + // node after figuring out what the currently highlighted + // word is. Otherwise, test it now. + this.testCurrentNode_(); + } + } + } + + // Finally update the word highlight if it is enabled. + if (this.prefsManager_.wordHighlightingEnabled()) { + if (hasLength) { + this.currentNodeWord_ = { + 'start': event.charIndex - this.currentNode_.startChar, + 'end': event.charIndex + event.length - this.currentNode_.startChar + }; + this.testCurrentNode_(); + } else { + this.updateNodeHighlight_( + nodeGroup.text, event.charIndex, undefined, opt_endIndex); + } + } else { + this.currentNodeWord_ = null; + } + }, + + /** + * Updates the current node and relevant points to be the next node in the + * group, then returns the next node in the group after that. + * @param {!ParagraphUtils.NodeGroup} nodeGroup + * @return {ParagraphUtils.NodeGroupItem} + * @private + */ + incrementCurrentNodeAndGetNext_: function(nodeGroup) { + // Move to the next node. + this.currentNodeGroupIndex_ += 1; + this.currentNode_ = nodeGroup.nodes[this.currentNodeGroupIndex_]; + // Setting this.currentNodeWord_ to null signals it should be recalculated + // later. + this.currentNodeWord_ = null; + if (this.currentNodeGroupIndex_ + 1 >= nodeGroup.nodes.length) + return null; + return nodeGroup.nodes[this.currentNodeGroupIndex_ + 1]; + }, + + /** * Updates the state. * @param {!chrome.accessibilityPrivate.SelectToSpeakState} state * @private
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index 67606ba..708038d 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -102,6 +102,7 @@ <include name="IDR_PDF_TOOLBAR_MANAGER_JS" file="pdf/toolbar_manager.js" type="BINDATA" /> <include name="IDR_PDF_PDF_FITTING_TYPE_JS" file="pdf/pdf_fitting_type.js" type="BINDATA" /> <include name="IDR_PDF_VIEWPORT_JS" file="pdf/viewport.js" type="BINDATA" /> + <include name="IDR_PDF_VIEWPORT_INTERFACE_JS" file="pdf/viewport_interface.js" type="BINDATA" /> <include name="IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS" file="pdf/open_pdf_params_parser.js" type="BINDATA" /> <include name="IDR_PDF_NAVIGATOR_JS" file="pdf/navigator.js" type="BINDATA" /> <include name="IDR_PDF_VIEWPORT_SCROLLER_JS" file="pdf/viewport_scroller.js" type="BINDATA" />
diff --git a/chrome/browser/resources/downloads/item.js b/chrome/browser/resources/downloads/item.js index 0775982..3c87033 100644 --- a/chrome/browser/resources/downloads/item.js +++ b/chrome/browser/resources/downloads/item.js
@@ -10,6 +10,9 @@ cr.ui.FocusRowBehavior, ], + /** Used by FocusRowBehavior. */ + overrideCustomEquivalent: true, + properties: { /** @type {!downloads.Data} */ data: Object, @@ -104,6 +107,17 @@ this.content = this.$.content; }, + /** Overrides FocusRowBehavior. */ + getCustomEquivalent: function(sampleElement) { + if (sampleElement.getAttribute('focus-type') == 'cancel') { + return this.$$('[focus-type="retry"]'); + } + if (sampleElement.getAttribute('focus-type') == 'retry') { + return this.$$('[focus-type="pauseOrResume"]'); + } + return null; + }, + /** @return {!HTMLElement} */ getFileIcon: function() { return assert(this.$['file-icon']);
diff --git a/chrome/browser/resources/downloads/toolbar.js b/chrome/browser/resources/downloads/toolbar.js index 829d48f..db9f9b8 100644 --- a/chrome/browser/resources/downloads/toolbar.js +++ b/chrome/browser/resources/downloads/toolbar.js
@@ -69,12 +69,12 @@ }, /** - * @param {!CustomEvent} event + * @param {!CustomEvent<string>} event * @private */ onSearchChanged_: function(event) { const searchService = downloads.SearchService.getInstance(); - if (searchService.search(/** @type {string} */ (event.detail))) { + if (searchService.search(event.detail)) { this.spinnerActive = searchService.isSearching(); } this.updateClearAll_();
diff --git a/chrome/browser/resources/history/history_toolbar.js b/chrome/browser/resources/history/history_toolbar.js index 23eae2f0..5ead9094 100644 --- a/chrome/browser/resources/history/history_toolbar.js +++ b/chrome/browser/resources/history/history_toolbar.js
@@ -96,7 +96,7 @@ }, /** - * @param {!CustomEvent} event + * @param {!CustomEvent<string>} event * @private */ onSearchChanged_: function(event) {
diff --git a/chrome/browser/resources/history/side_bar.js b/chrome/browser/resources/history/side_bar.js index 647d931b..f6a5723c 100644 --- a/chrome/browser/resources/history/side_bar.js +++ b/chrome/browser/resources/history/side_bar.js
@@ -38,7 +38,7 @@ }, /** - * @param {CustomEvent} e + * @param {!CustomEvent<{keyboardEvent: !KeyboardEvent}>} e * @private */ onSpacePressed_: function(e) {
diff --git a/chrome/browser/resources/history/synced_device_card.js b/chrome/browser/resources/history/synced_device_card.js index 5f95836..a6ce0c7 100644 --- a/chrome/browser/resources/history/synced_device_card.js +++ b/chrome/browser/resources/history/synced_device_card.js
@@ -145,7 +145,7 @@ }, /** - * @param {CustomEvent} e + * @param {!Event} e * @private */ onMenuButtonTap_: function(e) {
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index e0ac8f4..d585c33 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -256,6 +256,13 @@ /** + * True if dark mode is enabled. + * @type {boolean} + */ +let isDarkModeEnabled = false; + + +/** * Returns a timeout that can be executed early. * @param {!Function} timeout The timeout function. * @param {number} delay The timeout delay. @@ -317,7 +324,7 @@ // custom background set). if (!info || info.usingDefaultTheme && !info.customBackgroundConfigured) { // Dark mode is always considered a dark theme. - return configData.isDarkModeEnabled; + return isDarkModeEnabled; } // Heuristic: light text implies dark theme. @@ -338,10 +345,15 @@ return; } + const useDarkMode = !!info.usingDarkMode; + if (isDarkModeEnabled != useDarkMode) { + document.documentElement.setAttribute('darkmode', useDarkMode); + isDarkModeEnabled = useDarkMode; + } + var background = [ - (configData.isDarkModeEnabled ? - DARK_MODE_BACKGROUND_COLOR : - convertToRGBAColor(info.backgroundColorRgba)), + (isDarkModeEnabled ? DARK_MODE_BACKGROUND_COLOR : + convertToRGBAColor(info.backgroundColorRgba)), info.imageUrl, info.imageTiling, info.imageHorizontalAlignment, info.imageVerticalAlignment ].join(' ').trim(); @@ -353,8 +365,8 @@ } // Dark mode uses a white Google logo. - const useWhiteLogo = info.alternateLogo || - (info.usingDefaultTheme && configData.isDarkModeEnabled); + const useWhiteLogo = + info.alternateLogo || (info.usingDefaultTheme && isDarkModeEnabled); document.body.classList.toggle(CLASSES.ALTERNATE_LOGO, useWhiteLogo); const isNonWhiteBackground = !WHITE_BACKGROUND_COLORS.includes(background); document.body.classList.toggle(CLASSES.NON_WHITE_BG, isNonWhiteBackground); @@ -424,6 +436,7 @@ var message = {cmd: 'updateTheme'}; message.isThemeDark = isThemeDark; message.isUsingTheme = !info.usingDefaultTheme; + message.isDarkMode = !!info.usingDarkMode; var titleColor = NTP_DESIGN.titleColor; if (!info.usingDefaultTheme && info.textColorRgba) { @@ -465,9 +478,18 @@ * @private */ function onThemeChange() { + // Save the current dark mode state to check if dark mode has changed. + const usingDarkMode = isDarkModeEnabled; + renderTheme(); renderOneGoogleBarTheme(); sendThemeInfoToMostVisitedIframe(); + + // If dark mode has been changed, refresh the MV tiles to render the + // appropriate icon. + if (usingDarkMode != isDarkModeEnabled) { + reloadTiles(); + } } @@ -577,7 +599,7 @@ let maxNumTiles = configData.isGooglePage ? MAX_NUM_TILES_CUSTOM_LINKS : MAX_NUM_TILES_MOST_VISITED; for (var i = 0; i < Math.min(maxNumTiles, pages.length); ++i) { - cmds.push({cmd: 'tile', rid: pages[i].rid}); + cmds.push({cmd: 'tile', rid: pages[i].rid, darkMode: isDarkModeEnabled}); } cmds.push({cmd: 'show'}); @@ -1020,9 +1042,6 @@ ntpApiHandle.onthemechange = onThemeChange; ntpApiHandle.onmostvisitedchange = onMostVisitedChange; - if (configData.isDarkModeEnabled) { - document.documentElement.setAttribute('darkmode', true); - } renderTheme(); var searchboxApiHandle = embeddedSearchApiHandle.searchBox;
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js index 9271b92..d4752fc 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.js +++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -343,6 +343,7 @@ document.body.style.setProperty('--tile-title-color', info.tileTitleColor); document.body.classList.toggle('dark-theme', info.isThemeDark); document.body.classList.toggle('using-theme', info.isUsingTheme); + document.documentElement.setAttribute('darkmode', info.isDarkMode); // Reduce font weight on the default(white) background for Mac and CrOS. document.body.classList.toggle('mac-chromeos', @@ -482,6 +483,9 @@ } data.tid = data.rid; + // Use a dark icon if dark mode is enabled. Keep value in sync with + // NtpIconSource. + data.dark = args.darkMode ? 'dark/' : ''; if (!data.faviconUrl) { data.faviconUrl = 'chrome-search://favicon/size/16@' + window.devicePixelRatio + 'x/' + data.renderViewId + '/' + data.tid; @@ -729,7 +733,7 @@ fi.title = ''; fi.alt = ''; fi.src = 'chrome-search://ntpicon/size/24@' + window.devicePixelRatio + - 'x/' + data.url; + 'x/' + data.dark + data.url; loadedCounter += 1; fi.addEventListener('load', function(ev) { // Store the type for a potential later navigation.
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js index 77ce634..2125fc2 100644 --- a/chrome/browser/resources/md_extensions/manager.js +++ b/chrome/browser/resources/md_extensions/manager.js
@@ -284,14 +284,14 @@ }, /** - * @param {!CustomEvent} event + * @param {!CustomEvent<string>} event * @private */ onFilterChanged_: function(event) { if (this.currentPage_.page !== Page.LIST) { extensions.navigation.navigateTo({page: Page.LIST}); } - this.filter = /** @type {string} */ (event.detail); + this.filter = event.detail; }, /** @private */ @@ -543,7 +543,7 @@ }, /** - * @param {!CustomEvent} e + * @param {!Event} e * @private */ onViewExitStart_: function(e) { @@ -552,7 +552,7 @@ }, /** - * @param {!CustomEvent} e + * @param {!Event} e * @private */ onViewExitFinish_: function(e) { @@ -577,14 +577,14 @@ }, /** - * @param {!CustomEvent} e + * @param {!CustomEvent<!Array<string>>} e * @private */ onShowInstallWarnings_: function(e) { // Leverage Polymer data bindings instead of just assigning the // installWarnings on the dialog since the dialog hasn't been stamped // in the DOM yet. - this.installWarnings_ = /** @type{!Array<string>} */ (e.detail); + this.installWarnings_ = e.detail; this.showInstallWarningsDialog_ = true; },
diff --git a/chrome/browser/resources/md_extensions/toggle_row.js b/chrome/browser/resources/md_extensions/toggle_row.js index d1786a77..c4f67ba 100644 --- a/chrome/browser/resources/md_extensions/toggle_row.js +++ b/chrome/browser/resources/md_extensions/toggle_row.js
@@ -57,8 +57,7 @@ }, /** - * Fires - * @param {!CustomEvent} e + * @param {!CustomEvent<boolean>} e * @private */ onCrToggleChange_: function(e) {
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn index f79f345..ac96b75 100644 --- a/chrome/browser/resources/pdf/BUILD.gn +++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -53,6 +53,29 @@ js_library("viewport_scroller") { } +js_library("viewport_interface") { + deps = [ + ":pdf_fitting_type", + ] +} + +js_library("viewport") { + deps = [ + ":gesture_detector", + ":viewport_interface", + ":zoom_manager", + "//ui/webui/resources/js:util", + ] + externs_list = [ "$externs_path/pending.js" ] +} + +js_library("zoom_manager") { + deps = [ + ":browser_api", + ":viewport_interface", + ] +} + js_type_check("pdf_resources") { deps = [ ":browser_api", @@ -60,6 +83,9 @@ ":open_pdf_params_parser", ":pdf_fitting_type", ":pdf_scripting_api", + ":viewport", + ":viewport_interface", ":viewport_scroller", + ":zoom_manager", ] }
diff --git a/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn b/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn index 420a227..a2cb5af 100644 --- a/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn +++ b/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn
@@ -12,11 +12,7 @@ js_library("viewer-ink-host") { deps = [ + "//chrome/browser/resources/pdf:viewport", "//chrome/browser/resources/pdf/ink:ink_api", ] - externs_list = [ - # TODO(dstockwell): Once viewport can be typechecked this can be replaced - # by a dep on viewport. - "externs.js", - ] }
diff --git a/chrome/browser/resources/pdf/elements/viewer-ink-host/externs.js b/chrome/browser/resources/pdf/elements/viewer-ink-host/externs.js deleted file mode 100644 index f3769e2..0000000 --- a/chrome/browser/resources/pdf/elements/viewer-ink-host/externs.js +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @typedef {{ - * x: number, - * y: number - * }} - */ -let Point; - -/** - * @typedef {{ - * width: number, - * height: number - * }} - */ -let Size; - -class Viewport { - /** - * @param {number} zoom - * @return {{width: number, height: number}} - */ - getDocumentDimensions(zoom) {} - - /** - * @param {!Point} point - * @return {boolean} - */ - isPointInsidePage(point) {} - - /** @return {!Point} */ - get position() {} - - /** @return {!Size} */ - get size() {} - - /** @return {number} */ - get zoom() {} -} - -/** @type {Object} */ -Viewport.PAGE_SHADOW; - -/** @type {number} */ -Viewport.PAGE_SHADOW.top; - -/** @type {number} */ -Viewport.PAGE_SHADOW.left;
diff --git a/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js b/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js index 1895a2347..d4e26340 100644 --- a/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js +++ b/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js
@@ -222,7 +222,7 @@ const pos = viewport.position; const size = viewport.size; const zoom = viewport.zoom; - const documentWidth = viewport.getDocumentDimensions(zoom).width * zoom; + const documentWidth = viewport.getDocumentDimensions().width * zoom; // Adjust for page shadows. const y = pos.y - Viewport.PAGE_SHADOW.top * zoom; let x = pos.x - Viewport.PAGE_SHADOW.left * zoom;
diff --git a/chrome/browser/resources/pdf/index.html b/chrome/browser/resources/pdf/index.html index 3450bd5..9d79f99 100644 --- a/chrome/browser/resources/pdf/index.html +++ b/chrome/browser/resources/pdf/index.html
@@ -35,6 +35,7 @@ </body> <script src="pdf_fitting_type.js"></script> <script src="toolbar_manager.js"></script> +<script src="viewport_interface.js"></script> <script src="viewport.js"></script> <script src="open_pdf_params_parser.js"></script> <script src="navigator.js"></script>
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index f98dfc0a..cf5b485eb 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -175,7 +175,7 @@ this.browserApi_.getZoomBehavior() == BrowserApi.ZoomBehavior.MANAGE ? this.browserApi_.getDefaultZoom() : 1.0; - this.viewport_ = new Viewport( + this.viewport_ = new ViewportImpl( window, this.sizer_, this.viewportChanged_.bind(this), () => this.currentController_.beforeZoom(), () => {
diff --git a/chrome/browser/resources/pdf/viewport.js b/chrome/browser/resources/pdf/viewport.js index dce8d53..02664b3f 100644 --- a/chrome/browser/resources/pdf/viewport.js +++ b/chrome/browser/resources/pdf/viewport.js
@@ -2,37 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * @typedef {{ - * x: number, - * y: number - * }} - */ -let Point; /** - * @typedef {{ - * x: (number|undefined), - * y: (number|undefined), - * }} + * Clamps the zoom factor (or page scale factor) to be within the limits. + * + * @param {number} factor The zoom/scale factor. + * @return {number} The factor clamped within the limits. */ -let PartialPoint; - -/** - * @typedef {{ - * x: number, - * y: number, - * width: number, - * heigh: number, - * }} - */ -let Rect; +function clampZoom(factor) { + return Math.max( + Viewport.ZOOM_FACTOR_RANGE.min, + Math.min(factor, Viewport.ZOOM_FACTOR_RANGE.max)); +} /** * Returns the height of the intersection of two rectangles. * - * @param {Rect} rect1 the first rect - * @param {Rect} rect2 the second rect + * @param {!ViewportRect} rect1 the first rect + * @param {!ViewportRect} rect2 the second rect * @return {number} the height of the intersection of the rects */ function getIntersectionHeight(rect1, rect2) { @@ -45,9 +32,9 @@ /** * Computes vector between two points. * - * @param {!Object} p1 The first point. - * @param {!Object} p2 The second point. - * @return {!Object} The vector. + * @param {!Point} p1 The first point. + * @param {!Point} p2 The second point. + * @return {!Point} The vector. */ function vectorDelta(p1, p2) { return {x: p2.x - p1.x, y: p2.y - p1.y}; @@ -61,133 +48,75 @@ }; } -// TODO: convert Viewport to ES6 class syntax -/** - * Create a new viewport. - * - * @param {Window} window the window - * @param {Object} sizer is the element which represents the size of the - * document in the viewport - * @param {Function} viewportChangedCallback is run when the viewport changes - * @param {Function} beforeZoomCallback is run before a change in zoom - * @param {Function} afterZoomCallback is run after a change in zoom - * @param {Function} setUserInitiatedCallback is run to indicate whether a zoom - * event is user initiated. - * @param {number} scrollbarWidth the width of scrollbars on the page - * @param {number} defaultZoom The default zoom level. - * @param {number} topToolbarHeight The number of pixels that should initially - * be left blank above the document for the toolbar. - * @constructor - */ -function Viewport( - window, sizer, viewportChangedCallback, beforeZoomCallback, - afterZoomCallback, setUserInitiatedCallback, scrollbarWidth, defaultZoom, - topToolbarHeight) { - this.window_ = window; - this.sizer_ = sizer; - this.viewportChangedCallback_ = viewportChangedCallback; - this.beforeZoomCallback_ = beforeZoomCallback; - this.afterZoomCallback_ = afterZoomCallback; - this.setUserInitiatedCallback_ = setUserInitiatedCallback; - this.allowedToChangeZoom_ = false; - this.internalZoom_ = 1; - this.zoomManager_ = new InactiveZoomManager(this, 1); - this.documentDimensions_ = null; - this.pageDimensions_ = []; - this.scrollbarWidth_ = scrollbarWidth; - this.fittingType_ = FittingType.NONE; - this.defaultZoom_ = defaultZoom; - this.topToolbarHeight_ = topToolbarHeight; - this.prevScale_ = 1; - this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE; - this.pinchPanVector_ = null; - this.pinchCenter_ = null; - this.firstPinchCenterInFrame_ = null; - this.rotations_ = 0; +/** @implements {Viewport} */ +class ViewportImpl { + /** + * Create a new viewport. + * + * @param {Window} window the window + * @param {Object} sizer is the element which represents the size of the + * document in the viewport + * @param {Function} viewportChangedCallback is run when the viewport changes + * @param {Function} beforeZoomCallback is run before a change in zoom + * @param {Function} afterZoomCallback is run after a change in zoom + * @param {Function} setUserInitiatedCallback is run to indicate whether a + * zoom event is user initiated. + * @param {number} scrollbarWidth the width of scrollbars on the page + * @param {number} defaultZoom The default zoom level. + * @param {number} topToolbarHeight The number of pixels that should initially + * be left blank above the document for the toolbar. + */ + constructor( + window, sizer, viewportChangedCallback, beforeZoomCallback, + afterZoomCallback, setUserInitiatedCallback, scrollbarWidth, defaultZoom, + topToolbarHeight) { + this.window_ = window; + this.sizer_ = sizer; + this.viewportChangedCallback_ = viewportChangedCallback; + this.beforeZoomCallback_ = beforeZoomCallback; + this.afterZoomCallback_ = afterZoomCallback; + this.setUserInitiatedCallback_ = setUserInitiatedCallback; + this.allowedToChangeZoom_ = false; + this.internalZoom_ = 1; + this.zoomManager_ = new InactiveZoomManager(this, 1); + /** @private {?DocumentDimensions} */ + this.documentDimensions_ = null; + /** @private {Array<ViewportRect>} */ + this.pageDimensions_ = []; + this.scrollbarWidth_ = scrollbarWidth; + this.fittingType_ = FittingType.NONE; + this.defaultZoom_ = defaultZoom; + this.topToolbarHeight_ = topToolbarHeight; + this.prevScale_ = 1; + this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE; + this.pinchPanVector_ = null; + this.pinchCenter_ = null; + /** @private {?Point} */ + this.firstPinchCenterInFrame_ = null; + this.rotations_ = 0; + // TODO(dstockwell): why isn't this private? + this.oldCenterInContent = null; + this.keepContentCentered_ = null; - window.addEventListener('scroll', this.updateViewport_.bind(this)); - window.addEventListener('resize', this.resizeWrapper_.bind(this)); -} - -/** - * Enumeration of pinch states. - * This should match PinchPhase enum in pdf/out_of_process_instance.h - * @enum {number} - */ -Viewport.PinchPhase = { - PINCH_NONE: 0, - PINCH_START: 1, - PINCH_UPDATE_ZOOM_OUT: 2, - PINCH_UPDATE_ZOOM_IN: 3, - PINCH_END: 4 -}; - -/** - * The increment to scroll a page by in pixels when up/down/left/right arrow - * keys are pressed. Usually we just let the browser handle scrolling on the - * window when these keys are pressed but in certain cases we need to simulate - * these events. - */ -Viewport.SCROLL_INCREMENT = 40; - -/** - * Predefined zoom factors to be used when zooming in/out. These are in - * ascending order. This should match the lists in - * components/ui/zoom/page_zoom_constants.h and - * chrome/browser/resources/settings/appearance_page/appearance_page.js - */ -Viewport.ZOOM_FACTORS = [ - 0.25, 1 / 3, 0.5, 2 / 3, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3, - 4, 5 -]; - -/** - * The minimum and maximum range to be used to clip zoom factor. - */ -Viewport.ZOOM_FACTOR_RANGE = { - min: Viewport.ZOOM_FACTORS[0], - max: Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1] -}; - -/** - * Clamps the zoom factor (or page scale factor) to be within the limits. - * - * @param {number} factor The zoom/scale factor. - * @return {number} The factor clamped within the limits. - */ -Viewport.clampZoom = function(factor) { - return Math.max( - Viewport.ZOOM_FACTOR_RANGE.min, - Math.min(factor, Viewport.ZOOM_FACTOR_RANGE.max)); -}; - -/** - * The width of the page shadow around pages in pixels. - */ -Viewport.PAGE_SHADOW = { - top: 3, - bottom: 7, - left: 5, - right: 5 -}; - -Viewport.prototype = { + window.addEventListener('scroll', this.updateViewport_.bind(this)); + window.addEventListener('resize', this.resizeWrapper_.bind(this)); + } /** * @param {number} n the number of clockwise 90-degree rotations to * increment by. */ - rotateClockwise: function(n) { + rotateClockwise(n) { this.rotations_ = (this.rotations_ + n) % 4; - }, + } /** * @return {number} the number of clockwise 90-degree rotations that have been * applied. */ - getClockwiseRotations: function() { + getClockwiseRotations() { return this.rotations_; - }, + } /** * Converts a page position (e.g. the location of a bookmark) to a screen @@ -197,7 +126,7 @@ * @param {Point} point The position on `page`. * @return The screen position. */ - convertPageToScreen: function(page, point) { + convertPageToScreen(page, point) { const dimensions = this.getPageInsetDimensions(page); // width & height are already rotated. @@ -231,7 +160,7 @@ x: result.x + Viewport.PAGE_SHADOW.left, y: result.y + Viewport.PAGE_SHADOW.top, }; - }, + } /** @@ -244,7 +173,7 @@ * @return {Object} A dictionary with scaled 'width'/'height' of the document. * @private */ - getZoomedDocumentDimensions_: function(zoom) { + getZoomedDocumentDimensions_(zoom) { if (!this.documentDimensions_) { return null; } @@ -252,30 +181,23 @@ width: Math.round(this.documentDimensions_.width * zoom), height: Math.round(this.documentDimensions_.height * zoom) }; - }, + } - /** - * Returns the document dimensions. - * - * @return {Point} A dictionary with the 'width'/'height' of the document. - */ - getDocumentDimensions: function() { + /** @override */ + getDocumentDimensions() { return { width: this.documentDimensions_.width, height: this.documentDimensions_.height }; - }, + } /** - * Returns true if the document needs scrollbars at the given zoom level. - * * @param {number} zoom compute whether scrollbars are needed at this zoom - * @return {Object} with 'horizontal' and 'vertical' keys which map to bool - * values indicating if the horizontal and vertical scrollbars are needed - * respectively. + * @return {{horizontal: boolean, vertical: boolean}} whether horizontal or + * vertical scrollbars are needed. * @private */ - documentNeedsScrollbars_: function(zoom) { + documentNeedsScrollbars_(zoom) { const zoomedDimensions = this.getZoomedDocumentDimensions_(zoom); if (!zoomedDimensions) { return {horizontal: false, vertical: false}; @@ -294,7 +216,7 @@ vertical: zoomedDimensions.height + this.topToolbarHeight_ > this.window_.innerHeight }; - }, + } /** * Returns true if the document needs scrollbars at the current zoom level. @@ -303,50 +225,50 @@ * indicating if the horizontal and vertical scrollbars are needed * respectively. */ - documentHasScrollbars: function() { + documentHasScrollbars() { return this.documentNeedsScrollbars_(this.zoom); - }, + } /** * Helper function called when the zoomed document size changes. * * @private */ - contentSizeChanged_: function() { + contentSizeChanged_() { const zoomedDimensions = this.getZoomedDocumentDimensions_(this.zoom); if (zoomedDimensions) { this.sizer_.style.width = zoomedDimensions.width + 'px'; this.sizer_.style.height = zoomedDimensions.height + this.topToolbarHeight_ + 'px'; } - }, + } /** * Called when the viewport should be updated. * * @private */ - updateViewport_: function() { + updateViewport_() { this.viewportChangedCallback_(); - }, + } /** * Called when the browser window size changes. * * @private */ - resizeWrapper_: function() { + resizeWrapper_() { this.setUserInitiatedCallback_(false); this.resize_(); this.setUserInitiatedCallback_(true); - }, + } /** * Called when the viewport size changes. * * @private */ - resize_: function() { + resize_() { if (this.fittingType_ == FittingType.FIT_TO_PAGE) { this.fitToPageInternal_(false); } else if (this.fittingType_ == FittingType.FIT_TO_WIDTH) { @@ -358,30 +280,26 @@ } else { this.updateViewport_(); } - }, + } - /** - * @type {Point} the scroll position of the viewport. - */ + /** @override */ get position() { return { x: this.window_.pageXOffset, y: this.window_.pageYOffset - this.topToolbarHeight_ }; - }, + } /** * Scroll the viewport to the specified position. * - * @type {Point} position The position to scroll to. + * @param {Point} position The position to scroll to. */ set position(position) { this.window_.scrollTo(position.x, position.y + this.topToolbarHeight_); - }, + } - /** - * @type {Object} the size of the viewport excluding scrollbars. - */ + /** @override */ get size() { const needsScrollbars = this.documentNeedsScrollbars_(this.zoom); const scrollbarWidth = needsScrollbars.vertical ? this.scrollbarWidth_ : 0; @@ -391,14 +309,12 @@ width: this.window_.innerWidth - scrollbarWidth, height: this.window_.innerHeight - scrollbarHeight }; - }, + } - /** - * @type {number} the zoom level of the viewport. - */ + /** @override */ get zoom() { return this.zoomManager_.applyBrowserZoom(this.internalZoom_); - }, + } /** * Set the zoom manager. @@ -407,30 +323,31 @@ */ set zoomManager(manager) { this.zoomManager_ = manager; - }, + } /** - * @type {Viewport.PinchPhase} The phase of the current pinch gesture for + * @return {Viewport.PinchPhase} The phase of the current pinch gesture for * the viewport. */ get pinchPhase() { return this.pinchPhase_; - }, + } /** - * @type {Object} The panning caused by the current pinch gesture (as + * @return {Object} The panning caused by the current pinch gesture (as * the deltas of the x and y coordinates). */ get pinchPanVector() { return this.pinchPanVector_; - }, + } /** - * @type {Object} The coordinates of the center of the current pinch gesture. + * @return {Object} The coordinates of the center of the current pinch + * gesture. */ get pinchCenter() { return this.pinchCenter_; - }, + } /** * Used to wrap a function that might perform zooming on the viewport. This is @@ -441,13 +358,13 @@ * @param {Function} f Function to wrap * @private */ - mightZoom_: function(f) { + mightZoom_(f) { this.beforeZoomCallback_(); this.allowedToChangeZoom_ = true; f(); this.allowedToChangeZoom_ = false; this.afterZoomCallback_(); - }, + } /** * Sets the zoom of the viewport. @@ -455,7 +372,7 @@ * @param {number} newZoom the zoom level to zoom to. * @private */ - setZoomInternal_: function(newZoom) { + setZoomInternal_(newZoom) { assert( this.allowedToChangeZoom_, 'Called Viewport.setZoomInternal_ without calling ' + @@ -473,7 +390,7 @@ x: currentScrollPos.x * this.zoom, y: currentScrollPos.y * this.zoom }; - }, + } /** * Sets the zoom of the viewport. @@ -483,12 +400,12 @@ * @param {!Object} center The pinch center in content coordinates. * @private */ - setPinchZoomInternal_: function(scaleDelta, center) { + setPinchZoomInternal_(scaleDelta, center) { assert( this.allowedToChangeZoom_, 'Called Viewport.setPinchZoomInternal_ without calling ' + 'Viewport.mightZoom_.'); - this.internalZoom_ = Viewport.clampZoom(this.internalZoom_ * scaleDelta); + this.internalZoom_ = clampZoom(this.internalZoom_ * scaleDelta); const newCenterInContent = this.frameToContent(center); const delta = { @@ -505,7 +422,7 @@ this.contentSizeChanged_(); // Scroll to the scaled scroll position. this.position = {x: currentScrollPos.x, y: currentScrollPos.y}; - }, + } /** * Converts a point from frame to content coordinates. @@ -514,35 +431,30 @@ * @return {!Object} The content coordinates. * @private */ - frameToContent: function(framePoint) { + frameToContent(framePoint) { // TODO(mcnee) Add a helper Point class to avoid duplicating operations // on plain {x,y} objects. return { x: (framePoint.x + this.position.x) / this.zoom, y: (framePoint.y + this.position.y) / this.zoom }; - }, + } /** * Sets the zoom to the given zoom level. * * @param {number} newZoom the zoom level to zoom to. */ - setZoom: function(newZoom) { + setZoom(newZoom) { this.fittingType_ = FittingType.NONE; this.mightZoom_(() => { - this.setZoomInternal_(Viewport.clampZoom(newZoom)); + this.setZoomInternal_(clampZoom(newZoom)); this.updateViewport_(); }); - }, + } - /** - * Gets notified of the browser zoom changing seperately from the - * internal zoom. - * - * @param {number} oldBrowserZoom the previous value of the browser zoom. - */ - updateZoomFromBrowserChange: function(oldBrowserZoom) { + /** @override */ + updateZoomFromBrowserChange(oldBrowserZoom) { this.mightZoom_(() => { // Record the scroll position (relative to the top-left of the window). const oldZoom = oldBrowserZoom * this.internalZoom_; @@ -558,21 +470,21 @@ }; this.updateViewport_(); }); - }, + } /** - * @type {number} the width of scrollbars in the viewport in pixels. + * @return {number} the width of scrollbars in the viewport in pixels. */ get scrollbarWidth() { return this.scrollbarWidth_; - }, + } /** - * @type {FittingType} the fitting type the viewport is currently in. + * @return {FittingType} the fitting type the viewport is currently in. */ get fittingType() { return this.fittingType_; - }, + } /** * Get the which page is at a given y position. @@ -581,7 +493,7 @@ * @return {number} the index of a page overlapping the given y-coordinate. * @private */ - getPageAtY_: function(y) { + getPageAtY_(y) { let min = 0; let max = this.pageDimensions_.length - 1; while (max >= min) { @@ -607,12 +519,9 @@ } } return 0; - }, + } - /** - * @param {Point} point - * @return {boolean} Whether |point| (in screen coordinates) is inside a page - */ + /** @override */ isPointInsidePage(point) { const zoom = this.zoom; const size = this.size; @@ -632,7 +541,7 @@ const minX = (outerWidth - pageWidth) / 2; const maxX = outerWidth - minX; return x >= minX && x <= maxX; - }, + } /** * Returns the page with the greatest proportion of its height in the current @@ -640,7 +549,7 @@ * * @return {number} the index of the most visible page. */ - getMostVisiblePage: function() { + getMostVisiblePage() { const firstVisiblePage = this.getPageAtY_(this.position.y / this.zoom); if (firstVisiblePage == this.pageDimensions_.length - 1) { return firstVisiblePage; @@ -664,7 +573,7 @@ return firstVisiblePage + 1; } return firstVisiblePage; - }, + } /** * Compute the zoom level for fit-to-page, fit-to-width or fit-to-height. @@ -679,7 +588,7 @@ * @return {number} the internal zoom to set * @private */ - computeFittingZoom_: function(pageDimensions, fitWidth, fitHeight) { + computeFittingZoom_(pageDimensions, fitWidth, fitHeight) { assert( fitWidth || fitHeight, 'Invalid parameters. At least one of fitWidth and fitHeight must be ' + @@ -730,7 +639,7 @@ pageDimensions.height); return this.zoomManager_.internalZoomComponent(zoom); - }, + } /** * Compute a zoom level given the dimensions to fit and the actual numbers @@ -747,7 +656,7 @@ * @return {number} the internal zoom to set * @private */ - computeFittingZoomGivenDimensions_: function( + computeFittingZoomGivenDimensions_( fitWidth, fitHeight, windowWidth, windowHeight, pageWidth, pageHeight) { // Assumes at least one of {fitWidth, fitHeight} is set. let zoomWidth; @@ -772,12 +681,12 @@ } return Math.max(zoom, 0); - }, + } /** * Zoom the viewport so that the page width consumes the entire viewport. */ - fitToWidth: function() { + fitToWidth() { this.mightZoom_(() => { this.fittingType_ = FittingType.FIT_TO_WIDTH; if (!this.documentDimensions_) { @@ -789,7 +698,7 @@ this.computeFittingZoom_(this.documentDimensions_, true, false)); this.updateViewport_(); }); - }, + } /** * Zoom the viewport so that the page height consumes the entire viewport. @@ -799,7 +708,7 @@ * should remain at the current scroll position. * @private */ - fitToHeightInternal_: function(scrollToTopOfPage) { + fitToHeightInternal_(scrollToTopOfPage) { this.mightZoom_(() => { this.fittingType_ = FittingType.FIT_TO_HEIGHT; if (!this.documentDimensions_) { @@ -818,14 +727,14 @@ } this.updateViewport_(); }); - }, + } /** * Zoom the viewport so that the page height consumes the entire viewport. */ - fitToHeight: function() { + fitToHeight() { this.fitToHeightInternal_(true); - }, + } /** * Zoom the viewport so that a page consumes as much as possible of the it. @@ -835,7 +744,7 @@ * should remain at the current scroll position. * @private */ - fitToPageInternal_: function(scrollToTopOfPage) { + fitToPageInternal_(scrollToTopOfPage) { this.mightZoom_(() => { this.fittingType_ = FittingType.FIT_TO_PAGE; if (!this.documentDimensions_) { @@ -853,20 +762,20 @@ } this.updateViewport_(); }); - }, + } /** * Zoom the viewport so that a page consumes the entire viewport. Also scrolls * the viewport to the top of the current page. */ - fitToPage: function() { + fitToPage() { this.fitToPageInternal_(true); - }, + } /** * Zoom the viewport to the default zoom policy. */ - fitToNone: function() { + fitToNone() { this.mightZoom_(() => { this.fittingType_ = FittingType.NONE; if (!this.documentDimensions_) { @@ -877,12 +786,12 @@ this.computeFittingZoom_(this.documentDimensions_, true, false))); this.updateViewport_(); }); - }, + } /** * Zoom out to the next predefined zoom level. */ - zoomOut: function() { + zoomOut() { this.mightZoom_(() => { this.fittingType_ = FittingType.NONE; let nextZoom = Viewport.ZOOM_FACTORS[0]; @@ -894,12 +803,12 @@ this.setZoomInternal_(nextZoom); this.updateViewport_(); }); - }, + } /** * Zoom in to the next predefined zoom level. */ - zoomIn: function() { + zoomIn() { this.mightZoom_(() => { this.fittingType_ = FittingType.NONE; let nextZoom = Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1]; @@ -911,26 +820,28 @@ this.setZoomInternal_(nextZoom); this.updateViewport_(); }); - }, + } /** * Pinch zoom event handler. * * @param {!Object} e The pinch event. */ - pinchZoom: function(e) { + pinchZoom(e) { this.mightZoom_(() => { this.pinchPhase_ = e.direction == 'out' ? Viewport.PinchPhase.PINCH_UPDATE_ZOOM_OUT : Viewport.PinchPhase.PINCH_UPDATE_ZOOM_IN; const scaleDelta = e.startScaleRatio / this.prevScale_; - this.pinchPanVector_ = - vectorDelta(e.center, this.firstPinchCenterInFrame_); + if (this.firstPinchCenterInFrame_ != null) { + this.pinchPanVector_ = + vectorDelta(e.center, this.firstPinchCenterInFrame_); + } const needsScrollbars = this.documentNeedsScrollbars_(this.zoomManager_.applyBrowserZoom( - Viewport.clampZoom(this.internalZoom_ * scaleDelta))); + clampZoom(this.internalZoom_ * scaleDelta))); this.pinchCenter_ = e.center; @@ -955,9 +866,10 @@ this.updateViewport_(); this.prevScale_ = e.startScaleRatio; }); - }, + } - pinchZoomStart: function(e) { + /** @param {!Object} e The pinch event. */ + pinchZoomStart(e) { this.pinchPhase_ = Viewport.PinchPhase.PINCH_START; this.prevScale_ = 1; this.oldCenterInContent = @@ -968,9 +880,10 @@ // We keep track of begining of the pinch. // By doing so we will be able to compute the pan distance. this.firstPinchCenterInFrame_ = e.center; - }, + } - pinchZoomEnd: function(e) { + /** @param {!Object} e The pinch event. */ + pinchZoomEnd(e) { this.mightZoom_(() => { this.pinchPhase_ = Viewport.PinchPhase.PINCH_END; const scaleDelta = e.startScaleRatio / this.prevScale_; @@ -984,16 +897,16 @@ this.pinchPanVector_ = null; this.pinchCenter_ = null; this.firstPinchCenterInFrame_ = null; - }, + } /** * Go to the given page index. * * @param {number} page the index of the page to go to. zero-based. */ - goToPage: function(page) { + goToPage(page) { this.goToPageAndXY(page, 0, 0); - }, + } /** * Go to the given y position in the given page index. @@ -1002,7 +915,7 @@ * @param {number} x the x position in the page to go to. * @param {number} y the y position in the page to go to. */ - goToPageAndXY: function(page, x, y) { + goToPageAndXY(page, x, y) { this.mightZoom_(() => { if (this.pageDimensions_.length === 0) { return; @@ -1027,14 +940,15 @@ }; this.updateViewport_(); }); - }, + } /** * Set the dimensions of the document. * - * @param {Object} documentDimensions the dimensions of the document + * @param {DocumentDimensions} documentDimensions the dimensions of the + * document */ - setDocumentDimensions: function(documentDimensions) { + setDocumentDimensions(documentDimensions) { this.mightZoom_(() => { const initialDimensions = !this.documentDimensions_; this.documentDimensions_ = documentDimensions; @@ -1048,13 +962,13 @@ this.contentSizeChanged_(); this.resize_(); }); - }, + } /** * @param {number} page - * @return {Rect} The bounds for page `page` minus the shadows. + * @return {ViewportRect} The bounds for page `page` minus the shadows. */ - getPageInsetDimensions: function(page) { + getPageInsetDimensions(page) { const pageDimensions = this.pageDimensions_[page]; const shadow = Viewport.PAGE_SHADOW; return { @@ -1063,7 +977,7 @@ width: pageDimensions.width - shadow.left - shadow.right, height: pageDimensions.height - shadow.top - shadow.bottom, }; - }, + } /** * Get the coordinates of the page contents (excluding the page shadow) @@ -1072,7 +986,7 @@ * @param {number} page the index of the page to get the rect for. * @return {Object} a rect representing the page in screen coordinates. */ - getPageScreenRect: function(page) { + getPageScreenRect(page) { if (!this.documentDimensions_) { return {x: 0, y: 0, width: 0, height: 0}; } @@ -1102,7 +1016,7 @@ width: insetDimensions.width * this.zoom, height: insetDimensions.height * this.zoom }; - }, + } /** * Check if the current fitting type is a paged mode. @@ -1112,18 +1026,18 @@ * * @return {boolean} Whether the current fitting type is a paged mode. */ - isPagedMode: function(page) { + isPagedMode() { return ( this.fittingType_ == FittingType.FIT_TO_PAGE || this.fittingType_ == FittingType.FIT_TO_HEIGHT); - }, + } /** * Scroll the viewport to the specified position. * - * @param {!PartialPoint} point The position to which to move the viewport. + * @param {!Point} point The position to which to move the viewport. */ - scrollTo: function(point) { + scrollTo(point) { let changed = false; const newPosition = this.position; if (point.x !== undefined && point.x != newPosition.x) { @@ -1138,17 +1052,17 @@ if (changed) { this.position = newPosition; } - }, + } /** * Scroll the viewport by the specified delta. * * @param {!Point} delta The delta by which to move the viewport. */ - scrollBy: function(delta) { + scrollBy(delta) { const newPosition = this.position; newPosition.x += delta.x; newPosition.y += delta.y; this.scrollTo(newPosition); } -}; +}
diff --git a/chrome/browser/resources/pdf/viewport_interface.js b/chrome/browser/resources/pdf/viewport_interface.js new file mode 100644 index 0000000..c9f99ac --- /dev/null +++ b/chrome/browser/resources/pdf/viewport_interface.js
@@ -0,0 +1,136 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @typedef {{ + * width: number, + * height: number, + * pageDimensions: Array<ViewportRect>, + * }} + */ +let DocumentDimensions; + +/** + * @typedef {{ + * x: number, + * y: number + * }} + */ +let Point; + +/** + * @typedef {{ + * width: number, + * height: number, + * }} + */ +let Size; + +/** + * @typedef {{ + * x: number, + * y: number, + * width: number, + * height: number, + * }} + */ +let ViewportRect; + +/** + * @interface + */ +class Viewport { + /** + * Returns the document dimensions. + * + * @return {!Size} A dictionary with the 'width'/'height' of the document. + */ + getDocumentDimensions() {} + + /** + * @return {!Point} the scroll position of the viewport. + */ + get position() {} + + /** + * @return {!Size} the size of the viewport excluding scrollbars. + */ + get size() {} + + /** + * @return {number} the zoom level of the viewport. + */ + get zoom() {} + + /** + * Sets the zoom to the given zoom level. + * + * @param {number} newZoom the zoom level to zoom to. + */ + setZoom(newZoom) {} + + /** + * Gets notified of the browser zoom changing separately from the + * internal zoom. + * + * @param {number} oldBrowserZoom the previous value of the browser zoom. + */ + updateZoomFromBrowserChange(oldBrowserZoom) {} + + /** + * @param {!Point} point + * @return {boolean} Whether |point| (in screen coordinates) is inside a page + */ + isPointInsidePage(point) {} +} + +/** + * Enumeration of pinch states. + * This should match PinchPhase enum in pdf/out_of_process_instance.h + * @enum {number} + */ +Viewport.PinchPhase = { + PINCH_NONE: 0, + PINCH_START: 1, + PINCH_UPDATE_ZOOM_OUT: 2, + PINCH_UPDATE_ZOOM_IN: 3, + PINCH_END: 4 +}; + +/** + * The increment to scroll a page by in pixels when up/down/left/right arrow + * keys are pressed. Usually we just let the browser handle scrolling on the + * window when these keys are pressed but in certain cases we need to simulate + * these events. + */ +Viewport.SCROLL_INCREMENT = 40; + +/** + * Predefined zoom factors to be used when zooming in/out. These are in + * ascending order. This should match the lists in + * components/ui/zoom/page_zoom_constants.h and + * chrome/browser/resources/settings/appearance_page/appearance_page.js + */ +Viewport.ZOOM_FACTORS = [ + 0.25, 1 / 3, 0.5, 2 / 3, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3, + 4, 5 +]; + +/** + * The minimum and maximum range to be used to clip zoom factor. + */ +Viewport.ZOOM_FACTOR_RANGE = { + min: Viewport.ZOOM_FACTORS[0], + max: Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1] +}; + +/** + * The width of the page shadow around pages in pixels. + */ +Viewport.PAGE_SHADOW = { + top: 3, + bottom: 7, + left: 5, + right: 5 +};
diff --git a/chrome/browser/resources/print_preview/metrics.js b/chrome/browser/resources/print_preview/metrics.js index 34af759..83d0cf7 100644 --- a/chrome/browser/resources/print_preview/metrics.js +++ b/chrome/browser/resources/print_preview/metrics.js
@@ -49,8 +49,10 @@ INVITATION_ACCEPTED: 12, // User rejected printer sharing invitation. INVITATION_REJECTED: 13, + // User clicked on Manage button + MANAGE_BUTTON_CLICKED: 14, // Max value. - DESTINATION_SEARCH_MAX_BUCKET: 14 + DESTINATION_SEARCH_MAX_BUCKET: 15 }; /**
diff --git a/chrome/browser/resources/print_preview/new/destination_dialog.js b/chrome/browser/resources/print_preview/new/destination_dialog.js index b5d3299..7229839c 100644 --- a/chrome/browser/resources/print_preview/new/destination_dialog.js +++ b/chrome/browser/resources/print_preview/new/destination_dialog.js
@@ -405,6 +405,8 @@ /** @private */ onOpenSettingsPrintPage_: function() { + this.metrics_.record( + print_preview.Metrics.DestinationSearchBucket.MANAGE_BUTTON_CLICKED); print_preview.NativeLayer.getInstance().openSettingsPrintPage(); }, });
diff --git a/chrome/browser/resources/quota_internals/event_handler.js b/chrome/browser/resources/quota_internals/event_handler.js index 98c89c5..9fd9c8a 100644 --- a/chrome/browser/resources/quota_internals/event_handler.js +++ b/chrome/browser/resources/quota_internals/event_handler.js
@@ -260,12 +260,9 @@ * Event Handler for |cr.quota.onAvailableSpaceUpdated|. * |event.detail| contains |availableSpace|. * |availableSpace| represents total available disk space. - * @param {CustomEvent} event AvailableSpaceUpdated event. + * @param {!CustomEvent<string>} event AvailableSpaceUpdated event. */ function handleAvailableSpace(event) { - /** - * @type {string} - */ availableSpace = event.detail; $('diskspace-entry').innerHTML = numBytesToText_(availableSpace); } @@ -284,17 +281,14 @@ * * |usage|, |unlimitedUsage| and |quota| can be missing, * and some additional fields can be included. - * @param {CustomEvent} event GlobalInfoUpdated event. + * @param {!CustomEvent<!{ + * type: string, + * usage: ?number, + * unlimitedUsage: ?number, + * quota: ?string + * }>} event GlobalInfoUpdated event. */ function handleGlobalInfo(event) { - /** - * @type {{ - * type: {!string}, - * usage: {?number}, - * unlimitedUsage: {?number} - * quota: {?string} - * }} - */ const data = event.detail; const storageObject = getStorageObject(data.type); copyAttributes_(data, storageObject.detail.payload); @@ -318,17 +312,14 @@ * * |usage| and |quota| can be missing, * and some additional fields can be included. - * @param {CustomEvent} event PerHostInfoUpdated event. + * @param {!CustomEvent<!Array<{ + * host: string, + * type: string, + * usage: ?number, + * quota: ?number + * }>>} event PerHostInfoUpdated event. */ function handlePerHostInfo(event) { - /** - * @type {Array<{ - * host: {!string}, - * type: {!string}, - * usage: {?number}, - * quota: {?number} - * }} - */ const dataArray = event.detail; for (let i = 0; i < dataArray.length; ++i) { @@ -364,20 +355,17 @@ * * |inUse|, |usedCount|, |lastAccessTime| and |lastModifiedTime| can be missing, * and some additional fields can be included. - * @param {CustomEvent} event PerOriginInfoUpdated event. + * @param {!CustomEvent<!Array<!{ + * origin: string, + * type: string, + * host: string, + * inUse: ?boolean, + * usedCount: ?number, + * lastAccessTime: ?number, + * lastModifiedTime: ?number + * }>>} event PerOriginInfoUpdated event. */ function handlePerOriginInfo(event) { - /** - * @type {Array<{ - * origin: {!string}, - * type: {!string}, - * host: {!string}, - * inUse: {?boolean}, - * usedCount: {?number}, - * lastAccessTime: {?number} - * lastModifiedTime: {?number} - * }>} - */ const dataArray = event.detail; for (let i = 0; i < dataArray.length; ++i) { @@ -394,12 +382,9 @@ /** * Event Handler for |cr.quota.onStatisticsUpdated|. * |event.detail| contains misc statistics data as dictionary. - * @param {CustomEvent} event StatisticsUpdated event. + * @param {!CustomEvent<!Object>} event StatisticsUpdated event. */ function handleStatistics(event) { - /** - * @type {Object<string>} - */ const data = event.detail; for (const key in data) { let entry = statistics[key];
diff --git a/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chrome/browser/resources/safe_browsing/download_file_types.asciipb index e82e6166..0d36080 100644 --- a/chrome/browser/resources/safe_browsing/download_file_types.asciipb +++ b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
@@ -8,7 +8,7 @@ ## ## Top level settings ## -version_id: 27 +version_id: 28 sampled_ping_probability: 0.01 max_archived_binaries_to_report: 10 default_file_type { @@ -24,7 +24,8 @@ ## General cross-platform file types ## -# Files that are not dangerous but for which we want to track via UMA. +# Files that are not dangerous, and are popular enough that we'd like to +# exclude them from download pings. file_types { extension: "bin" uma_value: 159 @@ -41,6 +42,106 @@ uma_value: 244 ping_setting: SAMPLED_PING } +file_types { + extension: "jpg" + uma_value: 322 + ping_setting: SAMPLED_PING +} +file_types { + extension: "jpeg" + uma_value: 323 + ping_setting: SAMPLED_PING +} +file_types { + extension: "mp3" + uma_value: 324 + ping_setting: SAMPLED_PING +} +file_types { + extension: "mp4" + uma_value: 325 + ping_setting: SAMPLED_PING +} +file_types { + extension: "png" + uma_value: 326 + ping_setting: SAMPLED_PING +} +file_types { + extension: "xls" + uma_value: 327 + ping_setting: SAMPLED_PING +} +file_types { + extension: "doc" + uma_value: 328 + ping_setting: SAMPLED_PING +} +file_types { + extension: "pptx" + uma_value: 329 + ping_setting: SAMPLED_PING +} +file_types { + extension: "csv" + uma_value: 330 + ping_setting: SAMPLED_PING +} +file_types { + extension: "ica" + uma_value: 331 + ping_setting: SAMPLED_PING +} +file_types { + extension: "ppt" + uma_value: 332 + ping_setting: SAMPLED_PING +} +file_types { + extension: "gif" + uma_value: 333 + ping_setting: SAMPLED_PING +} +file_types { + extension: "txt" + uma_value: 334 + ping_setting: SAMPLED_PING +} +file_types { + extension: "package" + uma_value: 335 + ping_setting: SAMPLED_PING +} +file_types { + extension: "tif" + uma_value: 336 + ping_setting: SAMPLED_PING +} +file_types { + extension: "rtf" + uma_value: 337 + ping_setting: SAMPLED_PING +} +file_types { + extension: "webp" + uma_value: 338 + ping_setting: SAMPLED_PING +} +file_types { + extension: "mkv" + uma_value: 339 + ping_setting: SAMPLED_PING +} +file_types { + extension: "wav" + uma_value: 340 + ping_setting: SAMPLED_PING +} +file_types { + extension: "mov" + uma_value: 341 + ping_setting: SAMPLED_PING +} # Flash files downloaded locally can sometimes access the local filesystem file_types {
diff --git a/chrome/browser/resources/settings/device_page/display.js b/chrome/browser/resources/settings/device_page/display.js index c1881cb5..7528b6f7 100644 --- a/chrome/browser/resources/settings/device_page/display.js +++ b/chrome/browser/resources/settings/device_page/display.js
@@ -136,14 +136,6 @@ }, /** @private */ - multiMirroringAvailable_: { - type: Boolean, - value: function() { - return loadTimeData.getBoolean('multiMirroringAvailable'); - } - }, - - /** @private */ unifiedDesktopMode_: { type: Boolean, value: false, @@ -576,9 +568,7 @@ } return this.isMirrored_(displays) || - (!unifiedDesktopMode && - ((this.multiMirroringAvailable_ && displays.length > 1) || - displays.length == 2)); + (!unifiedDesktopMode && displays.length > 1); }, /**
diff --git a/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html b/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html index c40e950..fda8a287d 100644 --- a/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html +++ b/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
@@ -39,6 +39,10 @@ #messageDiv[invisible] { visibility: hidden; } + + #closeButton { + margin-inline-start: 5px; + } </style> <cr-dialog id="dialog" on-close="close"
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index af69a2e..d4cd336 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -3,6 +3,7 @@ <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html"> <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.html"> @@ -334,6 +335,24 @@ </template> <if expr="not chromeos"> + <template is="dom-if" if="[[showSetupCancelDialog_]]" restamp> + <cr-dialog id="setupCancelDialog" on-close="onSetupCancelDialogClose_" + ignore-popstate> + <div slot="title">$i18n{syncSetupCancelDialogTitle}</div> + <div slot="body">$i18n{syncSetupCancelDialogBody}</div> + <div slot="button-container"> + <paper-button class="cancel-button" + on-click="onSetupCancelDialogBack_"> + $i18n{back} + </paper-button> + <paper-button class="action-button" + on-click="onSetupCancelDialogConfirm_"> + $i18n{cancelSync} + </paper-button> + </div> + </cr-dialog> + </template> + <template is="dom-if" if="[[!unifiedConsentEnabled]]"> <cr-toast id="toast" open="[[syncStatus.setupInProgress]]"> <div>$i18n{syncWillStart}</div>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js index e7377df..b102f70 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.js +++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -141,6 +141,12 @@ type: Boolean, observer: 'initializeDidAbort_', }, + + /** @private */ + showSetupCancelDialog_: { + type: Boolean, + value: false, + }, }, /** @private {?settings.SyncBrowserProxy} */ @@ -172,6 +178,12 @@ */ didAbort_: false, + /** + * Whether the user clicked the confirm button on the "Cancel sync?" dialog. + * @private {boolean} + */ + setupCancelDialogConfirmed_: false, + /** @override */ created: function() { this.browserProxy_ = settings.SyncBrowserProxyImpl.getInstance(); @@ -229,12 +241,42 @@ return this.syncStatus != undefined && !!this.syncStatus.managed; }, + /** @private */ + onSetupCancelDialogBack_: function() { + this.$$('#setupCancelDialog').cancel(); + }, + + /** @private */ + onSetupCancelDialogConfirm_: function() { + this.setupCancelDialogConfirmed_ = true; + this.$$('#setupCancelDialog').close(); + settings.navigateTo(settings.routes.BASIC); + }, + + /** @private */ + onSetupCancelDialogClose_: function() { + this.showSetupCancelDialog_ = false; + }, + /** @protected */ currentRouteChanged: function() { if (settings.getCurrentRoute() == settings.routes.SYNC) { this.onNavigateToPage_(); } else if (!settings.routes.SYNC.contains(settings.getCurrentRoute())) { - this.onNavigateAwayFromPage_(); + // When the user wants to cancel the sync setup, but hasn't confirmed + // the cancel dialog, navigate back and show the dialog. + if (this.unifiedConsentEnabled && this.syncStatus && + !!this.syncStatus.setupInProgress && this.didAbort_ && + !this.setupCancelDialogConfirmed_) { + settings.navigateTo(settings.routes.SYNC); + this.showSetupCancelDialog_ = true; + // Flush to make sure that the setup cancel dialog is attached. + Polymer.dom.flush(); + this.$$('#setupCancelDialog').showModal(); + } else { + this.setupCancelDialogConfirmed_ = false; + this.onNavigateAwayFromPage_(); + } } }, @@ -540,7 +582,10 @@ !this.unifiedConsentEnabled; }, - /** @private */ + /** + * Used when unified consent is disabled. + * @private + */ onSyncSetupCancel_: function() { this.didAbort_ = true; settings.navigateTo(settings.routes.BASIC);
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_page.js b/chrome/browser/resources/settings/search_engines_page/search_engines_page.js index b840321..84e5d33b 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engines_page.js +++ b/chrome/browser/resources/settings/search_engines_page/search_engines_page.js
@@ -128,14 +128,14 @@ }, /** - * @param {!CustomEvent} e + * @param {!CustomEvent<!{ + * engine: !SearchEngine, + * anchorElement: !HTMLElement + * }>} e * @private */ onEditSearchEngine_: function(e) { - const params = - /** @type {!{engine: !SearchEngine, anchorElement: !HTMLElement}} */ ( - e.detail); - this.openDialog_(params.engine, params.anchorElement); + this.openDialog_(e.detail.engine, e.detail.anchorElement); }, /** @private */
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.js b/chrome/browser/resources/settings/settings_main/settings_main.js index a3d68c29..da38cb80 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.js +++ b/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -153,7 +153,7 @@ * A handler for the 'showing-section' event fired from settings-basic-page, * indicating that a section should be scrolled into view as a result of a * navigation. - * @param {!CustomEvent} e + * @param {!CustomEvent<!HTMLElement>} e * @private */ onShowingSection_: function(e) {
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn index 4126eaa..a0264f5 100644 --- a/chrome/browser/safe_browsing/BUILD.gn +++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -281,11 +281,13 @@ ] deps = [ + "//components/keyed_service/content", "//components/prefs:prefs", "//components/safe_browsing/common:common", "//components/safe_browsing/common:safe_browsing_prefs", "//components/signin/core/browser:browser", "//content/public/browser:browser", + "//services/identity/public/cpp", ] } @@ -299,6 +301,10 @@ deps = [ ":safe_browsing", "//chrome/common/safe_browsing:proto", + "//components/safe_browsing/db:database_manager", + "//components/safe_browsing/db:test_database_manager", + "//components/safe_browsing/db:v4_feature_list", + "//components/safe_browsing/db:v4_protocol_manager_util", "//content/public/browser:browser", ] }
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc index 85da0e38..c99f1ede 100644 --- a/chrome/browser/search/instant_service.cc +++ b/chrome/browser/search/instant_service.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/files/file_util.h" #include "base/path_service.h" +#include "base/scoped_observer.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" @@ -49,6 +50,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/url_data_source.h" #include "ui/gfx/color_utils.h" +#include "ui/native_theme/native_theme_observer.h" namespace { @@ -145,6 +147,48 @@ base::RepeatingCallback<void(bool)> callback_; }; +// Keeps track of any changes to system dark mode and notifies InstantService if +// dark mode has been changed. Use this to check if dark mode is enabled. +class InstantService::DarkModeHandler : public ui::NativeThemeObserver { + public: + explicit DarkModeHandler(ui::NativeTheme* theme, + base::RepeatingCallback<void(bool)> callback) + : theme_(theme), callback_(std::move(callback)), observer_(this) { + using_dark_mode_ = IsDarkModeEnabled(); + observer_.Add(theme_); + } + + bool IsDarkModeEnabled() { return theme_->SystemDarkModeEnabled(); } + + void SetThemeForTesting(ui::NativeTheme* theme) { + observer_.RemoveAll(); + + theme_ = theme; + using_dark_mode_ = IsDarkModeEnabled(); + observer_.Add(theme_); + } + + private: + // ui::NativeThemeObserver: + void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override { + DCHECK_EQ(observed_theme, theme_); + + bool using_dark_mode = IsDarkModeEnabled(); + if (using_dark_mode == using_dark_mode_) + return; + + using_dark_mode_ = using_dark_mode; + callback_.Run(using_dark_mode_); + } + + // The theme to query/watch for changes. + ui::NativeTheme* theme_; + // Whether or not the theme is using dark mode. + bool using_dark_mode_; + base::RepeatingCallback<void(bool)> callback_; + ScopedObserver<ui::NativeTheme, DarkModeHandler> observer_; +}; + InstantService::InstantService(Profile* profile) : profile_(profile), pref_service_(profile_->GetPrefs()), @@ -198,6 +242,11 @@ } } + dark_mode_handler_ = std::make_unique<DarkModeHandler>( + ui::NativeTheme::GetInstanceForNativeUi(), + base::BindRepeating(&InstantService::OnDarkModeChanged, + weak_ptr_factory_.GetWeakPtr())); + background_service_ = NtpBackgroundServiceFactory::GetForProfile(profile_); // Listen for theme installation. @@ -400,6 +449,11 @@ weak_ptr_factory_.GetWeakPtr())); } +void InstantService::SetDarkModeThemeForTesting(ui::NativeTheme* theme) { + if (dark_mode_handler_) + dark_mode_handler_->SetThemeForTesting(theme); +} + void InstantService::Shutdown() { process_ids_.clear(); @@ -464,6 +518,12 @@ most_visited_sites_->EnableCustomLinks(is_google); } +void InstantService::OnDarkModeChanged(bool dark_mode) { + if (theme_info_) + theme_info_->using_dark_mode = dark_mode; + UpdateThemeInfo(); +} + void InstantService::OnURLsAvailable( const std::map<ntp_tiles::SectionType, ntp_tiles::NTPTilesVector>& sections) { @@ -525,6 +585,8 @@ theme_info_->using_default_theme = theme_service->UsingDefaultTheme() || theme_service->UsingSystemTheme(); + theme_info_->using_dark_mode = dark_mode_handler_->IsDarkModeEnabled(); + // Get theme colors. const ui::ThemeProvider& theme_provider = ThemeService::GetThemeProviderForProfile(profile_);
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h index 4c5b1226..0db2b10 100644 --- a/chrome/browser/search/instant_service.h +++ b/chrome/browser/search/instant_service.h
@@ -25,6 +25,7 @@ #include "components/prefs/pref_registry_simple.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "ui/native_theme/native_theme.h" #include "url/gurl.h" #if defined(OS_ANDROID) @@ -135,6 +136,10 @@ // Used for testing. ThemeBackgroundInfo* GetThemeInfoForTesting() { return theme_info_.get(); } + // Used for testing. + void SetDarkModeThemeForTesting(ui::NativeTheme* theme); + + // Used for testing. void AddValidBackdropUrlForTesting(const GURL& url) const; // Check if a custom background has been set by the user. @@ -143,6 +148,8 @@ private: class SearchProviderObserver; + class DarkModeHandler; + friend class InstantExtendedTest; friend class InstantUnitTestBase; @@ -165,6 +172,10 @@ // search provider is not Google. void OnSearchProviderChanged(bool is_google); + // Called when dark mode changes. Updates current theme info as necessary and + // notifies that the theme has changed. + void OnDarkModeChanged(bool dark_mode); + // ntp_tiles::MostVisitedSites::Observer implementation. void OnURLsAvailable( const std::map<ntp_tiles::SectionType, ntp_tiles::NTPTilesVector>& @@ -225,6 +236,9 @@ // Keeps track of any changes in search engine provider. May be null. std::unique_ptr<SearchProviderObserver> search_provider_observer_; + // Keeps track of any changes to system dark mode. + std::unique_ptr<DarkModeHandler> dark_mode_handler_; + PrefChangeRegistrar pref_change_registrar_; PrefService* pref_service_;
diff --git a/chrome/browser/search/instant_service_unittest.cc b/chrome/browser/search/instant_service_unittest.cc index a6435c2..a867712 100644 --- a/chrome/browser/search/instant_service_unittest.cc +++ b/chrome/browser/search/instant_service_unittest.cc
@@ -22,6 +22,7 @@ #include "components/ntp_tiles/section_type.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/native_theme/test_native_theme.h" #include "url/gurl.h" namespace { @@ -416,3 +417,38 @@ EXPECT_EQ(GURL(), theme_info->custom_background_url); EXPECT_FALSE(instant_service_->IsCustomBackgroundSet()); } + +class InstantServiceThemeTest : public InstantServiceTest { + public: + InstantServiceThemeTest() {} + ~InstantServiceThemeTest() override {} + + ui::TestNativeTheme* theme() { return &theme_; } + + private: + ui::TestNativeTheme theme_; + + DISALLOW_COPY_AND_ASSIGN(InstantServiceThemeTest); +}; + +TEST_F(InstantServiceThemeTest, DarkModeHandler) { + theme()->SetDarkMode(false); + instant_service_->SetDarkModeThemeForTesting(theme()); + thread_bundle()->RunUntilIdle(); + + // Enable dark mode. + theme()->SetDarkMode(true); + theme()->NotifyObservers(); + thread_bundle()->RunUntilIdle(); + + ThemeBackgroundInfo* theme_info = instant_service_->GetThemeInfoForTesting(); + EXPECT_TRUE(theme_info->using_dark_mode); + + // Disable dark mode. + theme()->SetDarkMode(false); + theme()->NotifyObservers(); + thread_bundle()->RunUntilIdle(); + + theme_info = instant_service_->GetThemeInfoForTesting(); + EXPECT_FALSE(theme_info->using_dark_mode); +}
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index 2a102fe..b06a19c 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -73,10 +73,7 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" -#include "ui/base/ui_base_switches.h" #include "ui/base/webui/web_ui_util.h" -#include "ui/native_theme/native_theme.h" #include "ui/resources/grit/ui_resources.h" #include "url/gurl.h" @@ -591,9 +588,6 @@ config_data.SetBoolean("isAccessibleBrowser", content::BrowserAccessibilityState::GetInstance() ->IsAccessibleBrowser()); - config_data.SetBoolean( - "isDarkModeEnabled", - ui::NativeTheme::GetInstanceForNativeUi()->SystemDarkModeEnabled()); // Serialize the dictionary. std::string js_text;
diff --git a/chrome/browser/search/ntp_icon_source.cc b/chrome/browser/search/ntp_icon_source.cc index 4e07db92..d0db7807 100644 --- a/chrome/browser/search/ntp_icon_source.cc +++ b/chrome/browser/search/ntp_icon_source.cc
@@ -61,6 +61,9 @@ // Delimiter in the url that looks for the size specification. const char kSizeParameter[] = "size/"; +// Delimiter in the url for dark mode specification. +const char kDarkModeParameter[] = "dark/"; + // Size of the icon background (gray circle), in dp. const int kIconSizeDip = 48; @@ -128,6 +131,15 @@ parsed_index = slash + 1; + // Parse the dark mode spec (e.g. "dark"), if available. The value is not + // used, but is required to generate a new icon for dark mode. + if (HasSubstringAt(path, parsed_index, kDarkModeParameter)) { + slash = path.find("/", parsed_index); + if (slash == std::string::npos) + return parsed; + parsed_index = slash + 1; + } + parsed.url = GURL(path.substr(parsed_index)); return parsed; }
diff --git a/chrome/browser/search/search_suggest/search_suggest_loader.h b/chrome/browser/search/search_suggest/search_suggest_loader.h index 7a041ee..8209726c 100644 --- a/chrome/browser/search/search_suggest/search_suggest_loader.h +++ b/chrome/browser/search/search_suggest/search_suggest_loader.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_SEARCH_SEARCH_SUGGEST_SEARCH_SUGGEST_LOADER_H_ #define CHROME_BROWSER_SEARCH_SEARCH_SUGGEST_SEARCH_SUGGEST_LOADER_H_ +#include <string> + #include "base/callback_forward.h" #include "base/optional.h" @@ -41,8 +43,8 @@ // Initiates a load from the network. On completion (successful or not), the // callback will be called with the result, which will be nullopt on failure. - // |blacklist| will be appended to the request as the url param 'vtgb'. - virtual void Load(const std::string& blacklist, + // |blocklist| will be appended to the request as the url param 'vtgb'. + virtual void Load(const std::string& blocklist, SearchSuggestionsCallback callback) = 0; // Retrieves the URL from which SearchSuggestData will be loaded.
diff --git a/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc b/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc index f0d04a9..8067939 100644 --- a/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc +++ b/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc
@@ -212,7 +212,7 @@ SearchSuggestLoaderImpl::~SearchSuggestLoaderImpl() = default; -void SearchSuggestLoaderImpl::Load(const std::string& blacklist, +void SearchSuggestLoaderImpl::Load(const std::string& blocklist, SearchSuggestionsCallback callback) { callbacks_.push_back(std::move(callback)); @@ -220,18 +220,18 @@ // something has changed in the meantime (e.g. signin state) that would make // the result obsolete. pending_request_ = std::make_unique<AuthenticatedURLLoader>( - url_loader_factory_, GetApiUrl(blacklist), + url_loader_factory_, GetApiUrl(blocklist), base::BindOnce(&SearchSuggestLoaderImpl::LoadDone, base::Unretained(this))); pending_request_->Start(); } GURL SearchSuggestLoaderImpl::GetLoadURLForTesting() const { - std::string blacklist; - return GetApiUrl(blacklist); + std::string blocklist; + return GetApiUrl(blocklist); } -GURL SearchSuggestLoaderImpl::GetApiUrl(const std::string& blacklist) const { +GURL SearchSuggestLoaderImpl::GetApiUrl(const std::string& blocklist) const { GURL google_base_url = google_util::CommandLineGoogleBaseURL(); if (!google_base_url.is_valid()) { google_base_url = google_url_tracker_->google_url(); @@ -239,7 +239,7 @@ GURL api_url = google_base_url.Resolve(kNewTabSearchSuggestionsApiPath); - api_url = net::AppendQueryParameter(api_url, "vtgb", blacklist); + api_url = net::AppendQueryParameter(api_url, "vtgb", blocklist); return api_url; }
diff --git a/chrome/browser/search/search_suggest/search_suggest_loader_impl.h b/chrome/browser/search/search_suggest/search_suggest_loader_impl.h index b529650..cd9d5d0d 100644 --- a/chrome/browser/search/search_suggest/search_suggest_loader_impl.h +++ b/chrome/browser/search/search_suggest/search_suggest_loader_impl.h
@@ -35,7 +35,7 @@ const std::string& application_locale); ~SearchSuggestLoaderImpl() override; - void Load(const std::string& blacklist, + void Load(const std::string& blocklist, SearchSuggestionsCallback callback) override; GURL GetLoadURLForTesting() const override; @@ -43,7 +43,7 @@ private: class AuthenticatedURLLoader; - GURL GetApiUrl(const std::string& blacklist) const; + GURL GetApiUrl(const std::string& blocklist) const; void LoadDone(const network::SimpleURLLoader* simple_loader, std::unique_ptr<std::string> response_body);
diff --git a/chrome/browser/search/search_suggest/search_suggest_loader_impl_unittest.cc b/chrome/browser/search/search_suggest/search_suggest_loader_impl_unittest.cc index 50541cc..f5b5b20 100644 --- a/chrome/browser/search/search_suggest/search_suggest_loader_impl_unittest.cc +++ b/chrome/browser/search/search_suggest/search_suggest_loader_impl_unittest.cc
@@ -141,8 +141,8 @@ SetUpResponseWithData(kMinimalValidResponse); base::MockCallback<SearchSuggestLoader::SearchSuggestionsCallback> callback; - std::string blacklist; - search_suggest_loader()->Load(blacklist, callback.Get()); + std::string blocklist; + search_suggest_loader()->Load(blocklist, callback.Get()); base::Optional<SearchSuggestData> data; base::RunLoop loop; @@ -159,8 +159,8 @@ SetUpResponseWithData(std::string(")]}'") + kMinimalValidResponse); base::MockCallback<SearchSuggestLoader::SearchSuggestionsCallback> callback; - std::string blacklist; - search_suggest_loader()->Load(blacklist, callback.Get()); + std::string blocklist; + search_suggest_loader()->Load(blocklist, callback.Get()); base::Optional<SearchSuggestData> data; base::RunLoop loop; @@ -179,8 +179,8 @@ }}})json"); base::MockCallback<SearchSuggestLoader::SearchSuggestionsCallback> callback; - std::string blacklist; - search_suggest_loader()->Load(blacklist, callback.Get()); + std::string blocklist; + search_suggest_loader()->Load(blocklist, callback.Get()); base::Optional<SearchSuggestData> data; base::RunLoop loop; @@ -202,11 +202,11 @@ // Trigger two requests. base::MockCallback<SearchSuggestLoader::SearchSuggestionsCallback> first_callback; - std::string blacklist; - search_suggest_loader()->Load(blacklist, first_callback.Get()); + std::string blocklist; + search_suggest_loader()->Load(blocklist, first_callback.Get()); base::MockCallback<SearchSuggestLoader::SearchSuggestionsCallback> second_callback; - search_suggest_loader()->Load(blacklist, second_callback.Get()); + search_suggest_loader()->Load(blocklist, second_callback.Get()); // Make sure that a single response causes both callbacks to be called. base::Optional<SearchSuggestData> first_data; @@ -228,8 +228,8 @@ SetUpResponseWithNetworkError(); base::MockCallback<SearchSuggestLoader::SearchSuggestionsCallback> callback; - std::string blacklist; - search_suggest_loader()->Load(blacklist, callback.Get()); + std::string blocklist; + search_suggest_loader()->Load(blocklist, callback.Get()); base::RunLoop loop; EXPECT_CALL(callback, Run(SearchSuggestLoader::Status::TRANSIENT_ERROR, @@ -243,8 +243,8 @@ SetUpResponseWithData(kMinimalValidResponse + std::string(")")); base::MockCallback<SearchSuggestLoader::SearchSuggestionsCallback> callback; - std::string blacklist; - search_suggest_loader()->Load(blacklist, callback.Get()); + std::string blocklist; + search_suggest_loader()->Load(blocklist, callback.Get()); base::RunLoop loop; EXPECT_CALL(callback, @@ -257,8 +257,8 @@ SetUpResponseWithData(R"json({"update": {}})json"); base::MockCallback<SearchSuggestLoader::SearchSuggestionsCallback> callback; - std::string blacklist; - search_suggest_loader()->Load(blacklist, callback.Get()); + std::string blocklist; + search_suggest_loader()->Load(blocklist, callback.Get()); base::RunLoop loop; EXPECT_CALL(callback,
diff --git a/chrome/browser/search/search_suggest/search_suggest_service.cc b/chrome/browser/search/search_suggest/search_suggest_service.cc index 731cf981..c2e2dae 100644 --- a/chrome/browser/search/search_suggest/search_suggest_service.cc +++ b/chrome/browser/search/search_suggest/search_suggest_service.cc
@@ -8,13 +8,31 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/strings/string_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search/search.h" #include "chrome/browser/search/search_suggest/search_suggest_loader.h" #include "chrome/common/pref_names.h" #include "components/prefs/scoped_user_pref_update.h" #include "services/identity/public/cpp/identity_manager.h" +#include "third_party/re2/src/re2/re2.h" namespace { +constexpr char kSuggestionHashRegex[] = "[a-z0-9]{1,4}"; + +std::string* ValidateHash(const uint8_t hash[4]) { + const std::string hash_string = reinterpret_cast<const char*>(hash); + + std::string* trimmed_string = new std::string(""); + // The uint8_t array received via IPC ends in an EOT byte (\4), remove it. + base::TrimString(hash_string, "\4", trimmed_string); + + if (!re2::RE2::FullMatch(*trimmed_string, kSuggestionHashRegex)) + return nullptr; + return trimmed_string; +} + const char kFirstShownTimeMs[] = "first_shown_time_ms"; const char kImpressionCapExpireTimeMs[] = "impression_cap_expire_time_ms"; const char kImpressionsCount[] = "impressions_count"; @@ -72,7 +90,7 @@ }; SearchSuggestService::SearchSuggestService( - PrefService* pref_service, + Profile* profile, identity::IdentityManager* identity_manager, std::unique_ptr<SearchSuggestLoader> loader) : loader_(std::move(loader)), @@ -80,7 +98,7 @@ identity_manager, base::BindRepeating(&SearchSuggestService::SigninStatusChanged, base::Unretained(this)))), - pref_service_(pref_service) {} + profile_(profile) {} SearchSuggestService::~SearchSuggestService() = default; @@ -94,10 +112,17 @@ } void SearchSuggestService::Refresh() { + const std::string blocklist = GetBlocklistAsString(); + MaybeLoadWithBlocklist(blocklist); +} + +void SearchSuggestService::MaybeLoadWithBlocklist( + const std::string& blocklist) { if (!signin_observer_->SignedIn()) { SearchSuggestDataLoaded(SearchSuggestLoader::Status::SIGNED_OUT, base::nullopt); - } else if (pref_service_->GetBoolean(prefs::kNtpSearchSuggestionsOptOut)) { + } else if (profile_->GetPrefs()->GetBoolean( + prefs::kNtpSearchSuggestionsOptOut)) { SearchSuggestDataLoaded(SearchSuggestLoader::Status::OPTED_OUT, base::nullopt); } else if (RequestsFrozen()) { @@ -107,8 +132,7 @@ SearchSuggestDataLoaded(SearchSuggestLoader::Status::IMPRESSION_CAP, base::nullopt); } else { - const std::string blacklist = GetBlacklistAsString(); - loader_->Load(blacklist, + loader_->Load(blocklist, base::BindOnce(&SearchSuggestService::SearchSuggestDataLoaded, base::Unretained(this))); } @@ -139,7 +163,7 @@ search_suggest_data_ = data; search_suggest_status_ = status; - DictionaryPrefUpdate update(pref_service_, + DictionaryPrefUpdate update(profile_->GetPrefs(), prefs::kNtpSearchSuggestionsImpressions); if (data.has_value()) { @@ -164,8 +188,8 @@ } bool SearchSuggestService::ImpressionCapReached() { - const base::DictionaryValue* dict = - pref_service_->GetDictionary(prefs::kNtpSearchSuggestionsImpressions); + const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary( + prefs::kNtpSearchSuggestionsImpressions); int first_shown_time_ms = 0; int impression_cap_expire_time_ms = 0; @@ -182,7 +206,7 @@ .InMilliseconds(); if (time_delta > impression_cap_expire_time_ms) { impression_count = 0; - DictionaryPrefUpdate update(pref_service_, + DictionaryPrefUpdate update(profile_->GetPrefs(), prefs::kNtpSearchSuggestionsImpressions); update.Get()->SetInteger(kImpressionsCount, impression_count); } @@ -191,8 +215,8 @@ } bool SearchSuggestService::RequestsFrozen() { - const base::DictionaryValue* dict = - pref_service_->GetDictionary(prefs::kNtpSearchSuggestionsImpressions); + const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary( + prefs::kNtpSearchSuggestionsImpressions); bool is_request_frozen = false; int request_freeze_time_ms = 0; @@ -209,7 +233,7 @@ if (time_delta < request_freeze_time_ms) { return true; } else { - DictionaryPrefUpdate update(pref_service_, + DictionaryPrefUpdate update(profile_->GetPrefs(), prefs::kNtpSearchSuggestionsImpressions); update.Get()->SetBoolean(kIsRequestFrozen, false); } @@ -218,46 +242,79 @@ return false; } -void SearchSuggestService::BlacklistSearchSuggestion(int task_version, +void SearchSuggestService::BlocklistSearchSuggestion(int task_version, long task_id) { + if (!search::DefaultSearchProviderIsGoogle(profile_)) + return; + std::string task_version_id = std::to_string(task_version) + "_" + std::to_string(task_id); - DictionaryPrefUpdate update(pref_service_, - prefs::kNtpSearchSuggestionsBlacklist); - base::DictionaryValue* blacklist = update.Get(); - blacklist->SetKey(task_version_id, base::ListValue()); + DictionaryPrefUpdate update(profile_->GetPrefs(), + prefs::kNtpSearchSuggestionsBlocklist); + base::DictionaryValue* blocklist = update.Get(); + blocklist->SetKey(task_version_id, base::ListValue()); search_suggest_data_ = base::nullopt; Refresh(); } -void SearchSuggestService::BlacklistSearchSuggestionWithHash( +void SearchSuggestService::BlocklistSearchSuggestionWithHash( int task_version, long task_id, - const std::vector<uint8_t>& hash) { + const uint8_t hash[4]) { + if (!search::DefaultSearchProviderIsGoogle(profile_)) + return; + + std::string* hash_string = ValidateHash(hash); + + if (!hash_string) + return; + std::string task_version_id = std::to_string(task_version) + "_" + std::to_string(task_id); - std::string hash_string; - hash_string.assign(hash.begin(), hash.end()); - DictionaryPrefUpdate update(pref_service_, - prefs::kNtpSearchSuggestionsBlacklist); - base::DictionaryValue* blacklist = update.Get(); - base::Value* value = blacklist->FindKey(task_version_id); + + DictionaryPrefUpdate update(profile_->GetPrefs(), + prefs::kNtpSearchSuggestionsBlocklist); + base::DictionaryValue* blocklist = update.Get(); + base::Value* value = blocklist->FindKey(task_version_id); if (!value) - value = blacklist->SetKey(task_version_id, base::ListValue()); - value->GetList().emplace_back(base::Value(hash_string)); + value = blocklist->SetKey(task_version_id, base::ListValue()); + value->GetList().emplace_back(base::Value(*hash_string)); search_suggest_data_ = base::nullopt; Refresh(); } -std::string SearchSuggestService::GetBlacklistAsString() { - const base::DictionaryValue* blacklist = - pref_service_->GetDictionary(prefs::kNtpSearchSuggestionsBlacklist); +void SearchSuggestService::SearchSuggestionSelected(int task_version, + long task_id, + const uint8_t hash[4]) { + if (!search::DefaultSearchProviderIsGoogle(profile_)) + return; - std::string blacklist_as_string; - for (const auto& dict : blacklist->DictItems()) { - blacklist_as_string += dict.first; + std::string* hash_string = ValidateHash(hash); + + if (!hash_string) + return; + + std::string blocklist_item = std::to_string(task_version) + "_" + + std::to_string(task_id) + ":" + *hash_string; + + std::string blocklist = GetBlocklistAsString(); + if (!blocklist.empty()) + blocklist += ";"; + blocklist += blocklist_item; + + search_suggest_data_ = base::nullopt; + MaybeLoadWithBlocklist(blocklist); +} + +std::string SearchSuggestService::GetBlocklistAsString() { + const base::DictionaryValue* blocklist = profile_->GetPrefs()->GetDictionary( + prefs::kNtpSearchSuggestionsBlocklist); + + std::string blocklist_as_string; + for (const auto& dict : blocklist->DictItems()) { + blocklist_as_string += dict.first; if (!dict.second.GetList().empty()) { std::string list = ":"; @@ -268,22 +325,22 @@ // Remove trailing comma. list.pop_back(); - blacklist_as_string += list; + blocklist_as_string += list; } - blacklist_as_string += ";"; + blocklist_as_string += ";"; } // Remove trailing semi-colon. - if (!blacklist_as_string.empty()) - blacklist_as_string.pop_back(); - return blacklist_as_string; + if (!blocklist_as_string.empty()) + blocklist_as_string.pop_back(); + return blocklist_as_string; } void SearchSuggestService::SuggestionsDisplayed() { search_suggest_data_ = base::nullopt; - DictionaryPrefUpdate update(pref_service_, + DictionaryPrefUpdate update(profile_->GetPrefs(), prefs::kNtpSearchSuggestionsImpressions); base::DictionaryValue* dict = update.Get(); @@ -298,14 +355,17 @@ } void SearchSuggestService::OptOutOfSearchSuggestions() { - pref_service_->SetBoolean(prefs::kNtpSearchSuggestionsOptOut, true); + if (!search::DefaultSearchProviderIsGoogle(profile_)) + return; + + profile_->GetPrefs()->SetBoolean(prefs::kNtpSearchSuggestionsOptOut, true); search_suggest_data_ = base::nullopt; } // static void SearchSuggestService::RegisterProfilePrefs(PrefRegistrySimple* registry) { - registry->RegisterDictionaryPref(prefs::kNtpSearchSuggestionsBlacklist); + registry->RegisterDictionaryPref(prefs::kNtpSearchSuggestionsBlocklist); registry->RegisterDictionaryPref(prefs::kNtpSearchSuggestionsImpressions, ImpressionDictDefaults()); registry->RegisterBooleanPref(prefs::kNtpSearchSuggestionsOptOut, false);
diff --git a/chrome/browser/search/search_suggest/search_suggest_service.h b/chrome/browser/search/search_suggest/search_suggest_service.h index ebb8c5b..513eb9d 100644 --- a/chrome/browser/search/search_suggest/search_suggest_service.h +++ b/chrome/browser/search/search_suggest/search_suggest_service.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_SEARCH_SEARCH_SUGGEST_SEARCH_SUGGEST_SERVICE_H_ #include <memory> +#include <string> #include "base/observer_list.h" #include "base/optional.h" @@ -16,6 +17,8 @@ #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" +class Profile; + namespace identity { class IdentityManager; } // namespace identity @@ -25,7 +28,7 @@ // user signs in or out, the cached value is cleared. class SearchSuggestService : public KeyedService { public: - SearchSuggestService(PrefService* pref_service, + SearchSuggestService(Profile* profile, identity::IdentityManager* identity_manager, std::unique_ptr<SearchSuggestLoader> loader); ~SearchSuggestService() override; @@ -57,13 +60,13 @@ // Register prefs associated with the NTP. static void RegisterProfilePrefs(PrefRegistrySimple* registry); - // Add the task_id to the blacklist stored in user prefs. Overrides any + // Add the task_id to the blocklist stored in user prefs. Overrides any // existing entry for the given task_id. // // A task_id represents a category of searches such as "Camping", a // task_version represents the selection criteria used to generate the // suggestion. - void BlacklistSearchSuggestion(int task_version, long task_id); + void BlocklistSearchSuggestion(int task_version, long task_id); // Add the hash to the list of hashes for the task_id. Stored as a // dict of task_ids to lists of hashes in user prefs. @@ -72,9 +75,17 @@ // is a specific search within the category such as "Camping equipment", and // a task_version represents the selection criteria used ti generate the // suggestion. - void BlacklistSearchSuggestionWithHash(int task_version, + void BlocklistSearchSuggestionWithHash(int task_version, long task_id, - const std::vector<uint8_t>& hash); + const uint8_t hash[4]); + + // Issue a new request with the selected suggestion appended to the blocklist + // but NOT stored in user prefs. This prevents a race condition where the + // request completes before the data server side is updated to reflect the + // selection, resulting in the same suggestion appearing in the next set. + void SearchSuggestionSelected(int task_version, + long task_id, + const uint8_t hash[4]); // Opt the current profile out of seeing search suggestions. Requests will // no longer be made. @@ -82,9 +93,9 @@ SearchSuggestLoader* loader_for_testing() { return loader_.get(); } - // Returns the string representation of the suggestions blacklist in the form: + // Returns the string representation of the suggestions blocklist in the form: // "task_id1:hash1,hash2,hash3;task_id2;task_id3:hash1,hash2". - std::string GetBlacklistAsString(); + std::string GetBlocklistAsString(); // Called when suggestions are displayed on the NTP, clears the cached data // and updates timestamps and impression counts. @@ -95,6 +106,10 @@ void SigninStatusChanged(); + // Either calls SearchSuggestLoader::Load with |blocklist| or immediately + // calls SearchSuggestDataLoaded with the reason a request was not made. + void MaybeLoadWithBlocklist(const std::string& blocklist); + // Called when a Refresh() is requested. If |status|==OK, |data| will contain // the fetched data. Otherwise |data| will be nullopt and |status| will // indicate if the request failed or the reason it was not sent. @@ -121,7 +136,7 @@ std::unique_ptr<SigninObserver> signin_observer_; - PrefService* pref_service_; + Profile* profile_; base::ObserverList<SearchSuggestServiceObserver, true>::Unchecked observers_;
diff --git a/chrome/browser/search/search_suggest/search_suggest_service_factory.cc b/chrome/browser/search/search_suggest/search_suggest_service_factory.cc index 0d854ba..131d0a8 100644 --- a/chrome/browser/search/search_suggest/search_suggest_service_factory.cc +++ b/chrome/browser/search/search_suggest/search_suggest_service_factory.cc
@@ -54,7 +54,6 @@ return nullptr; } Profile* profile = Profile::FromBrowserContext(context); - PrefService* pref_service = profile->GetPrefs(); identity::IdentityManager* identity_manager = IdentityManagerFactory::GetForProfile(profile); GoogleURLTracker* google_url_tracker = @@ -63,7 +62,7 @@ content::BrowserContext::GetDefaultStoragePartition(context) ->GetURLLoaderFactoryForBrowserProcess(); return new SearchSuggestService( - pref_service, identity_manager, + profile, identity_manager, std::make_unique<SearchSuggestLoaderImpl>( url_loader_factory, google_url_tracker, g_browser_process->GetApplicationLocale()));
diff --git a/chrome/browser/search/search_suggest/search_suggest_service_unittest.cc b/chrome/browser/search/search_suggest/search_suggest_service_unittest.cc index 22a1fc2..5e0f55c 100644 --- a/chrome/browser/search/search_suggest/search_suggest_service_unittest.cc +++ b/chrome/browser/search/search_suggest/search_suggest_service_unittest.cc
@@ -9,10 +9,15 @@ #include <vector> #include "base/optional.h" +#include "base/strings/utf_string_conversions.h" #include "base/test/scoped_task_environment.h" #include "chrome/browser/search/search_suggest/search_suggest_data.h" #include "chrome/browser/search/search_suggest/search_suggest_loader.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/common/pref_names.h" +#include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/search_test_utils.h" +#include "components/search_engines/template_url_service.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/test_signin_client.h" #include "components/sync_preferences/testing_pref_service_syncable.h" @@ -21,7 +26,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::Eq; using testing::InSequence; using testing::StrictMock; @@ -47,35 +51,63 @@ std::vector<SearchSuggestionsCallback> callbacks_; }; -class SearchSuggestServiceTest : public testing::Test { +class SearchSuggestServiceTest : public BrowserWithTestWindowTest { public: - SearchSuggestServiceTest() - : identity_env_(&test_url_loader_factory_, &pref_service_) { - SearchSuggestService::RegisterProfilePrefs(pref_service_.registry()); + SearchSuggestServiceTest() {} + ~SearchSuggestServiceTest() override {} + void SetUp() override { + BrowserWithTestWindowTest::SetUp(); + + TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( + profile(), + base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor)); + template_url_service_ = TemplateURLServiceFactory::GetForProfile(profile()); + search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service_); + + identity_env_ = std::make_unique<identity::IdentityTestEnvironment>( + &test_url_loader_factory_); auto loader = std::make_unique<FakeSearchSuggestLoader>(); loader_ = loader.get(); service_ = std::make_unique<SearchSuggestService>( - &pref_service_, identity_env_.identity_manager(), std::move(loader)); + profile(), identity_env_->identity_manager(), std::move(loader)); - identity_env_.MakePrimaryAccountAvailable("example@gmail.com"); - identity_env_.SetAutomaticIssueOfAccessTokens(true); + identity_env_->MakePrimaryAccountAvailable("example@gmail.com"); + identity_env_->SetAutomaticIssueOfAccessTokens(true); + } + + void TearDown() override { BrowserWithTestWindowTest::TearDown(); } + + TestingProfile* CreateProfile() override { + TestingProfile* profile = BrowserWithTestWindowTest::CreateProfile(); + return profile; } FakeSearchSuggestLoader* loader() { return loader_; } SearchSuggestService* service() { return service_.get(); } sync_preferences::TestingPrefServiceSyncable* pref_service() { - return &pref_service_; + return profile()->GetTestingPrefService(); } void SignIn() { AccountInfo account_info = - identity_env_.MakeAccountAvailable("test@email.com"); - identity_env_.SetCookieAccounts({{account_info.email, account_info.gaia}}); + identity_env_->MakeAccountAvailable("test@email.com"); + identity_env_->SetCookieAccounts({{account_info.email, account_info.gaia}}); } - void SignOut() { - identity_env_.SetCookieAccounts({}); + void SignOut() { identity_env_->SetCookieAccounts({}); } + + void SetUserSelectedDefaultSearchProvider(const std::string& base_url) { + TemplateURLData data; + data.SetShortName(base::UTF8ToUTF16(base_url)); + data.SetKeyword(base::UTF8ToUTF16(base_url)); + data.SetURL(base_url + "url?bar={searchTerms}"); + data.new_tab_url = base_url + "newtab"; + data.alternate_urls.push_back(base_url + "alt#quux={searchTerms}"); + + TemplateURL* template_url = + template_url_service_->Add(std::make_unique<TemplateURL>(data)); + template_url_service_->SetUserSelectedDefaultSearchProvider(template_url); } // Returns a default data object for testing, initializes the impression @@ -99,11 +131,9 @@ } private: - base::test::ScopedTaskEnvironment task_environment_; - - sync_preferences::TestingPrefServiceSyncable pref_service_; + TemplateURLService* template_url_service_; network::TestURLLoaderFactory test_url_loader_factory_; - identity::IdentityTestEnvironment identity_env_; + std::unique_ptr<identity::IdentityTestEnvironment> identity_env_; // Owned by the service. FakeSearchSuggestLoader* loader_; @@ -112,158 +142,241 @@ }; TEST_F(SearchSuggestServiceTest, NoRefreshOnSignedOutRequest) { - ASSERT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + ASSERT_EQ(base::nullopt, service()->search_suggest_data()); // Request a refresh. That should do nothing as no user is signed-in. service()->Refresh(); - EXPECT_THAT(loader()->GetCallbackCount(), Eq(0u)); - EXPECT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + EXPECT_EQ(0u, loader()->GetCallbackCount()); + EXPECT_EQ(base::nullopt, service()->search_suggest_data()); } TEST_F(SearchSuggestServiceTest, RefreshesOnSignedInRequest) { - ASSERT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + ASSERT_EQ(base::nullopt, service()->search_suggest_data()); SignIn(); // Request a refresh. That should arrive at the loader. service()->Refresh(); - EXPECT_THAT(loader()->GetCallbackCount(), Eq(1u)); + EXPECT_EQ(1u, loader()->GetCallbackCount()); // Fulfill it. SearchSuggestData data = TestSearchSuggestData(); loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, data); - EXPECT_THAT(service()->search_suggest_data(), Eq(data)); + EXPECT_EQ(data, service()->search_suggest_data()); // Request another refresh. service()->Refresh(); - EXPECT_THAT(loader()->GetCallbackCount(), Eq(1u)); + EXPECT_EQ(1u, loader()->GetCallbackCount()); // For now, the old data should still be there. - EXPECT_THAT(service()->search_suggest_data(), Eq(data)); + EXPECT_EQ(data, service()->search_suggest_data()); // Fulfill the second request. SearchSuggestData other_data = TestSearchSuggestData(); loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, other_data); - EXPECT_THAT(service()->search_suggest_data(), Eq(other_data)); + EXPECT_EQ(other_data, service()->search_suggest_data()); } TEST_F(SearchSuggestServiceTest, KeepsCacheOnTransientError) { - ASSERT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + ASSERT_EQ(base::nullopt, service()->search_suggest_data()); SignIn(); // Load some data. service()->Refresh(); SearchSuggestData data = TestSearchSuggestData(); loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, data); - ASSERT_THAT(service()->search_suggest_data(), Eq(data)); + ASSERT_EQ(data, service()->search_suggest_data()); // Request a refresh and respond with a transient error. service()->Refresh(); loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::TRANSIENT_ERROR, base::nullopt); // Cached data should still be there. - EXPECT_THAT(service()->search_suggest_data(), Eq(data)); + EXPECT_EQ(data, service()->search_suggest_data()); } TEST_F(SearchSuggestServiceTest, ClearsCacheOnFatalError) { - ASSERT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + ASSERT_EQ(base::nullopt, service()->search_suggest_data()); SignIn(); // Load some data. service()->Refresh(); SearchSuggestData data = TestSearchSuggestData(); loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, data); - ASSERT_THAT(service()->search_suggest_data(), Eq(data)); + ASSERT_EQ(data, service()->search_suggest_data()); // Request a refresh and respond with a fatal error. service()->Refresh(); loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::FATAL_ERROR, base::nullopt); // Cached data should be gone now. - EXPECT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + EXPECT_EQ(base::nullopt, service()->search_suggest_data()); } TEST_F(SearchSuggestServiceTest, ResetsOnSignOut) { - ASSERT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + ASSERT_EQ(base::nullopt, service()->search_suggest_data()); SignIn(); // Load some data. service()->Refresh(); SearchSuggestData data = TestSearchSuggestData(); loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, data); - ASSERT_THAT(service()->search_suggest_data(), Eq(data)); + ASSERT_EQ(data, service()->search_suggest_data()); // Sign out. This should clear the cached data and notify the observer. SignOut(); - EXPECT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + EXPECT_EQ(base::nullopt, service()->search_suggest_data()); } -TEST_F(SearchSuggestServiceTest, BlacklistSuggestionUpdatesBlacklistString) { - ASSERT_THAT(service()->GetBlacklistAsString(), Eq(std::string())); +TEST_F(SearchSuggestServiceTest, BlocklistSuggestionUpdatesBlocklistString) { + SetUserSelectedDefaultSearchProvider("{google:baseURL}"); + ASSERT_EQ(std::string(), service()->GetBlocklistAsString()); - std::vector<uint8_t> hash1 = {'a', 'b', 'c', 'd'}; - std::vector<uint8_t> hash2 = {'e', 'f', 'g', 'h'}; - service()->BlacklistSearchSuggestionWithHash(0, 1234, hash1); - service()->BlacklistSearchSuggestion(2, 5678); - service()->BlacklistSearchSuggestionWithHash(1, 1234, hash2); - service()->BlacklistSearchSuggestionWithHash(2, 1234, hash1); - service()->BlacklistSearchSuggestion(4, 1234); - service()->BlacklistSearchSuggestionWithHash(2, 1234, hash2); - service()->BlacklistSearchSuggestionWithHash(0, 1234, hash2); + uint8_t hash1[5] = {'a', 'b', 'c', 'd', '\0'}; + uint8_t hash2[5] = {'e', 'f', 'g', 'h', '\0'}; + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash1); + service()->BlocklistSearchSuggestion(2, 5678); + service()->BlocklistSearchSuggestionWithHash(1, 1234, hash2); + service()->BlocklistSearchSuggestionWithHash(2, 1234, hash1); + service()->BlocklistSearchSuggestion(4, 1234); + service()->BlocklistSearchSuggestionWithHash(2, 1234, hash2); + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash2); std::string expected = "0_1234:abcd,efgh;1_1234:efgh;2_1234:abcd,efgh;2_5678;4_1234"; - ASSERT_THAT(service()->GetBlacklistAsString(), Eq(expected)); + ASSERT_EQ(expected, service()->GetBlocklistAsString()); +} + +TEST_F(SearchSuggestServiceTest, BlocklistUnchangedOnInvalidHash) { + SetUserSelectedDefaultSearchProvider("{google:baseURL}"); + ASSERT_EQ(std::string(), service()->GetBlocklistAsString()); + + uint8_t hash1[5] = {'a', 'b', '?', 'd', '\0'}; + uint8_t hash2[5] = {'a', '_', 'b', 'm', '\0'}; + uint8_t hash3[5] = {'A', 'B', 'C', 'D', '\0'}; + uint8_t hash4[6] = {'a', 'b', 'c', 'd', 'e', '\0'}; + std::string expected = std::string(); + + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash1); + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash2); + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash3); + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash4); + ASSERT_EQ(expected, service()->GetBlocklistAsString()); +} + +TEST_F(SearchSuggestServiceTest, ShortHashUpdatesBlackist) { + SetUserSelectedDefaultSearchProvider("{google:baseURL}"); + ASSERT_EQ(std::string(), service()->GetBlocklistAsString()); + + uint8_t hash1[4] = {'a', 'b', 'c', '\0'}; + uint8_t hash2[5] = {'d', 'e', '\0', 'f', '\0'}; + std::string expected = "0_1234:abc;1_5678:de"; + + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash1); + service()->BlocklistSearchSuggestionWithHash(1, 5678, hash2); + ASSERT_EQ(expected, service()->GetBlocklistAsString()); } TEST_F(SearchSuggestServiceTest, - BlacklistSuggestionOverridesBlackistSuggestionWithHash) { - ASSERT_THAT(service()->GetBlacklistAsString(), Eq(std::string())); + BlocklistSuggestionOverridesBlackistSuggestionWithHash) { + SetUserSelectedDefaultSearchProvider("{google:baseURL}"); + ASSERT_EQ(std::string(), service()->GetBlocklistAsString()); - std::vector<uint8_t> hash = {'a', 'b', 'c', 'd'}; - service()->BlacklistSearchSuggestionWithHash(0, 1234, hash); - ASSERT_THAT(service()->GetBlacklistAsString(), Eq("0_1234:abcd")); + uint8_t hash[5] = {'a', 'b', 'c', 'd', '\0'}; + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash); + ASSERT_EQ("0_1234:abcd", service()->GetBlocklistAsString()); - service()->BlacklistSearchSuggestion(0, 1234); - ASSERT_THAT(service()->GetBlacklistAsString(), Eq("0_1234")); + service()->BlocklistSearchSuggestion(0, 1234); + ASSERT_EQ("0_1234", service()->GetBlocklistAsString()); } -TEST_F(SearchSuggestServiceTest, BlacklistClearsCachedDataAndIssuesRequest) { - ASSERT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); +TEST_F(SearchSuggestServiceTest, BlocklistClearsCachedDataAndIssuesRequest) { + SetUserSelectedDefaultSearchProvider("{google:baseURL}"); + ASSERT_EQ(base::nullopt, service()->search_suggest_data()); SignIn(); // Request a refresh. That should arrive at the loader. service()->Refresh(); - EXPECT_THAT(loader()->GetCallbackCount(), Eq(1u)); + EXPECT_EQ(1u, loader()->GetCallbackCount()); // Fulfill it. SearchSuggestData data = TestSearchSuggestData(); loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, data); - EXPECT_THAT(service()->search_suggest_data(), Eq(data)); + EXPECT_EQ(data, service()->search_suggest_data()); - // Blacklist something. - std::vector<uint8_t> hash = {'a', 'b', 'c', 'd'}; - service()->BlacklistSearchSuggestionWithHash(0, 1234, hash); - ASSERT_THAT(service()->GetBlacklistAsString(), Eq("0_1234:abcd")); - EXPECT_THAT(loader()->GetCallbackCount(), Eq(1u)); + // Select a suggestion to blocklist. + uint8_t hash[5] = {'a', 'b', 'c', 'd', '\0'}; + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash); + ASSERT_EQ("0_1234:abcd", service()->GetBlocklistAsString()); + EXPECT_EQ(1u, loader()->GetCallbackCount()); // Fulfill the second request. SearchSuggestData other_data; other_data.suggestions_html = "<div>Different!</div>"; loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, other_data); - EXPECT_THAT(service()->search_suggest_data(), Eq(other_data)); + EXPECT_EQ(other_data, service()->search_suggest_data()); +} + +TEST_F(SearchSuggestServiceTest, + SuggestionSelectedClearsCachedDataAndIssuesRequest) { + SetUserSelectedDefaultSearchProvider("{google:baseURL}"); + ASSERT_EQ(base::nullopt, service()->search_suggest_data()); + SignIn(); + + // Request a refresh. That should arrive at the loader. + service()->Refresh(); + EXPECT_EQ(1u, loader()->GetCallbackCount()); + + // Fulfill it. + SearchSuggestData data = TestSearchSuggestData(); + loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, data); + EXPECT_EQ(data, service()->search_suggest_data()); + + // Select a suggestion to blocklist. + uint8_t hash[5] = {'a', 'b', 'c', 'd', '\0'}; + service()->SearchSuggestionSelected(0, 1234, hash); + + // The local blocklist should not be updated. + ASSERT_EQ(std::string(), service()->GetBlocklistAsString()); + EXPECT_EQ(1u, loader()->GetCallbackCount()); + + // Fulfill the second request. + SearchSuggestData other_data; + other_data.suggestions_html = "<div>Different!</div>"; + loader()->RespondToAllCallbacks(SearchSuggestLoader::Status::OK, other_data); + EXPECT_EQ(other_data, service()->search_suggest_data()); } TEST_F(SearchSuggestServiceTest, OptOutPreventsRequests) { - ASSERT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + SetUserSelectedDefaultSearchProvider("{google:baseURL}"); + ASSERT_EQ(base::nullopt, service()->search_suggest_data()); SignIn(); service()->OptOutOfSearchSuggestions(); // Request a refresh. That should do nothing as the user opted-out. service()->Refresh(); - EXPECT_THAT(loader()->GetCallbackCount(), Eq(0u)); - EXPECT_THAT(service()->search_suggest_data(), Eq(base::nullopt)); + EXPECT_EQ(0u, loader()->GetCallbackCount()); + EXPECT_EQ(base::nullopt, service()->search_suggest_data()); +} + +TEST_F(SearchSuggestServiceTest, SuggestionAPIsDoNothingWithNonGoogleDSP) { + SetUserSelectedDefaultSearchProvider("https://search.com/"); + ASSERT_EQ(std::string(), service()->GetBlocklistAsString()); + + uint8_t hash[5] = {'a', 'b', 'c', 'd', '\0'}; + service()->BlocklistSearchSuggestionWithHash(0, 1234, hash); + EXPECT_EQ(std::string(), service()->GetBlocklistAsString()); + + service()->BlocklistSearchSuggestion(1, 2345); + EXPECT_EQ(std::string(), service()->GetBlocklistAsString()); + + service()->OptOutOfSearchSuggestions(); + EXPECT_FALSE(profile()->GetTestingPrefService()->GetBoolean( + prefs::kNtpSearchSuggestionsOptOut)); + + service()->SearchSuggestionSelected(0, 1234, hash); + EXPECT_EQ(0u, loader()->GetCallbackCount()); } TEST_F(SearchSuggestServiceTest, UpdateImpressionCapParameters) {
diff --git a/chrome/browser/serial/OWNERS b/chrome/browser/serial/OWNERS new file mode 100644 index 0000000..4ae83ca --- /dev/null +++ b/chrome/browser/serial/OWNERS
@@ -0,0 +1,3 @@ +file://content/browser/serial/OWNERS + +# COMPONENT: Blink>Serial
diff --git a/chrome/browser/serial/chrome_serial_delegate.cc b/chrome/browser/serial/chrome_serial_delegate.cc new file mode 100644 index 0000000..b6dbbab --- /dev/null +++ b/chrome/browser/serial/chrome_serial_delegate.cc
@@ -0,0 +1,62 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/serial/chrome_serial_delegate.h" + +#include <utility> + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/serial/serial_chooser_context.h" +#include "chrome/browser/serial/serial_chooser_context_factory.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/chrome_bubble_manager.h" +#include "chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h" +#include "chrome/browser/ui/serial/serial_chooser.h" +#include "chrome/browser/ui/serial/serial_chooser_controller.h" +#include "content/public/browser/web_contents.h" + +ChromeSerialDelegate::ChromeSerialDelegate() = default; + +ChromeSerialDelegate::~ChromeSerialDelegate() = default; + +std::unique_ptr<content::SerialChooser> ChromeSerialDelegate::RunChooser( + content::RenderFrameHost* frame, + std::vector<blink::mojom::SerialPortFilterPtr> filters, + content::SerialChooser::Callback callback) { + Browser* browser = chrome::FindBrowserWithWebContents( + content::WebContents::FromRenderFrameHost(frame)); + if (!browser) { + std::move(callback).Run(nullptr); + return nullptr; + } + + auto chooser_controller = std::make_unique<SerialChooserController>( + frame, std::move(filters), std::move(callback)); + auto chooser_bubble_delegate = std::make_unique<ChooserBubbleDelegate>( + frame, std::move(chooser_controller)); + BubbleReference bubble_reference = browser->GetBubbleManager()->ShowBubble( + std::move(chooser_bubble_delegate)); + return std::make_unique<SerialChooser>(std::move(bubble_reference)); +} + +bool ChromeSerialDelegate::HasPortPermission( + content::RenderFrameHost* frame, + const device::mojom::SerialPortInfo& port) { + auto* web_contents = content::WebContents::FromRenderFrameHost(frame); + auto* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + auto* chooser_context = SerialChooserContextFactory::GetForProfile(profile); + return chooser_context->HasPortPermission( + frame->GetLastCommittedOrigin(), + web_contents->GetMainFrame()->GetLastCommittedOrigin(), port); +} + +device::mojom::SerialPortManager* ChromeSerialDelegate::GetPortManager( + content::RenderFrameHost* frame) { + auto* web_contents = content::WebContents::FromRenderFrameHost(frame); + auto* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + auto* chooser_context = SerialChooserContextFactory::GetForProfile(profile); + return chooser_context->GetPortManager(); +}
diff --git a/chrome/browser/serial/chrome_serial_delegate.h b/chrome/browser/serial/chrome_serial_delegate.h new file mode 100644 index 0000000..2ca3730 --- /dev/null +++ b/chrome/browser/serial/chrome_serial_delegate.h
@@ -0,0 +1,31 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SERIAL_CHROME_SERIAL_DELEGATE_H_ +#define CHROME_BROWSER_SERIAL_CHROME_SERIAL_DELEGATE_H_ + +#include <memory> +#include <vector> + +#include "content/public/browser/serial_delegate.h" + +class ChromeSerialDelegate : public content::SerialDelegate { + public: + ChromeSerialDelegate(); + ~ChromeSerialDelegate() override; + + std::unique_ptr<content::SerialChooser> RunChooser( + content::RenderFrameHost* frame, + std::vector<blink::mojom::SerialPortFilterPtr> filters, + content::SerialChooser::Callback callback) override; + bool HasPortPermission(content::RenderFrameHost* frame, + const device::mojom::SerialPortInfo& port) override; + device::mojom::SerialPortManager* GetPortManager( + content::RenderFrameHost* frame) override; + + private: + DISALLOW_COPY_AND_ASSIGN(ChromeSerialDelegate); +}; + +#endif // CHROME_BROWSER_SERIAL_CHROME_SERIAL_DELEGATE_H_
diff --git a/chrome/browser/serial/serial_chooser_context.cc b/chrome/browser/serial/serial_chooser_context.cc new file mode 100644 index 0000000..8c0611bce --- /dev/null +++ b/chrome/browser/serial/serial_chooser_context.cc
@@ -0,0 +1,215 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/serial/serial_chooser_context.h" + +#include <utility> + +#include "base/base64.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/common/service_manager_connection.h" +#include "services/device/public/mojom/constants.mojom.h" +#include "services/service_manager/public/cpp/connector.h" + +namespace { + +constexpr char kPortNameKey[] = "name"; +constexpr char kTokenKey[] = "token"; + +std::string EncodeToken(const base::UnguessableToken& token) { + const uint64_t data[2] = {token.GetHighForSerialization(), + token.GetLowForSerialization()}; + std::string buffer; + base::Base64Encode( + base::StringPiece(reinterpret_cast<const char*>(&data[0]), sizeof(data)), + &buffer); + return buffer; +} + +base::UnguessableToken DecodeToken(base::StringPiece input) { + std::string buffer; + if (!base::Base64Decode(input, &buffer) || + buffer.length() != sizeof(uint64_t) * 2) { + return base::UnguessableToken(); + } + + const uint64_t* data = reinterpret_cast<const uint64_t*>(buffer.data()); + return base::UnguessableToken::Deserialize(data[0], data[1]); +} + +base::Value PortInfoToValue(const device::mojom::SerialPortInfo& port) { + base::Value value(base::Value::Type::DICTIONARY); + if (port.display_name) + value.SetKey(kPortNameKey, base::Value(*port.display_name)); + else + value.SetKey(kPortNameKey, base::Value(port.path.LossyDisplayName())); + value.SetKey(kTokenKey, base::Value(EncodeToken(port.token))); + return value; +} + +} // namespace + +SerialChooserContext::SerialChooserContext(Profile* profile) + : ChooserContextBase(profile, + CONTENT_SETTINGS_TYPE_SERIAL_GUARD, + CONTENT_SETTINGS_TYPE_SERIAL_CHOOSER_DATA), + is_incognito_(profile->IsOffTheRecord()) {} + +SerialChooserContext::~SerialChooserContext() = default; + +bool SerialChooserContext::IsValidObject(const base::DictionaryValue& object) { + const std::string* token = object.FindStringKey(kTokenKey); + return object.size() == 2 && object.FindStringKey(kPortNameKey) && token && + DecodeToken(*token); +} + +std::string SerialChooserContext::GetObjectName( + const base::DictionaryValue& object) { + DCHECK(IsValidObject(object)); + return *object.FindStringKey(kPortNameKey); +} + +std::vector<std::unique_ptr<ChooserContextBase::Object>> +SerialChooserContext::GetGrantedObjects(const GURL& requesting_origin, + const GURL& embedding_origin) { + std::vector<std::unique_ptr<Object>> objects; + auto origin_it = ephemeral_ports_.find( + std::make_pair(url::Origin::Create(requesting_origin), + url::Origin::Create(embedding_origin))); + if (origin_it == ephemeral_ports_.end()) + return objects; + const std::set<base::UnguessableToken> ports = origin_it->second; + + for (const auto& token : ports) { + auto it = port_info_.find(token); + if (it == port_info_.end()) + continue; + + // Object's constructor should take a base::Value directly. + base::Value clone = it->second.Clone(); + base::DictionaryValue* object; + clone.GetAsDictionary(&object); + + objects.push_back(std::make_unique<Object>( + requesting_origin, embedding_origin, object, + content_settings::SettingSource::SETTING_SOURCE_USER, is_incognito_)); + } + + return objects; +} + +std::vector<std::unique_ptr<ChooserContextBase::Object>> +SerialChooserContext::GetAllGrantedObjects() { + std::vector<std::unique_ptr<Object>> objects; + for (const auto& map_entry : ephemeral_ports_) { + GURL requesting_origin = map_entry.first.first.GetURL(); + GURL embedding_origin = map_entry.first.second.GetURL(); + + if (!CanRequestObjectPermission(requesting_origin, embedding_origin)) + continue; + + for (const auto& token : map_entry.second) { + auto it = port_info_.find(token); + if (it == port_info_.end()) + continue; + + // Object's constructor should take a base::Value directly. + base::Value clone = it->second.Clone(); + base::DictionaryValue* object; + clone.GetAsDictionary(&object); + + objects.push_back(std::make_unique<Object>( + requesting_origin, embedding_origin, object, + content_settings::SettingSource::SETTING_SOURCE_USER, is_incognito_)); + } + } + + return objects; +} + +void SerialChooserContext::RevokeObjectPermission( + const GURL& requesting_origin, + const GURL& embedding_origin, + const base::DictionaryValue& object) { + auto origin_it = ephemeral_ports_.find( + std::make_pair(url::Origin::Create(requesting_origin), + url::Origin::Create(embedding_origin))); + if (origin_it == ephemeral_ports_.end()) + return; + std::set<base::UnguessableToken>& ports = origin_it->second; + + DCHECK(IsValidObject(object)); + ports.erase(DecodeToken(*object.FindStringKey(kTokenKey))); +} + +void SerialChooserContext::GrantPortPermission( + const url::Origin& requesting_origin, + const url::Origin& embedding_origin, + const device::mojom::SerialPortInfo& port) { + // TODO(crbug.com/908836): If |port| can be remembered persistently call into + // ChooserContextBase to store it in user preferences. + ephemeral_ports_[std::make_pair(requesting_origin, embedding_origin)].insert( + port.token); + port_info_[port.token] = PortInfoToValue(port); +} + +bool SerialChooserContext::HasPortPermission( + const url::Origin& requesting_origin, + const url::Origin& embedding_origin, + const device::mojom::SerialPortInfo& port) { + if (!CanRequestObjectPermission(requesting_origin.GetURL(), + embedding_origin.GetURL())) { + return false; + } + + auto origin_it = ephemeral_ports_.find( + std::make_pair(requesting_origin, embedding_origin)); + if (origin_it == ephemeral_ports_.end()) + return false; + const std::set<base::UnguessableToken> ports = origin_it->second; + + // TODO(crbug.com/908836): Call into ChooserContextBase to check persistent + // permissions. + auto port_it = ports.find(port.token); + return port_it != ports.end(); +} + +device::mojom::SerialPortManager* SerialChooserContext::GetPortManager() { + EnsurePortManagerConnection(); + return port_manager_.get(); +} + +void SerialChooserContext::SetPortManagerForTesting( + device::mojom::SerialPortManagerPtr manager) { + SetUpPortManagerConnection(std::move(manager)); +} + +base::WeakPtr<SerialChooserContext> SerialChooserContext::AsWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + +void SerialChooserContext::EnsurePortManagerConnection() { + if (port_manager_) + return; + + device::mojom::SerialPortManagerPtr manager; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(device::mojom::kServiceName, mojo::MakeRequest(&manager)); + SetUpPortManagerConnection(std::move(manager)); +} + +void SerialChooserContext::SetUpPortManagerConnection( + device::mojom::SerialPortManagerPtr manager) { + port_manager_ = std::move(manager); + port_manager_.set_connection_error_handler( + base::BindOnce(&SerialChooserContext::OnPortManagerConnectionError, + base::Unretained(this))); +} + +void SerialChooserContext::OnPortManagerConnectionError() { + port_info_.clear(); + ephemeral_ports_.clear(); +}
diff --git a/chrome/browser/serial/serial_chooser_context.h b/chrome/browser/serial/serial_chooser_context.h new file mode 100644 index 0000000..7079a73c --- /dev/null +++ b/chrome/browser/serial/serial_chooser_context.h
@@ -0,0 +1,86 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SERIAL_SERIAL_CHOOSER_CONTEXT_H_ +#define CHROME_BROWSER_SERIAL_SERIAL_CHOOSER_CONTEXT_H_ + +#include <map> +#include <memory> +#include <set> +#include <string> +#include <utility> +#include <vector> + +#include "base/memory/weak_ptr.h" +#include "base/unguessable_token.h" +#include "chrome/browser/permissions/chooser_context_base.h" +#include "services/device/public/mojom/serial.mojom.h" +#include "third_party/blink/public/mojom/serial/serial.mojom.h" +#include "url/gurl.h" +#include "url/origin.h" + +namespace base { +class DictionaryValue; +} + +class SerialChooserContext : public ChooserContextBase { + public: + explicit SerialChooserContext(Profile* profile); + ~SerialChooserContext() override; + + // ChooserContextBase implementation. + bool IsValidObject(const base::DictionaryValue& object) override; + std::string GetObjectName(const base::DictionaryValue& object) override; + + // In addition these methods from ChooserContextBase are overridden in order + // to expose ephemeral devices through the public interface. + std::vector<std::unique_ptr<Object>> GetGrantedObjects( + const GURL& requesting_origin, + const GURL& embedding_origin) override; + std::vector<std::unique_ptr<Object>> GetAllGrantedObjects() override; + void RevokeObjectPermission(const GURL& requesting_origin, + const GURL& embedding_origin, + const base::DictionaryValue& object) override; + + // Serial-specific interface for granting and checking permissions. + void GrantPortPermission(const url::Origin& requesting_origin, + const url::Origin& embedding_origin, + const device::mojom::SerialPortInfo& port); + bool HasPortPermission(const url::Origin& requesting_origin, + const url::Origin& embedding_origin, + const device::mojom::SerialPortInfo& port); + + device::mojom::SerialPortManager* GetPortManager(); + + void SetPortManagerForTesting(device::mojom::SerialPortManagerPtr manager); + base::WeakPtr<SerialChooserContext> AsWeakPtr(); + + private: + void EnsurePortManagerConnection(); + void SetUpPortManagerConnection(device::mojom::SerialPortManagerPtr manager); + void OnPortManagerConnectionError(); + void OnGetPorts(const url::Origin& requesting_origin, + const url::Origin& embedding_origin, + blink::mojom::SerialService::GetPortsCallback callback, + std::vector<device::mojom::SerialPortInfoPtr> ports); + + const bool is_incognito_; + + // Tracks the set of ports to which an origin (potentially embedded in another + // origin) has access to. Key is (requesting_origin, embedding_origin). + std::map<std::pair<url::Origin, url::Origin>, + std::set<base::UnguessableToken>> + ephemeral_ports_; + + // Holds information about ports in |ephemeral_ports_|. + std::map<base::UnguessableToken, base::Value> port_info_; + + device::mojom::SerialPortManagerPtr port_manager_; + + base::WeakPtrFactory<SerialChooserContext> weak_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(SerialChooserContext); +}; + +#endif // CHROME_BROWSER_SERIAL_SERIAL_CHOOSER_CONTEXT_H_
diff --git a/chrome/browser/serial/serial_chooser_context_factory.cc b/chrome/browser/serial/serial_chooser_context_factory.cc new file mode 100644 index 0000000..89c7e4c --- /dev/null +++ b/chrome/browser/serial/serial_chooser_context_factory.cc
@@ -0,0 +1,42 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/serial/serial_chooser_context_factory.h" + +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/profiles/incognito_helpers.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/serial/serial_chooser_context.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" + +SerialChooserContextFactory::SerialChooserContextFactory() + : BrowserContextKeyedServiceFactory( + "SerialChooserContext", + BrowserContextDependencyManager::GetInstance()) { + DependsOn(HostContentSettingsMapFactory::GetInstance()); +} + +SerialChooserContextFactory::~SerialChooserContextFactory() {} + +KeyedService* SerialChooserContextFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new SerialChooserContext(Profile::FromBrowserContext(context)); +} + +// static +SerialChooserContextFactory* SerialChooserContextFactory::GetInstance() { + return base::Singleton<SerialChooserContextFactory>::get(); +} + +// static +SerialChooserContext* SerialChooserContextFactory::GetForProfile( + Profile* profile) { + return static_cast<SerialChooserContext*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +content::BrowserContext* SerialChooserContextFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return chrome::GetBrowserContextOwnInstanceInIncognito(context); +}
diff --git a/chrome/browser/serial/serial_chooser_context_factory.h b/chrome/browser/serial/serial_chooser_context_factory.h new file mode 100644 index 0000000..d19b033 --- /dev/null +++ b/chrome/browser/serial/serial_chooser_context_factory.h
@@ -0,0 +1,35 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SERIAL_SERIAL_CHOOSER_CONTEXT_FACTORY_H_ +#define CHROME_BROWSER_SERIAL_SERIAL_CHOOSER_CONTEXT_FACTORY_H_ + +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +class SerialChooserContext; +class Profile; + +class SerialChooserContextFactory : public BrowserContextKeyedServiceFactory { + public: + static SerialChooserContext* GetForProfile(Profile* profile); + static SerialChooserContextFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits<SerialChooserContextFactory>; + + SerialChooserContextFactory(); + ~SerialChooserContextFactory() override; + + // BrowserContextKeyedBaseFactory methods: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* profile) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + + DISALLOW_COPY_AND_ASSIGN(SerialChooserContextFactory); +}; + +#endif // CHROME_BROWSER_SERIAL_SERIAL_CHOOSER_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/serial/serial_chooser_context_unittest.cc b/chrome/browser/serial/serial_chooser_context_unittest.cc new file mode 100644 index 0000000..8a95111e --- /dev/null +++ b/chrome/browser/serial/serial_chooser_context_unittest.cc
@@ -0,0 +1,66 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/serial/serial_chooser_context.h" + +#include "base/run_loop.h" +#include "chrome/browser/serial/serial_chooser_context_factory.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "services/device/public/mojom/serial.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class SerialChooserContextTest : public testing::Test { + public: + SerialChooserContextTest() = default; + ~SerialChooserContextTest() override = default; + + Profile* profile() { return &profile_; } + + SerialChooserContext* GetContext(Profile* profile) { + return SerialChooserContextFactory::GetForProfile(profile); + } + + private: + content::TestBrowserThreadBundle thread_bundle_; + TestingProfile profile_; +}; + +} // namespace + +TEST_F(SerialChooserContextTest, GrantAndRevokeEphemeralPermission) { + const auto origin = url::Origin::Create(GURL("https://google.com")); + + auto port = device::mojom::SerialPortInfo::New(); + port->token = base::UnguessableToken::Create(); + + SerialChooserContext* context = GetContext(profile()); + EXPECT_FALSE(context->HasPortPermission(origin, origin, *port)); + context->GrantPortPermission(origin, origin, *port); + EXPECT_TRUE(context->HasPortPermission(origin, origin, *port)); + + std::vector<std::unique_ptr<ChooserContextBase::Object>> origin_objects = + context->GetGrantedObjects(origin.GetURL(), origin.GetURL()); + ASSERT_EQ(1u, origin_objects.size()); + + std::vector<std::unique_ptr<ChooserContextBase::Object>> objects = + context->GetAllGrantedObjects(); + ASSERT_EQ(1u, objects.size()); + EXPECT_EQ(origin.GetURL(), objects[0]->requesting_origin); + EXPECT_EQ(origin.GetURL(), objects[0]->embedding_origin); + EXPECT_EQ(origin_objects[0]->value, objects[0]->value); + EXPECT_EQ(content_settings::SettingSource::SETTING_SOURCE_USER, + objects[0]->source); + EXPECT_FALSE(objects[0]->incognito); + + context->RevokeObjectPermission(origin.GetURL(), origin.GetURL(), + objects[0]->value); + EXPECT_FALSE(context->HasPortPermission(origin, origin, *port)); + origin_objects = context->GetGrantedObjects(origin.GetURL(), origin.GetURL()); + EXPECT_EQ(0u, origin_objects.size()); + objects = context->GetAllGrantedObjects(); + EXPECT_EQ(0u, objects.size()); +}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index daf6d6ad..0d70af2 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3719,6 +3719,8 @@ sources += [ "ash/fake_tablet_mode_controller.cc", "ash/fake_tablet_mode_controller.h", + "ash/test_login_screen.cc", + "ash/test_login_screen.h", "ash/test_session_controller.cc", "ash/test_session_controller.h", "ash/test_wallpaper_controller.cc",
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc index 5743d7d..53f5407e 100644 --- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc +++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -423,7 +423,6 @@ auto* controller = keyboard::KeyboardController::Get(); - controller->LoadKeyboardWindowInBackground(); EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardControllerState::LOADING_EXTENSION);
diff --git a/chrome/browser/ui/ash/tab_scrubber.cc b/chrome/browser/ui/ash/tab_scrubber.cc index 5c82cbf..a97836762 100644 --- a/chrome/browser/ui/ash/tab_scrubber.cc +++ b/chrome/browser/ui/ash/tab_scrubber.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" -#include "chrome/browser/ui/views/tabs/glow_hover_controller.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/tabs/tab_style.h" @@ -153,7 +152,7 @@ if (highlighted_tab_ != -1) { gfx::Point hover_point(swipe_x_, swipe_y_); views::View::ConvertPointToTarget(tab_strip_, new_tab, &hover_point); - new_tab->hover_controller()->SetLocation(hover_point); + new_tab->tab_style()->SetHoverLocation(hover_point); } } @@ -240,7 +239,7 @@ TabStrip* tab_strip = browser_view->tabstrip(); if (activate && highlighted_tab_ != -1) { Tab* tab = tab_strip->tab_at(highlighted_tab_); - tab->hover_controller()->HideImmediately(); + tab->tab_style()->HideHover(GlowHoverController::HideStyle::kImmediate); int distance = std::abs(highlighted_tab_ - browser_->tab_strip_model()->active_index()); UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.ScrubDistance", distance, 1, 20, 21); @@ -318,12 +317,13 @@ if (highlighted_tab_ != -1) { Tab* tab = tab_strip_->tab_at(highlighted_tab_); - tab->hover_controller()->HideImmediately(); + tab->tab_style()->HideHover(GlowHoverController::HideStyle::kImmediate); } if (new_index != browser_->tab_strip_model()->active_index()) { highlighted_tab_ = new_index; - new_tab->hover_controller()->Show(GlowHoverController::PRONOUNCED); + new_tab->tab_style()->ShowHover( + GlowHoverController::ShowStyle::kPronounced); } else { highlighted_tab_ = -1; }
diff --git a/chrome/browser/ui/ash/test_login_screen.cc b/chrome/browser/ui/ash/test_login_screen.cc new file mode 100644 index 0000000..fbcad54 --- /dev/null +++ b/chrome/browser/ui/ash/test_login_screen.cc
@@ -0,0 +1,137 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/test_login_screen.h" + +#include <utility> + +#include "ash/public/interfaces/constants.mojom.h" +#include "content/public/common/service_manager_connection.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/service_filter.h" + +TestLoginScreen::TestLoginScreen() { + CHECK(content::ServiceManagerConnection::GetForProcess()) + << "ServiceManager is uninitialized. Did you forget to create a " + "content::TestServiceManagerContext?"; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->OverrideBinderForTesting( + service_manager::ServiceFilter::ByName(ash::mojom::kServiceName), + ash::mojom::LoginScreen::Name_, + base::BindRepeating(&TestLoginScreen::Bind, base::Unretained(this))); +} + +TestLoginScreen::~TestLoginScreen() { + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->ClearBinderOverrideForTesting( + service_manager::ServiceFilter::ByName(ash::mojom::kServiceName), + ash::mojom::LoginScreen::Name_); +} + +void TestLoginScreen::SetClient(ash::mojom::LoginScreenClientPtr client) {} + +void TestLoginScreen::ShowLockScreen(ShowLockScreenCallback callback) { + std::move(callback).Run(true); +} + +void TestLoginScreen::ShowLoginScreen(ShowLoginScreenCallback callback) { + std::move(callback).Run(true); +} + +void TestLoginScreen::ShowErrorMessage(int32_t login_attempts, + const std::string& error_text, + const std::string& help_link_text, + int32_t help_topic_id) {} + +void TestLoginScreen::ShowWarningBanner(const base::string16& message) {} + +void TestLoginScreen::HideWarningBanner() {} + +void TestLoginScreen::ClearErrors() {} + +void TestLoginScreen::ShowUserPodCustomIcon( + const AccountId& account_id, + ::ash::mojom::EasyUnlockIconOptionsPtr icon) {} + +void TestLoginScreen::HideUserPodCustomIcon(const AccountId& account_id) {} + +void TestLoginScreen::SetAuthType(const AccountId& account_id, + ::proximity_auth::mojom::AuthType auth_type, + const base::string16& initial_value) {} + +void TestLoginScreen::SetUserList( + std::vector<::ash::mojom::LoginUserInfoPtr> users) {} + +void TestLoginScreen::SetPinEnabledForUser(const AccountId& account_id, + bool is_enabled) {} + +void TestLoginScreen::SetFingerprintState( + const AccountId& account_id, + ::ash::mojom::FingerprintState state) {} + +void TestLoginScreen::NotifyFingerprintAuthResult(const AccountId& account_id, + bool successful) {} + +void TestLoginScreen::SetAvatarForUser(const AccountId& account_id, + ::ash::mojom::UserAvatarPtr avatar) {} + +void TestLoginScreen::SetAuthEnabledForUser( + const AccountId& account_id, + bool is_enabled, + base::Optional<base::Time> auth_reenabled_time) {} + +void TestLoginScreen::HandleFocusLeavingLockScreenApps(bool reverse) {} + +void TestLoginScreen::SetSystemInfo(bool show_if_hidden, + const std::string& os_version_label_text, + const std::string& enterprise_info_text, + const std::string& bluetooth_name) {} + +void TestLoginScreen::IsReadyForPassword(IsReadyForPasswordCallback callback) { + std::move(callback).Run(true); +} + +void TestLoginScreen::SetPublicSessionDisplayName( + const AccountId& account_id, + const std::string& display_name) {} + +void TestLoginScreen::SetPublicSessionLocales( + const AccountId& account_id, + std::vector<::ash::mojom::LocaleItemPtr> locales, + const std::string& default_locale, + bool show_advanced_view) {} + +void TestLoginScreen::SetPublicSessionKeyboardLayouts( + const AccountId& account_id, + const std::string& locale, + std::vector<::ash::mojom::InputMethodItemPtr> keyboard_layouts) {} + +void TestLoginScreen::SetPublicSessionShowFullManagementDisclosure( + bool show_full_management_disclosure) {} + +void TestLoginScreen::SetKioskApps( + std::vector<::ash::mojom::KioskAppInfoPtr> kiosk_apps) {} + +void TestLoginScreen::ShowKioskAppError(const std::string& message) {} + +void TestLoginScreen::NotifyOobeDialogState(ash::mojom::OobeDialogState state) { +} + +void TestLoginScreen::SetAddUserButtonEnabled(bool enable) {} + +void TestLoginScreen::SetShutdownButtonEnabled(bool enable) {} + +void TestLoginScreen::SetAllowLoginAsGuest(bool allow_guest) {} + +void TestLoginScreen::SetShowGuestButtonInOobe(bool show) {} + +void TestLoginScreen::SetShowParentAccess(bool show) {} + +void TestLoginScreen::FocusLoginShelf(bool reverse) {} + +void TestLoginScreen::Bind(mojo::ScopedMessagePipeHandle handle) { + binding_.Bind(ash::mojom::LoginScreenRequest(std::move(handle))); +}
diff --git a/chrome/browser/ui/ash/test_login_screen.h b/chrome/browser/ui/ash/test_login_screen.h new file mode 100644 index 0000000..cde5266 --- /dev/null +++ b/chrome/browser/ui/ash/test_login_screen.h
@@ -0,0 +1,95 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_ASH_TEST_LOGIN_SCREEN_H_ +#define CHROME_BROWSER_UI_ASH_TEST_LOGIN_SCREEN_H_ + +#include <string> +#include <vector> + +#include "ash/public/interfaces/login_screen.mojom.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" + +// Test implementation of ash's mojo LoginScreen interface. +// +// Registers itself to ServiceManager on construction and deregisters +// on destruction. +// +// Note: A ServiceManagerConnection must be initialized before constructing this +// object. Consider using content::TestServiceManagerContext on your tests. +class TestLoginScreen : public ash::mojom::LoginScreen { + public: + TestLoginScreen(); + ~TestLoginScreen() override; + + // ash:mojom::LoginScreen: + void SetClient(ash::mojom::LoginScreenClientPtr client) override; + void ShowLockScreen(ShowLockScreenCallback callback) override; + void ShowLoginScreen(ShowLoginScreenCallback callback) override; + void ShowErrorMessage(int32_t login_attempts, + const std::string& error_text, + const std::string& help_link_text, + int32_t help_topic_id) override; + void ShowWarningBanner(const base::string16& message) override; + void HideWarningBanner() override; + void ClearErrors() override; + void ShowUserPodCustomIcon( + const AccountId& account_id, + ::ash::mojom::EasyUnlockIconOptionsPtr icon) override; + void HideUserPodCustomIcon(const AccountId& account_id) override; + void SetAuthType(const AccountId& account_id, + ::proximity_auth::mojom::AuthType auth_type, + const base::string16& initial_value) override; + void SetUserList(std::vector<::ash::mojom::LoginUserInfoPtr> users) override; + + void SetPinEnabledForUser(const AccountId& account_id, + bool is_enabled) override; + void SetFingerprintState(const AccountId& account_id, + ::ash::mojom::FingerprintState state) override; + void NotifyFingerprintAuthResult(const AccountId& account_id, + bool successful) override; + void SetAvatarForUser(const AccountId& account_id, + ::ash::mojom::UserAvatarPtr avatar) override; + void SetAuthEnabledForUser( + const AccountId& account_id, + bool is_enabled, + base::Optional<base::Time> auth_reenabled_time) override; + void HandleFocusLeavingLockScreenApps(bool reverse) override; + void SetSystemInfo(bool show_if_hidden, + const std::string& os_version_label_text, + const std::string& enterprise_info_text, + const std::string& bluetooth_name) override; + void IsReadyForPassword(IsReadyForPasswordCallback callback) override; + void SetPublicSessionDisplayName(const AccountId& account_id, + const std::string& display_name) override; + void SetPublicSessionLocales(const AccountId& account_id, + std::vector<::ash::mojom::LocaleItemPtr> locales, + const std::string& default_locale, + bool show_advanced_view) override; + void SetPublicSessionKeyboardLayouts( + const AccountId& account_id, + const std::string& locale, + std::vector<::ash::mojom::InputMethodItemPtr> keyboard_layouts) override; + void SetPublicSessionShowFullManagementDisclosure( + bool show_full_management_disclosure) override; + void SetKioskApps( + std::vector<::ash::mojom::KioskAppInfoPtr> kiosk_apps) override; + void ShowKioskAppError(const std::string& message) override; + void NotifyOobeDialogState(ash::mojom::OobeDialogState state) override; + void SetAddUserButtonEnabled(bool enable) override; + void SetShutdownButtonEnabled(bool enable) override; + void SetAllowLoginAsGuest(bool allow_guest) override; + void SetShowGuestButtonInOobe(bool show) override; + void SetShowParentAccess(bool show) override; + void FocusLoginShelf(bool reverse) override; + + private: + void Bind(mojo::ScopedMessagePipeHandle handle); + mojo::Binding<ash::mojom::LoginScreen> binding_{this}; + + DISALLOW_COPY_AND_ASSIGN(TestLoginScreen); +}; + +#endif // CHROME_BROWSER_UI_ASH_TEST_LOGIN_SCREEN_H_
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index de5c795e7..49ea4a9 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -135,8 +135,6 @@ #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h" #include "chrome/browser/ui/search/search_tab_helper.h" -#include "chrome/browser/ui/serial/serial_chooser.h" -#include "chrome/browser/ui/serial/serial_chooser_controller.h" #include "chrome/browser/ui/singleton_tabs.h" #include "chrome/browser/ui/status_bubble.h" #include "chrome/browser/ui/sync/browser_synced_window_delegate.h" @@ -1188,19 +1186,6 @@ return std::move(bluetooth_chooser_desktop); } -std::unique_ptr<content::SerialChooser> Browser::RunSerialChooser( - content::RenderFrameHost* frame, - std::vector<blink::mojom::SerialPortFilterPtr> filters, - content::SerialChooser::Callback callback) { - auto chooser_controller = std::make_unique<SerialChooserController>( - frame, std::move(filters), std::move(callback)); - auto chooser_bubble_delegate = std::make_unique<ChooserBubbleDelegate>( - frame, std::move(chooser_controller)); - BubbleReference bubble_reference = - GetBubbleManager()->ShowBubble(std::move(chooser_bubble_delegate)); - return std::make_unique<SerialChooser>(std::move(bubble_reference)); -} - void Browser::PassiveInsecureContentFound(const GURL& resource_url) { // Note: this implementation is a mirror of // ContentSettingsObserver::passiveInsecureContentFound
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 8a3d545e5..0307e6f 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -520,10 +520,6 @@ std::unique_ptr<content::BluetoothChooser> RunBluetoothChooser( content::RenderFrameHost* frame, const content::BluetoothChooser::EventHandler& event_handler) override; - std::unique_ptr<content::SerialChooser> RunSerialChooser( - content::RenderFrameHost* frame, - std::vector<blink::mojom::SerialPortFilterPtr> filters, - content::SerialChooser::Callback callback) override; void PassiveInsecureContentFound(const GURL& resource_url) override; bool ShouldAllowRunningInsecureContent(content::WebContents* web_contents, bool allowed_per_prefs,
diff --git a/chrome/browser/ui/search/search_ipc_router.cc b/chrome/browser/ui/search/search_ipc_router.cc index db319ab..1f85b6b6 100644 --- a/chrome/browser/ui/search/search_ipc_router.cc +++ b/chrome/browser/ui/search/search_ipc_router.cc
@@ -358,22 +358,39 @@ delegate_->OnSelectLocalBackgroundImage(); } -void SearchIPCRouter::BlacklistSearchSuggestion(int32_t task_version, +void SearchIPCRouter::BlocklistSearchSuggestion(int32_t task_version, int64_t task_id) { - if (!policy_->ShouldProcessBlacklistSearchSuggestion()) + if (!policy_->ShouldProcessBlocklistSearchSuggestion()) return; - delegate_->OnBlacklistSearchSuggestion(task_version, task_id); + delegate_->OnBlocklistSearchSuggestion(task_version, task_id); } -void SearchIPCRouter::BlacklistSearchSuggestionWithHash( +void SearchIPCRouter::BlocklistSearchSuggestionWithHash( int32_t task_version, int64_t task_id, const std::vector<uint8_t>& hash) { - if (!policy_->ShouldProcessBlacklistSearchSuggestionWithHash()) + if (!policy_->ShouldProcessBlocklistSearchSuggestionWithHash()) return; - delegate_->OnBlacklistSearchSuggestionWithHash(task_version, task_id, hash); + if (hash.size() > 4) { + return; + } + delegate_->OnBlocklistSearchSuggestionWithHash(task_version, task_id, + hash.data()); +} + +void SearchIPCRouter::SearchSuggestionSelected( + int32_t task_version, + int64_t task_id, + const std::vector<uint8_t>& hash) { + if (!policy_->ShouldProcessSearchSuggestionSelected()) + return; + + if (hash.size() > 4) { + return; + } + delegate_->OnSearchSuggestionSelected(task_version, task_id, hash.data()); } void SearchIPCRouter::OptOutOfSearchSuggestions() {
diff --git a/chrome/browser/ui/search/search_ipc_router.h b/chrome/browser/ui/search/search_ipc_router.h index 7bf8186b..be735dda 100644 --- a/chrome/browser/ui/search/search_ipc_router.h +++ b/chrome/browser/ui/search/search_ipc_router.h
@@ -119,16 +119,20 @@ // NTP background image. virtual void OnSelectLocalBackgroundImage() = 0; - // Called when a search suggestion is blacklisted on the local NTP. - virtual void OnBlacklistSearchSuggestion(int task_version, + // Called when a search suggestion is blocklisted on the local NTP. + virtual void OnBlocklistSearchSuggestion(int task_version, long task_id) = 0; - // Called when a search suggestion is blacklisted on the local NTP and a + // Called when a search suggestion is blocklisted on the local NTP and a // hash is provided. - virtual void OnBlacklistSearchSuggestionWithHash( - int task_version, - long task_id, - const std::vector<uint8_t>& hash) = 0; + virtual void OnBlocklistSearchSuggestionWithHash(int task_version, + long task_id, + const uint8_t hash[4]) = 0; + + // Called when a search suggestion is selected on the local NTP. + virtual void OnSearchSuggestionSelected(int task_version, + long task_id, + const uint8_t hash[4]) = 0; // Called when a user selected to completely opt out of NTP search // suggestions. @@ -165,8 +169,9 @@ virtual bool ShouldProcessSetCustomBackgroundURL() = 0; virtual bool ShouldProcessSetCustomBackgroundURLWithAttributions() = 0; virtual bool ShouldProcessSelectLocalBackgroundImage() = 0; - virtual bool ShouldProcessBlacklistSearchSuggestion() = 0; - virtual bool ShouldProcessBlacklistSearchSuggestionWithHash() = 0; + virtual bool ShouldProcessBlocklistSearchSuggestion() = 0; + virtual bool ShouldProcessBlocklistSearchSuggestionWithHash() = 0; + virtual bool ShouldProcessSearchSuggestionSelected() = 0; virtual bool ShouldProcessOptOutOfSearchSuggestions() = 0; }; @@ -256,12 +261,15 @@ const std::string& attribution_line_2, const GURL& action_url) override; void SelectLocalBackgroundImage() override; - void BlacklistSearchSuggestion(int32_t task_version, + void BlocklistSearchSuggestion(int32_t task_version, int64_t task_id) override; - void BlacklistSearchSuggestionWithHash( + void BlocklistSearchSuggestionWithHash( int32_t task_version, int64_t task_id, const std::vector<uint8_t>& hash) override; + void SearchSuggestionSelected(int32_t task_version, + int64_t task_id, + const std::vector<uint8_t>& hash) override; void OptOutOfSearchSuggestions() override; void set_embedded_search_client_factory_for_testing( std::unique_ptr<EmbeddedSearchClientFactory> factory) {
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc index 3f7f7731..b3a6a21 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc +++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
@@ -108,12 +108,16 @@ return !is_incognito_ && search::IsInstantNTP(web_contents_); } -bool SearchIPCRouterPolicyImpl::ShouldProcessBlacklistSearchSuggestion() { +bool SearchIPCRouterPolicyImpl::ShouldProcessBlocklistSearchSuggestion() { return !is_incognito_ && search::IsInstantNTP(web_contents_); } bool SearchIPCRouterPolicyImpl:: - ShouldProcessBlacklistSearchSuggestionWithHash() { + ShouldProcessBlocklistSearchSuggestionWithHash() { + return !is_incognito_ && search::IsInstantNTP(web_contents_); +} + +bool SearchIPCRouterPolicyImpl::ShouldProcessSearchSuggestionSelected() { return !is_incognito_ && search::IsInstantNTP(web_contents_); }
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.h b/chrome/browser/ui/search/search_ipc_router_policy_impl.h index d54f287..f8e0c19 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_impl.h +++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.h
@@ -48,8 +48,9 @@ bool ShouldProcessSetCustomBackgroundURL() override; bool ShouldProcessSetCustomBackgroundURLWithAttributions() override; bool ShouldProcessSelectLocalBackgroundImage() override; - bool ShouldProcessBlacklistSearchSuggestion() override; - bool ShouldProcessBlacklistSearchSuggestionWithHash() override; + bool ShouldProcessBlocklistSearchSuggestion() override; + bool ShouldProcessBlocklistSearchSuggestionWithHash() override; + bool ShouldProcessSearchSuggestionSelected() override; bool ShouldProcessOptOutOfSearchSuggestions() override; // Used by unit tests.
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc index fb88b93..1bdad86 100644 --- a/chrome/browser/ui/search/search_ipc_router_unittest.cc +++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -87,12 +87,12 @@ const std::string& attribution2, const GURL& attributionActionUrl)); MOCK_METHOD0(OnSelectLocalBackgroundImage, void()); - MOCK_METHOD2(OnBlacklistSearchSuggestion, + MOCK_METHOD2(OnBlocklistSearchSuggestion, void(int task_version, long task_id)); - MOCK_METHOD3(OnBlacklistSearchSuggestionWithHash, - void(int task_version, - long task_id, - const std::vector<uint8_t>& hash)); + MOCK_METHOD3(OnBlocklistSearchSuggestionWithHash, + void(int task_version, long task_id, const uint8_t hash[4])); + MOCK_METHOD3(OnSearchSuggestionSelected, + void(int task_version, long task_id, const uint8_t hash[4])); MOCK_METHOD0(OnOptOutOfSearchSuggestions, void()); }; @@ -117,8 +117,9 @@ MOCK_METHOD0(ShouldProcessSetCustomBackgroundURL, bool()); MOCK_METHOD0(ShouldProcessSetCustomBackgroundURLWithAttributions, bool()); MOCK_METHOD0(ShouldProcessSelectLocalBackgroundImage, bool()); - MOCK_METHOD0(ShouldProcessBlacklistSearchSuggestion, bool()); - MOCK_METHOD0(ShouldProcessBlacklistSearchSuggestionWithHash, bool()); + MOCK_METHOD0(ShouldProcessBlocklistSearchSuggestion, bool()); + MOCK_METHOD0(ShouldProcessBlocklistSearchSuggestionWithHash, bool()); + MOCK_METHOD0(ShouldProcessSearchSuggestionSelected, bool()); MOCK_METHOD0(ShouldProcessOptOutOfSearchSuggestions, bool()); MOCK_METHOD1(ShouldSendSetInputInProgress, bool(bool)); MOCK_METHOD0(ShouldSendOmniboxFocusChanged, bool()); @@ -904,39 +905,75 @@ GetSearchIPCRouter().SelectLocalBackgroundImage(); } -TEST_F(SearchIPCRouterTest, ProcessBlacklistSearchSuggestion) { +TEST_F(SearchIPCRouterTest, ProcessBlocklistSearchSuggestion) { NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); SetupMockDelegateAndPolicy(); MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); int task_version = 0; int task_id = 1234; EXPECT_CALL(*mock_delegate(), - OnBlacklistSearchSuggestion(task_version, task_id)) + OnBlocklistSearchSuggestion(task_version, task_id)) .Times(1); - EXPECT_CALL(*policy, ShouldProcessBlacklistSearchSuggestion()) + EXPECT_CALL(*policy, ShouldProcessBlocklistSearchSuggestion()) .Times(1) .WillOnce(Return(true)); - GetSearchIPCRouter().BlacklistSearchSuggestion(task_version, task_id); + GetSearchIPCRouter().BlocklistSearchSuggestion(task_version, task_id); } -TEST_F(SearchIPCRouterTest, IgnoreBlacklistSearchSuggestion) { +TEST_F(SearchIPCRouterTest, IgnoreBlocklistSearchSuggestion) { NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); SetupMockDelegateAndPolicy(); MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); int task_version = 0; int task_id = 1234; EXPECT_CALL(*mock_delegate(), - OnBlacklistSearchSuggestion(task_version, task_id)) + OnBlocklistSearchSuggestion(task_version, task_id)) .Times(0); - EXPECT_CALL(*policy, ShouldProcessBlacklistSearchSuggestion()) + EXPECT_CALL(*policy, ShouldProcessBlocklistSearchSuggestion()) .Times(1) .WillOnce(Return(false)); - GetSearchIPCRouter().BlacklistSearchSuggestion(task_version, task_id); + GetSearchIPCRouter().BlocklistSearchSuggestion(task_version, task_id); } -TEST_F(SearchIPCRouterTest, ProcessBlacklistSearchSuggestionWithHash) { +TEST_F(SearchIPCRouterTest, ProcessBlocklistSearchSuggestionWithHash) { + NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); + SetupMockDelegateAndPolicy(); + MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); + int task_version = 0; + int task_id = 1234; + std::vector<uint8_t> hash = {'a', 'b', 'c', 'd'}; + EXPECT_CALL(*mock_delegate(), OnBlocklistSearchSuggestionWithHash( + task_version, task_id, hash.data())) + .Times(1); + EXPECT_CALL(*policy, ShouldProcessBlocklistSearchSuggestionWithHash()) + .Times(1) + .WillOnce(Return(true)); + + GetSearchIPCRouter().BlocklistSearchSuggestionWithHash(task_version, task_id, + hash); +} + +TEST_F(SearchIPCRouterTest, IgnoreBlocklistSearchSuggestionWithHash) { + NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); + SetupMockDelegateAndPolicy(); + MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); + int task_version = 0; + int task_id = 1234; + std::vector<uint8_t> hash = {'a', 'b', 'c', 'd'}; + EXPECT_CALL(*mock_delegate(), OnBlocklistSearchSuggestionWithHash( + task_version, task_id, hash.data())) + .Times(0); + EXPECT_CALL(*policy, ShouldProcessBlocklistSearchSuggestionWithHash()) + .Times(1) + .WillOnce(Return(false)); + + GetSearchIPCRouter().BlocklistSearchSuggestionWithHash(task_version, task_id, + hash); +} + +TEST_F(SearchIPCRouterTest, ProcessSearchSuggestionSelected) { NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); SetupMockDelegateAndPolicy(); MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); @@ -944,17 +981,16 @@ int task_id = 1234; std::vector<uint8_t> hash = {'a', 'b', 'c', 'd'}; EXPECT_CALL(*mock_delegate(), - OnBlacklistSearchSuggestionWithHash(task_version, task_id, hash)) + OnSearchSuggestionSelected(task_version, task_id, hash.data())) .Times(1); - EXPECT_CALL(*policy, ShouldProcessBlacklistSearchSuggestionWithHash()) + EXPECT_CALL(*policy, ShouldProcessSearchSuggestionSelected()) .Times(1) .WillOnce(Return(true)); - GetSearchIPCRouter().BlacklistSearchSuggestionWithHash(task_version, task_id, - hash); + GetSearchIPCRouter().SearchSuggestionSelected(task_version, task_id, hash); } -TEST_F(SearchIPCRouterTest, IgnoreBlacklistSearchSuggestionWithHash) { +TEST_F(SearchIPCRouterTest, IgnoreSearchSuggestionSelected) { NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); SetupMockDelegateAndPolicy(); MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); @@ -962,14 +998,13 @@ int task_id = 1234; std::vector<uint8_t> hash = {'a', 'b', 'c', 'd'}; EXPECT_CALL(*mock_delegate(), - OnBlacklistSearchSuggestionWithHash(task_version, task_id, hash)) + OnSearchSuggestionSelected(task_version, task_id, hash.data())) .Times(0); - EXPECT_CALL(*policy, ShouldProcessBlacklistSearchSuggestionWithHash()) + EXPECT_CALL(*policy, ShouldProcessSearchSuggestionSelected()) .Times(1) .WillOnce(Return(false)); - GetSearchIPCRouter().BlacklistSearchSuggestionWithHash(task_version, task_id, - hash); + GetSearchIPCRouter().SearchSuggestionSelected(task_version, task_id, hash); } TEST_F(SearchIPCRouterTest, ProcessOptOutOfSearchSuggestions) {
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc index 4c297a6..2d6d9fd 100644 --- a/chrome/browser/ui/search/search_tab_helper.cc +++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -461,21 +461,29 @@ return browser->window()->GetLocationBar()->GetOmniboxView(); } -void SearchTabHelper::OnBlacklistSearchSuggestion(int task_version, +void SearchTabHelper::OnBlocklistSearchSuggestion(int task_version, long task_id) { if (search_suggest_service_) - search_suggest_service_->BlacklistSearchSuggestion(task_version, task_id); + search_suggest_service_->BlocklistSearchSuggestion(task_version, task_id); } -void SearchTabHelper::OnBlacklistSearchSuggestionWithHash( +void SearchTabHelper::OnBlocklistSearchSuggestionWithHash( int task_version, long task_id, - const std::vector<uint8_t>& hash) { + const uint8_t hash[4]) { if (search_suggest_service_) - search_suggest_service_->BlacklistSearchSuggestionWithHash(task_version, + search_suggest_service_->BlocklistSearchSuggestionWithHash(task_version, task_id, hash); } +void SearchTabHelper::OnSearchSuggestionSelected(int task_version, + long task_id, + const uint8_t hash[4]) { + if (search_suggest_service_) + search_suggest_service_->SearchSuggestionSelected(task_version, task_id, + hash); +} + void SearchTabHelper::OnOptOutOfSearchSuggestions() { if (search_suggest_service_) search_suggest_service_->OptOutOfSearchSuggestions();
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h index 591257b..3d0d1003 100644 --- a/chrome/browser/ui/search/search_tab_helper.h +++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -124,11 +124,13 @@ const std::string& attribution_line_2, const GURL& action_url) override; void OnSelectLocalBackgroundImage() override; - void OnBlacklistSearchSuggestion(int task_version, long task_id) override; - void OnBlacklistSearchSuggestionWithHash( - int task_version, - long task_id, - const std::vector<uint8_t>& hash) override; + void OnBlocklistSearchSuggestion(int task_version, long task_id) override; + void OnBlocklistSearchSuggestionWithHash(int task_version, + long task_id, + const uint8_t hash[4]) override; + void OnSearchSuggestionSelected(int task_version, + long task_id, + const uint8_t hash[4]) override; void OnOptOutOfSearchSuggestions() override; // Overridden from InstantServiceObserver:
diff --git a/chrome/browser/ui/serial/serial_chooser_controller.cc b/chrome/browser/ui/serial/serial_chooser_controller.cc index 0da4f077..3786b91 100644 --- a/chrome/browser/ui/serial/serial_chooser_controller.cc +++ b/chrome/browser/ui/serial/serial_chooser_controller.cc
@@ -10,30 +10,13 @@ #include "base/files/file_path.h" #include "base/strings/utf_string_conversions.h" #include "base/unguessable_token.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/serial/serial_chooser_context.h" +#include "chrome/browser/serial/serial_chooser_context_factory.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/service_manager_connection.h" -#include "services/device/public/mojom/constants.mojom.h" -#include "services/service_manager/public/cpp/connector.h" #include "ui/base/l10n/l10n_util.h" -namespace { - -blink::mojom::SerialPortInfoPtr ToBlinkType( - const device::mojom::SerialPortInfo& port) { - auto info = blink::mojom::SerialPortInfo::New(); - info->token = port.token; - info->has_vendor_id = port.has_vendor_id; - if (port.has_vendor_id) - info->vendor_id = port.vendor_id; - info->has_product_id = port.has_product_id; - if (port.has_product_id) - info->product_id = port.product_id; - return info; -} - -} // namespace - SerialChooserController::SerialChooserController( content::RenderFrameHost* render_frame_host, std::vector<blink::mojom::SerialPortFilterPtr> filters, @@ -43,15 +26,18 @@ IDS_SERIAL_PORT_CHOOSER_PROMPT_EXTENSION_NAME), filters_(std::move(filters)), callback_(std::move(callback)) { - DCHECK(content::ServiceManagerConnection::GetForProcess()); - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(device::mojom::kServiceName, - mojo::MakeRequest(&port_manager_)); - port_manager_.set_connection_error_handler(base::BindOnce( - &SerialChooserController::OnGetDevices, base::Unretained(this), - std::vector<device::mojom::SerialPortInfoPtr>())); - port_manager_->GetDevices(base::BindOnce( + auto* web_contents = + content::WebContents::FromRenderFrameHost(render_frame_host); + requesting_origin_ = render_frame_host->GetLastCommittedOrigin(); + embedding_origin_ = web_contents->GetMainFrame()->GetLastCommittedOrigin(); + + auto* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + chooser_context_ = + SerialChooserContextFactory::GetForProfile(profile)->AsWeakPtr(); + DCHECK(chooser_context_); + + chooser_context_->GetPortManager()->GetDevices(base::BindOnce( &SerialChooserController::OnGetDevices, base::Unretained(this))); } @@ -92,7 +78,13 @@ } bool SerialChooserController::IsPaired(size_t index) const { - return false; + DCHECK_LE(index, ports_.size()); + + if (!chooser_context_) + return false; + + return chooser_context_->HasPortPermission(requesting_origin_, + embedding_origin_, *ports_[index]); } void SerialChooserController::Select(const std::vector<size_t>& indices) { @@ -100,8 +92,14 @@ size_t index = indices[0]; DCHECK_LT(index, ports_.size()); - const device::mojom::SerialPortInfo& port = *ports_[index]; - std::move(callback_).Run(ToBlinkType(port)); + if (!chooser_context_) { + std::move(callback_).Run(nullptr); + return; + } + + chooser_context_->GrantPortPermission(requesting_origin_, embedding_origin_, + *ports_[index]); + std::move(callback_).Run(std::move(ports_[index])); } void SerialChooserController::Cancel() {}
diff --git a/chrome/browser/ui/serial/serial_chooser_controller.h b/chrome/browser/ui/serial/serial_chooser_controller.h index 92c44d7..8e654bb 100644 --- a/chrome/browser/ui/serial/serial_chooser_controller.h +++ b/chrome/browser/ui/serial/serial_chooser_controller.h
@@ -15,12 +15,14 @@ #include "content/public/browser/serial_chooser.h" #include "services/device/public/mojom/serial.mojom.h" #include "third_party/blink/public/mojom/serial/serial.mojom.h" -#include "url/gurl.h" +#include "url/origin.h" namespace content { class RenderFrameHost; } // namespace content +class SerialChooserContext; + // SerialChooserController provides data for the Serial API permission prompt. // It is owned by ChooserBubbleDelegate. class SerialChooserController : public ChooserController { @@ -48,8 +50,10 @@ std::vector<blink::mojom::SerialPortFilterPtr> filters_; content::SerialChooser::Callback callback_; + url::Origin requesting_origin_; + url::Origin embedding_origin_; - device::mojom::SerialPortManagerPtr port_manager_; + base::WeakPtr<SerialChooserContext> chooser_context_; std::vector<device::mojom::SerialPortInfoPtr> ports_; DISALLOW_COPY_AND_ASSIGN(SerialChooserController);
diff --git a/chrome/browser/ui/views/autofill/dialog_view_ids.h b/chrome/browser/ui/views/autofill/dialog_view_ids.h index eb7d8ac..3a9b2be 100644 --- a/chrome/browser/ui/views/autofill/dialog_view_ids.h +++ b/chrome/browser/ui/views/autofill/dialog_view_ids.h
@@ -8,17 +8,21 @@ #include "components/autofill/core/browser/field_types.h" // This defines an enumeration of IDs that can uniquely identify a view within -// the scope of the local and upload credit card save bubbles. +// the scope of the local and upload credit card save bubbles as well as the +// local card migration bubble and dialogs. namespace autofill { enum DialogViewId : int { VIEW_ID_NONE = 0, - // The following are the important containing views of the bubble. - MAIN_CONTENT_VIEW_LOCAL, // The main content view, for a local save bubble - MAIN_CONTENT_VIEW_UPLOAD, // The main content view, for an upload save bubble - FOOTNOTE_VIEW, // Contains the legal messages for upload save + // The following views are contained in SaveCardBubbleViews. + MAIN_CONTENT_VIEW_LOCAL, // The main content view for a local + // save bubble + MAIN_CONTENT_VIEW_UPLOAD, // The main content view for an upload + // save bubble + FOOTNOTE_VIEW, // The footnote view of either an upload + // save bubble or a manage cards view. SIGN_IN_PROMO_VIEW, // Contains the sign-in promo view MANAGE_CARDS_VIEW, // The manage cards view EXPIRATION_DATE_VIEW, // Contains the dropdowns for expiration date @@ -26,6 +30,12 @@ // The sub-view that contains the sign-in button in the promo. SIGN_IN_VIEW, + // The main content view for a migration offer bubble. + MAIN_CONTENT_VIEW_MIGRATION_BUBBLE, + + // The main content view for the main migration dialog. + MAIN_CONTENT_VIEW_MIGRATION_OFFER_DIALOG, + // The following are views::LabelButton objects (clickable). OK_BUTTON, // Can say [Save], [Next], [Confirm], // or [Done] depending on context
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc b/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc new file mode 100644 index 0000000..4f60dea4 --- /dev/null +++ b/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
@@ -0,0 +1,673 @@ +// 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 <ctime> +#include <list> +#include <memory> +#include <string> +#include <utility> + +#include "base/callback_list.h" +#include "base/command_line.h" +#include "base/macros.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/autofill/autofill_uitest_util.h" +#include "chrome/browser/signin/account_fetcher_service_factory.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" +#include "chrome/browser/signin/fake_account_fetcher_service_builder.h" +#include "chrome/browser/signin/fake_signin_manager_builder.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" +#include "chrome/browser/sync/test/integration/sync_test.h" +#include "chrome/browser/ui/autofill/chrome_autofill_client.h" +#include "chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h" +#include "chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h" +#include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/location_bar/location_bar.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/views/autofill/dialog_view_ids.h" +#include "chrome/browser/ui/views/autofill/local_card_migration_bubble_views.h" +#include "chrome/browser/ui/views/autofill/local_card_migration_dialog_view.h" +#include "chrome/browser/ui/views/autofill/local_card_migration_icon_view.h" +#include "chrome/browser/ui/views/autofill/save_card_bubble_views.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/credit_card_save_manager.h" +#include "components/autofill/core/browser/form_data_importer.h" +#include "components/autofill/core/browser/local_card_migration_manager.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/test_event_waiter.h" +#include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_prefs.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/network_session_configurator/common/network_switches.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/fake_account_fetcher_service.h" +#include "components/sync/test/fake_server/fake_server.h" +#include "components/sync/test/fake_server/fake_server_network_resources.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_navigation_observer.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "services/device/public/cpp/test/scoped_geolocation_overrider.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/identity_test_utils.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/base_event_utils.h" +#include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/test/widget_test.h" +#include "ui/views/window/dialog_client_view.h" + +using base::Bucket; +using testing::ElementsAre; + +namespace autofill { + +namespace { + +constexpr char kURLGetUploadDetailsRequest[] = + "https://payments.google.com/payments/apis/chromepaymentsservice/" + "getdetailsforsavecard"; +constexpr char kResponseGetUploadDetailsSuccess[] = + "{\"legal_message\":{\"line\":[{\"template\":\"Legal message template with " + "link: " + "{0}.\",\"template_parameter\":[{\"display_text\":\"Link\",\"url\":\"https:" + "//www.example.com/\"}]}]},\"context_token\":\"dummy_context_token\"}"; +constexpr char kResponseGetUploadDetailsFailure[] = + "{\"error\":{\"code\":\"FAILED_PRECONDITION\",\"user_error_message\":\"An " + "unexpected error has occurred. Please try again later.\"}}"; + +constexpr char kCreditCardFormURL[] = + "/credit_card_upload_form_address_and_cc.html"; + +constexpr char kFirstCardNumber[] = "5428424047572420"; // Mastercard +constexpr char kSecondCardNumber[] = "4782187095085933"; // Visa + +constexpr double kFakeGeolocationLatitude = 1.23; +constexpr double kFakeGeolocationLongitude = 4.56; + +} // namespace + +class LocalCardMigrationBrowserTest + : public SyncTest, + public LocalCardMigrationManager::ObserverForTest { + protected: + // Various events that can be waited on by the DialogEventWaiter. + enum class DialogEvent : int { + REQUESTED_LOCAL_CARD_MIGRATION, + RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + SENT_MIGRATE_CARDS_REQUEST, + RECEIVED_MIGRATE_CARDS_RESPONSE + }; + + LocalCardMigrationBrowserTest() : SyncTest(SINGLE_CLIENT) {} + + ~LocalCardMigrationBrowserTest() override {} + + void SetUpOnMainThread() override { + SyncTest::SetUpOnMainThread(); + + // Set up the HTTPS server (uses the embedded_test_server). + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + embedded_test_server()->ServeFilesFromSourceDirectory( + "components/test/data/autofill"); + embedded_test_server()->StartAcceptingConnections(); + + ProfileSyncServiceFactory::GetForProfile(browser()->profile()) + ->OverrideNetworkResourcesForTest( + std::make_unique<fake_server::FakeServerNetworkResources>( + GetFakeServer()->AsWeakPtr())); + + std::string username; +#if defined(OS_CHROMEOS) + // In ChromeOS browser tests, the profile may already by authenticated with + // stub account |user_manager::kStubUserEmail|. + AccountInfo info = + IdentityManagerFactory::GetForProfile(browser()->profile()) + ->GetPrimaryAccountInfo(); + username = info.email; +#endif + if (username.empty()) + username = "user@gmail.com"; + + harness_ = ProfileSyncServiceHarness::Create( + browser()->profile(), username, "password", + ProfileSyncServiceHarness::SigninType::FAKE_SIGNIN); + + // Set up the URL loader factory for the payments client so we can intercept + // those network requests too. + test_shared_loader_factory_ = + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_); + ContentAutofillDriver::GetForRenderFrameHost( + GetActiveWebContents()->GetMainFrame()) + ->autofill_manager() + ->client() + ->GetPaymentsClient() + ->set_url_loader_factory_for_testing(test_shared_loader_factory_); + + // Set up this class as the ObserverForTest implementation. + LocalCardMigrationManager* local_card_migration_manager = + ContentAutofillDriver::GetForRenderFrameHost( + GetActiveWebContents()->GetMainFrame()) + ->autofill_manager() + ->client() + ->GetFormDataImporter() + ->local_card_migration_manager_.get(); + + local_card_migration_manager->SetEventObserverForTesting(this); + + // Set up the fake geolocation data. + geolocation_overrider_ = + std::make_unique<device::ScopedGeolocationOverrider>( + kFakeGeolocationLatitude, kFakeGeolocationLongitude); + + // Set up billing customer ID. + ContentAutofillDriver::GetForRenderFrameHost( + GetActiveWebContents()->GetMainFrame()) + ->autofill_manager() + ->client() + ->GetPrefs() + ->SetDouble(prefs::kAutofillBillingCustomerNumber, 1234); + + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); + ASSERT_TRUE(harness_->SetupSync()); + SetUploadDetailsRpcPaymentsAccepts(); + } + + void NavigateTo(const std::string& file_path) { + ui_test_utils::NavigateToURL( + browser(), file_path.find("data:") == 0U + ? GURL(file_path) + : embedded_test_server()->GetURL(file_path)); + } + + void OnDecideToRequestLocalCardMigration() override { + if (event_waiter_) + event_waiter_->OnEvent(DialogEvent::REQUESTED_LOCAL_CARD_MIGRATION); + } + + void OnReceivedGetUploadDetailsResponse() override { + if (event_waiter_) + event_waiter_->OnEvent(DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE); + } + + void OnSentMigrateCardsRequest() override { + if (event_waiter_) + event_waiter_->OnEvent(DialogEvent::SENT_MIGRATE_CARDS_REQUEST); + } + + void OnReceivedMigrateCardsResponse() override { + if (event_waiter_) + event_waiter_->OnEvent(DialogEvent::RECEIVED_MIGRATE_CARDS_RESPONSE); + } + + void SaveLocalCard(std::string card_number) { + CreditCard local_card; + test::SetCreditCardInfo(&local_card, "John Smith", card_number.c_str(), + "12", test::NextYear().c_str(), "1"); + local_card.set_guid("00000000-0000-0000-0000-" + card_number.substr(0, 12)); + local_card.set_record_type(CreditCard::LOCAL_CARD); + AddTestCreditCard(browser(), local_card); + } + + void SaveServerCard(std::string card_number) { + CreditCard server_card; + test::SetCreditCardInfo(&server_card, "John Smith", card_number.c_str(), + "12", test::NextYear().c_str(), "1"); + server_card.set_guid("00000000-0000-0000-0000-" + + card_number.substr(0, 12)); + server_card.set_record_type(CreditCard::FULL_SERVER_CARD); + server_card.set_server_id("full_id_" + card_number); + AddTestServerCreditCard(browser(), server_card); + } + + void UseCardAndWaitForMigrationOffer(std::string card_number) { + // Reusing a card should show the migration offer bubble. + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_LOCAL_CARD_MIGRATION, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + FillAndSubmitFormWithCard(card_number); + WaitForObservedEvent(); + } + + void FillAndSubmitFormWithCard(std::string card_number) { + NavigateTo(kCreditCardFormURL); + content::WebContents* web_contents = GetActiveWebContents(); + + const std::string click_fill_button_js = + "(function() { document.getElementById('fill_form').click(); })();"; + ASSERT_TRUE(content::ExecuteScript(web_contents, click_fill_button_js)); + + const std::string fill_cc_number_js = + "(function() { document.getElementsByName(\"cc_number\")[0].value = " + + card_number + "; })();"; + ASSERT_TRUE(content::ExecuteScript(web_contents, fill_cc_number_js)); + + const std::string click_submit_button_js = + "(function() { document.getElementById('submit').click(); })();"; + content::TestNavigationObserver nav_observer(web_contents); + ASSERT_TRUE(content::ExecuteScript(web_contents, click_submit_button_js)); + nav_observer.Wait(); + } + + void SetUploadDetailsRpcPaymentsAccepts() { + test_url_loader_factory()->AddResponse(kURLGetUploadDetailsRequest, + kResponseGetUploadDetailsSuccess); + } + + void SetUploadDetailsRpcPaymentsDeclines() { + test_url_loader_factory()->AddResponse(kURLGetUploadDetailsRequest, + kResponseGetUploadDetailsFailure); + } + + void ClickOnView(views::View* view) { + DCHECK(view); + ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + view->OnMousePressed(pressed); + ui::MouseEvent released_event = + ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + view->OnMouseReleased(released_event); + } + + void ClickOnDialogViewAndWait( + views::View* view, + views::DialogDelegateView* local_card_migration_view) { + DCHECK(local_card_migration_view); + views::test::WidgetDestroyedWaiter destroyed_waiter( + local_card_migration_view->GetWidget()); + local_card_migration_view->GetDialogClientView() + ->ResetViewShownTimeStampForTesting(); + views::BubbleFrameView* bubble_frame_view = + static_cast<views::BubbleFrameView*>( + local_card_migration_view->GetWidget() + ->non_client_view() + ->frame_view()); + bubble_frame_view->ResetViewShownTimeStampForTesting(); + ClickOnView(view); + destroyed_waiter.Wait(); + } + + views::View* FindViewInDialogById( + DialogViewId view_id, + views::DialogDelegateView* local_card_migration_view) { + DCHECK(local_card_migration_view); + + views::View* specified_view = + local_card_migration_view->GetViewByID(static_cast<int>(view_id)); + + if (!specified_view) { + specified_view = + local_card_migration_view->GetDialogClientView()->GetViewByID( + static_cast<int>(view_id)); + } + + return specified_view; + } + + void ClickOnOkButton(views::DialogDelegateView* local_card_migration_view) { + views::View* ok_button = + local_card_migration_view->GetDialogClientView()->ok_button(); + + ClickOnDialogViewAndWait(ok_button, local_card_migration_view); + } + + void ClickOnCancelButton( + views::DialogDelegateView* local_card_migration_view) { + views::View* cancel_button = + local_card_migration_view->GetDialogClientView()->cancel_button(); + ClickOnDialogViewAndWait(cancel_button, local_card_migration_view); + } + + views::DialogDelegateView* GetLocalCardMigrationOfferBubbleViews() { + LocalCardMigrationBubbleControllerImpl* + local_card_migration_bubble_controller_impl = + LocalCardMigrationBubbleControllerImpl::FromWebContents( + GetActiveWebContents()); + if (!local_card_migration_bubble_controller_impl) + return nullptr; + return static_cast<LocalCardMigrationBubbleViews*>( + local_card_migration_bubble_controller_impl + ->local_card_migration_bubble_view()); + } + + views::DialogDelegateView* GetLocalCardMigrationMainDialogView() { + LocalCardMigrationDialogControllerImpl* + local_card_migration_dialog_controller_impl = + LocalCardMigrationDialogControllerImpl::FromWebContents( + GetActiveWebContents()); + if (!local_card_migration_dialog_controller_impl) + return nullptr; + return static_cast<LocalCardMigrationDialogView*>( + local_card_migration_dialog_controller_impl + ->local_card_migration_dialog_view()); + } + + LocalCardMigrationIconView* GetLocalCardMigrationIconView() { + if (!browser()) + return nullptr; + LocationBarView* location_bar_view = + static_cast<LocationBarView*>(browser()->window()->GetLocationBar()); + DCHECK(location_bar_view->local_card_migration_icon_view()); + return location_bar_view->local_card_migration_icon_view(); + } + + views::View* GetCloseButton() { + LocalCardMigrationBubbleViews* local_card_migration_bubble_views = + static_cast<LocalCardMigrationBubbleViews*>( + GetLocalCardMigrationOfferBubbleViews()); + DCHECK(local_card_migration_bubble_views); + return local_card_migration_bubble_views->GetBubbleFrameView() + ->GetCloseButtonForTest(); + } + + views::View* GetCardListView() { + return static_cast<LocalCardMigrationDialogView*>( + GetLocalCardMigrationMainDialogView()) + ->card_list_view_; + } + + content::WebContents* GetActiveWebContents() { + return browser()->tab_strip_model()->GetActiveWebContents(); + } + + void ResetEventWaiterForSequence(std::list<DialogEvent> event_sequence) { + event_waiter_ = + std::make_unique<EventWaiter<DialogEvent>>(std::move(event_sequence)); + } + + void WaitForObservedEvent() { event_waiter_->Wait(); } + + network::TestURLLoaderFactory* test_url_loader_factory() { + return &test_url_loader_factory_; + } + + std::unique_ptr< + base::CallbackList<void(content::BrowserContext*)>::Subscription> + will_create_browser_context_services_subscription_; + + base::test::ScopedFeatureList scoped_feature_list_; + + std::unique_ptr<ProfileSyncServiceHarness> harness_; + + private: + std::unique_ptr<autofill::EventWaiter<DialogEvent>> event_waiter_; + std::unique_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_; + network::TestURLLoaderFactory test_url_loader_factory_; + scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; + std::unique_ptr<device::ScopedGeolocationOverrider> geolocation_overrider_; + + DISALLOW_COPY_AND_ASSIGN(LocalCardMigrationBrowserTest); +}; + +// Ensures that migration is not offered when user saves a new card. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + UsingNewCardDoesNotShowIntermediateMigrationOffer) { + base::HistogramTester histogram_tester; + + SaveLocalCard(kFirstCardNumber); + FillAndSubmitFormWithCard(kSecondCardNumber); + + // No migration bubble should be showing, because the single card upload + // bubble should be displayed instead. + EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews()); + // No metrics are recorded when migration is not offered. + histogram_tester.ExpectTotalCount( + "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0); +} + +// Ensures that migration is not offered when payments declines the cards. +IN_PROC_BROWSER_TEST_F( + LocalCardMigrationBrowserTest, + IntermediateMigrationOfferDoesNotShowWhenPaymentsDeclines) { + base::HistogramTester histogram_tester; + SetUploadDetailsRpcPaymentsDeclines(); + + SaveLocalCard(kFirstCardNumber); + SaveLocalCard(kSecondCardNumber); + FillAndSubmitFormWithCard(kFirstCardNumber); + + // No bubble should be showing. + EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews()); + // No metrics are recorded when migration is not offered. + histogram_tester.ExpectTotalCount( + "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0); +} + +// Ensures that the intermediate migration bubble is not shown after reusing +// a saved server card, if there are no other cards to migrate. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + ReusingServerCardDoesNotShowIntermediateMigrationOffer) { + base::HistogramTester histogram_tester; + + SaveServerCard(kFirstCardNumber); + FillAndSubmitFormWithCard(kFirstCardNumber); + + // No bubble should be showing. + EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews()); + // No metrics are recorded when migration is not offered. + histogram_tester.ExpectTotalCount( + "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0); +} + +// Ensures that the intermediate migration bubble is not shown after reusing +// a previously saved local card, if there are no other cards to migrate. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + ReusingLocalCardDoesNotShowIntermediateMigrationOffer) { + base::HistogramTester histogram_tester; + + SaveLocalCard(kFirstCardNumber); + FillAndSubmitFormWithCard(kFirstCardNumber); + + // No migration bubble should be showing, because the single card upload + // bubble should be displayed instead. + EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews()); + // No metrics are recorded when migration is not offered. + histogram_tester.ExpectTotalCount( + "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0); +} + +// Ensures that the intermediate migration bubble is triggered after reusing +// a saved local card, if there are multiple local cards available to migrate. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + ReusingLocalCardShowsIntermediateMigrationOffer) { + base::HistogramTester histogram_tester; + + SaveLocalCard(kFirstCardNumber); + SaveLocalCard(kSecondCardNumber); + UseCardAndWaitForMigrationOffer(kFirstCardNumber); + + // The intermediate migration bubble should show. + EXPECT_TRUE( + FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE, + GetLocalCardMigrationOfferBubbleViews()) + ->visible()); + // Metrics + EXPECT_THAT( + histogram_tester.GetAllSamples( + "Autofill.LocalCardMigrationBubbleOffer.FirstShow"), + ElementsAre( + Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_REQUESTED, 1), + Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, 1))); + histogram_tester.ExpectUniqueSample( + "Autofill.LocalCardMigrationOrigin.UseOfLocalCard", + AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1); +} + +// Ensures that clicking [X] on the offer bubble makes the bubble disappear. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + ClickingCloseClosesBubble) { + base::HistogramTester histogram_tester; + + SaveLocalCard(kFirstCardNumber); + SaveLocalCard(kSecondCardNumber); + UseCardAndWaitForMigrationOffer(kFirstCardNumber); + ClickOnDialogViewAndWait(GetCloseButton(), + GetLocalCardMigrationOfferBubbleViews()); + + // No bubble should be showing. + EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews()); + // Metrics + histogram_tester.ExpectUniqueSample( + "Autofill.LocalCardMigrationOrigin.UseOfLocalCard", + AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1); +} + +// Ensures that clicking on the credit card icon in the omnibox reopens the +// offer bubble after closing it. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + ClickingOmniboxIconReshowsBubble) { + base::HistogramTester histogram_tester; + + SaveLocalCard(kFirstCardNumber); + SaveLocalCard(kSecondCardNumber); + UseCardAndWaitForMigrationOffer(kFirstCardNumber); + ClickOnDialogViewAndWait(GetCloseButton(), + GetLocalCardMigrationOfferBubbleViews()); + ClickOnView(GetLocalCardMigrationIconView()); + + // Clicking the icon should reshow the bubble. + EXPECT_TRUE( + FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE, + GetLocalCardMigrationOfferBubbleViews()) + ->visible()); + // Metrics + EXPECT_THAT( + histogram_tester.GetAllSamples( + "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"), + ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1))); + EXPECT_THAT( + histogram_tester.GetAllSamples( + "Autofill.LocalCardMigrationBubbleOffer.Reshows"), + ElementsAre( + Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_REQUESTED, 1), + Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, 1))); +} + +// Ensures that accepting the intermediate migration offer opens up the main +// migration dialog. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + ClickingContinueOpensDialog) { + base::HistogramTester histogram_tester; + + SaveLocalCard(kFirstCardNumber); + SaveLocalCard(kSecondCardNumber); + UseCardAndWaitForMigrationOffer(kFirstCardNumber); + // Click the [Continue] button. + ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews()); + + // Dialog should be visible. + EXPECT_TRUE(FindViewInDialogById( + DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_OFFER_DIALOG, + GetLocalCardMigrationMainDialogView()) + ->visible()); + // Intermediate bubble should be gone. + EXPECT_EQ(nullptr, GetLocalCardMigrationOfferBubbleViews()); + // Metrics + EXPECT_THAT( + histogram_tester.GetAllSamples( + "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"), + ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1), + Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 1), + Bucket(AutofillMetrics::MAIN_DIALOG_SHOWN, 1))); + histogram_tester.ExpectUniqueSample( + "Autofill.LocalCardMigrationBubbleUserInteraction.FirstShow", + AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_CLOSED_ACCEPTED, 1); + histogram_tester.ExpectUniqueSample( + "Autofill.LocalCardMigrationDialogOffer", + AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_SHOWN, 1); +} + +// Ensures that rejecting the main migration dialog closes the dialog. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + ClickingCancelClosesDialog) { + base::HistogramTester histogram_tester; + + SaveLocalCard(kFirstCardNumber); + SaveLocalCard(kSecondCardNumber); + UseCardAndWaitForMigrationOffer(kFirstCardNumber); + // Click the [Continue] button. + ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews()); + // Click the [Cancel] button. + ClickOnCancelButton(GetLocalCardMigrationMainDialogView()); + + // No dialog should be showing. + EXPECT_EQ(nullptr, GetLocalCardMigrationMainDialogView()); + // Metrics + EXPECT_THAT( + histogram_tester.GetAllSamples( + "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"), + ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1), + Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 1), + Bucket(AutofillMetrics::MAIN_DIALOG_SHOWN, 1))); + histogram_tester.ExpectUniqueSample( + "Autofill.LocalCardMigrationDialogUserInteraction", + AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_CLOSED_CANCEL_BUTTON_CLICKED, + 1); +} + +// Ensures that accepting the main migration dialog closes the dialog. +IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest, + ClickingSaveClosesDialog) { + base::HistogramTester histogram_tester; + + SaveLocalCard(kFirstCardNumber); + SaveLocalCard(kSecondCardNumber); + UseCardAndWaitForMigrationOffer(kFirstCardNumber); + // Click the [Continue] button in the bubble. + ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews()); + // Click the [Save] button in the dialog. + // TODO(crbug.com/897998): Add Payments Rpc setup and event waiter. + ClickOnOkButton(GetLocalCardMigrationMainDialogView()); + + // No dialog should be showing. + EXPECT_EQ(nullptr, GetLocalCardMigrationMainDialogView()); + // Metrics + EXPECT_THAT( + histogram_tester.GetAllSamples( + "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"), + ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1), + Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 1), + Bucket(AutofillMetrics::MAIN_DIALOG_SHOWN, 1), + Bucket(AutofillMetrics::MAIN_DIALOG_ACCEPTED, 1))); + histogram_tester.ExpectUniqueSample( + "Autofill.LocalCardMigrationDialogUserInteraction", + AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_CLOSED_SAVE_BUTTON_CLICKED, + 1); +} + +// TODO(crbug.com/897998): Add these following tests. +// 1) Reusing a server card shows the intermediate bubble. +// 2) All valid cards are visible in the migration offer view. +// 3) Local cards should get deleted after migration. +// 4) Expired and invalid cards should not be shown. +// 5) When user navigates away after five seconds, the bubble disappears. +// 6) When user navigates away after five seconds, the dialog should stay. +// 7) When user clicks legal message links, browser should show a pop-up window. +// 8) Simulate checkboxes to ensure +// LocalCardMigrationDialogUserSelectionPercentage is logged correctly. +// 9) Ensure LocalCardMigrationDialogActiveDuration is logged correctly. + +} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc b/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc index b2cfc02..472062fe 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc
@@ -6,6 +6,7 @@ #include <stddef.h> #include <memory> +#include <utility> #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -29,6 +30,7 @@ #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/style/typography.h" +#include "ui/views/window/dialog_client_view.h" namespace autofill { @@ -154,6 +156,7 @@ explanatory_message->SetHorizontalAlignment(gfx::ALIGN_LEFT); explanatory_message->SetMultiLine(true); AddChildView(explanatory_message); + set_id(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE); } } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.h b/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.h index 80b3503d..aa0f787 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.h +++ b/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.h
@@ -47,6 +47,8 @@ void WindowClosing() override; private: + friend class LocalCardMigrationBrowserTest; + ~LocalCardMigrationBubbleViews() override; // views::BubbleDialogDelegateView:
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc index 84b0331..3ce85b2 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc
@@ -4,6 +4,10 @@ #include "chrome/browser/ui/views/autofill/local_card_migration_dialog_view.h" +#include <memory> +#include <string> +#include <vector> + #include "base/i18n/message_formatter.h" #include "base/location.h" #include "base/macros.h" @@ -311,6 +315,8 @@ } private: + friend class LocalCardMigrationDialogView; + LocalCardMigrationDialogController* controller_; views::View* card_list_view_ = nullptr; @@ -467,6 +473,8 @@ if (view_state == LocalCardMigrationDialogState::kOffered) { offer_view_ = new LocalCardMigrationOfferView(controller_, this); + offer_view_->set_id(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_OFFER_DIALOG); + card_list_view_ = offer_view_->card_list_view_; AddChildView(offer_view_); } else { AddChildView(CreateFeedbackContentView(controller_, this).release());
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.h b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.h index 4b2759b..5f559cd 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.h +++ b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.h
@@ -51,7 +51,10 @@ void UpdateLayout(); private: + friend class LocalCardMigrationBrowserTest; + void ConstructView(); + base::string16 GetOkButtonLabel() const; base::string16 GetCancelButtonLabel() const; @@ -63,6 +66,10 @@ // dialog is not in the 'offer' state. LocalCardMigrationOfferView* offer_view_ = nullptr; + // The view containing a list of cards. It is the content of the scroll bar. + // Owned by the LocalCardMigrationOfferView. + views::View* card_list_view_; + DISALLOW_COPY_AND_ASSIGN(LocalCardMigrationDialogView); };
diff --git a/chrome/browser/ui/views/tabs/glow_hover_controller.cc b/chrome/browser/ui/views/tabs/glow_hover_controller.cc index 2dcf1d4..681db8d 100644 --- a/chrome/browser/ui/views/tabs/glow_hover_controller.cc +++ b/chrome/browser/ui/views/tabs/glow_hover_controller.cc
@@ -40,15 +40,15 @@ subtle_opacity_scale_ = opacity_scale; } -void GlowHoverController::Show(Style style) { +void GlowHoverController::Show(ShowStyle style) { switch (style) { - case SUBTLE: + case ShowStyle::kSubtle: opacity_scale_ = subtle_opacity_scale_; animation_.SetSlideDuration(kTrackHoverDurationMs); animation_.SetTweenType(gfx::Tween::EASE_OUT); animation_.Show(); break; - case PRONOUNCED: + case ShowStyle::kPronounced: opacity_scale_ = kPronouncedOpacityScale; // Force the end state to show immediately. animation_.Show(); @@ -57,15 +57,18 @@ } } -void GlowHoverController::Hide() { - animation_.SetTweenType(gfx::Tween::EASE_IN); - animation_.Hide(); -} - -void GlowHoverController::HideImmediately() { - if (ShouldDraw()) - view_->SchedulePaint(); - animation_.Reset(); +void GlowHoverController::Hide(HideStyle style) { + switch (style) { + case HideStyle::kGradual: + animation_.SetTweenType(gfx::Tween::EASE_IN); + animation_.Hide(); + break; + case HideStyle::kImmediate: + if (ShouldDraw()) + view_->SchedulePaint(); + animation_.Reset(); + break; + } } double GlowHoverController::GetAnimationValue() const {
diff --git a/chrome/browser/ui/views/tabs/glow_hover_controller.h b/chrome/browser/ui/views/tabs/glow_hover_controller.h index 7fcc29d..d95b558 100644 --- a/chrome/browser/ui/views/tabs/glow_hover_controller.h +++ b/chrome/browser/ui/views/tabs/glow_hover_controller.h
@@ -27,7 +27,12 @@ // invokes SchedulePaint() back on the View as necessary. class GlowHoverController : public gfx::AnimationDelegate { public: - enum Style { SUBTLE, PRONOUNCED }; + enum class ShowStyle { kSubtle, kPronounced }; + + enum class HideStyle { + kGradual, // The hover should fade out. + kImmediate, // The hover should cut off, with no fade out. + }; explicit GlowHoverController(views::View* view); ~GlowHoverController() override; @@ -45,13 +50,10 @@ const gfx::Point& location() const { return location_; } // Initiates showing the hover. - void Show(Style style); + void Show(ShowStyle style); // Hides the hover. - void Hide(); - - // Hides the hover immediately. - void HideImmediately(); + void Hide(HideStyle); // Returns the value of the animation. double GetAnimationValue() const;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index d06bc67b..ae914a7 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -91,9 +91,6 @@ // transitioning a tab from normal to pinned tab. constexpr int kPinnedTabExtraWidthToRenderAsNormal = 30; -// Opacity of the active tab background painted over inactive selected tabs. -constexpr float kSelectedTabOpacity = 0.75f; - // Helper functions ------------------------------------------------------------ // Returns the coordinate for an object of size |item_size| centered in a region @@ -121,10 +118,7 @@ Tab::Tab(TabController* controller) : controller_(controller), title_(new views::Label()), - title_animation_(this), - hover_controller_(gfx::Animation::ShouldRenderRichAnimation() - ? new GlowHoverController(this) - : nullptr) { + title_animation_(this) { DCHECK(controller); tab_style_ = TabStyle::CreateForTab(this); @@ -173,26 +167,16 @@ Tab::~Tab() = default; void Tab::AnimationEnded(const gfx::Animation* animation) { - if (animation == &title_animation_) - title_->SetBoundsRect(target_title_bounds_); - else - SchedulePaint(); + DCHECK_EQ(animation, &title_animation_); + title_->SetBoundsRect(target_title_bounds_); } void Tab::AnimationProgressed(const gfx::Animation* animation) { - if (animation == &title_animation_) { - title_->SetBoundsRect(gfx::Tween::RectValueBetween( - gfx::Tween::CalculateValue(gfx::Tween::FAST_OUT_SLOW_IN, - animation->GetCurrentValue()), - start_title_bounds_, target_title_bounds_)); - return; - } - - SchedulePaint(); -} - -void Tab::AnimationCanceled(const gfx::Animation* animation) { - SchedulePaint(); + DCHECK_EQ(animation, &title_animation_); + title_->SetBoundsRect(gfx::Tween::RectValueBetween( + gfx::Tween::CalculateValue(gfx::Tween::FAST_OUT_SLOW_IN, + animation->GetCurrentValue()), + start_title_bounds_, target_title_bounds_)); } void Tab::ButtonPressed(views::Button* sender, const ui::Event& event) { @@ -493,18 +477,13 @@ } void Tab::OnMouseMoved(const ui::MouseEvent& event) { - if (hover_controller_) - hover_controller_->SetLocation(event.location()); + tab_style_->SetHoverLocation(event.location()); controller_->OnMouseEventInTab(this, event); } void Tab::OnMouseEntered(const ui::MouseEvent& event) { mouse_hovered_ = true; - if (hover_controller_) { - hover_controller_->SetSubtleOpacityScale( - controller_->GetHoverOpacityForRadialHighlight()); - hover_controller_->Show(GlowHoverController::SUBTLE); - } + tab_style_->ShowHover(GlowHoverController::ShowStyle::kSubtle); UpdateForegroundColors(); Layout(); controller_->UpdateHoverCard(this, true); @@ -512,8 +491,7 @@ void Tab::OnMouseExited(const ui::MouseEvent& event) { mouse_hovered_ = false; - if (hover_controller_) - hover_controller_->Hide(); + tab_style_->HideHover(GlowHoverController::HideStyle::kGradual); UpdateForegroundColors(); Layout(); } @@ -820,23 +798,6 @@ (ideal_x - bounds->x()))); } -float Tab::GetThrobValue() const { - const bool is_selected = IsSelected(); - double val = is_selected ? kSelectedTabOpacity : 0; - - // Wrapping in closure to only compute offset when needed (animate or hover). - const auto offset = [=] { - constexpr float kSelectedTabThrobScale = 0.95f - kSelectedTabOpacity; - const float opacity = GetHoverOpacity(); - return is_selected ? (kSelectedTabThrobScale * opacity) : opacity; - }; - - if (hover_controller_ && hover_controller_->ShouldDraw()) - val += hover_controller_->GetAnimationValue() * offset(); - - return val; -} - void Tab::UpdateIconVisibility() { // TODO(pkasting): This whole function should go away, and we should simply // compute child visibility state in Layout(). @@ -946,17 +907,6 @@ kPinnedTabExtraWidthToRenderAsNormal)); } -float Tab::GetHoverOpacity() const { - // Opacity boost varies on tab width. The interpolation is nonlinear so - // that most tabs will fall on the low end of the opacity range, but very - // narrow tabs will still stand out on the high end. - const float range_start = float{TabStyle::GetStandardWidth()}; - const float range_end = float{TabStyle::GetMinimumInactiveWidth()}; - const float value_in_range = float{width()}; - const float t = (value_in_range - range_start) / (range_end - range_start); - return controller_->GetHoverOpacityForTab(t * t); -} - void Tab::UpdateTabIconNeedsAttentionBlocked() { // Only show the blocked attention indicator on non-active tabs. For active // tabs, the user sees the dialog blocking the tab, so there's no point to it @@ -970,80 +920,18 @@ } void Tab::UpdateForegroundColors() { - // The theme provider may be null if we're not currently in a widget - // hierarchy. - const ui::ThemeProvider* theme_provider = GetThemeProvider(); - if (!theme_provider) - return; + TabStyle::TabColors colors = tab_style_->CalculateColors(); - // These ratios are calculated from the default Chrome theme colors. - // Active/inactive are the contrast ratios of the close X against the tab - // background. Hovered/pressed are the contrast ratios of the highlight circle - // against the tab background. - constexpr float kMinimumActiveContrastRatio = 6.05f; - constexpr float kMinimumInactiveContrastRatio = 4.61f; - constexpr float kMinimumHoveredContrastRatio = 5.02f; - constexpr float kMinimumPressedContrastRatio = 4.41f; + icon_->SetBackgroundColor(colors.background_color); + title_->SetEnabledColor(colors.title_color); - // In some cases, inactive tabs may have background more like active tabs than - // inactive tabs, so colors should be adapted to ensure appropriate contrast. - // In particular, text should have plenty of contrast in all cases, so switch - // to using foreground color designed for active tabs if the tab looks more - // like an active tab than an inactive tab. - float expected_opacity = 0.0f; - if (IsActive()) { - expected_opacity = 1.0f; - } else if (IsSelected()) { - expected_opacity = kSelectedTabOpacity; - } else if (mouse_hovered_) { - expected_opacity = GetHoverOpacity(); - } - const SkColor tab_bg_color = color_utils::AlphaBlend( - controller_->GetTabBackgroundColor(TAB_ACTIVE), - controller_->GetTabBackgroundColor(TAB_INACTIVE), expected_opacity); - SkColor tab_title_color = controller_->GetTabForegroundColor( - expected_opacity > 0.5f ? TAB_ACTIVE : TAB_INACTIVE, tab_bg_color); - tab_title_color = - color_utils::GetColorWithMinimumContrast(tab_title_color, tab_bg_color); - - icon_->SetBackgroundColor(tab_bg_color); - - title_->SetEnabledColor(tab_title_color); - - const SkColor base_hovered_color = theme_provider->GetColor( - ThemeProperties::COLOR_TAB_CLOSE_BUTTON_BACKGROUND_HOVER); - const SkColor base_pressed_color = theme_provider->GetColor( - ThemeProperties::COLOR_TAB_CLOSE_BUTTON_BACKGROUND_PRESSED); - - const auto get_color_for_contrast_ratio = [](SkColor fg_color, - SkColor bg_color, - float contrast_ratio) { - const SkAlpha blend_alpha = color_utils::GetBlendValueWithMinimumContrast( - bg_color, fg_color, bg_color, contrast_ratio); - return color_utils::AlphaBlend(fg_color, bg_color, blend_alpha); - }; - - const SkColor generated_icon_color = get_color_for_contrast_ratio( - tab_title_color, tab_bg_color, - IsActive() ? kMinimumActiveContrastRatio : kMinimumInactiveContrastRatio); - const SkColor generated_hovered_color = get_color_for_contrast_ratio( - base_hovered_color, tab_bg_color, kMinimumHoveredContrastRatio); - const SkColor generated_pressed_color = get_color_for_contrast_ratio( - base_pressed_color, tab_bg_color, kMinimumPressedContrastRatio); - - const SkColor generated_hovered_icon_color = - color_utils::GetColorWithMinimumContrast(tab_title_color, - generated_hovered_color); - const SkColor generated_pressed_icon_color = - color_utils::GetColorWithMinimumContrast(tab_title_color, - generated_pressed_color); close_button_->SetIconColors( - generated_icon_color, generated_hovered_icon_color, - generated_pressed_icon_color, generated_hovered_color, - generated_pressed_color); + colors.button_icon_idle_color, colors.button_icon_hovered_color, + colors.button_icon_hovered_color, colors.button_background_hovered_color, + colors.button_background_pressed_color); - if (button_color_ != generated_icon_color) { - button_color_ = generated_icon_color; + if (button_color_ != colors.button_icon_idle_color) { + button_color_ = colors.button_icon_idle_color; alert_indicator_->OnParentTabButtonColorChanged(); }
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h index 4d0cfa4e..019c1aec 100644 --- a/chrome/browser/ui/views/tabs/tab.h +++ b/chrome/browser/ui/views/tabs/tab.h
@@ -12,7 +12,6 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "chrome/browser/ui/views/tabs/glow_hover_controller.h" #include "chrome/browser/ui/views/tabs/tab_renderer_data.h" #include "ui/base/layout.h" #include "ui/gfx/animation/animation_delegate.h" @@ -65,7 +64,6 @@ // gfx::AnimationDelegate: void AnimationEnded(const gfx::Animation* animation) override; void AnimationProgressed(const gfx::Animation* animation) override; - void AnimationCanceled(const gfx::Animation* animation) override; // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; @@ -168,19 +166,10 @@ return tab_activated_with_last_tap_down_; } - GlowHoverController* hover_controller() { return hover_controller_.get(); } - const GlowHoverController* hover_controller() const { - return hover_controller_.get(); - } - bool mouse_hovered() const { return mouse_hovered_; } - // Gets the throb value for the tab. When a tab is not selected the active - // background is drawn at GetThrobValue() * 100%. This is used for hover, mini - // tab title change and pulsing. - float GetThrobValue() const; - // Returns the TabStyle associated with this tab. + TabStyle* tab_style() { return tab_style_.get(); } const TabStyle* tab_style() const { return tab_style_.get(); } // Returns the text to show in a tab's tooltip: The contents |title|, followed @@ -211,9 +200,6 @@ // pinned tab. bool ShouldRenderAsNormalTab() const; - // Returns the final hover opacity for this tab (considers tab width). - float GetHoverOpacity() const; - // Updates the blocked attention state of the |icon_|. This only updates // state; it is the responsibility of the caller to request a paint. void UpdateTabIconNeedsAttentionBlocked(); @@ -223,7 +209,7 @@ // and alert icon. void UpdateForegroundColors(); - // The controller, never NULL. + // The controller, never nullptr. TabController* const controller_; TabRendererData data_; @@ -252,8 +238,6 @@ bool tab_activated_with_last_tap_down_ = false; - std::unique_ptr<GlowHoverController> hover_controller_; - // The offset used to paint the inactive background image. int background_offset_;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 4f852c3..f0696ba 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1366,9 +1366,7 @@ // this code defers drawing such tabs until later. const auto paint_or_add_to_tabs = [&paint_info, &selected_and_hovered_tabs](Tab* tab) { - if (tab->IsSelected() || - (tab->mouse_hovered() || - (tab->hover_controller() && tab->hover_controller()->ShouldDraw()))) { + if (tab->tab_style()->GetZValue() > 0.0) { selected_and_hovered_tabs.push_back(tab); } else { tab->Paint(paint_info); @@ -1417,39 +1415,10 @@ } } - // This will sort the inactive tabs so that they paint in the following order: - // - // o Unselected and hover-animating tabs in ascending animation value order. - // o The single unselected mouse hovered tab, if present. - // o Selected tabs in trailing-to-leading order. - // o Selected and hover animating tabs in ascending animation value order. - // o The single selected and mouse_hovered tab, if present. - // - // This is accomplished by adding a "weight" to the current hover animation - // value which represents the above groupings. - // - // 0.0 == sort_value Unselected/non hover animating (already painted). - // 0.0 < sort_value <= 1.0 Unselected/hover animating. - // 2.0 <= sort_value <= 3.0 Unselected/mouse hovered tab. - // 4.0 == sort_value Selected/non hover animating. - // 4.0 < sort_value <= 5.0 Selected/hover animating. - // 6.0 <= sort_value <= 7.0 Selected/mouse hovered tab. - // - auto tab_sort_value = [](Tab* tab) { - float sort_value = tab->hover_controller() - ? tab->hover_controller()->GetAnimationValue() - : 0; - if (tab->IsSelected()) - sort_value += 4.f; - if (tab->mouse_hovered()) - sort_value += 2.f; - return sort_value; - }; - std::stable_sort(selected_and_hovered_tabs.begin(), - selected_and_hovered_tabs.end(), - [&tab_sort_value](Tab* tab1, Tab* tab2) { - return tab_sort_value(tab1) < tab_sort_value(tab2); + selected_and_hovered_tabs.end(), [](Tab* tab1, Tab* tab2) { + return tab1->tab_style()->GetZValue() < + tab2->tab_style()->GetZValue(); }); for (Tab* tab : selected_and_hovered_tabs) tab->Paint(paint_info);
diff --git a/chrome/browser/ui/views/tabs/tab_style.cc b/chrome/browser/ui/views/tabs/tab_style.cc index d1caa9f..e3f91b1 100644 --- a/chrome/browser/ui/views/tabs/tab_style.cc +++ b/chrome/browser/ui/views/tabs/tab_style.cc
@@ -28,6 +28,9 @@ namespace { +// Opacity of the active tab background painted over inactive selected tabs. +constexpr float kSelectedTabOpacity = 0.75f; + // Cache of pre-painted backgrounds for tabs. class BackgroundCache { public: @@ -71,7 +74,7 @@ // Tab style implementation for the GM2 refresh (Chrome 69). class GM2TabStyle : public TabStyle { public: - explicit GM2TabStyle(const Tab* tab); + explicit GM2TabStyle(Tab* tab); protected: // TabStyle: @@ -81,8 +84,12 @@ bool force_active = false, RenderUnits render_units = RenderUnits::kPixels) const override; gfx::Insets GetContentsInsets() const override; - int GetStrokeThickness(bool should_paint_as_active = false) const override; + float GetZValue() const override; + TabStyle::TabColors CalculateColors() const override; void PaintTab(gfx::Canvas* canvas, const SkPath& clip) const override; + void SetHoverLocation(const gfx::Point& location) override; + void ShowHover(GlowHoverController::ShowStyle style) override; + void HideHover(GlowHoverController::HideStyle style) override; private: // Gets the bounds for the leading and trailing separators for a tab. @@ -96,6 +103,25 @@ // Returns whether we shoould extend the hit test region for Fitts' Law. bool ShouldExtendHitTest() const; + // Returns whether the hover animation is being shown. + bool IsHoverActive() const; + + // Returns the progress (0 to 1) of the hover animation. + double GetHoverAnimationValue() const; + + // Returns the opacity of the hover effect that should be drawn, which may not + // be the same as GetHoverAnimationValue. + float GetHoverOpacity() const; + + // Gets the throb value. A value of 0 indicates no throbbing. + float GetThrobValue() const; + + // Returns the thickness of the stroke drawn around the top and sides of the + // tab. Only active tabs may have a stroke, and not in all cases. If there + // is no stroke, returns 0. If |should_paint_as_active| is true, the tab is + // treated as an active tab regardless of its true current state. + int GetStrokeThickness(bool should_paint_as_active = false) const; + // Painting helper functions: void PaintInactiveTabBackground(gfx::Canvas* canvas, const SkPath& clip) const; @@ -127,9 +153,13 @@ const Tab* const tab_; + std::unique_ptr<GlowHoverController> hover_controller_; + // Cache of the paint output for tab backgrounds. mutable BackgroundCache background_active_cache_; mutable BackgroundCache background_inactive_cache_; + + DISALLOW_COPY_AND_ASSIGN(GM2TabStyle); }; // Thickness in DIPs of the separator painted on the left and right edges of @@ -194,7 +224,11 @@ // GM2TabStyle ----------------------------------------------------------------- -GM2TabStyle::GM2TabStyle(const Tab* tab) : tab_(tab) {} +GM2TabStyle::GM2TabStyle(Tab* tab) + : tab_(tab), + hover_controller_(gfx::Animation::ShouldRenderRichAnimation() + ? new GlowHoverController(tab) + : nullptr) {} SkPath GM2TabStyle::GetPath(PathType path_type, float scale, @@ -386,10 +420,105 @@ horizontal_inset); } -int GM2TabStyle::GetStrokeThickness(bool should_paint_as_active) const { - return (tab_->IsActive() || should_paint_as_active) - ? tab_->controller()->GetStrokeThickness() - : 0; +float GM2TabStyle::GetZValue() const { + // This will return values so that inactive tabs can be sorted in the + // following order: + // + // o Unselected tabs, in ascending hover animation value order. + // o The single unselected tab being hovered by the mouse, if present. + // o Selected tabs, in ascending hover animation value order. + // o The single selected tab being hovered by the mouse, if present. + // + // Representing the above groupings is accomplished by adding a "weight" to + // the current hover animation value. + // + // 0.0 == z-value Unselected/non hover animating. + // 0.0 < z-value <= 1.0 Unselected/hover animating. + // 2.0 <= z-value <= 3.0 Unselected/mouse hovered tab. + // 4.0 == z-value Selected/non hover animating. + // 4.0 < z-value <= 5.0 Selected/hover animating. + // 6.0 <= z-value <= 7.0 Selected/mouse hovered tab. + // + // This function doesn't handle active tabs, as they are normally painted by a + // different code path (with z-value infinity). + float sort_value = GetHoverAnimationValue(); + if (tab_->IsSelected()) + sort_value += 4.f; + if (tab_->mouse_hovered()) + sort_value += 2.f; + return sort_value; +} + +TabStyle::TabColors GM2TabStyle::CalculateColors() const { + const ui::ThemeProvider* theme_provider = tab_->GetThemeProvider(); + + // These ratios are calculated from the default Chrome theme colors. + // Active/inactive are the contrast ratios of the close X against the tab + // background. Hovered/pressed are the contrast ratios of the highlight circle + // against the tab background. + constexpr float kMinimumActiveContrastRatio = 6.05f; + constexpr float kMinimumInactiveContrastRatio = 4.61f; + constexpr float kMinimumHoveredContrastRatio = 5.02f; + constexpr float kMinimumPressedContrastRatio = 4.41f; + + // In some cases, inactive tabs may have background more like active tabs than + // inactive tabs, so colors should be adapted to ensure appropriate contrast. + // In particular, text should have plenty of contrast in all cases, so switch + // to using foreground color designed for active tabs if the tab looks more + // like an active tab than an inactive tab. + float expected_opacity = 0.0f; + if (tab_->IsActive()) { + expected_opacity = 1.0f; + } else if (tab_->IsSelected()) { + expected_opacity = kSelectedTabOpacity; + } else if (tab_->mouse_hovered()) { + expected_opacity = GetHoverOpacity(); + } + const SkColor bg_color = color_utils::AlphaBlend( + tab_->controller()->GetTabBackgroundColor(TAB_ACTIVE), + tab_->controller()->GetTabBackgroundColor(TAB_INACTIVE), + expected_opacity); + + SkColor title_color = tab_->controller()->GetTabForegroundColor( + expected_opacity > 0.5f ? TAB_ACTIVE : TAB_INACTIVE, bg_color); + title_color = color_utils::GetColorWithMinimumContrast(title_color, bg_color); + + const SkColor base_hovered_color = theme_provider->GetColor( + ThemeProperties::COLOR_TAB_CLOSE_BUTTON_BACKGROUND_HOVER); + const SkColor base_pressed_color = theme_provider->GetColor( + ThemeProperties::COLOR_TAB_CLOSE_BUTTON_BACKGROUND_PRESSED); + + const auto get_color_for_contrast_ratio = [](SkColor fg_color, + SkColor bg_color, + float contrast_ratio) { + const SkAlpha blend_alpha = color_utils::GetBlendValueWithMinimumContrast( + bg_color, fg_color, bg_color, contrast_ratio); + return color_utils::AlphaBlend(fg_color, bg_color, blend_alpha); + }; + + const SkColor generated_icon_color = get_color_for_contrast_ratio( + title_color, bg_color, + tab_->IsActive() ? kMinimumActiveContrastRatio + : kMinimumInactiveContrastRatio); + const SkColor generated_hovered_color = get_color_for_contrast_ratio( + base_hovered_color, bg_color, kMinimumHoveredContrastRatio); + const SkColor generated_pressed_color = get_color_for_contrast_ratio( + base_pressed_color, bg_color, kMinimumPressedContrastRatio); + + const SkColor generated_hovered_icon_color = + color_utils::GetColorWithMinimumContrast(title_color, + generated_hovered_color); + const SkColor generated_pressed_icon_color = + color_utils::GetColorWithMinimumContrast(title_color, + generated_pressed_color); + + return {bg_color, + title_color, + generated_icon_color, + generated_hovered_icon_color, + generated_pressed_icon_color, + generated_hovered_color, + generated_pressed_color}; } void GM2TabStyle::PaintTab(gfx::Canvas* canvas, const SkPath& clip) const { @@ -406,7 +535,7 @@ } else { PaintInactiveTabBackground(canvas, clip); - const float throb_value = tab_->GetThrobValue(); + const float throb_value = GetThrobValue(); if (throb_value > 0) { canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), tab_->GetLocalBounds()); @@ -417,6 +546,27 @@ } } +void GM2TabStyle::SetHoverLocation(const gfx::Point& location) { + if (hover_controller_) + hover_controller_->SetLocation(location); +} + +void GM2TabStyle::ShowHover(GlowHoverController::ShowStyle style) { + if (!hover_controller_) + return; + + if (style == GlowHoverController::ShowStyle::kSubtle) { + hover_controller_->SetSubtleOpacityScale( + tab_->controller()->GetHoverOpacityForRadialHighlight()); + } + hover_controller_->Show(style); +} + +void GM2TabStyle::HideHover(GlowHoverController::HideStyle style) { + if (hover_controller_) + hover_controller_->Hide(style); +} + TabStyle::SeparatorBounds GM2TabStyle::GetSeparatorBounds(float scale) const { const gfx::RectF aligned_bounds = ScaleAndAlignBounds(tab_->bounds(), scale, GetStrokeThickness()); @@ -462,15 +612,14 @@ // hovered. If the subsequent tab is active, don't consider its hover // animation value, lest the trailing separator on this tab disappear while // the subsequent tab is being dragged. - const float hover_value = - tab_->hover_controller() ? tab_->hover_controller()->GetAnimationValue() - : 0; + const float hover_value = GetHoverAnimationValue(); const Tab* subsequent_tab = tab_->controller()->GetAdjacentTab(tab_, 1); - const float subsequent_hover = - !for_layout && subsequent_tab && subsequent_tab->hover_controller() && - !subsequent_tab->IsActive() - ? float{subsequent_tab->hover_controller()->GetAnimationValue()} - : 0; + float subsequent_hover = 0; + if (!for_layout && subsequent_tab && !subsequent_tab->IsActive()) { + auto* subsequent_tab_style = + static_cast<const GM2TabStyle*>(subsequent_tab->tab_style()); + subsequent_hover = float{subsequent_tab_style->GetHoverAnimationValue()}; + } trailing_opacity = 1.f - std::max(hover_value, subsequent_hover); // The leading separator need not consider the previous tab's hover value, @@ -536,6 +685,50 @@ return widget->IsMaximized() || widget->IsFullscreen(); } +bool GM2TabStyle::IsHoverActive() const { + if (!hover_controller_) + return false; + return hover_controller_->ShouldDraw(); +} + +double GM2TabStyle::GetHoverAnimationValue() const { + if (!hover_controller_) + return 0.0; + return hover_controller_->GetAnimationValue(); +} + +float GM2TabStyle::GetHoverOpacity() const { + // Opacity boost varies on tab width. The interpolation is nonlinear so + // that most tabs will fall on the low end of the opacity range, but very + // narrow tabs will still stand out on the high end. + const float range_start = float{GetStandardWidth()}; + const float range_end = float{GetMinimumInactiveWidth()}; + const float value_in_range = float{tab_->width()}; + const float t = (value_in_range - range_start) / (range_end - range_start); + return tab_->controller()->GetHoverOpacityForTab(t * t); +} + +float GM2TabStyle::GetThrobValue() const { + const bool is_selected = tab_->IsSelected(); + double val = is_selected ? kSelectedTabOpacity : 0; + + if (IsHoverActive()) { + constexpr float kSelectedTabThrobScale = 0.95f - kSelectedTabOpacity; + const float opacity = GetHoverOpacity(); + const float offset = + is_selected ? (kSelectedTabThrobScale * opacity) : opacity; + val += GetHoverAnimationValue() * offset; + } + + return val; +} + +int GM2TabStyle::GetStrokeThickness(bool should_paint_as_active) const { + return (tab_->IsActive() || should_paint_as_active) + ? tab_->controller()->GetStrokeThickness() + : 0; +} + void GM2TabStyle::PaintInactiveTabBackground(gfx::Canvas* canvas, const SkPath& clip) const { bool has_custom_image; @@ -564,8 +757,7 @@ : SK_ColorTRANSPARENT; const SkColor stroke_color = tab_->controller()->GetToolbarTopSeparatorColor(); - const bool paint_hover_effect = !active && tab_->hover_controller() && - tab_->hover_controller()->ShouldDraw(); + const bool paint_hover_effect = !active && IsHoverActive(); const float scale = canvas->image_scale(); const float stroke_thickness = GetStrokeThickness(active); @@ -660,15 +852,13 @@ } if (paint_hover_effect) { - SkPoint hover_location( - gfx::PointToSkPoint(tab_->hover_controller()->location())); + SkPoint hover_location(gfx::PointToSkPoint(hover_controller_->location())); hover_location.scale(SkFloatToScalar(scale)); const SkScalar kMinHoverRadius = 16; const SkScalar radius = std::max(SkFloatToScalar(tab_->width() / 4.f), kMinHoverRadius); - DrawHighlight( - canvas, hover_location, radius * scale, - SkColorSetA(active_color, tab_->hover_controller()->GetAlpha())); + DrawHighlight(canvas, hover_location, radius * scale, + SkColorSetA(active_color, hover_controller_->GetAlpha())); } } @@ -767,7 +957,7 @@ TabStyle::~TabStyle() = default; // static -std::unique_ptr<TabStyle> TabStyle::CreateForTab(const Tab* tab) { +std::unique_ptr<TabStyle> TabStyle::CreateForTab(Tab* tab) { return std::make_unique<GM2TabStyle>(tab); }
diff --git a/chrome/browser/ui/views/tabs/tab_style.h b/chrome/browser/ui/views/tabs/tab_style.h index 1a22ca9..7393cfd 100644 --- a/chrome/browser/ui/views/tabs/tab_style.h +++ b/chrome/browser/ui/views/tabs/tab_style.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "chrome/browser/ui/views/tabs/glow_hover_controller.h" #include "ui/gfx/geometry/rect_f.h" namespace gfx { @@ -67,6 +68,17 @@ float left = 0, right = 0; }; + // Colors for various parts of the tab derived by TabStyle. + struct TabColors { + SkColor background_color; + SkColor title_color; + SkColor button_icon_idle_color; + SkColor button_icon_hovered_color; + SkColor button_icon_pressed_color; + SkColor button_background_hovered_color; + SkColor button_background_pressed_color; + }; + // Creates an appropriate TabStyle instance for a particular tab. // Caller is responsibly for the TabStyle object's lifespan and should delete // it when finished. @@ -74,7 +86,7 @@ // We've implemented this as a factory function so that when we're playing // with new variatons on tab shapes we can have a few possible implementations // and switch them in one place. - static std::unique_ptr<TabStyle> CreateForTab(const Tab* tab); + static std::unique_ptr<TabStyle> CreateForTab(Tab* tab); virtual ~TabStyle(); @@ -88,18 +100,28 @@ bool force_active = false, RenderUnits render_units = RenderUnits::kPixels) const = 0; - // Returns the thickness of the stroke drawn around the top and sides of the - // tab. Only active tabs may have a stroke, and not in all cases. If there - // is no stroke, returns 0. If |should_paint_as_active| is true, the tab is - // treated as an active tab regardless of its true current state. - virtual int GetStrokeThickness(bool should_paint_as_active = false) const = 0; - - // Paint the tab. - virtual void PaintTab(gfx::Canvas* canvas, const SkPath& clip) const = 0; - // Returns the insets to use for laying out tab contents. virtual gfx::Insets GetContentsInsets() const = 0; + // Returns the z-value of the tab, which should be used to paint them in + // ascending order. + virtual float GetZValue() const = 0; + + // Derives and returns colors for the tab. See TabColors, above. + virtual TabColors CalculateColors() const = 0; + + // Paints the tab. + virtual void PaintTab(gfx::Canvas* canvas, const SkPath& clip) const = 0; + + // Sets the center of the radial highlight in the hover animation. + virtual void SetHoverLocation(const gfx::Point& location) = 0; + + // Shows the hover animation. + virtual void ShowHover(GlowHoverController::ShowStyle style) = 0; + + // Hides the hover animation. + virtual void HideHover(GlowHoverController::HideStyle style) = 0; + // Returns the minimum possible width of a selected Tab. Selected tabs must // always show a close button, and thus have a larger minimum size than // unselected tabs.
diff --git a/chrome/browser/ui/web_applications/web_app_metrics_factory.cc b/chrome/browser/ui/web_applications/web_app_metrics_factory.cc index 79ad76bd..bd1fe48 100644 --- a/chrome/browser/ui/web_applications/web_app_metrics_factory.cc +++ b/chrome/browser/ui/web_applications/web_app_metrics_factory.cc
@@ -47,8 +47,7 @@ content::BrowserContext* WebAppMetricsFactory::GetBrowserContextToUse( content::BrowserContext* context) const { - Profile* profile = Profile::FromBrowserContext(context); - return AllowWebAppInstallation(profile) ? context : nullptr; + return GetBrowserContextForWebAppMetrics(context); } } // namespace web_app
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index b42f338..cc2994c 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -394,6 +394,7 @@ {"pdf/pdf_scripting_api.js", IDR_PDF_PDF_SCRIPTING_API_JS}, {"pdf/pdf_viewer.js", IDR_PDF_PDF_VIEWER_JS}, {"pdf/toolbar_manager.js", IDR_PDF_TOOLBAR_MANAGER_JS}, + {"pdf/viewport_interface.js", IDR_PDF_VIEWPORT_INTERFACE_JS}, {"pdf/viewport.js", IDR_PDF_VIEWPORT_JS}, {"pdf/viewport_scroller.js", IDR_PDF_VIEWPORT_SCROLLER_JS}, {"pdf/zoom_manager.js", IDR_PDF_ZOOM_MANAGER_JS},
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 982e64ac..4fac866 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -158,7 +158,7 @@ "isGuest", #if defined(OS_CHROMEOS) user_manager::UserManager::Get()->IsLoggedInAsGuest() || - user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()); + user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()); #else profile->IsOffTheRecord()); #endif @@ -822,8 +822,6 @@ base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess(); html_source->AddBoolean("unifiedDesktopAvailable", cmd.HasSwitch(::switches::kEnableUnifiedDesktop)); - html_source->AddBoolean("multiMirroringAvailable", - !cmd.HasSwitch(::switches::kDisableMultiMirroring)); html_source->AddBoolean( "enableTouchCalibrationSetting", @@ -1551,9 +1549,9 @@ sync_service->IsUsingSecondaryPassphrase()); html_source->AddBoolean( "uploadToGoogleActive", - syncer::GetUploadToGoogleState( - sync_service, syncer::ModelType::AUTOFILL_WALLET_DATA) == - syncer::UploadState::ACTIVE); + syncer::GetUploadToGoogleState( + sync_service, syncer::ModelType::AUTOFILL_WALLET_DATA) == + syncer::UploadState::ACTIVE); } else { html_source->AddBoolean("isUsingSecondaryPassphrase", false); html_source->AddBoolean("uploadToGoogleActive", false); @@ -1714,6 +1712,8 @@ : IDS_SETTINGS_SYNC_WILL_START}, {"syncSettingsSavedToast", IDS_SETTINGS_SYNC_SETTINGS_SAVED_TOAST_LABEL}, {"cancelSync", IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC}, + {"syncSetupCancelDialogTitle", IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_TITLE}, + {"syncSetupCancelDialogBody", IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_BODY}, #endif // defined(OS_CHROMEOS) #if BUILDFLAG(ENABLE_DICE_SUPPORT) {"peopleSignIn", IDS_PROFILES_DICE_SIGNIN_BUTTON}, @@ -1854,8 +1854,7 @@ "syncDisconnectManagedProfileExplanation", l10n_util::GetStringFUTF8( IDS_SETTINGS_SYNC_DISCONNECT_MANAGED_PROFILE_EXPLANATION, - base::ASCIIToUTF16("$1"), - base::ASCIIToUTF16(sync_dashboard_url))); + base::ASCIIToUTF16("$1"), base::ASCIIToUTF16(sync_dashboard_url))); // The syncDisconnect text differs depending on Dice-enabledness. if (AccountConsistencyModeManager::IsDiceEnabledForProfile(profile)) {
diff --git a/chrome/browser/ui/webui/site_settings_helper.cc b/chrome/browser/ui/webui/site_settings_helper.cc index f7ae9d36..89778049 100644 --- a/chrome/browser/ui/webui/site_settings_helper.cc +++ b/chrome/browser/ui/webui/site_settings_helper.cc
@@ -104,6 +104,9 @@ {CONTENT_SETTINGS_TYPE_PLUGINS_DATA, nullptr}, {CONTENT_SETTINGS_TYPE_BACKGROUND_FETCH, nullptr}, {CONTENT_SETTINGS_TYPE_INTENT_PICKER_DISPLAY, nullptr}, + // TODO(crbug.com/908836): Add UI for setting this permission. + {CONTENT_SETTINGS_TYPE_SERIAL_GUARD, nullptr}, + {CONTENT_SETTINGS_TYPE_SERIAL_CHOOSER_DATA, nullptr}, }; static_assert(base::size(kContentSettingsTypeGroupNames) == // ContentSettingsType starts at -1, so add 1 here.
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 3b9fe79..c7a8750 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -92,6 +92,7 @@ "web_app_icon_manager_unittest.cc", "web_app_install_manager_unittest.cc", "web_app_registrar_unittest.cc", + "web_app_utils_unittest.cc", ] deps = [ @@ -107,6 +108,10 @@ "//content/test:test_support", "//skia", ] + + if (is_chromeos) { + deps += [ "//chrome/browser/chromeos" ] + } } # TODO(loyso): Erase this and move WebAppProvider into web_applications set.
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/policy/web_app_policy_manager.cc index ee6872b..bf7979971 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.cc +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/task/post_task.h" #include "base/values.h" -#include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/policy/web_app_policy_constants.h" @@ -20,10 +19,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#endif // OS_CHROMEOS - namespace web_app { WebAppPolicyManager::WebAppPolicyManager(Profile* profile, @@ -48,22 +43,6 @@ registry->RegisterListPref(prefs::kWebAppInstallForceList); } -// static -bool WebAppPolicyManager::ShouldEnableForProfile(Profile* profile) { -// PolicyBrowserTests applies test policies to all profiles, including the -// sign-in profile. This causes tests to become flaky since the tests could -// finish before, during, or after the policy apps fail to install in the -// sign-in profile. So we temporarily add a guard to ignore the policy for the -// sign-in profile. -// TODO(crbug.com/876705): Remove once the policy no longer applies to the -// sign-in profile during tests. -#if defined(OS_CHROMEOS) - return !chromeos::ProfileHelper::IsSigninProfile(profile); -#else // !OS_CHROMEOS - return true; -#endif -} - void WebAppPolicyManager::InitChangeRegistrarAndRefreshPolicyInstalledApps() { pref_change_registrar_.Init(pref_service_); pref_change_registrar_.Add(
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.h b/chrome/browser/web_applications/policy/web_app_policy_manager.h index 4f81393..cbde4cb6 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.h +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.h
@@ -35,8 +35,6 @@ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - static bool ShouldEnableForProfile(Profile* profile); - private: void InitChangeRegistrarAndRefreshPolicyInstalledApps();
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc index 1d96397..13b00c86 100644 --- a/chrome/browser/web_applications/system_web_app_manager.cc +++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -12,15 +12,12 @@ #include "base/task/post_task.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/components/web_app_constants.h" +#include "chrome/browser/web_applications/web_app_utils.h" #include "chrome/common/chrome_features.h" #include "chrome/common/webui_url_constants.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#endif // OS_CHROMEOS - namespace web_app { namespace { @@ -55,12 +52,8 @@ // static bool SystemWebAppManager::ShouldEnableForProfile(Profile* profile) { - bool is_enabled = base::FeatureList::IsEnabled(features::kSystemWebApps); -#if defined(OS_CHROMEOS) - // System Apps should not be installed to the signin profile. - is_enabled = is_enabled && !chromeos::ProfileHelper::IsSigninProfile(profile); -#endif - return is_enabled; + return AreWebAppsEnabled(profile) && + base::FeatureList::IsEnabled(features::kSystemWebApps); } void SystemWebAppManager::StartAppInstallation() {
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc index 83a0189..3438c76 100644 --- a/chrome/browser/web_applications/web_app_install_manager.cc +++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -25,21 +25,22 @@ Profile* profile, std::unique_ptr<InstallFinalizer> install_finalizer) : data_retriever_(std::make_unique<WebAppDataRetriever>()), - install_finalizer_(std::move(install_finalizer)) { - DCHECK(AllowWebAppInstallation(profile)); -} + install_finalizer_(std::move(install_finalizer)), + profile_(profile) {} WebAppInstallManager::~WebAppInstallManager() = default; bool WebAppInstallManager::CanInstallWebApp( content::WebContents* web_contents) { - return IsValidWebAppUrl(web_contents->GetURL()); + return AreWebAppsUserInstallable(profile_) && + IsValidWebAppUrl(web_contents->GetLastCommittedURL()); } void WebAppInstallManager::InstallWebApp(content::WebContents* contents, bool force_shortcut_app, OnceInstallCallback install_callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(AreWebAppsUserInstallable(profile_)); // Concurrent calls are not allowed. DCHECK(!web_contents());
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h index 8137030..d50b796 100644 --- a/chrome/browser/web_applications/web_app_install_manager.h +++ b/chrome/browser/web_applications/web_app_install_manager.h
@@ -74,6 +74,7 @@ std::unique_ptr<WebAppDataRetriever> data_retriever_; std::unique_ptr<InstallFinalizer> install_finalizer_; + Profile* profile_; base::WeakPtrFactory<WebAppInstallManager> weak_ptr_factory_{this};
diff --git a/chrome/browser/web_applications/web_app_install_manager_unittest.cc b/chrome/browser/web_applications/web_app_install_manager_unittest.cc index 4cf1064e..f9d87bc0 100644 --- a/chrome/browser/web_applications/web_app_install_manager_unittest.cc +++ b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
@@ -173,7 +173,7 @@ }; TEST_F(WebAppInstallManagerTest, InstallFromWebContents) { - EXPECT_EQ(true, AllowWebAppInstallation(profile())); + EXPECT_TRUE(AreWebAppsUserInstallable(profile())); const GURL url = GURL("https://example.com/path"); const std::string name = "Name";
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index 023334a..d163b8c 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -55,7 +55,12 @@ return WebAppProvider::Get(profile); } -WebAppProvider::WebAppProvider(Profile* profile) : profile_(profile) {} +WebAppProvider::WebAppProvider(Profile* profile) : profile_(profile) { + DCHECK(AreWebAppsEnabled(profile_)); + // WebApp System must have only one instance in original profile. + // Exclude secondary off-the-record profiles. + DCHECK(!profile_->IsOffTheRecord()); +} WebAppProvider::~WebAppProvider() = default; @@ -73,10 +78,8 @@ content::Source<Profile>(profile_)); if (base::FeatureList::IsEnabled(features::kDesktopPWAsWithoutExtensions)) { - if (AllowWebAppInstallation(profile_)) { - registrar_->Init(base::BindOnce(&WebAppProvider::OnRegistryReady, - weak_ptr_factory_.GetWeakPtr())); - } + registrar_->Init(base::BindOnce(&WebAppProvider::OnRegistryReady, + weak_ptr_factory_.GetWeakPtr())); } else { system_web_app_manager_->Init(); @@ -91,9 +94,6 @@ } void WebAppProvider::CreateWebAppsSubsystems(Profile* profile) { - if (!AllowWebAppInstallation(profile)) - return; - database_factory_ = std::make_unique<WebAppDatabaseFactory>(profile); database_ = std::make_unique<WebAppDatabase>(database_factory_.get()); registrar_ = std::make_unique<WebAppRegistrar>(database_.get()); @@ -112,10 +112,8 @@ pending_app_manager_ = std::make_unique<extensions::PendingBookmarkAppManager>(profile); - if (WebAppPolicyManager::ShouldEnableForProfile(profile)) { - web_app_policy_manager_ = std::make_unique<WebAppPolicyManager>( - profile, pending_app_manager_.get()); - } + web_app_policy_manager_ = std::make_unique<WebAppPolicyManager>( + profile, pending_app_manager_.get()); system_web_app_manager_ = std::make_unique<SystemWebAppManager>( profile, pending_app_manager_.get());
diff --git a/chrome/browser/web_applications/web_app_provider_factory.cc b/chrome/browser/web_applications/web_app_provider_factory.cc index d17cd91b..1361373 100644 --- a/chrome/browser/web_applications/web_app_provider_factory.cc +++ b/chrome/browser/web_applications/web_app_provider_factory.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/web_app_provider.h" +#include "chrome/browser/web_applications/web_app_utils.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "extensions/browser/extension_system_provider.h" #include "extensions/browser/extensions_browser_client.h" @@ -49,8 +50,7 @@ content::BrowserContext* WebAppProviderFactory::GetBrowserContextToUse( content::BrowserContext* context) const { - Profile* profile = Profile::FromBrowserContext(context); - return profile ? profile->GetOriginalProfile() : nullptr; + return GetBrowserContextForWebApps(context); } } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_utils.cc b/chrome/browser/web_applications/web_app_utils.cc index cfe1848..14ab85b 100644 --- a/chrome/browser/web_applications/web_app_utils.cc +++ b/chrome/browser/web_applications/web_app_utils.cc
@@ -7,14 +7,55 @@ #include "base/files/file_path.h" #include "chrome/browser/profiles/profile.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#endif // OS_CHROMEOS + namespace web_app { constexpr base::FilePath::CharType kWebAppsDirectoryName[] = FILE_PATH_LITERAL("WebApps"); -bool AllowWebAppInstallation(Profile* profile) { - return !profile->IsGuestSession() && !profile->IsOffTheRecord() && - !profile->IsSystemProfile(); +bool AreWebAppsEnabled(Profile* profile) { + if (!profile) + return false; + + Profile* original_profile = profile->GetOriginalProfile(); + DCHECK(!original_profile->IsOffTheRecord()); + + if (original_profile->IsSystemProfile()) + return false; + +#if defined(OS_CHROMEOS) + // Web Apps should not be installed to the ChromeOS system profiles. + if (chromeos::ProfileHelper::IsSigninProfile(original_profile) || + chromeos::ProfileHelper::IsLockScreenAppProfile(original_profile)) { + return false; + } +#endif + return true; +} + +bool AreWebAppsUserInstallable(Profile* profile) { + return AreWebAppsEnabled(profile) && !profile->IsGuestSession(); +} + +content::BrowserContext* GetBrowserContextForWebApps( + content::BrowserContext* context) { + // Use original profile to create only one KeyedService instance. + Profile* original_profile = + Profile::FromBrowserContext(context)->GetOriginalProfile(); + return AreWebAppsEnabled(original_profile) ? original_profile : nullptr; +} + +content::BrowserContext* GetBrowserContextForWebAppMetrics( + content::BrowserContext* context) { + // Use original profile to create only one KeyedService instance. + Profile* original_profile = + Profile::FromBrowserContext(context)->GetOriginalProfile(); + const bool is_web_app_metrics_enabled = AreWebAppsEnabled(original_profile) && + !original_profile->IsGuestSession(); + return is_web_app_metrics_enabled ? original_profile : nullptr; } base::FilePath GetWebAppsDirectory(Profile* profile) {
diff --git a/chrome/browser/web_applications/web_app_utils.h b/chrome/browser/web_applications/web_app_utils.h index 3f21e79..2d9b3cb 100644 --- a/chrome/browser/web_applications/web_app_utils.h +++ b/chrome/browser/web_applications/web_app_utils.h
@@ -11,9 +11,27 @@ class FilePath; } +namespace content { +class BrowserContext; +} + namespace web_app { -bool AllowWebAppInstallation(Profile* profile); +// These functions return true if the WebApp System or its subset is allowed +// for a given profile. +// |profile| can be original profile or its secondary off-the-record profile. +// Returns false if |profile| is nullptr. +// +// Is main WebApp System allowed (WebAppProvider exists): +bool AreWebAppsEnabled(Profile* profile); +// Is user allowed to install web apps from UI: +bool AreWebAppsUserInstallable(Profile* profile); + +// Get BrowserContext to use for a WebApp KeyedService creation. +content::BrowserContext* GetBrowserContextForWebApps( + content::BrowserContext* context); +content::BrowserContext* GetBrowserContextForWebAppMetrics( + content::BrowserContext* context); base::FilePath GetWebAppsDirectory(Profile* profile);
diff --git a/chrome/browser/web_applications/web_app_utils_unittest.cc b/chrome/browser/web_applications/web_app_utils_unittest.cc new file mode 100644 index 0000000..4d035e533 --- /dev/null +++ b/chrome/browser/web_applications/web_app_utils_unittest.cc
@@ -0,0 +1,134 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/web_app_utils.h" + +#include "base/files/file_path.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/test/web_app_test.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#endif // OS_CHROMEOS + +namespace web_app { + +class WebAppUtilsTest : public WebAppTest {}; + +TEST_F(WebAppUtilsTest, AreWebAppsEnabled) { + Profile* regular_profile = profile(); + + EXPECT_FALSE(AreWebAppsEnabled(nullptr)); + EXPECT_TRUE(AreWebAppsEnabled(regular_profile)); + EXPECT_TRUE(AreWebAppsEnabled(regular_profile->GetOffTheRecordProfile())); + + TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(profile_manager.SetUp()); + + Profile* guest_profile = profile_manager.CreateGuestProfile(); + EXPECT_TRUE(AreWebAppsEnabled(guest_profile)); + EXPECT_TRUE(AreWebAppsEnabled(guest_profile->GetOffTheRecordProfile())); + + Profile* system_profile = profile_manager.CreateSystemProfile(); + EXPECT_FALSE(AreWebAppsEnabled(system_profile)); + EXPECT_FALSE(AreWebAppsEnabled(system_profile->GetOffTheRecordProfile())); + +#if defined(OS_CHROMEOS) + Profile* signin_profile = + profile_manager.CreateTestingProfile(chrome::kInitialProfile); + EXPECT_FALSE(AreWebAppsEnabled(signin_profile)); + EXPECT_FALSE(AreWebAppsEnabled(signin_profile->GetOffTheRecordProfile())); + + Profile* lock_screen_profile = profile_manager.CreateTestingProfile( + chromeos::ProfileHelper::GetLockScreenAppProfileName()); + EXPECT_FALSE(AreWebAppsEnabled(lock_screen_profile)); + EXPECT_FALSE( + AreWebAppsEnabled(lock_screen_profile->GetOffTheRecordProfile())); +#endif +} + +TEST_F(WebAppUtilsTest, AreWebAppsUserInstallable) { + Profile* regular_profile = profile(); + + EXPECT_FALSE(AreWebAppsEnabled(nullptr)); + EXPECT_TRUE(AreWebAppsUserInstallable(regular_profile)); + EXPECT_TRUE( + AreWebAppsUserInstallable(regular_profile->GetOffTheRecordProfile())); + + TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(profile_manager.SetUp()); + + Profile* guest_profile = profile_manager.CreateGuestProfile(); + EXPECT_FALSE(AreWebAppsUserInstallable(guest_profile)); + EXPECT_FALSE( + AreWebAppsUserInstallable(guest_profile->GetOffTheRecordProfile())); + + Profile* system_profile = profile_manager.CreateSystemProfile(); + EXPECT_FALSE(AreWebAppsUserInstallable(system_profile)); + EXPECT_FALSE( + AreWebAppsUserInstallable(system_profile->GetOffTheRecordProfile())); + +#if defined(OS_CHROMEOS) + Profile* signin_profile = + profile_manager.CreateTestingProfile(chrome::kInitialProfile); + EXPECT_FALSE(AreWebAppsUserInstallable(signin_profile)); + EXPECT_FALSE( + AreWebAppsUserInstallable(signin_profile->GetOffTheRecordProfile())); + + Profile* lock_screen_profile = profile_manager.CreateTestingProfile( + chromeos::ProfileHelper::GetLockScreenAppProfileName()); + EXPECT_FALSE(AreWebAppsUserInstallable(lock_screen_profile)); + EXPECT_FALSE( + AreWebAppsUserInstallable(lock_screen_profile->GetOffTheRecordProfile())); +#endif +} + +TEST_F(WebAppUtilsTest, GetBrowserContextForWebApps) { + Profile* regular_profile = profile(); + + EXPECT_EQ(regular_profile, GetBrowserContextForWebApps(regular_profile)); + EXPECT_EQ(regular_profile, GetBrowserContextForWebApps( + regular_profile->GetOffTheRecordProfile())); + + TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(profile_manager.SetUp()); + + Profile* guest_profile = profile_manager.CreateGuestProfile(); + EXPECT_EQ(guest_profile, GetBrowserContextForWebApps(guest_profile)); + EXPECT_EQ(guest_profile, GetBrowserContextForWebApps( + guest_profile->GetOffTheRecordProfile())); + + Profile* system_profile = profile_manager.CreateSystemProfile(); + EXPECT_EQ(nullptr, GetBrowserContextForWebApps(system_profile)); + EXPECT_EQ(nullptr, GetBrowserContextForWebApps( + system_profile->GetOffTheRecordProfile())); +} + +TEST_F(WebAppUtilsTest, GetBrowserContextForWebAppMetrics) { + Profile* regular_profile = profile(); + + EXPECT_EQ(regular_profile, + GetBrowserContextForWebAppMetrics(regular_profile)); + EXPECT_EQ(regular_profile, GetBrowserContextForWebAppMetrics( + regular_profile->GetOffTheRecordProfile())); + + TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(profile_manager.SetUp()); + + Profile* guest_profile = profile_manager.CreateGuestProfile(); + EXPECT_EQ(nullptr, GetBrowserContextForWebAppMetrics(guest_profile)); + EXPECT_EQ(nullptr, GetBrowserContextForWebAppMetrics( + guest_profile->GetOffTheRecordProfile())); + + Profile* system_profile = profile_manager.CreateSystemProfile(); + EXPECT_EQ(nullptr, GetBrowserContextForWebAppMetrics(system_profile)); + EXPECT_EQ(nullptr, GetBrowserContextForWebAppMetrics( + system_profile->GetOffTheRecordProfile())); +} + +} // namespace web_app
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index cc10e29..594214c 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -495,6 +495,12 @@ const base::Feature kPushMessagingBackgroundMode{ "PushMessagingBackgroundMode", base::FEATURE_DISABLED_BY_DEFAULT}; +#if defined(OS_CHROMEOS) +// Enables permanent removal of Legacy Supervised Users on startup. +const base::Feature kRemoveSupervisedUsersOnStartup{ + "RemoveSupervisedUsersOnStartup", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + const base::Feature kSafeSearchUrlReporting{"SafeSearchUrlReporting", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 8919c3b..f617750 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -327,6 +327,11 @@ COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kPushMessagingBackgroundMode; +#if defined(OS_CHROMEOS) +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kRemoveSupervisedUsersOnStartup; +#endif + COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kSafeSearchUrlReporting;
diff --git a/chrome/common/extensions/api/automation.idl b/chrome/common/extensions/api/automation.idl index d684388..4ac4c913 100644 --- a/chrome/common/extensions/api/automation.idl +++ b/chrome/common/extensions/api/automation.idl
@@ -844,9 +844,12 @@ // A data url with the contents of this object's image or thumbnail. DOMString? imageDataUrl; - // The language code for this subtree. + // The author-provided language code for this subtree. DOMString? language; + // The detected language code for this subtree. + DOMString? detectedLanguage; + // Indicates the availability and type of interactive popup element // true - the popup is a menu // menu - the popup is a menu
diff --git a/chrome/common/instant_struct_traits.h b/chrome/common/instant_struct_traits.h index b1c17cc..5fac96a 100644 --- a/chrome/common/instant_struct_traits.h +++ b/chrome/common/instant_struct_traits.h
@@ -60,6 +60,7 @@ IPC_STRUCT_TRAITS_BEGIN(ThemeBackgroundInfo) IPC_STRUCT_TRAITS_MEMBER(using_default_theme) + IPC_STRUCT_TRAITS_MEMBER(using_dark_mode) IPC_STRUCT_TRAITS_MEMBER(custom_background_url) IPC_STRUCT_TRAITS_MEMBER(custom_background_attribution_line_1) IPC_STRUCT_TRAITS_MEMBER(custom_background_attribution_line_2)
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 5784af1..e7ef619 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -1542,8 +1542,8 @@ "ntp.custom_background_local_to_device"; // Data associated with search suggestions that appear on the NTP. -const char kNtpSearchSuggestionsBlacklist[] = - "ntp.search_suggestions_blacklist"; +const char kNtpSearchSuggestionsBlocklist[] = + "ntp.search_suggestions_blocklist"; const char kNtpSearchSuggestionsImpressions[] = "ntp.search_suggestions_impressions"; const char kNtpSearchSuggestionsOptOut[] = "ntp.search_suggestions_opt_out";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index f2383b9..3ebba0b 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -536,7 +536,7 @@ #else extern const char kNtpCustomBackgroundDict[]; extern const char kNtpCustomBackgroundLocalToDevice[]; -extern const char kNtpSearchSuggestionsBlacklist[]; +extern const char kNtpSearchSuggestionsBlocklist[]; extern const char kNtpSearchSuggestionsImpressions[]; extern const char kNtpSearchSuggestionsOptOut[]; #endif // defined(OS_ANDROID)
diff --git a/chrome/common/search.mojom b/chrome/common/search.mojom index d405d3f..db1579e 100644 --- a/chrome/common/search.mojom +++ b/chrome/common/search.mojom
@@ -105,12 +105,17 @@ // Let the user select a local file for the NTP background. SelectLocalBackgroundImage(); - // Add a search suggestion task id to the blacklist. - BlacklistSearchSuggestion(int32 task_version, int64 task_id); + // Add a search suggestion task id to the blocklist. + BlocklistSearchSuggestion(int32 task_version, int64 task_id); - // Add a search suggestion task id and hash to the blacklist. - BlacklistSearchSuggestionWithHash(int32 task_version, int64 task_id, - array<uint8> hash); + // Add a search suggestion task id and hash to the blocklist. + BlocklistSearchSuggestionWithHash(int32 task_version, int64 task_id, + array<uint8, 4> hash); + + // A search suggestion was selected, issue a new request with the suggestion + // temporarily added to the blocklist. + SearchSuggestionSelected(int32 task_version, int64 task_id, + array<uint8, 4> hash); // Opts the user out of receiving search suggestions. OptOutOfSearchSuggestions();
diff --git a/chrome/common/search/instant_types.cc b/chrome/common/search/instant_types.cc index d4e907d..aee253b 100644 --- a/chrome/common/search/instant_types.cc +++ b/chrome/common/search/instant_types.cc
@@ -26,6 +26,7 @@ ThemeBackgroundInfo::ThemeBackgroundInfo() : using_default_theme(true), + using_dark_mode(false), custom_background_url(std::string()), custom_background_attribution_line_1(std::string()), custom_background_attribution_line_2(std::string()), @@ -47,6 +48,7 @@ bool ThemeBackgroundInfo::operator==(const ThemeBackgroundInfo& rhs) const { return using_default_theme == rhs.using_default_theme && + using_dark_mode == rhs.using_dark_mode && custom_background_url == rhs.custom_background_url && custom_background_attribution_line_1 == rhs.custom_background_attribution_line_1 &&
diff --git a/chrome/common/search/instant_types.h b/chrome/common/search/instant_types.h index eea2d4ef..a6ea2f1 100644 --- a/chrome/common/search/instant_types.h +++ b/chrome/common/search/instant_types.h
@@ -67,6 +67,9 @@ // True if the default theme is selected. bool using_default_theme; + // True if dark mode is enabled. + bool using_dark_mode; + // Url of the custom background selected by the user. GURL custom_background_url;
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc index 8e251c72..a42637a 100644 --- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc +++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -969,6 +969,15 @@ result.Set(v8::Boolean::New(isolate, value)); }); RouteNodeIDFunction( + "GetDetectedLanguage", + [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, + AutomationAXTreeWrapper* tree_wrapper, ui::AXNode* node) { + std::string detectedLanguage = node->GetLanguage(); + result.Set(v8::String::NewFromUtf8(isolate, detectedLanguage.c_str(), + v8::NewStringType::kNormal) + .ToLocalChecked()); + }); + RouteNodeIDFunction( "GetCustomActions", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, AutomationAXTreeWrapper* tree_wrapper, ui::AXNode* node) {
diff --git a/chrome/renderer/resources/extensions/automation/automation_node.js b/chrome/renderer/resources/extensions/automation/automation_node.js index ea9f407..52794fb2 100644 --- a/chrome/renderer/resources/extensions/automation/automation_node.js +++ b/chrome/renderer/resources/extensions/automation/automation_node.js
@@ -380,6 +380,13 @@ */ var GetTableCellRowIndex = natives.GetTableCellRowIndex; +/** + * @param {string} axTreeId The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {string} Detected language for this node. + */ +var GetDetectedLanguage = natives.GetDetectedLanguage; + var logging = requireNative('logging'); var utils = require('utils'); @@ -564,6 +571,10 @@ return GetLineThrough(this.treeID, this.id); }, + get detectedLanguage() { + return GetDetectedLanguage(this.treeID, this.id) + }, + get customActions() { return GetCustomActions(this.treeID, this.id); }, @@ -1551,6 +1562,7 @@ 'italic', 'underline', 'lineThrough', + 'detectedLanguage', 'customActions', 'standardActions', 'unclippedLocation',
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc index 2a9ea9d6..a4bb4537 100644 --- a/chrome/renderer/searchbox/searchbox.cc +++ b/chrome/renderer/searchbox/searchbox.cc
@@ -379,18 +379,25 @@ embedded_search_service_->SelectLocalBackgroundImage(); } -void SearchBox::BlacklistSearchSuggestion(int task_version, long task_id) { - embedded_search_service_->BlacklistSearchSuggestion(task_version, task_id); +void SearchBox::BlocklistSearchSuggestion(int task_version, long task_id) { + embedded_search_service_->BlocklistSearchSuggestion(task_version, task_id); } -void SearchBox::BlacklistSearchSuggestionWithHash( +void SearchBox::BlocklistSearchSuggestionWithHash( int task_version, long task_id, const std::vector<uint8_t>& hash) { - embedded_search_service_->BlacklistSearchSuggestionWithHash(task_version, + embedded_search_service_->BlocklistSearchSuggestionWithHash(task_version, task_id, hash); } +void SearchBox::SearchSuggestionSelected(int task_version, + long task_id, + const std::vector<uint8_t>& hash) { + embedded_search_service_->SearchSuggestionSelected(task_version, task_id, + hash); +} + void SearchBox::OptOutOfSearchSuggestions() { embedded_search_service_->OptOutOfSearchSuggestions(); }
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h index fb75ea48..c7e38fc3 100644 --- a/chrome/renderer/searchbox/searchbox.h +++ b/chrome/renderer/searchbox/searchbox.h
@@ -149,14 +149,20 @@ // Let the user select a local file for the NTP background. void SelectLocalBackgroundImage(); - // Add a search suggestion task id to the blacklist. - void BlacklistSearchSuggestion(int task_version, long task_id); + // Add a search suggestion task id to the blocklist. + void BlocklistSearchSuggestion(int task_version, long task_id); - // Add a search suggestion task id and hash to the blacklist. - void BlacklistSearchSuggestionWithHash(int task_version, + // Add a search suggestion task id and hash to the blocklist. + void BlocklistSearchSuggestionWithHash(int task_version, long task_id, const std::vector<uint8_t>& hash); + // A suggestion collected, issue a new request with the suggestion + // temporarily added to the blocklist. + void SearchSuggestionSelected(int task_version, + long task_id, + const std::vector<uint8_t>& hash); + // Opts the user out of receiving search suggestions. void OptOutOfSearchSuggestions();
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index 587d338a..ea00543 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -196,6 +196,8 @@ builder.Set("usingDefaultTheme", theme_info.using_default_theme); + builder.Set("usingDarkMode", theme_info.using_dark_mode); + // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and // B are between 0 and 255 inclusive, and A is a double between 0 and 1 // inclusive. @@ -634,10 +636,13 @@ const std::string& attribution_line_2, const std::string& attributionActionUrl); static void SelectLocalBackgroundImage(); - static void BlacklistSearchSuggestion(int task_version, int task_id); - static void BlacklistSearchSuggestionWithHash(int task_version, + static void BlocklistSearchSuggestion(int task_version, int task_id); + static void BlocklistSearchSuggestionWithHash(int task_version, int task_id, const std::string& hash); + static void SearchSuggestionSelected(int task_version, + int task_id, + const std::string& hash); static void OptOutOfSearchSuggestions(); DISALLOW_COPY_AND_ASSIGN(NewTabPageBindings); @@ -690,9 +695,11 @@ .SetMethod("selectLocalBackgroundImage", &NewTabPageBindings::SelectLocalBackgroundImage) .SetMethod("blacklistSearchSuggestion", - &NewTabPageBindings::BlacklistSearchSuggestion) + &NewTabPageBindings::BlocklistSearchSuggestion) .SetMethod("blacklistSearchSuggestionWithHash", - &NewTabPageBindings::BlacklistSearchSuggestionWithHash) + &NewTabPageBindings::BlocklistSearchSuggestionWithHash) + .SetMethod("searchSuggestionSelected", + &NewTabPageBindings::SearchSuggestionSelected) .SetMethod("optOutOfSearchSuggestions", &NewTabPageBindings::OptOutOfSearchSuggestions); } @@ -1005,24 +1012,43 @@ } // static -void NewTabPageBindings::BlacklistSearchSuggestion(const int task_version, +void NewTabPageBindings::BlocklistSearchSuggestion(const int task_version, const int task_id) { SearchBox* search_box = GetSearchBoxForCurrentContext(); if (!search_box) return; - search_box->BlacklistSearchSuggestion(task_version, task_id); + search_box->BlocklistSearchSuggestion(task_version, task_id); } // static -void NewTabPageBindings::BlacklistSearchSuggestionWithHash( +void NewTabPageBindings::BlocklistSearchSuggestionWithHash( int task_version, int task_id, const std::string& hash) { + if (hash.length() > 4) { + return; + } + std::vector<uint8_t> data(hash.begin(), hash.end()); SearchBox* search_box = GetSearchBoxForCurrentContext(); if (!search_box) return; - search_box->BlacklistSearchSuggestionWithHash(task_version, task_id, data); + search_box->BlocklistSearchSuggestionWithHash(task_version, task_id, data); +} + +// static +void NewTabPageBindings::SearchSuggestionSelected(int task_version, + int task_id, + const std::string& hash) { + if (hash.length() > 4) { + return; + } + + std::vector<uint8_t> data(hash.begin(), hash.end()); + SearchBox* search_box = GetSearchBoxForCurrentContext(); + if (!search_box) + return; + search_box->SearchSuggestionSelected(task_version, task_id, data); } // static
diff --git a/chrome/service/BUILD.gn b/chrome/service/BUILD.gn index 6f72490..6b1f867d 100644 --- a/chrome/service/BUILD.gn +++ b/chrome/service/BUILD.gn
@@ -4,7 +4,6 @@ import("//build/config/features.gni") import("//printing/buildflags/buildflags.gni") -import("//services/catalog/public/tools/catalog.gni") assert(!is_chromeos)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index f5d7d19..6e514d4 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -23,8 +23,6 @@ import("//ppapi/buildflags/buildflags.gni") import("//remoting/remoting_enable.gni") import("//rlz/buildflags/buildflags.gni") -import("//services/catalog/public/tools/catalog.gni") -import("//services/service_manager/public/service_manifest.gni") import("//testing/libfuzzer/fuzzer_test.gni") import("//testing/test.gni") import("//third_party/widevine/cdm/widevine.gni") @@ -273,6 +271,8 @@ public_deps += [ "//ash", "//ash:test_support", + "//ash/public/cpp:manifest", + "//ash/public/cpp:manifest_for_tests", "//components/ownership", "//components/user_manager:test_support", "//ui/aura", @@ -291,6 +291,8 @@ if (toolkit_views) { public_deps += [ "//ui/views:test_support" ] sources += [ + "../browser/autofill/autofill_uitest_util.cc", + "../browser/autofill/autofill_uitest_util.h", "../browser/ui/views/media_router/app_menu_test_api.h", "../browser/ui/views/media_router/app_menu_test_api_views.cc", "views/accessibility_checker.cc", @@ -1540,6 +1542,7 @@ "../browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc", "../browser/ui/views/autofill/card_unmask_prompt_view_tester_views.cc", "../browser/ui/views/autofill/card_unmask_prompt_view_tester_views.h", + "../browser/ui/views/autofill/local_card_migration_browsertest.cc", "../browser/ui/views/autofill/save_card_bubble_views_browsertest.cc", "../browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc", "../browser/ui/views/bookmarks/bookmark_bubble_view_browsertest.cc", @@ -1744,8 +1747,8 @@ "../browser/chromeos/login/login_screen_policy_browsertest.cc", "../browser/chromeos/login/login_ui_keyboard_browsertest.cc", "../browser/chromeos/login/login_utils_browsertest.cc", - "../browser/chromeos/login/mixin_based_browser_test.cc", - "../browser/chromeos/login/mixin_based_browser_test.h", + "../browser/chromeos/login/mixin_based_in_process_browser_test.cc", + "../browser/chromeos/login/mixin_based_in_process_browser_test.h", "../browser/chromeos/login/oobe_localization_browsertest.cc", "../browser/chromeos/login/proxy_auth_dialog_browsertest.cc", "../browser/chromeos/login/quick_unlock/pin_migration_browsertest.cc", @@ -1784,6 +1787,7 @@ "../browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc", "../browser/chromeos/login/users/avatar/user_image_manager_test_util.cc", "../browser/chromeos/login/users/avatar/user_image_manager_test_util.h", + "../browser/chromeos/login/users/remove_supervised_users_browsertest.cc", "../browser/chromeos/login/users/user_manager_hide_supervised_users_browsertest.cc", "../browser/chromeos/login/users/wallpaper_policy_browsertest.cc", "../browser/chromeos/login/webview_login_browsertest.cc", @@ -3215,6 +3219,7 @@ "../browser/search/search_suggest/search_suggest_loader_impl_unittest.cc", "../browser/search/search_suggest/search_suggest_service_unittest.cc", "../browser/search/search_unittest.cc", + "../browser/serial/serial_chooser_context_unittest.cc", "../browser/sessions/tab_restore_service_unittest.cc", "../browser/signin/signin_promo_unittest.cc", "../browser/speech/extension_api/extension_manifests_tts_unittest.cc", @@ -4745,8 +4750,6 @@ "../browser/autofill/autofill_interactive_uitest.cc", "../browser/autofill/autofill_uitest.cc", "../browser/autofill/autofill_uitest.h", - "../browser/autofill/autofill_uitest_util.cc", - "../browser/autofill/autofill_uitest_util.h", "../browser/browser_keyevents_browsertest.cc", "../browser/devtools/devtools_sanity_interactive_browsertest.cc", "../browser/extensions/api/extension_action/browser_action_interactive_test.cc", @@ -5031,8 +5034,8 @@ "../browser/chromeos/login/login_manager_test.h", "../browser/chromeos/login/login_ui_browsertest.cc", "../browser/chromeos/login/login_ui_hide_supervised_users_browsertest.cc", - "../browser/chromeos/login/mixin_based_browser_test.cc", - "../browser/chromeos/login/mixin_based_browser_test.h", + "../browser/chromeos/login/mixin_based_in_process_browser_test.cc", + "../browser/chromeos/login/mixin_based_in_process_browser_test.h", "../browser/chromeos/login/oobe_browsertest.cc", "../browser/chromeos/login/oobe_interactive_ui_test.cc", "../browser/chromeos/login/screenshot_testing/SkDiffPixelsMetric.h", @@ -5720,8 +5723,6 @@ "../browser/autofill/autofill_captured_sites_interactive_uitest.cc", "../browser/autofill/autofill_uitest.cc", "../browser/autofill/autofill_uitest.h", - "../browser/autofill/autofill_uitest_util.cc", - "../browser/autofill/autofill_uitest_util.h", "../browser/autofill/captured_sites_test_utils.cc", "../browser/autofill/captured_sites_test_utils.h", "../browser/password_manager/password_manager_captured_sites_interactive_uitest.cc",
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc index f59d1c3..8da3ff5 100644 --- a/chrome/test/base/chrome_test_launcher.cc +++ b/chrome/test/base/chrome_test_launcher.cc
@@ -49,6 +49,8 @@ #if defined(OS_CHROMEOS) #include "ash/mojo_interface_factory.h" #include "ash/mojo_test_interface_factory.h" +#include "ash/public/cpp/manifest.h" +#include "ash/public/cpp/test_manifest.h" #include "ash/test/ui_controls_factory_ash.h" #endif @@ -178,6 +180,7 @@ #if defined(OS_CHROMEOS) // Inject the test interfaces for ash. Use a callback to avoid linking test // interface support into production code. + ash::AmendManifestForTesting(ash::GetManifestOverlayForTesting()); ash::mojo_interface_factory::SetRegisterInterfacesCallback( base::Bind(&ash::mojo_test_interface_factory::RegisterInterfaces)); #endif
diff --git a/chrome/test/data/pdf/navigator_test.js b/chrome/test/data/pdf/navigator_test.js index 55da969..25a77e6 100644 --- a/chrome/test/data/pdf/navigator_test.js +++ b/chrome/test/data/pdf/navigator_test.js
@@ -75,10 +75,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockViewportChangedCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, - mockViewportChangedCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockViewportChangedCallback.callback, + function() {}, function() {}, function() {}, 0, 1, 0); var paramsParser = new OpenPDFParamsParser(function(name) { paramsParser.onNamedDestinationReceived(-1); @@ -108,9 +107,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); var paramsParser = new OpenPDFParamsParser(function(message) { if (message.namedDestination == 'US')
diff --git a/chrome/test/data/pdf/viewport_test.js b/chrome/test/data/pdf/viewport_test.js index 876cce14..2e24d9f2 100644 --- a/chrome/test/data/pdf/viewport_test.js +++ b/chrome/test/data/pdf/viewport_test.js
@@ -4,9 +4,9 @@ var tests = [ function testDocumentNeedsScrollbars() { - var viewport = - new Viewport(new MockWindow(100, 100), new MockSizer(), function() {}, - function() {}, function() {}, function() {}, 10, 1, 0); + var viewport = new ViewportImpl( + new MockWindow(100, 100), new MockSizer(), function() {}, function() {}, + function() {}, function() {}, 10, 1, 0); var scrollbars; viewport.setDocumentDimensions(new MockDocumentDimensions(90, 90)); @@ -62,10 +62,9 @@ // Test the case when there is a toolbar at the top. var toolbarHeight = 10; - var viewport = - new Viewport(new MockWindow(100, 100), new MockSizer(), function() {}, - function() {}, function() {}, function() {}, 10, 1, - toolbarHeight); + var viewport = new ViewportImpl( + new MockWindow(100, 100), new MockSizer(), function() {}, function() {}, + function() {}, function() {}, 10, 1, toolbarHeight); var scrollbars; viewport.setDocumentDimensions(new MockDocumentDimensions(90, 90)); @@ -103,9 +102,9 @@ var mockSizer = new MockSizer(); var mockWindow = new MockWindow(100, 100, mockSizer); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); // Test setting the zoom without the document dimensions set. The sizer // shouldn't change size. @@ -179,9 +178,9 @@ function testGetMostVisiblePage() { var mockWindow = new MockWindow(100, 100); - var viewport = new Viewport(mockWindow, new MockSizer(), function() {}, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, new MockSizer(), function() {}, function() {}, + function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(100, 100); documentDimensions.addPage(50, 100); @@ -230,9 +229,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(); function assertZoomed(expectedMockWidth, expectedMockHeight, expectedZoom) { @@ -288,9 +287,9 @@ // Test fitting works with scrollbars. The page will need to be zoomed to // fit to width, which will cause the page height to span outside of the // viewport, triggering 15px scrollbars to be shown. - viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 15, 1, 0); + viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 15, 1, 0); documentDimensions.reset(); documentDimensions.addPage(50, 100); viewport.setDocumentDimensions(documentDimensions); @@ -307,9 +306,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(); function assertZoomed(expectedMockWidth, expectedMockHeight, expectedZoom) { @@ -410,7 +409,7 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport( + var viewport = new ViewportImpl( mockWindow, mockSizer, mockCallback.callback, function() {}, function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(); @@ -513,9 +512,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(); documentDimensions.addPage(100, 100); @@ -555,9 +554,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(); documentDimensions.addPage(100, 100); @@ -609,9 +608,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(); documentDimensions.addPage(200, 200); @@ -664,9 +663,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(); documentDimensions.addPage(200, 200); @@ -713,9 +712,9 @@ var mockWindow = new MockWindow(100, 100); var mockSizer = new MockSizer(); var mockCallback = new MockViewportChangedCallback(); - var viewport = new Viewport(mockWindow, mockSizer, mockCallback.callback, - function() {}, function() {}, function() {}, - 0, 1, 0); + var viewport = new ViewportImpl( + mockWindow, mockSizer, mockCallback.callback, function() {}, + function() {}, function() {}, 0, 1, 0); var documentDimensions = new MockDocumentDimensions(); documentDimensions.addPage(100, 100); documentDimensions.addPage(200, 200); @@ -769,26 +768,26 @@ chrome.test.assertFalse(afterZoomCalled); chrome.test.assertEq(1, viewport.zoom); }; - viewport = new Viewport(mockWindow, mockSizer, function() {}, - beforeZoom, afterZoom, function() {}, 0, 1, 0); + viewport = new ViewportImpl( + mockWindow, mockSizer, function() {}, beforeZoom, afterZoom, + function() {}, 0, 1, 0); viewport.setZoom(0.5); chrome.test.succeed(); }, function testInitialSetDocumentDimensionsZoomConstrained() { - var viewport = - new Viewport(new MockWindow(100, 100), new MockSizer(), function() {}, - function() {}, function() {}, function() {}, 0, 1.2, 0); + var viewport = new ViewportImpl( + new MockWindow(100, 100), new MockSizer(), function() {}, function() {}, + function() {}, function() {}, 0, 1.2, 0); viewport.setDocumentDimensions(new MockDocumentDimensions(50, 50)); chrome.test.assertEq(1.2, viewport.zoom); chrome.test.succeed(); }, function testInitialSetDocumentDimensionsZoomUnconstrained() { - var viewport = new Viewport( - new MockWindow(100, 100), - new MockSizer(), function() {}, function() {}, function() {}, - function() {}, 0, 3, 0); + var viewport = new ViewportImpl( + new MockWindow(100, 100), new MockSizer(), function() {}, function() {}, + function() {}, function() {}, 0, 3, 0); viewport.setDocumentDimensions(new MockDocumentDimensions(50, 50)); chrome.test.assertEq(2, viewport.zoom); chrome.test.succeed(); @@ -797,9 +796,9 @@ function testToolbarHeightOffset() { var mockSizer = new MockSizer(); var mockWindow = new MockWindow(100, 100); - var viewport = new Viewport(mockWindow, - mockSizer, function() {}, function() {}, function() {}, function() {}, - 0, 1, 50); + var viewport = new ViewportImpl( + mockWindow, mockSizer, function() {}, function() {}, function() {}, + function() {}, 0, 1, 50); var documentDimensions = new MockDocumentDimensions(0, 0); documentDimensions.addPage(50, 500); viewport.setDocumentDimensions(documentDimensions);
diff --git a/chrome/test/data/webui/app_management/app_management_browsertest.js b/chrome/test/data/webui/app_management/app_management_browsertest.js index 1d5bee5..f1371334 100644 --- a/chrome/test/data/webui/app_management/app_management_browsertest.js +++ b/chrome/test/data/webui/app_management/app_management_browsertest.js
@@ -18,7 +18,9 @@ browsePreload: 'chrome://apps', - extraLibraries: PolymerTest.getLibraries(ROOT_PATH), + extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([ + 'test_util.js', + ]), featureList: ['features::kAppManagement', ''], @@ -26,7 +28,6 @@ runAccessibilityChecks: true, }; - function AppManagementAppTest() {} AppManagementAppTest.prototype = { @@ -55,6 +56,20 @@ mocha.run(); }); +function AppManagementMetadataViewTest() {} + +AppManagementMetadataViewTest.prototype = { + __proto__: AppManagementBrowserTest.prototype, + + extraLibraries: AppManagementBrowserTest.prototype.extraLibraries.concat([ + 'metadata_view_test.js', + ]), +}; + +TEST_F('AppManagementMetadataViewTest', 'All', function() { + mocha.run(); +}); + function AppManagementReducersTest() {} AppManagementReducersTest.prototype = {
diff --git a/chrome/test/data/webui/app_management/app_test.js b/chrome/test/data/webui/app_management/app_test.js index c2eddaf2..207c635 100644 --- a/chrome/test/data/webui/app_management/app_test.js +++ b/chrome/test/data/webui/app_management/app_test.js
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +'use strict'; + suite('<app-management-app>', function() { test('loads', async function() { // Check that the browser responds to the getApps() message.
diff --git a/chrome/test/data/webui/app_management/main_view_test.js b/chrome/test/data/webui/app_management/main_view_test.js index dc3eba52..379591e 100644 --- a/chrome/test/data/webui/app_management/main_view_test.js +++ b/chrome/test/data/webui/app_management/main_view_test.js
@@ -2,74 +2,57 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +'use strict'; + suite('<app-management-main-view>', function() { let mainView; let fakeHandler; - let callbackRouterProxy; let appIdCounter; + /** + * @param {number} numApps + */ + async function addApps(numApps) { + for (let i = 0; i < numApps; i++) { + await fakeHandler.addApp((appIdCounter++).toString()); + } + } + setup(function() { appIdCounter = 0; mainView = document.createElement('app-management-main-view'); PolymerTest.clearBody(); - let browserProxy = app_management.BrowserProxy.getInstance(); - callbackRouterProxy = browserProxy.callbackRouter.createProxy(); - - fakeHandler = new app_management.FakePageHandler(callbackRouterProxy); - browserProxy.handler = fakeHandler; - - app_management.Store.instance_ = new app_management.Store(); - - app_management.Store.getInstance().init( - app_management.util.createEmptyState()); + fakeHandler = setupFakeHandler(); + replaceStore(); document.body.appendChild(mainView); }); - /** - * @param {number} numApps - * @return {!Array<appManagement.mojom.App>} apps - */ - function createTestApps(numApps) { - let apps = []; - for (let i = 0; i < numApps; i++) { - apps.push( - app_management.FakePageHandler.createApp('TestApp' + appIdCounter++)); - } - return apps; - } - - async function addApps(apps) { - for (const app of apps) { - callbackRouterProxy.onAppAdded(app); - } - await callbackRouterProxy.flushForTesting(); - } - test('simple app addition', async function() { // Ensure there is no apps initially expectEquals( 0, mainView.root.querySelectorAll('app-management-app-item').length); - let apps = createTestApps(1); - await addApps(apps); + const appId = '1'; + await fakeHandler.addApp(appId); + let appItems = mainView.root.querySelectorAll('app-management-app-item'); expectEquals(1, appItems.length); - expectEquals(appItems[0].app.id, apps[0].id); + expectEquals(appId, appItems[0].app.id); }); test('more apps bar visibility', async function() { // The more apps bar shouldn't appear when there are 4 apps. - await addApps(createTestApps(4)); + await addApps(4); expectEquals( 4, mainView.root.querySelectorAll('app-management-app-item').length); expectTrue(mainView.$['expander-row'].hidden); // The more apps bar appears when there are 5 apps. - await addApps(createTestApps(1)); + await addApps(1); expectEquals( 5, mainView.root.querySelectorAll('app-management-app-item').length); expectFalse(mainView.$['expander-row'].hidden); @@ -77,14 +60,14 @@ test('notifications sublabel collapsibility', async function() { // The three spans contains collapsible attribute. - await addApps(createTestApps(4)); + await addApps(4); const pieces = await mainView.getNotificationSublabelPieces_(); expectTrue(pieces.filter(p => p.arg === '$1')[0].collapsible); expectTrue(pieces.filter(p => p.arg === '$2')[0].collapsible); expectTrue(pieces.filter(p => p.arg === '$3')[0].collapsible); // Checking ",and other x apps" is non-collapsible - await addApps(createTestApps(6)); + await addApps(6); const pieces2 = await mainView.getNotificationSublabelPieces_(); expectFalse(pieces2.filter(p => p.arg === '$4')[0].collapsible); });
diff --git a/chrome/test/data/webui/app_management/metadata_view_test.js b/chrome/test/data/webui/app_management/metadata_view_test.js new file mode 100644 index 0000000..c337bc5f --- /dev/null +++ b/chrome/test/data/webui/app_management/metadata_view_test.js
@@ -0,0 +1,72 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +suite('<app-management-metadata-view>', function() { + let metadataView; + let fakeHandler; + + const APP_ID = '1'; + + setup(async function() { + metadataView = document.createElement('app-management-metadata-view'); + + PolymerTest.clearBody(); + fakeHandler = setupFakeHandler(); + replaceStore(); + + // Add an app, and make it the currently selected app. + await fakeHandler.addApp(APP_ID); + app_management.Store.getInstance().dispatch( + app_management.actions.changePage(PageType.DETAIL, APP_ID)); + + document.body.appendChild(metadataView); + }); + + test( + 'when app.isPinned is unknown, the pin to shelf toggle is not visible', + async function() { + await fakeHandler.changeApp(APP_ID, {isPinned: OptionalBool.kUnknown}); + + // Check that the toggle is not visible. + const toggle = metadataView.root.getElementById('pin-to-shelf-toggle'); + if (toggle) { + expectTrue(isHidden(toggle)); + } + }); + + test( + 'clicking the pin to shelf toggle changes the isPinned field of the app', + async function() { + // Set app.isPinned to false. + await fakeHandler.changeApp(APP_ID, {isPinned: OptionalBool.kFalse}); + + const toggle = metadataView.root.getElementById('pin-to-shelf-toggle'); + + // Check that the toggle is visible and is not checked. + expectTrue(!!toggle && !isHidden(toggle)); + expectFalse(toggle.checked); + + // Toggle from false to true. + toggle.click(); + await fakeHandler.flushForTesting(); + + // Check that the isPinned field of the app has changed. + expectEquals(OptionalBool.kTrue, metadataView.app_.isPinned); + + // Check that the toggle is now checked. + expectTrue(toggle.checked); + + // Toggle from true to false. + toggle.click(); + await fakeHandler.flushForTesting(); + + // Check that the isPinned field of the app has changed. + expectEquals(OptionalBool.kFalse, metadataView.app_.isPinned); + + // Check that the toggle is no longer checked. + expectFalse(toggle.checked); + }); +});
diff --git a/chrome/test/data/webui/app_management/reducers_test.js b/chrome/test/data/webui/app_management/reducers_test.js index b8a4192..cfac2873 100644 --- a/chrome/test/data/webui/app_management/reducers_test.js +++ b/chrome/test/data/webui/app_management/reducers_test.js
@@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +'use strict'; + suite('app state', function() { let apps; - let action; let state; function createApp(id, config) { @@ -27,8 +28,7 @@ test('updates when an app is added', function() { const newApp = createApp('3', {type: 1, title: 'a'}); - - action = app_management.actions.addApp(newApp); + const action = app_management.actions.addApp(newApp); apps = app_management.AppState.updateApps(apps, action); // Check that apps contains a key for each app id. @@ -45,7 +45,7 @@ test('updates when an app is changed', function() { const changedApp = createApp('2', {type: 1, title: 'a'}); - action = app_management.actions.changeApp(changedApp); + const action = app_management.actions.changeApp(changedApp); apps = app_management.AppState.updateApps(apps, action); // Check that app has changed. @@ -58,7 +58,7 @@ }); test('updates when an app is removed', function() { - action = app_management.actions.removeApp('1'); + const action = app_management.actions.removeApp('1'); apps = app_management.AppState.updateApps(apps, action); // Check that app is removed. @@ -74,7 +74,7 @@ state.currentPage.selectedAppId = '1'; state.currentPage.pageType = PageType.DETAIL; - action = app_management.actions.removeApp('1'); + let action = app_management.actions.removeApp('1'); state = app_management.reduceAction(state, action); assertEquals(null, state.currentPage.selectedAppId); @@ -97,7 +97,7 @@ state.currentPage.selectedAppId = '1'; state.currentPage.pageType = PageType.DETAIL; - action = app_management.actions.changePage(PageType.MAIN); + let action = app_management.actions.changePage(PageType.MAIN); state = app_management.reduceAction(state, action); assertEquals(null, state.currentPage.selectedAppId); @@ -113,7 +113,7 @@ test('state updates when changing to app detail page', function() { // State updates when a valid app detail page is selected. - action = app_management.actions.changePage(PageType.DETAIL, '2'); + let action = app_management.actions.changePage(PageType.DETAIL, '2'); state = app_management.reduceAction(state, action); assertEquals('2', state.currentPage.selectedAppId); @@ -131,7 +131,7 @@ }); test('state updates when changing to notifications page', function() { - action = app_management.actions.changePage(PageType.NOTIFICATIONS); + const action = app_management.actions.changePage(PageType.NOTIFICATIONS); state = app_management.reduceAction(state, action); assertEquals(PageType.NOTIFICATIONS, state.currentPage.pageType);
diff --git a/chrome/test/data/webui/app_management/test_util.js b/chrome/test/data/webui/app_management/test_util.js new file mode 100644 index 0000000..d11716b --- /dev/null +++ b/chrome/test/data/webui/app_management/test_util.js
@@ -0,0 +1,37 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +/** + * @return {app_management.FakePageHandler} + */ +function setupFakeHandler() { + const browserProxy = app_management.BrowserProxy.getInstance(); + const callbackRouterProxy = browserProxy.callbackRouter.createProxy(); + + const fakeHandler = new app_management.FakePageHandler(callbackRouterProxy); + browserProxy.handler = fakeHandler; + + return fakeHandler; +} + +/** + * Replace the app management store instance with a new, empty store. + */ +function replaceStore() { + app_management.Store.instance_ = new app_management.Store(); + + app_management.Store.getInstance().init( + app_management.util.createEmptyState()); +} + +/** + * @param {Element} element + * @return {bool} + */ +function isHidden(element) { + const rect = element.getBoundingClientRect(); + return rect.height === 0 && rect.width === 0; +}
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js index b7b2e1e..a444757 100644 --- a/chrome/test/data/webui/settings/people_page_sync_page_test.js +++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -536,13 +536,43 @@ const cancelButton = syncPage.$$('settings-sync-account-control') .shadowRoot.querySelector('#setup-buttons .secondary-button'); - assertTrue(!!cancelButton); - cancelButton.click(); - return browserProxy.whenCalled('didNavigateAwayFromSyncPage') - .then(abort => { - assertTrue(abort); + // Clicking the setup cancel button opens the 'Cancel sync?' dialog. + cancelButton.click(); + Polymer.dom.flush(); + + assertEquals(settings.routes.SYNC, settings.getCurrentRoute()); + assertTrue(!!syncPage.$$('#setupCancelDialog')); + assertTrue(syncPage.$$('#setupCancelDialog').open); + + // Clicking the cancel button on the 'Cancel sync?' dialog closes the + // dialog and removes it from the DOM. + syncPage.$$('#setupCancelDialog') + .querySelector('.cancel-button') + .click(); + return test_util + .eventToPromise('close', syncPage.$$('#setupCancelDialog')) + .then(() => { + Polymer.dom.flush(); + assertEquals(settings.routes.SYNC, settings.getCurrentRoute()); + assertFalse(!!syncPage.$$('#setupCancelDialog')); + + // Clicking the setup cancel button shows the 'Cancel sync?' + // dialog again. + cancelButton.click(); + Polymer.dom.flush(); + assertTrue(syncPage.$$('#setupCancelDialog').open); + + // Clicking the confirm button on the dialog aborts sync. + syncPage.$$('#setupCancelDialog') + .querySelector('.action-button') + .click(); + + return browserProxy.whenCalled('didNavigateAwayFromSyncPage') + .then(abort => { + assertTrue(abort); + }); }); }); @@ -573,9 +603,26 @@ test('SyncSetupLeavePage UnifiedConsentEnabled', function() { syncPage.unifiedConsentEnabled = true; + syncPage.syncStatus = { + signinAllowed: true, + syncSystemEnabled: true, + setupInProgress: true, + signedIn: true + }; Polymer.dom.flush(); + // Navigating away while setup is in progress opens the 'Cancel sync?' + // dialog. settings.navigateTo(settings.routes.BASIC); + Polymer.dom.flush(); + + assertEquals(settings.routes.SYNC, settings.getCurrentRoute()); + assertTrue(syncPage.$$('#setupCancelDialog').open); + + // Clicking the confirm button on the dialog aborts sync. + syncPage.$$('#setupCancelDialog') + .querySelector('.action-button') + .click(); return browserProxy.whenCalled('didNavigateAwayFromSyncPage') .then(abort => {
diff --git a/components/arc/common/app.mojom b/components/arc/common/app.mojom index 203e4dd..99489cd 100644 --- a/components/arc/common/app.mojom +++ b/components/arc/common/app.mojom
@@ -191,6 +191,42 @@ kDynamic = 1, }; +[Extensible] +enum AppReinstallState { + // Request and response successful. + REQUEST_SUCCESS = 0, + // Request Timeout + REQUEST_TIMEOUT = 1, + // No Account. + REQUEST_NO_ACCOUNT = 2, + // Null data from aidl. + REQUEST_NULL_DATA = 3, + // Data that can't be converted from aidl bundle to mojom struct. + REQUEST_BUNDLE_ERROR = 4, + // Request failure other reason. + REQUEST_UNKNOWN_FAILURE = 5, +}; + +// Describes app reinstall candidates that are shown to users as suggestions. +struct AppReinstallCandidate { + // The package name of this in the Play Store. + string package_name; + + // The title of this package in the Play Store. + string title; + + // The url of an icon for this package. Optional, a default icon is used if + // unset. + string? icon_url; + + // Ratings Count from Play Store for this package. e.g. "17103" . + // Default of 0 if not set. + int64 rating_count; + + // Mean star rating for this package, [1, 5]. 0 indicates missing. + float star_rating; +}; + // Describes app shortcut that is published by Android's ShortcutManager. struct AppShortcutItem { // The ID of this shortcut. Unique within each publisher app and stable across @@ -432,6 +468,12 @@ // Sends a request to ARC to start FastAppReinstall flow. [MinVersion=33] StartFastAppReinstallFlow@25(array<string> arc_package_names); + // Sends a request to ARC to retrieve an array of app reinstall + // candidates for this user on this device. Order of results is in an + // unspecified order of relevance from Play Store. + [MinVersion=39] GetAppReinstallCandidates@31() => + (AppReinstallState state, array<AppReinstallCandidate> candidates); + // Sends a request to ARC to uninstall the given package. Error (if ever // happens) is ignored, and uninstall option should appear in the UI. [MinVersion=2] UninstallPackage@5(string package_name);
diff --git a/components/arc/test/fake_app_instance.cc b/components/arc/test/fake_app_instance.cc index d479edd..7011018 100644 --- a/components/arc/test/fake_app_instance.cc +++ b/components/arc/test/fake_app_instance.cc
@@ -467,6 +467,17 @@ std::move(callback).Run(pai_state_response_); } +void FakeAppInstance::GetAppReinstallCandidates( + GetAppReinstallCandidatesCallback callback) { + ++get_app_reinstall_callback_count_; + std::vector<arc::mojom::AppReinstallCandidatePtr> candidates; + for (const auto& candidate : app_reinstall_candidates_) + candidates.emplace_back(candidate.Clone()); + + std::move(callback).Run(arc::mojom::AppReinstallState::REQUEST_SUCCESS, + std::move(candidates)); +} + void FakeAppInstance::StartFastAppReinstallFlow( const std::vector<std::string>& package_names) { ++start_fast_app_reinstall_request_count_; @@ -516,4 +527,11 @@ void FakeAppInstance::RemoveCachedIcon(const std::string& icon_resource_id) {} +void FakeAppInstance::SetAppReinstallCandidates( + const std::vector<arc::mojom::AppReinstallCandidatePtr>& candidates) { + app_reinstall_candidates_.clear(); + for (const auto& candidate : candidates) + app_reinstall_candidates_.emplace_back(candidate.Clone()); +} + } // namespace arc
diff --git a/components/arc/test/fake_app_instance.h b/components/arc/test/fake_app_instance.h index e5eca74..c1b848a 100644 --- a/components/arc/test/fake_app_instance.h +++ b/components/arc/test/fake_app_instance.h
@@ -156,8 +156,11 @@ GetAppShortcutGlobalQueryItemsCallback callback) override; void GetAppShortcutItems(const std::string& package_name, GetAppShortcutItemsCallback callback) override; + void StartPaiFlowDeprecated() override; void StartPaiFlow(StartPaiFlowCallback callback) override; + void GetAppReinstallCandidates( + GetAppReinstallCandidatesCallback callback) override; void StartFastAppReinstallFlow( const std::vector<std::string>& package_names) override; void RequestAssistStructure(RequestAssistStructureCallback callback) override; @@ -231,6 +234,10 @@ return launch_intents_; } + int get_app_reinstall_callback_count() const { + return get_app_reinstall_callback_count_; + } + const std::vector<std::unique_ptr<IconRequest>>& icon_requests() const { return icon_requests_; } @@ -240,6 +247,9 @@ return shortcut_icon_requests_; } + void SetAppReinstallCandidates( + const std::vector<arc::mojom::AppReinstallCandidatePtr>& candidates); + private: using TaskIdToInfo = std::map<int32_t, std::unique_ptr<Request>>; // Mojo endpoints. @@ -254,6 +264,11 @@ int start_fast_app_reinstall_request_count_ = 0; // Keeps information about launch app shortcut requests. int launch_app_shortcut_item_count_ = 0; + // Keeps info about the number of times we got a request for app reinstalls. + int get_app_reinstall_callback_count_ = 0; + + // Vector to send as app reinstall candidates. + std::vector<arc::mojom::AppReinstallCandidatePtr> app_reinstall_candidates_; // Keeps information about launch requests. std::vector<std::unique_ptr<Request>> launch_requests_; // Keeps information about launch intents.
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 6f71f1eb..def89f8 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -179,6 +179,8 @@ "strike_database.h", "strike_database_integrator_base.cc", "strike_database_integrator_base.h", + "strike_database_integrator_test_strike_database.cc", + "strike_database_integrator_test_strike_database.h", "subkey_requester.cc", "subkey_requester.h", "suggestion.cc", @@ -385,8 +387,6 @@ "test_legacy_strike_database.h", "test_local_card_migration_manager.cc", "test_local_card_migration_manager.h", - "test_local_card_migration_strike_database.cc", - "test_local_card_migration_strike_database.h", "test_personal_data_manager.cc", "test_personal_data_manager.h", "test_region_data_loader.cc", @@ -512,7 +512,6 @@ "country_names_unittest.cc", "credit_card_field_unittest.cc", "credit_card_save_manager_unittest.cc", - "credit_card_save_strike_database_unittest.cc", "credit_card_unittest.cc", "field_candidates_unittest.cc", "field_filler_unittest.cc", @@ -522,7 +521,6 @@ "legacy_strike_database_unittest.cc", "legal_message_line_unittest.cc", "local_card_migration_manager_unittest.cc", - "local_card_migration_strike_database_unittest.cc", "name_field_unittest.cc", "password_generator_fips181_unittest.cc", "password_generator_unittest.cc", @@ -540,6 +538,7 @@ "rationalization_util_unittest.cc", "region_combobox_model_unittest.cc", "search_field_unittest.cc", + "strike_database_integrator_test_strike_database_unittest.cc", "strike_database_unittest.cc", "subkey_requester_unittest.cc", "suggestion_selection_unittest.cc",
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc index 3c637d11..6e40565 100644 --- a/components/autofill/core/browser/autofill_metrics.cc +++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -1473,6 +1473,7 @@ void AutofillMetrics::LogAutofillFormSubmittedState( AutofillFormSubmittedState state, bool is_for_credit_card, + bool has_upi_vpa_field, const std::set<FormType>& form_types, const base::TimeTicks& form_parsed_timestamp, FormSignature form_signature, @@ -1510,9 +1511,9 @@ NOTREACHED(); break; } - form_interactions_ukm_logger->LogFormSubmitted(is_for_credit_card, form_types, - state, form_parsed_timestamp, - form_signature); + form_interactions_ukm_logger->LogFormSubmitted( + is_for_credit_card, has_upi_vpa_field, form_types, state, + form_parsed_timestamp, form_signature); } // static @@ -2198,6 +2199,7 @@ void AutofillMetrics::FormInteractionsUkmLogger::LogFormSubmitted( bool is_for_credit_card, + bool has_upi_vpa_field, const std::set<FormType>& form_types, AutofillFormSubmittedState state, const base::TimeTicks& form_parsed_timestamp, @@ -2208,6 +2210,7 @@ ukm::builders::Autofill_FormSubmitted builder(source_id_); builder.SetAutofillFormSubmittedState(static_cast<int>(state)) .SetIsForCreditCard(is_for_credit_card) + .SetHasUpiVpaField(has_upi_vpa_field) .SetFormTypes(FormTypesToBitVector(form_types)) .SetFormSignature(HashFormSignature(form_signature)); if (form_parsed_timestamp.is_null())
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h index 0391e0d..2e2f615 100644 --- a/components/autofill/core/browser/autofill_metrics.h +++ b/components/autofill/core/browser/autofill_metrics.h
@@ -891,6 +891,7 @@ ServerFieldType predicted_type, ServerFieldType actual_type); void LogFormSubmitted(bool is_for_credit_card, + bool has_upi_vpa_field, const std::set<FormType>& form_types, AutofillFormSubmittedState state, const base::TimeTicks& form_parsed_timestamp, @@ -1212,6 +1213,7 @@ static void LogAutofillFormSubmittedState( AutofillFormSubmittedState state, bool is_for_credit_card, + bool has_upi_vpa_field, const std::set<FormType>& form_types, const base::TimeTicks& form_parsed_timestamp, FormSignature form_signature,
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc index d44102b..8dcda40 100644 --- a/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -154,12 +154,14 @@ const FormData& form, AutofillMetrics::AutofillFormSubmittedState state, bool is_for_credit_card, + bool has_upi_vpa_field, const std::set<FormType>& form_types) { VerifyFormInteractionUkm( ukm_recorder, form, UkmFormSubmittedType::kEntryName, {{{UkmFormSubmittedType::kAutofillFormSubmittedStateName, state}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, is_for_credit_card}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, has_upi_vpa_field}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector(form_types)}, {UkmFormSubmittedType::kFormSignatureName, @@ -3158,9 +3160,37 @@ Collapse(CalculateFormSignature(form))}}}); // Expect |NON_FILLABLE_FORM_OR_NEW_DATA| in |AutofillFormSubmittedState| // because |field.value| is empty in |DeterminePossibleFieldTypesForUpload|. - VerifySubmitFormUkm( - test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, - /*is_for_credit_card=*/true, {FormType::CREDIT_CARD_FORM}); + VerifySubmitFormUkm(test_ukm_recorder_, form, + AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, + /*is_for_credit_card=*/true, /* has_upi_vpa_field=*/false, + {FormType::CREDIT_CARD_FORM}); +} + +// Test that the UPI Checkout flow form submit is correctly logged +TEST_F(AutofillMetricsTest, UpiVpaUkmTest) { + FormData form; + form.name = ASCIIToUTF16("TestForm"); + form.origin = GURL("http://example.com/form.html"); + form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = url::Origin::Create(autofill_client_.form_origin()); + FormFieldData field; + test::CreateTestFormField("Enter VPA", "upi-vpa", "unique_id@upi", "text", + &field); + form.fields.push_back(field); + + std::vector<FormData> forms(1, form); + + { + autofill_manager_->OnFormsSeen(forms, TimeTicks::Now()); + + VerifySubmitFormUkm(test_ukm_recorder_, forms.back(), + AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, + /*is_for_credit_card=*/false, + /* has_upi_vpa_field */ true, + /* UPI VPA has Unknown form type.*/ + {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE}); + PurgeUKM(); + } } // Test that the profile checkout flow user actions are correctly logged. @@ -3297,7 +3327,8 @@ // because |field.value| is empty in |DeterminePossibleFieldTypesForUpload|. VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, - /*is_for_credit_card=*/false, {FormType::ADDRESS_FORM}); + /*is_for_credit_card=*/false, + /* has_upi_vpa_field=*/false, {FormType::ADDRESS_FORM}); } // Tests that the Autofill_PolledCreditCardSuggestions user action is only @@ -4678,6 +4709,7 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, + /* has_upi_vpa_field=*/false, {FormType::CREDIT_CARD_FORM}); } @@ -4721,6 +4753,7 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, + /* has_upi_vpa_field=*/false, {FormType::CREDIT_CARD_FORM}); } @@ -4768,6 +4801,7 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, + /* has_upi_vpa_field=*/false, {FormType::CREDIT_CARD_FORM}); } @@ -4812,6 +4846,7 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, + /* has_upi_vpa_field=*/false, {FormType::CREDIT_CARD_FORM}); } @@ -4858,6 +4893,7 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, + /* has_upi_vpa_field=*/false, {FormType::CREDIT_CARD_FORM}); } @@ -4909,6 +4945,7 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, + /* has_upi_vpa_field=*/false, {FormType::CREDIT_CARD_FORM}); } @@ -4936,6 +4973,7 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, + /* has_upi_vpa_field=*/false, {FormType::CREDIT_CARD_FORM}); autofill_manager_->OnFormSubmitted(form, false, @@ -4947,6 +4985,7 @@ AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, true}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector({FormType::CREDIT_CARD_FORM})}, {UkmFormSubmittedType::kFormSignatureName, @@ -4955,6 +4994,7 @@ AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, true}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector({FormType::CREDIT_CARD_FORM})}, {UkmFormSubmittedType::kFormSignatureName, @@ -5125,6 +5165,7 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, + /* has_upi_vpa_field=*/false, {FormType::CREDIT_CARD_FORM}); } } @@ -5889,7 +5930,8 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, - /*is_for_credit_card=*/false, {FormType::ADDRESS_FORM}); + /*is_for_credit_card=*/false, + /* has_upi_vpa_field=*/false, {FormType::ADDRESS_FORM}); } // Reset the autofill manager state and purge UKM logs. @@ -5917,7 +5959,8 @@ VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, - /*is_for_credit_card=*/false, {FormType::ADDRESS_FORM}); + /*is_for_credit_card=*/false, + /* has_upi_vpa_field=*/false, {FormType::ADDRESS_FORM}); } // Reset the autofill manager state and purge UKM logs. @@ -6482,6 +6525,7 @@ AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, false}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector( {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, @@ -6518,6 +6562,7 @@ AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, false}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector( {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, @@ -6558,6 +6603,7 @@ FILLABLE_FORM_AUTOFILLED_NONE_DID_NOT_SHOW_SUGGESTIONS}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, false}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector( {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, @@ -6605,6 +6651,7 @@ AutofillMetrics::FILLABLE_FORM_AUTOFILLED_NONE_DID_SHOW_SUGGESTIONS}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, false}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector( {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, @@ -6641,6 +6688,7 @@ AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, false}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector( {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, @@ -6678,6 +6726,7 @@ AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, false}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector( {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, @@ -6722,6 +6771,7 @@ AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, false}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector( {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, @@ -6797,6 +6847,7 @@ AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmFormSubmittedType::kIsForCreditCardName, false}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, false}, {UkmFormSubmittedType::kFormTypesName, AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, {UkmFormSubmittedType::kFormSignatureName,
diff --git a/components/autofill/core/browser/credit_card_save_manager.h b/components/autofill/core/browser/credit_card_save_manager.h index a1ae70e..1489879 100644 --- a/components/autofill/core/browser/credit_card_save_manager.h +++ b/components/autofill/core/browser/credit_card_save_manager.h
@@ -124,6 +124,7 @@ private: friend class CreditCardSaveManagerTest; friend class CreditCardSaveManagerTestObserverBridge; + friend class LocalCardMigrationBrowserTest; friend class TestCreditCardSaveManager; friend class SaveCardBubbleViewsFullFormBrowserTest;
diff --git a/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc b/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc deleted file mode 100644 index 6628663..0000000 --- a/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc +++ /dev/null
@@ -1,138 +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 "components/autofill/core/browser/credit_card_save_strike_database.h" - -#include <utility> -#include <vector> - -#include "base/files/scoped_temp_dir.h" -#include "base/run_loop.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/autofill/core/browser/proto/strike_data.pb.h" -#include "components/autofill/core/browser/test_autofill_clock.h" -#include "components/autofill/core/browser/test_credit_card_save_strike_database.h" -#include "components/autofill/core/common/autofill_clock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace autofill { - -class CreditCardSaveStrikeDatabaseTest : public ::testing::Test { - public: - CreditCardSaveStrikeDatabaseTest() - : strike_database_(new StrikeDatabase(InitFilePath())) {} - - protected: - base::HistogramTester* GetHistogramTester() { return &histogram_tester_; } - base::test::ScopedTaskEnvironment scoped_task_environment_; - TestCreditCardSaveStrikeDatabase strike_database_; - - private: - static const base::FilePath InitFilePath() { - base::ScopedTempDir temp_dir_; - EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - const base::FilePath file_path = - temp_dir_.GetPath().AppendASCII("StrikeDatabaseTest"); - return file_path; - } - - base::HistogramTester histogram_tester_; -}; - -TEST_F(CreditCardSaveStrikeDatabaseTest, GetKeyForCreditCardSaveTest) { - const std::string last_four = "1234"; - EXPECT_EQ("CreditCardSave__1234", strike_database_.GetKey(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, MaxStrikesLimitReachedTest) { - const std::string last_four = "1234"; - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(last_four)); - // 1st strike added for |last_four|. - strike_database_.AddStrike(last_four); - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(last_four)); - // 2nd strike added for |last_four|. - strike_database_.AddStrike(last_four); - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(last_four)); - // 3rd strike added for |last_four|. - strike_database_.AddStrike(last_four); - EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, - CreditCardSaveNthStrikeAddedHistogram) { - const std::string last_four1 = "1234"; - const std::string last_four2 = "9876"; - // 1st strike added for |last_four1|. - strike_database_.AddStrike(last_four1); - // 2nd strike added for |last_four1|. - strike_database_.AddStrike(last_four1); - // 1st strike added for |last_four2|. - strike_database_.AddStrike(last_four2); - std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( - "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave"); - // There should be two buckets, one for 1st strike, one for 2nd strike count. - ASSERT_EQ(2U, buckets.size()); - // Both |last_four1| and |last_four2| have 1st strikes recorded. - EXPECT_EQ(2, buckets[0].count); - // Only |last_four1| has 2nd strike recorded. - EXPECT_EQ(1, buckets[1].count); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, - AddStrikeForZeroAndNonZeroStrikesTest) { - const std::string last_four = "1234"; - EXPECT_EQ(0, strike_database_.GetStrikes(last_four)); - strike_database_.AddStrike(last_four); - EXPECT_EQ(1, strike_database_.GetStrikes(last_four)); - strike_database_.AddStrike(last_four); - EXPECT_EQ(2, strike_database_.GetStrikes(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, ClearStrikesForNonZeroStrikesTest) { - const std::string last_four = "1234"; - strike_database_.AddStrike(last_four); - EXPECT_EQ(1, strike_database_.GetStrikes(last_four)); - strike_database_.ClearStrikes(last_four); - EXPECT_EQ(0, strike_database_.GetStrikes(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, ClearStrikesForZeroStrikesTest) { - const std::string last_four = "1234"; - strike_database_.ClearStrikes(last_four); - EXPECT_EQ(0, strike_database_.GetStrikes(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, RemoveExpiredStrikesTest) { - autofill::TestAutofillClock test_clock; - test_clock.SetNow(AutofillClock::Now()); - const std::string last_four1 = "1234"; - const std::string last_four2 = "9876"; - strike_database_.AddStrike(last_four1); - - // Advance clock to past the entry for |last_four1|'s expiry time. - test_clock.Advance(base::TimeDelta::FromMicroseconds( - strike_database_.GetExpiryTimeMicros() + 1)); - - strike_database_.AddStrike(last_four2); - strike_database_.RemoveExpiredStrikes(); - - // |last_four1|'s entry should have its most recent strike expire, but - // |last_four2|'s should not. - EXPECT_EQ(0, strike_database_.GetStrikes(last_four1)); - EXPECT_EQ(1, strike_database_.GetStrikes(last_four2)); - - // Advance clock to past |last_four2|'s expiry time. - test_clock.Advance(base::TimeDelta::FromMicroseconds( - strike_database_.GetExpiryTimeMicros() + 1)); - - strike_database_.RemoveExpiredStrikes(); - - // |last_four1| and |last_four2| should have no more unexpired strikes. - EXPECT_EQ(0, strike_database_.GetStrikes(last_four1)); - EXPECT_EQ(0, strike_database_.GetStrikes(last_four2)); -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/form_data_importer.h b/components/autofill/core/browser/form_data_importer.h index 7fe9efed..56e32ab1 100644 --- a/components/autofill/core/browser/form_data_importer.h +++ b/components/autofill/core/browser/form_data_importer.h
@@ -145,6 +145,7 @@ friend class AutofillMergeTest; friend class FormDataImporterTest; friend class FormDataImporterTestBase; + friend class LocalCardMigrationBrowserTest; friend class SaveCardBubbleViewsFullFormBrowserTest; friend class SaveCardInfobarEGTestHelper; FRIEND_TEST_ALL_PREFIXES(AutofillMergeTest, MergeProfiles);
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 006b157..c715abb 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -966,6 +966,7 @@ bool did_autofill_all_possible_fields = true; bool did_autofill_some_possible_fields = false; bool is_for_credit_card = IsCompleteCreditCardForm(); + bool has_upi_vpa_field = false; // Determine the correct suffix for the metric, depending on whether or // not a submission was observed. @@ -976,6 +977,7 @@ for (size_t i = 0; i < field_count(); ++i) { auto* const field = this->field(i); if (IsUPIVirtualPaymentAddress(field->value)) { + has_upi_vpa_field = true; AutofillMetrics::LogUserHappinessMetric( AutofillMetrics::USER_DID_ENTER_UPI_VPA, field->Type().group(), security_state::SecurityLevel::SECURITY_LEVEL_COUNT); @@ -1060,8 +1062,8 @@ } AutofillMetrics::LogAutofillFormSubmittedState( - state, is_for_credit_card, GetFormTypes(), form_parsed_timestamp_, - form_signature(), form_interactions_ukm_logger); + state, is_for_credit_card, has_upi_vpa_field, GetFormTypes(), + form_parsed_timestamp_, form_signature(), form_interactions_ukm_logger); } }
diff --git a/components/autofill/core/browser/local_card_migration_manager.cc b/components/autofill/core/browser/local_card_migration_manager.cc index 764f915..bc9634e 100644 --- a/components/autofill/core/browser/local_card_migration_manager.cc +++ b/components/autofill/core/browser/local_card_migration_manager.cc
@@ -88,6 +88,9 @@ return; migration_request_ = payments::PaymentsClient::MigrationRequestDetails(); + if (observer_for_testing_) + observer_for_testing_->OnDecideToRequestLocalCardMigration(); + payments_client_->GetUploadDetails( std::vector<AutofillProfile>(), GetDetectedValues(), /*active_experiments=*/std::vector<const char*>(), app_locale_, @@ -145,15 +148,25 @@ bool migration_experiment_enabled = features::GetLocalCardMigrationExperimentalFlag() != features::LocalCardMigrationExperimentalFlag::kMigrationDisabled; - bool credit_card_upload_enabled = ::autofill::IsCreditCardUploadEnabled( - client_->GetPrefs(), client_->GetSyncService(), - client_->GetIdentityManager()->GetPrimaryAccountInfo().email); + + // If |observer_for_testing_| is set, assume we are in a browsertest and + // credit card upload should be enabled by default. Cannot get around this as + // Chrome OS testing requires an unsupported email domain (i.e. + // stub-user@example.com). + bool credit_card_upload_enabled = + observer_for_testing_ || + ::autofill::IsCreditCardUploadEnabled( + client_->GetPrefs(), client_->GetSyncService(), + client_->GetIdentityManager()->GetPrimaryAccountInfo().email); + bool has_google_payments_account = (payments::GetBillingCustomerId(personal_data_manager_, payments_client_->GetPrefService()) != 0); + bool sync_feature_enabled = (personal_data_manager_->GetSyncSigninState() == AutofillSyncSigninState::kSignedInAndSyncFeature); + return migration_experiment_enabled && credit_card_upload_enabled && has_google_payments_account && sync_feature_enabled; } @@ -163,6 +176,9 @@ AutofillClient::PaymentsRpcResult result, const base::string16& context_token, std::unique_ptr<base::Value> legal_message) { + if (observer_for_testing_) + observer_for_testing_->OnReceivedGetUploadDetailsResponse(); + if (result == AutofillClient::SUCCESS) { migration_request_.context_token = context_token; legal_message_ = base::DictionaryValue::From(std::move(legal_message)); @@ -196,6 +212,9 @@ AutofillClient::PaymentsRpcResult result, std::unique_ptr<std::unordered_map<std::string, std::string>> save_result, const std::string& display_text) { + if (observer_for_testing_) + observer_for_testing_->OnReceivedMigrateCardsResponse(); + if (!save_result) return; @@ -254,6 +273,9 @@ // Send the migration request. Will call payments_client to create a new // PaymentsRequest. Also create a new callback function OnDidMigrateLocalCards. void LocalCardMigrationManager::SendMigrateLocalCardsRequest() { + if (observer_for_testing_) + observer_for_testing_->OnSentMigrateCardsRequest(); + migration_request_.app_locale = app_locale_; migration_request_.billing_customer_number = payments::GetBillingCustomerId( personal_data_manager_, payments_client_->GetPrefService());
diff --git a/components/autofill/core/browser/local_card_migration_manager.h b/components/autofill/core/browser/local_card_migration_manager.h index 06e5ce5..dc2fa329 100644 --- a/components/autofill/core/browser/local_card_migration_manager.h +++ b/components/autofill/core/browser/local_card_migration_manager.h
@@ -43,7 +43,7 @@ FAILURE_ON_UPLOAD, }; - MigratableCreditCard(const CreditCard& credit_card); + explicit MigratableCreditCard(const CreditCard& credit_card); ~MigratableCreditCard(); CreditCard credit_card() const { return credit_card_; } @@ -66,6 +66,16 @@ // Owned by FormDataImporter. class LocalCardMigrationManager { public: + // An observer class used by browsertests that gets notified whenever + // particular actions occur. + class ObserverForTest { + public: + virtual void OnDecideToRequestLocalCardMigration() = 0; + virtual void OnReceivedGetUploadDetailsResponse() = 0; + virtual void OnSentMigrateCardsRequest() = 0; + virtual void OnReceivedMigrateCardsResponse() = 0; + }; + // The parameters should outlive the LocalCardMigrationManager. LocalCardMigrationManager(AutofillClient* client, payments::PaymentsClient* payments_client, @@ -141,6 +151,7 @@ payments::PaymentsClient* payments_client_; private: + friend class LocalCardMigrationBrowserTest; FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationManagerTest, MigrateCreditCard_MigrationPermanentFailure); FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationManagerTest, @@ -161,6 +172,11 @@ // Finalizes the migration request and calls PaymentsClient. void SendMigrateLocalCardsRequest(); + // For testing. + void SetEventObserverForTesting(ObserverForTest* observer) { + observer_for_testing_ = observer; + } + std::unique_ptr<base::DictionaryValue> legal_message_; std::string app_locale_; @@ -187,6 +203,9 @@ // Record the triggering source of the local card migration. AutofillMetrics::LocalCardMigrationOrigin local_card_migration_origin_; + // Initialized only during tests. + ObserverForTest* observer_for_testing_ = nullptr; + base::WeakPtrFactory<LocalCardMigrationManager> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(LocalCardMigrationManager);
diff --git a/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc b/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc deleted file mode 100644 index c7d3ad0..0000000 --- a/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/autofill/core/browser/local_card_migration_strike_database.h" - -#include <utility> -#include <vector> - -#include "base/files/scoped_temp_dir.h" -#include "base/run_loop.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/autofill/core/browser/proto/strike_data.pb.h" -#include "components/autofill/core/browser/test_autofill_clock.h" -#include "components/autofill/core/browser/test_local_card_migration_strike_database.h" -#include "components/autofill/core/common/autofill_clock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace autofill { - -class LocalCardMigrationStrikeDatabaseTest : public ::testing::Test { - public: - LocalCardMigrationStrikeDatabaseTest() - : strike_database_(new StrikeDatabase(InitFilePath())) {} - - protected: - base::HistogramTester* GetHistogramTester() { return &histogram_tester_; } - base::test::ScopedTaskEnvironment scoped_task_environment_; - TestLocalCardMigrationStrikeDatabase strike_database_; - - private: - static const base::FilePath InitFilePath() { - base::ScopedTempDir temp_dir_; - EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - const base::FilePath file_path = - temp_dir_.GetPath().AppendASCII("StrikeDatabaseTest"); - return file_path; - } - - base::HistogramTester histogram_tester_; -}; - -TEST_F(LocalCardMigrationStrikeDatabaseTest, MaxStrikesLimitReachedTest) { - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached()); - // 3 strikes added. - strike_database_.AddStrikes(3); - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached()); - // 4 strike added, total strike count is 7. - strike_database_.AddStrikes(4); - EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached()); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, - LocalCardMigrationNthStrikeAddedHistogram) { - // 2 strikes logged. - strike_database_.AddStrikes(2); - strike_database_.RemoveStrikes(2); - // 1 strike logged. - strike_database_.AddStrike(); - // 2 strikes logged. - strike_database_.AddStrike(); - std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( - "Autofill.StrikeDatabase.NthStrikeAdded.LocalCardMigration"); - // There should be two buckets, for strike counts of 1 and 2. - ASSERT_EQ(2U, buckets.size()); - // Bucket for 1 strike should have count of 1. - EXPECT_EQ(1, buckets[0].count); - // Bucket for 2 strikes should have count of 2. - EXPECT_EQ(2, buckets[1].count); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, - AddStrikeForZeroAndNonZeroStrikesTest) { - EXPECT_EQ(0, strike_database_.GetStrikes()); - strike_database_.AddStrike(); - EXPECT_EQ(1, strike_database_.GetStrikes()); - strike_database_.AddStrikes(2); - EXPECT_EQ(3, strike_database_.GetStrikes()); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, - ClearStrikesForNonZeroStrikesTest) { - strike_database_.AddStrikes(3); - EXPECT_EQ(3, strike_database_.GetStrikes()); - strike_database_.ClearStrikes(); - EXPECT_EQ(0, strike_database_.GetStrikes()); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, ClearStrikesForZeroStrikesTest) { - strike_database_.ClearStrikes(); - EXPECT_EQ(0, strike_database_.GetStrikes()); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, RemoveExpiredStrikesTest) { - autofill::TestAutofillClock test_clock; - test_clock.SetNow(AutofillClock::Now()); - strike_database_.AddStrikes(2); - EXPECT_EQ(2, strike_database_.GetStrikes()); - - // Advance clock to past expiry time. - test_clock.Advance(base::TimeDelta::FromMicroseconds( - strike_database_.GetExpiryTimeMicros() + 1)); - - // One strike should be removed. - strike_database_.RemoveExpiredStrikes(); - EXPECT_EQ(1, strike_database_.GetStrikes()); -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/strike_database_integrator_base.cc b/components/autofill/core/browser/strike_database_integrator_base.cc index f643819..b4f544e 100644 --- a/components/autofill/core/browser/strike_database_integrator_base.cc +++ b/components/autofill/core/browser/strike_database_integrator_base.cc
@@ -4,6 +4,7 @@ #include "components/autofill/core/browser/strike_database_integrator_base.h" +#include <algorithm> #include <string> #include <utility> #include <vector> @@ -81,8 +82,15 @@ expired_keys.push_back(entry.first); } } - for (std::string key : expired_keys) - strike_database_->RemoveStrikes(1, key); + for (std::string key : expired_keys) { + int strikes_to_remove = 1; + // If the key is already over the limit, remove additional strikes to + // emulate setting it back to the limit. These are done together to avoid + // multiple calls to the file system ProtoDatabase. + strikes_to_remove += + std::max(0, strike_database_->GetStrikes(key) - GetMaxStrikesLimit()); + strike_database_->RemoveStrikes(strikes_to_remove, key); + } } std::string StrikeDatabaseIntegratorBase::GetKey(const std::string id) {
diff --git a/components/autofill/core/browser/strike_database_integrator_base.h b/components/autofill/core/browser/strike_database_integrator_base.h index 9f207da..7996986 100644 --- a/components/autofill/core/browser/strike_database_integrator_base.h +++ b/components/autofill/core/browser/strike_database_integrator_base.h
@@ -56,14 +56,12 @@ private: FRIEND_TEST_ALL_PREFIXES(ChromeBrowsingDataRemoverDelegateTest, StrikeDatabaseEmptyOnAutofillRemoveEverything); - FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest, - GetKeyForCreditCardSaveTest); - FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest, - GetIdForCreditCardSaveTest); - FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest, + FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest, RemoveExpiredStrikesTest); - FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationStrikeDatabaseTest, - RemoveExpiredStrikesTest); + FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + GetKeyForStrikeDatabaseIntegratorUniqueIdTest); + FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + RemoveExpiredStrikesUniqueIdTest); friend class StrikeDatabaseTest; friend class StrikeDatabaseTester;
diff --git a/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc b/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc new file mode 100644 index 0000000..c5be513 --- /dev/null +++ b/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc
@@ -0,0 +1,46 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h" + +#include "components/autofill/core/browser/proto/strike_data.pb.h" + +namespace autofill { + +const char kProjectPrefix[] = "StrikeDatabaseIntegratorTest"; +const int kMaxStrikesLimit = 6; +// Expiry time is 1 year. +const long long kExpiryTimeMicros = (long long)1000000 * 60 * 60 * 24 * 365; + +StrikeDatabaseIntegratorTestStrikeDatabase:: + StrikeDatabaseIntegratorTestStrikeDatabase(StrikeDatabase* strike_database) + : StrikeDatabaseIntegratorBase(strike_database) { + RemoveExpiredStrikes(); +} + +StrikeDatabaseIntegratorTestStrikeDatabase:: + ~StrikeDatabaseIntegratorTestStrikeDatabase() {} + +std::string StrikeDatabaseIntegratorTestStrikeDatabase::GetProjectPrefix() { + return kProjectPrefix; +} + +int StrikeDatabaseIntegratorTestStrikeDatabase::GetMaxStrikesLimit() { + return kMaxStrikesLimit; +} + +long long StrikeDatabaseIntegratorTestStrikeDatabase::GetExpiryTimeMicros() { + return kExpiryTimeMicros; +} + +bool StrikeDatabaseIntegratorTestStrikeDatabase::UniqueIdsRequired() { + return unique_ids_required_; +} + +void StrikeDatabaseIntegratorTestStrikeDatabase::SetUniqueIdsRequired( + bool unique_ids_required) { + unique_ids_required_ = unique_ids_required; +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/strike_database_integrator_test_strike_database.h b/components/autofill/core/browser/strike_database_integrator_test_strike_database.h new file mode 100644 index 0000000..3a50f6e --- /dev/null +++ b/components/autofill/core/browser/strike_database_integrator_test_strike_database.h
@@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_ + +#include <string> + +#include "components/autofill/core/browser/strike_database.h" +#include "components/autofill/core/browser/strike_database_integrator_base.h" + +namespace autofill { + +// Mock per-project implementation of StrikeDatabase to test the functions in +// StrikeDatabaseIntegrator. +class StrikeDatabaseIntegratorTestStrikeDatabase + : public StrikeDatabaseIntegratorBase { + public: + StrikeDatabaseIntegratorTestStrikeDatabase(StrikeDatabase* strike_database); + ~StrikeDatabaseIntegratorTestStrikeDatabase() override; + + std::string GetProjectPrefix() override; + int GetMaxStrikesLimit() override; + long long GetExpiryTimeMicros() override; + bool UniqueIdsRequired() override; + + void SetUniqueIdsRequired(bool unique_ids_required); + + private: + bool unique_ids_required_ = false; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_
diff --git a/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc b/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc new file mode 100644 index 0000000..d183b93b --- /dev/null +++ b/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc
@@ -0,0 +1,229 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h" + +#include <utility> +#include <vector> + +#include "base/files/scoped_temp_dir.h" +#include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/autofill/core/browser/proto/strike_data.pb.h" +#include "components/autofill/core/browser/test_autofill_clock.h" +#include "components/autofill/core/common/autofill_clock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill { + +class StrikeDatabaseIntegratorTestStrikeDatabaseTest : public ::testing::Test { + public: + StrikeDatabaseIntegratorTestStrikeDatabaseTest() + : strike_database_(new StrikeDatabase(InitFilePath())) {} + + protected: + base::HistogramTester* GetHistogramTester() { return &histogram_tester_; } + base::test::ScopedTaskEnvironment scoped_task_environment_; + StrikeDatabaseIntegratorTestStrikeDatabase strike_database_; + + private: + static const base::FilePath InitFilePath() { + base::ScopedTempDir temp_dir_; + EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); + const base::FilePath file_path = + temp_dir_.GetPath().AppendASCII("StrikeDatabaseTest"); + return file_path; + } + + base::HistogramTester histogram_tester_; +}; + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + MaxStrikesLimitReachedTest) { + EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached()); + // 3 strikes added. + strike_database_.AddStrikes(3); + EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached()); + // 4 strike added, total strike count is 7. + strike_database_.AddStrikes(4); + EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + StrikeDatabaseIntegratorTestNthStrikeAddedHistogram) { + // 2 strikes logged. + strike_database_.AddStrikes(2); + strike_database_.RemoveStrikes(2); + // 1 strike logged. + strike_database_.AddStrike(); + // 2 strikes logged. + strike_database_.AddStrike(); + std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( + "Autofill.StrikeDatabase.NthStrikeAdded.StrikeDatabaseIntegratorTest"); + // There should be two buckets, for strike counts of 1 and 2. + ASSERT_EQ(2U, buckets.size()); + // Bucket for 1 strike should have count of 1. + EXPECT_EQ(1, buckets[0].count); + // Bucket for 2 strikes should have count of 2. + EXPECT_EQ(2, buckets[1].count); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + AddStrikeForZeroAndNonZeroStrikesTest) { + EXPECT_EQ(0, strike_database_.GetStrikes()); + strike_database_.AddStrike(); + EXPECT_EQ(1, strike_database_.GetStrikes()); + strike_database_.AddStrikes(2); + EXPECT_EQ(3, strike_database_.GetStrikes()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + ClearStrikesForNonZeroStrikesTest) { + strike_database_.AddStrikes(3); + EXPECT_EQ(3, strike_database_.GetStrikes()); + strike_database_.ClearStrikes(); + EXPECT_EQ(0, strike_database_.GetStrikes()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + ClearStrikesForZeroStrikesTest) { + strike_database_.ClearStrikes(); + EXPECT_EQ(0, strike_database_.GetStrikes()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + RemoveExpiredStrikesTest) { + autofill::TestAutofillClock test_clock; + test_clock.SetNow(AutofillClock::Now()); + strike_database_.AddStrikes(2); + EXPECT_EQ(2, strike_database_.GetStrikes()); + + // Advance clock to past expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + // One strike should be removed. + strike_database_.RemoveExpiredStrikes(); + EXPECT_EQ(1, strike_database_.GetStrikes()); + + // Strike count is past the max limit. + strike_database_.AddStrikes(10); + EXPECT_EQ(11, strike_database_.GetStrikes()); + + // Advance clock to past expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + // Strike count should be one less than the max limit. + strike_database_.RemoveExpiredStrikes(); + EXPECT_EQ(5, strike_database_.GetStrikes()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + GetKeyForStrikeDatabaseIntegratorUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + EXPECT_EQ("StrikeDatabaseIntegratorTest__1234", + strike_database_.GetKey(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + MaxStrikesLimitReachedUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(unique_id)); + // 1 strike added for |unique_id|. + strike_database_.AddStrike(unique_id); + EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(unique_id)); + // 6 strikes added for |unique_id|. + strike_database_.AddStrikes(6, unique_id); + EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + StrikeDatabaseIntegratorUniqueIdTestNthStrikeAddedHistogram) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id_1 = "1234"; + const std::string unique_id_2 = "9876"; + // 1st strike added for |unique_id_1|. + strike_database_.AddStrike(unique_id_1); + // 2nd strike added for |unique_id_1|. + strike_database_.AddStrike(unique_id_1); + // 1st strike added for |unique_id_2|. + strike_database_.AddStrike(unique_id_2); + std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( + "Autofill.StrikeDatabase.NthStrikeAdded." + "StrikeDatabaseIntegratorTest"); + // There should be two buckets, one for 1st strike, one for 2nd strike count. + ASSERT_EQ(2U, buckets.size()); + // Both |unique_id_1| and |unique_id_2| have 1st strikes recorded. + EXPECT_EQ(2, buckets[0].count); + // Only |unique_id_1| has 2nd strike recorded. + EXPECT_EQ(1, buckets[1].count); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + AddStrikeForZeroAndNonZeroStrikesUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id)); + strike_database_.AddStrike(unique_id); + EXPECT_EQ(1, strike_database_.GetStrikes(unique_id)); + strike_database_.AddStrike(unique_id); + EXPECT_EQ(2, strike_database_.GetStrikes(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + ClearStrikesForNonZeroStrikesUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + strike_database_.AddStrike(unique_id); + EXPECT_EQ(1, strike_database_.GetStrikes(unique_id)); + strike_database_.ClearStrikes(unique_id); + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + ClearStrikesForZeroStrikesUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + strike_database_.ClearStrikes(unique_id); + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + RemoveExpiredStrikesUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + autofill::TestAutofillClock test_clock; + test_clock.SetNow(AutofillClock::Now()); + const std::string unique_id_1 = "1234"; + const std::string unique_id_2 = "9876"; + strike_database_.AddStrike(unique_id_1); + + // Advance clock to past the entry for |unique_id_1|'s expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + strike_database_.AddStrike(unique_id_2); + strike_database_.RemoveExpiredStrikes(); + + // |unique_id_1|'s entry should have its most recent strike expire, but + // |unique_id_2|'s should not. + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id_1)); + EXPECT_EQ(1, strike_database_.GetStrikes(unique_id_2)); + + // Advance clock to past |unique_id_2|'s expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + strike_database_.RemoveExpiredStrikes(); + + // |unique_id_1| and |unique_id_2| should have no more unexpired strikes. + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id_1)); + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id_2)); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/test_local_card_migration_strike_database.cc b/components/autofill/core/browser/test_local_card_migration_strike_database.cc deleted file mode 100644 index cc212712..0000000 --- a/components/autofill/core/browser/test_local_card_migration_strike_database.cc +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/autofill/core/browser/test_local_card_migration_strike_database.h" - -namespace autofill { - -TestLocalCardMigrationStrikeDatabase::TestLocalCardMigrationStrikeDatabase( - StrikeDatabase* strike_database) - : LocalCardMigrationStrikeDatabase(strike_database) {} - -} // namespace autofill
diff --git a/components/autofill/core/browser/test_local_card_migration_strike_database.h b/components/autofill/core/browser/test_local_card_migration_strike_database.h deleted file mode 100644 index c1cac18..0000000 --- a/components/autofill/core/browser/test_local_card_migration_strike_database.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_ - -#include "components/autofill/core/browser/local_card_migration_strike_database.h" - -namespace autofill { - -class TestLocalCardMigrationStrikeDatabase - : public LocalCardMigrationStrikeDatabase { - public: - TestLocalCardMigrationStrikeDatabase(StrikeDatabase* strike_database); -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc index 912fdeba2..03d0c89f 100644 --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -440,6 +440,16 @@ ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE, ContentSettingsInfo::PERSISTENT, ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); + + Register(CONTENT_SETTINGS_TYPE_SERIAL_GUARD, "serial-guard", + CONTENT_SETTING_ASK, WebsiteSettingsInfo::UNSYNCABLE, + WhitelistedSchemes(), + ValidSettings(CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK), + WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE, + WebsiteSettingsRegistry::DESKTOP, + ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE, + ContentSettingsInfo::PERSISTENT, + ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); } void ContentSettingsRegistry::Register(
diff --git a/components/content_settings/core/browser/website_settings_registry.cc b/components/content_settings/core/browser/website_settings_registry.cc index 052b8db..085efe9 100644 --- a/components/content_settings/core/browser/website_settings_registry.cc +++ b/components/content_settings/core/browser/website_settings_registry.cc
@@ -194,6 +194,11 @@ WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY, WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE, DESKTOP, WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO); + Register(CONTENT_SETTINGS_TYPE_SERIAL_CHOOSER_DATA, "serial-chooser-data", + nullptr, WebsiteSettingsInfo::UNSYNCABLE, + WebsiteSettingsInfo::NOT_LOSSY, + WebsiteSettingsInfo::REQUESTING_ORIGIN_AND_TOP_LEVEL_ORIGIN_SCOPE, + DESKTOP, WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO); } } // namespace content_settings
diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc index 28e51c0..cac5b0c 100644 --- a/components/content_settings/core/common/content_settings.cc +++ b/components/content_settings/core/common/content_settings.cc
@@ -29,7 +29,7 @@ // content settings type name instead. // // The array size must be explicit for the static_asserts below. -constexpr size_t kNumHistogramValues = 41; +constexpr size_t kNumHistogramValues = 43; constexpr HistogramValue kHistogramValue[kNumHistogramValues] = { {CONTENT_SETTINGS_TYPE_COOKIES, 0}, {CONTENT_SETTINGS_TYPE_IMAGES, 1}, @@ -72,6 +72,8 @@ {CONTENT_SETTINGS_TYPE_BACKGROUND_FETCH, 45}, {CONTENT_SETTINGS_TYPE_INTENT_PICKER_DISPLAY, 46}, {CONTENT_SETTINGS_TYPE_IDLE_DETECTION, 47}, + {CONTENT_SETTINGS_TYPE_SERIAL_GUARD, 48}, + {CONTENT_SETTINGS_TYPE_SERIAL_CHOOSER_DATA, 49}, }; } // namespace
diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h index 17b6ab6..338fdd7e 100644 --- a/components/content_settings/core/common/content_settings_types.h +++ b/components/content_settings/core/common/content_settings_types.h
@@ -129,6 +129,13 @@ // Used to store whether to allow a website to detect user active/idle state. CONTENT_SETTINGS_TYPE_IDLE_DETECTION, + // Content settings for access to serial ports. The "guard" content setting + // stores whether to allow sites to ask for permission to access a port. The + // permissions granted to access particular ports are stored in the "chooser + // data" website setting. + CONTENT_SETTINGS_TYPE_SERIAL_GUARD, + CONTENT_SETTINGS_TYPE_SERIAL_CHOOSER_DATA, + CONTENT_SETTINGS_NUM_TYPES, };
diff --git a/components/cronet/BUILD.gn b/components/cronet/BUILD.gn index 794bad1..df22474f 100644 --- a/components/cronet/BUILD.gn +++ b/components/cronet/BUILD.gn
@@ -217,7 +217,7 @@ # Copy boiler-plate files into the package. copy("cronet_package_copy") { sources = [ - "$root_out_dir/$_cronet_shared_lib_file_name", + "${root_out_dir}${shlib_subdir}/${_cronet_shared_lib_file_name}", "//AUTHORS", "//chrome/VERSION", ]
diff --git a/components/download/internal/common/download_stats.cc b/components/download/internal/common/download_stats.cc index 11ac2934..3046017 100644 --- a/components/download/internal/common/download_stats.cc +++ b/components/download/internal/common/download_stats.cc
@@ -404,6 +404,26 @@ FILE_PATH_LITERAL(".pyo"), // 319 FILE_PATH_LITERAL(".desktop"), // 320 FILE_PATH_LITERAL(".cpi"), // 321 + FILE_PATH_LITERAL(".jpg"), // 322 + FILE_PATH_LITERAL(".jpeg"), // 323 + FILE_PATH_LITERAL(".mp3"), // 324 + FILE_PATH_LITERAL(".mp4"), // 325 + FILE_PATH_LITERAL(".png"), // 326 + FILE_PATH_LITERAL(".xls"), // 327 + FILE_PATH_LITERAL(".doc"), // 328 + FILE_PATH_LITERAL(".pptx"), // 329 + FILE_PATH_LITERAL(".csv"), // 330 + FILE_PATH_LITERAL(".ica"), // 331 + FILE_PATH_LITERAL(".ppt"), // 332 + FILE_PATH_LITERAL(".gif"), // 333 + FILE_PATH_LITERAL(".txt"), // 334 + FILE_PATH_LITERAL(".package"), // 335 + FILE_PATH_LITERAL(".tif"), // 336 + FILE_PATH_LITERAL(".rtf"), // 337 + FILE_PATH_LITERAL(".webp"), // 338 + FILE_PATH_LITERAL(".mkv"), // 339 + FILE_PATH_LITERAL(".wav"), // 340 + FILE_PATH_LITERAL(".mov"), // 341 // NOTE! When you add a type here, please add the UMA value as a comment. // These must all match DownloadItem.DangerousFileType in // enums.xml. From 263 onward, they should also match
diff --git a/components/flags_ui/resources/flags.js b/components/flags_ui/resources/flags.js index ba4750f..dea68e8 100644 --- a/components/flags_ui/resources/flags.js +++ b/components/flags_ui/resources/flags.js
@@ -44,9 +44,10 @@ }; } - elements = document.getElementsByClassName('experiment-restart-button'); - for (var i = 0; i < elements.length; ++i) { - elements[i].onclick = restartBrowser; + var element = $('experiment-restart-button'); + assert(element || cr.isIOS); + if (element) { + element.onclick = restartBrowser; } // Tab panel selection.
diff --git a/components/omnibox/browser/document_provider.cc b/components/omnibox/browser/document_provider.cc index e33a769..d5424709 100644 --- a/components/omnibox/browser/document_provider.cc +++ b/components/omnibox/browser/document_provider.cc
@@ -14,6 +14,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/feature_list.h" +#include "base/i18n/case_conversion.h" #include "base/i18n/time_formatting.h" #include "base/json/json_reader.h" #include "base/metrics/field_trial_params.h" @@ -24,14 +25,18 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "components/bookmarks/browser/bookmark_utils.h" #include "components/data_use_measurement/core/data_use_user_data.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/omnibox/browser/document_suggestions_service.h" +#include "components/omnibox/browser/history_provider.h" +#include "components/omnibox/browser/in_memory_url_index_types.h" #include "components/omnibox/browser/omnibox_field_trial.h" #include "components/omnibox/browser/omnibox_pref_names.h" +#include "components/omnibox/browser/scored_history_match.h" #include "components/omnibox/browser/search_provider.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" @@ -208,6 +213,8 @@ Stop(true, false); + input_ = input; + // Create a request for suggestions, routing completion to base::BindOnce(&DocumentProvider::OnDocumentSuggestionsLoaderAvailable, weak_ptr_factory_.GetWeakPtr()), @@ -458,8 +465,7 @@ match.stripped_destination_url = GURL(original_url); } match.contents = AutocompleteMatch::SanitizeString(title); - AutocompleteMatch::AddLastClassificationIfNecessary( - &match.contents_class, 0, ACMatchClassification::NONE); + match.contents_class = Classify(match.contents, input_.text()); const base::DictionaryValue* metadata = nullptr; if (result->GetDictionary("metadata", &metadata)) { if (metadata->GetString("mimeType", &mimetype)) { @@ -497,3 +503,32 @@ } return true; } + +// static +ACMatchClassifications DocumentProvider::Classify( + const base::string16& text, + const base::string16& input_text) { + base::string16 clean_text = bookmarks::CleanUpTitleForMatching(text); + base::string16 lower_input_text(base::i18n::ToLower(input_text)); + String16Vector input_terms = + base::SplitString(lower_input_text, base::kWhitespaceUTF16, + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + + TermMatches matches; + for (size_t i = 0; i < input_terms.size(); ++i) { + TermMatches term_matches = MatchTermInString(input_terms[i], clean_text, i); + matches.insert(matches.end(), term_matches.begin(), term_matches.end()); + } + matches = SortMatches(matches); + matches = DeoverlapMatches(matches); + + WordStarts word_starts; + String16VectorFromString16(clean_text, false, &word_starts); + + WordStarts terms_to_word_starts_offsets(input_terms.size(), 0); + matches = ScoredHistoryMatch::FilterTermMatchesByWordStarts( + matches, terms_to_word_starts_offsets, word_starts, 0, std::string::npos); + + return HistoryProvider::SpansFromTermMatch(matches, clean_text.length(), + false); +}
diff --git a/components/omnibox/browser/document_provider.h b/components/omnibox/browser/document_provider.h index 2e8fbe1..711a5e1f 100644 --- a/components/omnibox/browser/document_provider.h +++ b/components/omnibox/browser/document_provider.h
@@ -119,6 +119,18 @@ const std::string& modified_timestamp_string, base::Time now); + // Returns a set of classifications that highlight all the occurrences of + // |input_text| at word breaks in |text|. E.g., given |input_text| + // "rain if you dare" and |text| "how to tell if your kitten is a rainbow", + // will return the classifications: + // __ ___ ____ + // how to tell if your kitten is a rainbow + // ^ ^ ^^ ^ ^ ^ + // NONE M |M | | NONE + // NONE NONE MATCH + static ACMatchClassifications Classify(const base::string16& input_text, + const base::string16& text); + // Whether a field trial has triggered for this query and this session, // respectively. Works similarly to BaseSearchProvider, though this class does // not inherit from it. @@ -135,6 +147,10 @@ // Listener to notify when results are available. AutocompleteProviderListener* listener_; + // Saved when starting a new autocomplete request so that it can be retrieved + // when responses return asynchronously. + AutocompleteInput input_; + // Loader used to retrieve results. std::unique_ptr<network::SimpleURLLoader> loader_;
diff --git a/components/omnibox/browser/history_provider.cc b/components/omnibox/browser/history_provider.cc index d4b3528..12524533 100644 --- a/components/omnibox/browser/history_provider.cc +++ b/components/omnibox/browser/history_provider.cc
@@ -39,10 +39,41 @@ (!input.text().empty() && base::IsUnicodeWhitespace(input.text().back())); } +// static +ACMatchClassifications HistoryProvider::SpansFromTermMatch( + const TermMatches& matches, + size_t text_length, + bool is_url) { + ACMatchClassification::Style url_style = + is_url ? ACMatchClassification::URL : ACMatchClassification::NONE; + ACMatchClassifications spans; + if (matches.empty()) { + if (text_length) + spans.push_back(ACMatchClassification(0, url_style)); + return spans; + } + if (matches[0].offset) + spans.push_back(ACMatchClassification(0, url_style)); + size_t match_count = matches.size(); + for (size_t i = 0; i < match_count;) { + size_t offset = matches[i].offset; + spans.push_back(ACMatchClassification( + offset, ACMatchClassification::MATCH | url_style)); + // Skip all adjacent matches. + do { + offset += matches[i].length; + ++i; + } while ((i < match_count) && (offset == matches[i].offset)); + if (offset < text_length) + spans.push_back(ACMatchClassification(offset, url_style)); + } + + return spans; +} + HistoryProvider::HistoryProvider(AutocompleteProvider::Type type, AutocompleteProviderClient* client) - : AutocompleteProvider(type), client_(client) { -} + : AutocompleteProvider(type), client_(client) {} HistoryProvider::~HistoryProvider() {} @@ -68,35 +99,3 @@ } DCHECK(found) << "Asked to delete a URL that isn't in our set of matches"; } - -// static -ACMatchClassifications HistoryProvider::SpansFromTermMatch( - const TermMatches& matches, - size_t text_length, - bool is_url) { - ACMatchClassification::Style url_style = - is_url ? ACMatchClassification::URL : ACMatchClassification::NONE; - ACMatchClassifications spans; - if (matches.empty()) { - if (text_length) - spans.push_back(ACMatchClassification(0, url_style)); - return spans; - } - if (matches[0].offset) - spans.push_back(ACMatchClassification(0, url_style)); - size_t match_count = matches.size(); - for (size_t i = 0; i < match_count;) { - size_t offset = matches[i].offset; - spans.push_back(ACMatchClassification(offset, - ACMatchClassification::MATCH | url_style)); - // Skip all adjacent matches. - do { - offset += matches[i].length; - ++i; - } while ((i < match_count) && (offset == matches[i].offset)); - if (offset < text_length) - spans.push_back(ACMatchClassification(offset, url_style)); - } - - return spans; -}
diff --git a/components/omnibox/browser/history_provider.h b/components/omnibox/browser/history_provider.h index 9cf3414..e93b952 100644 --- a/components/omnibox/browser/history_provider.h +++ b/components/omnibox/browser/history_provider.h
@@ -27,6 +27,12 @@ // is true or the input text contains trailing whitespace. static bool PreventInlineAutocomplete(const AutocompleteInput& input); + // Fill and return an ACMatchClassifications structure given the |matches| + // to highlight. + static ACMatchClassifications SpansFromTermMatch(const TermMatches& matches, + size_t text_length, + bool is_url); + protected: HistoryProvider(AutocompleteProvider::Type type, AutocompleteProviderClient* client); @@ -37,12 +43,6 @@ // backing data. void DeleteMatchFromMatches(const AutocompleteMatch& match); - // Fill and return an ACMatchClassifications structure given the |matches| - // to highlight. - static ACMatchClassifications SpansFromTermMatch(const TermMatches& matches, - size_t text_length, - bool is_url); - AutocompleteProviderClient* client() { return client_; } private:
diff --git a/components/omnibox/browser/vector_icons/drive_forms.icon b/components/omnibox/browser/vector_icons/drive_forms.icon index f174d9a..33b0f0d 100644 --- a/components/omnibox/browser/vector_icons/drive_forms.icon +++ b/components/omnibox/browser/vector_icons/drive_forms.icon
@@ -1,46 +1,46 @@ -// 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. - -CANVAS_DIMENSIONS, 18, -PATH_COLOR_ARGB, 0xFF, 0x67, 0x3A, 0xB7, -MOVE_TO, 16, 0, -H_LINE_TO, 2, -CUBIC_TO, 0.9f, 0, 0, 0.9f, 0, 2, -R_V_LINE_TO, 14, -R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2, -R_H_LINE_TO, 14, -R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2, -V_LINE_TO, 2, -R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2, -CLOSE, -MOVE_TO, 6, 14, -H_LINE_TO, 4, -R_V_LINE_TO, -2, -R_H_LINE_TO, 2, -CLOSE, -R_MOVE_TO, 0, -4, -H_LINE_TO, 4, -V_LINE_TO, 8, -R_H_LINE_TO, 2, -CLOSE, -R_MOVE_TO, 0, -4, -H_LINE_TO, 4, -V_LINE_TO, 4, -R_H_LINE_TO, 2, -CLOSE, -R_MOVE_TO, 8, 8, -H_LINE_TO, 7, -R_V_LINE_TO, -2, -R_H_LINE_TO, 7, -CLOSE, -R_MOVE_TO, 0, -4, -H_LINE_TO, 7, -V_LINE_TO, 8, -R_H_LINE_TO, 7, -CLOSE, -R_MOVE_TO, 0, -4, -H_LINE_TO, 7, -V_LINE_TO, 4, -R_H_LINE_TO, 7, +// 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. + +CANVAS_DIMENSIONS, 18, +PATH_COLOR_ARGB, 0xFF, 0x67, 0x3A, 0xB7, +MOVE_TO, 16, 0, +H_LINE_TO, 2, +CUBIC_TO, 0.9f, 0, 0, 0.9f, 0, 2, +R_V_LINE_TO, 14, +R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2, +R_H_LINE_TO, 14, +R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2, +V_LINE_TO, 2, +R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2, +CLOSE, +MOVE_TO, 6, 14, +H_LINE_TO, 4, +R_V_LINE_TO, -2, +R_H_LINE_TO, 2, +CLOSE, +R_MOVE_TO, 0, -4, +H_LINE_TO, 4, +V_LINE_TO, 8, +R_H_LINE_TO, 2, +CLOSE, +R_MOVE_TO, 0, -4, +H_LINE_TO, 4, +V_LINE_TO, 4, +R_H_LINE_TO, 2, +CLOSE, +R_MOVE_TO, 8, 8, +H_LINE_TO, 7, +R_V_LINE_TO, -2, +R_H_LINE_TO, 7, +CLOSE, +R_MOVE_TO, 0, -4, +H_LINE_TO, 7, +V_LINE_TO, 8, +R_H_LINE_TO, 7, +CLOSE, +R_MOVE_TO, 0, -4, +H_LINE_TO, 7, +V_LINE_TO, 4, +R_H_LINE_TO, 7, CLOSE \ No newline at end of file
diff --git a/components/omnibox/browser/vector_icons/pedal.icon b/components/omnibox/browser/vector_icons/pedal.icon index e6bb15f..8a33051 100644 --- a/components/omnibox/browser/vector_icons/pedal.icon +++ b/components/omnibox/browser/vector_icons/pedal.icon
@@ -4,78 +4,78 @@ // Source: bicycle-pedal.svg -> SVGOMG -> Skiafy -CANVAS_DIMENSIONS, 100, -MOVE_TO, 97.5f, 49.85f, -R_ARC_TO, 2.23f, 2.23f, 0, 0, 0, -0.28f, -0.95f, -LINE_TO, 78.76f, 16.92f, -R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, -1.94f, -1.12f, -R_H_LINE_TO, -36.91f, -R_CUBIC_TO, -0.77f, 0, -1.53f, 0.44f, -1.92f, 1.12f, -LINE_TO, 19.53f, 48.9f, -R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, 0, 2.22f, -R_LINE_TO, 18.46f, 31.98f, -R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, 1.92f, 1.1f, -R_H_LINE_TO, 36.91f, -R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, 1.94f, -1.1f, -LINE_TO, 97.22f, 51.11f, -R_CUBIC_TO, 0.18f, -0.32f, 0.27f, -0.69f, 0.28f, -1.06f, -R_ARC_TO, 2.25f, 2.25f, 0, 0, 0, 0, -0.21f, -CLOSE, -R_MOVE_TO, -9.17f, -0.18f, -R_CUBIC_TO, 0.01f, 0.35f, -0.07f, 0.7f, -0.23f, 1.01f, -R_LINE_TO, -14.14f, 24.66f, -H_LINE_TO, 42.78f, -LINE_TO, 28.73f, 51.4f, -R_ARC_TO, 2.25f, 2.25f, 0, 0, 1, -0.11f, -1.99f, -R_LINE_TO, 14.15f, -24.74f, -R_H_LINE_TO, 31.18f, -LINE_TO, 88.03f, 48.61f, -R_CUBIC_TO, 0.19f, 0.32f, 0.29f, 0.69f, 0.3f, 1.06f, -CLOSE, -R_MOVE_TO, -1.82f, 0.09f, -R_ARC_TO, 2.23f, 2.23f, 0, 0, 0, -0.3f, -1.16f, -R_LINE_TO, -3.9f, -6.76f, -H_LINE_TO, 34.79f, -R_LINE_TO, -4.24f, 7.33f, -R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, 0, 2.22f, -R_LINE_TO, 3.91f, 6.77f, -H_LINE_TO, 81.97f, -R_LINE_TO, 4.24f, -7.34f, -R_CUBIC_TO, 0.19f, -0.32f, 0.29f, -0.69f, 0.3f, -1.06f, -CLOSE, -MOVE_TO, 73.96f, 20.24f, -R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, -R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, -CLOSE, -R_MOVE_TO, 0, 59.53f, -R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, -R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, -CLOSE, -MOVE_TO, 59.95f, 20.24f, -R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, -R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, -CLOSE, -R_MOVE_TO, 0, 59.53f, -R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, -R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, -CLOSE, -MOVE_TO, 45.94f, 20.24f, -R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, -R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, -CLOSE, -R_MOVE_TO, 0, 59.53f, -R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, -R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, -CLOSE, -MOVE_TO, 22, 41.46f, -H_LINE_TO, 13.91f, -R_V_LINE_TO, 2.22f, -H_LINE_TO, 2.5f, -R_V_LINE_TO, 12.67f, -R_H_LINE_TO, 11.41f, -R_V_LINE_TO, 2.21f, -R_H_LINE_TO, 8.09f, -R_LINE_TO, -4.29f, -7.43f, -R_ARC_TO, 2.22f, 2.22f, 0, 0, 1, 0, -2.22f, -R_LINE_TO, 4.29f, -7.44f, -CLOSE +CANVAS_DIMENSIONS, 100, +MOVE_TO, 97.5f, 49.85f, +R_ARC_TO, 2.23f, 2.23f, 0, 0, 0, -0.28f, -0.95f, +LINE_TO, 78.76f, 16.92f, +R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, -1.94f, -1.12f, +R_H_LINE_TO, -36.91f, +R_CUBIC_TO, -0.77f, 0, -1.53f, 0.44f, -1.92f, 1.12f, +LINE_TO, 19.53f, 48.9f, +R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, 0, 2.22f, +R_LINE_TO, 18.46f, 31.98f, +R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, 1.92f, 1.1f, +R_H_LINE_TO, 36.91f, +R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, 1.94f, -1.1f, +LINE_TO, 97.22f, 51.11f, +R_CUBIC_TO, 0.18f, -0.32f, 0.27f, -0.69f, 0.28f, -1.06f, +R_ARC_TO, 2.25f, 2.25f, 0, 0, 0, 0, -0.21f, +CLOSE, +R_MOVE_TO, -9.17f, -0.18f, +R_CUBIC_TO, 0.01f, 0.35f, -0.07f, 0.7f, -0.23f, 1.01f, +R_LINE_TO, -14.14f, 24.66f, +H_LINE_TO, 42.78f, +LINE_TO, 28.73f, 51.4f, +R_ARC_TO, 2.25f, 2.25f, 0, 0, 1, -0.11f, -1.99f, +R_LINE_TO, 14.15f, -24.74f, +R_H_LINE_TO, 31.18f, +LINE_TO, 88.03f, 48.61f, +R_CUBIC_TO, 0.19f, 0.32f, 0.29f, 0.69f, 0.3f, 1.06f, +CLOSE, +R_MOVE_TO, -1.82f, 0.09f, +R_ARC_TO, 2.23f, 2.23f, 0, 0, 0, -0.3f, -1.16f, +R_LINE_TO, -3.9f, -6.76f, +H_LINE_TO, 34.79f, +R_LINE_TO, -4.24f, 7.33f, +R_ARC_TO, 2.26f, 2.26f, 0, 0, 0, 0, 2.22f, +R_LINE_TO, 3.91f, 6.77f, +H_LINE_TO, 81.97f, +R_LINE_TO, 4.24f, -7.34f, +R_CUBIC_TO, 0.19f, -0.32f, 0.29f, -0.69f, 0.3f, -1.06f, +CLOSE, +MOVE_TO, 73.96f, 20.24f, +R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, +R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, +CLOSE, +R_MOVE_TO, 0, 59.53f, +R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, +R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, +CLOSE, +MOVE_TO, 59.95f, 20.24f, +R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, +R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, +CLOSE, +R_MOVE_TO, 0, 59.53f, +R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, +R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, +CLOSE, +MOVE_TO, 45.94f, 20.24f, +R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, +R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, +CLOSE, +R_MOVE_TO, 0, 59.53f, +R_ARC_TO, 1.58f, 1.58f, 0, 1, 1, -3.17f, 0, +R_ARC_TO, 1.58f, 1.58f, 0, 0, 1, 3.17f, 0, +CLOSE, +MOVE_TO, 22, 41.46f, +H_LINE_TO, 13.91f, +R_V_LINE_TO, 2.22f, +H_LINE_TO, 2.5f, +R_V_LINE_TO, 12.67f, +R_H_LINE_TO, 11.41f, +R_V_LINE_TO, 2.21f, +R_H_LINE_TO, 8.09f, +R_LINE_TO, -4.29f, -7.43f, +R_ARC_TO, 2.22f, 2.22f, 0, 0, 1, 0, -2.22f, +R_LINE_TO, 4.29f, -7.44f, +CLOSE
diff --git a/components/services/filesystem/BUILD.gn b/components/services/filesystem/BUILD.gn index 21d8a9f5..b251f7e9 100644 --- a/components/services/filesystem/BUILD.gn +++ b/components/services/filesystem/BUILD.gn
@@ -2,9 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//services/catalog/public/tools/catalog.gni") import("//services/service_manager/public/cpp/service_executable.gni") -import("//services/service_manager/public/service_manifest.gni") import("//testing/test.gni") static_library("lib") { @@ -52,11 +50,6 @@ ] } - service_manifest("manifest") { - name = "filesystem" - source = "manifest.json" - } - test("filesystem_service_unittests") { sources = [ "directory_impl_unittest.cc", @@ -66,9 +59,9 @@ ] deps = [ - ":filesystem_service_unittests_catalog_source", "//base", "//base/test:test_support", + "//components/services/filesystem/public/cpp:manifest", "//components/services/filesystem/public/interfaces", "//mojo/core/test:run_all_unittests", "//mojo/public/cpp/bindings", @@ -82,20 +75,4 @@ ":filesystem", ] } - - service_manifest("test_manifest") { - name = "filesystem_service_unittests" - source = "test_manifest.json" - } - - catalog("filesystem_service_unittests_catalog") { - embedded_services = [ ":test_manifest" ] - standalone_services = [ ":manifest" ] - } - - catalog_cpp_source("filesystem_service_unittests_catalog_source") { - testonly = true - catalog = ":filesystem_service_unittests_catalog" - generated_function_name = "filesystem::test::CreateTestCatalog" - } }
diff --git a/components/services/filesystem/OWNERS b/components/services/filesystem/OWNERS deleted file mode 100644 index 21beb1aa..0000000 --- a/components/services/filesystem/OWNERS +++ /dev/null
@@ -1,5 +0,0 @@ -per-file manifest.json=set noparent -per-file manifest.json=file://ipc/SECURITY_OWNERS - -per-file test_manifest.json=set noparent -per-file test_manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/components/services/filesystem/files_test_base.cc b/components/services/filesystem/files_test_base.cc index 1429cfd5..349bedf 100644 --- a/components/services/filesystem/files_test_base.cc +++ b/components/services/filesystem/files_test_base.cc
@@ -6,17 +6,25 @@ #include <utility> -#include "components/services/filesystem/filesystem_service_unittests_catalog_source.h" +#include "components/services/filesystem/public/cpp/manifest.h" #include "components/services/filesystem/public/interfaces/directory.mojom.h" #include "components/services/filesystem/public/interfaces/types.mojom.h" #include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/manifest_builder.h" namespace filesystem { +const char kTestServiceName[] = "filesystem_service_unittests"; + FilesTestBase::FilesTestBase() - : test_service_manager_(test::CreateTestCatalog()), - test_service_(test_service_manager_.RegisterTestInstance( - "filesystem_service_unittests")) {} + : test_service_manager_( + {GetManifest(), + service_manager::ManifestBuilder() + .WithServiceName(kTestServiceName) + .RequireCapability("filesystem", "filesystem:filesystem") + .Build()}), + test_service_( + test_service_manager_.RegisterTestInstance(kTestServiceName)) {} FilesTestBase::~FilesTestBase() {}
diff --git a/components/services/filesystem/manifest.json b/components/services/filesystem/manifest.json deleted file mode 100644 index 5e2e1647..0000000 --- a/components/services/filesystem/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "filesystem", - "display_name": "File System Service", - "sandbox_type": "none", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "filesystem:filesystem": [ "filesystem.mojom.FileSystem" ] - }, - "requires": { - "*": [ "app" ] - } - } - } -}
diff --git a/components/services/filesystem/public/cpp/BUILD.gn b/components/services/filesystem/public/cpp/BUILD.gn new file mode 100644 index 0000000..e72b732 --- /dev/null +++ b/components/services/filesystem/public/cpp/BUILD.gn
@@ -0,0 +1,16 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("manifest") { + sources = [ + "manifest.cc", + "manifest.h", + ] + + deps = [ + "//base", + "//components/services/filesystem/public/interfaces", + "//services/service_manager/public/cpp", + ] +}
diff --git a/components/services/filesystem/public/cpp/OWNERS b/components/services/filesystem/public/cpp/OWNERS new file mode 100644 index 0000000..6faeaa47 --- /dev/null +++ b/components/services/filesystem/public/cpp/OWNERS
@@ -0,0 +1,4 @@ +per-file manifest.cc=set noparent +per-file manifest.cc=file://ipc/SECURITY_OWNERS +per-file manifest.h=set noparent +per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/components/services/filesystem/public/cpp/manifest.cc b/components/services/filesystem/public/cpp/manifest.cc new file mode 100644 index 0000000..b27bfe37 --- /dev/null +++ b/components/services/filesystem/public/cpp/manifest.cc
@@ -0,0 +1,27 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/services/filesystem/public/cpp/manifest.h" + +#include "base/no_destructor.h" +#include "components/services/filesystem/public/interfaces/file_system.mojom.h" +#include "services/service_manager/public/cpp/manifest_builder.h" + +namespace filesystem { + +const service_manager::Manifest& GetManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .WithServiceName("filesystem") + .WithOptions(service_manager::ManifestOptionsBuilder() + .WithSandboxType("none") + .Build()) + .ExposeCapability( + "filesystem:filesystem", + service_manager::Manifest::InterfaceList<mojom::FileSystem>()) + .Build()}; + return *manifest; +} + +} // namespace filesystem
diff --git a/components/services/filesystem/public/cpp/manifest.h b/components/services/filesystem/public/cpp/manifest.h new file mode 100644 index 0000000..2009ebf --- /dev/null +++ b/components/services/filesystem/public/cpp/manifest.h
@@ -0,0 +1,16 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SERVICES_FILESYSTEM_PUBLIC_CPP_MANIFEST_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_PUBLIC_CPP_MANIFEST_H_ + +#include "services/service_manager/public/cpp/manifest.h" + +namespace filesystem { + +const service_manager::Manifest& GetManifest(); + +} // namespace filesystem + +#endif // COMPONENTS_SERVICES_FILESYSTEM_PUBLIC_CPP_MANIFEST_H_
diff --git a/components/services/filesystem/test_manifest.json b/components/services/filesystem/test_manifest.json deleted file mode 100644 index 219c700..0000000 --- a/components/services/filesystem/test_manifest.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "name": "filesystem_service_unittests", - "display_name": "Filesystem Service Unittests", - "interface_provider_specs": { - "service_manager:connector": { - "requires": { - "filesystem": [ "filesystem:filesystem" ] - } - } - } -}
diff --git a/components/services/leveldb/BUILD.gn b/components/services/leveldb/BUILD.gn index 29c62d4..9f2629f 100644 --- a/components/services/leveldb/BUILD.gn +++ b/components/services/leveldb/BUILD.gn
@@ -2,9 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//services/catalog/public/tools/catalog.gni") import("//services/service_manager/public/cpp/service_executable.gni") -import("//services/service_manager/public/service_manifest.gni") import("//testing/test.gni") static_library("lib") { @@ -48,11 +46,6 @@ ] } -service_manifest("manifest") { - name = "leveldb" - source = "manifest.json" -} - test("leveldb_service_unittests") { sources = [ "leveldb_mojo_unittest.cc", @@ -61,11 +54,12 @@ ] deps = [ - ":leveldb_service_unittests_catalog_source", "//base", "//base/test:test_support", + "//components/services/filesystem/public/cpp:manifest", "//components/services/filesystem/public/interfaces", "//components/services/leveldb/public/cpp", + "//components/services/leveldb/public/cpp:manifest", "//components/services/leveldb/public/interfaces", "//mojo/core/test:run_all_unittests", "//mojo/public/cpp/bindings", @@ -81,22 +75,3 @@ "//components/services/filesystem:filesystem", ] } - -service_manifest("test_manifest") { - name = "leveldb_service_unittests" - source = "test_manifest.json" -} - -catalog("leveldb_service_unittests_catalog") { - embedded_services = [ ":test_manifest" ] - standalone_services = [ - ":manifest", - "//components/services/filesystem:manifest", - ] -} - -catalog_cpp_source("leveldb_service_unittests_catalog_source") { - testonly = true - catalog = ":leveldb_service_unittests_catalog" - generated_function_name = "leveldb::test::CreateTestCatalog" -}
diff --git a/components/services/leveldb/OWNERS b/components/services/leveldb/OWNERS index be35d98..f1bfd1e 100644 --- a/components/services/leveldb/OWNERS +++ b/components/services/leveldb/OWNERS
@@ -1,13 +1,7 @@ mek@chromium.org -per-file manifest.json=set noparent -per-file manifest.json=file://ipc/SECURITY_OWNERS - per-file *_struct_traits*.*=set noparent per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS -per-file test_manifest.json=set noparent -per-file test_manifest.json=file://ipc/SECURITY_OWNERS - per-file *.typemap=set noparent per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/components/services/leveldb/leveldb_service_unittest.cc b/components/services/leveldb/leveldb_service_unittest.cc index 6fea47d1..79b57e3 100644 --- a/components/services/leveldb/leveldb_service_unittest.cc +++ b/components/services/leveldb/leveldb_service_unittest.cc
@@ -7,13 +7,15 @@ #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" +#include "components/services/filesystem/public/cpp/manifest.h" #include "components/services/filesystem/public/interfaces/directory.mojom.h" #include "components/services/filesystem/public/interfaces/file_system.mojom.h" #include "components/services/filesystem/public/interfaces/types.mojom.h" -#include "components/services/leveldb/leveldb_service_unittests_catalog_source.h" +#include "components/services/leveldb/public/cpp/manifest.h" #include "components/services/leveldb/public/cpp/util.h" #include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" +#include "services/service_manager/public/cpp/manifest_builder.h" #include "services/service_manager/public/cpp/test/test_service.h" #include "services/service_manager/public/cpp/test/test_service_manager.h" #include "testing/gtest/include/gtest/gtest.h" @@ -134,12 +136,20 @@ run_loop.Run(); } +const char kTestServiceName[] = "leveldb_service_unittests"; + class LevelDBServiceTest : public testing::Test { public: LevelDBServiceTest() - : test_service_manager_(test::CreateTestCatalog()), - test_service_(test_service_manager_.RegisterTestInstance( - "leveldb_service_unittests")) {} + : test_service_manager_( + {GetManifest(), filesystem::GetManifest(), + service_manager::ManifestBuilder() + .WithServiceName(kTestServiceName) + .RequireCapability("filesystem", "filesystem:filesystem") + .RequireCapability("leveldb", "leveldb:leveldb") + .Build()}), + test_service_( + test_service_manager_.RegisterTestInstance(kTestServiceName)) {} ~LevelDBServiceTest() override = default; protected:
diff --git a/components/services/leveldb/manifest.json b/components/services/leveldb/manifest.json deleted file mode 100644 index 41102cc4..0000000 --- a/components/services/leveldb/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "leveldb", - "display_name": "LevelDB Service", - "sandbox_type": "none", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "leveldb:leveldb": [ "leveldb.mojom.LevelDBService" ] - }, - "requires": { - "*": [ "app" ] - } - } - } -}
diff --git a/components/services/leveldb/public/cpp/BUILD.gn b/components/services/leveldb/public/cpp/BUILD.gn index aab9403..af0830e5 100644 --- a/components/services/leveldb/public/cpp/BUILD.gn +++ b/components/services/leveldb/public/cpp/BUILD.gn
@@ -17,3 +17,16 @@ "//third_party/leveldatabase", ] } + +source_set("manifest") { + sources = [ + "manifest.cc", + "manifest.h", + ] + + deps = [ + "//base", + "//components/services/leveldb/public/interfaces", + "//services/service_manager/public/cpp", + ] +}
diff --git a/components/services/leveldb/public/cpp/OWNERS b/components/services/leveldb/public/cpp/OWNERS new file mode 100644 index 0000000..6faeaa47 --- /dev/null +++ b/components/services/leveldb/public/cpp/OWNERS
@@ -0,0 +1,4 @@ +per-file manifest.cc=set noparent +per-file manifest.cc=file://ipc/SECURITY_OWNERS +per-file manifest.h=set noparent +per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/components/services/leveldb/public/cpp/manifest.cc b/components/services/leveldb/public/cpp/manifest.cc new file mode 100644 index 0000000..fc81f0c4 --- /dev/null +++ b/components/services/leveldb/public/cpp/manifest.cc
@@ -0,0 +1,28 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/services/leveldb/public/cpp/manifest.h" + +#include "base/no_destructor.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" +#include "services/service_manager/public/cpp/manifest_builder.h" + +namespace leveldb { + +const service_manager::Manifest& GetManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .WithServiceName("leveldb") + .WithDisplayName("LevelDB Service") + .WithOptions(service_manager::ManifestOptionsBuilder() + .WithSandboxType("none") + .Build()) + .ExposeCapability( + "leveldb:leveldb", + service_manager::Manifest::InterfaceList<mojom::LevelDBService>()) + .Build()}; + return *manifest; +} + +} // namespace leveldb
diff --git a/components/services/leveldb/public/cpp/manifest.h b/components/services/leveldb/public/cpp/manifest.h new file mode 100644 index 0000000..09d6c6a --- /dev/null +++ b/components/services/leveldb/public/cpp/manifest.h
@@ -0,0 +1,16 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_MANIFEST_H_ +#define COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_MANIFEST_H_ + +#include "services/service_manager/public/cpp/manifest.h" + +namespace leveldb { + +const service_manager::Manifest& GetManifest(); + +} // namespace leveldb + +#endif // COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_MANIFEST_H_
diff --git a/components/services/leveldb/remote_iterator_unittest.cc b/components/services/leveldb/remote_iterator_unittest.cc index a209a46..4e482fe 100644 --- a/components/services/leveldb/remote_iterator_unittest.cc +++ b/components/services/leveldb/remote_iterator_unittest.cc
@@ -8,10 +8,11 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" -#include "components/services/leveldb/leveldb_service_unittests_catalog_source.h" +#include "components/services/leveldb/public/cpp/manifest.h" #include "components/services/leveldb/public/cpp/remote_iterator.h" #include "components/services/leveldb/public/cpp/util.h" #include "components/services/leveldb/public/interfaces/leveldb.mojom.h" +#include "services/service_manager/public/cpp/manifest_builder.h" #include "services/service_manager/public/cpp/test/test_service.h" #include "services/service_manager/public/cpp/test/test_service_manager.h" #include "testing/gtest/include/gtest/gtest.h" @@ -42,12 +43,18 @@ quit_closure); } +const char kTestServiceName[] = "leveldb_service_unittests"; + class RemoteIteratorTest : public testing::Test { public: RemoteIteratorTest() - : test_service_manager_(test::CreateTestCatalog()), - test_service_(test_service_manager_.RegisterTestInstance( - "leveldb_service_unittests")) {} + : test_service_manager_( + {GetManifest(), service_manager::ManifestBuilder() + .WithServiceName(kTestServiceName) + .RequireCapability("leveldb", "leveldb:leveldb") + .Build()}), + test_service_( + test_service_manager_.RegisterTestInstance(kTestServiceName)) {} ~RemoteIteratorTest() override = default; protected:
diff --git a/components/services/leveldb/test_manifest.json b/components/services/leveldb/test_manifest.json deleted file mode 100644 index 30a2da69..0000000 --- a/components/services/leveldb/test_manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "leveldb_service_unittests", - "display_name": "LevelDB Service Unittests", - "interface_provider_specs": { - "service_manager:connector": { - "requires": { - "filesystem": [ "filesystem:filesystem" ], - "leveldb": [ "leveldb:leveldb" ] - } - } - } -}
diff --git a/components/test/BUILD.gn b/components/test/BUILD.gn index 870351a..59e4418 100644 --- a/components/test/BUILD.gn +++ b/components/test/BUILD.gn
@@ -3,8 +3,6 @@ # found in the LICENSE file. import("//printing/buildflags/buildflags.gni") -import("//services/catalog/public/tools/catalog.gni") -import("//services/service_manager/public/service_manifest.gni") import("//ui/base/ui_features.gni") source_set("test_support") {
diff --git a/components/url_formatter/idn_spoof_checker.cc b/components/url_formatter/idn_spoof_checker.cc index def420e..644c1f23 100644 --- a/components/url_formatter/idn_spoof_checker.cc +++ b/components/url_formatter/idn_spoof_checker.cc
@@ -35,24 +35,22 @@ if (!reader->Next(&is_same_skeleton)) return false; - if (is_same_skeleton) { - *out_found = true; - result_ = search; - return true; - } - - bool has_com_suffix = false; - if (!reader->Next(&has_com_suffix)) - return false; - std::string top_domain; - for (char c;; top_domain += c) { - huffman_decoder().Decode(reader, &c); - if (c == net::extras::PreloadDecoder::kEndOfTable) - break; + if (is_same_skeleton) { + top_domain = search; + } else { + bool has_com_suffix = false; + if (!reader->Next(&has_com_suffix)) + return false; + + for (char c;; top_domain += c) { + huffman_decoder().Decode(reader, &c); + if (c == net::extras::PreloadDecoder::kEndOfTable) + break; + } + if (has_com_suffix) + top_domain += ".com"; } - if (has_com_suffix) - top_domain += ".com"; if (current_search_offset == 0) { *out_found = true;
diff --git a/components/url_formatter/url_formatter_unittest.cc b/components/url_formatter/url_formatter_unittest.cc index dbced74..e935fe50 100644 --- a/components/url_formatter/url_formatter_unittest.cc +++ b/components/url_formatter/url_formatter_unittest.cc
@@ -1012,8 +1012,21 @@ // Test that top domains whose skeletons are the same as the domain name are // handled properly. In this case, tést.net should match test.net top - // domain. + // domain and not be converted to unicode. {"xn--tst-bma.net", L"t\x00e9st.net", false}, + // Variations of the above, for testing crbug.com/925199. + // some.tést.net should match test.net. + {"some.xn--tst-bma.net", L"some.t\x00e9st.net", false}, + // The following should not match test.net, so should be converted to + // unicode. + // ést.net (a suffix of tést.net). + {"xn--st-9ia.net", L"\x00e9st.net", true}, + // some.ést.net + {"some.xn--st-9ia.net", L"some.\x00e9st.net", true}, + // atést.net (tést.net is a suffix of atést.net) + {"xn--atst-cpa.net", L"at\x00e9st.net", true}, + // some.atést.net + {"some.xn--atst-cpa.net", L"some.at\x00e9st.net", true}, // Modifier-letter-voicing should be blocked (wwwˬtest.com). {"xn--wwwtest-2be.com", L"www\x02ectest.com", false},
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc index 6c53f8b..13d1bca 100644 --- a/components/variations/service/variations_service.cc +++ b/components/variations/service/variations_service.cc
@@ -25,6 +25,7 @@ #include "base/task/post_task.h" #include "base/task_runner_util.h" #include "base/timer/elapsed_timer.h" +#include "base/trace_event/trace_event.h" #include "base/values.h" #include "base/version.h" #include "build/build_config.h" @@ -692,6 +693,7 @@ void VariationsService::OnSimpleLoaderCompleteOrRedirect( std::unique_ptr<std::string> response_body, bool was_redirect) { + TRACE_EVENT0("browser", "VariationsService::OnSimpleLoaderCompleteOrRedirect"); const bool is_first_request = !initial_request_completed_; initial_request_completed_ = true;
diff --git a/components/viz/service/display_embedder/gpu_display_provider.cc b/components/viz/service/display_embedder/gpu_display_provider.cc index c8f499e..28bc28a 100644 --- a/components/viz/service/display_embedder/gpu_display_provider.cc +++ b/components/viz/service/display_embedder/gpu_display_provider.cc
@@ -150,7 +150,14 @@ if (IsFatalOrSurfaceFailure(context_result)) { #if defined(OS_ANDROID) - display_client->OnFatalOrSurfaceContextCreationFailure(context_result); + // Ignore context creation failures if exiting for lost context. We are + // about to lose the GPU process and Viz will re-create the context at + // that point. + if (!gpu_service_impl_->gpu_channel_manager() + ->is_exiting_for_lost_context()) { + display_client->OnFatalOrSurfaceContextCreationFailure( + context_result); + } #endif gpu_service_impl_->DisableGpuCompositing(); return nullptr;
diff --git a/components/viz/service/main/BUILD.gn b/components/viz/service/main/BUILD.gn index 13b0a27..6a7c537 100644 --- a/components/viz/service/main/BUILD.gn +++ b/components/viz/service/main/BUILD.gn
@@ -4,8 +4,6 @@ import("//build/config/ui.gni") import("//components/ui_devtools/devtools.gni") -import("//services/catalog/public/tools/catalog.gni") -import("//services/service_manager/public/service_manifest.gni") import("//testing/test.gni") source_set("main") {
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc index 8e975e9..6952610 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.cc +++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -585,9 +585,8 @@ return; } - if (services_uuid && - !allowed_devices().IsAllowedToAccessService(device_id, - services_uuid.value())) { + if (services_uuid && !allowed_devices().IsAllowedToAccessService( + device_id, services_uuid.value())) { std::move(callback).Run( blink::mojom::WebBluetoothResult::NOT_ALLOWED_TO_ACCESS_SERVICE, base::nullopt /* service */);
diff --git a/content/browser/content_service_delegate_impl.cc b/content/browser/content_service_delegate_impl.cc index 5f86d42..f792a5e 100644 --- a/content/browser/content_service_delegate_impl.cc +++ b/content/browser/content_service_delegate_impl.cc
@@ -58,6 +58,11 @@ WebContentsObserver::Observe(nullptr); } + bool TakeFocus(WebContents* source, bool reverse) override { + client_->ClearViewFocus(); + return true; + } + private: void NotifyAXTreeChange() { auto* rfh = web_contents_->GetMainFrame();
diff --git a/content/browser/dom_storage/dom_storage_area_unittest.cc b/content/browser/dom_storage/dom_storage_area_unittest.cc index b0c0ead..55f0ced 100644 --- a/content/browser/dom_storage/dom_storage_area_unittest.cc +++ b/content/browser/dom_storage/dom_storage_area_unittest.cc
@@ -85,7 +85,7 @@ ~DOMStorageAreaParamTest() override {} }; -INSTANTIATE_TEST_CASE_P(_, DOMStorageAreaParamTest, ::testing::Bool()); +INSTANTIATE_TEST_SUITE_P(_, DOMStorageAreaParamTest, ::testing::Bool()); TEST_P(DOMStorageAreaParamTest, DOMStorageAreaBasics) { const std::string kFirstNamespaceId = "id1";
diff --git a/content/browser/dom_storage/storage_area_impl_unittest.cc b/content/browser/dom_storage/storage_area_impl_unittest.cc index b1e8918..7357675 100644 --- a/content/browser/dom_storage/storage_area_impl_unittest.cc +++ b/content/browser/dom_storage/storage_area_impl_unittest.cc
@@ -313,10 +313,10 @@ ~StorageAreaImplParamTest() override {} }; -INSTANTIATE_TEST_CASE_P(StorageAreaImplTest, - StorageAreaImplParamTest, - testing::Values(CacheMode::KEYS_ONLY_WHEN_POSSIBLE, - CacheMode::KEYS_AND_VALUES)); +INSTANTIATE_TEST_SUITE_P(StorageAreaImplTest, + StorageAreaImplParamTest, + testing::Values(CacheMode::KEYS_ONLY_WHEN_POSSIBLE, + CacheMode::KEYS_AND_VALUES)); TEST_F(StorageAreaImplTest, GetLoadedFromMap) { storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
diff --git a/content/browser/media/hardware_key_media_controller.cc b/content/browser/media/hardware_key_media_controller.cc index 26be8a4..cb9b92a9 100644 --- a/content/browser/media/hardware_key_media_controller.cc +++ b/content/browser/media/hardware_key_media_controller.cc
@@ -31,12 +31,12 @@ controller_manager_ptr->CreateActiveMediaController( mojo::MakeRequest(&media_controller_ptr_)); - // Observe the active media session for changes to playback state and + // Observe the active media controller for changes to playback state and // supported actions. - media_session::mojom::MediaSessionObserverPtr media_session_observer; - media_session_observer_binding_.Bind( - mojo::MakeRequest(&media_session_observer)); - media_controller_ptr_->AddObserver(std::move(media_session_observer)); + media_session::mojom::MediaControllerObserverPtr media_controller_observer; + media_controller_observer_binding_.Bind( + mojo::MakeRequest(&media_controller_observer)); + media_controller_ptr_->AddObserver(std::move(media_controller_observer)); } HardwareKeyMediaController::~HardwareKeyMediaController() = default; @@ -175,4 +175,4 @@ } } -} // namespace content \ No newline at end of file +} // namespace content
diff --git a/content/browser/media/hardware_key_media_controller.h b/content/browser/media/hardware_key_media_controller.h index 1e5d40e..d8150446 100644 --- a/content/browser/media/hardware_key_media_controller.h +++ b/content/browser/media/hardware_key_media_controller.h
@@ -13,7 +13,6 @@ #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/media_session/public/mojom/media_controller.mojom.h" -#include "services/media_session/public/mojom/media_session.mojom.h" #include "ui/base/accelerators/media_keys_listener.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -25,13 +24,13 @@ // HardwareKeyMediaController controls media sessions via hardware media keys. class CONTENT_EXPORT HardwareKeyMediaController - : public media_session::mojom::MediaSessionObserver, + : public media_session::mojom::MediaControllerObserver, public ui::MediaKeysListener::Delegate { public: explicit HardwareKeyMediaController(service_manager::Connector* connector); ~HardwareKeyMediaController() override; - // media_session::mojom::MediaSessionObserver: + // media_session::mojom::MediaControllerObserver: void MediaSessionInfoChanged( media_session::mojom::MediaSessionInfoPtr session_info) override; void MediaSessionMetadataChanged( @@ -72,13 +71,13 @@ // Used to check which actions are currently supported. base::flat_set<media_session::mojom::MediaSessionAction> actions_; - // Used to receive updates to the active MediaSession. - mojo::Binding<media_session::mojom::MediaSessionObserver> - media_session_observer_binding_{this}; + // Used to receive updates to the active media controller. + mojo::Binding<media_session::mojom::MediaControllerObserver> + media_controller_observer_binding_{this}; DISALLOW_COPY_AND_ASSIGN(HardwareKeyMediaController); }; } // namespace content -#endif // CONTENT_BROWSER_MEDIA_HARDWARE_KEY_MEDIA_CONTROLLER_H_ \ No newline at end of file +#endif // CONTENT_BROWSER_MEDIA_HARDWARE_KEY_MEDIA_CONTROLLER_H_
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index e24b46ac..0d3a9e7 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -862,7 +862,7 @@ host_->SetNeedsAnimate(); } -void CompositorImpl::UpdateLayerTreeHost(bool record_main_frame_metrics) { +void CompositorImpl::UpdateLayerTreeHost() { client_->UpdateLayerTreeHost(); if (needs_animate_) { needs_animate_ = false;
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h index 9cd93e5..cce753d 100644 --- a/content/browser/renderer_host/compositor_impl_android.h +++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -113,7 +113,7 @@ void BeginMainFrame(const viz::BeginFrameArgs& args) override {} void BeginMainFrameNotExpectedSoon() override {} void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override {} - void UpdateLayerTreeHost(bool record_main_frame_metrics) override; + void UpdateLayerTreeHost() override; void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override { } void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel, @@ -134,6 +134,7 @@ void DidPresentCompositorFrame( uint32_t frame_token, const gfx::PresentationFeedback& feedback) override {} + void RecordStartOfFrameMetrics() override {} void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override {} void DidGenerateLocalSurfaceIdAllocation( const viz::LocalSurfaceIdAllocation& allocation) override {}
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc index 80175b1..bcc0bb0 100644 --- a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -265,8 +265,8 @@ buffer4.reset(); } -INSTANTIATE_TEST_CASE_P(, - VideoCaptureBufferPoolTest, - testing::ValuesIn(kCapturePixelFormats)); +INSTANTIATE_TEST_SUITE_P(, + VideoCaptureBufferPoolTest, + testing::ValuesIn(kCapturePixelFormats)); } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index 7f04243d8..b8b10dd 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -1528,7 +1528,7 @@ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMacPinchTest); }; -INSTANTIATE_TEST_CASE_P(, RenderWidgetHostViewMacPinchTest, testing::Bool()); +INSTANTIATE_TEST_SUITE_P(, RenderWidgetHostViewMacPinchTest, testing::Bool()); TEST_P(RenderWidgetHostViewMacPinchTest, PinchThresholding) { // Do a gesture that crosses the threshold.
diff --git a/content/browser/serial/serial_browsertest.cc b/content/browser/serial/serial_browsertest.cc index 91b05d11..361bd9d7 100644 --- a/content/browser/serial/serial_browsertest.cc +++ b/content/browser/serial/serial_browsertest.cc
@@ -7,7 +7,9 @@ #include "base/command_line.h" #include "base/unguessable_token.h" -#include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/serial_chooser.h" +#include "content/public/browser/serial_delegate.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" @@ -15,6 +17,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::_; using testing::ByMove; using testing::Return; @@ -22,34 +25,121 @@ namespace { -class MockWebContentsDelegate : public WebContentsDelegate { +class FakeSerialPortManager : public device::mojom::SerialPortManager { public: - MockWebContentsDelegate() {} - ~MockWebContentsDelegate() override {} + FakeSerialPortManager() = default; + ~FakeSerialPortManager() override = default; - std::unique_ptr<SerialChooser> RunSerialChooser( - content::RenderFrameHost* frame, + void AddPort(device::mojom::SerialPortInfoPtr port) { + base::UnguessableToken token = port->token; + ports_[token] = std::move(port); + } + + // device::mojom::SerialPortManager + void GetDevices(GetDevicesCallback callback) override { + std::vector<device::mojom::SerialPortInfoPtr> ports; + for (const auto& map_entry : ports_) + ports.push_back(map_entry.second.Clone()); + std::move(callback).Run(std::move(ports)); + } + + void GetPort(const base::UnguessableToken& token, + device::mojom::SerialPortRequest request) override {} + + private: + std::map<base::UnguessableToken, device::mojom::SerialPortInfoPtr> ports_; + + DISALLOW_COPY_AND_ASSIGN(FakeSerialPortManager); +}; + +class MockSerialDelegate : public SerialDelegate { + public: + MockSerialDelegate() = default; + ~MockSerialDelegate() override = default; + + std::unique_ptr<SerialChooser> RunChooser( + RenderFrameHost* frame, std::vector<blink::mojom::SerialPortFilterPtr> filters, - content::SerialChooser::Callback callback) override { - std::move(callback).Run(RunSerialChooserInternal()); + SerialChooser::Callback callback) override { + std::move(callback).Run(RunChooserInternal()); return nullptr; } - MOCK_METHOD0(RunSerialChooserInternal, blink::mojom::SerialPortInfoPtr()); + MOCK_METHOD0(RunChooserInternal, device::mojom::SerialPortInfoPtr()); + MOCK_METHOD2(HasPortPermission, + bool(content::RenderFrameHost* frame, + const device::mojom::SerialPortInfo& port)); + MOCK_METHOD1( + GetPortManager, + device::mojom::SerialPortManager*(content::RenderFrameHost* frame)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockSerialDelegate); }; -} // namespace +class TestContentBrowserClient : public ContentBrowserClient { + public: + TestContentBrowserClient() = default; + ~TestContentBrowserClient() override = default; + + MockSerialDelegate& delegate() { return delegate_; } + + SerialDelegate* GetSerialDelegate() override { return &delegate_; } + + private: + MockSerialDelegate delegate_; + + DISALLOW_COPY_AND_ASSIGN(TestContentBrowserClient); +}; class SerialTest : public ContentBrowserTest { + public: + SerialTest() { + ON_CALL(delegate(), GetPortManager).WillByDefault(Return(&port_manager_)); + } + + ~SerialTest() override = default; + void SetUpCommandLine(base::CommandLine* command_line) override { ContentBrowserTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII("enable-blink-features", "Serial"); } + + void SetUpOnMainThread() override { + original_client_ = SetBrowserClientForTesting(&test_client_); + } + + void TearDownOnMainThread() override { + if (original_client_) + SetBrowserClientForTesting(original_client_); + } + + MockSerialDelegate& delegate() { return test_client_.delegate(); } + FakeSerialPortManager* port_manager() { return &port_manager_; } + + private: + TestContentBrowserClient test_client_; + ContentBrowserClient* original_client_ = nullptr; + FakeSerialPortManager port_manager_; }; +} // namespace + IN_PROC_BROWSER_TEST_F(SerialTest, GetPorts) { NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html")); + // Three ports are added but only two will have permission granted. + for (size_t i = 0; i < 3; i++) { + auto port = device::mojom::SerialPortInfo::New(); + port->token = base::UnguessableToken::Create(); + port_manager()->AddPort(std::move(port)); + } + + EXPECT_CALL(delegate(), HasPortPermission(_, _)) + .WillOnce(Return(true)) + .WillOnce(Return(false)) + .WillOnce(Return(true)); + int result; EXPECT_TRUE(ExecuteScriptAndExtractInt( shell(), @@ -58,18 +148,15 @@ " domAutomationController.send(ports.length);" " });", &result)); - EXPECT_EQ(0, result); + EXPECT_EQ(2, result); } IN_PROC_BROWSER_TEST_F(SerialTest, RequestPort) { NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html")); - MockWebContentsDelegate delegate; - shell()->web_contents()->SetDelegate(&delegate); - - auto port = blink::mojom::SerialPortInfo::New(); + auto port = device::mojom::SerialPortInfo::New(); port->token = base::UnguessableToken::Create(); - EXPECT_CALL(delegate, RunSerialChooserInternal) + EXPECT_CALL(delegate(), RunChooserInternal) .WillOnce(Return(ByMove(std::move(port)))); bool result;
diff --git a/content/browser/serial/serial_service.cc b/content/browser/serial/serial_service.cc index 0029965..8a6cf13 100644 --- a/content/browser/serial/serial_service.cc +++ b/content/browser/serial/serial_service.cc
@@ -4,12 +4,31 @@ #include "content/browser/serial/serial_service.h" +#include <utility> + +#include "content/public/browser/content_browser_client.h" #include "content/public/browser/serial_chooser.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/serial_delegate.h" namespace content { +namespace { + +blink::mojom::SerialPortInfoPtr ToBlinkType( + const device::mojom::SerialPortInfo& port) { + auto info = blink::mojom::SerialPortInfo::New(); + info->token = port.token; + info->has_vendor_id = port.has_vendor_id; + if (port.has_vendor_id) + info->vendor_id = port.vendor_id; + info->has_product_id = port.has_product_id; + if (port.has_product_id) + info->product_id = port.product_id; + return info; +} + +} // namespace + SerialService::SerialService(RenderFrameHost* render_frame_host) : render_frame_host_(render_frame_host) {} @@ -20,21 +39,60 @@ } void SerialService::GetPorts(GetPortsCallback callback) { - std::move(callback).Run(std::vector<blink::mojom::SerialPortInfoPtr>()); + SerialDelegate* delegate = GetContentClient()->browser()->GetSerialDelegate(); + if (!delegate) { + std::move(callback).Run(std::vector<blink::mojom::SerialPortInfoPtr>()); + return; + } + + delegate->GetPortManager(render_frame_host_) + ->GetDevices(base::BindOnce(&SerialService::FinishGetPorts, + weak_factory_.GetWeakPtr(), + std::move(callback))); } void SerialService::RequestPort( std::vector<blink::mojom::SerialPortFilterPtr> filters, RequestPortCallback callback) { - WebContentsDelegate* delegate = - WebContents::FromRenderFrameHost(render_frame_host_)->GetDelegate(); + SerialDelegate* delegate = GetContentClient()->browser()->GetSerialDelegate(); if (!delegate) { std::move(callback).Run(nullptr); return; } - chooser_ = delegate->RunSerialChooser(render_frame_host_, std::move(filters), - std::move(callback)); + chooser_ = delegate->RunChooser( + render_frame_host_, std::move(filters), + base::BindOnce(&SerialService::FinishRequestPort, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void SerialService::FinishGetPorts( + GetPortsCallback callback, + std::vector<device::mojom::SerialPortInfoPtr> ports) { + std::vector<blink::mojom::SerialPortInfoPtr> result; + SerialDelegate* delegate = GetContentClient()->browser()->GetSerialDelegate(); + if (!delegate) { + std::move(callback).Run(std::move(result)); + return; + } + + for (const auto& port : ports) { + if (delegate->HasPortPermission(render_frame_host_, *port)) + result.push_back(ToBlinkType(*port)); + } + + std::move(callback).Run(std::move(result)); +} + +void SerialService::FinishRequestPort(RequestPortCallback callback, + device::mojom::SerialPortInfoPtr port) { + SerialDelegate* delegate = GetContentClient()->browser()->GetSerialDelegate(); + if (!delegate || !port) { + std::move(callback).Run(nullptr); + return; + } + + std::move(callback).Run(ToBlinkType(*port)); } } // namespace content
diff --git a/content/browser/serial/serial_service.h b/content/browser/serial/serial_service.h index 959df98..81c8048 100644 --- a/content/browser/serial/serial_service.h +++ b/content/browser/serial/serial_service.h
@@ -5,10 +5,13 @@ #ifndef CONTENT_BROWSER_SERIAL_SERIAL_SERVICE_H_ #define CONTENT_BROWSER_SERIAL_SERIAL_SERVICE_H_ +#include <memory> #include <vector> #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "mojo/public/cpp/bindings/binding_set.h" +#include "services/device/public/mojom/serial.mojom.h" #include "third_party/blink/public/mojom/serial/serial.mojom.h" namespace content { @@ -29,12 +32,19 @@ RequestPortCallback callback) override; private: + void FinishGetPorts(GetPortsCallback callback, + std::vector<device::mojom::SerialPortInfoPtr> ports); + void FinishRequestPort(RequestPortCallback callback, + device::mojom::SerialPortInfoPtr port); + RenderFrameHost* const render_frame_host_; mojo::BindingSet<blink::mojom::SerialService> bindings_; // The last shown serial port chooser UI. std::unique_ptr<SerialChooser> chooser_; + base::WeakPtrFactory<SerialService> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(SerialService); };
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index 156186f8..ba78ffd 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc
@@ -1391,7 +1391,8 @@ base::RunLoop().RunUntilIdle(); } -TEST_F(StoragePartitionImplTest, ClearCodeCacheDateRange) { +// TODO(https://crbug.com/925957): Flakes, especially under Fuchsia. +TEST_F(StoragePartitionImplTest, DISABLED_ClearCodeCacheDateRange) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache); ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 916d52bc..0d9061f 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -263,6 +263,7 @@ "security_style_explanations.h", "serial_chooser.cc", "serial_chooser.h", + "serial_delegate.h", "service_worker_context.h", "service_worker_context_observer.h", "session_storage_namespace.h",
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 984a6e00..61e4af6 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -803,6 +803,10 @@ RenderFrameHost* render_frame_host, mojo::InterfaceRequest<blink::mojom::WebUsbService> request) {} +SerialDelegate* ContentBrowserClient::GetSerialDelegate() { + return nullptr; +} + bool ContentBrowserClient::ShowPaymentHandlerWindow( content::BrowserContext* browser_context, const GURL& url,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 468d989..6d141289 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -171,6 +171,7 @@ class RenderProcessHost; class RenderViewHost; class ResourceContext; +class SerialDelegate; class ServiceManagerConnection; class SiteInstance; class SpeechRecognitionManagerDelegate; @@ -1313,6 +1314,9 @@ RenderFrameHost* render_frame_host, mojo::InterfaceRequest<blink::mojom::WebUsbService> request); + // Allows the embedder to provide an implementation of the Serial API. + virtual SerialDelegate* GetSerialDelegate(); + // Attempt to open the Payment Handler window inside its corresponding // PaymentRequest UI surface. Returns true if the ContentBrowserClient // implementation supports this operation (desktop Chrome) or false otherwise.
diff --git a/content/public/browser/serial_chooser.h b/content/public/browser/serial_chooser.h index 4d4401d..415d0db4 100644 --- a/content/public/browser/serial_chooser.h +++ b/content/public/browser/serial_chooser.h
@@ -8,7 +8,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "content/common/content_export.h" -#include "third_party/blink/public/mojom/serial/serial.mojom.h" +#include "services/device/public/mojom/serial.mojom.h" namespace content { @@ -18,7 +18,7 @@ public: // Callback type used to report the user action. Passed |nullptr| if no port // was selected. - using Callback = base::OnceCallback<void(blink::mojom::SerialPortInfoPtr)>; + using Callback = base::OnceCallback<void(device::mojom::SerialPortInfoPtr)>; SerialChooser(); virtual ~SerialChooser();
diff --git a/content/public/browser/serial_delegate.h b/content/public/browser/serial_delegate.h new file mode 100644 index 0000000..aaea94ba --- /dev/null +++ b/content/public/browser/serial_delegate.h
@@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_SERIAL_DELEGATE_H_ +#define CONTENT_PUBLIC_BROWSER_SERIAL_DELEGATE_H_ + +#include <memory> +#include <vector> + +#include "content/common/content_export.h" +#include "content/public/browser/serial_chooser.h" +#include "services/device/public/mojom/serial.mojom.h" +#include "third_party/blink/public/mojom/serial/serial.mojom.h" + +namespace content { + +class RenderFrameHost; + +class CONTENT_EXPORT SerialDelegate { + public: + virtual ~SerialDelegate() = default; + + // Shows a chooser for the user to select a serial port. |callback| will be + // run when the prompt is closed. Deleting the returned object will cancel the + // prompt. + virtual std::unique_ptr<SerialChooser> RunChooser( + RenderFrameHost* frame, + std::vector<blink::mojom::SerialPortFilterPtr> filters, + SerialChooser::Callback callback) = 0; + + // Returns whether |frame| has permission to access |port|. + virtual bool HasPortPermission(RenderFrameHost* frame, + const device::mojom::SerialPortInfo& port) = 0; + + // Returns an open connection to the SerialPortManager interface owned by + // the embedder and being used to serve requests from |frame|. + // + // Content and the embedder must use the same connection so that the embedder + // can process connect/disconnect events for permissions management purposes + // before they are delivered to content. Otherwise race conditions are + // possible. + virtual device::mojom::SerialPortManager* GetPortManager( + RenderFrameHost* frame) = 0; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_SERIAL_DELEGATE_H_
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc index 3ce59d6..84bf210 100644 --- a/content/public/browser/web_contents_delegate.cc +++ b/content/public/browser/web_contents_delegate.cc
@@ -143,14 +143,6 @@ return nullptr; } -std::unique_ptr<SerialChooser> WebContentsDelegate::RunSerialChooser( - RenderFrameHost* frame, - std::vector<blink::mojom::SerialPortFilterPtr> filters, - SerialChooser::Callback callback) { - std::move(callback).Run(nullptr); - return nullptr; -} - bool WebContentsDelegate::EmbedsFullscreenWidget() const { return false; }
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h index 7e76c0e6..b02226b 100644 --- a/content/public/browser/web_contents_delegate.h +++ b/content/public/browser/web_contents_delegate.h
@@ -395,14 +395,6 @@ RenderFrameHost* frame, const BluetoothChooser::EventHandler& event_handler); - // Shows a chooser for the user to select a serial port. |callback| will be - // run when the prompt is closed. Deleting the returned object will cancel the - // prompt. - virtual std::unique_ptr<SerialChooser> RunSerialChooser( - RenderFrameHost* frame, - std::vector<blink::mojom::SerialPortFilterPtr> filters, - SerialChooser::Callback callback); - // Returns true if the delegate will embed a WebContents-owned fullscreen // render widget. In this case, the delegate may access the widget by calling // WebContents::GetFullscreenRenderWidgetHostView(). If false is returned,
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc index f9bbf582..86cca0a 100644 --- a/content/renderer/compositor/layer_tree_view.cc +++ b/content/renderer/compositor/layer_tree_view.cc
@@ -500,7 +500,7 @@ // frame, but the compositor does not support this. In this case, we only // run blink's lifecycle updates. delegate_->BeginMainFrame(base::TimeTicks::Now()); - delegate_->UpdateVisualState(false /* record_main_frame_metrics */); + delegate_->UpdateVisualState(); return; } @@ -602,8 +602,8 @@ web_main_thread_scheduler_->BeginMainFrameNotExpectedUntil(time); } -void LayerTreeView::UpdateLayerTreeHost(bool record_main_frame_metrics) { - delegate_->UpdateVisualState(record_main_frame_metrics); +void LayerTreeView::UpdateLayerTreeHost() { + delegate_->UpdateVisualState(); } void LayerTreeView::ApplyViewportChanges( @@ -704,6 +704,10 @@ } } +void LayerTreeView::RecordStartOfFrameMetrics() { + delegate_->RecordStartOfFrameMetrics(); +} + void LayerTreeView::RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) { delegate_->RecordEndOfFrameMetrics(frame_begin_time); }
diff --git a/content/renderer/compositor/layer_tree_view.h b/content/renderer/compositor/layer_tree_view.h index a9eb7ce..aa54b853 100644 --- a/content/renderer/compositor/layer_tree_view.h +++ b/content/renderer/compositor/layer_tree_view.h
@@ -191,7 +191,7 @@ void BeginMainFrame(const viz::BeginFrameArgs& args) override; void BeginMainFrameNotExpectedSoon() override; void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override; - void UpdateLayerTreeHost(bool record_main_frame_metrics) override; + void UpdateLayerTreeHost() override; void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override; void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel, bool has_scrolled_by_touch) override; @@ -211,6 +211,7 @@ void DidPresentCompositorFrame( uint32_t frame_token, const gfx::PresentationFeedback& feedback) override; + void RecordStartOfFrameMetrics() override; void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override; void DidGenerateLocalSurfaceIdAllocation( const viz::LocalSurfaceIdAllocation& allocation) override {}
diff --git a/content/renderer/compositor/layer_tree_view_delegate.h b/content/renderer/compositor/layer_tree_view_delegate.h index f3ef7a52..a5d2d82 100644 --- a/content/renderer/compositor/layer_tree_view_delegate.h +++ b/content/renderer/compositor/layer_tree_view_delegate.h
@@ -53,7 +53,7 @@ virtual void SendScrollEndEventFromImplSide( cc::ElementId scroll_latched_element_id) = 0; - // Notifies that the compositor has issed a BeginMainFrame. + // Notifies that the compositor has issued a BeginMainFrame. virtual void BeginMainFrame(base::TimeTicks frame_time) = 0; // Requests a LayerTreeFrameSink to submit CompositorFrames to. @@ -69,20 +69,26 @@ // Called by the compositor when page scale animation completed. virtual void DidCompletePageScaleAnimation() = 0; - // Requests that a UMA and UKM metric be recorded for the total frame time. - // Call this as soon as the total frame time becomes known for a given frame. - // For example, ProxyMain::BeginMainFrame calls it immediately before aborting - // or committing a frame (at the same time Tracing measurements are taken). + // Requests that a UMA and UKM metrics be recorded for the total frame time + // and the portion of frame time spent in various sub-systems. + // Call RecordStartOfFrameMetrics when a main frame is starting, and call + // RecordEndOfFrameMetrics as soon as the total frame time becomes known for + // a given frame. For example, ProxyMain::BeginMainFrame calls + // RecordStartOfFrameMetrics just be WillBeginCompositorFrame() and + // RecordEndOfFrameMetrics immediately before aborting or committing a frame + // (at the same time Tracing measurements are taken). + virtual void RecordStartOfFrameMetrics() = 0; virtual void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) = 0; // Requests a visual frame-based update to the state of the delegate if there - // is an update available. |record_main_frame_metrics| will be true if - // this is a main frame for which we want metrics. - virtual void UpdateVisualState(bool record_main_frame_metrics) = 0; + // is an update available. + virtual void UpdateVisualState() = 0; // Indicates that the compositor is about to begin a frame. This is primarily // to signal to flow control mechanisms that a frame is beginning, not to - // perform actual painting work. + // perform actual painting work. When |record_main_frame_metrics| is true + // we are in a frame that shoujld capture metrics data, and the local frame's + // UKM aggregator must be informed that the frame is starting. virtual void WillBeginCompositorFrame() = 0; // For use in web test mode only, attempts to copy the full content of the
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index e51bcafa..f75bf59 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -206,6 +206,21 @@ blink::WebWidget* webwidget_; }; +class ScopedUkmRafAlignedInputTimer { + public: + explicit ScopedUkmRafAlignedInputTimer(blink::WebWidget* webwidget) + : webwidget_(webwidget) { + webwidget_->BeginRafAlignedInput(); + } + + ~ScopedUkmRafAlignedInputTimer() { webwidget_->EndRafAlignedInput(); } + + private: + blink::WebWidget* webwidget_; + + DISALLOW_COPY_AND_ASSIGN(ScopedUkmRafAlignedInputTimer); +}; + bool IsDateTimeInput(ui::TextInputType type) { return type == ui::TEXT_INPUT_TYPE_DATE || type == ui::TEXT_INPUT_TYPE_DATE_TIME || @@ -983,10 +998,19 @@ void RenderWidget::BeginMainFrame(base::TimeTicks frame_time) { if (!GetWebWidget()) return; - if (input_event_queue_) - input_event_queue_->DispatchRafAlignedInput(frame_time); - GetWebWidget()->BeginFrame(frame_time); + // We record metrics only when running in multi-threaded mode, not + // single-thread mode for testing. + bool record_main_frame_metrics = + !!compositor_deps_->GetCompositorImplThreadTaskRunner(); + if (input_event_queue_) { + base::Optional<ScopedUkmRafAlignedInputTimer> ukm_timer; + if (record_main_frame_metrics) + ukm_timer.emplace(GetWebWidget()); + input_event_queue_->DispatchRafAlignedInput(frame_time); + } + + GetWebWidget()->BeginFrame(frame_time, record_main_frame_metrics); } void RenderWidget::RequestNewLayerTreeFrameSink( @@ -1120,10 +1144,15 @@ host->SetDebugState(debug_state); } -void RenderWidget::UpdateVisualState(bool record_main_frame_metrics) { +void RenderWidget::UpdateVisualState() { if (!GetWebWidget()) return; + // We record metrics only when running in multi-threaded mode, not + // single-thread mode for testing. + bool record_main_frame_metrics = + !!compositor_deps_->GetCompositorImplThreadTaskRunner(); + // When recording main frame metrics set the lifecycle reason to // kBeginMainFrame, because this is the calller of UpdateLifecycle // for the main frame. Otherwise, set the reason to kTests, which is @@ -1158,6 +1187,13 @@ } } +void RenderWidget::RecordStartOfFrameMetrics() { + if (!GetWebWidget()) + return; + + GetWebWidget()->RecordStartOfFrameMetrics(); +} + void RenderWidget::RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) { if (!GetWebWidget()) return;
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 9469c37b..a4fc4a0 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -313,8 +313,9 @@ void DidCommitAndDrawCompositorFrame() override; void DidCommitCompositorFrame() override; void DidCompletePageScaleAnimation() override; + void RecordStartOfFrameMetrics() override; void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override; - void UpdateVisualState(bool record_main_frame_metrics) override; + void UpdateVisualState() override; void WillBeginCompositorFrame() override; std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForWebTest( std::unique_ptr<viz::CopyOutputRequest> request) override;
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index 6295a33d..b7b3bbe 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -680,11 +680,11 @@ TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "START_WORKER_CONTEXT", this); - TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATE_SCRIPT", this); } void ServiceWorkerContextClient::WillEvaluateScript() { DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATE_SCRIPT", this); start_timing_->script_evaluation_start_time = base::TimeTicks::Now(); // Temporary CHECK for https://crbug.com/881100
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 40dd1b2..78ca1e6 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -76,7 +76,7 @@ #include "content/public/browser/context_factory.h" #include "content/public/browser/gpu_interface_provider_factory.h" #include "services/ws/public/mojom/constants.mojom.h" // nogncheck -#include "services/ws/test_ws/manifest.h" // nogncheck +#include "services/ws/test_ws/test_manifest.h" // nogncheck #include "services/ws/test_ws/test_window_service_factory.h" // nogncheck #include "services/ws/test_ws/test_ws.mojom.h" // nogncheck #endif
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index 7660dfb..c707c979 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -49,11 +49,16 @@ # TODO(vmiura) check / generate reference images for Android devices self.Fail('Pixel_SolidColorBackground', ['mac', 'android'], bug=624256) - self.Fail('Pixel_CSSFilterEffects', ['mac', ('nvidia', 0xfe9)], bug=690277) + # TODO(wangxianzhu): This is commented out temporarily because of the entry + # for crbug.com/836884. + # self.Fail('Pixel_CSSFilterEffects', ['mac', ('nvidia', 0xfe9)], + # bug=690277) # Became flaky on 10.13.6. When it flakes, it flakes 3 times, so # mark failing, unfortunately. - self.Fail('Pixel_CSSFilterEffects', ['highsierra', 'amd'], bug=872423) + # TODO(wangxianzhu): This is commented out temporarily because of the entry + # for crbug.com/836884. + # self.Fail('Pixel_CSSFilterEffects', ['highsierra', 'amd'], bug=872423) # TODO(kbr): flakily timing out on this configuration. self.Flaky('*', ['linux', 'intel', 'debug'], bug=648369) @@ -112,6 +117,12 @@ self.Fail('Pixel_BackgroundImage', ['android', ('qualcomm', 'Adreno (TM) 430')], bug=883500) + # TODO(wangxianzhu): Re-enable after and rebaselining + self.Fail('Pixel_CSSFilterEffects', bug=836884) + self.Fail('Pixel_CSSFilterEffects_NoOverlays', bug=836884) + self.Fail('Pixel_2DCanvasWebGL', bug=836884) + self.Fail('Pixel_CSS3DBlueBox', bug=836884) + # Fails on Mac Pro FYI Release (AMD) self.Fail('Pixel_Video_MP4', ['mac', ('amd', 0x679e)], bug=925744)
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 78a4d67c..6dc216bb 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -198,7 +198,7 @@ 'pixel_canvas2d_webgl.html', base_name + '_2DCanvasWebGL', test_rect=[0, 0, 300, 300], - revision=11), + revision=12), PixelTestPage( 'pixel_background.html', @@ -902,7 +902,7 @@ 'pixel_css3d.html', base_name + '_CSS3DBlueBox' + suffix, test_rect=[0, 0, 300, 300], - revision=1, + revision=2, browser_args=browser_args), PixelTestPage( @@ -1012,12 +1012,12 @@ 'filter_effects.html', base_name + '_CSSFilterEffects', test_rect=[0, 0, 300, 300], - revision=9), + revision=10), PixelTestPage( 'filter_effects.html', base_name + '_CSSFilterEffects_NoOverlays', test_rect=[0, 0, 300, 300], - revision=9, + revision=10, tolerance=10, browser_args=no_overlays_args),
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index ba36d2f..ca9744d7 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -492,6 +492,8 @@ self.Flaky( 'conformance/extensions/webgl-compressed-texture-size-limit.html', ['mac', ('nvidia', 0xfe9)], bug=483282) + self.Flaky('conformance/ogles/GL/exp2/exp2_001_to_008.html', + ['mac', ('nvidia', 0xfe9)], bug=923080) self.Fail('conformance/programs/' + 'gl-bind-attrib-location-long-names-test.html', ['mac', ('nvidia', 0xfe9)], bug=483282)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index c38577d..f81bb68 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -480,6 +480,8 @@ ['win', 'passthrough', 'vulkan'], bug=2905) # ANGLE bug ID self.Fail('WebglExtension_WEBGL_draw_buffers', ['win', 'passthrough', 'vulkan'], bug=2394) # ANGLE bug ID + self.Skip('deqp/data/gles2/shaders/swizzles.html', + ['win', 'passthrough', 'vulkan'], bug=3111) # ANGLE bug ID # Vulkan / Win / NVIDIA / Passthough command decoder self.Fail('conformance/canvas/' + @@ -501,9 +503,6 @@ ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2915) # ANGLE bug ID self.Fail('deqp/data/gles2/shaders/conversions.html', ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2926) # ANGLE bug ID - self.Fail('deqp/data/gles2/shaders/swizzles.html', - ['win', 'passthrough', 'vulkan', 'nvidia', 'debug'], - bug=2940) # ANGLE bug ID # Vulkan / Win / Intel / Passthough command decoder self.Fail('conformance/rendering/clipping-wide-points.html',
diff --git a/content/test/stub_layer_tree_view_delegate.h b/content/test/stub_layer_tree_view_delegate.h index 1e98a9b9c..a75b0eb 100644 --- a/content/test/stub_layer_tree_view_delegate.h +++ b/content/test/stub_layer_tree_view_delegate.h
@@ -26,13 +26,14 @@ void SendScrollEndEventFromImplSide( cc::ElementId scroll_latched_element_id) override {} void BeginMainFrame(base::TimeTicks frame_time) override {} + void RecordStartOfFrameMetrics() override {} void RecordEndOfFrameMetrics(base::TimeTicks) override {} void RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) override; void DidCommitAndDrawCompositorFrame() override {} void DidCommitCompositorFrame() override {} void DidCompletePageScaleAnimation() override {} - void UpdateVisualState(bool record_main_frame_metrics) override {} + void UpdateVisualState() override {} void WillBeginCompositorFrame() override {} std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForWebTest( std::unique_ptr<viz::CopyOutputRequest> request) override;
diff --git a/device/bluetooth/OWNERS b/device/bluetooth/OWNERS index 8ac8597..3b9f2534 100644 --- a/device/bluetooth/OWNERS +++ b/device/bluetooth/OWNERS
@@ -1,4 +1,7 @@ ortuno@chromium.org +reillyg@chromium.org +odejesush@chromium.org +dougt@chromium.org # For changes related to Chrome OS. rkc@chromium.org
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java index 9256c38..b6067bfb 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java
@@ -289,9 +289,10 @@ // Object can be destroyed, but Android keeps calling onScanResult. if (mNativeBluetoothAdapterAndroid != 0) { nativeCreateOrUpdateDeviceOnScan(mNativeBluetoothAdapterAndroid, - result.getDevice().getAddress(), result.getDevice(), result.getRssi(), - uuid_strings, result.getScanRecord_getTxPowerLevel(), serviceDataKeys, - serviceDataValues, manufacturerDataKeys, manufacturerDataValues); + result.getDevice().getAddress(), result.getDevice(), + result.getScanRecord_getDeviceName(), result.getRssi(), uuid_strings, + result.getScanRecord_getTxPowerLevel(), serviceDataKeys, serviceDataValues, + manufacturerDataKeys, manufacturerDataValues); } } @@ -349,8 +350,8 @@ // Binds to BluetoothAdapterAndroid::CreateOrUpdateDeviceOnScan. private native void nativeCreateOrUpdateDeviceOnScan(long nativeBluetoothAdapterAndroid, - String address, Wrappers.BluetoothDeviceWrapper deviceWrapper, int rssi, - String[] advertisedUuids, int txPower, String[] serviceDataKeys, + String address, Wrappers.BluetoothDeviceWrapper deviceWrapper, String localName, + int rssi, String[] advertisedUuids, int txPower, String[] serviceDataKeys, Object[] serviceDataValues, int[] manufacturerDataKeys, Object[] manufacturerDataValues);
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java index c8bf2f82..e46dd20 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java
@@ -310,6 +310,10 @@ public int getScanRecord_getTxPowerLevel() { return mScanResult.getScanRecord().getTxPowerLevel(); } + + public String getScanRecord_getDeviceName() { + return mScanResult.getScanRecord().getDeviceName(); + } } /**
diff --git a/device/bluetooth/bluetooth_adapter.cc b/device/bluetooth/bluetooth_adapter.cc index efac70e..d445aadb 100644 --- a/device/bluetooth/bluetooth_adapter.cc +++ b/device/bluetooth/bluetooth_adapter.cc
@@ -5,6 +5,7 @@ #include "device/bluetooth/bluetooth_adapter.h" #include <memory> +#include <string> #include <utility> #include "base/bind.h"
diff --git a/device/bluetooth/bluetooth_adapter_android.cc b/device/bluetooth/bluetooth_adapter_android.cc index 1b6b29cd..5b95e2d 100644 --- a/device/bluetooth/bluetooth_adapter_android.cc +++ b/device/bluetooth/bluetooth_adapter_android.cc
@@ -5,6 +5,7 @@ #include "device/bluetooth/bluetooth_adapter_android.h" #include <memory> +#include <string> #include "base/android/jni_android.h" #include "base/android/jni_array.h" @@ -167,6 +168,7 @@ const JavaParamRef<jstring>& address, const JavaParamRef<jobject>& bluetooth_device_wrapper, // Java Type: bluetoothDeviceWrapper + const JavaParamRef<jstring>& local_name, int32_t rssi, const JavaParamRef<jobjectArray>& advertised_uuids, // Java Type: String[] int32_t tx_power, @@ -175,7 +177,7 @@ const JavaParamRef<jintArray>& manufacturer_data_keys, // Java Type: int[] const JavaParamRef<jobjectArray>& manufacturer_data_values // Java Type: byte[] - ) { +) { std::string device_address = ConvertJavaStringToUTF8(env, address); auto iter = devices_.find(device_address); @@ -235,13 +237,30 @@ device_android->UpdateAdvertisementData( BluetoothDevice::ClampPower(rssi), base::nullopt /* flags */, - std::move(advertised_bluetooth_uuids), + advertised_bluetooth_uuids, // Android uses INT32_MIN to indicate no Advertised Tx Power. // https://developer.android.com/reference/android/bluetooth/le/ScanRecord.html#getTxPowerLevel() tx_power == INT32_MIN ? base::nullopt : base::make_optional(clamped_tx_power), service_data_map, manufacturer_data_map); + for (auto& observer : observers_) { + base::Optional<std::string> device_name_opt = device_android->GetName(); + base::Optional<std::string> advertisement_name_opt; + if (local_name) + advertisement_name_opt = ConvertJavaStringToUTF8(env, local_name); + + observer.DeviceAdvertisementReceived( + device_android->GetAddress(), device_name_opt, advertisement_name_opt, + BluetoothDevice::ClampPower(rssi), + // Android uses INT32_MIN to indicate no Advertised Tx Power. + // https://developer.android.com/reference/android/bluetooth/le/ScanRecord.html#getTxPowerLevel() + tx_power == INT32_MIN ? base::nullopt + : base::make_optional(clamped_tx_power), + base::nullopt, /* TODO(crbug.com/588083) Implement appearance */ + advertised_bluetooth_uuids, service_data_map, manufacturer_data_map); + } + if (is_new_device) { devices_[device_address] = std::move(device_android_owner); for (auto& observer : observers_)
diff --git a/device/bluetooth/bluetooth_adapter_android.h b/device/bluetooth/bluetooth_adapter_android.h index 113f9c9..90ba958 100644 --- a/device/bluetooth/bluetooth_adapter_android.h +++ b/device/bluetooth/bluetooth_adapter_android.h
@@ -92,6 +92,7 @@ const base::android::JavaParamRef<jstring>& address, const base::android::JavaParamRef<jobject>& bluetooth_device_wrapper, // Java Type: bluetoothDeviceWrapper + const base::android::JavaParamRef<jstring>& local_name, int32_t rssi, const base::android::JavaParamRef<jobjectArray>& advertised_uuids, // Java Type: String[] @@ -104,7 +105,7 @@ manufacturer_data_keys, // Java Type: int[] const base::android::JavaParamRef<jobjectArray>& manufacturer_data_values // Java Type: byte[] - ); + ); protected: BluetoothAdapterAndroid();
diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc index 25c7256..9eaeeb7 100644 --- a/device/bluetooth/bluetooth_adapter_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -1794,12 +1794,12 @@ #endif // defined(OS_MACOSX) #if defined(OS_WIN) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( /* no prefix */, BluetoothTestWinrt, ::testing::Bool()); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( /* no prefix */, BluetoothTestWinrtOnly, ::testing::Values(true));
diff --git a/device/bluetooth/bluetooth_device_unittest.cc b/device/bluetooth/bluetooth_device_unittest.cc index 5a21ab62..83a0e79 100644 --- a/device/bluetooth/bluetooth_device_unittest.cc +++ b/device/bluetooth/bluetooth_device_unittest.cc
@@ -588,7 +588,7 @@ EXPECT_EQ(ToInt8(TestTxPower::LOWEST), device->GetInquiryTxPower().value()); } -#if defined(OS_MACOSX) +#if defined(OS_ANDROID) || defined(OS_MACOSX) // TODO(dougt) As I turn on new platforms for WebBluetooth Scanning, // I will relax this #ifdef TEST_F(BluetoothTest, DeviceAdvertisementReceived) {
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc index 967f2dc..96fbe64 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc
@@ -3743,17 +3743,17 @@ #endif // defined(OS_MACOSX) #if defined(OS_WIN) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( /* no prefix */, BluetoothRemoteGattCharacteristicTestWinrt, ::testing::Bool()); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( /* no prefix */, BluetoothRemoteGattCharacteristicTestWin32Only, ::testing::Values(false)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( /* no prefix */, BluetoothRemoteGattCharacteristicTestWinrtOnly, ::testing::Values(true));
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc b/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc index f1a79bf..9052dc7 100644 --- a/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc
@@ -996,7 +996,7 @@ #endif // defined(OS_MACOSX) #if defined(OS_WIN) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( /* no prefix */, BluetoothRemoteGattDescriptorTestWinrtOnly, ::testing::Values(true));
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc b/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc index 9969ed5..591c1d5a 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc +++ b/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc
@@ -597,7 +597,7 @@ #endif // defined(OS_MACOSX) #if defined(OS_WIN) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( /* no prefix */, BluetoothRemoteGattServiceTestWinrt, ::testing::Bool());
diff --git a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java index 856f947..5ded1ca 100644 --- a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java +++ b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java
@@ -152,8 +152,8 @@ mFakeScanner.mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, new FakeScanResult(new FakeBluetoothDevice(this, "01:00:00:90:1E:BE", "FakeBluetoothDevice"), - TestRSSI.LOWEST, uuids, TestTxPower.LOWEST, serviceData, - manufacturerData)); + "FakeBluetoothDevice", TestRSSI.LOWEST, uuids, + TestTxPower.LOWEST, serviceData, manufacturerData)); break; } case 2: { @@ -173,8 +173,8 @@ mFakeScanner.mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, new FakeScanResult(new FakeBluetoothDevice(this, "01:00:00:90:1E:BE", "FakeBluetoothDevice"), - TestRSSI.LOWER, uuids, TestTxPower.LOWER, serviceData, - manufacturerData)); + "Local Device Name", TestRSSI.LOWER, uuids, TestTxPower.LOWER, + serviceData, manufacturerData)); break; } case 3: { @@ -182,7 +182,8 @@ mFakeScanner.mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, new FakeScanResult( new FakeBluetoothDevice(this, "01:00:00:90:1E:BE", ""), - TestRSSI.LOW, uuids, NO_TX_POWER, null, null)); + "Local Device Name", TestRSSI.LOW, uuids, NO_TX_POWER, null, + null)); break; } @@ -191,7 +192,8 @@ mFakeScanner.mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, new FakeScanResult( new FakeBluetoothDevice(this, "02:00:00:8B:74:63", ""), - TestRSSI.MEDIUM, uuids, NO_TX_POWER, null, null)); + "Local Device Name", TestRSSI.MEDIUM, uuids, NO_TX_POWER, null, + null)); break; } @@ -200,7 +202,8 @@ mFakeScanner.mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, new FakeScanResult( new FakeBluetoothDevice(this, "01:00:00:90:1E:BE", null), - TestRSSI.HIGH, uuids, NO_TX_POWER, null, null)); + "Local Device Name", TestRSSI.HIGH, uuids, NO_TX_POWER, null, + null)); break; } case 6: { @@ -208,7 +211,8 @@ mFakeScanner.mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, new FakeScanResult( new FakeBluetoothDevice(this, "02:00:00:8B:74:63", null), - TestRSSI.LOWEST, uuids, NO_TX_POWER, null, null)); + "Local Device Name", TestRSSI.LOWEST, uuids, NO_TX_POWER, null, + null)); break; } case 7: { @@ -222,7 +226,8 @@ mFakeScanner.mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, new FakeScanResult(new FakeBluetoothDevice( this, "01:00:00:90:1E:BE", "U2F FakeDevice"), - TestRSSI.LOWEST, uuids, NO_TX_POWER, serviceData, null)); + "Local Device Name", TestRSSI.LOWEST, uuids, NO_TX_POWER, + serviceData, null)); break; } } @@ -362,17 +367,19 @@ */ static class FakeScanResult extends Wrappers.ScanResultWrapper { private final FakeBluetoothDevice mDevice; + private final String mLocalName; private final int mRssi; private final int mTxPower; private final ArrayList<ParcelUuid> mUuids; private final Map<ParcelUuid, byte[]> mServiceData; private final SparseArray<byte[]> mManufacturerData; - FakeScanResult(FakeBluetoothDevice device, int rssi, ArrayList<ParcelUuid> uuids, - int txPower, Map<ParcelUuid, byte[]> serviceData, + FakeScanResult(FakeBluetoothDevice device, String localName, int rssi, + ArrayList<ParcelUuid> uuids, int txPower, Map<ParcelUuid, byte[]> serviceData, SparseArray<byte[]> manufacturerData) { super(null); mDevice = device; + mLocalName = localName; mRssi = rssi; mUuids = uuids; mTxPower = txPower; @@ -409,6 +416,11 @@ public SparseArray<byte[]> getScanRecord_getManufacturerSpecificData() { return mManufacturerData; } + + @Override + public String getScanRecord_getDeviceName() { + return mLocalName; + } } /**
diff --git a/gpu/command_buffer/common/gpu_memory_buffer_support.cc b/gpu/command_buffer/common/gpu_memory_buffer_support.cc index e6bb4c7..48808be1 100644 --- a/gpu/command_buffer/common/gpu_memory_buffer_support.cc +++ b/gpu/command_buffer/common/gpu_memory_buffer_support.cc
@@ -106,4 +106,18 @@ return found ? gpu::GetPlatformSpecificTextureTarget() : GL_TEXTURE_2D; } +GPU_EXPORT bool NativeBufferNeedsPlatformSpecificTextureTarget( + gfx::BufferFormat format) { +#if defined(USE_OZONE) + // Always use GL_TEXTURE_2D as the target for RGB textures. + // https://crbug.com/916728 + if (format == gfx::BufferFormat::RGBA_8888 || + format == gfx::BufferFormat::RGBX_8888 || + format == gfx::BufferFormat::BGRX_8888) { + return false; + } +#endif + return true; +} + } // namespace gpu
diff --git a/gpu/command_buffer/common/gpu_memory_buffer_support.h b/gpu/command_buffer/common/gpu_memory_buffer_support.h index 3cd069b..c14b9e07 100644 --- a/gpu/command_buffer/common/gpu_memory_buffer_support.h +++ b/gpu/command_buffer/common/gpu_memory_buffer_support.h
@@ -63,6 +63,11 @@ gfx::BufferFormat format, const Capabilities& capabilities); +// Returns whether a native GMB with the given format needs to be bound to the +// platform-specfic texture target or GL_TEXTURE_2D. +GPU_EXPORT bool NativeBufferNeedsPlatformSpecificTextureTarget( + gfx::BufferFormat format); + } // namespace gpu #endif // GPU_COMMAND_BUFFER_COMMON_GPU_MEMORY_BUFFER_SUPPORT_H_
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc index b60c7fbc..56090006 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
@@ -792,15 +792,26 @@ return nullptr; } - GLenum target = handle.type == gfx::SHARED_MEMORY_BUFFER - ? GL_TEXTURE_2D - : gpu::GetPlatformSpecificTextureTarget(); + GLenum target = + (handle.type == gfx::SHARED_MEMORY_BUFFER || + !NativeBufferNeedsPlatformSpecificTextureTarget(buffer_format)) + ? GL_TEXTURE_2D + : gpu::GetPlatformSpecificTextureTarget(); scoped_refptr<gl::GLImage> image = MakeGLImage( client_id, std::move(handle), buffer_format, surface_handle, size); if (!image) { LOG(ERROR) << "Failed to create image."; return nullptr; } + // If we decide to use GL_TEXTURE_2D at the target for a native buffer, we + // would like to verify that it will actually work. If the image expects to be + // copied, there is no way to do this verification here, because copying is + // done lazily after the SharedImage is created, so require that the image is + // bindable. Currently NativeBufferNeedsPlatformSpecificTextureTarget can + // only return false on Chrome OS where GLImageNativePixmap is used which is + // always bindable. + DCHECK(handle.type == gfx::SHARED_MEMORY_BUFFER || target != GL_TEXTURE_2D || + image->ShouldBindOrCopy() == gl::GLImage::BIND); if (color_space.IsValid()) image->SetColorSpace(color_space);
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface_unittest.cc b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface_unittest.cc index 44a53ae..2855e9f5 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface_unittest.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface_unittest.cc
@@ -8,9 +8,9 @@ namespace gpu { namespace { -INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferImplIOSurface, - GpuMemoryBufferImplTest, - GpuMemoryBufferImplIOSurface); +INSTANTIATE_TYPED_TEST_SUITE_P(GpuMemoryBufferImplIOSurface, + GpuMemoryBufferImplTest, + GpuMemoryBufferImplIOSurface); } // namespace } // namespace gpu
diff --git a/gpu/ipc/host/gpu_memory_buffer_support.cc b/gpu/ipc/host/gpu_memory_buffer_support.cc index d35beb1..af8eb2a 100644 --- a/gpu/ipc/host/gpu_memory_buffer_support.cc +++ b/gpu/ipc/host/gpu_memory_buffer_support.cc
@@ -88,6 +88,8 @@ bool GetImageNeedsPlatformSpecificTextureTarget(gfx::BufferFormat format, gfx::BufferUsage usage) { + if (!NativeBufferNeedsPlatformSpecificTextureTarget(format)) + return false; #if defined(USE_OZONE) || defined(OS_MACOSX) || defined(OS_WIN) || \ defined(OS_ANDROID) GpuMemoryBufferSupport support;
diff --git a/headless/test/data/protocol/emulation/virtual-time-dialog-while-loading-expected.txt b/headless/test/data/protocol/emulation/virtual-time-dialog-while-loading-expected.txt new file mode 100644 index 0000000..6ed18a3 --- /dev/null +++ b/headless/test/data/protocol/emulation/virtual-time-dialog-while-loading-expected.txt
@@ -0,0 +1 @@ +Tests that virtual time pausing during loading of main resource works correctly when dialog is shown while page loads.
diff --git a/headless/test/data/protocol/emulation/virtual-time-dialog-while-loading.js b/headless/test/data/protocol/emulation/virtual-time-dialog-while-loading.js new file mode 100644 index 0000000..1b8d1fd --- /dev/null +++ b/headless/test/data/protocol/emulation/virtual-time-dialog-while-loading.js
@@ -0,0 +1,37 @@ +// 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. + +const server = new Map([ + ['http://test.com/index.html', + '<html><body><script>alert("No pasarán!");</script></body></html>']]); + +(async function(testRunner) { + var {page, session, dp} = await testRunner.startBlank( + 'Tests that virtual time pausing during loading of main resource ' + + 'works correctly when dialog is shown while page loads.'); + await dp.Network.enable(); + await dp.Network.setRequestInterception({ patterns: [{ urlPattern: '*' }] }); + dp.Network.onRequestIntercepted(event => { + let body = server.get(event.params.request.url); + dp.Network.continueInterceptedRequest({ + interceptionId: event.params.interceptionId, + rawResponse: btoa(body) + }); + }); + + dp.Page.onJavascriptDialogOpening(event => { + dp.Page.handleJavaScritpDialog({accept: true}); + }); + + dp.Emulation.onVirtualTimeBudgetExpired(async data => { + testRunner.log(await session.evaluate('document.title')); + testRunner.completeTest(); + }); + + await dp.Emulation.setVirtualTimePolicy({policy: 'pause'}); + await dp.Emulation.setVirtualTimePolicy({ + policy: 'pauseIfNetworkFetchesPending', budget: 5000, + waitForNavigation: true}); + await dp.Page.navigate({url: 'http://test.com/index.html'}); +})
diff --git a/headless/test/headless_protocol_browsertest.cc b/headless/test/headless_protocol_browsertest.cc index 5507899..1bd21fa 100644 --- a/headless/test/headless_protocol_browsertest.cc +++ b/headless/test/headless_protocol_browsertest.cc
@@ -231,6 +231,8 @@ "emulation/virtual-time-error-loop.js"); HEADLESS_PROTOCOL_TEST(VirtualTimeFetchStream, "emulation/virtual-time-fetch-stream.js"); +HEADLESS_PROTOCOL_TEST(VirtualTimeDialogWhileLoading, + "emulation/virtual-time-dialog-while-loading.js"); // Flaky Test crbug.com/859382 HEADLESS_PROTOCOL_TEST(DISABLED_VirtualTimeHistoryNavigation,
diff --git a/ios/chrome/browser/infobars/BUILD.gn b/ios/chrome/browser/infobars/BUILD.gn index 1329252d..8cffdfb 100644 --- a/ios/chrome/browser/infobars/BUILD.gn +++ b/ios/chrome/browser/infobars/BUILD.gn
@@ -26,7 +26,7 @@ "//components/translate/core/browser", "//ios/chrome/browser", "//ios/chrome/browser/ui/infobars:infobars_ui", - "//ios/chrome/browser/ui/infobars/confirm_infobar", + "//ios/chrome/browser/ui/infobars/banners", "//ios/web", "//ui/base", "//ui/gfx",
diff --git a/ios/chrome/browser/infobars/infobar_utils.mm b/ios/chrome/browser/infobars/infobar_utils.mm index 5ac2013..de274e6 100644 --- a/ios/chrome/browser/infobars/infobar_utils.mm +++ b/ios/chrome/browser/infobars/infobar_utils.mm
@@ -11,7 +11,7 @@ #include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/infobars/confirm_infobar_controller.h" #include "ios/chrome/browser/infobars/infobar.h" -#import "ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h" +#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -20,8 +20,8 @@ std::unique_ptr<infobars::InfoBar> CreateConfirmInfoBar( std::unique_ptr<ConfirmInfoBarDelegate> delegate) { if (experimental_flags::IsInfobarUIRebootEnabled()) { - ConfirmInfobarViewController* controller = - [[ConfirmInfobarViewController alloc] + InfobarBannerViewController* controller = + [[InfobarBannerViewController alloc] initWithInfoBarDelegate:delegate.get()]; return std::make_unique<InfoBarIOS>(controller, std::move(delegate)); } else {
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 39b32d5..213b8db 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -2845,8 +2845,12 @@ id nativeController = [self nativeControllerForTab:[self.tabModel currentTab]]; if ([nativeController conformsToProtocol:@protocol(NewTabPageOwning)] && - [nativeController respondsToSelector:@selector(scrollOffset)]) { - return [nativeController scrollOffset].y == 0; + [nativeController respondsToSelector:@selector(contentOffset)]) { + CGFloat scrolledToTopOffset = + [nativeController respondsToSelector:@selector(contentInset)] + ? [nativeController contentInset].top + : 0.0; + return [nativeController contentOffset].y == scrolledToTopOffset; } CRWWebViewScrollViewProxy* scrollProxy =
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index cbe6bf4..37be9d31 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -281,7 +281,11 @@ [self.NTPMediator dismissModals]; } -- (CGPoint)scrollOffset { +- (UIEdgeInsets)contentInset { + return self.suggestionsViewController.collectionView.contentInset; +} + +- (CGPoint)contentOffset { CGPoint collectionOffset = self.suggestionsViewController.collectionView.contentOffset; collectionOffset.y -=
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm index 37ab0e7..a04fd368 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm
@@ -573,12 +573,14 @@ web::NavigationManager* manager = webState->GetNavigationManager(); web::NavigationItem* item = manager->GetLastCommittedItem(); web::PageDisplayState displayState; - CGPoint scrollOffset = + UIEdgeInsets contentInset = + self.suggestionsViewController.collectionView.contentInset; + CGPoint contentOffset = self.suggestionsViewController.collectionView.contentOffset; - scrollOffset.y -= + contentOffset.y -= self.headerCollectionInteractionHandler.collectionShiftingOffset; - displayState.scroll_state().set_offset_x(scrollOffset.x); - displayState.scroll_state().set_offset_y(scrollOffset.y); + displayState.scroll_state() = + web::PageScrollState(contentOffset, contentInset); item->SetPageDisplayState(displayState); } @@ -589,10 +591,10 @@ } web::NavigationManager* navigationManager = webState->GetNavigationManager(); web::NavigationItem* item = navigationManager->GetVisibleItem(); - if (item && item->GetPageDisplayState().scroll_state().offset_y() > 0) { - CGFloat offset = item->GetPageDisplayState().scroll_state().offset_y(); + CGFloat offset = + item ? item->GetPageDisplayState().scroll_state().content_offset().y : 0; + if (offset > 0) [self.suggestionsViewController setContentOffset:offset]; - } } @end
diff --git a/ios/chrome/browser/ui/dialogs/BUILD.gn b/ios/chrome/browser/ui/dialogs/BUILD.gn index f992244..4f054c6 100644 --- a/ios/chrome/browser/ui/dialogs/BUILD.gn +++ b/ios/chrome/browser/ui/dialogs/BUILD.gn
@@ -110,6 +110,7 @@ "//base", "//base/test:test_support", "//components/strings", + "//components/url_formatter", "//ios/chrome/app/strings", "//ios/chrome/browser/ui", "//ios/chrome/test/app:test_support",
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter.mm b/ios/chrome/browser/ui/dialogs/dialog_presenter.mm index 4b3d5bc..a60d95b5 100644 --- a/ios/chrome/browser/ui/dialogs/dialog_presenter.mm +++ b/ios/chrome/browser/ui/dialogs/dialog_presenter.mm
@@ -9,8 +9,8 @@ #include "base/containers/circular_deque.h" #import "base/ios/block_types.h" #include "base/logging.h" -#include "base/strings/sys_string_conversions.h" #include "components/strings/grit/components_strings.h" +#include "components/url_formatter/elide_url.h" #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" #import "ios/chrome/browser/ui/alert_coordinator/input_alert_coordinator.h" @@ -376,19 +376,14 @@ + (NSString*)localizedTitleForJavaScriptAlertFromPage:(const GURL&)pageURL mainFrameURL: (const GURL&)mainFrameURL { - NSString* localizedTitle = nil; - NSString* hostname = base::SysUTF8ToNSString(pageURL.host()); - bool sameOriginAsMainFrame = pageURL.GetOrigin() == mainFrameURL.GetOrigin(); - if (!sameOriginAsMainFrame) { - localizedTitle = l10n_util::GetNSString( + return l10n_util::GetNSString( IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL_IFRAME); - } else { - localizedTitle = l10n_util::GetNSStringF( - IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base::SysNSStringToUTF16(hostname)); } - return localizedTitle; + base::string16 title = url_formatter::FormatUrlForSecurityDisplay( + pageURL, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS); + return l10n_util::GetNSStringF(IDS_JAVASCRIPT_MESSAGEBOX_TITLE, title); } #pragma mark - Private methods.
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm b/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm index 5fda247..51906f8 100644 --- a/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm +++ b/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/dialogs/dialog_presenter.h" #include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" @@ -138,6 +139,23 @@ EXPECT_NSEQ(expected_title, different_origin_title); } +// Tests that JavaScript dialogs have correct title when they are presented from +// about:blank page. +TEST_F(DialogPresenterTest, AboutBlankTest) { + DialogPresenterTestWebState web_state; + web_state.SetCurrentURL(GURL(url::kAboutBlankURL)); + [presenter() runJavaScriptAlertPanelWithMessage:@"" + requestURL:GURL(url::kAboutBlankURL) + webState:&web_state + completionHandler:nil]; + + NSString* expected_title = l10n_util::GetNSStringF( + IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base::UTF8ToUTF16(url::kAboutBlankURL)); + NSString* actual_title = + [presenter() presentedDialogCoordinator].alertController.title; + EXPECT_NSEQ(expected_title, actual_title); +} + // Tests that multiple JavaScript dialogs are queued TEST_F(DialogPresenterTest, QueueTest) { // Tests that the dialog for |webState1| has been shown.
diff --git a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm index c1717724..6b52a38c 100644 --- a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm +++ b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
@@ -12,6 +12,7 @@ #include "base/strings/utf_string_conversions.h" #import "base/test/ios/wait_util.h" #include "components/strings/grit/components_strings.h" +#include "components/url_formatter/elide_url.h" #import "ios/chrome/browser/ui/dialogs/dialog_presenter.h" #include "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/grit/ios_strings.h" @@ -233,10 +234,10 @@ // Waits for a JavaScript dialog to be shown from the page at |url|. void WaitForJavaScriptDialogToBeShown(const GURL& url) { - NSString* hostname = base::SysUTF8ToNSString(url.host()); - NSString* expectedTitle = l10n_util::GetNSStringF( - IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base::SysNSStringToUTF16(hostname)); - + base::string16 URLString = url_formatter::FormatUrlForSecurityDisplay( + url, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS); + NSString* expectedTitle = + l10n_util::GetNSStringF(IDS_JAVASCRIPT_MESSAGEBOX_TITLE, URLString); WaitForAlertToBeShown(expectedTitle); } @@ -259,9 +260,10 @@ void AssertJavaScriptAlertNotPresent(const GURL& url) { ConditionBlock condition = ^{ NSError* error = nil; - NSString* hostname = base::SysUTF8ToNSString(url.host()); - NSString* expectedTitle = l10n_util::GetNSStringF( - IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base::SysNSStringToUTF16(hostname)); + base::string16 URLString = url_formatter::FormatUrlForSecurityDisplay( + url, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS); + NSString* expectedTitle = + l10n_util::GetNSStringF(IDS_JAVASCRIPT_MESSAGEBOX_TITLE, URLString); id<GREYMatcher> titleLabel = chrome_test_util::StaticTextWithAccessibilityLabel(expectedTitle); @@ -608,11 +610,7 @@ } // Wait for the alert to be shown. - NSString* hostname = base::SysUTF8ToNSString(self.onLoadPageURL.host()); - NSString* expectedTitle = l10n_util::GetNSStringF( - IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base::SysNSStringToUTF16(hostname)); - - WaitForAlertToBeShown(expectedTitle); + WaitForJavaScriptDialogToBeShown(self.onLoadPageURL); // Verify that the omnibox shows the correct URL when the dialog is visible. std::string title =
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn index 2de84bac..a157317 100644 --- a/ios/chrome/browser/ui/infobars/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -20,6 +20,7 @@ "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + "//ios/chrome/browser/ui/infobars/presentation", "//ios/chrome/browser/ui/settings/sync_utils", "//ios/chrome/browser/ui/signin_interaction/public", "//ios/chrome/browser/ui/translate",
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar/BUILD.gn b/ios/chrome/browser/ui/infobars/banners/BUILD.gn similarity index 62% rename from ios/chrome/browser/ui/infobars/confirm_infobar/BUILD.gn rename to ios/chrome/browser/ui/infobars/banners/BUILD.gn index b349587..6f9f657 100644 --- a/ios/chrome/browser/ui/infobars/confirm_infobar/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/banners/BUILD.gn
@@ -1,12 +1,12 @@ -# Copyright 2018 The Chromium Authors. All rights reserved. +# Copyright 2019 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("confirm_infobar") { +source_set("banners") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "confirm_infobar_view_controller.h", - "confirm_infobar_view_controller.mm", + "infobar_banner_view_controller.h", + "infobar_banner_view_controller.mm", ] deps = [ "//base",
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h similarity index 67% rename from ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h rename to ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h index 001d5bc5..05f40005 100644 --- a/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h +++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_CONFIRM_INFOBAR_CONFIRM_INFOBAR_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_INFOBARS_CONFIRM_INFOBAR_CONFIRM_INFOBAR_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_INFOBAR_BANNER_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_INFOBAR_BANNER_VIEW_CONTROLLER_H_ #import <UIKit/UIKit.h> @@ -13,7 +13,7 @@ // TODO(crbug.com/911864): PLACEHOLDER Work in Progress class for the new // InfobarUI. -@interface ConfirmInfobarViewController : UIViewController <InfobarUIDelegate> +@interface InfobarBannerViewController : UIViewController <InfobarUIDelegate> - (instancetype)initWithInfoBarDelegate:(ConfirmInfoBarDelegate*)infoBarDelegate NS_DESIGNATED_INITIALIZER; @@ -25,4 +25,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_INFOBARS_CONFIRM_INFOBAR_CONFIRM_INFOBAR_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_INFOBAR_BANNER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm new file mode 100644 index 0000000..15a0a90b --- /dev/null +++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
@@ -0,0 +1,123 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h" + +#include "base/strings/sys_string_conversions.h" +#include "components/infobars/core/confirm_infobar_delegate.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface InfobarBannerViewController () + +@property(nonatomic, readonly) ConfirmInfoBarDelegate* infoBarDelegate; +@property(nonatomic, assign) CGPoint originalCenter; + +@end + +// TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new +// InfobarUI. +@implementation InfobarBannerViewController +@synthesize delegate = _delegate; + +- (instancetype)initWithInfoBarDelegate: + (ConfirmInfoBarDelegate*)infoBarDelegate { + self = [super initWithNibName:nil bundle:nil]; + if (self) { + _infoBarDelegate = infoBarDelegate; + } + return self; +} + +#pragma mark - View Lifecycle + +- (void)viewDidLoad { + [super viewDidLoad]; + + NSString* messageText = + base::SysUTF16ToNSString(self.infoBarDelegate->GetMessageText()); + UILabel* messageLabel = [[UILabel alloc] init]; + messageLabel.text = messageText; + messageLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + messageLabel.adjustsFontForContentSizeCategory = YES; + messageLabel.textColor = [UIColor blackColor]; + messageLabel.translatesAutoresizingMaskIntoConstraints = NO; + messageLabel.numberOfLines = 0; + + NSString* buttonText = base::SysUTF16ToNSString( + self.infoBarDelegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK)); + UIButton* infobarButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [infobarButton setTitle:buttonText forState:UIControlStateNormal]; + [infobarButton addTarget:self + action:@selector(buttonTapped:) + forControlEvents:UIControlEventTouchUpInside]; + infobarButton.translatesAutoresizingMaskIntoConstraints = NO; + + UIPanGestureRecognizer* panGestureRecognizer = + [[UIPanGestureRecognizer alloc] init]; + [panGestureRecognizer addTarget:self action:@selector(handlePanGesture:)]; + [panGestureRecognizer setMaximumNumberOfTouches:1]; + [self.view addGestureRecognizer:panGestureRecognizer]; + + [self.view addSubview:messageLabel]; + [self.view addSubview:infobarButton]; + self.view.backgroundColor = [UIColor lightGrayColor]; + + [NSLayoutConstraint activateConstraints:@[ + [messageLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor + constant:30], + [messageLabel.trailingAnchor + constraintEqualToAnchor:infobarButton.leadingAnchor], + [messageLabel.centerYAnchor + constraintEqualToAnchor:self.view.centerYAnchor], + [infobarButton.centerYAnchor + constraintEqualToAnchor:self.view.centerYAnchor], + [infobarButton.trailingAnchor + constraintEqualToAnchor:self.view.trailingAnchor], + [infobarButton.widthAnchor constraintEqualToConstant:100] + ]]; +} + +#pragma mark - InfobarUIDelegate + +- (void)removeView { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)detachView { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - Private Methods + +- (void)buttonTapped:(id)sender { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture { + CGPoint translation = [gesture translationInView:self.view]; + + if (gesture.state == UIGestureRecognizerStateBegan) { + self.originalCenter = self.view.center; + + } else if (gesture.state == UIGestureRecognizerStateChanged) { + self.view.center = + CGPointMake(self.view.center.x, self.view.center.y + translation.y); + } + + if (gesture.state == UIGestureRecognizerStateEnded || + gesture.state == UIGestureRecognizerStateCancelled) { + if (self.view.center.y > self.originalCenter.y) { + self.view.center = self.originalCenter; + } else { + [self dismissViewControllerAnimated:YES completion:nil]; + } + } + + [gesture setTranslation:CGPointZero inView:self.view]; +} + +@end
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.mm b/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.mm deleted file mode 100644 index c935b75c..0000000 --- a/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.mm +++ /dev/null
@@ -1,70 +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. - -#import "ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h" - -#include "base/strings/sys_string_conversions.h" -#include "components/infobars/core/confirm_infobar_delegate.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface ConfirmInfobarViewController () - -@property(nonatomic, readonly) ConfirmInfoBarDelegate* infoBarDelegate; - -@end - -// TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new -// InfobarUI. -@implementation ConfirmInfobarViewController -@synthesize delegate = _delegate; - -- (instancetype)initWithInfoBarDelegate: - (ConfirmInfoBarDelegate*)infoBarDelegate { - self = [super initWithNibName:nil bundle:nil]; - if (self) { - _infoBarDelegate = infoBarDelegate; - } - return self; -} - -#pragma mark - View Lifecycle - -- (void)viewDidLoad { - [super viewDidLoad]; - base::string16 messageText = self.infoBarDelegate->GetMessageText(); - NSString* message = base::SysUTF16ToNSString(messageText); - - UILabel* messageLabel = [[UILabel alloc] init]; - messageLabel.text = message; - messageLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleTitle1]; - messageLabel.adjustsFontForContentSizeCategory = YES; - messageLabel.textColor = [UIColor blackColor]; - messageLabel.translatesAutoresizingMaskIntoConstraints = NO; - - [self.view addSubview:messageLabel]; - self.view.backgroundColor = [UIColor grayColor]; - - [NSLayoutConstraint activateConstraints:@[ - [messageLabel.leadingAnchor - constraintEqualToAnchor:self.view.leadingAnchor], - [messageLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor], - [messageLabel.heightAnchor constraintEqualToConstant:30], - [messageLabel.widthAnchor constraintEqualToConstant:200], - ]]; -} - -#pragma mark - InfobarUIDelegate - -- (void)removeView { - // TO-DO -} - -- (void)detachView { - // TO-DO -} - -@end
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm index 799b86c..9d4c2e5e 100644 --- a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
@@ -13,6 +13,8 @@ #include "ios/chrome/browser/ui/infobars/infobar_container_view_controller.h" #import "ios/chrome/browser/ui/infobars/infobar_positioner.h" #include "ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.h" +#import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h" +#import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h" #import "ios/chrome/browser/ui/signin_interaction/public/signin_presenter.h" #include "ios/chrome/browser/upgrade/upgrade_center.h" @@ -20,7 +22,10 @@ #error "This file requires ARC support." #endif -@interface InfobarContainerCoordinator () <SigninPresenter> +@interface InfobarContainerCoordinator () < + InfobarContainerPresenter, + UIViewControllerTransitioningDelegate, + SigninPresenter> @property(nonatomic, assign) TabModel* tabModel; @@ -52,13 +57,10 @@ // Create and setup the ViewController. if (experimental_flags::IsInfobarUIRebootEnabled()) { - self.containerViewController = + InfobarContainerViewController* container = [[InfobarContainerViewController alloc] init]; - [self.baseViewController - addChildViewController:self.containerViewController]; - [self.baseViewController.view addSubview:self.containerViewController.view]; - [self.containerViewController - didMoveToParentViewController:self.baseViewController]; + container.presenter = self; + self.containerViewController = container; } else { LegacyInfobarContainerViewController* legacyContainer = [[LegacyInfobarContainerViewController alloc] init]; @@ -108,6 +110,51 @@ return NO; } +#pragma mark - InfobarContainerPresenter + +- (void)presentInfobarContainer { + // Should only be called in the new UI implementation. + DCHECK(experimental_flags::IsInfobarUIRebootEnabled()); + + self.containerViewController.transitioningDelegate = self; + [self.containerViewController + setModalPresentationStyle:UIModalPresentationCustom]; + [self.baseViewController presentViewController:self.containerViewController + animated:YES + completion:nil]; +} + +#pragma mark - UIViewControllerTransitioningDelegate + +- (UIPresentationController*) + presentationControllerForPresentedViewController: + (UIViewController*)presented + presentingViewController: + (UIViewController*)presenting + sourceViewController:(UIViewController*)source { + InfobarBannerPresentationController* presentationController = + [[InfobarBannerPresentationController alloc] + initWithPresentedViewController:presented + presentingViewController:presenting]; + return presentationController; +} + +- (id<UIViewControllerAnimatedTransitioning>) + animationControllerForPresentedController:(UIViewController*)presented + presentingController:(UIViewController*)presenting + sourceController:(UIViewController*)source { + InfobarBannerAnimator* animator = [[InfobarBannerAnimator alloc] init]; + animator.presenting = YES; + return animator; +} + +- (id<UIViewControllerAnimatedTransitioning>) + animationControllerForDismissedController:(UIViewController*)dismissed { + InfobarBannerAnimator* animator = [[InfobarBannerAnimator alloc] init]; + animator.presenting = NO; + return animator; +} + #pragma mark - SigninPresenter - (void)showSignin:(ShowSigninCommand*)command {
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h index e3a2bd774..ca38aff 100644 --- a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h +++ b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h
@@ -9,11 +9,24 @@ #import "ios/chrome/browser/ui/infobars/infobar_container_consumer.h" +// TODO(crbug.com/1372916): PLACEHOLDER Work in Progress protocol for the new +// InfobarUI. +// Manages the InfobarContainer presentation. +@protocol InfobarContainerPresenter + +// Presents the InfobarContainerViewController. +- (void)presentInfobarContainer; + +@end + // TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new // InfobarUI. ViewController that contains all Infobars. @interface InfobarContainerViewController : UIViewController <InfobarContainerConsumer> +// Delegate to present this ViewController. +@property(nonatomic, strong) id<InfobarContainerPresenter> presenter; + @end #endif // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm index efb5197..cf07408d 100644 --- a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm
@@ -6,7 +6,6 @@ #include "base/ios/block_types.h" #include "base/logging.h" -#import "ios/chrome/browser/ui/util/rtl_geometry.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -14,34 +13,48 @@ // TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new // InfobarUI. +@interface InfobarContainerViewController () + +@property(nonatomic, strong) NSMutableArray<UIViewController*>* currentInfobars; + +@end + @implementation InfobarContainerViewController +#pragma mark - UIViewController + - (void)viewDidLoad { - self.view = [[UIView alloc] initWithFrame:CGRectMake(20, 100, 360, 75)]; + self.view = [[UIView alloc] initWithFrame:CGRectZero]; } #pragma mark - InfobarConsumer - (void)addInfoBarWithDelegate:(id<InfobarUIDelegate>)infoBarDelegate position:(NSInteger)position { - UIViewController* infoBarViewController = + UIViewController* infobarViewController = static_cast<UIViewController*>(infoBarDelegate); - [self addChildViewController:infoBarViewController]; - [self.view addSubview:infoBarViewController.view]; - infoBarViewController.view.translatesAutoresizingMaskIntoConstraints = NO; - [infoBarViewController didMoveToParentViewController:self]; - + [self addChildViewController:infobarViewController]; + [self.view addSubview:infobarViewController.view]; + [infobarViewController didMoveToParentViewController:self]; + infobarViewController.view.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ - [infoBarViewController.view.leadingAnchor + [infobarViewController.view.topAnchor + constraintEqualToAnchor:self.view.topAnchor + constant:10], + [infobarViewController.view.bottomAnchor + constraintEqualToAnchor:self.view.bottomAnchor], + [infobarViewController.view.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], - [infoBarViewController.view.trailingAnchor - constraintEqualToAnchor:self.view.trailingAnchor], - [infoBarViewController.view.topAnchor - constraintEqualToAnchor:self.view.topAnchor], - [infoBarViewController.view.bottomAnchor - constraintEqualToAnchor:self.view.bottomAnchor] + [infobarViewController.view.trailingAnchor + constraintEqualToAnchor:self.view.trailingAnchor] ]]; + + if (![self.currentInfobars count]) { + [self.presenter presentInfobarContainer]; + } + + [self.currentInfobars addObject:infobarViewController]; } - (void)setUserInteractionEnabled:(BOOL)enabled { @@ -49,8 +62,17 @@ } - (void)updateLayoutAnimated:(BOOL)animated { - // NO-OP - This shouldn't be need in the new UI since we use autolayout for + // NO-OP - This shouldn't be needed in the new UI since we use autolayout for // the contained Infobars. } +#pragma mark - Private Methods + +- (NSMutableArray<UIViewController*>*)currentInfobars { + if (!_currentInfobars) { + _currentInfobars = [[NSMutableArray alloc] init]; + } + return _currentInfobars; +} + @end
diff --git a/ios/chrome/browser/ui/infobars/presentation/BUILD.gn b/ios/chrome/browser/ui/infobars/presentation/BUILD.gn new file mode 100644 index 0000000..963665c --- /dev/null +++ b/ios/chrome/browser/ui/infobars/presentation/BUILD.gn
@@ -0,0 +1,16 @@ +# 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. + +source_set("presentation") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "infobar_banner_animator.h", + "infobar_banner_animator.mm", + "infobar_banner_presentation_controller.h", + "infobar_banner_presentation_controller.mm", + ] + deps = [ + "//base", + ] +}
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h new file mode 100644 index 0000000..96fd220 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h
@@ -0,0 +1,21 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_ANIMATOR_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_ANIMATOR_H_ + +#import <UIKit/UIKit.h> + +// TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new +// InfobarUI. +@interface InfobarBannerAnimator + : NSObject <UIViewControllerAnimatedTransitioning> + +// YES if this animator is presenting a view controller, NO if it is dismissing +// one. +@property(nonatomic, assign) BOOL presenting; + +@end + +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.mm b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.mm new file mode 100644 index 0000000..df8df12 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.mm
@@ -0,0 +1,80 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation InfobarBannerAnimator + +- (NSTimeInterval)transitionDuration: + (id<UIViewControllerContextTransitioning>)transitionContext { + return 1; +} + +- (void)animateTransition: + (id<UIViewControllerContextTransitioning>)transitionContext { + // Set up the keys for the "base" view/VC and the "presented" view/VC. These + // will be used to fetch the associated objects later. + NSString* baseViewKey = self.presenting ? UITransitionContextFromViewKey + : UITransitionContextToViewKey; + NSString* presentedViewControllerKey = + self.presenting ? UITransitionContextToViewControllerKey + : UITransitionContextFromViewControllerKey; + NSString* presentedViewKey = self.presenting ? UITransitionContextToViewKey + : UITransitionContextFromViewKey; + + // Get views and view controllers for this transition. + UIView* baseView = [transitionContext viewForKey:baseViewKey]; + UIViewController* presentedViewController = + [transitionContext viewControllerForKey:presentedViewControllerKey]; + UIView* presentedView = [transitionContext viewForKey:presentedViewKey]; + + // Always add the destination view to the container. + UIView* containerView = [transitionContext containerView]; + if (self.presenting) { + [containerView addSubview:presentedView]; + } else { + [containerView addSubview:baseView]; + } + + // Set the initial frame and Compute the final frame for the presented view. + CGRect presentedViewFinalFrame = CGRectZero; + + if (self.presenting) { + presentedViewFinalFrame = + [transitionContext finalFrameForViewController:presentedViewController]; + CGRect presentedViewStartFrame = presentedViewFinalFrame; + presentedViewStartFrame.origin.y = -CGRectGetWidth(containerView.bounds); + presentedView.frame = presentedViewStartFrame; + } else { + presentedViewFinalFrame = presentedView.frame; + presentedViewFinalFrame.origin.y = -CGRectGetWidth(containerView.bounds); + } + + // Animate using the animator's own duration value. + [UIView animateWithDuration:[self transitionDuration:transitionContext] + delay:0 + usingSpringWithDamping:0.85 + initialSpringVelocity:0 + options:UIViewAnimationOptionTransitionNone + animations:^{ + presentedView.frame = presentedViewFinalFrame; + } + completion:^(BOOL finished) { + BOOL success = ![transitionContext transitionWasCancelled]; + + // If presentation failed, remove the view. + if (self.presenting && !success) { + [presentedView removeFromSuperview]; + } + + // Notify UIKit that the transition has finished + [transitionContext completeTransition:success]; + }]; +} + +@end
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h new file mode 100644 index 0000000..bbe80a8 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h
@@ -0,0 +1,16 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_PRESENTATION_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_PRESENTATION_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +// TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new +// InfobarUI. +@interface InfobarBannerPresentationController : UIPresentationController + +@end + +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_PRESENTATION_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm new file mode 100644 index 0000000..1bf914e --- /dev/null +++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm
@@ -0,0 +1,54 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// Presented frame size and position. +const CGFloat kContainerHeight = 75; +const CGFloat kContainerHorizontalPadding = 20; +const CGFloat kContainerTopPadding = 80; + +} + +@interface InfobarBannerPresentationController () + +// UIView that contains information about the position and size of the container +// and presented views. +@property(nonatomic, strong) UIView* viewForPresentedView; + +@end + +@implementation InfobarBannerPresentationController + +- (CGRect)frameOfPresentedViewInContainerView { + return self.viewForPresentedView.bounds; +} + +- (void)presentationTransitionWillBegin { + self.containerView.frame = self.viewForPresentedView.frame; +} + +- (void)containerViewWillLayoutSubviews { + self.presentedView.frame = [self frameOfPresentedViewInContainerView]; +} + +- (UIView*)viewForPresentedView { + if (!_viewForPresentedView) { + CGFloat safeAreaWidth = + CGRectGetWidth(self.containerView.safeAreaLayoutGuide.layoutFrame); + CGFloat maxAvailableWidth = safeAreaWidth - 2 * kContainerHorizontalPadding; + _viewForPresentedView = [[UIView alloc] + initWithFrame:CGRectMake(kContainerHorizontalPadding, + kContainerTopPadding, maxAvailableWidth, + kContainerHeight)]; + } + return _viewForPresentedView; +} + +@end
diff --git a/ios/chrome/browser/ui/ntp/incognito_view_controller.mm b/ios/chrome/browser/ui/ntp/incognito_view_controller.mm index 0b568df..705a60c 100644 --- a/ios/chrome/browser/ui/ntp/incognito_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/incognito_view_controller.mm
@@ -63,7 +63,11 @@ - (void)wasHidden { } -- (CGPoint)scrollOffset { +- (UIEdgeInsets)contentInset { + return UIEdgeInsetsZero; +} + +- (CGPoint)contentOffset { return CGPointZero; }
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_controller.mm index 23fe33c0..22429ba 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_controller.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_controller.mm
@@ -233,8 +233,8 @@ [_currentController willUpdateSnapshot]; } -- (CGPoint)scrollOffset { - return [_currentController scrollOffset]; +- (CGPoint)contentOffset { + return [_currentController contentOffset]; } #pragma mark - LogoAnimationControllerOwnerOwner
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm index 268f13d..7ca4021 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -102,19 +102,18 @@ return self.viewController.view; } -- (CGPoint)scrollOffset { - return [self.contentSuggestionsCoordinator scrollOffset]; +- (UIEdgeInsets)contentInset { + return [self.contentSuggestionsCoordinator contentInset]; +} + +- (CGPoint)contentOffset { + return [self.contentSuggestionsCoordinator contentOffset]; } - (void)willUpdateSnapshot { [self.contentSuggestionsCoordinator willUpdateSnapshot]; } -- (UIEdgeInsets)contentInset { - return self.contentSuggestionsCoordinator.viewController.collectionView - .contentInset; -} - - (void)setContentInset:(UIEdgeInsets)contentInset { // UIKit will adjust the contentOffset sometimes when changing the // contentInset.bottom. We don't want the NTP to scroll, so store and re-set
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_owning.h b/ios/chrome/browser/ui/ntp/new_tab_page_owning.h index 1d5d8fc..8838b7f 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_owning.h +++ b/ios/chrome/browser/ui/ntp/new_tab_page_owning.h
@@ -23,8 +23,9 @@ // Called when a snapshot of the content will be taken. - (void)willUpdateSnapshot; -// The scroll offset of this native view. -- (CGPoint)scrollOffset; +// The content inset and offset of the scroll view. +- (UIEdgeInsets)contentInset; +- (CGPoint)contentOffset; // The current NTP view. - (UIView*)view;
diff --git a/ios/web/navigation/crw_navigation_item_storage_unittest.mm b/ios/web/navigation/crw_navigation_item_storage_unittest.mm index 7660b243..76da767 100644 --- a/ios/web/navigation/crw_navigation_item_storage_unittest.mm +++ b/ios/web/navigation/crw_navigation_item_storage_unittest.mm
@@ -34,7 +34,8 @@ [item_storage_ setTimestamp:base::Time::Now()]; [item_storage_ setTitle:base::SysNSStringToUTF16(@"Title")]; [item_storage_ - setDisplayState:web::PageDisplayState(0.0, 0.0, 0.0, 0.0, 0.0)]; + setDisplayState:web::PageDisplayState(CGPointZero, UIEdgeInsetsZero, + 0.0, 0.0, 0.0)]; [item_storage_ setPOSTData:[@"Test data" dataUsingEncoding:NSUTF8StringEncoding]]; [item_storage_ setHTTPRequestHeaders:@{ @"HeaderKey" : @"HeaderValue" }];
diff --git a/ios/web/navigation/crw_session_storage_unittest.mm b/ios/web/navigation/crw_session_storage_unittest.mm index 3ade210..fa6d9e1 100644 --- a/ios/web/navigation/crw_session_storage_unittest.mm +++ b/ios/web/navigation/crw_session_storage_unittest.mm
@@ -75,7 +75,8 @@ [item_storage setTimestamp:base::Time::Now()]; [item_storage setTitle:base::SysNSStringToUTF16(@"Title")]; [item_storage - setDisplayState:web::PageDisplayState(0.0, 0.0, 0.0, 0.0, 0.0)]; + setDisplayState:web::PageDisplayState(CGPointZero, UIEdgeInsetsZero, + 0.0, 0.0, 0.0)]; [item_storage setPOSTData:[@"Test data" dataUsingEncoding:NSUTF8StringEncoding]]; [item_storage setHTTPRequestHeaders:@{ @"HeaderKey" : @"HeaderValue" }];
diff --git a/ios/web/public/web_state/page_display_state.h b/ios/web/public/web_state/page_display_state.h index 063b504..7c975c9c 100644 --- a/ios/web/public/web_state/page_display_state.h +++ b/ios/web/public/web_state/page_display_state.h
@@ -5,42 +5,49 @@ #ifndef IOS_WEB_PUBLIC_WEB_STATE_PAGE_DISPLAY_STATE_H_ #define IOS_WEB_PUBLIC_WEB_STATE_PAGE_DISPLAY_STATE_H_ -#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> namespace web { -// Class used to represent the scrolling offset of a webview. The offsets -// stored are offsets from the scrolled-to-top-left resting position. That -// means an |offset_y| value of 0 corresponds to a UIScrollView.contentOffset.y -// value of -UIScrollView.contentInset.top. -// TODO(crbug.com/925073): Update this class to store contentInset and -// contentOffset directly. +// Class used to represent the scrolling state of a webview. class PageScrollState { public: - // Default constructor. Initializes scroll offsets to NAN. + // Default constructor. Initializes scroll values to NAN. PageScrollState(); // Constructor with initial values. - PageScrollState(double offset_x, double offset_y); + PageScrollState(const CGPoint& content_offset, + const UIEdgeInsets& content_inset); ~PageScrollState(); - // The scroll offset is valid if its x and y values are both non-NAN. + // The scroll offset is valid if its content inset and offset contain only + // non-NAN values. bool IsValid() const; - // Accessors for scroll offsets. - double offset_x() const { return offset_x_; } - void set_offset_x(double offset_x) { offset_x_ = offset_x; } - double offset_y() const { return offset_y_; } - void set_offset_y(double offset_y) { offset_y_ = offset_y; } + // Returns the content offset that produces an equivalent scroll offset when + // applied to a UIScrollView whose contentInset is |content_inset|. + CGPoint GetEffectiveContentOffsetForContentInset( + UIEdgeInsets content_inset) const; + + // Accessors for scroll offsets and zoom scale. + const CGPoint& content_offset() const { return content_offset_; } + CGPoint& content_offset() { return content_offset_; } + void set_content_offset(const CGPoint& content_offset) { + content_offset_ = content_offset; + } + const UIEdgeInsets& content_inset() const { return content_inset_; } + UIEdgeInsets& content_inset() { return content_inset_; } + void set_content_inset(const UIEdgeInsets& content_inset) { + content_inset_ = content_inset; + } // Comparator operators. bool operator==(const PageScrollState& other) const; bool operator!=(const PageScrollState& other) const; private: - // The x value of the page's UIScrollView contentOffset. - double offset_x_; - // The y value of the page's UIScrollView contentOffset. - double offset_y_; + // The content offset and content inset of the web view scroll view. + CGPoint content_offset_; + UIEdgeInsets content_inset_; }; // Class used to represent the scrolling offset and the zoom scale of a webview. @@ -49,9 +56,9 @@ // Default constructor. Initializes scroll offsets and zoom scales to NAN. PageZoomState(); // Constructor with initial values. - PageZoomState(double minimum_zoom_scale, - double maximum_zoom_scale, - double zoom_scale); + PageZoomState(CGFloat minimum_zoom_scale, + CGFloat maximum_zoom_scale, + CGFloat zoom_scale); ~PageZoomState(); // Non-legacy zoom scales are valid if all three values are non-NAN and the @@ -61,21 +68,21 @@ bool IsValid() const; // Returns the allowed zoom scale range for this scroll state. - double GetMinMaxZoomDifference() const { + CGFloat GetMinMaxZoomDifference() const { return maximum_zoom_scale_ - minimum_zoom_scale_; } // Accessors. - double minimum_zoom_scale() const { return minimum_zoom_scale_; } - void set_minimum_zoom_scale(double minimum_zoom_scale) { + CGFloat minimum_zoom_scale() const { return minimum_zoom_scale_; } + void set_minimum_zoom_scale(CGFloat minimum_zoom_scale) { minimum_zoom_scale_ = minimum_zoom_scale; } - double maximum_zoom_scale() const { return maximum_zoom_scale_; } - void set_maximum_zoom_scale(double maximum_zoom_scale) { + CGFloat maximum_zoom_scale() const { return maximum_zoom_scale_; } + void set_maximum_zoom_scale(CGFloat maximum_zoom_scale) { maximum_zoom_scale_ = maximum_zoom_scale; } - double zoom_scale() const { return zoom_scale_; } - void set_zoom_scale(double zoom_scale) { zoom_scale_ = zoom_scale; } + CGFloat zoom_scale() const { return zoom_scale_; } + void set_zoom_scale(CGFloat zoom_scale) { zoom_scale_ = zoom_scale; } // Comparator operators. bool operator==(const PageZoomState& other) const; @@ -83,11 +90,11 @@ private: // The minimumZoomScale value of the page's UIScrollView. - double minimum_zoom_scale_; + CGFloat minimum_zoom_scale_; // The maximumZoomScale value of the page's UIScrollView. - double maximum_zoom_scale_; + CGFloat maximum_zoom_scale_; // The zoomScale value of the page's UIScrollView. - double zoom_scale_; + CGFloat zoom_scale_; }; // Class used to represent the scroll offset and zoom scale of a webview. @@ -98,11 +105,11 @@ // Constructor with initial values. PageDisplayState(const PageScrollState& scroll_state, const PageZoomState& zoom_state); - PageDisplayState(double offset_x, - double offset_y, - double minimum_zoom_scale, - double maximum_zoom_scale, - double zoom_scale); + PageDisplayState(const CGPoint& content_offset, + const UIEdgeInsets& content_inset, + CGFloat minimum_zoom_scale, + CGFloat maximum_zoom_scale, + CGFloat zoom_scale); PageDisplayState(NSDictionary* serialization); ~PageDisplayState();
diff --git a/ios/web/public/web_state/page_display_state.mm b/ios/web/public/web_state/page_display_state.mm index cb1ac33..b9307a3 100644 --- a/ios/web/public/web_state/page_display_state.mm +++ b/ios/web/public/web_state/page_display_state.mm
@@ -14,42 +14,103 @@ namespace { // Serialiation keys. -NSString* const kXOffsetKey = @"scrollX"; -NSString* const kYOffsetKey = @"scrollY"; +NSString* const kContentOffsetKey = @"contentOffset"; +NSString* const kContentInsetKey = @"contentInset"; NSString* const kMinZoomKey = @"minZoom"; NSString* const kMaxZoomKey = @"maxZoom"; NSString* const kZoomKey = @"zoom"; -// Returns true if: -// - both |value1| and |value2| are NAN, or -// - |value1| and |value2| are equal non-NAN values. -inline bool StateValuesAreEqual(double value1, double value2) { +// Deprecated serialization keys. +// TODO(crbug.com/926041): Remove these keys. +NSString* const kDeprecatedXOffsetKey = @"scrollX"; +NSString* const kDeprecatedYOffsetKey = @"scrollY"; +// Invalid consts. +const CGPoint kInvalidContentOffset = CGPointMake(NAN, NAN); +const UIEdgeInsets kInvalidContentInset = UIEdgeInsetsMake(NAN, NAN, NAN, NAN); +// Equality checkers. Return true if both values are NAN or equivalent. +inline bool StateValuesAreEqual(CGFloat value1, CGFloat value2) { return std::isnan(value1) ? std::isnan(value2) : value1 == value2; } -// Returns the double stored under |key| in |serialization|, or NAN if it is not -// set. -inline double GetValue(NSString* key, NSDictionary* serialization) { +inline bool StateContentOffsetsAreEqual(const CGPoint& offset1, + const CGPoint& offset2) { + return StateValuesAreEqual(offset1.x, offset2.x) && + StateValuesAreEqual(offset1.y, offset2.y); +} +inline bool StateContentInsetsAreEqual(const UIEdgeInsets& inset1, + const UIEdgeInsets& inset2) { + return StateValuesAreEqual(inset1.top, inset2.top) && + StateValuesAreEqual(inset1.left, inset2.left) && + StateValuesAreEqual(inset1.bottom, inset2.bottom) && + StateValuesAreEqual(inset1.right, inset2.right); +} +// Validity checker util functions. +inline bool IsContentOffsetValid(const CGPoint& content_offset) { + return !std::isnan(content_offset.x) && !std::isnan(content_offset.y); +} +inline bool IsContentInsetValid(const UIEdgeInsets& content_inset) { + return !std::isnan(content_inset.top) && !std::isnan(content_inset.left) && + !std::isnan(content_inset.bottom) && !std::isnan(content_inset.right); +} +// Returns the CGFloat stored under |key| in |serialization|, or NAN if it is +// not set. +inline CGFloat GetFloatValue(NSString* key, NSDictionary* serialization) { NSNumber* value = serialization[key]; return value ? [value doubleValue] : NAN; } +// Returns the contentOffset stored in |serialization|, or a NAN offset if it is +// not set. +inline CGPoint GetContentOffset(NSDictionary* serialization) { + NSValue* value = serialization[kContentOffsetKey]; + if (value) + return [value CGPointValue]; + // TODO(crbug.com/926041): Return kInvalidContentOffset when legacy keys are + // removed. + return CGPointMake(GetFloatValue(kDeprecatedXOffsetKey, serialization), + GetFloatValue(kDeprecatedYOffsetKey, serialization)); +} +// Returns the contentInset stored in |serialization|, or a NAN inset if it is +// not set. +inline UIEdgeInsets GetContentInset(NSDictionary* serialization) { + NSValue* value = serialization[kContentInsetKey]; + if (value) + return [value UIEdgeInsetsValue]; + if (serialization[kDeprecatedXOffsetKey] && + serialization[kDeprecatedYOffsetKey]) { + // When restoring PageScrollStates created using the deprecated + // serialization keyes, use UIEdgeInsetsZero as default. + // TODO(crbug.com/926041): Just return kInvalidContentInset when legacy keys + // are removed. + return UIEdgeInsetsZero; + } + // Return an invalid inset if neither the new nor legacy keys were contained. + return kInvalidContentInset; +} } // namespace -PageScrollState::PageScrollState() : offset_x_(NAN), offset_y_(NAN) { -} +PageScrollState::PageScrollState() + : content_offset_(kInvalidContentOffset), + content_inset_(kInvalidContentInset) {} -PageScrollState::PageScrollState(double offset_x, double offset_y) - : offset_x_(offset_x), offset_y_(offset_y) { -} +PageScrollState::PageScrollState(const CGPoint& content_offset, + const UIEdgeInsets& content_inset) + : content_offset_(content_offset), content_inset_(content_inset) {} -PageScrollState::~PageScrollState() { -} +PageScrollState::~PageScrollState() = default; bool PageScrollState::IsValid() const { - return !std::isnan(offset_x_) && !std::isnan(offset_y_); + return IsContentOffsetValid(content_offset_) && + IsContentInsetValid(content_inset_); +} + +CGPoint PageScrollState::GetEffectiveContentOffsetForContentInset( + UIEdgeInsets content_inset) const { + return CGPointMake( + content_offset_.x + content_inset_.left - content_inset.left, + content_offset_.y + content_inset_.top - content_inset.top); } bool PageScrollState::operator==(const PageScrollState& other) const { - return StateValuesAreEqual(offset_x_, other.offset_x_) && - StateValuesAreEqual(offset_y_, other.offset_y_); + return StateContentOffsetsAreEqual(content_offset_, other.content_offset_) && + StateContentInsetsAreEqual(content_inset_, other.content_inset_); } bool PageScrollState::operator!=(const PageScrollState& other) const { @@ -60,13 +121,12 @@ : minimum_zoom_scale_(NAN), maximum_zoom_scale_(NAN), zoom_scale_(NAN) { } -PageZoomState::PageZoomState(double minimum_zoom_scale, - double maximum_zoom_scale, - double zoom_scale) +PageZoomState::PageZoomState(CGFloat minimum_zoom_scale, + CGFloat maximum_zoom_scale, + CGFloat zoom_scale) : minimum_zoom_scale_(minimum_zoom_scale), maximum_zoom_scale_(maximum_zoom_scale), - zoom_scale_(zoom_scale) { -} + zoom_scale_(zoom_scale) {} PageZoomState::~PageZoomState() { } @@ -96,21 +156,20 @@ : scroll_state_(scroll_state), zoom_state_(zoom_state) { } -PageDisplayState::PageDisplayState(double offset_x, - double offset_y, - double minimum_zoom_scale, - double maximum_zoom_scale, - double zoom_scale) - : scroll_state_(offset_x, offset_y), - zoom_state_(minimum_zoom_scale, maximum_zoom_scale, zoom_scale) { -} +PageDisplayState::PageDisplayState(const CGPoint& content_offset, + const UIEdgeInsets& content_inset, + CGFloat minimum_zoom_scale, + CGFloat maximum_zoom_scale, + CGFloat zoom_scale) + : scroll_state_(content_offset, content_inset), + zoom_state_(minimum_zoom_scale, maximum_zoom_scale, zoom_scale) {} PageDisplayState::PageDisplayState(NSDictionary* serialization) - : PageDisplayState(GetValue(kXOffsetKey, serialization), - GetValue(kYOffsetKey, serialization), - GetValue(kMinZoomKey, serialization), - GetValue(kMaxZoomKey, serialization), - GetValue(kZoomKey, serialization)) {} + : PageDisplayState(GetContentOffset(serialization), + GetContentInset(serialization), + GetFloatValue(kMinZoomKey, serialization), + GetFloatValue(kMaxZoomKey, serialization), + GetFloatValue(kZoomKey, serialization)) {} PageDisplayState::~PageDisplayState() { } @@ -130,8 +189,10 @@ NSDictionary* PageDisplayState::GetSerialization() const { return @{ - kXOffsetKey : @(scroll_state_.offset_x()), - kYOffsetKey : @(scroll_state_.offset_y()), + kContentOffsetKey : + [NSValue valueWithCGPoint:scroll_state_.content_offset()], + kContentInsetKey : + [NSValue valueWithUIEdgeInsets:scroll_state_.content_inset()], kMinZoomKey : @(zoom_state_.minimum_zoom_scale()), kMaxZoomKey : @(zoom_state_.maximum_zoom_scale()), kZoomKey : @(zoom_state_.zoom_scale()) @@ -140,14 +201,15 @@ NSString* PageDisplayState::GetDescription() const { NSString* const kPageScrollStateDescriptionFormat = - @"{ scrollOffset:(%0.2f, %0.2f), zoomScaleRange:(%0.2f, %0.2f), " + @"{ contentOffset:%@, contentInset:%@, zoomScaleRange:(%0.2f, %0.2f), " @"zoomScale:%0.2f }"; - return [NSString stringWithFormat:kPageScrollStateDescriptionFormat, - scroll_state_.offset_x(), - scroll_state_.offset_y(), - zoom_state_.minimum_zoom_scale(), - zoom_state_.maximum_zoom_scale(), - zoom_state_.zoom_scale()]; + return [NSString + stringWithFormat:kPageScrollStateDescriptionFormat, + NSStringFromCGPoint(scroll_state_.content_offset()), + NSStringFromUIEdgeInsets(scroll_state_.content_inset()), + zoom_state_.minimum_zoom_scale(), + zoom_state_.maximum_zoom_scale(), + zoom_state_.zoom_scale()]; } } // namespace web
diff --git a/ios/web/public/web_state/ui/crw_native_content.h b/ios/web/public/web_state/ui/crw_native_content.h index ec5f23c..42798dd 100644 --- a/ios/web/public/web_state/ui/crw_native_content.h +++ b/ios/web/public/web_state/ui/crw_native_content.h
@@ -80,8 +80,9 @@ // content. - (GURL)virtualURL; -// The scroll offset of this native view. -- (CGPoint)scrollOffset; +// The content inset and offset of this native view. +- (CGPoint)contentOffset; +- (UIEdgeInsets)contentInset; @end
diff --git a/ios/web/web_state/page_display_state_unittest.mm b/ios/web/web_state/page_display_state_unittest.mm index 726673d..07353e8 100644 --- a/ios/web/web_state/page_display_state_unittest.mm +++ b/ios/web/web_state/page_display_state_unittest.mm
@@ -19,8 +19,12 @@ // NAN values. TEST_F(PageDisplayStateTest, EmptyConstructor) { web::PageDisplayState state; - EXPECT_NAN(state.scroll_state().offset_x()); - EXPECT_NAN(state.scroll_state().offset_y()); + EXPECT_NAN(state.scroll_state().content_offset().y); + EXPECT_NAN(state.scroll_state().content_offset().x); + EXPECT_NAN(state.scroll_state().content_inset().top); + EXPECT_NAN(state.scroll_state().content_inset().left); + EXPECT_NAN(state.scroll_state().content_inset().bottom); + EXPECT_NAN(state.scroll_state().content_inset().right); EXPECT_NAN(state.zoom_state().minimum_zoom_scale()); EXPECT_NAN(state.zoom_state().maximum_zoom_scale()); EXPECT_NAN(state.zoom_state().zoom_scale()); @@ -30,9 +34,13 @@ // Tests that the constructor with input states correctly populates the display // state. TEST_F(PageDisplayStateTest, StatesConstructor) { - web::PageScrollState scroll_state(0.0, 1.0); - EXPECT_EQ(0.0, scroll_state.offset_x()); - EXPECT_EQ(1.0, scroll_state.offset_y()); + const CGPoint kContentOffset = CGPointMake(0.0, 1.0); + const UIEdgeInsets kContentInset = UIEdgeInsetsMake(0.0, 1.0, 2.0, 3.0); + web::PageScrollState scroll_state(kContentOffset, kContentInset); + EXPECT_TRUE( + CGPointEqualToPoint(scroll_state.content_offset(), kContentOffset)); + EXPECT_TRUE(UIEdgeInsetsEqualToEdgeInsets(scroll_state.content_inset(), + kContentInset)); EXPECT_TRUE(scroll_state.IsValid()); web::PageZoomState zoom_state(1.0, 5.0, 1.0); EXPECT_EQ(1.0, zoom_state.minimum_zoom_scale()); @@ -40,30 +48,48 @@ EXPECT_EQ(1.0, zoom_state.zoom_scale()); EXPECT_TRUE(zoom_state.IsValid()); web::PageDisplayState state(scroll_state, zoom_state); - EXPECT_EQ(scroll_state.offset_x(), state.scroll_state().offset_x()); - EXPECT_EQ(scroll_state.offset_y(), state.scroll_state().offset_y()); - EXPECT_EQ(zoom_state.minimum_zoom_scale(), - state.zoom_state().minimum_zoom_scale()); - EXPECT_EQ(zoom_state.maximum_zoom_scale(), - state.zoom_state().maximum_zoom_scale()); - EXPECT_EQ(zoom_state.zoom_scale(), state.zoom_state().zoom_scale()); - EXPECT_TRUE(state.IsValid()); -} - -// Tests the constructor with value inputs. -TEST_F(PageDisplayStateTest, ValuesConstructor) { - web::PageDisplayState state(0.0, 1.0, 1.0, 5.0, 1.0); - EXPECT_EQ(0.0, state.scroll_state().offset_x()); - EXPECT_EQ(1.0, state.scroll_state().offset_y()); - EXPECT_EQ(1.0, state.zoom_state().minimum_zoom_scale()); - EXPECT_EQ(5.0, state.zoom_state().maximum_zoom_scale()); - EXPECT_EQ(1.0, state.zoom_state().zoom_scale()); + EXPECT_EQ(scroll_state, state.scroll_state()); + EXPECT_EQ(zoom_state, state.zoom_state()); EXPECT_TRUE(state.IsValid()); } // Tests converting between a PageDisplayState, its serialization, and back. TEST_F(PageDisplayStateTest, Serialization) { - web::PageDisplayState state(0.0, 1.0, 1.0, 5.0, 1.0); + web::PageDisplayState state(CGPointMake(0.0, 1.0), + UIEdgeInsetsMake(0.0, 1.0, 2.0, 3.0), 1.0, 5.0, + 1.0); web::PageDisplayState new_state(state.GetSerialization()); EXPECT_EQ(state, new_state); } + +// Tests that the PageScrollState is updated correctly when restored from the +// deprecated serialization keys. +// TODO(crbug.com/926041): Delete this test when legacy keys are removed. +TEST_F(PageDisplayStateTest, LegacySerialization) { + const CGPoint kContentOffset = CGPointMake(25.0, 100.0); + web::PageDisplayState state( + @{@"scrollX" : @(kContentOffset.x), + @"scrollY" : @(kContentOffset.y)}); + EXPECT_TRUE(CGPointEqualToPoint(kContentOffset, + state.scroll_state().content_offset())); + EXPECT_TRUE(UIEdgeInsetsEqualToEdgeInsets( + state.scroll_state().content_inset(), UIEdgeInsetsZero)); +} + +// Tests PageScrollState::GetEffectiveContentOffsetForContentInset(). +TEST_F(PageDisplayStateTest, EffectiveContentOffset) { + // kContentOffset is chosen such that a page with kTopInset is scrolled to the + // top. + const CGFloat kTopInset = 100; + const CGPoint kContentOffset = CGPointMake(0.0, -kTopInset); + const UIEdgeInsets kContentInset = UIEdgeInsetsMake(kTopInset, 0.0, 0.0, 0.0); + web::PageScrollState scroll_state(kContentOffset, kContentInset); + // Tests that GetEffectiveContentOffsetForContentInset() returns the scrolled- + // to-top content offset for kNewTopInset. + const CGFloat kNewTopInset = 50.0; + const UIEdgeInsets kNewContentInset = + UIEdgeInsetsMake(kNewTopInset, 0.0, 0.0, 0.0); + CGPoint effective_content_offset = + scroll_state.GetEffectiveContentOffsetForContentInset(kNewContentInset); + EXPECT_EQ(effective_content_offset.y, -kNewTopInset); +}
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 0a77771..de7e5d43 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -3588,19 +3588,17 @@ // If a native controller is present, record its display state instead of that // of the underlying placeholder webview. if (self.nativeController) { - if ([self.nativeController respondsToSelector:@selector(scrollOffset)]) { - displayState.scroll_state().set_offset_x( - [self.nativeController scrollOffset].x); - displayState.scroll_state().set_offset_y( - [self.nativeController scrollOffset].y); + if ([self.nativeController respondsToSelector:@selector(contentOffset)]) { + displayState.scroll_state().set_content_offset( + [self.nativeController contentOffset]); + } + if ([self.nativeController respondsToSelector:@selector(contentInset)]) { + displayState.scroll_state().set_content_inset( + [self.nativeController contentInset]); } } else if (_webView) { - CGPoint scrollOffset = [self scrollPosition]; - UIEdgeInsets contentInset = self.webScrollView.contentInset; - displayState.scroll_state().set_offset_x( - std::floor(scrollOffset.x + contentInset.left)); - displayState.scroll_state().set_offset_y( - std::floor(scrollOffset.y + contentInset.top)); + displayState.set_scroll_state(web::PageScrollState( + self.scrollPosition, self.webScrollView.contentInset)); UIScrollView* scrollView = self.webScrollView; displayState.zoom_state().set_minimum_zoom_scale( scrollView.minimumZoomScale); @@ -3619,10 +3617,8 @@ // scrolled or changed the zoom scale while the page is still loading, don't // restore any state since it will confuse the user. web::PageDisplayState currentPageDisplayState = self.pageDisplayState; - if (currentPageDisplayState.scroll_state().offset_x() == - _displayStateOnStartLoading.scroll_state().offset_x() && - currentPageDisplayState.scroll_state().offset_y() == - _displayStateOnStartLoading.scroll_state().offset_y() && + if (currentPageDisplayState.scroll_state() == + _displayStateOnStartLoading.scroll_state() && !_pageHasZoomed) { [self applyPageDisplayState:displayState]; } @@ -3769,18 +3765,17 @@ - (void)applyWebViewScrollOffsetFromScrollState: (const web::PageScrollState&)scrollState { DCHECK(scrollState.IsValid()); - UIEdgeInsets contentInset = self.webScrollView.contentInset; - CGPoint scrollOffset = CGPointMake(scrollState.offset_x() - contentInset.left, - scrollState.offset_y() - contentInset.top); + CGPoint contentOffset = scrollState.GetEffectiveContentOffsetForContentInset( + self.webScrollView.contentInset); if (_loadPhase == web::PAGE_LOADED) { // If the page is loaded, update the scroll immediately. - [self.webScrollView setContentOffset:scrollOffset]; + self.webScrollView.contentOffset = contentOffset; } else { // If the page isn't loaded, store the action to update the scroll // when the page finishes loading. __weak UIScrollView* weakScrollView = self.webScrollView; ProceduralBlock action = [^{ - [weakScrollView setContentOffset:scrollOffset]; + weakScrollView.contentOffset = contentOffset; } copy]; [_pendingLoadCompleteActions addObject:action]; }
diff --git a/media/filters/fuchsia/fuchsia_video_decoder.cc b/media/filters/fuchsia/fuchsia_video_decoder.cc index ef261f9..731a619b 100644 --- a/media/filters/fuchsia/fuchsia_video_decoder.cc +++ b/media/filters/fuchsia/fuchsia_video_decoder.cc
@@ -226,7 +226,7 @@ zx_status_t status = zx::vmar::root_self()->map( /*vmar_offset=*/0, buffer_.vmo(), 0, buffer_.size(), - ZX_VM_REQUIRE_NON_RESIZABLE | ZX_VM_FLAG_PERM_READ, &mapped_memory_); + ZX_VM_REQUIRE_NON_RESIZABLE | ZX_VM_PERM_READ, &mapped_memory_); if (status != ZX_OK) { ZX_DLOG(ERROR, status) << "zx_vmar_map";
diff --git a/media/gpu/android/image_reader_gl_owner.cc b/media/gpu/android/image_reader_gl_owner.cc index 7767d3e5..690d5de 100644 --- a/media/gpu/android/image_reader_gl_owner.cc +++ b/media/gpu/android/image_reader_gl_owner.cc
@@ -60,10 +60,16 @@ texture_owner_(std::move(texture_owner)), image_(image) {} ~ScopedHardwareBufferImpl() override { - texture_owner_->ReleaseRefOnImage(image_); + texture_owner_->ReleaseRefOnImage(image_, std::move(read_fence_)); + } + + void SetReadFence(base::ScopedFD fence_fd) final { + DCHECK(!read_fence_.is_valid()); + read_fence_ = std::move(fence_fd); } private: + base::ScopedFD read_fence_; scoped_refptr<ImageReaderGLOwner> texture_owner_; AImage* image_; }; @@ -292,35 +298,42 @@ auto fence_fd = base::ScopedFD(HANDLE_EINTR(dup(current_image_fence_.get()))); // Add a ref that the caller will release. - auto it = external_image_refs_.find(current_image_); - if (it == external_image_refs_.end()) - external_image_refs_[current_image_] = 1; - else - it->second++; - + external_image_refs_[current_image_].count++; return std::make_unique<ScopedHardwareBufferImpl>( this, current_image_, base::android::ScopedHardwareBufferHandle::Create(buffer), std::move(fence_fd)); } -void ImageReaderGLOwner::ReleaseRefOnImage(AImage* image) { +void ImageReaderGLOwner::ReleaseRefOnImage(AImage* image, + base::ScopedFD fence_fd) { auto it = external_image_refs_.find(image); DCHECK(it != external_image_refs_.end()); - DCHECK_GT(it->second, 0u); - it->second--; - if (it->second > 0) + auto& image_ref = it->second; + DCHECK_GT(image_ref.count, 0u); + image_ref.count--; + + // TODO(khushalsagar): We should probably merge this fence with any + // pre-existing fence, and there are also a couple of other cases that are + // being ignored here (delete image async if it is the |current_image| using + // this fence, combining display compositor fence with the |fence_fd| here). + // But all of this is going to be automagically fixed with SharedImages, so + // need to do the proper thing once media switches to that. + image_ref.fence_fd = std::move(fence_fd); + + if (image_ref.count > 0) return; + + // Delete the image if it has no pending refs and it is not the current image. + if (image != current_image_) { + if (image_ref.fence_fd.is_valid()) + loader_.AImage_deleteAsync(image, image_ref.fence_fd.release()); + else + loader_.AImage_delete(image); + } + external_image_refs_.erase(it); - - if (image == current_image_) - return; - - // No refs on the image. If it is no longer current, delete it. Note that this - // can be deleted synchronously here since the caller ensures that any pending - // GPU work for the image is finished before marking it for release. - loader_.AImage_delete(image); } void ImageReaderGLOwner::GetTransformMatrix(float mtx[]) { @@ -397,4 +410,10 @@ } } +ImageReaderGLOwner::ImageRef::ImageRef() = default; +ImageReaderGLOwner::ImageRef::~ImageRef() = default; +ImageReaderGLOwner::ImageRef::ImageRef(ImageRef&& other) = default; +ImageReaderGLOwner::ImageRef& ImageReaderGLOwner::ImageRef::operator=( + ImageRef&& other) = default; + } // namespace media
diff --git a/media/gpu/android/image_reader_gl_owner.h b/media/gpu/android/image_reader_gl_owner.h index 77377dd..f3d4857 100644 --- a/media/gpu/android/image_reader_gl_owner.h +++ b/media/gpu/android/image_reader_gl_owner.h
@@ -63,7 +63,10 @@ bool MaybeDeleteCurrentImage(); void EnsureTexImageBound(); - void ReleaseRefOnImage(AImage* image); + + // Releases an external ref on the image, with the fence that must be signaled + // before the |image| can be resued by the AImageReader. + void ReleaseRefOnImage(AImage* image, base::ScopedFD fence_fd); // AImageReader instance AImageReader* image_reader_; @@ -80,7 +83,19 @@ // A map consisting of pending external refs on an AImage. If an image has any // external refs, it is automatically released once the ref-count is 0 and the // image is no longer current. - using AImageRefMap = base::flat_map<AImage*, size_t>; + struct ImageRef { + ImageRef(); + ~ImageRef(); + + ImageRef(ImageRef&& other); + ImageRef& operator=(ImageRef&& other); + + size_t count = 0u; + base::ScopedFD fence_fd; + + DISALLOW_COPY_AND_ASSIGN(ImageRef); + }; + using AImageRefMap = base::flat_map<AImage*, ImageRef>; AImageRefMap external_image_refs_; // reference to the class instance which is used to dynamically
diff --git a/media/gpu/image_processor_test.cc b/media/gpu/image_processor_test.cc index 8480373..bc17118 100644 --- a/media/gpu/image_processor_test.cc +++ b/media/gpu/image_processor_test.cc
@@ -99,10 +99,10 @@ }; // I420->NV12 -INSTANTIATE_TEST_CASE_P(ConvertI420ToNV12, - ImageProcessorSimpleParamTest, - ::testing::Values(std::make_tuple(kI420Image, - kNV12Image))); +INSTANTIATE_TEST_SUITE_P(ConvertI420ToNV12, + ImageProcessorSimpleParamTest, + ::testing::Values(std::make_tuple(kI420Image, + kNV12Image))); #if defined(OS_CHROMEOS) // TODO(hiroh): Add more tests.
diff --git a/media/gpu/ipc/service/vda_video_decoder_unittest.cc b/media/gpu/ipc/service/vda_video_decoder_unittest.cc index 4031b27..963380d 100644 --- a/media/gpu/ipc/service/vda_video_decoder_unittest.cc +++ b/media/gpu/ipc/service/vda_video_decoder_unittest.cc
@@ -475,8 +475,8 @@ NotifyFlushDone(); } -INSTANTIATE_TEST_CASE_P(VdaVideoDecoder, - VdaVideoDecoderTest, - ::testing::Values(false, true)); +INSTANTIATE_TEST_SUITE_P(VdaVideoDecoder, + VdaVideoDecoderTest, + ::testing::Values(false, true)); } // namespace media
diff --git a/media/gpu/test/video_frame_file_writer.cc b/media/gpu/test/video_frame_file_writer.cc index fb1f35e..6fa87a6 100644 --- a/media/gpu/test/video_frame_file_writer.cc +++ b/media/gpu/test/video_frame_file_writer.cc
@@ -97,8 +97,6 @@ void VideoFrameFileWriter::ProcessVideoFrame( scoped_refptr<const VideoFrame> video_frame, size_t frame_index) { - DCHECK_CALLED_ON_VALID_SEQUENCE(writer_sequence_checker_); - base::AutoLock auto_lock(frame_writer_lock_); num_frames_writing_++;
diff --git a/media/gpu/test/video_player/frame_renderer_dummy.cc b/media/gpu/test/video_player/frame_renderer_dummy.cc index 594b890..020b747 100644 --- a/media/gpu/test/video_player/frame_renderer_dummy.cc +++ b/media/gpu/test/video_player/frame_renderer_dummy.cc
@@ -76,15 +76,11 @@ } gl::GLContext* FrameRendererDummy::GetGLContext() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // As no actual rendering is done we don't have a GLContext. return nullptr; } -void FrameRendererDummy::RenderFrame(scoped_refptr<VideoFrame> video_frame) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} +void FrameRendererDummy::RenderFrame(scoped_refptr<VideoFrame> video_frame) {} } // namespace test } // namespace media
diff --git a/media/gpu/test/video_player/video_player.h b/media/gpu/test/video_player/video_player.h index 9736bb1..2a233d3 100644 --- a/media/gpu/test/video_player/video_player.h +++ b/media/gpu/test/video_player/video_player.h
@@ -26,7 +26,7 @@ class VideoFrameProcessor; // Default timeout used when waiting for events. -constexpr base::TimeDelta kDefaultTimeout = base::TimeDelta::FromSeconds(10); +constexpr base::TimeDelta kDefaultTimeout = base::TimeDelta::FromSeconds(30); enum class VideoPlayerState : size_t { kUninitialized = 0,
diff --git a/media/gpu/video_decode_accelerator_tests.cc b/media/gpu/video_decode_accelerator_tests.cc index 99a6c080..7f06e12 100644 --- a/media/gpu/video_decode_accelerator_tests.cc +++ b/media/gpu/video_decode_accelerator_tests.cc
@@ -84,12 +84,12 @@ std::unique_ptr<VideoPlayer> CreateVideoPlayer( const Video* video, const VideoDecoderClientConfig& config = VideoDecoderClientConfig()) { - frame_validator_ = - media::test::VideoFrameValidator::Create(video->FrameChecksums()); - // TODO(dstaessens@) allow enabling/disabling file writing + frame_validators_.push_back( + media::test::VideoFrameValidator::Create(video->FrameChecksums())); return VideoPlayer::Create( video, g_env->dummy_frame_renderer_.get(), - {frame_validator_.get(), g_env->frame_file_writer_.get()}, config); + {frame_validators_.back().get(), g_env->frame_file_writer_.get()}, + config); } void SetUp() override { @@ -104,8 +104,12 @@ void TearDown() override { g_env->frame_file_writer_->WaitUntilDone(); } + const VideoFrameValidator* GetFrameValidator(size_t index = 0) { + return frame_validators_[index].get(); + } + protected: - std::unique_ptr<VideoFrameValidator> frame_validator_; + std::vector<std::unique_ptr<VideoFrameValidator>> frame_validators_; }; } // namespace @@ -120,7 +124,7 @@ EXPECT_EQ(tvp->GetFlushDoneCount(), 1u); EXPECT_EQ(tvp->GetFrameDecodedCount(), g_env->video_->NumFrames()); - EXPECT_TRUE(frame_validator_->WaitUntilValidated()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); } // Flush the decoder immediately after initialization. @@ -134,7 +138,7 @@ EXPECT_EQ(tvp->GetFlushDoneCount(), 2u); EXPECT_EQ(tvp->GetFrameDecodedCount(), g_env->video_->NumFrames()); - EXPECT_TRUE(frame_validator_->WaitUntilValidated()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); } // Flush the decoder immediately after doing a mid-stream reset, without waiting @@ -156,7 +160,7 @@ EXPECT_EQ(tvp->GetResetDoneCount(), 1u); EXPECT_EQ(tvp->GetFlushDoneCount(), 1u); EXPECT_LE(tvp->GetFrameDecodedCount(), g_env->video_->NumFrames()); - EXPECT_TRUE(frame_validator_->WaitUntilValidated()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); } // Reset the decoder immediately after initialization. @@ -171,7 +175,7 @@ EXPECT_EQ(tvp->GetResetDoneCount(), 1u); EXPECT_EQ(tvp->GetFlushDoneCount(), 1u); EXPECT_EQ(tvp->GetFrameDecodedCount(), g_env->video_->NumFrames()); - EXPECT_TRUE(frame_validator_->WaitUntilValidated()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); } // Reset the decoder when the middle of the stream is reached. @@ -190,7 +194,7 @@ EXPECT_EQ(tvp->GetFlushDoneCount(), 1u); EXPECT_EQ(tvp->GetFrameDecodedCount(), numFramesDecoded + g_env->video_->NumFrames()); - EXPECT_TRUE(frame_validator_->WaitUntilValidated()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); } // Reset the decoder when the end of the stream is reached. @@ -208,7 +212,7 @@ EXPECT_EQ(tvp->GetResetDoneCount(), 1u); EXPECT_EQ(tvp->GetFlushDoneCount(), 2u); EXPECT_EQ(tvp->GetFrameDecodedCount(), g_env->video_->NumFrames() * 2); - EXPECT_TRUE(frame_validator_->WaitUntilValidated()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); } // Reset the decoder immediately when the end-of-stream flush starts, without @@ -230,22 +234,7 @@ EXPECT_LE(tvp->GetFlushDoneCount(), 1u); EXPECT_EQ(tvp->GetResetDoneCount(), 1u); EXPECT_LE(tvp->GetFrameDecodedCount(), g_env->video_->NumFrames()); - EXPECT_TRUE(frame_validator_->WaitUntilValidated()); -} - -// Play video from start to end. Multiple buffer decodes will be queued in the -// decoder, without waiting for the result of the previous decode requests. -TEST_F(VideoDecoderTest, FlushAtEndOfStream_MultipleOutstandingDecodes) { - VideoDecoderClientConfig config; - config.max_outstanding_decode_requests = 5; - auto tvp = CreateVideoPlayer(g_env->video_, config); - - tvp->Play(); - EXPECT_TRUE(tvp->WaitForFlushDone()); - - EXPECT_EQ(tvp->GetFlushDoneCount(), 1u); - EXPECT_EQ(tvp->GetFrameDecodedCount(), g_env->video_->NumFrames()); - EXPECT_TRUE(frame_validator_->WaitUntilValidated()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); } // Reset the decoder immediately when encountering the first config info in a @@ -271,7 +260,43 @@ EXPECT_EQ(tvp->GetFrameDecodedCount(), numFramesDecoded + g_env->video_->NumFrames()); EXPECT_GE(tvp->GetEventCount(VideoPlayerEvent::kConfigInfo), 1u); - EXPECT_EQ(0u, frame_validator_->GetMismatchedFramesCount()); + EXPECT_EQ(0u, GetFrameValidator()->GetMismatchedFramesCount()); +} + +// Play video from start to end. Multiple buffer decodes will be queued in the +// decoder, without waiting for the result of the previous decode requests. +TEST_F(VideoDecoderTest, FlushAtEndOfStream_MultipleOutstandingDecodes) { + VideoDecoderClientConfig config; + config.max_outstanding_decode_requests = 5; + auto tvp = CreateVideoPlayer(g_env->video_, config); + + tvp->Play(); + EXPECT_TRUE(tvp->WaitForFlushDone()); + + EXPECT_EQ(tvp->GetFlushDoneCount(), 1u); + EXPECT_EQ(tvp->GetFrameDecodedCount(), g_env->video_->NumFrames()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); +} + +// Play multiple videos simultaneously from start to finish. +TEST_F(VideoDecoderTest, FlushAtEndOfStream_MultipleConcurrentDecodes) { + // The minimal number of concurrent decoders we expect to be supported. + constexpr size_t kMinSupportedConcurrentDecoders = 3; + + std::vector<std::unique_ptr<VideoPlayer>> tvps( + kMinSupportedConcurrentDecoders); + for (size_t i = 0; i < kMinSupportedConcurrentDecoders; ++i) + tvps[i] = CreateVideoPlayer(g_env->video_); + + for (size_t i = 0; i < kMinSupportedConcurrentDecoders; ++i) + tvps[i]->Play(); + + for (size_t i = 0; i < kMinSupportedConcurrentDecoders; ++i) { + EXPECT_TRUE(tvps[i]->WaitForFlushDone()); + EXPECT_EQ(tvps[i]->GetFlushDoneCount(), 1u); + EXPECT_EQ(tvps[i]->GetFrameDecodedCount(), g_env->video_->NumFrames()); + EXPECT_TRUE(GetFrameValidator()->WaitUntilValidated()); + } } } // namespace test
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc index 096c1d7..e7dc801 100644 --- a/media/gpu/video_decode_accelerator_unittest.cc +++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -1431,25 +1431,26 @@ }; // Test that replay after EOS works fine. -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ReplayAfterEOS, VideoDecodeAcceleratorParamTest, ::testing::Values( std::make_tuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false))); // Test that Reset() before the first Decode() works fine. -INSTANTIATE_TEST_CASE_P(ResetBeforeDecode, - VideoDecodeAcceleratorParamTest, - ::testing::Values(std::make_tuple(1, - 1, - 1, - START_OF_STREAM_RESET, - CS_RESET, - false, - false))); +INSTANTIATE_TEST_SUITE_P( + ResetBeforeDecode, + VideoDecodeAcceleratorParamTest, + ::testing::Values(std::make_tuple(1, + 1, + 1, + START_OF_STREAM_RESET, + CS_RESET, + false, + false))); // Test Reset() immediately after Decode() containing config info. -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ResetAfterFirstConfigInfo, VideoDecodeAcceleratorParamTest, ::testing::Values(std::make_tuple(1, @@ -1461,7 +1462,7 @@ false))); // Test Reset() immediately after Flush() and before NotifyFlushDone(). -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ResetBeforeNotifyFlushDone, VideoDecodeAcceleratorParamTest, ::testing::Values(std::make_tuple(1, @@ -1474,13 +1475,13 @@ // Test that Reset() mid-stream works fine and doesn't affect decoding even when // Decode() calls are made during the reset. -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MidStreamReset, VideoDecodeAcceleratorParamTest, ::testing::Values( std::make_tuple(1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( SlowRendering, VideoDecodeAcceleratorParamTest, ::testing::Values( @@ -1488,7 +1489,7 @@ // Test that Destroy() mid-stream works fine (primarily this is testing that no // crashes occur). -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( TearDownTiming, VideoDecodeAcceleratorParamTest, ::testing::Values( @@ -1544,7 +1545,7 @@ false))); // Test that decoding various variation works with multiple in-flight decodes. -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( DecodeVariations, VideoDecodeAcceleratorParamTest, ::testing::Values( @@ -1561,7 +1562,7 @@ // Find out how many concurrent decoders can go before we exhaust system // resources. -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ResourceExhaustion, VideoDecodeAcceleratorParamTest, ::testing::Values(std::make_tuple(kMinSupportedNumConcurrentDecoders, @@ -1580,8 +1581,8 @@ false))); // Allow MAYBE macro substitution. -#define WRAPPED_INSTANTIATE_TEST_CASE_P(a, b, c) \ - INSTANTIATE_TEST_CASE_P(a, b, c) +#define WRAPPED_INSTANTIATE_TEST_SUITE_P(a, b, c) \ + INSTANTIATE_TEST_SUITE_P(a, b, c) #if defined(OS_WIN) // There are no reference images for windows. @@ -1590,7 +1591,7 @@ #define MAYBE_Thumbnail Thumbnail #endif // Thumbnailing test -WRAPPED_INSTANTIATE_TEST_CASE_P( +WRAPPED_INSTANTIATE_TEST_SUITE_P( MAYBE_Thumbnail, VideoDecodeAcceleratorParamTest, ::testing::Values(
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc index 7de4f403..9cdf9252 100644 --- a/media/gpu/video_encode_accelerator_unittest.cc +++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -2522,104 +2522,104 @@ #if defined(OS_CHROMEOS) || defined(OS_LINUX) // TODO(kcwu): add back test of verify_output=true after // https://crbug.com/694131 fixed. -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( SimpleEncode, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, true, 0, false, false, false, false, false, false))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( EncoderPerf, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, false, 0, false, true, false, false, false, false))); -INSTANTIATE_TEST_CASE_P(ForceKeyframes, - VideoEncodeAcceleratorTest, - ::testing::Values(std::make_tuple(1, - false, - 10, - false, - false, - false, - false, - false, - false))); +INSTANTIATE_TEST_SUITE_P(ForceKeyframes, + VideoEncodeAcceleratorTest, + ::testing::Values(std::make_tuple(1, + false, + 10, + false, + false, + false, + false, + false, + false))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ForceBitrate, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, false, 0, true, false, false, false, false, false))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MidStreamParamSwitchBitrate, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, false, 0, true, false, true, false, false, false))); // TODO(kcwu): add back bitrate test after https://crbug.com/693336 fixed. -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( DISABLED_MidStreamParamSwitchFPS, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, false, 0, true, false, false, true, false, false))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MultipleEncoders, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(3, false, 0, false, false, false, false, false, false), std::make_tuple(3, false, 0, true, false, true, false, false, false))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( VerifyTimestamp, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, false, 0, false, false, false, false, false, true))); -INSTANTIATE_TEST_CASE_P(NoInputTest, - VideoEncodeAcceleratorSimpleTest, - ::testing::Values(0)); +INSTANTIATE_TEST_SUITE_P(NoInputTest, + VideoEncodeAcceleratorSimpleTest, + ::testing::Values(0)); -INSTANTIATE_TEST_CASE_P(CacheLineUnalignedInputTest, - VideoEncodeAcceleratorSimpleTest, - ::testing::Values(1)); +INSTANTIATE_TEST_SUITE_P(CacheLineUnalignedInputTest, + VideoEncodeAcceleratorSimpleTest, + ::testing::Values(1)); #elif defined(OS_MACOSX) || defined(OS_WIN) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( SimpleEncode, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, true, 0, false, false, false, false, false, false), std::make_tuple(1, true, 0, false, false, false, false, true, false))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( EncoderPerf, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, false, 0, false, true, false, false, false, false))); -INSTANTIATE_TEST_CASE_P(MultipleEncoders, - VideoEncodeAcceleratorTest, - ::testing::Values(std::make_tuple(3, - false, - 0, - false, - false, - false, - false, - false, - false))); +INSTANTIATE_TEST_SUITE_P(MultipleEncoders, + VideoEncodeAcceleratorTest, + ::testing::Values(std::make_tuple(3, + false, + 0, + false, + false, + false, + false, + false, + false))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( VerifyTimestamp, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, false, 0, false, false, false, false, false, true))); #if defined(OS_WIN) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ForceBitrate, VideoEncodeAcceleratorTest, ::testing::Values(
diff --git a/media/muxers/webm_muxer_unittest.cc b/media/muxers/webm_muxer_unittest.cc index 71eb083..f819ecd48 100644 --- a/media/muxers/webm_muxer_unittest.cc +++ b/media/muxers/webm_muxer_unittest.cc
@@ -327,6 +327,6 @@ {kCodecVP8, kCodecPCM, 1, 1}, }; -INSTANTIATE_TEST_CASE_P(, WebmMuxerTest, ValuesIn(kTestCases)); +INSTANTIATE_TEST_SUITE_P(, WebmMuxerTest, ValuesIn(kTestCases)); } // namespace media
diff --git a/mojo/public/tools/bindings/generators/js_templates/lite/interface_externs.tmpl b/mojo/public/tools/bindings/generators/js_templates/lite/interface_externs.tmpl index 813684e..72c3cd0d 100644 --- a/mojo/public/tools/bindings/generators/js_templates/lite/interface_externs.tmpl +++ b/mojo/public/tools/bindings/generators/js_templates/lite/interface_externs.tmpl
@@ -54,6 +54,11 @@ * @return {!{{module.namespace}}.{{interface.name}}Request} */ createRequest() {} + + /** + * @return {Promise} + */ + flushForTesting() {} }; {{module.namespace}}.{{interface.name}} = class {
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 8e37704a..1eb2cd3 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -6818,7 +6818,6 @@ { "name": "tonage.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "toncusters.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "toomanypillows.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "tooolroc.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "topmarine.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "tosteberg.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "toucedo.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -8161,7 +8160,6 @@ { "name": "imusic.dk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "indusfastremit-us.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "indusfastremit.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "insighti.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "insighti.sk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "iprice.co.id", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "iprice.hk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11403,7 +11401,6 @@ { "name": "convergemagazine.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "creativeartifice.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "cookiesoft.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "computersystems.guru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "comotalk.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "crumbcontrol.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "crtvmgmt.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11493,7 +11490,6 @@ { "name": "eintageinzug.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "elaintehtaat.fi", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "elemprendedor.com.ve", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "eit-web.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "elonbase.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "emi-air-comprime.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "endlessdiy.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11548,7 +11544,6 @@ { "name": "foreveralone.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "fourchin.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "flexapplications.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "forschbach-janssen.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "frickenate.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "fumiware.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "freebus.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11883,7 +11878,6 @@ { "name": "newtonhaus.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nicocourts.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nikksno.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "niagaraschoice.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nitropur.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nicolasklotz.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nicolasbettag.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11908,7 +11902,6 @@ { "name": "oh14.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ojls.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ons.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "onlinebizdirect.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "onearth.one", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "onarto.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "newline.online", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11934,7 +11927,6 @@ { "name": "overalglas.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "opensourcehouse.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "oxynux.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "partnercardservices.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "papa-webzeit.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "pastenib.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "penguinclientsystem.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11946,7 +11938,6 @@ { "name": "phantasie.cc", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "perroud.pro", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "perthdevicelab.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "pgpmail.cc", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "peterfolta.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "pfolta.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "performancesantafe.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11993,7 +11984,6 @@ { "name": "psncardplus.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "quail.solutions", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "radar.sx", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "r0uzic.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "qkka.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "psncardplus.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "qldformulaford.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -12011,12 +12001,10 @@ { "name": "refreshingserum.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ray-works.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rayworks.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "recepty.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "refill-roboter.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "redra.ws", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "relayawards.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rem.pe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "remitatm.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "res-rheingau.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "regionalcoalition.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rentacarcluj.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -12032,7 +12020,6 @@ { "name": "rhapsodhy.hu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rochman.id", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rointe.online", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "rotozen.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "royalhop.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rokort.dk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rogue-e.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -12045,19 +12032,12 @@ { "name": "runawebinar.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rr105.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "samraskauskas.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "s-mdb.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "saraleebread.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "sagsmarseille.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sagedocumentmanager.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "sanissimo.com.mx", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ruh-veit.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "saleslift.pl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "saba-piserver.info", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sangwon.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "saml-gateway.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "sandobygg.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "sandogruppen.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "saro.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sbirecruitment.co.in", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sansemea.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "samsen.club", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -12148,7 +12128,6 @@ { "name": "stigroom.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "studiozelden.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "svatba-frantovi.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "sumoatm.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "tails.com.ar", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sv-turm-hohenlimburg.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "taravancil.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -13002,7 +12981,6 @@ { "name": "tocaro.im", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "toursandtransfers.it", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "tracetracker.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "transport.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "trefpuntdemeent.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "tronatic-studio.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "tsaro.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -16332,7 +16310,6 @@ { "name": "tetrarch.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "studio-panic.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sudaraka.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "teamx-gaming.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "teamtrack.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "solariiknight.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "techace.jp", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -16577,7 +16554,6 @@ { "name": "xn--werner-schffer-fib.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ylinternal.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "yourgame.co.il", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "xyndrac.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ytuquelees.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "youlend.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "vanderziel.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -17956,7 +17932,6 @@ { "name": "yuzu.tk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "zlc1994.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "woufbox.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "zenycosta.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "worldsbeststory.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "yantrasthal.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "zefiris.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -18724,7 +18699,6 @@ { "name": "europapier.rs", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "europapier.ba", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "europapier.hu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "francisli.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "foxterrier.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "feld.saarland", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "foo.fo", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -19433,7 +19407,6 @@ { "name": "mysqldump-secure.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nadyaolcer.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "namereel.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "n-un.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "myepass.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "neatous.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "mydebian.in.ua", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -19677,7 +19650,6 @@ { "name": "rc-offi.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "remedica.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "professors.ee", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "puurwonengeldrop.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "pruikshop.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "robototes.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "questionable.host", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -20437,7 +20409,6 @@ { "name": "a-little-linux-box.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "8ackprotect.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "alicialab.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "adamek.online", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "4u2ore.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "akalashnikov.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "advokat-romanov.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -22230,7 +22201,6 @@ { "name": "projectnom.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "queryplayground.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "project-rune.tech", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "oblast45.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "mrning.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "pollet-ghys.be", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "quantumwebs.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -22260,7 +22230,6 @@ { "name": "rbti.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "recreation.gov", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "pfeuffer-elektro.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "proteinnuts.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ps4all.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rachelreagan.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "qrpth.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -22666,7 +22635,6 @@ { "name": "t4x.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "thailandpropertylisting.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "tacklog.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "tepitus.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "thewp.pro", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "teknotes.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "technotonic.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -23113,7 +23081,6 @@ { "name": "aux-arts-de-la-table.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "avticket.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "bacimg.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "backgroundchecks.online", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "badseacoffee.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "bagiobella.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "bakkerinjebuurt.be", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -25065,7 +25032,6 @@ { "name": "deepvision.com.ua", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "defrax.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "defrax.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "deftek.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "deftnerd.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "degen-elektrotechnik.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "deinewebsite.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -26788,7 +26754,6 @@ { "name": "panpsychist.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "panzer72.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "papakatsu-life.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "paperhaven.com.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "parachute70.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "paradise-engineer.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "paradise-engineers.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -28526,7 +28491,6 @@ { "name": "bentphotos.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "biaggeo.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "arfad.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "beyond-infinity.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "beraru.tk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "birdbrowser.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "bestwarezone.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -28893,7 +28857,6 @@ { "name": "crunchy.rocks", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "congobunkering.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "cuongthach.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "crows.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "currynissanmaparts.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "customwritingservice.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "chasafilli.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -29545,7 +29508,6 @@ { "name": "geneve-naturisme.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gilmoreid.com.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "govtjobs.blog", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "grandefratellonews.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gmx.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gmx.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "groentefruitzeep.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -31558,7 +31520,6 @@ { "name": "tsumi.moe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "travel-to-nature.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "tradietrove.com.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "tniad.mil.id", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "trekfriend.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "troedelhannes.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "thelostyankee.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -34490,7 +34451,6 @@ { "name": "apn-dz.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "aquarium-supplement.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "arcenergy.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "arcobalabs.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "arian.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "artsinthevalley.net.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "atlantahairsurgeon.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -36075,7 +36035,6 @@ { "name": "domengrad.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "domian.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "dominik-schlueter.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "donnoval.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "donpaginasweb.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "donzool.es", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "doopdidoop.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -36984,7 +36943,6 @@ { "name": "rwky.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ryzhov.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sabine-forschbach.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "sabineforschbach.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "saclier.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sacred-knights.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "saint-astier-triathlon.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -38976,7 +38934,6 @@ { "name": "leveluprails.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lidel.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lifemarque.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "lifeventure.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lignemalin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lilysbouncycastles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "limberg.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -39095,7 +39052,6 @@ { "name": "multikalender.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "muusika.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mvandek.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "mxlife.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "myjumparoo.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mymun.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "myowndisk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -40117,7 +40073,6 @@ { "name": "monkeytek.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "moonkin.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "moorewelliver.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "moppy.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "morespacestorage.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "moshwire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mp3donusturucu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -42719,7 +42674,6 @@ { "name": "konventa.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kopio.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kopjethee.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "koppelvlak.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "korben.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kotly-marten.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kouten-jp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -49481,7 +49435,6 @@ { "name": "kolcsey.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kotonoha.cafe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kovuthehusky.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "kryha.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ksk-agentur.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kuops.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lacetsfun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -50335,7 +50288,6 @@ { "name": "lunanova.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "luteijn.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "luteijn.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "mailum.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "makera.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "maketheneighborsjealous.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "malscan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -52247,7 +52199,6 @@ { "name": "portugal-a-programar.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "pour-la-culture-aulnay.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "pouwels-oss.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "prettynode.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "priorityelectric-agourahills.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "priorityelectric-calabasas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "priorityelectric-camarillo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -52300,7 +52251,6 @@ { "name": "sadev.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sadou.kyoto.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "safepay.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "samip.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sanantoniolocksmithinc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "santensautomatics.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sap-inc.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -53563,7 +53513,6 @@ { "name": "smart-media-gmbh.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "smartwoodczech.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "smcbox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "smith.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "smplr.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sms.storage", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "snowyluma.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -54023,7 +53972,6 @@ { "name": "romatrip.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ronniegane.kiwi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "rossmacphee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "rustralasia.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "saastopankki.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sac-shop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sacrome.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -62686,7 +62634,6 @@ { "name": "qkzy.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "qlcvea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "qpcna.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "qtap.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "quadra.srl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "rachurch.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "radiobox.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -65877,6 +65824,446 @@ { "name": "zstu.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zumub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zzbnet.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "021002.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "077768.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "081115.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "0x41.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "138000.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "161263.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "162361.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "177603.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "1android.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "1gp.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "1zombie.team", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "22delta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "411quest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "4hmediaproductions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "62314.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "662607.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "6bwcp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "8212p.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "877027.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "908.la", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "929349.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "9hosts.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "a-pro-pos.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acchicocchi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ace-aegon.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acg1080.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "adnmb1.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aimd.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alhost.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alloutofgum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "allrad-buck.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "almamet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alonas.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "americanindiancoc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ames.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amj74-informatique.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amyria.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "android-tv.3utilities.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "androzoom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "appspace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "arslankaynakmetal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "asmeets.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "auto1.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "autolawetawroclaw.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "avtek.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aylavblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bagwrap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "banderasdelmundo.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "barneveldcentrum.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "basics.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bawbby.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bazinga-events.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bcubic.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bebeautiful.business", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "beherit.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bestlooperpedalsguide.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bezlampowe.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bitcert.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blackmagicshaman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blogit.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "briograce.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "buck-hydro.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "burakogun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "burakogun.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "burakogun.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "burakogun.net.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "burakogun.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "burzum.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cabanactf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "camping-le-pasquier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "canopy.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "casinoportugal.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cclasabana.com.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "charlylou.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chemco.mu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ciclista.roma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "citywidealarms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "clo.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cloud255.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "codeandsupply.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "coincircle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "coisabakana.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "colcomm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "coldiario.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "comoaliviareldolor.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cooksecuritygroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "creativ-impuls-dekorateurin-muenchen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "crismatthews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "crypkit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cslaboralistas.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cuegee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cumtd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d4fx.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dadadani.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "danads.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dapianw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dare.deals", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "darf.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dead-letter.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "decorumcomics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "deepspace4.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "deplorablesdaily.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "depositart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "derekbooth.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "developer.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dickord.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dictionarypro.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "directoriostelefonicos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "divineglowinghealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "donetsk24.su", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dotesports.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dpsg-hohenlinden.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "drros.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dubstep.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "e-webos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eallion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eblog.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "educacionvirtual.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "educateyourskin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ekaplast.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ekouniejow.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "electricgatemotorglenvista.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eosolutions.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "esteladigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "estraks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "estudiaryaprenderingles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "excaliburtitle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "excess-baggage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eyemagic.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "facingbipolar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fantasysportsnews.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "farleybrass.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fb-feed.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "feross.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "festicle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "filehash.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fili.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "firefense.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fletcherdigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flexbuildingsystems.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flowersquito.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fonzone.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "foreverclean.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "forself.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "freertomorrow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "friedzombie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frsnpwr.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fruityfitness.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gakdigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gamerwares.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "garbagedisposalguides.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gestsal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "giftlist.guru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gpyy.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "groundmc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gurunpa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gyume.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "h33t.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "harelmallac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "harelmallacglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hartkampforkids.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hawawa.kr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "healthyrecharge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "heikohessenkemper.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "helpwithinsomnia.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hokung.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hostco.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hsg-kreuzberg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hugonote.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "icdp.org.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ictussistemas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iinf.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iiyama-bg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ilmainensanakirja.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "indigolawnscape.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "innovere.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "instafuckfriend.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "instahub.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "institutomaritimocolombiano.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "internationalstudentassociation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ishland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "isif-ostewg.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "islamicmarkets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "j0e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jamestmartin.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jerrysretailstores.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jix.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "joyfulhealthyeats.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "julestern.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jwhite.network", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kalashcards.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "keeckee.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "keeckee.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kiasystems.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kileahh.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "klop.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "komp247.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kosmos.org.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lares.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "launcher-minecraft.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "leafland.co.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "left-baggage.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "legabot.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "leszonderstress.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "linasjourney.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "linkst.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "linkyou.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lippu1.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lisahh-jayne.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "living-with-outlook-2010.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "localegroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ltlec.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ltlec.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ltmw.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "m2tm.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mailhardener.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mainhattan-handwerker.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "malibumodas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mantuo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "manwish.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "maorx.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "markhoodwrites.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "marron-dietrecipe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "masterpassword.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "matematyka.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "matteobrenci.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "matthi3u.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mcfi.mu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "melodict.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mentecuriosa.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "michilaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mindmax.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mionerve.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mionerve.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "misterseguros.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mmgal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mostcomfortableworkboots.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motogb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motospaya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mralonas.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mrdatenschutz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mte.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mukyu.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "murphycraftbeerfest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mvbug.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mycreditunion.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mypt3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nailsart.roma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nan.ge", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "napkins-wholesale.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "napkins-wholesale.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "napkins-wholesale.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "napkins-wholesale.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "napkins-wholesale.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "napkins-wholesale.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nasosvdom.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nauris.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ncua.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nebras.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "networkhane.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "new-vip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newfoundland-labradorflora.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nextcloud-miyamoto.spdns.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nilgirispice.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nonx.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nook.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "northebridge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "novengi.mu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "noxx.global", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "obec-krakovany.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "olandiz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "olivemultispecialist.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ordbokpro.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "outdoorchoose.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "outdoorhole.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "oxz.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "p5on.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paya.cat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paydigital.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "perevedi.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pglaum.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pharmaquality.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "phrazor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pinkmango.travel", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pixeoapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "platinapump.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "podipod.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "postandfly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "powersergdatasystems.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "powersergdynamic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "projectmakeit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "promuovi.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "proximoconcurso.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ptasiepodroze.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qklshequ.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qxzgssr.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rbuddenhagen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "reby.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "redmangallpsychologists.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "revivalsstores.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "richbutler.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "riddler.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ristisanat.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "robgorman.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ruhnke.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rvsuitlaatdelen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "saatchiart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sabbottlabs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "safungerar.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scevity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "searchpartners.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "securevideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "seemomclick.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "seht.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sektor.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "selber-coden.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sendingbee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "senorporno.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "senseict.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "servetten-groothandel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "servietten-grosshandel.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "servietten-grosshandel.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "servietten-grosshandel.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "servietten-grosshandel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "serviettes-et-plus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "servilletas-de-papel.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "servilletas-de-papel.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "serwetki-papierowe.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shavit.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shdsub.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shiny.gift", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shippinglabel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopdongho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sietejefes.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "simulping.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sirihouse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skillside.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skinandglamour.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skinwhiteningoptions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skorpil.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smaltimentoamianto.campania.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smartphone-pliable.wtf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "snwsjz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "socialmedia-manager.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sonaraamat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "southwesteventhire.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sozialstation-ritterhude.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spalnobelyo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spanch.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stgabrielavondalepa.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stoerevrouwensporten.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stretchmarkdestroyer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "studio-n.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "suchem.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "superenduro.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "suppwatch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "svenrath.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sweetenedcondensed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "systemctl.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tandartszilverschoon.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tease.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "techlr.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tedxyalesecondaryschool.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "telsu.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "testeri.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thea-team.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thealonas.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "theappliancedepot.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thecandyjam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thedermreport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thefriedzombie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "theseoplatform.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thesetwohands864.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thoxyn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tomorrowmuseum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "topyachts.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tovaglioli-di-carta.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tql.plus", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tracker.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tradexport.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tradexport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "transferbags.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trinitycorporateservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "troxal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "truecosmeticbeauty.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trustees.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tryplo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tryplo.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tryplo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tryplo.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "turingmind.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tusmedicamentos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "twoleftsticks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "u-chan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "u29dc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uitvaartvrouwenfriesland.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ukrn.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ummati.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "unicmotos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "unkn0wncat.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "upcloud.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uscis.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "valimised.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "valuehost.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "veggiesecret.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "velassoltas.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vexsoluciones.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "virtualizy.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vista-research-group.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "viviendy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "w3n14izy.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "weymouthslowik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wijnimportjanssen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "witch-spells.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wordnietvindbaar.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "worldsy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wsp-center.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ww-design.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wzilverschoon.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xavierdmello.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xgwap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xi.ht", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn-----6kcbjcgl1atjj7aadbkxfxfe7a9yia.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--12c3bpr6bsv7c.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--3st814ec8r.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--3stv82k.hk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--3stv82k.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--bersetzung-8db.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--durhre-yxa.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yachtlettering.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yateshomesales.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yesornut.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yolandgao.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yuhindo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zadania.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zeno-dev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zhang.ge", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zhina.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zistemo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zxssl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, // END OF 1-YEAR BULK HSTS ENTRIES // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/services/content/public/cpp/navigable_contents.cc b/services/content/public/cpp/navigable_contents.cc index 791cb27..6a0e715 100644 --- a/services/content/public/cpp/navigable_contents.cc +++ b/services/content/public/cpp/navigable_contents.cc
@@ -65,6 +65,11 @@ contents_->FocusThroughTabTraversal(reverse); } +void NavigableContents::ClearViewFocus() { + if (view_) + view_->ClearNativeFocus(); +} + void NavigableContents::DidFinishNavigation( const GURL& url, bool is_main_frame,
diff --git a/services/content/public/cpp/navigable_contents.h b/services/content/public/cpp/navigable_contents.h index 0f9772a..ae675b0 100644 --- a/services/content/public/cpp/navigable_contents.h +++ b/services/content/public/cpp/navigable_contents.h
@@ -71,6 +71,7 @@ private: // mojom::NavigableContentsClient: + void ClearViewFocus() override; void DidFinishNavigation( const GURL& url, bool is_main_frame,
diff --git a/services/content/public/cpp/navigable_contents_view.cc b/services/content/public/cpp/navigable_contents_view.cc index 502b7a90..8c1ef02 100644 --- a/services/content/public/cpp/navigable_contents_view.cc +++ b/services/content/public/cpp/navigable_contents_view.cc
@@ -17,6 +17,7 @@ #include "ui/accessibility/ax_node_data.h" #if defined(TOOLKIT_VIEWS) +#include "ui/views/focus/focus_manager.h" // nogncheck #include "ui/views/layout/fill_layout.h" // nogncheck #include "ui/views/view.h" // nogncheck @@ -145,6 +146,14 @@ return GetInServiceProcessFlag().IsSet(); } +void NavigableContentsView::ClearNativeFocus() { +#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) + auto* focus_manager = view_->GetFocusManager(); + if (focus_manager) + focus_manager->ClearNativeFocus(); +#endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) +} + void NavigableContentsView::NotifyAccessibilityTreeChange() { #if defined(TOOLKIT_VIEWS) && defined(USE_AURA) view_->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false);
diff --git a/services/content/public/cpp/navigable_contents_view.h b/services/content/public/cpp/navigable_contents_view.h index 8900ac7..30a2913 100644 --- a/services/content/public/cpp/navigable_contents_view.h +++ b/services/content/public/cpp/navigable_contents_view.h
@@ -78,6 +78,9 @@ gfx::NativeView native_view() const { return view_->native_view(); } #endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) + // Clears the native view having focus. See FocusManager::ClearNativeFocus. + void ClearNativeFocus(); + // Has this view notify the UI subsystem of an accessibility tree change. void NotifyAccessibilityTreeChange();
diff --git a/services/content/public/mojom/navigable_contents.mojom b/services/content/public/mojom/navigable_contents.mojom index abbdfe4..d90f305 100644 --- a/services/content/public/mojom/navigable_contents.mojom +++ b/services/content/public/mojom/navigable_contents.mojom
@@ -59,6 +59,9 @@ // A client interface used by the Content Service to push contents-scoped events // back to the application. interface NavigableContentsClient { + // Requests that the client relinquish focus from the content area's view. + ClearViewFocus(); + // Notifies the client that a navigation has finished. DidFinishNavigation(url.mojom.Url url, bool is_main_frame,
diff --git a/services/content/service_unittest.cc b/services/content/service_unittest.cc index 04bf305..c6c2aab 100644 --- a/services/content/service_unittest.cc +++ b/services/content/service_unittest.cc
@@ -30,6 +30,7 @@ private: // mojom::NavigableContentsClient: + void ClearViewFocus() override {} void DidFinishNavigation(const GURL& url, bool is_main_frame, bool is_error_page,
diff --git a/services/device/fingerprint/fingerprint_chromeos.cc b/services/device/fingerprint/fingerprint_chromeos.cc index 28a5e27..07173d2 100644 --- a/services/device/fingerprint/fingerprint_chromeos.cc +++ b/services/device/fingerprint/fingerprint_chromeos.cc
@@ -115,11 +115,6 @@ if (!result) return; - ScheduleStartEnroll(user_id, label); -} - -void FingerprintChromeOS::ScheduleStartEnroll(const std::string& user_id, - const std::string& label) { GetBiodClient()->StartEnrollSession( user_id, label, base::Bind(&FingerprintChromeOS::OnStartEnrollSession, @@ -166,7 +161,9 @@ base::BindRepeating(&FingerprintChromeOS::OnCloseEnrollSessionForAuth, weak_ptr_factory_.GetWeakPtr())); } else { - ScheduleStartAuth(); + GetBiodClient()->StartAuthSession( + base::Bind(&FingerprintChromeOS::OnStartAuthSession, + weak_ptr_factory_.GetWeakPtr())); } } @@ -174,10 +171,6 @@ if (!result) return; - ScheduleStartAuth(); -} - -void FingerprintChromeOS::ScheduleStartAuth() { GetBiodClient()->StartAuthSession( base::Bind(&FingerprintChromeOS::OnStartAuthSession, weak_ptr_factory_.GetWeakPtr()));
diff --git a/services/device/fingerprint/fingerprint_chromeos.h b/services/device/fingerprint/fingerprint_chromeos.h index 8f2623d1f..5d92809c 100644 --- a/services/device/fingerprint/fingerprint_chromeos.h +++ b/services/device/fingerprint/fingerprint_chromeos.h
@@ -79,9 +79,6 @@ void OnCloseAuthSessionForEnroll(const std::string& user_id, const std::string& label, bool result); - void ScheduleStartEnroll(const std::string& user_id, - const std::string& label); - void ScheduleStartAuth(); void RunGetRecordsForUser(const std::string& user_id, GetRecordsForUserCallback callback);
diff --git a/services/media_session/media_controller.cc b/services/media_session/media_controller.cc index 4d48b59..19afe2c 100644 --- a/services/media_session/media_controller.cc +++ b/services/media_session/media_controller.cc
@@ -49,13 +49,11 @@ } } -void MediaController::AddObserver(mojom::MediaSessionObserverPtr observer) { +void MediaController::AddObserver(mojom::MediaControllerObserverPtr observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Flush the new observer with the state. We always flush the metadata as that - // is optional so null is a valid value whereas the session info is required. - if (!session_info_.is_null()) - observer->MediaSessionInfoChanged(session_info_.Clone()); + // Flush the new observer with the current state. + observer->MediaSessionInfoChanged(session_info_.Clone()); observer->MediaSessionMetadataChanged(session_metadata_); observer->MediaSessionActionsChanged(session_actions_); @@ -65,7 +63,7 @@ void MediaController::MediaSessionInfoChanged(mojom::MediaSessionInfoPtr info) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - observers_.ForAllPtrs([&info](mojom::MediaSessionObserver* observer) { + observers_.ForAllPtrs([&info](mojom::MediaControllerObserver* observer) { observer->MediaSessionInfoChanged(info.Clone()); }); @@ -76,7 +74,7 @@ const base::Optional<MediaMetadata>& metadata) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - observers_.ForAllPtrs([&metadata](mojom::MediaSessionObserver* observer) { + observers_.ForAllPtrs([&metadata](mojom::MediaControllerObserver* observer) { observer->MediaSessionMetadataChanged(metadata); }); @@ -87,7 +85,7 @@ const std::vector<mojom::MediaSessionAction>& actions) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - observers_.ForAllPtrs([&actions](mojom::MediaSessionObserver* observer) { + observers_.ForAllPtrs([&actions](mojom::MediaControllerObserver* observer) { observer->MediaSessionActionsChanged(actions); }); @@ -131,6 +129,15 @@ mojom::MediaSessionObserverPtr observer; session_binding_.Bind(mojo::MakeRequest(&observer)); session->AddObserver(std::move(observer)); + } else { + // If we are no longer bound to a session we should flush the observers + // with empty data. + observers_.ForAllPtrs([](mojom::MediaControllerObserver* observer) { + observer->MediaSessionInfoChanged(nullptr); + observer->MediaSessionMetadataChanged(base::nullopt); + observer->MediaSessionActionsChanged( + std::vector<mojom::MediaSessionAction>()); + }); } }
diff --git a/services/media_session/media_controller.h b/services/media_session/media_controller.h index 0cf05d70..7cb0b0e 100644 --- a/services/media_session/media_controller.h +++ b/services/media_session/media_controller.h
@@ -33,7 +33,7 @@ void Resume() override; void Stop() override; void ToggleSuspendResume() override; - void AddObserver(mojom::MediaSessionObserverPtr observer) override; + void AddObserver(mojom::MediaControllerObserverPtr observer) override; void PreviousTrack() override; void NextTrack() override; void Seek(base::TimeDelta seek_time) override; @@ -70,8 +70,8 @@ // the underlying MediaSession. mojom::MediaSession* session_ = nullptr; - // Observers that are observing |session_|. - mojo::InterfacePtrSet<mojom::MediaSessionObserver> observers_; + // Observers that are observing |this|. + mojo::InterfacePtrSet<mojom::MediaControllerObserver> observers_; // Binding for |this| to act as an observer to |session_|. mojo::Binding<mojom::MediaSessionObserver> session_binding_{this};
diff --git a/services/media_session/media_controller_unittest.cc b/services/media_session/media_controller_unittest.cc index 16a15db8..9e2f0d2 100644 --- a/services/media_session/media_controller_unittest.cc +++ b/services/media_session/media_controller_unittest.cc
@@ -16,6 +16,7 @@ #include "services/media_session/media_session_service.h" #include "services/media_session/public/cpp/media_metadata.h" #include "services/media_session/public/cpp/test/mock_media_session.h" +#include "services/media_session/public/cpp/test/test_media_controller.h" #include "services/media_session/public/mojom/constants.mojom.h" #include "services/service_manager/public/cpp/test/test_connector_factory.h" #include "testing/gtest/include/gtest/gtest.h" @@ -416,18 +417,18 @@ } { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive); } { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); controller()->Suspend(); observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended); } { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain); observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive); } @@ -439,7 +440,7 @@ } { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive); } } @@ -523,8 +524,8 @@ media_session.AbandonAudioFocusFromClient(); { - test::MockMediaSessionMojoObserver observer(controller()); - EXPECT_FALSE(observer.WaitForMetadata()); + test::TestMediaControllerObserver observer(controller()); + observer.WaitForEmptyMetadata(); } } @@ -541,9 +542,9 @@ } { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); media_session.SimulateMetadataChanged(test_metadata); - EXPECT_EQ(test_metadata, observer.WaitForMetadata()); + observer.WaitForEmptyMetadata(); } } @@ -565,9 +566,10 @@ } { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); media_session.SimulateMetadataChanged(test_metadata); - EXPECT_EQ(metadata, observer.WaitForNonEmptyMetadata()); + observer.WaitForNonEmptyMetadata(); + EXPECT_EQ(metadata, observer.session_metadata()); } } @@ -586,8 +588,8 @@ media_session.SimulateMetadataChanged(test_metadata); { - test::MockMediaSessionMojoObserver observer(controller()); - EXPECT_EQ(test_metadata, observer.WaitForMetadata()); + test::TestMediaControllerObserver observer(controller()); + observer.WaitForEmptyMetadata(); } } @@ -611,8 +613,9 @@ media_session.SimulateMetadataChanged(test_metadata); { - test::MockMediaSessionMojoObserver observer(controller()); - EXPECT_EQ(metadata, *observer.WaitForMetadata()); + test::TestMediaControllerObserver observer(controller()); + observer.WaitForNonEmptyMetadata(); + EXPECT_EQ(metadata, observer.session_metadata()); } } @@ -740,7 +743,7 @@ } { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); observer.WaitForActions(); EXPECT_TRUE(observer.actions().empty()); } @@ -759,7 +762,7 @@ media_session.EnableAction(mojom::MediaSessionAction::kPlay); { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); observer.WaitForActions(); EXPECT_EQ(1u, observer.actions().size()); @@ -779,9 +782,7 @@ } { - test::MockMediaSessionMojoObserver observer(controller()); - observer.WaitForActions(); - + test::TestMediaControllerObserver observer(controller()); media_session.DisableAction(mojom::MediaSessionAction::kPlay); observer.WaitForActions(); @@ -800,9 +801,7 @@ } { - test::MockMediaSessionMojoObserver observer(controller()); - observer.WaitForActions(); - + test::TestMediaControllerObserver observer(controller()); media_session.EnableAction(mojom::MediaSessionAction::kPlay); observer.WaitForActions(); @@ -825,7 +824,54 @@ media_session.AbandonAudioFocusFromClient(); { - test::MockMediaSessionMojoObserver observer(controller()); + test::TestMediaControllerObserver observer(controller()); + observer.WaitForActions(); + EXPECT_TRUE(observer.actions().empty()); + } +} + +TEST_F(MediaControllerTest, ActiveController_Observer_Abandoned) { + test::MockMediaSession media_session; + media_session.SetIsControllable(true); + + { + test::MockMediaSessionMojoObserver observer(media_session); + RequestAudioFocus(media_session, mojom::AudioFocusType::kGain); + observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive); + } + + { + test::TestMediaControllerObserver observer(controller()); + media_session.AbandonAudioFocusFromClient(); + + // We should see empty info, metadata and actions flushed since the active + // controller is no longer bound to a media session. + observer.WaitForEmptyInfo(); + observer.WaitForEmptyMetadata(); + observer.WaitForActions(); + EXPECT_TRUE(observer.actions().empty()); + } +} + +TEST_F(MediaControllerTest, ActiveController_AddObserver_Abandoned) { + test::MockMediaSession media_session; + media_session.SetIsControllable(true); + + { + test::MockMediaSessionMojoObserver observer(media_session); + RequestAudioFocus(media_session, mojom::AudioFocusType::kGain); + observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive); + } + + media_session.AbandonAudioFocusFromClient(); + + { + test::TestMediaControllerObserver observer(controller()); + + // We should see empty info, metadata and actions since the active + // controller is no longer bound to a media session. + observer.WaitForEmptyInfo(); + observer.WaitForEmptyMetadata(); observer.WaitForActions(); EXPECT_TRUE(observer.actions().empty()); }
diff --git a/services/media_session/public/cpp/media_metadata.cc b/services/media_session/public/cpp/media_metadata.cc index 0d07d04e8..42ed11b 100644 --- a/services/media_session/public/cpp/media_metadata.cc +++ b/services/media_session/public/cpp/media_metadata.cc
@@ -36,4 +36,9 @@ return !(*this == other); } +bool MediaMetadata::IsEmpty() const { + return title.empty() && artist.empty() && album.empty() && + source_title.empty() && artwork.empty(); +} + } // namespace media_session
diff --git a/services/media_session/public/cpp/media_metadata.h b/services/media_session/public/cpp/media_metadata.h index 6716521..f209927c 100644 --- a/services/media_session/public/cpp/media_metadata.h +++ b/services/media_session/public/cpp/media_metadata.h
@@ -80,6 +80,9 @@ // session. This could be the name of the app or the name of the site playing // media. base::string16 source_title; + + // Returns whether |this| contains no metadata. + bool IsEmpty() const; }; } // namespace media_session
diff --git a/services/media_session/public/cpp/test/mock_media_session.cc b/services/media_session/public/cpp/test/mock_media_session.cc index 92f2ece1..b3ccd79 100644 --- a/services/media_session/public/cpp/test/mock_media_session.cc +++ b/services/media_session/public/cpp/test/mock_media_session.cc
@@ -12,19 +12,6 @@ namespace media_session { namespace test { -namespace { - -bool IsMetadataNonEmpty(const base::Optional<MediaMetadata>& metadata) { - if (!metadata.has_value()) - return false; - - return !metadata->title.empty() || !metadata->artist.empty() || - !metadata->album.empty() || !metadata->source_title.empty() || - !metadata->artwork.empty(); -} - -} // namespace - MockMediaSessionMojoObserver::MockMediaSessionMojoObserver( mojom::MediaSession& media_session) : binding_(this) { @@ -33,14 +20,6 @@ media_session.AddObserver(std::move(observer)); } -MockMediaSessionMojoObserver::MockMediaSessionMojoObserver( - mojom::MediaControllerPtr& controller) - : binding_(this) { - mojom::MediaSessionObserverPtr observer; - binding_.Bind(mojo::MakeRequest(&observer)); - controller->AddObserver(std::move(observer)); -} - MockMediaSessionMojoObserver::~MockMediaSessionMojoObserver() = default; void MockMediaSessionMojoObserver::MediaSessionInfoChanged( @@ -60,7 +39,8 @@ if (waiting_for_metadata_) { run_loop_->Quit(); waiting_for_metadata_ = false; - } else if (waiting_for_non_empty_metadata_ && IsMetadataNonEmpty(metadata)) { + } else if (waiting_for_non_empty_metadata_ && metadata.has_value() && + !metadata->IsEmpty()) { run_loop_->Quit(); waiting_for_non_empty_metadata_ = false; }
diff --git a/services/media_session/public/cpp/test/mock_media_session.h b/services/media_session/public/cpp/test/mock_media_session.h index 904e7d1..a226ffa 100644 --- a/services/media_session/public/cpp/test/mock_media_session.h +++ b/services/media_session/public/cpp/test/mock_media_session.h
@@ -27,10 +27,7 @@ class COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP) MockMediaSessionMojoObserver : public mojom::MediaSessionObserver { public: - // A MediaSessionObserver can observe a MediaSession directly or through a - // MediaController. explicit MockMediaSessionMojoObserver(mojom::MediaSession& media_session); - explicit MockMediaSessionMojoObserver(mojom::MediaControllerPtr& controller); ~MockMediaSessionMojoObserver() override;
diff --git a/services/media_session/public/cpp/test/test_media_controller.cc b/services/media_session/public/cpp/test/test_media_controller.cc index 0d8de275..905c153 100644 --- a/services/media_session/public/cpp/test/test_media_controller.cc +++ b/services/media_session/public/cpp/test/test_media_controller.cc
@@ -7,6 +7,116 @@ namespace media_session { namespace test { +TestMediaControllerObserver::TestMediaControllerObserver( + mojom::MediaControllerPtr& media_controller) + : binding_(this) { + mojom::MediaControllerObserverPtr observer; + binding_.Bind(mojo::MakeRequest(&observer)); + media_controller->AddObserver(std::move(observer)); +} + +TestMediaControllerObserver::~TestMediaControllerObserver() = default; + +void TestMediaControllerObserver::MediaSessionInfoChanged( + mojom::MediaSessionInfoPtr session) { + session_info_ = std::move(session); + + if (session_info_.has_value() && !session_info_->is_null()) { + if (wanted_state_ == session_info()->state || + session_info()->playback_state == wanted_playback_state_) { + run_loop_->Quit(); + } + } else if (waiting_for_empty_info_) { + waiting_for_empty_info_ = false; + run_loop_->Quit(); + } +} + +void TestMediaControllerObserver::MediaSessionMetadataChanged( + const base::Optional<MediaMetadata>& metadata) { + session_metadata_ = metadata; + + if (waiting_for_empty_metadata_ && + (!metadata.has_value() || metadata->IsEmpty())) { + run_loop_->Quit(); + waiting_for_empty_metadata_ = false; + } else if (waiting_for_non_empty_metadata_ && metadata.has_value() && + !metadata->IsEmpty()) { + run_loop_->Quit(); + waiting_for_non_empty_metadata_ = false; + } +} + +void TestMediaControllerObserver::MediaSessionActionsChanged( + const std::vector<mojom::MediaSessionAction>& actions) { + session_actions_ = actions; + session_actions_set_ = + std::set<mojom::MediaSessionAction>(actions.begin(), actions.end()); + + if (waiting_for_actions_) { + run_loop_->Quit(); + waiting_for_actions_ = false; + } +} + +void TestMediaControllerObserver::WaitForState( + mojom::MediaSessionInfo::SessionState wanted_state) { + if (session_info_ && session_info()->state == wanted_state) + return; + + wanted_state_ = wanted_state; + StartWaiting(); +} + +void TestMediaControllerObserver::WaitForPlaybackState( + mojom::MediaPlaybackState wanted_state) { + if (session_info_ && session_info()->playback_state == wanted_state) + return; + + wanted_playback_state_ = wanted_state; + StartWaiting(); +} + +void TestMediaControllerObserver::WaitForEmptyInfo() { + if (session_info_.has_value() && session_info_->is_null()) + return; + + waiting_for_empty_info_ = true; + StartWaiting(); +} + +void TestMediaControllerObserver::WaitForEmptyMetadata() { + if (session_metadata_.has_value()) + return; + + waiting_for_empty_metadata_ = true; + StartWaiting(); +} + +void TestMediaControllerObserver::WaitForNonEmptyMetadata() { + if (session_metadata_.has_value() && !session_metadata_.value()->IsEmpty()) + return; + + waiting_for_non_empty_metadata_ = true; + StartWaiting(); +} + +void TestMediaControllerObserver::WaitForActions() { + if (session_actions_.has_value()) + return; + + waiting_for_actions_ = true; + StartWaiting(); +} + +void TestMediaControllerObserver::StartWaiting() { + DCHECK(!run_loop_); + + run_loop_ = std::make_unique<base::RunLoop>(); + run_loop_->Run(); + run_loop_.reset(); +} + TestMediaController::TestMediaController() = default; TestMediaController::~TestMediaController() = default; @@ -29,7 +139,8 @@ ++toggle_suspend_resume_count_; } -void TestMediaController::AddObserver(mojom::MediaSessionObserverPtr observer) { +void TestMediaController::AddObserver( + mojom::MediaControllerObserverPtr observer) { ++add_observer_count_; observers_.AddPtr(std::move(observer)); } @@ -54,7 +165,7 @@ void TestMediaController::SimulateMediaSessionActionsChanged( const std::vector<mojom::MediaSessionAction>& actions) { - observers_.ForAllPtrs([&actions](mojom::MediaSessionObserver* observer) { + observers_.ForAllPtrs([&actions](mojom::MediaControllerObserver* observer) { observer->MediaSessionActionsChanged(actions); }); }
diff --git a/services/media_session/public/cpp/test/test_media_controller.h b/services/media_session/public/cpp/test/test_media_controller.h index bc24564..8801a67d 100644 --- a/services/media_session/public/cpp/test/test_media_controller.h +++ b/services/media_session/public/cpp/test/test_media_controller.h
@@ -6,6 +6,7 @@ #define SERVICES_MEDIA_SESSION_PUBLIC_CPP_TEST_TEST_MEDIA_CONTROLLER_H_ #include "base/component_export.h" +#include "base/run_loop.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" #include "services/media_session/public/mojom/media_controller.mojom.h" @@ -13,6 +14,70 @@ namespace media_session { namespace test { +// A mock MediaControllerObsever that can be used for waiting for state changes. +class COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP) + TestMediaControllerObserver : public mojom::MediaControllerObserver { + public: + explicit TestMediaControllerObserver( + mojom::MediaControllerPtr& media_controller); + + ~TestMediaControllerObserver() override; + + // mojom::MediaControllerObserver overrides. + void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr session) override; + void MediaSessionMetadataChanged( + const base::Optional<MediaMetadata>& metadata) override; + void MediaSessionActionsChanged( + const std::vector<mojom::MediaSessionAction>& actions) override; + + void WaitForState(mojom::MediaSessionInfo::SessionState wanted_state); + void WaitForPlaybackState(mojom::MediaPlaybackState wanted_state); + void WaitForEmptyInfo(); + + void WaitForEmptyMetadata(); + void WaitForNonEmptyMetadata(); + + void WaitForActions(); + + const mojom::MediaSessionInfoPtr& session_info() const { + return *session_info_; + } + + const base::Optional<base::Optional<MediaMetadata>>& session_metadata() + const { + return session_metadata_; + } + + const std::vector<mojom::MediaSessionAction>& actions() const { + return *session_actions_; + } + + const std::set<mojom::MediaSessionAction>& actions_set() const { + return session_actions_set_; + } + + private: + void StartWaiting(); + + base::Optional<mojom::MediaSessionInfoPtr> session_info_; + base::Optional<base::Optional<MediaMetadata>> session_metadata_; + base::Optional<std::vector<mojom::MediaSessionAction>> session_actions_; + std::set<mojom::MediaSessionAction> session_actions_set_; + + bool waiting_for_empty_metadata_ = false; + bool waiting_for_non_empty_metadata_ = false; + + bool waiting_for_actions_ = false; + + bool waiting_for_empty_info_ = false; + base::Optional<mojom::MediaSessionInfo::SessionState> wanted_state_; + base::Optional<mojom::MediaPlaybackState> wanted_playback_state_; + + std::unique_ptr<base::RunLoop> run_loop_; + + mojo::Binding<mojom::MediaControllerObserver> binding_; +}; + // Implements the MediaController mojo interface for tests. class COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP) TestMediaController : public mojom::MediaController { @@ -27,7 +92,7 @@ void Resume() override; void Stop() override {} void ToggleSuspendResume() override; - void AddObserver(mojom::MediaSessionObserverPtr observer) override; + void AddObserver(mojom::MediaControllerObserverPtr observer) override; void PreviousTrack() override; void NextTrack() override; void Seek(base::TimeDelta seek_time) override; @@ -58,7 +123,7 @@ int seek_backward_count_ = 0; int seek_forward_count_ = 0; - mojo::InterfacePtrSet<mojom::MediaSessionObserver> observers_; + mojo::InterfacePtrSet<mojom::MediaControllerObserver> observers_; mojo::Binding<mojom::MediaController> binding_{this};
diff --git a/services/media_session/public/mojom/media_controller.mojom b/services/media_session/public/mojom/media_controller.mojom index 07a854b3..2aa9af7b 100644 --- a/services/media_session/public/mojom/media_controller.mojom +++ b/services/media_session/public/mojom/media_controller.mojom
@@ -40,7 +40,7 @@ // Adds an observer that will forward events from the active media session. // If the active session changes then observers do not need to be readded. // Adding the observer will update the observer with the latest state. - AddObserver(MediaSessionObserver observer); + AddObserver(MediaControllerObserver observer); // Skip to the previous track. If there is no previous track then this will be // a no-op. @@ -57,3 +57,22 @@ // few seconds. Seek(mojo_base.mojom.TimeDelta seek_time); }; + +// The observer for observing media controller events. This is different to a +// MediaSessionObserver because a media controller can have nullable session +// info which will be null if it is not bound to a media session. This would +// be invalid for a media session because it must always have some state. +interface MediaControllerObserver { + // Called when the state of the bound media session changes. If |info| is + // empty then the controller is no longer bound to a media session. + MediaSessionInfoChanged(MediaSessionInfo? info); + + // Called when the bound media session has changed metadata. If |metadata| + // is null then it can be reset, e.g. the media that ws being played has + // been stopped. + MediaSessionMetadataChanged(MediaMetadata? metadata); + + // Called when the bound media session action list has changed. This tells + // the observer which actions can be used to control the session. + MediaSessionActionsChanged(array<MediaSessionAction> action); +};
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index deda168..1cd4aad 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -12,8 +12,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" -#include "base/debug/alias.h" -#include "base/debug/dump_without_crashing.h" #include "base/files/file.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" @@ -52,16 +50,12 @@ namespace network { namespace { - constexpr size_t kDefaultAllocationSize = 512 * 1024; // Cannot use 0, because this means "default" in // mojo::core::Core::CreateDataPipe constexpr size_t kBlockedBodyAllocationSize = 1; -// Used to dump when we get too many requests, once. -bool g_reported_too_many_requests = false; - // TODO: this duplicates some of PopulateResourceResponse in // content/browser/loader/resource_loader.cc void PopulateResourceResponse(net::URLRequest* request, @@ -445,18 +439,6 @@ if (keepalive_ && keepalive_statistics_recorder_) keepalive_statistics_recorder_->OnLoadStarted(factory_params_->process_id); - // Record some debug info in hope of tracing down leaks. - int32_t annotation_hash = - url_request_->traffic_annotation().unique_id_hash_code; - size_t num_running_requests = url_request_context_->url_requests()->size(); - base::debug::Alias(&annotation_hash); - base::debug::Alias(&num_running_requests); - DEBUG_ALIAS_FOR_GURL(url_buf, url_request_->url()); - if (!g_reported_too_many_requests && num_running_requests > 10000) { - g_reported_too_many_requests = true; - base::debug::DumpWithoutCrashing(); - } - // Resolve elements from request_body and prepare upload data. if (request.request_body.get()) { OpenFilesForUpload(request);
diff --git a/services/ws/ime/ime_unittest.cc b/services/ws/ime/ime_unittest.cc index b9031e1..6ac270a 100644 --- a/services/ws/ime/ime_unittest.cc +++ b/services/ws/ime/ime_unittest.cc
@@ -17,7 +17,7 @@ #include "services/ws/ime/test_ime_driver/public/mojom/constants.mojom.h" #include "services/ws/public/mojom/constants.mojom.h" #include "services/ws/public/mojom/ime/ime.mojom.h" -#include "services/ws/test_ws/manifest.h" +#include "services/ws/test_ws/test_manifest.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/event.h" #include "ui/events/keycodes/dom/dom_code.h"
diff --git a/services/ws/test_ws/BUILD.gn b/services/ws/test_ws/BUILD.gn index ac94174..710801dd 100644 --- a/services/ws/test_ws/BUILD.gn +++ b/services/ws/test_ws/BUILD.gn
@@ -54,12 +54,19 @@ ] } -service_manifest("manifest") { +source_set("manifest") { testonly = true - - name = "test_ws" - source = "manifest.json" - packaged_services = [ "//services/ws:manifest" ] + sources = [ + "test_manifest.cc", + "test_manifest.h", + ] + deps = [ + ":mojom", + "//base", + "//services/service_manager/public/cpp", + "//services/service_manager/public/mojom", + "//services/ws:manifest", + ] } mojom("mojom") {
diff --git a/services/ws/test_ws/manifest.json b/services/ws/test_ws/manifest.json deleted file mode 100644 index b1ea0bd9..0000000 --- a/services/ws/test_ws/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "test_ws", - "sandbox_type": "none", - "display_name": "Test Window Service", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "service_manager:service_factory": [ - "service_manager.mojom.ServiceFactory" - ], - "test": [ - "test_ws.mojom.TestWs" - ] - } - } - } -}
diff --git a/services/ws/test_ws/test_manifest.cc b/services/ws/test_ws/test_manifest.cc new file mode 100644 index 0000000..58dcb8d --- /dev/null +++ b/services/ws/test_ws/test_manifest.cc
@@ -0,0 +1,33 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/ws/test_ws/test_manifest.h" + +#include "base/no_destructor.h" +#include "services/service_manager/public/cpp/manifest_builder.h" +#include "services/service_manager/public/mojom/service_factory.mojom.h" +#include "services/ws/manifest.h" +#include "services/ws/test_ws/test_ws.mojom.h" + +namespace test_ws { + +const service_manager::Manifest& GetManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .WithServiceName(mojom::kServiceName) + .WithDisplayName("Test Window Service") + .WithOptions(service_manager::ManifestOptionsBuilder() + .WithSandboxType("none") + .Build()) + .ExposeCapability( + "test", service_manager::Manifest::InterfaceList<mojom::TestWs>()) + .ExposeCapability("service_manager:service_factory", + service_manager::Manifest::InterfaceList< + service_manager::mojom::ServiceFactory>()) + .PackageService(ui::GetManifest()) + .Build()}; + return *manifest; +} + +} // namespace test_ws
diff --git a/services/ws/test_ws/test_manifest.h b/services/ws/test_ws/test_manifest.h new file mode 100644 index 0000000..a9115db --- /dev/null +++ b/services/ws/test_ws/test_manifest.h
@@ -0,0 +1,16 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_WS_TEST_WS_TEST_MANIFEST_H_ +#define SERVICES_WS_TEST_WS_TEST_MANIFEST_H_ + +#include "services/service_manager/public/cpp/manifest.h" + +namespace test_ws { + +const service_manager::Manifest& GetManifest(); + +} // namespace test_ws + +#endif // SERVICES_WS_TEST_WS_TEST_MANIFEST_H_
diff --git a/services/ws/window_server_service_test_base.cc b/services/ws/window_server_service_test_base.cc index c6245b0d..1caa360 100644 --- a/services/ws/window_server_service_test_base.cc +++ b/services/ws/window_server_service_test_base.cc
@@ -12,7 +12,7 @@ #include "services/ws/common/switches.h" #include "services/ws/public/mojom/constants.mojom.h" #include "services/ws/public/mojom/window_tree.mojom.h" -#include "services/ws/test_ws/manifest.h" +#include "services/ws/test_ws/test_manifest.h" #include "ui/gl/gl_switches.h" namespace ws {
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index a51c431..a92c1014 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -23694,6 +23694,9 @@ ], "isolated_scripts": [ { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index e4fe884..9334f2f 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -13696,6 +13696,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -13754,6 +13757,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 428c4cd5..f1b61b1 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -891,6 +891,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -949,6 +952,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -6654,6 +6660,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -10805,6 +10814,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -12220,6 +12232,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -12320,6 +12335,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 7347cb3..99dd07e 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -206,10 +206,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -682,10 +689,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -728,12 +742,19 @@ }, { "args": [ + "--gtest-benchmark-name=passthrough_command_buffer_perftests", "-v", "--use-cmd-decoder=passthrough", "--use-angle=gl-null", "--fast-run" ], "isolate_name": "command_buffer_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "passthrough_command_buffer_perftests", "should_retry_with_patch": false, "swarming": { @@ -749,12 +770,19 @@ }, { "args": [ + "--gtest-benchmark-name=validating_command_buffer_perftests", "-v", "--use-cmd-decoder=validating", "--use-stub", "--fast-run" ], "isolate_name": "command_buffer_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "validating_command_buffer_perftests", "should_retry_with_patch": false, "swarming": { @@ -1055,11 +1083,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -1154,11 +1189,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -1253,11 +1295,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -1487,11 +1536,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -1586,11 +1642,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -1685,11 +1748,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -2024,11 +2094,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -2825,11 +2902,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -3749,11 +3833,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -4195,11 +4286,18 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only", "--shard-timeout=500" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -5383,10 +5481,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -5890,10 +5995,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -7070,10 +7182,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -14569,10 +14688,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -15324,10 +15450,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -15864,10 +15997,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -15928,12 +16068,19 @@ }, { "args": [ + "--gtest-benchmark-name=passthrough_command_buffer_perftests", "-v", "--use-cmd-decoder=passthrough", "--use-angle=gl-null", "--fast-run" ], "isolate_name": "command_buffer_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "passthrough_command_buffer_perftests", "should_retry_with_patch": false, "swarming": { @@ -15958,12 +16105,19 @@ }, { "args": [ + "--gtest-benchmark-name=validating_command_buffer_perftests", "-v", "--use-cmd-decoder=validating", "--use-stub", "--fast-run" ], "isolate_name": "command_buffer_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "validating_command_buffer_perftests", "should_retry_with_patch": false, "swarming": { @@ -17195,10 +17349,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -18031,10 +18192,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -19000,10 +19168,17 @@ "isolated_scripts": [ { "args": [ + "--gtest-benchmark-name=angle_perftests", "-v", "--one-frame-only" ], "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "angle_perftests", "swarming": { "can_use_on_swarming_builders": true, @@ -19236,12 +19411,19 @@ }, { "args": [ + "--gtest-benchmark-name=passthrough_command_buffer_perftests", "-v", "--use-cmd-decoder=passthrough", "--use-angle=gl-null", "--fast-run" ], "isolate_name": "command_buffer_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "passthrough_command_buffer_perftests", "should_retry_with_patch": false, "swarming": { @@ -19381,12 +19563,19 @@ }, { "args": [ + "--gtest-benchmark-name=validating_command_buffer_perftests", "-v", "--use-cmd-decoder=validating", "--use-stub", "--fast-run" ], "isolate_name": "command_buffer_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, "name": "validating_command_buffer_perftests", "should_retry_with_patch": false, "swarming": {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 52f54cc..249c697 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -1731,6 +1731,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -2447,6 +2450,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -3119,6 +3125,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -4375,6 +4384,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 350713f..88d47af 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -995,6 +995,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -1092,6 +1095,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -2133,6 +2139,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -2230,6 +2239,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -3354,6 +3366,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -3451,6 +3466,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -4492,6 +4510,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -4570,6 +4591,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -5679,6 +5703,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index c95e65de..0aa98c44 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -6,9 +6,7 @@ { "args": [ "--gtest-benchmark-name", - "components_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "components_perftests" ], "isolate_name": "components_perftests", "merge": { @@ -47,9 +45,7 @@ { "args": [ "--gtest-benchmark-name", - "gpu_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "gpu_perftests" ], "isolate_name": "gpu_perftests", "merge": { @@ -88,9 +84,7 @@ { "args": [ "--gtest-benchmark-name", - "tracing_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "tracing_perftests" ], "isolate_name": "tracing_perftests", "merge": { @@ -270,9 +264,7 @@ { "args": [ "--gtest-benchmark-name", - "angle_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "angle_perftests" ], "isolate_name": "angle_perftests", "merge": { @@ -309,9 +301,7 @@ { "args": [ "--gtest-benchmark-name", - "load_library_perf_tests", - "--non-telemetry=true", - "--migrated-test=true" + "load_library_perf_tests" ], "isolate_name": "load_library_perf_tests", "merge": { @@ -348,9 +338,7 @@ { "args": [ "--gtest-benchmark-name", - "media_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "media_perftests" ], "isolate_name": "media_perftests", "merge": { @@ -388,8 +376,6 @@ "args": [ "--gtest-benchmark-name", "passthrough_command_buffer_perftests", - "--non-telemetry=true", - "--migrated-test=true", "--use-cmd-decoder=passthrough", "--use-angle=gl-null" ], @@ -429,8 +415,6 @@ "args": [ "--gtest-benchmark-name", "validating_command_buffer_perftests", - "--non-telemetry=true", - "--migrated-test=true", "--use-cmd-decoder=validating", "--use-stub" ], @@ -514,9 +498,7 @@ { "args": [ "--gtest-benchmark-name", - "components_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "components_perftests" ], "isolate_name": "components_perftests", "merge": { @@ -553,9 +535,7 @@ { "args": [ "--gtest-benchmark-name", - "load_library_perf_tests", - "--non-telemetry=true", - "--migrated-test=true" + "load_library_perf_tests" ], "isolate_name": "load_library_perf_tests", "merge": { @@ -592,9 +572,7 @@ { "args": [ "--gtest-benchmark-name", - "media_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "media_perftests" ], "isolate_name": "media_perftests", "merge": { @@ -729,8 +707,6 @@ "args": [ "--gtest-benchmark-name", "angle_perftests", - "--non-telemetry=true", - "--migrated-test=true", "--shard-timeout=300" ], "isolate_name": "angle_perftests", @@ -770,9 +746,7 @@ { "args": [ "--gtest-benchmark-name", - "base_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "base_perftests" ], "isolate_name": "base_perftests", "merge": { @@ -811,9 +785,7 @@ { "args": [ "--gtest-benchmark-name", - "components_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "components_perftests" ], "isolate_name": "components_perftests", "merge": { @@ -852,9 +824,7 @@ { "args": [ "--gtest-benchmark-name", - "gpu_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "gpu_perftests" ], "isolate_name": "gpu_perftests", "merge": { @@ -893,9 +863,7 @@ { "args": [ "--gtest-benchmark-name", - "media_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "media_perftests" ], "isolate_name": "media_perftests", "merge": { @@ -934,9 +902,7 @@ { "args": [ "--gtest-benchmark-name", - "tracing_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "tracing_perftests" ], "isolate_name": "tracing_perftests", "merge": { @@ -1034,9 +1000,7 @@ { "args": [ "--gtest-benchmark-name", - "base_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "base_perftests" ], "isolate_name": "base_perftests", "merge": { @@ -1073,9 +1037,7 @@ { "args": [ "--gtest-benchmark-name", - "load_library_perf_tests", - "--non-telemetry=true", - "--migrated-test=true" + "load_library_perf_tests" ], "isolate_name": "load_library_perf_tests", "merge": { @@ -1112,9 +1074,7 @@ { "args": [ "--gtest-benchmark-name", - "media_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "media_perftests" ], "isolate_name": "media_perftests", "merge": { @@ -1151,9 +1111,7 @@ { "args": [ "--gtest-benchmark-name", - "net_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "net_perftests" ], "isolate_name": "net_perftests", "merge": { @@ -1190,9 +1148,7 @@ { "args": [ "--gtest-benchmark-name", - "performance_browser_tests", - "--non-telemetry=true", - "--migrated-test=true" + "performance_browser_tests" ], "isolate_name": "performance_browser_tests", "merge": { @@ -1229,9 +1185,7 @@ { "args": [ "--gtest-benchmark-name", - "tracing_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "tracing_perftests" ], "isolate_name": "tracing_perftests", "merge": { @@ -1313,9 +1267,7 @@ { "args": [ "--gtest-benchmark-name", - "load_library_perf_tests", - "--non-telemetry=true", - "--migrated-test=true" + "load_library_perf_tests" ], "isolate_name": "load_library_perf_tests", "merge": { @@ -1352,9 +1304,7 @@ { "args": [ "--gtest-benchmark-name", - "performance_browser_tests", - "--non-telemetry=true", - "--migrated-test=true" + "performance_browser_tests" ], "isolate_name": "performance_browser_tests", "merge": { @@ -1436,9 +1386,7 @@ { "args": [ "--gtest-benchmark-name", - "base_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "base_perftests" ], "isolate_name": "base_perftests", "merge": { @@ -1475,9 +1423,7 @@ { "args": [ "--gtest-benchmark-name", - "media_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "media_perftests" ], "isolate_name": "media_perftests", "merge": { @@ -1514,9 +1460,7 @@ { "args": [ "--gtest-benchmark-name", - "net_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "net_perftests" ], "isolate_name": "net_perftests", "merge": { @@ -1553,9 +1497,7 @@ { "args": [ "--gtest-benchmark-name", - "performance_browser_tests", - "--non-telemetry=true", - "--migrated-test=true" + "performance_browser_tests" ], "isolate_name": "performance_browser_tests", "merge": { @@ -1592,9 +1534,7 @@ { "args": [ "--gtest-benchmark-name", - "views_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "views_perftests" ], "isolate_name": "views_perftests", "merge": { @@ -1682,8 +1622,6 @@ "args": [ "--gtest-benchmark-name", "angle_perftests", - "--non-telemetry=true", - "--migrated-test=true", "--shard-timeout=300" ], "isolate_name": "angle_perftests", @@ -1721,9 +1659,7 @@ { "args": [ "--gtest-benchmark-name", - "base_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "base_perftests" ], "isolate_name": "base_perftests", "merge": { @@ -1760,9 +1696,7 @@ { "args": [ "--gtest-benchmark-name", - "components_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "components_perftests" ], "isolate_name": "components_perftests", "merge": { @@ -1799,9 +1733,7 @@ { "args": [ "--gtest-benchmark-name", - "media_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "media_perftests" ], "isolate_name": "media_perftests", "merge": { @@ -1838,9 +1770,7 @@ { "args": [ "--gtest-benchmark-name", - "views_perftests", - "--non-telemetry=true", - "--migrated-test=true" + "views_perftests" ], "isolate_name": "views_perftests", "merge": {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index bb6d83a..f93abd10 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -716,6 +716,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -786,6 +789,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -3382,6 +3388,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -4116,6 +4125,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], "isolate_name": "components_perftests", "merge": { "args": [ @@ -4186,6 +4198,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [ @@ -4972,6 +4987,9 @@ } }, { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], "isolate_name": "views_perftests", "merge": { "args": [
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 772fb5f8..13487c28 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -127,6 +127,8 @@ "angle_perftests": { "args": [ "angle_perftests", + "--non-telemetry=true", + "--migrated-test=true", "--test-launcher-print-test-stdio=always", "--test-launcher-jobs=1", "--test-launcher-retry-limit=0", @@ -251,6 +253,8 @@ "base_perftests": { "args": [ "base_perftests", + "--non-telemetry=true", + "--migrated-test=true", "--test-launcher-print-test-stdio=always", "--test-launcher-jobs=1", "--test-launcher-retry-limit=0", @@ -619,6 +623,8 @@ "command_buffer_perftests": { "args": [ "command_buffer_perftests", + "--non-telemetry=true", + "--migrated-test=true", "--adb-path", "src/third_party/android_tools/sdk/platform-tools/adb", ], @@ -649,7 +655,6 @@ "components_perftests": { "args": [ "--xvfb", - "--gtest-benchmark-name=components_perftests", "--non-telemetry=true", "--migrated-test=true", "components_perftests", @@ -1028,6 +1033,8 @@ "gpu_perftests": { "args": [ "gpu_perftests", + "--non-telemetry=true", + "--migrated-test=true", "--adb-path", "src/third_party/android_tools/sdk/platform-tools/adb", ], @@ -1353,6 +1360,8 @@ "load_library_perf_tests": { "args": [ "load_library_perf_tests", + "--non-telemetry=true", + "--migrated-test=true", "--test-launcher-print-test-stdio=always", ], "label": "//chrome/test:load_library_perf_tests", @@ -1390,6 +1399,8 @@ "media_perftests": { "args": [ "media_perftests", + "--non-telemetry=true", + "--migrated-test=true", "--single-process-tests", "--test-launcher-retry-limit=0", "--isolated-script-test-filter=*::-*_unoptimized::*_unaligned::*unoptimized_aligned", @@ -1789,6 +1800,8 @@ "net_perftests": { "args": [ "net_perftests", + "--non-telemetry=true", + "--migrated-test=true", ], "label": "//net:net_perftests", "script": "//testing/scripts/run_performance_tests_wrapper.py", @@ -2018,6 +2031,8 @@ "performance_browser_tests": { "args": [ "performance_browser_tests", + "--non-telemetry=true", + "--migrated-test=true", "--test-launcher-print-test-stdio=always", # TODO(crbug.com/759866): Figure out why CastV2PerformanceTest/0 sometimes # takes 15-30 seconds to start up and, once fixed, remove this workaround @@ -2434,6 +2449,8 @@ "tracing_perftests": { "args": [ "tracing_perftests", + "--non-telemetry=true", + "--migrated-test=true", "--test-launcher-print-test-stdio=always", "--adb-path", "src/third_party/android_tools/sdk/platform-tools/adb", @@ -2574,7 +2591,6 @@ "views_perftests": { "args": [ "--xvfb", - "--gtest-benchmark-name=views_perftests", "--non-telemetry=true", "--migrated-test=true", "views_perftests", @@ -2614,8 +2630,7 @@ "vr_common_perftests": { "args": [ "vr_common_perftests", - "--non-telemetry=1", - "--gtest-benchmark-name=xr.vr.common_perftests", + "--non-telemetry=true", "--adb-path", "src/third_party/android_tools/sdk/platform-tools/adb", ],
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 8c9eb62..b29400c 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -2657,6 +2657,9 @@ '--smoke-test-mode', ], }, + 'args': [ + '--gtest-benchmark-name=components_perftests', + ], }, }, @@ -2707,6 +2710,9 @@ '--smoke-test-mode', ], }, + 'args': [ + '--gtest-benchmark-name=views_perftests', + ], }, 'webkit_layout_tests': { # layout test failures are retried 3 times when '--test-list' is not @@ -3054,6 +3060,7 @@ 'gpu_angle_perftests': { 'angle_perftests': { 'args': [ + '--gtest-benchmark-name=angle_perftests', '-v', # Tell the tests to exit after one frame for faster iteration. '--one-frame-only', @@ -3061,6 +3068,12 @@ 'android_args': [ '--shard-timeout=500', ], + 'merge': { + 'script': '//tools/perf/process_perf_results.py', + 'args': [ + '--smoke-test-mode', + ], + }, }, }, @@ -3096,12 +3109,19 @@ 'gpu_command_buffer_perftests_passthrough': { 'passthrough_command_buffer_perftests': { 'args': [ + '--gtest-benchmark-name=passthrough_command_buffer_perftests', '-v', '--use-cmd-decoder=passthrough', '--use-angle=gl-null', '--fast-run', ], 'isolate_name': 'command_buffer_perftests', + 'merge': { + 'script': '//tools/perf/process_perf_results.py', + 'args': [ + '--smoke-test-mode', + ], + }, 'should_retry_with_patch': False, }, }, @@ -3109,12 +3129,19 @@ 'gpu_command_buffer_perftests_validating': { 'validating_command_buffer_perftests': { 'args': [ + '--gtest-benchmark-name=validating_command_buffer_perftests', '-v', '--use-cmd-decoder=validating', '--use-stub', '--fast-run', ], 'isolate_name': 'command_buffer_perftests', + 'merge': { + 'script': '//tools/perf/process_perf_results.py', + 'args': [ + '--smoke-test-mode', + ], + }, 'should_retry_with_patch': False, }, },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 0be8968..1b75e321 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -970,6 +970,25 @@ ] } ], + "BlinkGenPropertyTrees": [ + { + "platforms": [ + "android", + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "BlinkGenPropertyTrees" + ] + } + ] + } + ], "BlinkSchedulerDedicatedWorkerThrottling": [ { "platforms": [
diff --git a/third_party/blink/public/platform/task_type.h b/third_party/blink/public/platform/task_type.h index 718031f..19abed3 100644 --- a/third_party/blink/public/platform/task_type.h +++ b/third_party/blink/public/platform/task_type.h
@@ -143,6 +143,9 @@ // https://www.w3.org/TR/permissions/ kPermission = 59, + // https://w3c.github.io/ServiceWorker/#dfn-client-message-queue + kServiceWorkerClientMessage = 60, + /////////////////////////////////////// // Not-speced tasks should use one of the following task types /////////////////////////////////////// @@ -217,7 +220,7 @@ kWorkerThreadTaskQueueV8 = 47, kWorkerThreadTaskQueueCompositor = 48, - kCount = 60, + kCount = 61, }; } // namespace blink
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h index 2e90d02f..7064cd2 100644 --- a/third_party/blink/public/web/web_widget.h +++ b/third_party/blink/public/web/web_widget.h
@@ -95,13 +95,29 @@ // Called to update imperative animation state. This should be called before // paint, although the client can rate-limit these calls. - // |last_frame_time| is in seconds. - virtual void BeginFrame(base::TimeTicks last_frame_time) {} + // |last_frame_time| is in seconds. |record_main_frame_metrics| is true when + // UMA and UKM metrics should be emitted for animation work. + virtual void BeginFrame(base::TimeTicks last_frame_time, + bool record_main_frame_metrics) {} + + // Called when main frame metrics are desired. The local frame's UKM + // aggregator must be informed that collection is starting for the + // frame. + virtual void RecordStartOfFrameMetrics() {} // Called when a main frame time metric should be emitted, along with // any metrics that depend upon the main frame total time. virtual void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) {} + // Methods called to mark the beginning and end of input processing work + // before rAF scripts are executed. Only called when gathering main frame + // UMA and UKM. That is, when RecordStartOfFrameMetrics has been called, and + // before RecordEndOfFrameMetrics has been called. Only implement if the + // rAF input update will be called as part of a layer tree view main frame + // update. + virtual void BeginRafAlignedInput() {} + virtual void EndRafAlignedInput() {} + // Called to run through the entire set of document lifecycle phases needed // to render a frame of the web widget. This MUST be called before Paint, // and it may result in calls to WebWidgetClient::DidInvalidateRect.
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc index c50c77d..7cbc75cf 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -8,19 +8,31 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/v8_response.h" +#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/fetch/body_stream_buffer.h" #include "third_party/blink/renderer/core/fetch/fetch_data_loader.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" +#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h" +#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" +#include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { namespace { +// Wasm only has a single metadata type, but we need to tag it. +static const int kWasmModuleTag = 1; + // The |FetchDataLoader| for streaming compilation of WebAssembly code. The // received bytes get forwarded to the V8 API class |WasmStreaming|. class FetchDataLoaderForWasmStreaming final : public FetchDataLoader, @@ -28,10 +40,12 @@ USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderForWasmStreaming); public: - FetchDataLoaderForWasmStreaming(ScriptState* script_state, - std::shared_ptr<v8::WasmStreaming> streaming) + FetchDataLoaderForWasmStreaming(std::shared_ptr<v8::WasmStreaming> streaming, + ScriptState* script_state) : streaming_(std::move(streaming)), script_state_(script_state) {} + v8::WasmStreaming* streaming() const { return streaming_.get(); } + void Start(BytesConsumer* consumer, FetchDataLoader::Client* client) override { DCHECK(!consumer_); @@ -112,7 +126,8 @@ streaming_->Abort(v8::Local<v8::Value>()); } } - TraceWrapperMember<BytesConsumer> consumer_; + + Member<BytesConsumer> consumer_; Member<FetchDataLoader::Client> client_; std::shared_ptr<v8::WasmStreaming> streaming_; const Member<ScriptState> script_state_; @@ -167,8 +182,87 @@ ExceptionState& exception_state_; }; +SingleCachedMetadataHandler* GetCachedMetadataHandler(ScriptState* script_state, + const KURL& url) { + if (!RuntimeEnabledFeatures::WasmCodeCacheEnabled()) + return nullptr; + ExecutionContext* execution_context = ExecutionContext::From(script_state); + if (!execution_context) + return nullptr; + ResourceFetcher* fetcher = execution_context->Fetcher(); + if (!fetcher) + return nullptr; + if (!url.IsValid()) + return nullptr; + Resource* resource = fetcher->CachedResource(url); + if (!resource) + return nullptr; + + // Wasm modules should be fetched as raw resources. + DCHECK_EQ(ResourceType::kRaw, resource->GetType()); + RawResource* raw_resource = ToRawResource(resource); + return raw_resource->ScriptCacheHandler(); +} + +class WasmStreamingClient : public v8::WasmStreaming::Client { + public: + WasmStreamingClient(const KURL& url, + v8::Isolate* isolate, + v8::Local<v8::Context> context) + : url_(url), isolate_(isolate), context_(isolate, context) { + context_.SetWeak(); + } + + void OnModuleCompiled(v8::CompiledWasmModule compiled_module) override { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "v8.wasm.compiledModule", TRACE_EVENT_SCOPE_THREAD, + "url", url_.GetString().Utf8()); + + // Don't cache if Context has been destroyed. + if (context_.IsEmpty()) + return; + + v8::HandleScope handle_scope(isolate_); + auto context = context_.Get(isolate_); + ScriptState* script_state = ScriptState::From(context); + SingleCachedMetadataHandler* cache_handler = + GetCachedMetadataHandler(script_state, url_); + if (!cache_handler) + return; + + v8::MemorySpan<const uint8_t> wire_bytes = + compiled_module.GetWireBytesRef(); + // Our heuristic for whether it's worthwhile to cache is that the module + // was fully compiled and it is "large". Wire bytes size is likely to be + // highly correlated with compiled module size so we use it to avoid the + // cost of serializing when not caching. + const size_t kWireBytesSizeThresholdBytes = 1UL << 17; // 128 KB. + if (wire_bytes.size() < kWireBytesSizeThresholdBytes) + return; + + v8::OwnedBuffer serialized_module = compiled_module.Serialize(); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "v8.wasm.cachedModule", TRACE_EVENT_SCOPE_THREAD, + "producedCacheSize", serialized_module.size); + cache_handler->SetCachedMetadata( + kWasmModuleTag, + reinterpret_cast<const uint8_t*>(serialized_module.buffer.get()), + serialized_module.size); + } + + private: + KURL url_; + v8::Isolate* isolate_; + v8::Global<v8::Context> context_; + + DISALLOW_COPY_AND_ASSIGN(WasmStreamingClient); +}; + void StreamFromResponseCallback( const v8::FunctionCallbackInfo<v8::Value>& args) { + TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "v8.wasm.streamFromResponseCallback", + TRACE_EVENT_SCOPE_THREAD); ExceptionState exception_state(args.GetIsolate(), ExceptionState::kExecutionContext, "WebAssembly", "compile"); @@ -224,9 +318,35 @@ return; } + KURL url(response->url()); + SingleCachedMetadataHandler* cache_handler = + GetCachedMetadataHandler(script_state, url); + if (cache_handler) { + streaming->SetClient(std::make_shared<WasmStreamingClient>( + url, args.GetIsolate(), script_state->GetContext())); + scoped_refptr<CachedMetadata> cached_module = + cache_handler->GetCachedMetadata(kWasmModuleTag); + if (cached_module) { + TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "v8.wasm.moduleCacheHit", TRACE_EVENT_SCOPE_THREAD, + "url", url.GetString().Utf8(), "consumedCacheSize", + cached_module->size()); + bool is_valid = streaming->SetCompiledModuleBytes( + reinterpret_cast<const uint8_t*>(cached_module->Data()), + cached_module->size()); + if (!is_valid) { + TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "v8.wasm.moduleCacheInvalid", + TRACE_EVENT_SCOPE_THREAD); + cache_handler->ClearCachedMetadata( + CachedMetadataHandler::kSendToPlatform); + } + } + } + FetchDataLoaderForWasmStreaming* loader = - MakeGarbageCollected<FetchDataLoaderForWasmStreaming>(script_state, - streaming); + MakeGarbageCollected<FetchDataLoaderForWasmStreaming>(streaming, + script_state); response->BodyBuffer()->StartLoading( loader, MakeGarbageCollected<WasmDataLoaderClient>(), exception_state); }
diff --git a/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.cc b/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.cc index 0fb41b12..7f33f0e 100644 --- a/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.cc +++ b/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.cc
@@ -4,10 +4,6 @@ #include "third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h" -#include <ctype.h> -#include <fcntl.h> -#include <unistd.h> - #include "base/allocator/partition_allocator/oom_callback.h" #include "base/metrics/histogram_macros.h" #include "base/process/memory.h" @@ -20,25 +16,6 @@ namespace blink { -namespace { - -// Roughly calculates amount of memory which is used to execute pages. -uint64_t BlinkMemoryWorkloadCalculator() { - v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate(); - DCHECK(isolate); - v8::HeapStatistics heap_statistics; - isolate->GetHeapStatistics(&heap_statistics); - // TODO: Add memory usage for worker threads. - size_t v8_size = - heap_statistics.total_heap_size() + heap_statistics.malloced_memory(); - size_t blink_gc_size = ProcessHeap::TotalAllocatedObjectSize() + - ProcessHeap::TotalMarkedObjectSize(); - size_t partition_alloc_size = WTF::Partitions::TotalSizeOfCommittedPages(); - return v8_size + blink_gc_size + partition_alloc_size; -} - -} // namespace - // static void CrashMemoryMetricsReporterImpl::Bind( mojom::blink::CrashMemoryMetricsReporterRequest request) { @@ -68,6 +45,11 @@ shared_metrics_mapping_ = shared_metrics_buffer.Map(); } +void CrashMemoryMetricsReporterImpl::OnMemoryPing(MemoryUsage usage) { + WriteIntoSharedMemory( + CrashMemoryMetricsReporterImpl::MemoryUsageToMetrics(usage)); +} + void CrashMemoryMetricsReporterImpl::WriteIntoSharedMemory( const OomInterventionMetrics& metrics) { if (!shared_metrics_mapping_.IsValid()) @@ -96,31 +78,30 @@ OomInterventionMetrics CrashMemoryMetricsReporterImpl::GetCurrentMemoryMetrics() { - // This can only be called after ResetFileDescriptors(). - DCHECK(statm_fd_.is_valid() && status_fd_.is_valid()); - - OomInterventionMetrics metrics = {}; - metrics.current_blink_usage_kb = BlinkMemoryWorkloadCalculator() / 1024; - uint64_t private_footprint, swap, vm_size; - if (MemoryUsageMonitorAndroid::CalculateProcessMemoryFootprint( - statm_fd_.get(), status_fd_.get(), &private_footprint, &swap, - &vm_size)) { - metrics.current_private_footprint_kb = private_footprint / 1024; - metrics.current_swap_kb = swap / 1024; - metrics.current_vm_size_kb = vm_size / 1024; - } - metrics.allocation_failed = 0; // false - return metrics; + return MemoryUsageToMetrics( + MemoryUsageMonitor::Instance().GetCurrentMemoryUsage()); } -bool CrashMemoryMetricsReporterImpl::ResetFileDiscriptors() { - // See https://goo.gl/KjWnZP For details about why we read these files from - // sandboxed renderer. Keep these files open when detection is enabled. - if (!statm_fd_.is_valid()) - statm_fd_.reset(open("/proc/self/statm", O_RDONLY)); - if (!status_fd_.is_valid()) - status_fd_.reset(open("/proc/self/status", O_RDONLY)); - return !statm_fd_.is_valid() || !status_fd_.is_valid(); +// static +OomInterventionMetrics CrashMemoryMetricsReporterImpl::MemoryUsageToMetrics( + MemoryUsage usage) { + OomInterventionMetrics metrics = {}; + + DCHECK(!std::isnan(usage.private_footprint_bytes)); + DCHECK(!std::isnan(usage.swap_bytes)); + DCHECK(!std::isnan(usage.vm_size_bytes)); + metrics.current_blink_usage_kb = + (usage.v8_bytes + usage.blink_gc_bytes + usage.partition_alloc_bytes) / + 1024; + + DCHECK(!std::isnan(usage.private_footprint_bytes)); + DCHECK(!std::isnan(usage.swap_bytes)); + DCHECK(!std::isnan(usage.vm_size_bytes)); + metrics.current_private_footprint_kb = usage.private_footprint_bytes / 1024; + metrics.current_swap_kb = usage.swap_bytes / 1024; + metrics.current_vm_size_kb = usage.vm_size_bytes / 1024; + metrics.allocation_failed = 0; // false + return metrics; } } // namespace blink
diff --git a/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h b/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h index bcf6de72..aa70ac6 100644 --- a/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h +++ b/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h
@@ -10,15 +10,18 @@ #include "third_party/blink/public/common/oom_intervention/oom_intervention_types.h" #include "third_party/blink/public/mojom/crash/crash_memory_metrics_reporter.mojom-blink.h" #include "third_party/blink/renderer/controller/controller_export.h" +#include "third_party/blink/renderer/controller/memory_usage_monitor.h" namespace blink { // Writes data about renderer into shared memory that will be read by browser. class CONTROLLER_EXPORT CrashMemoryMetricsReporterImpl - : public mojom::blink::CrashMemoryMetricsReporter { + : public mojom::blink::CrashMemoryMetricsReporter, + public MemoryUsageMonitor::Observer { public: static CrashMemoryMetricsReporterImpl& Instance(); static void Bind(mojom::blink::CrashMemoryMetricsReporterRequest); + static OomInterventionMetrics MemoryUsageToMetrics(MemoryUsage); ~CrashMemoryMetricsReporterImpl() override; @@ -26,7 +29,8 @@ void SetSharedMemory( base::UnsafeSharedMemoryRegion shared_metrics_buffer) override; - void WriteIntoSharedMemory(const OomInterventionMetrics& metrics); + // MemoryUsageMonitor::Observer: + void OnMemoryPing(MemoryUsage) override; // This method tracks when an allocation failure occurs. It should be hooked // into all platform allocation failure handlers in a process such as @@ -38,22 +42,16 @@ // This function needs to be called after ResetFileDescriptors. OomInterventionMetrics GetCurrentMemoryMetrics(); - // This function resets statm_fd_ & status_fd_ to prepare for getting metrics. - bool ResetFileDiscriptors(); - protected: CrashMemoryMetricsReporterImpl(); private: FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, CalculateProcessFootprint); + void WriteIntoSharedMemory(const OomInterventionMetrics& metrics); + base::WritableSharedMemoryMapping shared_metrics_mapping_; mojo::Binding<mojom::blink::CrashMemoryMetricsReporter> binding_; - - // The file descriptor to current process proc files. The files are kept open - // when detection is on to reduce measurement overhead. - base::ScopedFD statm_fd_; - base::ScopedFD status_fd_; }; } // namespace blink
diff --git a/third_party/blink/renderer/controller/memory_usage_monitor.cc b/third_party/blink/renderer/controller/memory_usage_monitor.cc index 16e9978e..8e60ff0 100644 --- a/third_party/blink/renderer/controller/memory_usage_monitor.cc +++ b/third_party/blink/renderer/controller/memory_usage_monitor.cc
@@ -28,6 +28,10 @@ observers_.RemoveObserver(observer); } +bool MemoryUsageMonitor::HasObserver(Observer* observer) { + return observers_.HasObserver(observer); +} + void MemoryUsageMonitor::StartMonitoringIfNeeded() { if (timer_.IsActive()) return;
diff --git a/third_party/blink/renderer/controller/memory_usage_monitor.h b/third_party/blink/renderer/controller/memory_usage_monitor.h index 86e8706..62b26a3 100644 --- a/third_party/blink/renderer/controller/memory_usage_monitor.h +++ b/third_party/blink/renderer/controller/memory_usage_monitor.h
@@ -36,12 +36,13 @@ virtual ~MemoryUsageMonitor() = default; // Returns the current memory usage. - MemoryUsage GetCurrentMemoryUsage(); + virtual MemoryUsage GetCurrentMemoryUsage(); // Ensures that an observer is only added once. void AddObserver(Observer*); // Observers must be removed before they are destroyed. void RemoveObserver(Observer*); + bool HasObserver(Observer*); bool TimerIsActive() const { return timer_.IsActive(); }
diff --git a/third_party/blink/renderer/controller/oom_intervention_impl.cc b/third_party/blink/renderer/controller/oom_intervention_impl.cc index 708b5a8..6ca589b 100644 --- a/third_party/blink/renderer/controller/oom_intervention_impl.cc +++ b/third_party/blink/renderer/controller/oom_intervention_impl.cc
@@ -11,10 +11,10 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.h" #include "third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h" +#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" -#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" namespace blink { @@ -25,14 +25,13 @@ } OomInterventionImpl::OomInterventionImpl() - : timer_(Thread::MainThread()->GetTaskRunner(), - this, - &OomInterventionImpl::Check), - delayed_report_timer_(Thread::MainThread()->GetTaskRunner(), + : delayed_report_timer_(Thread::MainThread()->GetTaskRunner(), this, &OomInterventionImpl::TimerFiredUMAReport) {} -OomInterventionImpl::~OomInterventionImpl() {} +OomInterventionImpl::~OomInterventionImpl() { + MemoryUsageMonitorInstance().RemoveObserver(this); +} void OomInterventionImpl::StartDetection( mojom::blink::OomInterventionHostPtr host, @@ -42,26 +41,29 @@ bool purge_v8_memory_enabled) { host_ = std::move(host); - // Disable intervention if we cannot get memory details of current process. - if (CrashMemoryMetricsReporterImpl::Instance().ResetFileDiscriptors()) - return; - detection_args_ = std::move(detection_args); renderer_pause_enabled_ = renderer_pause_enabled; navigate_ads_enabled_ = navigate_ads_enabled; purge_v8_memory_enabled_ = purge_v8_memory_enabled; - timer_.Start(TimeDelta(), TimeDelta::FromSeconds(1), FROM_HERE); + MemoryUsageMonitorInstance().AddObserver(this); } -OomInterventionMetrics OomInterventionImpl::GetCurrentMemoryMetrics() { - return CrashMemoryMetricsReporterImpl::Instance().GetCurrentMemoryMetrics(); +MemoryUsageMonitor& OomInterventionImpl::MemoryUsageMonitorInstance() { + return MemoryUsageMonitor::Instance(); } -void OomInterventionImpl::Check(TimerBase*) { +void OomInterventionImpl::OnMemoryPing(MemoryUsage usage) { + // Ignore pings without process memory usage information. + if (std::isnan(usage.private_footprint_bytes) || + std::isnan(usage.swap_bytes) || std::isnan(usage.vm_size_bytes)) + return; + Check(CrashMemoryMetricsReporterImpl::MemoryUsageToMetrics(usage)); +} + +void OomInterventionImpl::Check(OomInterventionMetrics current_memory) { DCHECK(host_); - OomInterventionMetrics current_memory = GetCurrentMemoryMetrics(); bool oom_detected = false; oom_detected |= detection_args_->blink_workload_threshold > 0 && @@ -100,7 +102,7 @@ } host_->OnHighMemoryUsage(); - timer_.Stop(); + MemoryUsageMonitorInstance().RemoveObserver(this); // Send memory pressure notification to trigger GC. Thread::MainThread()->GetTaskRunner()->PostTask(FROM_HERE, base::BindOnce(&TriggerGC)); @@ -134,13 +136,11 @@ "Memory.Experimental.OomIntervention.RendererVmSize", base::saturated_cast<base::Histogram::Sample>( current_memory.current_vm_size_kb / 1024)); - - CrashMemoryMetricsReporterImpl::Instance().WriteIntoSharedMemory( - current_memory); } void OomInterventionImpl::TimerFiredUMAReport(TimerBase*) { - OomInterventionMetrics current_memory = GetCurrentMemoryMetrics(); + OomInterventionMetrics current_memory = + CrashMemoryMetricsReporterImpl::Instance().GetCurrentMemoryMetrics(); switch (number_of_report_needed_--) { case 3: base::UmaHistogramSparse(
diff --git a/third_party/blink/renderer/controller/oom_intervention_impl.h b/third_party/blink/renderer/controller/oom_intervention_impl.h index 21ed667e..8c59240f1 100644 --- a/third_party/blink/renderer/controller/oom_intervention_impl.h +++ b/third_party/blink/renderer/controller/oom_intervention_impl.h
@@ -5,11 +5,10 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CONTROLLER_OOM_INTERVENTION_IMPL_H_ #define THIRD_PARTY_BLINK_RENDERER_CONTROLLER_OOM_INTERVENTION_IMPL_H_ -#include "base/files/scoped_file.h" #include "third_party/blink/public/common/oom_intervention/oom_intervention_types.h" #include "third_party/blink/public/platform/oom_intervention.mojom-blink.h" #include "third_party/blink/renderer/controller/controller_export.h" -#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/controller/memory_usage_monitor.h" #include "third_party/blink/renderer/core/page/scoped_page_pauser.h" #include "third_party/blink/renderer/platform/timer.h" @@ -20,7 +19,8 @@ // Implementation of OOM intervention. This pauses all pages by using // ScopedPagePauser when near-OOM situation is detected. class CONTROLLER_EXPORT OomInterventionImpl - : public mojom::blink::OomIntervention { + : public mojom::blink::OomIntervention, + public MemoryUsageMonitor::Observer { public: static void Create(mojom::blink::OomInterventionRequest); @@ -34,17 +34,20 @@ bool navigate_ads_enabled, bool purge_v8_memory_enabled) override; + // MemoryUsageMonitor::Observer: + void OnMemoryPing(MemoryUsage) override; + private: FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, DetectedAndDeclined); - FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, CalculateProcessFootprint); FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, StopWatchingAfterDetection); FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, ContinueWatchingWithoutDetection); FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, V1DetectionAdsNavigation); // Overridden by test. - virtual OomInterventionMetrics GetCurrentMemoryMetrics(); - void Check(TimerBase*); + virtual MemoryUsageMonitor& MemoryUsageMonitorInstance(); + + void Check(OomInterventionMetrics); void ReportMemoryStats(OomInterventionMetrics& current_memory); @@ -58,7 +61,6 @@ bool renderer_pause_enabled_ = false; bool navigate_ads_enabled_ = false; bool purge_v8_memory_enabled_ = false; - TaskRunnerTimer<OomInterventionImpl> timer_; std::unique_ptr<ScopedPagePauser> pauser_; OomInterventionMetrics metrics_at_intervention_; int number_of_report_needed_ = 0;
diff --git a/third_party/blink/renderer/controller/oom_intervention_impl_test.cc b/third_party/blink/renderer/controller/oom_intervention_impl_test.cc index 28fb8dc..230bc89b 100644 --- a/third_party/blink/renderer/controller/oom_intervention_impl_test.cc +++ b/third_party/blink/renderer/controller/oom_intervention_impl_test.cc
@@ -44,28 +44,39 @@ mojo::Binding<mojom::blink::OomInterventionHost> binding_; }; -// Mock intervention class that has custom method for fetching metrics. +// Mock that allows setting mock memory usage. +class MockMemoryUsageMonitor : public MemoryUsageMonitor { + public: + MockMemoryUsageMonitor() = default; + + MemoryUsage GetCurrentMemoryUsage() override { return mock_memory_usage_; } + + // MemoryUsageMonitor will report the current memory usage as this value. + void SetMockMemoryUsage(MemoryUsage usage) { mock_memory_usage_ = usage; } + + private: + MemoryUsage mock_memory_usage_; +}; + +// Mock intervention class that uses a mock MemoryUsageMonitor. class MockOomInterventionImpl : public OomInterventionImpl { public: - MockOomInterventionImpl() {} + MockOomInterventionImpl() + : mock_memory_usage_monitor_(std::make_unique<MockMemoryUsageMonitor>()) { + } ~MockOomInterventionImpl() override {} - // If metrics are set by calling this method, then GetCurrentMemoryMetrics() - // will return the given metrics, else it will calculate metrics from - // providers. - void SetMetrics(OomInterventionMetrics metrics) { - metrics_ = std::make_unique<OomInterventionMetrics>(); - *metrics_ = metrics; + MemoryUsageMonitor& MemoryUsageMonitorInstance() override { + return *mock_memory_usage_monitor_; + } + + MockMemoryUsageMonitor* mock_memory_usage_monitor() { + return mock_memory_usage_monitor_.get(); } private: - OomInterventionMetrics GetCurrentMemoryMetrics() override { - if (metrics_) - return *metrics_; - return CrashMemoryMetricsReporterImpl::Instance().GetCurrentMemoryMetrics(); - } - std::unique_ptr<OomInterventionMetrics> metrics_; + std::unique_ptr<MockMemoryUsageMonitor> mock_memory_usage_monitor_; }; } // namespace @@ -109,13 +120,15 @@ }; TEST_F(OomInterventionImplTest, NoDetectionOnBelowThreshold) { - OomInterventionMetrics mock_metrics = {}; + MemoryUsage usage; // Set value less than the threshold to not trigger intervention. - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1; - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1; - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1; - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1; - intervention_->SetMetrics(mock_metrics); + usage.v8_bytes = kTestBlinkThreshold - 1024; + usage.blink_gc_bytes = 0; + usage.partition_alloc_bytes = 0; + usage.private_footprint_bytes = kTestPMFThreshold - 1024; + usage.swap_bytes = kTestSwapThreshold - 1024; + usage.vm_size_bytes = kTestVmSizeThreshold - 1024; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); Page* page = DetectOnceOnBlankPage(); @@ -123,13 +136,15 @@ } TEST_F(OomInterventionImplTest, BlinkThresholdDetection) { - OomInterventionMetrics mock_metrics = {}; - // Set value more than the threshold to not trigger intervention. - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) + 1; - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1; - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1; - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1; - intervention_->SetMetrics(mock_metrics); + MemoryUsage usage; + // Set value more than the threshold to trigger intervention. + usage.v8_bytes = kTestBlinkThreshold + 1024; + usage.blink_gc_bytes = 0; + usage.partition_alloc_bytes = 0; + usage.private_footprint_bytes = 0; + usage.swap_bytes = 0; + usage.vm_size_bytes = 0; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); Page* page = DetectOnceOnBlankPage(); @@ -139,13 +154,15 @@ } TEST_F(OomInterventionImplTest, PmfThresholdDetection) { - OomInterventionMetrics mock_metrics = {}; - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1; + MemoryUsage usage; + usage.v8_bytes = 0; + usage.blink_gc_bytes = 0; + usage.partition_alloc_bytes = 0; // Set value more than the threshold to trigger intervention. - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) + 1; - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1; - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1; - intervention_->SetMetrics(mock_metrics); + usage.private_footprint_bytes = kTestPMFThreshold + 1024; + usage.swap_bytes = 0; + usage.vm_size_bytes = 0; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); Page* page = DetectOnceOnBlankPage(); @@ -155,13 +172,15 @@ } TEST_F(OomInterventionImplTest, SwapThresholdDetection) { - OomInterventionMetrics mock_metrics = {}; - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1; - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1; + MemoryUsage usage; + usage.v8_bytes = 0; + usage.blink_gc_bytes = 0; + usage.partition_alloc_bytes = 0; + usage.private_footprint_bytes = 0; // Set value more than the threshold to trigger intervention. - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) + 1; - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1; - intervention_->SetMetrics(mock_metrics); + usage.swap_bytes = kTestSwapThreshold + 1024; + usage.vm_size_bytes = 0; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); Page* page = DetectOnceOnBlankPage(); @@ -171,13 +190,15 @@ } TEST_F(OomInterventionImplTest, VmSizeThresholdDetection) { - OomInterventionMetrics mock_metrics = {}; - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1; - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1; - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1; + MemoryUsage usage; + usage.v8_bytes = 0; + usage.blink_gc_bytes = 0; + usage.partition_alloc_bytes = 0; + usage.private_footprint_bytes = 0; + usage.swap_bytes = 0; // Set value more than the threshold to trigger intervention. - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) + 1; - intervention_->SetMetrics(mock_metrics); + usage.vm_size_bytes = kTestVmSizeThreshold + 1024; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); Page* page = DetectOnceOnBlankPage(); @@ -187,94 +208,51 @@ } TEST_F(OomInterventionImplTest, StopWatchingAfterDetection) { - OomInterventionMetrics mock_metrics = {}; + MemoryUsage usage; + usage.v8_bytes = 0; // Set value more than the threshold to trigger intervention. - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) + 1; - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1; - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1; - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1; - intervention_->SetMetrics(mock_metrics); + usage.blink_gc_bytes = kTestBlinkThreshold + 1024; + usage.partition_alloc_bytes = 0; + usage.private_footprint_bytes = 0; + usage.swap_bytes = 0; + usage.vm_size_bytes = 0; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); DetectOnceOnBlankPage(); - EXPECT_FALSE(intervention_->timer_.IsActive()); + EXPECT_FALSE(intervention_->mock_memory_usage_monitor()->HasObserver( + intervention_.get())); } TEST_F(OomInterventionImplTest, ContinueWatchingWithoutDetection) { - OomInterventionMetrics mock_metrics = {}; + MemoryUsage usage; // Set value less than the threshold to not trigger intervention. - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1; - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1; - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1; - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1; - intervention_->SetMetrics(mock_metrics); + usage.v8_bytes = 0; + usage.blink_gc_bytes = 0; + usage.partition_alloc_bytes = 0; + usage.private_footprint_bytes = 0; + usage.swap_bytes = 0; + usage.vm_size_bytes = 0; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); DetectOnceOnBlankPage(); - EXPECT_TRUE(intervention_->timer_.IsActive()); -} - -TEST_F(OomInterventionImplTest, CalculateProcessFootprint) { - const char kStatusFile[] = - "First: 1\n Second: 2 kB\nVmSwap: 10 kB \n Third: 10 kB\n Last: 8"; - const char kStatmFile[] = "100 40 25 0 0"; - uint64_t expected_swap_kb = 10; - uint64_t expected_private_footprint_kb = - (40 - 25) * getpagesize() / 1024 + expected_swap_kb; - uint64_t expected_vm_size_kb = 100 * getpagesize() / 1024; - - base::FilePath statm_path; - EXPECT_TRUE(base::CreateTemporaryFile(&statm_path)); - EXPECT_EQ(static_cast<int>(sizeof(kStatmFile)), - base::WriteFile(statm_path, kStatmFile, sizeof(kStatmFile))); - base::File statm_file(statm_path, - base::File::FLAG_OPEN | base::File::FLAG_READ); - base::FilePath status_path; - EXPECT_TRUE(base::CreateTemporaryFile(&status_path)); - EXPECT_EQ(static_cast<int>(sizeof(kStatusFile)), - base::WriteFile(status_path, kStatusFile, sizeof(kStatusFile))); - base::File status_file(status_path, - base::File::FLAG_OPEN | base::File::FLAG_READ); - - CrashMemoryMetricsReporterImpl::Instance().statm_fd_.reset( - statm_file.TakePlatformFile()); - CrashMemoryMetricsReporterImpl::Instance().status_fd_.reset( - status_file.TakePlatformFile()); - - mojom::blink::OomInterventionHostPtr host_ptr; - MockOomInterventionHost mock_host(mojo::MakeRequest(&host_ptr)); - mojom::blink::DetectionArgsPtr args(mojom::blink::DetectionArgs::New()); - intervention_->StartDetection( - std::move(host_ptr), std::move(args), true /*renderer_pause_enabled*/, - true /*navigate_ads_enabled*/, true /*purge_v8_memory_enabled*/); - // Create unsafe shared memory region to write metrics in reporter. - base::UnsafeSharedMemoryRegion shm = - base::UnsafeSharedMemoryRegion::Create(sizeof(OomInterventionMetrics)); - CrashMemoryMetricsReporterImpl::Instance().shared_metrics_mapping_ = - shm.Map(); - EXPECT_TRUE(CrashMemoryMetricsReporterImpl::Instance() - .shared_metrics_mapping_.IsValid()); - - intervention_->Check(nullptr); - OomInterventionMetrics* metrics = static_cast<OomInterventionMetrics*>( - CrashMemoryMetricsReporterImpl::Instance() - .shared_metrics_mapping_.memory()); - EXPECT_EQ(expected_private_footprint_kb, - metrics->current_private_footprint_kb); - EXPECT_EQ(expected_swap_kb, metrics->current_swap_kb); - EXPECT_EQ(expected_vm_size_kb, metrics->current_vm_size_kb); + EXPECT_TRUE(intervention_->mock_memory_usage_monitor()->HasObserver( + intervention_.get())); } // TODO(yuzus): Once OOPIF unit test infrastructure is ready, add a test case // with OOPIF enabled. TEST_F(OomInterventionImplTest, V1DetectionAdsNavigation) { - OomInterventionMetrics mock_metrics = {}; - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1; - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1; - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1; + MemoryUsage usage; + usage.v8_bytes = 0; + usage.blink_gc_bytes = 0; // Set value more than the threshold to trigger intervention. - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) + 1; - intervention_->SetMetrics(mock_metrics); + usage.partition_alloc_bytes = kTestBlinkThreshold + 1024; + usage.private_footprint_bytes = 0; + usage.swap_bytes = 0; + usage.vm_size_bytes = 0; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); WebViewImpl* web_view = web_view_helper_.InitializeAndLoad("about:blank"); Page* page = web_view->MainFrameImpl()->GetFrame()->GetPage(); @@ -308,13 +286,15 @@ } TEST_F(OomInterventionImplTest, V2DetectionV8PurgeMemory) { - OomInterventionMetrics mock_metrics = {}; - mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1; - mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1; - mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1; + MemoryUsage usage; + usage.v8_bytes = 0; + usage.blink_gc_bytes = 0; + usage.partition_alloc_bytes = 0; + usage.private_footprint_bytes = 0; + usage.swap_bytes = 0; // Set value more than the threshold to trigger intervention. - mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) + 1; - intervention_->SetMetrics(mock_metrics); + usage.vm_size_bytes = kTestVmSizeThreshold + 1024; + intervention_->mock_memory_usage_monitor()->SetMockMemoryUsage(usage); WebViewImpl* web_view = web_view_helper_.InitializeAndLoad("about:blank"); Page* page = web_view->MainFrameImpl()->GetFrame()->GetPage();
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 9002c20..41989d7d 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1804,6 +1804,7 @@ "dom/document_statistics_collector_test.cc", "dom/document_test.cc", "dom/dom_implementation_test.cc", + "dom/dom_node_ids_test.cc", "dom/element_test.cc", "dom/element_visibility_observer_test.cc", "dom/events/event_path_test.cc",
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc index d27d062c..3c9c76fa 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -465,7 +465,7 @@ void BeginFrame() { helper_.GetWebView()->MainFrameWidget()->BeginFrame( - WTF::CurrentTimeTicks()); + WTF::CurrentTimeTicks(), false /* record_main_frame_metrics */); } void ForceFullCompositingUpdate() {
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index dc148fc0..71b8964 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -1527,7 +1527,7 @@ bool StyleEngine::UpdateRemUnits(const ComputedStyle* old_root_style, const ComputedStyle* new_root_style) { - if (!UsesRemUnits()) + if (!new_root_style || !UsesRemUnits()) return false; if (!old_root_style || old_root_style->FontSize() != new_root_style->FontSize()) {
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 0fe7c25..bc4689e7 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
@@ -163,12 +163,9 @@ if (state_ == kUnlocked) return GetRejectedPromise(script_state); - // If we have a resolver, we must be committing already, just return the same - // promise. - if (commit_resolver_) { - DCHECK(state_ == kCommitting) << state_; + // If we're already committing then return the promise. + if (state_ == kCommitting) return commit_resolver_->Promise(); - } // Now that we've explicitly been requested to commit, we have cancel the // timeout task. @@ -179,12 +176,42 @@ // together will still wait until the lifecycle is clean before resolving any // of the promises. DCHECK_NE(state_, kCommitting); - commit_resolver_ = ScriptPromiseResolver::Create(script_state); + // We might already have a resolver if we called updateAndCommit() before + // this. + if (!commit_resolver_) + commit_resolver_ = ScriptPromiseResolver::Create(script_state); auto promise = commit_resolver_->Promise(); StartCommit(); return promise; } +ScriptPromise DisplayLockContext::updateAndCommit(ScriptState* script_state) { + // Reject if we're unlocked. + if (state_ == kUnlocked) + return GetRejectedPromise(script_state); + + // If we're in a state where a co-operative update doesn't make sense (e.g. we + // haven't acquired the lock, or we're already sync committing), then do + // whatever commit() would do. + if (state_ == kPendingAcquire || state_ == kCommitting || + !element_->isConnected()) { + return commit(script_state); + } + + // If we have a commit resolver already, return it. + if (commit_resolver_) { + // We must be in a second call to updateAndCommit(), meaning that we're in + // the kUpdating state with a commit_resolver_. + DCHECK_EQ(state_, kUpdating); + return commit_resolver_->Promise(); + } + + CancelTimeoutTask(); + commit_resolver_ = ScriptPromiseResolver::Create(script_state); + StartUpdateIfNeeded(); + return commit_resolver_->Promise(); +} + void DisplayLockContext::FinishUpdateResolver(ResolverState state) { FinishResolver(&update_resolver_, state); } @@ -240,10 +267,11 @@ // unexpected behavior. By rejecting the promise, the behavior can be detected // by script. if (!ElementSupportsDisplayLocking()) { + bool should_stay_locked = state_ == kUpdating && !commit_resolver_; FinishUpdateResolver(kReject); FinishCommitResolver(kReject); FinishAcquireResolver(kReject); - state_ = state_ == kUpdating ? kLocked : kUnlocked; + state_ = should_stay_locked ? kLocked : kUnlocked; return; } @@ -300,16 +328,17 @@ } void DisplayLockContext::DidAttachLayoutTree() { - if (state_ == kUnlocked) + if (state_ >= kUnlocked) return; // Note that although we checked at style recalc time that the element has // "contain: style layout", it might not actually apply the containment at the // layout object level. This confirms that containment should apply. if (!ElementSupportsDisplayLocking()) { + bool should_stay_locked = state_ == kUpdating && !commit_resolver_; FinishUpdateResolver(kReject); FinishCommitResolver(kReject); - state_ = state_ == kUpdating ? kLocked : kUnlocked; + state_ = should_stay_locked ? kLocked : kUnlocked; } } @@ -546,7 +575,13 @@ if (!element_ || !element_->isConnected()) { FinishUpdateResolver(kReject); update_budget_.reset(); - state_ = kLocked; + + if (commit_resolver_) { + FinishCommitResolver(kReject); + state_ = kUnlocked; + } else { + state_ = kLocked; + } return; } @@ -563,6 +598,17 @@ FinishUpdateResolver(kResolve); update_budget_.reset(); state_ = kLocked; + + if (commit_resolver_) { + // Schedule a commit to run. Note that we can't call StartCommit directly + // here, since we're in the lifecycle updates right now and the code that + // runs after may depend on having clean layout state, which StartCommit + // might dirty. + GetExecutionContext() + ->GetTaskRunner(TaskType::kMiscPlatformAPI) + ->PostTask(FROM_HERE, WTF::Bind(&DisplayLockContext::StartCommit, + WrapWeakPersistent(this))); + } } void DisplayLockContext::ScheduleAnimation() {
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 3144eda..a5c0d38 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
@@ -95,6 +95,7 @@ ScriptPromise acquire(ScriptState*, DisplayLockOptions*); ScriptPromise update(ScriptState*); ScriptPromise commit(ScriptState*); + ScriptPromise updateAndCommit(ScriptState*); // Lifecycle observation / state functions. bool ShouldStyle() const;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.idl b/third_party/blink/renderer/core/display_lock/display_lock_context.idl index 2e34af83b..592208e 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.idl +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.idl
@@ -16,4 +16,8 @@ // necessary lifecycle phases. // Returns a promise that resolves when the commit is finished. [CallWith=ScriptState] Promise<any> commit(); + + // Causes co-operative updates to happen, followed by a commit. + // Returns a promise that resolves when the commit is finished. + [CallWith=ScriptState] Promise<any> updateAndCommit(); };
diff --git a/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h b/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h index da7512a..77c6ca1f 100644 --- a/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h +++ b/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h
@@ -34,7 +34,7 @@ protected: base::Optional<Phase> last_completed_phase_; - bool completed_new_phase_this_cycle_; + bool completed_new_phase_this_cycle_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/dom_node_ids.cc b/third_party/blink/renderer/core/dom/dom_node_ids.cc index cad3cc1..18c9844d 100644 --- a/third_party/blink/renderer/core/dom/dom_node_ids.cc +++ b/third_party/blink/renderer/core/dom/dom_node_ids.cc
@@ -12,12 +12,15 @@ // static DOMNodeId DOMNodeIds::IdForNode(Node* node) { - return WeakIdentifierMap<Node, DOMNodeId>::Identifier(node); + return node ? WeakIdentifierMap<Node, DOMNodeId>::Identifier(node) + : kInvalidDOMNodeId; } // static Node* DOMNodeIds::NodeForId(DOMNodeId id) { - return WeakIdentifierMap<Node, DOMNodeId>::Lookup(id); + return id == kInvalidDOMNodeId + ? nullptr + : WeakIdentifierMap<Node, DOMNodeId>::Lookup(id); } } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/dom_node_ids_test.cc b/third_party/blink/renderer/core/dom/dom_node_ids_test.cc new file mode 100644 index 0000000..d8038d99 --- /dev/null +++ b/third_party/blink/renderer/core/dom/dom_node_ids_test.cc
@@ -0,0 +1,60 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/dom/dom_node_ids.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" +#include "third_party/blink/renderer/platform/heap/heap.h" + +namespace blink { + +using DOMNodeIdsTest = EditingTestBase; + +TEST_F(DOMNodeIdsTest, NonNull) { + SetBodyContent("<div id='a'></div><div id='b'></div>"); + Node* a = GetDocument().getElementById("a"); + Node* b = GetDocument().getElementById("b"); + + DOMNodeId id_a = DOMNodeIds::IdForNode(a); + EXPECT_NE(kInvalidDOMNodeId, id_a); + EXPECT_EQ(id_a, DOMNodeIds::IdForNode(a)); + EXPECT_EQ(a, DOMNodeIds::NodeForId(id_a)); + + DOMNodeId id_b = DOMNodeIds::IdForNode(b); + EXPECT_NE(kInvalidDOMNodeId, id_b); + EXPECT_NE(id_a, id_b); + EXPECT_EQ(id_b, DOMNodeIds::IdForNode(b)); + EXPECT_EQ(b, DOMNodeIds::NodeForId(id_b)); + + EXPECT_EQ(id_a, DOMNodeIds::IdForNode(a)); + EXPECT_EQ(a, DOMNodeIds::NodeForId(id_a)); +} + +TEST_F(DOMNodeIdsTest, DeletedNode) { + SetBodyContent("<div id='a'></div>"); + Node* a = GetDocument().getElementById("a"); + DOMNodeId id_a = DOMNodeIds::IdForNode(a); + + a->remove(); + ThreadState::Current()->CollectGarbage( + BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, + BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + EXPECT_EQ(nullptr, DOMNodeIds::NodeForId(id_a)); +} + +TEST_F(DOMNodeIdsTest, UnusedID) { + SetBodyContent("<div id='a'></div>"); + Node* a = GetDocument().getElementById("a"); + DOMNodeId id_a = DOMNodeIds::IdForNode(a); + EXPECT_EQ(nullptr, DOMNodeIds::NodeForId(id_a + 1)); +} + +TEST_F(DOMNodeIdsTest, Null) { + EXPECT_EQ(kInvalidDOMNodeId, DOMNodeIds::IdForNode(nullptr)); + EXPECT_EQ(nullptr, DOMNodeIds::NodeForId(kInvalidDOMNodeId)); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc index 8b71a1fc..d7167cb 100644 --- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc +++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -47,6 +47,7 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" +#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/visual_viewport.h" @@ -383,7 +384,8 @@ page_->Animator().SetSuppressFrameRequestsWorkaroundFor704763Only( suppress_frame_requests); } -void WebPagePopupImpl::BeginFrame(base::TimeTicks last_frame_time) { + +void WebPagePopupImpl::BeginFrame(base::TimeTicks last_frame_time, bool) { if (!page_) return; // FIXME: This should use lastFrameTimeMonotonic but doing so
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.h b/third_party/blink/renderer/core/exported/web_page_popup_impl.h index f8b1ec81..0ddae22 100644 --- a/third_party/blink/renderer/core/exported/web_page_popup_impl.h +++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
@@ -83,9 +83,10 @@ // WebWidget functions void SetLayerTreeView(WebLayerTreeView*) override; void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final; - void BeginFrame(base::TimeTicks last_frame_time) override; + void BeginFrame(base::TimeTicks last_frame_time, + bool record_main_frame_metrics) override; void UpdateLifecycle(LifecycleUpdate requested_update, - LifecycleUpdateReason reason /* Not used */) override; + LifecycleUpdateReason reason) override; void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) override; void WillCloseLayerTreeView() override; void PaintContent(cc::PaintCanvas*, const WebRect&) override; @@ -136,6 +137,7 @@ WebLayerTreeView* layer_tree_view_ = nullptr; scoped_refptr<cc::Layer> root_layer_; std::unique_ptr<CompositorAnimationHost> animation_host_; + base::TimeTicks raf_aligned_input_start_time_; bool is_accelerated_compositing_active_ = false; friend class WebPagePopup;
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc index 68128c69..e0ad521 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc +++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
@@ -59,6 +59,7 @@ #include "third_party/blink/renderer/core/clipboard/data_object.h" #include "third_party/blink/renderer/core/clipboard/data_transfer.h" #include "third_party/blink/renderer/core/clipboard/system_clipboard.h" +#include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" #include "third_party/blink/renderer/core/events/drag_event.h" #include "third_party/blink/renderer/core/events/gesture_event.h" @@ -368,8 +369,10 @@ if (layer_) GraphicsLayer::UnregisterContentsLayer(layer_); - if (new_layer) + if (new_layer) { GraphicsLayer::RegisterContentsLayer(new_layer); + new_layer->set_owner_node_id(DOMNodeIds::IdForNode(element_.Get())); + } layer_ = new_layer; prevent_contents_opaque_changes_ = prevent_contents_opaque_changes;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 4263bf1..8bafa25 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -98,6 +98,7 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" +#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h" #include "third_party/blink/renderer/core/frame/remote_frame.h" @@ -1500,7 +1501,8 @@ AsView().page->Animator().SetSuppressFrameRequestsWorkaroundFor704763Only( suppress_frame_requests); } -void WebViewImpl::BeginFrame(base::TimeTicks last_frame_time) { +void WebViewImpl::BeginFrame(base::TimeTicks last_frame_time, + bool record_main_frame_metrics) { TRACE_EVENT1("blink", "WebViewImpl::beginFrame", "frameTime", last_frame_time); DCHECK(!last_frame_time.is_null()); @@ -1515,15 +1517,46 @@ DocumentLifecycle::AllowThrottlingScope throttling_scope( MainFrameImpl()->GetFrame()->GetDocument()->Lifecycle()); + + base::Optional<LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer> ukm_timer; + if (record_main_frame_metrics) { + ukm_timer.emplace(MainFrameImpl() + ->GetFrame() + ->View() + ->EnsureUkmAggregator() + .GetScopedTimer(LocalFrameUkmAggregator::kAnimate)); + } PageWidgetDelegate::Animate(*AsView().page, last_frame_time); } +void WebViewImpl::BeginRafAlignedInput() { + raf_aligned_input_start_time_ = CurrentTimeTicks(); +} + +void WebViewImpl::EndRafAlignedInput() { + if (MainFrameImpl()) { + MainFrameImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample( + LocalFrameUkmAggregator::kHandleInputEvents, + raf_aligned_input_start_time_, CurrentTimeTicks()); + } +} + +void WebViewImpl::RecordStartOfFrameMetrics() { + if (!MainFrameImpl()) + return; + + MainFrameImpl()->GetFrame()->View()->EnsureUkmAggregator().BeginMainFrame(); +} + void WebViewImpl::RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) { if (!MainFrameImpl()) return; - MainFrameImpl()->GetFrame()->View()->RecordEndOfFrameMetrics( - frame_begin_time); + MainFrameImpl() + ->GetFrame() + ->View() + ->EnsureUkmAggregator() + .RecordEndOfFrameMetrics(frame_begin_time, CurrentTimeTicks()); } void WebViewImpl::UpdateLifecycle(LifecycleUpdate requested_update,
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index c83d975..931dbf6 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -427,7 +427,11 @@ void DidEnterFullscreen() override; void DidExitFullscreen() override; void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) override; - void BeginFrame(base::TimeTicks last_frame_time) override; + void BeginFrame(base::TimeTicks last_frame_time, + bool record_main_frame_metrics) override; + void BeginRafAlignedInput() override; + void EndRafAlignedInput() override; + void RecordStartOfFrameMetrics() override; void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override; void UpdateLifecycle(LifecycleUpdate requested_update, LifecycleUpdateReason reason) override; @@ -697,6 +701,8 @@ scoped_defer_main_frame_update_; Persistent<ResizeViewportAnchor> resize_viewport_anchor_; + + base::TimeTicks raf_aligned_input_start_time_; }; // We have no ways to check if the specified WebView is an instance of
diff --git a/third_party/blink/renderer/core/frame/ad_tracker_test.cc b/third_party/blink/renderer/core/frame/ad_tracker_test.cc index 617ca7c1..56558d4 100644 --- a/third_party/blink/renderer/core/frame/ad_tracker_test.cc +++ b/third_party/blink/renderer/core/frame/ad_tracker_test.cc
@@ -381,7 +381,8 @@ EXPECT_TRUE(IsKnownAdScript(&GetDocument(), kAdUrl)); EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kAdUrl)); - EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaUrl)); + Frame* child_frame = GetDocument().GetFrame()->Tree().FirstChild(); + EXPECT_TRUE(ToLocalFrame(child_frame)->IsAdSubframe()); } // A script tagged as an ad in one frame shouldn't cause it to be considered
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h index 5cb8e27..2d3be7e 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
@@ -132,6 +132,8 @@ kStyleAndLayout, kForcedStyleAndLayout, kScrollingCoordinator, + kHandleInputEvents, + kAnimate, kCount }; @@ -149,7 +151,9 @@ "PrePaint", "StyleAndLayout", "ForcedStyleAndLayout", - "ScrollingCoordinator"}; + "ScrollingCoordinator", + "HandleInputEvents", + "Animate"}; return *strings; } @@ -202,6 +206,8 @@ void BeginMainFrame(); + bool InMainFrame() { return in_main_frame_update_; } + private: struct AbsoluteMetricRecord { String worst_case_metric_name;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 7dc3264..53b5e89 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1997,11 +1997,6 @@ DocumentLifecycle::LifecycleUpdateReason::kOther); } -void LocalFrameView::RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) { - LocalFrameUkmAggregator& ukm_aggregator = EnsureUkmAggregator(); - ukm_aggregator.RecordEndOfFrameMetrics(frame_begin_time, CurrentTimeTicks()); -} - void LocalFrameView::ScheduleVisualUpdateForPaintInvalidationIfNeeded() { LocalFrame& local_frame_root = GetFrame().LocalFrameRoot(); if (local_frame_root.View()->current_update_lifecycle_phases_target_state_ < @@ -2145,9 +2140,6 @@ return Lifecycle().GetState() == target_state; } - if (reason == DocumentLifecycle::LifecycleUpdateReason::kBeginMainFrame) - EnsureUkmAggregator().BeginMainFrame(); - for (auto& observer : lifecycle_observers_) observer->WillStartLifecycleUpdate(); @@ -2746,6 +2738,8 @@ paint_artifact_compositor_->Update( paint_controller_->GetPaintArtifactShared(), composited_element_ids, viewport_properties, settings); + + probe::layerTreePainted(&GetFrame()); } std::unique_ptr<JSONObject> LocalFrameView::CompositedLayersAsJSON(
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index fb5bd13d6..9fd61ff7 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -369,9 +369,6 @@ // desired state. bool UpdateLifecycleToLayoutClean(); - // Record any UMA and UKM metrics that depend on the end of a main frame. - void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time); - void ScheduleVisualUpdateForPaintInvalidationIfNeeded(); bool InvalidateViewportConstrainedObjects();
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index f927f69..fd5bc6e2 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -60,6 +60,7 @@ #include "third_party/blink/renderer/core/exported/web_remote_frame_impl.h" #include "third_party/blink/renderer/core/exported/web_view_impl.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/remote_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" @@ -284,7 +285,8 @@ GetPage()->Animator().SetSuppressFrameRequestsWorkaroundFor704763Only( suppress_frame_requests); } -void WebFrameWidgetImpl::BeginFrame(base::TimeTicks last_frame_time) { +void WebFrameWidgetImpl::BeginFrame(base::TimeTicks last_frame_time, + bool record_main_frame_metrics) { TRACE_EVENT1("blink", "WebFrameWidgetImpl::beginFrame", "frameTime", last_frame_time); DCHECK(!last_frame_time.is_null()); @@ -294,19 +296,48 @@ DocumentLifecycle::AllowThrottlingScope throttling_scope( LocalRootImpl()->GetFrame()->GetDocument()->Lifecycle()); - PageWidgetDelegate::Animate(*GetPage(), last_frame_time); + if (record_main_frame_metrics) { + SCOPED_UMA_AND_UKM_TIMER( + LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator(), + LocalFrameUkmAggregator::kAnimate); + PageWidgetDelegate::Animate(*GetPage(), last_frame_time); + } else { + PageWidgetDelegate::Animate(*GetPage(), last_frame_time); + } // Animate can cause the local frame to detach. if (LocalRootImpl()) GetPage()->GetValidationMessageClient().LayoutOverlay(); } +void WebFrameWidgetImpl::BeginRafAlignedInput() { + raf_aligned_input_start_time_ = CurrentTimeTicks(); +} + +void WebFrameWidgetImpl::EndRafAlignedInput() { + if (LocalRootImpl()) { + LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample( + LocalFrameUkmAggregator::kHandleInputEvents, + raf_aligned_input_start_time_, CurrentTimeTicks()); + } +} + +void WebFrameWidgetImpl::RecordStartOfFrameMetrics() { + if (!LocalRootImpl()) + return; + + LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().BeginMainFrame(); +} + void WebFrameWidgetImpl::RecordEndOfFrameMetrics( base::TimeTicks frame_begin_time) { if (!LocalRootImpl()) return; - LocalRootImpl()->GetFrame()->View()->RecordEndOfFrameMetrics( - frame_begin_time); + LocalRootImpl() + ->GetFrame() + ->View() + ->EnsureUkmAggregator() + .RecordEndOfFrameMetrics(frame_begin_time, CurrentTimeTicks()); } void WebFrameWidgetImpl::UpdateLifecycle(LifecycleUpdate requested_update,
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index 622592b..283b04a 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -84,7 +84,11 @@ void DidEnterFullscreen() override; void DidExitFullscreen() override; void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final; - void BeginFrame(base::TimeTicks last_frame_time) override; + void BeginFrame(base::TimeTicks last_frame_time, + bool record_main_frame_metrics) override; + void BeginRafAlignedInput() override; + void EndRafAlignedInput() override; + void RecordStartOfFrameMetrics() override; void RecordEndOfFrameMetrics(base::TimeTicks) override; void UpdateLifecycle(LifecycleUpdate requested_update, LifecycleUpdateReason reason) override; @@ -204,6 +208,7 @@ scoped_refptr<cc::Layer> root_layer_; GraphicsLayer* root_graphics_layer_; std::unique_ptr<CompositorAnimationHost> animation_host_; + base::TimeTicks raf_aligned_input_start_time_; bool is_accelerated_compositing_active_; bool layer_tree_view_closed_;
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc index 8831aaf..4e358507 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -56,8 +56,21 @@ web_view_->SetSuppressFrameRequestsWorkaroundFor704763Only( suppress_frame_requests); } -void WebViewFrameWidget::BeginFrame(base::TimeTicks last_frame_time) { - web_view_->BeginFrame(last_frame_time); +void WebViewFrameWidget::BeginFrame(base::TimeTicks last_frame_time, + bool record_main_frame_metrics) { + web_view_->BeginFrame(last_frame_time, record_main_frame_metrics); +} + +void WebViewFrameWidget::BeginRafAlignedInput() { + web_view_->BeginRafAlignedInput(); +} + +void WebViewFrameWidget::EndRafAlignedInput() { + web_view_->EndRafAlignedInput(); +} + +void WebViewFrameWidget::RecordStartOfFrameMetrics() { + web_view_->RecordStartOfFrameMetrics(); } void WebViewFrameWidget::RecordEndOfFrameMetrics(
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h index fdffbc9..6c8832ed 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -48,7 +48,11 @@ void DidEnterFullscreen() override; void DidExitFullscreen() override; void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final; - void BeginFrame(base::TimeTicks last_frame_time) override; + void BeginFrame(base::TimeTicks last_frame_time, + bool record_main_frame_metrics) override; + void BeginRafAlignedInput() override; + void EndRafAlignedInput() override; + void RecordStartOfFrameMetrics() override; void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override; void UpdateLifecycle(LifecycleUpdate requested_update, LifecycleUpdateReason reason) override;
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index af63c781..bcd91590 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -44,6 +44,7 @@ #include "third_party/blink/renderer/core/css/css_font_selector.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" @@ -1528,6 +1529,9 @@ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && GetLayoutObject() && GetLayoutObject()->HasLayer()) GetLayoutBoxModelObject()->Layer()->SetNeedsRepaint(); + + if (auto* layer = ContentsCcLayer()) + layer->set_owner_node_id(DOMNodeIds::IdForNode(this)); } } // namespace blink
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index fe485736..b45129b6 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -51,6 +51,7 @@ #include "third_party/blink/renderer/core/css/media_list.h" #include "third_party/blink/renderer/core/dom/attribute.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" +#include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/element_visibility_observer.h" #include "third_party/blink/renderer/core/dom/events/event.h" @@ -3962,8 +3963,10 @@ if (cc_layer_) GraphicsLayer::UnregisterContentsLayer(cc_layer_); cc_layer_ = cc_layer; - if (cc_layer_) + if (cc_layer_) { GraphicsLayer::RegisterContentsLayer(cc_layer_); + cc_layer_->set_owner_node_id(DOMNodeIds::IdForNode(this)); + } } void HTMLMediaElement::MediaSourceOpened(WebMediaSource* web_media_source) {
diff --git a/third_party/blink/renderer/core/html/parser/preload_request.cc b/third_party/blink/renderer/core/html/parser/preload_request.cc index 889dbb73..8cea788 100644 --- a/third_party/blink/renderer/core/html/parser/preload_request.cc +++ b/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -43,8 +43,8 @@ if (referrer_source_ == kBaseUrlIsReferrer) resource_request.SetReferrerString(base_url_.StrippedForUseAsReferrer()); - resource_request.SetRequestContext(ResourceFetcher::DetermineRequestContext( - resource_type_, is_image_set_, false)); + resource_request.SetRequestContext( + ResourceFetcher::DetermineRequestContext(resource_type_, is_image_set_)); resource_request.SetFetchImportanceMode(importance_);
diff --git a/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc b/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc index d7f42bc..7e20a15 100644 --- a/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc
@@ -268,9 +268,17 @@ Response InspectorLayerTreeAgent::enable() { instrumenting_agents_->addInspectorLayerTreeAgent(this); Document* document = inspected_frames_->Root()->GetDocument(); - if (document && - document->Lifecycle().GetState() >= DocumentLifecycle::kCompositingClean) + if (!document) + return Response::Error("The root frame doesn't have document"); + + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || + RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + if (document->Lifecycle().GetState() >= DocumentLifecycle::kPaintClean) + LayerTreePainted(); + } else if (document->Lifecycle().GetState() >= + DocumentLifecycle::kCompositingClean) { LayerTreeDidChange(); + } return Response::OK(); } @@ -281,12 +289,15 @@ } void InspectorLayerTreeAgent::LayerTreeDidChange() { + DCHECK(!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() && + !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); GetFrontend()->layerTreeDidChange(BuildLayerTree()); } void InspectorLayerTreeAgent::DidPaint(const cc::Layer* layer, - GraphicsContext&, const LayoutRect& rect) { + DCHECK(!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() && + !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); if (suppress_layer_paint_events_) return; @@ -304,6 +315,21 @@ GetFrontend()->layerPainted(IdForLayer(layer), std::move(dom_rect)); } +void InspectorLayerTreeAgent::LayerTreePainted() { + DCHECK(RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || + RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); + + GetFrontend()->layerTreeDidChange(BuildLayerTree()); + + for (const auto& layer : + inspected_frames_->Root()->View()->RootCcLayer()->children()) { + if (!layer->update_rect().IsEmpty()) { + GetFrontend()->layerPainted(IdForLayer(layer.get()), + BuildObjectForRect(layer->update_rect())); + } + } +} + std::unique_ptr<Array<protocol::LayerTree::Layer>> InspectorLayerTreeAgent::BuildLayerTree() { const auto* root_layer = RootLayer();
diff --git a/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h b/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h index 6346595..5229321 100644 --- a/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h
@@ -44,7 +44,6 @@ namespace blink { -class GraphicsContext; class InspectedFrames; class LayoutRect; class PictureSnapshot; @@ -72,7 +71,8 @@ // Called from InspectorInstrumentation void LayerTreeDidChange(); - void DidPaint(const cc::Layer*, GraphicsContext&, const LayoutRect&); + void DidPaint(const cc::Layer*, const LayoutRect&); + void LayerTreePainted(); // Called from the front-end. protocol::Response enable() override;
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc index cbfc3b68..765fb6e 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -747,14 +747,7 @@ const FetchInitiatorInfo& initiator_info, InspectorPageAgent::ResourceType type) { String loader_id = IdentifiersFactory::LoaderId(loader); - // DocumentLoader doesn't have main resource set at the point, so RequestId() - // won't properly detect main resource. Workaround this by checking the - // frame type and manually setting request id to loader id. String request_id = IdentifiersFactory::RequestId(loader, identifier); - bool is_navigation = - request.GetFrameType() != network::mojom::RequestContextFrameType::kNone; - if (is_navigation) - request_id = loader_id; NetworkResourcesData::ResourceData const* data = resources_data_->Data(request_id); // Support for POST request redirect @@ -775,9 +768,6 @@ type = pending_request_type_; resources_data_->SetResourceType(request_id, type); - if (is_navigation) - return; - String frame_id = loader && loader->GetFrame() ? IdentifiersFactory::FrameId(loader->GetFrame()) : ""; @@ -827,6 +817,29 @@ pending_request_ = nullptr; } +void InspectorNetworkAgent::WillSendNavigationRequest( + ExecutionContext* execution_context, + unsigned long identifier, + DocumentLoader* loader, + const KURL& url, + const AtomicString& http_method, + EncodedFormData* http_body) { + String loader_id = IdentifiersFactory::LoaderId(loader); + String request_id = loader_id; + NetworkResourcesData::ResourceData const* data = + resources_data_->Data(request_id); + // Support for POST request redirect. + scoped_refptr<EncodedFormData> post_data; + if (data) + post_data = data->PostData(); + else if (http_body) + post_data = http_body->DeepCopy(); + resources_data_->ResourceCreated(execution_context, request_id, loader_id, + url, post_data); + resources_data_->SetResourceType(request_id, + InspectorPageAgent::kDocumentResource); +} + void InspectorNetworkAgent::WillSendRequest( ExecutionContext* execution_context, unsigned long identifier, @@ -839,10 +852,6 @@ if (initiator_info.name == fetch_initiator_type_names::kInternal) return; - if (initiator_info.name == fetch_initiator_type_names::kDocument && - loader->HasSubstituteData()) - return; - if (!extra_request_headers_.IsEmpty()) { for (const WTF::String& key : extra_request_headers_.Keys()) { const WTF::String& value = extra_request_headers_.Get(key); @@ -918,9 +927,6 @@ saved_type == InspectorPageAgent::kEventSourceResource) { type = saved_type; } - if (type == InspectorPageAgent::kDocumentResource && loader && - loader->HasSubstituteData()) - return; // Resources are added to NetworkResourcesData as a WeakMember here and // removed in willDestroyResource() called in the prefinalizer of Resource.
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.h b/third_party/blink/renderer/core/inspector/inspector_network_agent.h index e37e634..6cc00cd 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.h
@@ -101,6 +101,12 @@ const ResourceResponse& redirect_response, const FetchInitiatorInfo&, ResourceType); + void WillSendNavigationRequest(ExecutionContext*, + unsigned long identifier, + DocumentLoader*, + const KURL&, + const AtomicString& http_method, + EncodedFormData* http_body); void MarkResourceAsCached(DocumentLoader*, unsigned long identifier); void DidReceiveResourceResponse(unsigned long identifier, DocumentLoader*,
diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc index fb2982364f..1e07683 100644 --- a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
@@ -203,8 +203,7 @@ return type == ResourceType::kCSSStyleSheet || type == ResourceType::kXSLStyleSheet || type == ResourceType::kScript || type == ResourceType::kRaw || - type == ResourceType::kImportResource || - type == ResourceType::kMainResource; + type == ResourceType::kImportResource; } static std::unique_ptr<TextResourceDecoder> CreateResourceTextDecoder( @@ -430,8 +429,6 @@ case blink::ResourceType::kScript: return InspectorPageAgent::kScriptResource; case blink::ResourceType::kImportResource: - // Fall through. - case blink::ResourceType::kMainResource: return InspectorPageAgent::kDocumentResource; default: break;
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 0069c74c..11cc66c 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -116,6 +116,20 @@ inspector_send_request_event::Data(loader, identifier, frame, request)); } +void InspectorTraceEvents::WillSendNavigationRequest( + ExecutionContext*, + unsigned long identifier, + DocumentLoader* loader, + const KURL& url, + const AtomicString& http_method, + EncodedFormData*) { + LocalFrame* frame = loader ? loader->GetFrame() : nullptr; + TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceSendRequest", + TRACE_EVENT_SCOPE_THREAD, "data", + inspector_send_navigation_request_event::Data( + loader, identifier, frame, url, http_method)); +} + void InspectorTraceEvents::DidReceiveResourceResponse( unsigned long identifier, DocumentLoader* loader, @@ -759,6 +773,25 @@ return value; } +std::unique_ptr<TracedValue> inspector_send_navigation_request_event::Data( + DocumentLoader* loader, + unsigned long identifier, + LocalFrame* frame, + const KURL& url, + const AtomicString& http_method) { + std::unique_ptr<TracedValue> value = TracedValue::Create(); + value->SetString("requestId", IdentifiersFactory::LoaderId(loader)); + value->SetString("frame", IdentifiersFactory::FrameId(frame)); + value->SetString("url", url.GetString()); + value->SetString("requestMethod", http_method); + const char* priority = + ResourcePriorityString(ResourceLoadPriority::kVeryHigh); + if (priority) + value->SetString("priority", priority); + SetCallStack(value.get()); + return value; +} + namespace { void RecordTiming(const ResourceLoadTiming& timing, TracedValue* value) { value->SetDouble("requestTime", TimeTicksInSeconds(timing.RequestTime()));
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.h b/third_party/blink/renderer/core/inspector/inspector_trace_events.h index 92a8ae8..691c2a5 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.h +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.h
@@ -43,6 +43,7 @@ class Document; class DocumentLoader; class Element; +class EncodedFormData; class Event; class ExecutionContext; struct FetchInitiatorInfo; @@ -89,6 +90,12 @@ const ResourceResponse& redirect_response, const FetchInitiatorInfo&, ResourceType); + void WillSendNavigationRequest(ExecutionContext*, + unsigned long identifier, + DocumentLoader*, + const KURL&, + const AtomicString& http_method, + EncodedFormData*); void DidReceiveResourceResponse(unsigned long identifier, DocumentLoader*, const ResourceResponse&, @@ -275,6 +282,14 @@ const ResourceRequest&); } +namespace inspector_send_navigation_request_event { +std::unique_ptr<TracedValue> Data(DocumentLoader*, + unsigned long identifier, + LocalFrame*, + const KURL&, + const AtomicString& http_method); +} + namespace inspector_receive_response_event { std::unique_ptr<TracedValue> Data(DocumentLoader*, unsigned long identifier,
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 54653b22..a377c5e5 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1550,6 +1550,10 @@ return name.ToString(); } +DOMNodeId LayoutObject::OwnerNodeId() const { + return GetNode() ? DOMNodeIds::IdForNode(GetNode()) : kInvalidDOMNodeId; +} + LayoutRect LayoutObject::FragmentsVisualRectBoundingBox() const { if (!fragment_.NextFragment()) return fragment_.VisualRect();
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 721856e3..6128199 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -266,6 +266,8 @@ .SetPartialInvalidationVisualRect(LayoutRect()); } + DOMNodeId OwnerNodeId() const final; + public: LayoutRect PartialInvalidationVisualRect() const final { return FirstFragment().PartialInvalidationVisualRect();
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc index 821393f..846f7b76 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc
@@ -33,26 +33,11 @@ return GetData().IsBidiEnabled(); } -const NGInlineItem& NGCaretNavigator::GetItem(unsigned index) const { - const auto& items = GetData().items; - const NGInlineItem* item = - std::lower_bound(items.begin(), items.end(), index, - [](const NGInlineItem& item, unsigned index) { - if (item.StartOffset() > index) - return false; - return item.EndOffset() <= index; - }); - DCHECK_NE(item, items.end()); - DCHECK_LE(item->StartOffset(), index); - DCHECK_LT(index, item->EndOffset()); - return *item; -} - UBiDiLevel NGCaretNavigator::BidiLevelAt(unsigned index) const { DCHECK_LT(index, GetText().length()); if (!IsBidiEnabled()) return 0; - return GetItem(index).BidiLevel(); + return GetData().FindItemForTextOffset(index).BidiLevel(); } TextDirection NGCaretNavigator::TextDirectionAt(unsigned index) const { @@ -73,6 +58,7 @@ NGCaretNavigator::CaretPositionFromTextContentOffsetAndAffinity( unsigned offset, TextAffinity affinity) const { + DCHECK_LE(offset, GetText().length()); // Callers sometimes pass in (0, upstream) or (length, downstream), which // originate from legacy callers. Make sure they are fixed up. // TODO(xiaochengh): Catch and eliminate such callers.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc index a22d01eb..a054069 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc
@@ -275,4 +275,20 @@ is_end_collapsible_newline_ = is_newline; } +const NGInlineItem& NGInlineItemsData::FindItemForTextOffset( + unsigned offset) const { + DCHECK_LT(offset, text_content.length()); + const NGInlineItem* item = + std::lower_bound(items.begin(), items.end(), offset, + [](const NGInlineItem& item, unsigned offset) { + if (item.StartOffset() > offset) + return false; + return item.EndOffset() <= offset; + }); + DCHECK_NE(item, items.end()); + DCHECK_LE(item->StartOffset(), offset); + DCHECK_LT(offset, item->EndOffset()); + return *item; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h index 7604cd2..c74ae29 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
@@ -224,6 +224,11 @@ void AssertEndOffset(unsigned index, unsigned offset) const { items[index].AssertEndOffset(offset); } + + // Returns the non-zero-length inline item whose |StartOffset() <= offset| and + // |EndOffset() > offset|, namely, contains the character at |offset|. + // Note: This function is not a trivial getter, but does a binary search. + const NGInlineItem& FindItemForTextOffset(unsigned offset) const; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc index 040374a..d97fcb0a 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -92,41 +92,36 @@ } // namespace -void BaseFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request, - FetchResourceType type) { +void BaseFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request) { const FetchClientSettingsObject& fetch_client_settings_object = GetResourceFetcherProperties().GetFetchClientSettingsObject(); - bool is_main_resource = type == kFetchMainResource; - if (!is_main_resource) { - // TODO(domfarolino): we can probably *just set* the HTTP `Referer` here - // no matter what now. - if (!request.DidSetHTTPReferrer()) { - String referrer_to_use = request.ReferrerString(); - network::mojom::ReferrerPolicy referrer_policy_to_use = - request.GetReferrerPolicy(); + // TODO(domfarolino): we can probably *just set* the HTTP `Referer` here + // no matter what now. + if (!request.DidSetHTTPReferrer()) { + String referrer_to_use = request.ReferrerString(); + network::mojom::ReferrerPolicy referrer_policy_to_use = + request.GetReferrerPolicy(); - if (referrer_to_use == Referrer::ClientReferrerString()) - referrer_to_use = fetch_client_settings_object.GetOutgoingReferrer(); + if (referrer_to_use == Referrer::ClientReferrerString()) + referrer_to_use = fetch_client_settings_object.GetOutgoingReferrer(); - if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault) { - referrer_policy_to_use = - fetch_client_settings_object.GetReferrerPolicy(); - } - - // TODO(domfarolino): Stop storing ResourceRequest's referrer as a header - // and store it elsewhere. See https://crbug.com/850813. - request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer( - referrer_policy_to_use, request.Url(), referrer_to_use)); - request.SetHTTPOriginIfNeeded( - fetch_client_settings_object.GetSecurityOrigin()); - } else { - CHECK_EQ(SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(), - request.Url(), - request.HttpReferrer()) - .referrer, - request.HttpReferrer()); - request.SetHTTPOriginToMatchReferrerIfNeeded(); + if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault) { + referrer_policy_to_use = fetch_client_settings_object.GetReferrerPolicy(); } + + // TODO(domfarolino): Stop storing ResourceRequest's referrer as a header + // and store it elsewhere. See https://crbug.com/850813. + request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer( + referrer_policy_to_use, request.Url(), referrer_to_use)); + request.SetHTTPOriginIfNeeded( + fetch_client_settings_object.GetSecurityOrigin()); + } else { + CHECK_EQ( + SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(), + request.Url(), request.HttpReferrer()) + .referrer, + request.HttpReferrer()); + request.SetHTTPOriginToMatchReferrerIfNeeded(); } auto address_space = GetAddressSpace(); @@ -194,9 +189,8 @@ SubresourceFilter* filter = GetSubresourceFilter(); // We do not need main document tagging currently so skipping main resources. - if (filter && type != ResourceType::kMainResource) { + if (filter) return filter->IsAdResource(resource_url, request_context); - } return false; } @@ -333,8 +327,7 @@ // SVG Images have unique security rules that prevent all subresource requests // except for data urls. - if (type != ResourceType::kMainResource && IsSVGImageChromeClient() && - !url.ProtocolIsData()) + if (IsSVGImageChromeClient() && !url.ProtocolIsData()) return ResourceRequestBlockedReason::kOrigin; network::mojom::RequestContextFrameType frame_type = @@ -386,8 +379,7 @@ // Let the client have the final say into whether or not the load should // proceed. - if (GetSubresourceFilter() && type != ResourceType::kMainResource && - type != ResourceType::kImportResource) { + if (GetSubresourceFilter() && type != ResourceType::kImportResource) { if (!GetSubresourceFilter()->AllowLoad(url, request_context, reporting_policy)) { return ResourceRequestBlockedReason::kSubresourceFilter;
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third_party/blink/renderer/core/loader/base_fetch_context.h index ed614f9..07497fa 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.h +++ b/third_party/blink/renderer/core/loader/base_fetch_context.h
@@ -30,8 +30,7 @@ // Frame. This class provides basic default implementation for some methods. class CORE_EXPORT BaseFetchContext : public FetchContext { public: - void AddAdditionalRequestHeaders(ResourceRequest&, - FetchResourceType) override; + void AddAdditionalRequestHeaders(ResourceRequest&) override; base::Optional<ResourceRequestBlockedReason> CanRequest( ResourceType, const ResourceRequest&,
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc index b09e1c1..01f04b8 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
@@ -168,14 +168,8 @@ ScopedCorsRFC1918ForTest cors_rfc1918(false); for (const auto& test : cases) { SCOPED_TRACE(test.url); - ResourceRequest main_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(main_request, - kFetchMainResource); - EXPECT_FALSE(main_request.IsExternalRequest()); - ResourceRequest sub_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(sub_request, - kFetchSubresource); + fetch_context_->AddAdditionalRequestHeaders(sub_request); EXPECT_FALSE(sub_request.IsExternalRequest()); } } @@ -184,14 +178,8 @@ ScopedCorsRFC1918ForTest cors_rfc1918(true); for (const auto& test : cases) { SCOPED_TRACE(test.url); - ResourceRequest main_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(main_request, - kFetchMainResource); - EXPECT_EQ(test.is_external_expectation, main_request.IsExternalRequest()); - ResourceRequest sub_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(sub_request, - kFetchSubresource); + fetch_context_->AddAdditionalRequestHeaders(sub_request); EXPECT_EQ(test.is_external_expectation, sub_request.IsExternalRequest()); } } @@ -220,14 +208,8 @@ ScopedCorsRFC1918ForTest cors_rfc1918(false); for (const auto& test : cases) { SCOPED_TRACE(test.url); - ResourceRequest main_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(main_request, - kFetchMainResource); - EXPECT_FALSE(main_request.IsExternalRequest()); - ResourceRequest sub_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(sub_request, - kFetchSubresource); + fetch_context_->AddAdditionalRequestHeaders(sub_request); EXPECT_FALSE(sub_request.IsExternalRequest()); } } @@ -236,14 +218,8 @@ ScopedCorsRFC1918ForTest cors_rfc1918(true); for (const auto& test : cases) { SCOPED_TRACE(test.url); - ResourceRequest main_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(main_request, - kFetchMainResource); - EXPECT_EQ(test.is_external_expectation, main_request.IsExternalRequest()); - ResourceRequest sub_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(sub_request, - kFetchSubresource); + fetch_context_->AddAdditionalRequestHeaders(sub_request); EXPECT_EQ(test.is_external_expectation, sub_request.IsExternalRequest()); } } @@ -271,14 +247,8 @@ { ScopedCorsRFC1918ForTest cors_rfc1918(false); for (const auto& test : cases) { - ResourceRequest main_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(main_request, - kFetchMainResource); - EXPECT_FALSE(main_request.IsExternalRequest()); - ResourceRequest sub_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(sub_request, - kFetchSubresource); + fetch_context_->AddAdditionalRequestHeaders(sub_request); EXPECT_FALSE(sub_request.IsExternalRequest()); } } @@ -286,14 +256,8 @@ { ScopedCorsRFC1918ForTest cors_rfc1918(true); for (const auto& test : cases) { - ResourceRequest main_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(main_request, - kFetchMainResource); - EXPECT_EQ(test.is_external_expectation, main_request.IsExternalRequest()); - ResourceRequest sub_request(test.url); - fetch_context_->AddAdditionalRequestHeaders(sub_request, - kFetchSubresource); + fetch_context_->AddAdditionalRequestHeaders(sub_request); EXPECT_EQ(test.is_external_expectation, sub_request.IsExternalRequest()); } }
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index f9d060e..665324f 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -79,6 +79,7 @@ #include "third_party/blink/renderer/core/timing/window_performance.h" #include "third_party/blink/renderer/platform/bindings/microtask.h" #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" +#include "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" #include "third_party/blink/renderer/platform/loader/cors/cors.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h" @@ -936,12 +937,13 @@ void DocumentLoader::SetDefersLoading(bool defers) { defers_loading_ = defers; Fetcher()->SetDefersLoading(defers); - if (body_loader_) + if (body_loader_) { body_loader_->SetDefersLoading(defers); - if (defers_loading_) - virtual_time_pauser_.UnpauseVirtualTime(); - else - virtual_time_pauser_.PauseVirtualTime(); + if (defers_loading_) + virtual_time_pauser_.UnpauseVirtualTime(); + else + virtual_time_pauser_.PauseVirtualTime(); + } } void DocumentLoader::DetachFromFrame(bool flush_microtask_queue) { @@ -1106,8 +1108,7 @@ main_resource_identifier_ = CreateUniqueIdentifier(); navigation_timing_info_ = ResourceTimingInfo::Create( - fetch_initiator_type_names::kDocument, GetTiming().NavigationStart(), - true /* is_main_resource */); + fetch_initiator_type_names::kDocument, GetTiming().NavigationStart()); navigation_timing_info_->SetInitialURL(url_); report_timing_info_to_parent_ = ShouldReportTimingInfoToParent(); @@ -1123,24 +1124,23 @@ // Many parties are interested in resource loading, so we will notify // them through various DispatchXXX methods on FrameFetchContext. - // TODO(dgozman): get rid of fake request and initiator info, we only use them - // for DispatchWillSendRequest. - ResourceRequest fake_request; - fake_request.SetURL(url_); - fake_request.SetPriority(WebURLRequest::Priority::kVeryHigh); - fake_request.SetHTTPBody(http_body_); - fake_request.SetFrameType( - frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel - : network::mojom::RequestContextFrameType::kNested); - fake_request.SetRequestContext(mojom::RequestContextType::HYPERLINK); - FetchInitiatorInfo initiator_info; - initiator_info.name = fetch_initiator_type_names::kDocument; - fetcher_->Context().RecordLoadingActivity( - fake_request, ResourceType::kMainResource, - fetch_initiator_type_names::kDocument); - fetcher_->Context().DispatchWillSendRequest( - main_resource_identifier_, fake_request, ResourceResponse(), - ResourceType::kMainResource, initiator_info); + if (!fetcher_->Archive()) { + V8DOMActivityLogger* activity_logger = + V8DOMActivityLogger::CurrentActivityLoggerIfIsolatedWorld(); + if (activity_logger) { + Vector<String> argv; + argv.push_back("Main resource"); + argv.push_back(url_.GetString()); + activity_logger->LogEvent("blinkRequestResource", argv.size(), + argv.data()); + } + } + + GetFrameLoader().Progress().WillStartLoading(main_resource_identifier_, + ResourceLoadPriority::kVeryHigh); + probe::willSendNavigationRequest(GetFrame()->GetDocument(), + main_resource_identifier_, this, url_, + http_method_, http_body_.get()); for (size_t i = 0; i < params_->redirects.size(); ++i) { WebNavigationParams::RedirectInfo& redirect = params_->redirects[i]; @@ -1148,7 +1148,6 @@ AtomicString new_http_method = redirect.new_http_method; if (http_method_ != new_http_method) { http_body_ = nullptr; - fake_request.SetHTTPBody(nullptr); http_method_ = new_http_method; } if (redirect.new_referrer.IsEmpty()) { @@ -1160,16 +1159,22 @@ http_content_type_ = g_null_atom; // TODO(dgozman): check whether clearing origin policy is intended behavior. origin_policy_ = String(); - fake_request.SetURL(url_); + probe::willSendNavigationRequest(GetFrame()->GetDocument(), + main_resource_identifier_, this, url_, + http_method_, http_body_.get()); ResourceResponse redirect_response = redirect.redirect_response.ToResourceResponse(); - fetcher_->Context().DispatchWillSendRequest( - main_resource_identifier_, fake_request, redirect_response, - ResourceType::kMainResource, initiator_info); navigation_timing_info_->AddRedirect(redirect_response, url_); HandleRedirect(redirect_response.CurrentRequestUrl()); } + // TODO(dgozman): get rid of fake request, we only use it for + // DispatchDidReceiveResponse. + ResourceRequest fake_request; + fake_request.SetFrameType( + frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel + : network::mojom::RequestContextFrameType::kNested); + fake_request.SetRequestContext(mojom::RequestContextType::HYPERLINK); fetcher_->Context().DispatchDidReceiveResponse( main_resource_identifier_, fake_request, final_response, nullptr, FetchContext::ResourceResponseType::kNotFromMemoryCache);
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index 6b84959..f2a9e82 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -157,7 +157,6 @@ return state_ >= kCommitted && !data_received_; } - bool HasSubstituteData() const { return has_substitute_data_; } void FillNavigationParamsForErrorPage(WebNavigationParams*); // Without PlzNavigate, this is only false for a narrow window during
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc index bc3130e..629ee8a 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -122,19 +122,15 @@ "AllowClientHintsToThirdParty", base::FEATURE_DISABLED_BY_DEFAULT}; #endif -enum class RequestMethod { kIsPost, kIsNotPost }; -enum class RequestType { kIsConditional, kIsNotConditional }; -enum class MainResourceType { kIsMainResource, kIsNotMainResource }; - void MaybeRecordCTPolicyComplianceUseCounter( LocalFrame* frame, - ResourceType resource_type, + bool is_main_resource, ResourceResponse::CTPolicyCompliance compliance, DocumentLoader* loader) { if (compliance != ResourceResponse::kCTPolicyDoesNotComply) return; // Exclude main-frame navigation requests; those are tracked elsewhere. - if (!frame->Tree().Parent() && resource_type == ResourceType::kMainResource) + if (!frame->Tree().Parent() && is_main_resource) return; if (loader) { loader->GetUseCounter().Count( @@ -146,66 +142,21 @@ } } -void RecordLegacySymantecCertUseCounter(LocalFrame* frame, - ResourceType resource_type) { - // Main resources are counted in DocumentLoader. - if (resource_type == ResourceType::kMainResource) { - return; - } - UseCounter::Count(frame, WebFeature::kLegacySymantecCertInSubresource); -} - -// Determines FetchCacheMode for a main resource, or FetchCacheMode that is -// corresponding to WebFrameLoadType. -// TODO(toyoshim): Probably, we should split WebFrameLoadType to FetchCacheMode -// conversion logic into a separate function. -mojom::FetchCacheMode DetermineCacheMode(RequestMethod method, - RequestType request_type, - MainResourceType resource_type, - WebFrameLoadType load_type) { - switch (load_type) { - case WebFrameLoadType::kStandard: - case WebFrameLoadType::kReplaceCurrentItem: - return (request_type == RequestType::kIsConditional || - method == RequestMethod::kIsPost) - ? mojom::FetchCacheMode::kValidateCache - : mojom::FetchCacheMode::kDefault; - case WebFrameLoadType::kBackForward: - // Mutates the policy for POST requests to avoid form resubmission. - return method == RequestMethod::kIsPost - ? mojom::FetchCacheMode::kOnlyIfCached - : mojom::FetchCacheMode::kForceCache; - case WebFrameLoadType::kReload: - return resource_type == MainResourceType::kIsMainResource - ? mojom::FetchCacheMode::kValidateCache - : mojom::FetchCacheMode::kDefault; - case WebFrameLoadType::kReloadBypassingCache: - return mojom::FetchCacheMode::kBypassCache; - } - NOTREACHED(); - return mojom::FetchCacheMode::kDefault; -} - // Determines FetchCacheMode for |frame|. This FetchCacheMode should be a base // policy to consider one of each resource belonging to the frame, and should // not count resource specific conditions in. -// TODO(toyoshim): Remove |resourceType| to realize the design described above. -// See also comments in resourceRequestCachePolicy(). -mojom::FetchCacheMode DetermineFrameCacheMode(Frame* frame, - MainResourceType resource_type) { +mojom::FetchCacheMode DetermineFrameCacheMode(Frame* frame) { if (!frame) return mojom::FetchCacheMode::kDefault; if (!frame->IsLocalFrame()) - return DetermineFrameCacheMode(frame->Tree().Parent(), resource_type); + return DetermineFrameCacheMode(frame->Tree().Parent()); // Does not propagate cache policy for subresources after the load event. // TODO(toyoshim): We should be able to remove following parents' policy check // if each frame has a relevant WebFrameLoadType for reload and history // navigations. - if (resource_type == MainResourceType::kIsNotMainResource && - ToLocalFrame(frame)->GetDocument()->LoadEventFinished()) { + if (ToLocalFrame(frame)->GetDocument()->LoadEventFinished()) return mojom::FetchCacheMode::kDefault; - } // Respects BypassingCache rather than parent's policy. WebFrameLoadType load_type = @@ -215,15 +166,25 @@ // Respects parent's policy if it has a special one. mojom::FetchCacheMode parent_cache_mode = - DetermineFrameCacheMode(frame->Tree().Parent(), resource_type); + DetermineFrameCacheMode(frame->Tree().Parent()); if (parent_cache_mode != mojom::FetchCacheMode::kDefault) return parent_cache_mode; - // Otherwise, follows WebFrameLoadType. Use kIsNotPost, kIsNotConditional, and - // kIsNotMainResource to obtain a representative policy for the frame. - return DetermineCacheMode(RequestMethod::kIsNotPost, - RequestType::kIsNotConditional, - MainResourceType::kIsNotMainResource, load_type); + // Otherwise, follows WebFrameLoadType. + switch (load_type) { + case WebFrameLoadType::kStandard: + case WebFrameLoadType::kReplaceCurrentItem: + return mojom::FetchCacheMode::kDefault; + case WebFrameLoadType::kBackForward: + // Mutates the policy for POST requests to avoid form resubmission. + return mojom::FetchCacheMode::kForceCache; + case WebFrameLoadType::kReload: + return mojom::FetchCacheMode::kDefault; + case WebFrameLoadType::kReloadBypassingCache: + return mojom::FetchCacheMode::kBypassCache; + } + NOTREACHED(); + return mojom::FetchCacheMode::kDefault; } } // namespace @@ -371,9 +332,8 @@ return GetFrame()->Client(); } -void FrameFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request, - FetchResourceType type) { - BaseFetchContext::AddAdditionalRequestHeaders(request, type); +void FrameFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request) { + BaseFetchContext::AddAdditionalRequestHeaders(request); // The remaining modifications are only necessary for HTTP and HTTPS. if (!request.Url().IsEmpty() && !request.Url().ProtocolIsInHTTPFamily()) @@ -426,27 +386,7 @@ return mojom::FetchCacheMode::kDefault; DCHECK(GetFrame()); - if (type == ResourceType::kMainResource) { - const auto cache_mode = DetermineCacheMode( - request.HttpMethod() == http_names::kPOST ? RequestMethod::kIsPost - : RequestMethod::kIsNotPost, - request.IsConditional() ? RequestType::kIsConditional - : RequestType::kIsNotConditional, - MainResourceType::kIsMainResource, MasterDocumentLoader()->LoadType()); - // Follows the parent frame's policy. - // TODO(toyoshim): Probably, WebFrameLoadType for each frame should have a - // right type for reload or history navigations, and should not need to - // check parent's frame policy here. Once it has a right WebFrameLoadType, - // we can remove Resource::Type argument from determineFrameCacheMode. - // See also crbug.com/332602. - if (cache_mode != mojom::FetchCacheMode::kDefault) - return cache_mode; - return DetermineFrameCacheMode(GetFrame()->Tree().Parent(), - MainResourceType::kIsMainResource); - } - - const auto cache_mode = - DetermineFrameCacheMode(GetFrame(), MainResourceType::kIsNotMainResource); + const auto cache_mode = DetermineFrameCacheMode(GetFrame()); // TODO(toyoshim): Revisit to consider if this clause can be merged to // determineWebCachePolicy or determineFrameCacheMode. @@ -556,16 +496,15 @@ if (IsDetached()) return; - // Note: resource can be null for navigations. - ResourceType resource_type = - resource ? resource->GetType() : ResourceType::kMainResource; + // Note: resource is null if and only if this is a navigation response. + bool is_main_resource = !resource; if (GetSubresourceFilter() && resource && resource->GetResourceRequest().IsAdResource()) { GetSubresourceFilter()->ReportAdRequestId(response.RequestId()); } - MaybeRecordCTPolicyComplianceUseCounter(GetFrame(), resource_type, + MaybeRecordCTPolicyComplianceUseCounter(GetFrame(), is_main_resource, response.GetCTPolicyCompliance(), MasterDocumentLoader()); @@ -594,19 +533,13 @@ // haven't committed yet, and we cannot load resources, only preconnect. resource_loading_policy = PreloadHelper::kDoNotLoadResources; } - // Client hints preferences should be persisted only from responses that were - // served by the same host as the host of the document-level origin. - KURL frame_url = Url(); - if (frame_url == NullURL()) - frame_url = GetDocumentLoader()->Url(); // The accept-ch-lifetime header is honored only on the navigation responses. // Further, the navigation response should be from a top level frame (i.e., // main frame) or the origin of the response should match the origin of the // top level frame. - if (resource_type == ResourceType::kMainResource && - (GetResourceFetcherProperties().IsMainFrame() || - IsFirstPartyOrigin(response.CurrentRequestUrl()))) { + if (is_main_resource && (GetResourceFetcherProperties().IsMainFrame() || + IsFirstPartyOrigin(response.CurrentRequestUrl()))) { ParseAndPersistClientHints(response); } @@ -623,13 +556,17 @@ } if (response.IsLegacySymantecCert()) { - RecordLegacySymantecCertUseCounter(GetFrame(), resource_type); + if (!is_main_resource) { + // Main resources are counted in DocumentLoader. + UseCounter::Count(GetFrame(), + WebFeature::kLegacySymantecCertInSubresource); + } GetLocalFrameClient()->ReportLegacySymantecCert( response.CurrentRequestUrl(), false /* did_fail */); } if (response.IsLegacyTLSVersion()) { - if (resource_type != ResourceType::kMainResource) { + if (!is_main_resource) { // Main resources are counted in DocumentLoader. UseCounter::Count(GetFrame(), WebFeature::kLegacyTLSVersionInSubresource); } @@ -793,7 +730,6 @@ return; // Timing for main resource is handled in DocumentLoader. - DCHECK(!info.IsMainResource()); // All other resources are reported to the corresponding Document. DOMWindowPerformance::performance( *frame_or_imported_document_->GetDocument()->domWindow())
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h index f5f84c41..7816b46 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.h +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -72,8 +72,7 @@ explicit FrameFetchContext(const FrameOrImportedDocument&); ~FrameFetchContext() override = default; - void AddAdditionalRequestHeaders(ResourceRequest&, - FetchResourceType) override; + void AddAdditionalRequestHeaders(ResourceRequest&) override; base::Optional<ResourceRequestBlockedReason> CanRequest( ResourceType type, const ResourceRequest& resource_request, @@ -97,7 +96,7 @@ const ResourceResponse& redirect_response, ResourceType, const FetchInitiatorInfo& = FetchInitiatorInfo()) override; - // Resource* can be null for navigations. + // Resource* is null if and only if this is a navigation response. void DispatchDidReceiveResponse(unsigned long identifier, const ResourceRequest&, const ResourceResponse&,
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc index f87adc15..c1a25b5 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -837,102 +837,6 @@ GetHeaderValue("https://www.example.com/1.gif", "ect").Ascii().length()); } -TEST_F(FrameFetchContextTest, MainResourceCachePolicy) { - // Default case - ResourceRequest request("http://www.example.com"); - EXPECT_EQ( - mojom::FetchCacheMode::kDefault, - GetFetchContext()->ResourceRequestCachePolicy( - request, ResourceType::kMainResource, FetchParameters::kNoDefer)); - - // Post - ResourceRequest post_request("http://www.example.com"); - post_request.SetHTTPMethod(http_names::kPOST); - EXPECT_EQ(mojom::FetchCacheMode::kValidateCache, - GetFetchContext()->ResourceRequestCachePolicy( - post_request, ResourceType::kMainResource, - FetchParameters::kNoDefer)); - - // Re-post - document->Loader()->SetLoadType(WebFrameLoadType::kBackForward); - EXPECT_EQ(mojom::FetchCacheMode::kOnlyIfCached, - GetFetchContext()->ResourceRequestCachePolicy( - post_request, ResourceType::kMainResource, - FetchParameters::kNoDefer)); - - // WebFrameLoadType::kReload - document->Loader()->SetLoadType(WebFrameLoadType::kReload); - EXPECT_EQ( - mojom::FetchCacheMode::kValidateCache, - GetFetchContext()->ResourceRequestCachePolicy( - request, ResourceType::kMainResource, FetchParameters::kNoDefer)); - - // Conditional request - document->Loader()->SetLoadType(WebFrameLoadType::kStandard); - ResourceRequest conditional("http://www.example.com"); - conditional.SetHTTPHeaderField(http_names::kIfModifiedSince, "foo"); - EXPECT_EQ( - mojom::FetchCacheMode::kValidateCache, - GetFetchContext()->ResourceRequestCachePolicy( - conditional, ResourceType::kMainResource, FetchParameters::kNoDefer)); - - // WebFrameLoadType::kReloadBypassingCache - document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache); - EXPECT_EQ( - mojom::FetchCacheMode::kBypassCache, - GetFetchContext()->ResourceRequestCachePolicy( - request, ResourceType::kMainResource, FetchParameters::kNoDefer)); - - // WebFrameLoadType::kReloadBypassingCache with a conditional request - document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache); - EXPECT_EQ( - mojom::FetchCacheMode::kBypassCache, - GetFetchContext()->ResourceRequestCachePolicy( - conditional, ResourceType::kMainResource, FetchParameters::kNoDefer)); - - // WebFrameLoadType::kReloadBypassingCache with a post request - document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache); - EXPECT_EQ(mojom::FetchCacheMode::kBypassCache, - GetFetchContext()->ResourceRequestCachePolicy( - post_request, ResourceType::kMainResource, - FetchParameters::kNoDefer)); - - // Set up a child frame - FrameFetchContext* child_fetch_context = CreateChildFrame(); - - // Child frame as part of back/forward - document->Loader()->SetLoadType(WebFrameLoadType::kBackForward); - EXPECT_EQ( - mojom::FetchCacheMode::kForceCache, - child_fetch_context->ResourceRequestCachePolicy( - request, ResourceType::kMainResource, FetchParameters::kNoDefer)); - - // Child frame as part of reload - document->Loader()->SetLoadType(WebFrameLoadType::kReload); - EXPECT_EQ( - mojom::FetchCacheMode::kDefault, - child_fetch_context->ResourceRequestCachePolicy( - request, ResourceType::kMainResource, FetchParameters::kNoDefer)); - - // Child frame as part of reload bypassing cache - document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache); - EXPECT_EQ( - mojom::FetchCacheMode::kBypassCache, - child_fetch_context->ResourceRequestCachePolicy( - request, ResourceType::kMainResource, FetchParameters::kNoDefer)); - - // Per-frame bypassing reload, but parent load type is different. - // This is not the case users can trigger through user interfaces, but for - // checking code correctness and consistency. - document->Loader()->SetLoadType(WebFrameLoadType::kReload); - child_frame->Loader().GetDocumentLoader()->SetLoadType( - WebFrameLoadType::kReloadBypassingCache); - EXPECT_EQ( - mojom::FetchCacheMode::kBypassCache, - child_fetch_context->ResourceRequestCachePolicy( - request, ResourceType::kMainResource, FetchParameters::kNoDefer)); -} - TEST_F(FrameFetchContextTest, SubResourceCachePolicy) { // Reset load event state: if the load event is finished, we ignore the // DocumentLoader load type. @@ -1042,14 +946,12 @@ RecreateFetchContext(); ResourceRequest resource_request("http://www.example.com"); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ("on", resource_request.HttpHeaderField("Save-Data")); // Subsequent call to addAdditionalRequestHeaders should not append to the // save-data header. - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ("on", resource_request.HttpHeaderField("Save-Data")); } @@ -1060,8 +962,7 @@ RecreateFetchContext(); ResourceRequest resource_request("http://www.example.com"); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ(String(), resource_request.HttpHeaderField("Save-Data")); } @@ -1071,28 +972,24 @@ // Recreate the fetch context so that the updated save data settings are read. RecreateFetchContext(); ResourceRequest resource_request("http://www.example.com"); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ("on", resource_request.HttpHeaderField("Save-Data")); GetNetworkStateNotifier().SetSaveDataEnabledOverride(false); RecreateFetchContext(); document->Loader()->SetLoadType(WebFrameLoadType::kReload); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ(String(), resource_request.HttpHeaderField("Save-Data")); GetNetworkStateNotifier().SetSaveDataEnabledOverride(true); RecreateFetchContext(); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ("on", resource_request.HttpHeaderField("Save-Data")); GetNetworkStateNotifier().SetSaveDataEnabledOverride(false); RecreateFetchContext(); document->Loader()->SetLoadType(WebFrameLoadType::kReload); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ(String(), resource_request.HttpHeaderField("Save-Data")); } @@ -1202,7 +1099,7 @@ dummy_page_holder = nullptr; - GetFetchContext()->AddAdditionalRequestHeaders(request, kFetchSubresource); + GetFetchContext()->AddAdditionalRequestHeaders(request); EXPECT_EQ(origin, request.HttpHeaderField(http_names::kOrigin)); EXPECT_EQ(String(origin + "/"), @@ -1311,8 +1208,6 @@ EXPECT_FALSE(GetFetchContext()->ShouldLoadNewResource(ResourceType::kImage)); EXPECT_FALSE(GetFetchContext()->ShouldLoadNewResource(ResourceType::kRaw)); EXPECT_FALSE(GetFetchContext()->ShouldLoadNewResource(ResourceType::kScript)); - EXPECT_FALSE( - GetFetchContext()->ShouldLoadNewResource(ResourceType::kMainResource)); } TEST_F(FrameFetchContextTest, RecordLoadingActivityWhenDetached) { @@ -1342,7 +1237,7 @@ TEST_F(FrameFetchContextTest, AddResourceTimingWhenDetached) { scoped_refptr<ResourceTimingInfo> info = - ResourceTimingInfo::Create("type", TimeTicksFromSeconds(0.3), false); + ResourceTimingInfo::Create("type", TimeTicksFromSeconds(0.3)); dummy_page_holder = nullptr; @@ -1417,15 +1312,13 @@ EXPECT_CALL(*client, GetPreviewsStateForFrame()) .WillRepeatedly(testing::Return(WebURLRequest::kPreviewsOff)); ResourceRequest resource_request("http://www.example.com/style.css"); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ(g_null_atom, resource_request.HttpHeaderField("Intervention")); // Verify header is added if Lo-Fi is active. EXPECT_CALL(*client, GetPreviewsStateForFrame()) .WillRepeatedly(testing::Return(WebURLRequest::kClientLoFiOn)); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchSubresource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ( "<https://www.chromestatus.com/features/6072546726248448>; " "level=\"warning\"", @@ -1435,8 +1328,7 @@ ResourceRequest resource_request2("http://www.example.com/getad.js"); resource_request2.SetHTTPHeaderField("Intervention", "<https://otherintervention.org>"); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request2, - kFetchSubresource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request2); EXPECT_EQ( "<https://otherintervention.org>, " "<https://www.chromestatus.com/features/6072546726248448>; " @@ -1451,15 +1343,13 @@ EXPECT_CALL(*client, GetPreviewsStateForFrame()) .WillRepeatedly(testing::Return(WebURLRequest::kPreviewsOff)); ResourceRequest resource_request("http://www.example.com/style.css"); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchMainResource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ(g_null_atom, resource_request.HttpHeaderField("Intervention")); // Verify header is added if NoScript is active. EXPECT_CALL(*client, GetPreviewsStateForFrame()) .WillRepeatedly(testing::Return(WebURLRequest::kNoScriptOn)); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request, - kFetchSubresource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request); EXPECT_EQ( "<https://www.chromestatus.com/features/4775088607985664>; " "level=\"warning\"", @@ -1469,8 +1359,7 @@ ResourceRequest resource_request2("http://www.example.com/getad.js"); resource_request2.SetHTTPHeaderField("Intervention", "<https://otherintervention.org>"); - GetFetchContext()->AddAdditionalRequestHeaders(resource_request2, - kFetchSubresource); + GetFetchContext()->AddAdditionalRequestHeaders(resource_request2); EXPECT_EQ( "<https://otherintervention.org>, " "<https://www.chromestatus.com/features/4775088607985664>; "
diff --git a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc index 7174e5d..5222d7e 100644 --- a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc +++ b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
@@ -67,16 +67,6 @@ return document && document->LoadEventFinished(); } -bool FrameResourceFetcherProperties::ShouldBlockLoadingMainResource() const { - DocumentLoader* document_loader = - frame_or_imported_document_->GetDocumentLoader(); - if (!document_loader) - return false; - - FrameLoader& loader = frame_or_imported_document_->GetFrame().Loader(); - return document_loader != loader.GetProvisionalDocumentLoader(); -} - bool FrameResourceFetcherProperties::ShouldBlockLoadingSubResource() const { DocumentLoader* document_loader = frame_or_imported_document_->GetDocumentLoader();
diff --git a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h index e941e43..0b70eb8 100644 --- a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h +++ b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
@@ -39,7 +39,6 @@ bool IsPaused() const override; bool IsDetached() const override { return false; } bool IsLoadComplete() const override; - bool ShouldBlockLoadingMainResource() const override; bool ShouldBlockLoadingSubResource() const override; private:
diff --git a/third_party/blink/renderer/core/loader/preload_helper.cc b/third_party/blink/renderer/core/loader/preload_helper.cc index 72d95c5c..3fd0fd5 100644 --- a/third_party/blink/renderer/core/loader/preload_helper.cc +++ b/third_party/blink/renderer/core/loader/preload_helper.cc
@@ -253,7 +253,7 @@ } ResourceRequest resource_request(url); resource_request.SetRequestContext(ResourceFetcher::DetermineRequestContext( - resource_type.value(), ResourceFetcher::kImageNotImageSet, false)); + resource_type.value(), ResourceFetcher::kImageNotImageSet)); resource_request.SetReferrerPolicy(params.referrer_policy);
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc index 74fcefe..2d8bcac 100644 --- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -235,9 +235,8 @@ web_context_->WillSendRequest(webreq); } -void WorkerFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request, - FetchResourceType type) { - BaseFetchContext::AddAdditionalRequestHeaders(request, type); +void WorkerFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request) { + BaseFetchContext::AddAdditionalRequestHeaders(request); // The remaining modifications are only necessary for HTTP and HTTPS. if (!request.Url().IsEmpty() && !request.Url().ProtocolIsInHTTPFamily())
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/third_party/blink/renderer/core/loader/worker_fetch_context.h index ba2a6db..b169c88 100644 --- a/third_party/blink/renderer/core/loader/worker_fetch_context.h +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -74,8 +74,7 @@ void PrepareRequest(ResourceRequest&, WebScopedVirtualTimePauser&, RedirectType) override; - void AddAdditionalRequestHeaders(ResourceRequest&, - FetchResourceType) override; + void AddAdditionalRequestHeaders(ResourceRequest&) override; void DispatchWillSendRequest(unsigned long, ResourceRequest&, const ResourceResponse&,
diff --git a/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h b/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h index ac54710b7..eb400bb 100644 --- a/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h +++ b/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h
@@ -44,7 +44,6 @@ bool IsPaused() const override; bool IsDetached() const override { return false; } bool IsLoadComplete() const override { return false; } - bool ShouldBlockLoadingMainResource() const override { return false; } bool ShouldBlockLoadingSubResource() const override { return false; } private:
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index dc4c742..6860f86 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -3455,9 +3455,12 @@ } else if (IsScrollableAreaLayer(graphics_layer)) { PaintScrollableArea(graphics_layer, context, interest_rect); } - probe::didPaint(owning_layer_.GetLayoutObject().GetFrame(), - graphics_layer->CcLayer(), context, - LayoutRect(interest_rect)); + + if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { + probe::didPaint(owning_layer_.GetLayoutObject().GetFrame(), + graphics_layer->CcLayer(), LayoutRect(interest_rect)); + } + #if DCHECK_IS_ON() if (Page* page = GetLayoutObject().GetFrame()->GetPage()) page->SetIsPainting(false);
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc index 6111fe6..85774d7 100644 --- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc +++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
@@ -560,7 +560,7 @@ AttachRootLayerViaChromeClient(); // Inform the inspector that the layer tree has changed. - if (IsMainFrame()) + if (IsMainFrame() && !RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) probe::layerTreeDidChange(layout_view_.GetFrame()); Lifecycle().AdvanceTo(DocumentLifecycle::kCompositingClean);
diff --git a/third_party/blink/renderer/core/paint/frame_painter.cc b/third_party/blink/renderer/core/paint/frame_painter.cc index f2bc7e39..2a4b508 100644 --- a/third_party/blink/renderer/core/paint/frame_painter.cc +++ b/third_party/blink/renderer/core/paint/frame_painter.cc
@@ -12,7 +12,6 @@ #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_painter.h" #include "third_party/blink/renderer/core/paint/scrollbar_painter.h" -#include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/platform/graphics/graphics_context.h" #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" @@ -115,9 +114,6 @@ GetMemoryCache()->UpdateFramePaintTimestamp(); in_paint_contents_ = false; } - - probe::didPaint(layout_view->GetFrame(), nullptr, context, - LayoutRect(cull_rect.Rect())); } const LocalFrameView& FramePainter::GetFrameView() {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc index 4d210a13..82fa3393 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -532,8 +532,9 @@ NGPaintFragment::FragmentRange NGPaintFragment::InlineFragmentsFor( const LayoutObject* layout_object) { - DCHECK(layout_object && layout_object->IsInline() && - !layout_object->IsFloatingOrOutOfFlowPositioned()); + DCHECK(layout_object); + DCHECK(layout_object->IsInline()); + DCHECK(!layout_object->IsFloatingOrOutOfFlowPositioned()); if (layout_object->IsInLayoutNGInlineFormattingContext()) return FragmentRange(layout_object->FirstInlineFragment());
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 584f9390a..6fe8640 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -235,6 +235,10 @@ return GetLayoutObject().DebugName(); } +DOMNodeId PaintLayer::OwnerNodeId() const { + return static_cast<const DisplayItemClient&>(GetLayoutObject()).OwnerNodeId(); +} + LayoutRect PaintLayer::VisualRect() const { return layout_object_.FragmentsVisualRectBoundingBox(); }
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 939ba935..ac350c6 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -231,6 +231,7 @@ // DisplayItemClient methods String DebugName() const final; + DOMNodeId OwnerNodeId() const final; LayoutRect VisualRect() const final; LayoutBoxModelObject& GetLayoutObject() const { return layout_object_; }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index c5a561b..fb6fdabb0 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -2880,6 +2880,13 @@ scrollable_area_->GetLayoutBox()->DebugName(); } +DOMNodeId +PaintLayerScrollableArea::ScrollingBackgroundDisplayItemClient::OwnerNodeId() + const { + return static_cast<const DisplayItemClient*>(scrollable_area_->GetLayoutBox()) + ->OwnerNodeId(); +} + bool PaintLayerScrollableArea::ScrollingBackgroundDisplayItemClient:: PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const { return scrollable_area_->GetLayoutBox()
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h index 225e030..25ba9d5 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -691,7 +691,7 @@ LayoutRect vertical_scrollbar_visual_rect_; LayoutRect scroll_corner_and_resizer_visual_rect_; - class ScrollingBackgroundDisplayItemClient : public DisplayItemClient { + class ScrollingBackgroundDisplayItemClient final : public DisplayItemClient { DISALLOW_NEW(); public: @@ -699,13 +699,14 @@ const PaintLayerScrollableArea& scrollable_area) : scrollable_area_(&scrollable_area) {} - LayoutRect VisualRect() const override; - String DebugName() const override; - bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override; - void Trace(Visitor* visitor) { visitor->Trace(scrollable_area_); } private: + LayoutRect VisualRect() const final; + String DebugName() const final; + DOMNodeId OwnerNodeId() const final; + bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const final; + Member<const PaintLayerScrollableArea> scrollable_area_; };
diff --git a/third_party/blink/renderer/core/probe/core_probes.json5 b/third_party/blink/renderer/core/probe/core_probes.json5 index 40ada2c..56e4adf 100644 --- a/third_party/blink/renderer/core/probe/core_probes.json5 +++ b/third_party/blink/renderer/core/probe/core_probes.json5
@@ -107,6 +107,7 @@ probes: [ "didPaint", "layerTreeDidChange", + "layerTreePainted", ] }, InspectorLogAgent: { @@ -145,6 +146,7 @@ "willLoadXHR", "willSendEventSourceRequest", "willSendRequest", + "willSendNavigationRequest", "willSendWebSocketHandshakeRequest", ] }, @@ -207,6 +209,7 @@ "frameStartedLoading", "paintTiming", "willSendRequest", + "willSendNavigationRequest", ] }, DevToolsSession: {
diff --git a/third_party/blink/renderer/core/probe/core_probes.pidl b/third_party/blink/renderer/core/probe/core_probes.pidl index a3e17b50..de8a05a 100644 --- a/third_party/blink/renderer/core/probe/core_probes.pidl +++ b/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -85,12 +85,14 @@ void didFireWebGLWarning(Element*); void didFireWebGLErrorOrWarning(Element*, const String& message); void didResizeMainFrame(LocalFrame*); - void didPaint(LocalFrame*, const cc::Layer*, GraphicsContext&, const LayoutRect&); + /* This is for pre-BlinkGenPropertyTrees. TODO(wangxianzhu): Remove this function for BlinkGenPropertyTrees. */ + void didPaint(LocalFrame*, const cc::Layer*, const LayoutRect&); void applyAcceptLanguageOverride(ExecutionContext*, String* acceptLanguage); void applyUserAgentOverride(CoreProbeSink*, String* userAgent); void didBlockRequest([Keep] ExecutionContext*, const ResourceRequest&, DocumentLoader*, const FetchInitiatorInfo&, ResourceRequestBlockedReason, ResourceType); void didChangeResourcePriority(LocalFrame*, DocumentLoader*, unsigned long identifier, ResourceLoadPriority loadPriority); void willSendRequest([Keep] ExecutionContext*, unsigned long identifier, DocumentLoader*, ResourceRequest&, const ResourceResponse& redirectResponse, const FetchInitiatorInfo&, ResourceType); + void willSendNavigationRequest([Keep] ExecutionContext*, unsigned long identifier, DocumentLoader*, const KURL&, const AtomicString& http_method, EncodedFormData*); void markResourceAsCached(LocalFrame*, DocumentLoader*, unsigned long identifier); void didReceiveResourceResponse(CoreProbeSink*, unsigned long identifier, DocumentLoader*, const ResourceResponse&, Resource*); void didReceiveData(CoreProbeSink*, unsigned long identifier, DocumentLoader*, const char* data, uint64_t dataLength); @@ -130,7 +132,10 @@ void didReceiveWebSocketMessageError(ExecutionContext*, unsigned long identifier, const String& errorMessage); void networkStateChanged([Keep] LocalFrame*, bool online); void updateApplicationCacheStatus([Keep] LocalFrame*); + /* This is for pre-BlinkGenPropertyTrees. TODO(wangxianzhu): Remove this function for BlinkGenPropertyTrees. */ void layerTreeDidChange(LocalFrame*); + /* For BlinkGenPropertyTrees/CompositeAfterPaint. */ + void layerTreePainted(LocalFrame*); void pseudoElementCreated([Keep] PseudoElement*); void pseudoElementDestroyed([Keep] PseudoElement*); void didCreateAnimation(Document*, unsigned);
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc index 0affb2c7..e06c443 100644 --- a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc +++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -101,7 +101,7 @@ void SimCompositor::BeginMainFrame(base::TimeTicks frame_time) { // There is no WebWidget like RenderWidget would have..? So go right to the // WebViewImpl. - web_view_->MainFrameWidget()->BeginFrame(last_frame_time_); + web_view_->MainFrameWidget()->BeginFrame(last_frame_time_, false); web_view_->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); *paint_commands_ = PaintFrame();
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js index 5334c9e..3993199 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js +++ b/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
@@ -109,6 +109,16 @@ new Timeline.TimelineRecordStyle(Common.UIString('Evaluate Module'), categories['scripting']); eventStyles[recordTypes.ParseScriptOnBackground] = new Timeline.TimelineRecordStyle(Common.UIString('Parse Script'), categories['scripting']); + eventStyles[recordTypes.WasmStreamFromResponseCallback] = + new Timeline.TimelineRecordStyle(Common.UIString(ls`Streaming Wasm Response`), categories['scripting']); + eventStyles[recordTypes.WasmCompiledModule] = + new Timeline.TimelineRecordStyle(Common.UIString(ls`Compiled Wasm Module`), categories['scripting']); + eventStyles[recordTypes.WasmCachedModule] = + new Timeline.TimelineRecordStyle(Common.UIString(ls`Cached Wasm Module`), categories['scripting']); + eventStyles[recordTypes.WasmModuleCacheHit] = + new Timeline.TimelineRecordStyle(Common.UIString(ls`Wasm Module Cache Hit`), categories['scripting']); + eventStyles[recordTypes.WasmModuleCacheInvalid] = + new Timeline.TimelineRecordStyle(Common.UIString(ls`Wasm Module Cache Invalid`), categories['scripting']); eventStyles[recordTypes.FrameStartedLoading] = new Timeline.TimelineRecordStyle(ls`Frame Started Loading`, categories['loading'], true); eventStyles[recordTypes.MarkLoad] = @@ -560,6 +570,14 @@ detailsText = Bindings.displayNameForURL(url) + ':' + (eventData['lineNumber'] + 1); break; } + case recordType.WasmCompiledModule: + case recordType.WasmModuleCacheHit: { + const url = event.args['url']; + if (url) + detailsText = Bindings.displayNameForURL(url); + break; + } + case recordType.ParseScriptOnBackground: case recordType.XHRReadyStateChange: case recordType.XHRLoad: { @@ -666,6 +684,11 @@ case recordType.Animation: case recordType.EmbedderCallback: case recordType.ParseHTML: + case recordType.WasmStreamFromResponseCallback: + case recordType.WasmCompiledModule: + case recordType.WasmModuleCacheHit: + case recordType.WasmCachedModule: + case recordType.WasmModuleCacheInvalid: case recordType.WebSocketCreate: case recordType.WebSocketSendHandshakeRequest: case recordType.WebSocketReceiveHandshakeResponse: @@ -893,6 +916,23 @@ if (url) contentHelper.appendLocationRow(ls`Script`, url, eventData['lineNumber'], eventData['columnNumber']); break; + case recordTypes.WasmStreamFromResponseCallback: + case recordTypes.WasmCompiledModule: + case recordTypes.WasmCachedModule: + case recordTypes.WasmModuleCacheHit: + case recordTypes.WasmModuleCacheInvalid: + if (eventData) { + url = event.args['url']; + if (url) + contentHelper.appendTextRow(ls`Url`, url); + const producedCachedSize = event.args['producedCachedSize']; + if (producedCachedSize) + contentHelper.appendTextRow(ls`Produced Cache Size`, producedCachedSize); + const consumedCachedSize = event.args['consumedCachedSize']; + if (consumedCachedSize) + contentHelper.appendTextRow(ls`Consumed Cache Size`, consumedCachedSize); + } + break; case recordTypes.Paint: const clip = eventData['clip']; contentHelper.appendTextRow(ls`Location`, ls`(${clip[0]}, ${clip[1]})`);
diff --git a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js index 1b0efac5..65809eba 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js +++ b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
@@ -1211,6 +1211,11 @@ EvaluateScript: 'EvaluateScript', CompileModule: 'v8.compileModule', EvaluateModule: 'v8.evaluateModule', + WasmStreamFromResponseCallback: 'v8.wasm.streamFromResponseCallback', + WasmCompiledModule: 'v8.wasm.compiledModule', + WasmCachedModule: 'v8.wasm.cachedModule', + WasmModuleCacheHit: 'v8.wasm.moduleCacheHit', + WasmModuleCacheInvalid: 'v8.wasm.moduleCacheInvalid', FrameStartedLoading: 'FrameStartedLoading', CommitLoad: 'CommitLoad',
diff --git a/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc b/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc index edcb448..3b5378c 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
@@ -69,9 +69,7 @@ case kMediaOverlayCastOnButton: case kMediaOverflowButton: case kMediaOverflowList: - case kMediaScrubbingMessage: case kMediaDisplayCutoutFullscreenButton: - case kMediaAnimatedArrowContainer: return MakeGarbageCollected<AccessibilityMediaControl>(layout_object, ax_object_cache); // Removed as a part of the a11y tree rewrite https://crbug/836549. @@ -124,8 +122,6 @@ case kMediaTimelineContainer: case kMediaControlsPanel: case kMediaOverflowList: - case kMediaScrubbingMessage: - case kMediaAnimatedArrowContainer: return QueryString(WebLocalizedString::kAXMediaDefault); case kMediaDisplayCutoutFullscreenButton: return QueryString( @@ -161,8 +157,6 @@ case kMediaTimelineContainer: case kMediaControlsPanel: case kMediaOverflowList: - case kMediaScrubbingMessage: - case kMediaAnimatedArrowContainer: return QueryString(WebLocalizedString::kAXMediaDefault); case kMediaSlider: // Removed as a part of the a11y tree rewrite https://crbug/836549. @@ -201,8 +195,6 @@ case kMediaControlsPanel: case kMediaSliderThumb: - case kMediaScrubbingMessage: - case kMediaAnimatedArrowContainer: return ax::mojom::Role::kUnknown; case kMediaSlider:
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_animated_arrow_container_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_animated_arrow_container_element.cc index da595e2a..02e5a74e 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_animated_arrow_container_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_animated_arrow_container_element.cc
@@ -72,7 +72,7 @@ MediaControlAnimatedArrowContainerElement:: MediaControlAnimatedArrowContainerElement(MediaControlsImpl& media_controls) - : MediaControlDivElement(media_controls, kMediaAnimatedArrowContainer), + : MediaControlDivElement(media_controls, kMediaIgnore), left_jump_arrow_(nullptr), right_jump_arrow_(nullptr) { EnsureUserAgentShadowRoot();
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h b/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h index da1cb2e8..8b743ea 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h
@@ -19,9 +19,7 @@ kMediaOverlayCastOnButton, kMediaOverflowButton, kMediaOverflowList, - kMediaScrubbingMessage, kMediaDisplayCutoutFullscreenButton, - kMediaAnimatedArrowContainer, kMediaIgnore };
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc index aa7722e..4bd0dd5 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc
@@ -16,7 +16,7 @@ MediaControlScrubbingMessageElement::MediaControlScrubbingMessageElement( MediaControlsImpl& media_controls) - : MediaControlDivElement(media_controls, kMediaScrubbingMessage) { + : MediaControlDivElement(media_controls, kMediaIgnore) { SetShadowPseudoId(AtomicString("-internal-media-controls-scrubbing-message")); CreateUserAgentShadowRoot(); SetIsWanted(false);
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_event.cc b/third_party/blink/renderer/modules/service_worker/fetch_event.cc index 38630ba..75bcb24 100644 --- a/third_party/blink/renderer/modules/service_worker/fetch_event.cc +++ b/third_party/blink/renderer/modules/service_worker/fetch_event.cc
@@ -195,8 +195,7 @@ // According to the Resource Timing spec, the initiator type of // navigation preload request is "navigation". scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create( - "navigation", resource_response.GetResourceLoadTiming()->RequestTime(), - false /* is_main_resource */); + "navigation", resource_response.GetResourceLoadTiming()->RequestTime()); info->SetNegativeAllowed(true); info->SetLoadFinishTime(completion_time); info->SetInitialURL(request_->url());
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc index d943705..84ecf71 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
@@ -494,7 +494,7 @@ event = MessageEvent::CreateError( GetExecutionContext()->GetSecurityOrigin()->ToString(), source); } - DispatchEvent(*event); + EnqueueEvent(*event, TaskType::kServiceWorkerClientMessage); } void ServiceWorkerContainer::CountFeature(mojom::WebFeature feature) {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc index 0f6eea3..566aab93 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc
@@ -138,7 +138,7 @@ // Render by reading directly from the buffer. if (!RenderFromBuffer(output_bus, quantum_frame_offset, - buffer_frames_to_process)) { + buffer_frames_to_process, start_time_offset)) { output_bus->Zero(); return; } @@ -177,7 +177,8 @@ bool AudioBufferSourceHandler::RenderFromBuffer( AudioBus* bus, unsigned destination_frame_offset, - uint32_t number_of_frames) { + uint32_t number_of_frames, + double start_time_offset) { DCHECK(Context()->IsAudioThread()); // Basic sanity checking @@ -273,6 +274,20 @@ // Get local copy. double virtual_read_index = virtual_read_index_; + // We should never start the the source before the start time, so + // start_time_offset should always be negative or 0. + DCHECK_LE(start_time_offset, 0); + + // Adjust the read index by the start_time_offset (compensated by the playback + // rate) because we always start output on a frame boundary with interpolation + // if necessary. + if (start_time_offset < 0) { + if (computed_playback_rate != 0) { + virtual_read_index += + std::abs(start_time_offset * computed_playback_rate); + } + } + // Render loop - reading from the source buffer to the destination using // linear interpolation. int frames_to_process = number_of_frames; @@ -293,6 +308,7 @@ unsigned read_index = static_cast<unsigned>(virtual_read_index); unsigned delta_frames = static_cast<unsigned>(virtual_delta_frames); end_frame = static_cast<unsigned>(virtual_end_frame); + while (frames_to_process > 0) { int frames_to_end = end_frame - read_index; int frames_this_time = std::min(frames_to_process, frames_to_end);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h index 19bd49c..d9cd745 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h
@@ -108,10 +108,25 @@ bool is_duration_given, ExceptionState&); - // Returns true on success. - bool RenderFromBuffer(AudioBus*, + // Render audio directly from the buffer to the audio bus. Returns true on + // success, i.e., audio was written to the output bus because all the internal + // checks passed. + // + // output_bus - + // AudioBus where the rendered audio goes. + // destination_frame_offset - + // Index into the output bus where the first frame should be written. + // number_of_frames - + // Maximum number of frames to process; this can be less that a render + // quantum. + // start_time_offset - + // Actual start time relative to the |destination_frame_offset|. This + // should be the \sart_time_offset| value returned by + // |UpdateSchedulingInfo|. + bool RenderFromBuffer(AudioBus* output_bus, unsigned destination_frame_offset, - uint32_t number_of_frames); + uint32_t number_of_frames, + double start_time_offset); // Render silence starting from "index" frame in AudioBus. inline bool RenderSilenceAndFinishIfNotLooping(AudioBus*,
diff --git a/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc b/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc index 767cd03..54d9875 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc
@@ -83,12 +83,22 @@ // endFrame : End frame for this source. size_t quantum_start_frame = Context()->CurrentSampleFrame(); size_t quantum_end_frame = quantum_start_frame + quantum_frame_size; - size_t start_frame = - audio_utilities::TimeToSampleFrame(start_time_, sample_rate); - size_t end_frame = - end_time_ == kUnknownTime - ? 0 - : audio_utilities::TimeToSampleFrame(end_time_, sample_rate); + + // Round up if the start_time isn't on a frame boundary so we don't start too + // early. + size_t start_frame = audio_utilities::TimeToSampleFrame( + start_time_, sample_rate, audio_utilities::kRoundUp); + size_t end_frame = 0; + + if (end_time_ == kUnknownTime) { + end_frame = 0; + } else { + // The end frame is the end time rounded up because it is an exclusive upper + // bound of the end time. We also need to take care to handle huge end + // times and clamp the corresponding frame to the largest size_t value. + end_frame = audio_utilities::TimeToSampleFrame(end_time_, sample_rate, + audio_utilities::kRoundUp); + } // If we know the end time and it's already passed, then don't bother doing // any more rendering this cycle. @@ -125,6 +135,7 @@ if (!non_silent_frames_to_process) { // Output silence. + DCHECK_LE(start_frame_offset, 0); output_bus->Zero(); return std::make_tuple(quantum_frame_offset, non_silent_frames_to_process, start_frame_offset); @@ -147,11 +158,13 @@ size_t zero_start_frame = end_frame - quantum_start_frame; size_t frames_to_zero = quantum_frame_size - zero_start_frame; + DCHECK_LT(zero_start_frame, quantum_frame_size); + DCHECK_LE(frames_to_zero, quantum_frame_size); + DCHECK_LE(zero_start_frame + frames_to_zero, quantum_frame_size); + bool is_safe = zero_start_frame < quantum_frame_size && frames_to_zero <= quantum_frame_size && zero_start_frame + frames_to_zero <= quantum_frame_size; - DCHECK(is_safe); - if (is_safe) { if (frames_to_zero > non_silent_frames_to_process) non_silent_frames_to_process = 0; @@ -166,6 +179,7 @@ Finish(); } + DCHECK_LE(start_frame_offset, 0); return std::make_tuple(quantum_frame_offset, non_silent_frames_to_process, start_frame_offset); }
diff --git a/third_party/blink/renderer/platform/audio/audio_utilities.cc b/third_party/blink/renderer/platform/audio/audio_utilities.cc index f15d376..14d96f75a 100644 --- a/third_party/blink/renderer/platform/audio/audio_utilities.cc +++ b/third_party/blink/renderer/platform/audio/audio_utilities.cc
@@ -66,9 +66,25 @@ return 1 - exp(-1 / (sample_rate * time_constant)); } -size_t TimeToSampleFrame(double time, double sample_rate) { +size_t TimeToSampleFrame(double time, + double sample_rate, + enum SampleFrameRounding rounding_mode) { DCHECK_GE(time, 0); - double frame = round(time * sample_rate); + double frame; + + switch (rounding_mode) { + case kRoundToNearest: + frame = round(time * sample_rate); + break; + case kRoundDown: + frame = floor(time * sample_rate); + break; + case kRoundUp: + frame = ceil(time * sample_rate); + break; + default: + NOTREACHED(); + } // Just return the largest possible size_t value if necessary. if (frame >= std::numeric_limits<size_t>::max()) {
diff --git a/third_party/blink/renderer/platform/audio/audio_utilities.h b/third_party/blink/renderer/platform/audio/audio_utilities.h index 94cdb94b..2d17f6bd 100644 --- a/third_party/blink/renderer/platform/audio/audio_utilities.h +++ b/third_party/blink/renderer/platform/audio/audio_utilities.h
@@ -32,6 +32,16 @@ namespace blink { namespace audio_utilities { +// How to do rounding when converting time to sample frame. +enum SampleFrameRounding { + // Round to nearest integer + kRoundToNearest, + // Round down + kRoundDown, + // Round up + kRoundUp +}; + // Rendering quantum size. This is how many frames are processed at a time for // each node in the audio graph. static const unsigned kRenderQuantumFrames = 128; @@ -48,7 +58,10 @@ double sample_rate); // Convert the time to a sample frame at the given sample rate. -PLATFORM_EXPORT size_t TimeToSampleFrame(double time, double sample_rate); +PLATFORM_EXPORT size_t +TimeToSampleFrame(double time, + double sample_rate, + enum SampleFrameRounding rounding = kRoundToNearest); // Check that |sampleRate| is a valid rate for AudioBuffers. PLATFORM_EXPORT bool IsValidAudioBufferSampleRate(float sample_rate);
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index 4d20e8d..973f8bd 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -386,6 +386,11 @@ rect_known_to_be_opaque = FloatRect(); } +const PaintChunk& PaintArtifactCompositor::PendingLayer::FirstPaintChunk( + const PaintArtifact& paint_artifact) const { + return paint_artifact.PaintChunks()[paint_chunk_indices[0]]; +} + static bool IsNonCompositingAncestorOf( const TransformPaintPropertyNode* unaliased_ancestor, const TransformPaintPropertyNode* node) { @@ -884,10 +889,12 @@ layer->SetEffectTreeIndex(effect_id); bool backface_hidden = property_state.Transform()->IsBackfaceHidden(); layer->SetDoubleSided(!backface_hidden); - // TODO(wangxianzhu): cc::PropertyTreeBuilder has a more sophisticated - // condition for this. Do we need to do the same here? layer->SetShouldCheckBackfaceVisibility(backface_hidden); + layer->set_owner_node_id( + pending_layer.FirstPaintChunk(*paint_artifact).id.client.OwnerNodeId()); + // TODO(wangxianzhu): cc_picture_layer_->set_compositing_reasons(...); + InsertAncestorElementIds(property_state.Effect(), composited_element_ids); InsertAncestorElementIds(transform, composited_element_ids); if (layer->scrollable())
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h index 26a8f15..e38c90f9 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
@@ -155,6 +155,8 @@ // to the chunks as Skia commands. void Upcast(const PropertyTreeState&); + const PaintChunk& FirstPaintChunk(const PaintArtifact&) const; + FloatRect bounds; Vector<wtf_size_t> paint_chunk_indices; FloatRect rect_known_to_be_opaque;
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc index 75bfb51..60d859d9 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -914,6 +914,7 @@ .TakePaintImage(); if (!image_layer_) { image_layer_ = cc::PictureImageLayer::Create(); + image_layer_->set_owner_node_id(CcLayer()->owner_node_id()); RegisterContentsLayer(image_layer_.get()); } image_layer_->SetImage(std::move(paint_image), matrix,
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_client.h b/third_party/blink/renderer/platform/graphics/paint/display_item_client.h index 27a43f1..4342ad0 100644 --- a/third_party/blink/renderer/platform/graphics/paint/display_item_client.h +++ b/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_CLIENT_H_ #include "third_party/blink/renderer/platform/geometry/layout_rect.h" +#include "third_party/blink/renderer/platform/graphics/dom_node_id.h" #include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" @@ -41,6 +42,12 @@ virtual String DebugName() const = 0; + // Needed for paint chunk clients only. Returns the id of the DOM node + // associated with this DisplayItemClient, or kInvalidDOMNodeId if there is no + // associated DOM node or this DisplayItemClient is never used as a paint + // chunk client. + virtual DOMNodeId OwnerNodeId() const { return kInvalidDOMNodeId; } + // The visual rect of this DisplayItemClient. For SPv1, it's in the object // space of the object that owns the GraphicsLayer, i.e. offset by // GraphicsLayer::OffsetFromLayoutObjectWithSubpixelAccumulation().
diff --git a/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc index 5e57ee5..7fdeabc 100644 --- a/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc +++ b/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
@@ -24,6 +24,8 @@ String DebugName() const final { return "ForeignLayer"; } + DOMNodeId OwnerNodeId() const final { return layer_->owner_node_id(); } + LayoutRect VisualRect() const final { const auto& offset = layer_->offset_to_transform_parent(); return LayoutRect(LayoutPoint(offset.x(), offset.y()),
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc index d874c6a0..16a3a17 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
@@ -81,8 +81,7 @@ ResourceLoadPriority, int) {} -void FetchContext::AddAdditionalRequestHeaders(ResourceRequest&, - FetchResourceType) {} +void FetchContext::AddAdditionalRequestHeaders(ResourceRequest&) {} mojom::FetchCacheMode FetchContext::ResourceRequestCachePolicy( const ResourceRequest&, @@ -129,8 +128,6 @@ bool) {} bool FetchContext::ShouldLoadNewResource(ResourceType type) const { - if (type == ResourceType::kMainResource) - return !GetResourceFetcherProperties().ShouldBlockLoadingMainResource(); return !GetResourceFetcherProperties().ShouldBlockLoadingSubResource(); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h index 4d084287..cce2e96 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -71,8 +71,6 @@ class ResourceTimingInfo; class WebScopedVirtualTimePauser; -enum FetchResourceType { kFetchMainResource, kFetchSubresource }; - // The FetchContext is an interface for performing context specific processing // in response to events in the ResourceFetcher. The ResourceFetcher or its job // class, ResourceLoader, may call the methods on a FetchContext. @@ -98,7 +96,7 @@ virtual void Trace(blink::Visitor*); - virtual void AddAdditionalRequestHeaders(ResourceRequest&, FetchResourceType); + virtual void AddAdditionalRequestHeaders(ResourceRequest&); const ResourceFetcherProperties& GetResourceFetcherProperties() const;
diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc b/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc index 04a6bdf5..9b1a1dc 100644 --- a/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
@@ -119,7 +119,6 @@ MockFetchContext* context = MakeGarbageCollected<MockFetchContext>(); auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(security_origin_); - properties->SetShouldBlockLoadingMainResource(true); properties->SetShouldBlockLoadingSubResource(true); fetcher_ = MakeGarbageCollected<ResourceFetcher>( ResourceFetcherInit(*properties, context,
diff --git a/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h b/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h index 7f6867a..7a2d62b 100644 --- a/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h +++ b/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h
@@ -38,7 +38,6 @@ bool IsPaused() const override { return false; } bool IsDetached() const override { return true; } bool IsLoadComplete() const override { return true; } - bool ShouldBlockLoadingMainResource() const override { return true; } bool ShouldBlockLoadingSubResource() const override { return true; } private:
diff --git a/third_party/blink/renderer/platform/loader/fetch/preload_key.h b/third_party/blink/renderer/platform/loader/fetch/preload_key.h index 3340d39..04bf568 100644 --- a/third_party/blink/renderer/platform/loader/fetch/preload_key.h +++ b/third_party/blink/renderer/platform/loader/fetch/preload_key.h
@@ -46,7 +46,7 @@ } KURL url; - ResourceType type = ResourceType::kMainResource; + ResourceType type = ResourceType::kImage; }; } // namespace blink @@ -61,6 +61,8 @@ template <> struct HashTraits<blink::PreloadKey> : public SimpleClassHashTraits<blink::PreloadKey> { + static const bool kEmptyValueIsZero = false; + static bool IsDeletedValue(const blink::PreloadKey& value) { return HashTraits<blink::KURL>::IsDeletedValue(value.url); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc b/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc index f41bfb1f..658ed0c4 100644 --- a/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
@@ -171,12 +171,6 @@ c->RedirectBlocked(); } -SourceKeyedCachedMetadataHandler* RawResource::InlineScriptCacheHandler() { - DCHECK_EQ(ResourceType::kMainResource, GetType()); - return static_cast<SourceKeyedCachedMetadataHandler*>( - Resource::CacheHandler()); -} - SingleCachedMetadataHandler* RawResource::ScriptCacheHandler() { DCHECK_EQ(ResourceType::kRaw, GetType()); return static_cast<SingleCachedMetadataHandler*>(Resource::CacheHandler()); @@ -210,12 +204,7 @@ CachedMetadataHandler* RawResource::CreateCachedMetadataHandler( std::unique_ptr<CachedMetadataSender> send_callback) { - if (GetType() == ResourceType::kMainResource) { - // This is a document resource; create a cache handler that can handle - // multiple inline scripts. - return MakeGarbageCollected<SourceKeyedCachedMetadataHandler>( - Encoding(), std::move(send_callback)); - } else if (GetType() == ResourceType::kRaw) { + if (GetType() == ResourceType::kRaw) { // This is a resource of indeterminate type, e.g. a fetched WebAssembly // module; create a cache handler that can store a single metadata entry. return MakeGarbageCollected<ScriptCachedMetadataHandler>( @@ -228,13 +217,7 @@ size_t size) { Resource::SetSerializedCachedMetadata(data, size); - if (GetType() == ResourceType::kMainResource) { - SourceKeyedCachedMetadataHandler* cache_handler = - InlineScriptCacheHandler(); - if (cache_handler) { - cache_handler->SetSerializedCachedMetadata(data, size); - } - } else if (GetType() == ResourceType::kRaw) { + if (GetType() == ResourceType::kRaw) { ScriptCachedMetadataHandler* cache_handler = static_cast<ScriptCachedMetadataHandler*>(Resource::CacheHandler()); if (cache_handler) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/raw_resource.h b/third_party/blink/renderer/platform/loader/fetch/raw_resource.h index ed590d0..820f14e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/raw_resource.h +++ b/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
@@ -38,7 +38,6 @@ class FetchParameters; class RawResourceClient; class ResourceFetcher; -class SourceKeyedCachedMetadataHandler; class PLATFORM_EXPORT RawResource final : public Resource { public: @@ -86,12 +85,6 @@ void SetSerializedCachedMetadata(const uint8_t*, size_t) override; - // Used for code caching of scripts with source code inline in the HTML. - // Returns a cache handler which can store multiple cache metadata entries, - // keyed by the source code of the script. This is valid only if type is - // kMainResource. - SourceKeyedCachedMetadataHandler* InlineScriptCacheHandler(); - // Used for code caching of fetched code resources. Returns a cache handler // which can only store a single cache metadata entry. This is valid only if // type is kRaw. @@ -145,9 +138,9 @@ // TODO(yhirano): Recover #if ENABLE_SECURITY_ASSERT when we stop adding // RawResources to MemoryCache. inline bool IsRawResource(ResourceType type) { - return type == ResourceType::kMainResource || type == ResourceType::kRaw || - type == ResourceType::kTextTrack || type == ResourceType::kAudio || - type == ResourceType::kVideo || type == ResourceType::kManifest || + return type == ResourceType::kRaw || type == ResourceType::kTextTrack || + type == ResourceType::kAudio || type == ResourceType::kVideo || + type == ResourceType::kManifest || type == ResourceType::kImportResource; } inline bool IsRawResource(const Resource& resource) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.cc b/third_party/blink/renderer/platform/loader/fetch/resource.cc index a20c89be..af9a3700 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -1150,8 +1150,6 @@ ResourceType type, const AtomicString& fetch_initiator_name) { switch (type) { - case ResourceType::kMainResource: - return "Main resource"; case ResourceType::kImage: return "Image"; case ResourceType::kCSSStyleSheet: @@ -1191,9 +1189,8 @@ DCHECK( // Cacheable WebAssembly modules are fetched, so raw resource type. resource_type == ResourceType::kRaw || - // Cacheable Javascript is a script or a document resource. + // Cacheable Javascript is a script resource. resource_type == ResourceType::kScript || - resource_type == ResourceType::kMainResource || // Also accept mock resources for testing. resource_type == ResourceType::kMock); return ToCodeCacheType(resource_type); @@ -1205,7 +1202,6 @@ bool Resource::IsLoadEventBlockingResourceType() const { switch (type_) { - case ResourceType::kMainResource: case ResourceType::kImage: case ResourceType::kCSSStyleSheet: case ResourceType::kScript:
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.h b/third_party/blink/renderer/platform/loader/fetch/resource.h index 7874407..07e2364 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -70,8 +70,8 @@ // |ResourceType| enum values are used in UMAs, so do not change the values of // existing types. When adding a new type, append it at the end. enum class ResourceType : uint8_t { - kMainResource, - kImage, + // We do not have kMainResource anymore, which used to have zero value. + kImage = 1, kCSSStyleSheet, kScript, kFont,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index 208a7f2..99e8d05 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -103,7 +103,6 @@ DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Image) \ DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, ImportResource) \ DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, LinkPrefetch) \ - DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, MainResource) \ DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Manifest) \ DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Audio) \ DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Video) \ @@ -117,7 +116,6 @@ ResourceLoadPriority TypeToPriority(ResourceType type) { switch (type) { - case ResourceType::kMainResource: case ResourceType::kCSSStyleSheet: case ResourceType::kFont: // Also parser-blocking scripts (set explicitly in loadPriority) @@ -335,17 +333,10 @@ mojom::RequestContextType ResourceFetcher::DetermineRequestContext( ResourceType type, - IsImageSet is_image_set, - bool is_main_frame) { + IsImageSet is_image_set) { DCHECK((is_image_set == kImageNotImageSet) || (type == ResourceType::kImage && is_image_set == kImageIsImageSet)); switch (type) { - case ResourceType::kMainResource: - if (!is_main_frame) - return mojom::RequestContextType::IFRAME; - // FIXME: Change this to a context frame type (once we introduce them): - // http://fetch.spec.whatwg.org/#concept-request-context-frame-type - return mojom::RequestContextType::HYPERLINK; case ResourceType::kXSLStyleSheet: DCHECK(RuntimeEnabledFeatures::XSLTEnabled()); FALLTHROUGH; @@ -440,10 +431,6 @@ bool IsLoadComplete() const override { return properties_ ? properties_->IsLoadComplete() : load_complete_; } - bool ShouldBlockLoadingMainResource() const override { - // Returns true when detached in order to preserve the existing behavior. - return properties_ ? properties_->ShouldBlockLoadingMainResource() : true; - } bool ShouldBlockLoadingSubResource() const override { // Returns true when detached in order to preserve the existing behavior. return properties_ ? properties_->ShouldBlockLoadingSubResource() : true; @@ -547,8 +534,7 @@ // Resources loaded from memory cache should be reported the first time // they're used. scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create( - params.Options().initiator_info.name, CurrentTimeTicks(), - resource->GetType() == ResourceType::kMainResource); + params.Options().initiator_info.name, CurrentTimeTicks()); // TODO(yoav): GetInitialUrlForResourceTiming() is only needed until // Out-of-Blink CORS lands: https://crbug.com/736308 info->SetInitialURL( @@ -776,8 +762,8 @@ } if (resource_request.GetRequestContext() == mojom::RequestContextType::UNSPECIFIED) { - resource_request.SetRequestContext(DetermineRequestContext( - resource_type, kImageNotImageSet, properties_->IsMainFrame())); + resource_request.SetRequestContext( + DetermineRequestContext(resource_type, kImageNotImageSet)); } if (resource_type == ResourceType::kLinkPrefetch) resource_request.SetHTTPHeaderField(http_names::kPurpose, "prefetch"); @@ -813,10 +799,7 @@ resource_request.HttpMethod() == http_names::kGET && !IsRawResource(resource_type) && !params.IsStaleRevalidation()); - Context().AddAdditionalRequestHeaders( - resource_request, (resource_type == ResourceType::kMainResource) - ? kFetchMainResource - : kFetchSubresource); + Context().AddAdditionalRequestHeaders(resource_request); network_instrumentation::ResourcePrioritySet(identifier, resource_request.Priority()); @@ -1125,11 +1108,8 @@ if (fetch_initiator == fetch_initiator_type_names::kInternal) return; - if (resource->GetType() == ResourceType::kMainResource) - return; - - scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create( - fetch_initiator, CurrentTimeTicks(), false /* is_main_resource */); + scoped_refptr<ResourceTimingInfo> info = + ResourceTimingInfo::Create(fetch_initiator, CurrentTimeTicks()); if (resource->IsCacheValidator()) { const AtomicString& timing_allow_origin = @@ -1713,7 +1693,7 @@ // original request. scoped_refptr<ResourceTimingInfo> preflight_info = ResourceTimingInfo::Create(info->InitiatorType(), - timing_info.start_time, false); + timing_info.start_time); preflight_info->SetInitialURL(info->InitialURL()); preflight_info->SetLoadFinishTime(timing_info.finish_time); preflight_info->AddFinalTransferSize(timing_info.transfer_size);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h index e0ce7e9..f74b2d44 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -211,8 +211,9 @@ enum IsImageSet { kImageNotImageSet, kImageIsImageSet }; - WARN_UNUSED_RESULT static mojom::RequestContextType - DetermineRequestContext(ResourceType, IsImageSet, bool is_main_frame); + WARN_UNUSED_RESULT static mojom::RequestContextType DetermineRequestContext( + ResourceType, + IsImageSet); void UpdateAllImageResourcePriorities();
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h index dafb16d..e860655b9 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h
@@ -66,9 +66,6 @@ // Returns whether the main resource for this global context is loaded. virtual bool IsLoadComplete() const = 0; - // Returns whether we should disallow a main resource loading. - virtual bool ShouldBlockLoadingMainResource() const = 0; - // Returns whether we should disallow a sub resource loading. virtual bool ShouldBlockLoadingSubResource() const = 0; };
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc index 3a23c15..76a8f17 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -230,11 +230,10 @@ TEST_F(ResourceFetcherTest, ResourceTimingInfo) { auto info = ResourceTimingInfo::Create(fetch_initiator_type_names::kDocument, - CurrentTimeTicks(), - true /* is_main_resource */); + CurrentTimeTicks()); info->AddFinalTransferSize(5); EXPECT_EQ(info->TransferSize(), 5); - ResourceResponse redirect_response(KURL("https://example.com")); + ResourceResponse redirect_response(KURL("https://example.com/original")); redirect_response.SetHTTPStatusCode(200); redirect_response.SetEncodedDataLength(7); info->AddRedirect(redirect_response, KURL("https://example.com/redirect")); @@ -1004,7 +1003,6 @@ EXPECT_FALSE(properties.IsPaused()); EXPECT_FALSE(properties.IsDetached()); EXPECT_FALSE(properties.IsLoadComplete()); - EXPECT_FALSE(properties.ShouldBlockLoadingMainResource()); EXPECT_FALSE(properties.ShouldBlockLoadingSubResource()); fetcher->ClearContext(); @@ -1022,7 +1020,6 @@ EXPECT_FALSE(properties.IsPaused()); EXPECT_TRUE(properties.IsDetached()); EXPECT_FALSE(properties.IsLoadComplete()); - EXPECT_TRUE(properties.ShouldBlockLoadingMainResource()); EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); } @@ -1050,7 +1047,6 @@ original_properties.SetServiceWorkerId(133); original_properties.SetIsPaused(true); original_properties.SetIsLoadComplete(true); - original_properties.SetShouldBlockLoadingMainResource(true); original_properties.SetShouldBlockLoadingSubResource(true); const auto& client_settings_object = @@ -1063,7 +1059,6 @@ EXPECT_TRUE(properties.IsPaused()); EXPECT_FALSE(properties.IsDetached()); EXPECT_TRUE(properties.IsLoadComplete()); - EXPECT_TRUE(properties.ShouldBlockLoadingMainResource()); EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); fetcher->ClearContext(); @@ -1081,7 +1076,6 @@ EXPECT_TRUE(properties.IsPaused()); EXPECT_TRUE(properties.IsDetached()); EXPECT_TRUE(properties.IsLoadComplete()); - EXPECT_TRUE(properties.ShouldBlockLoadingMainResource()); EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc index 6a546a44..9cbe68a 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
@@ -68,7 +68,6 @@ void SetUp() override { DCHECK(RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled()); auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); - properties->SetShouldBlockLoadingMainResource(true); properties->SetShouldBlockLoadingSubResource(true); auto* context = MakeGarbageCollected<MockFetchContext>(); MakeGarbageCollected<ResourceFetcher>(
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc index 5ff90f1..fe5f7740 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -335,12 +335,6 @@ !RuntimeEnabledFeatures::WasmCodeCacheEnabled()) return false; - // TODO(crbug.com/867347): Enable fetching of code caches on non-main threads - // once code cache has its own mojo interface. Currently it is using - // RenderMessageFilter that is not available on non-main threads. - if (!IsMainThread()) - return false; - const ResourceRequest& request = resource_->GetResourceRequest(); if (!request.Url().ProtocolIsInHTTPFamily()) return false; @@ -352,9 +346,9 @@ return false; if (request.DownloadToBlob()) return false; - // Javascript resources have type kScript or kMainResource (for inline - // scripts). WebAssembly module resources have type kRaw. Note that we - // always perform a code fetch for all of these resources because: + // Javascript resources have type kScript. WebAssembly module resources + // have type kRaw. Note that we always perform a code fetch for all of + // these resources because: // // * It is not easy to distinguish WebAssembly modules from other raw // resources @@ -366,7 +360,6 @@ // no browser process disk IO since the cache index is in memory and the // resource key should not be present. return resource_->GetType() == ResourceType::kScript || - resource_->GetType() == ResourceType::kMainResource || resource_->GetType() == ResourceType::kRaw; } @@ -384,9 +377,6 @@ // stoppable. We also disable throttling and stopping for non-http[s] // requests. if (resource_->Options().synchronous_policy == kRequestSynchronously || - (request.GetFrameType() == - network::mojom::RequestContextFrameType::kTopLevel && - resource_->GetType() == ResourceType::kMainResource) || !request.Url().ProtocolIsInHTTPFamily()) { throttle_option = ResourceLoadScheduler::ThrottleOption::kCanNotBeStoppedOrThrottled; @@ -1105,10 +1095,6 @@ return; DCHECK_GE(response_out.ToResourceResponse().EncodedBodyLength(), 0); - // TODO(crbug.com/867347): Enable fetching of code caches synchronously - // once code cache has its own mojo interface. Currently it is using - // RenderMessageFilter that is not available on non-main threads. - // Follow the async case convention of not calling DidReceiveData or // appending data to m_resource if the response body is empty. Copying the // empty buffer is a noop in most cases, but is destructive in the case of
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h b/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h index ce12f13..541ef06 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h
@@ -49,12 +49,10 @@ public: static scoped_refptr<ResourceTimingInfo> Create(const AtomicString& type, - const TimeTicks time, - bool is_main_resource) { - return base::AdoptRef(new ResourceTimingInfo(type, time, is_main_resource)); + const TimeTicks time) { + return base::AdoptRef(new ResourceTimingInfo(type, time)); } TimeTicks InitialTime() const { return initial_time_; } - bool IsMainResource() const { return is_main_resource_; } const AtomicString& InitiatorType() const { return type_; } @@ -100,10 +98,8 @@ bool NegativeAllowed() const { return negative_allowed_; } private: - ResourceTimingInfo(const AtomicString& type, - const TimeTicks time, - bool is_main_resource) - : type_(type), initial_time_(time), is_main_resource_(is_main_resource) {} + ResourceTimingInfo(const AtomicString& type, const TimeTicks time) + : type_(type), initial_time_(time) {} AtomicString type_; AtomicString original_timing_allow_origin_; @@ -113,7 +109,6 @@ ResourceResponse final_response_; Vector<ResourceResponse> redirect_chain_; long long transfer_size_ = 0; - bool is_main_resource_; bool has_cross_origin_redirect_ = false; bool negative_allowed_ = false; };
diff --git a/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h b/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h index 5e6360b..7e94739 100644 --- a/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h +++ b/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h
@@ -42,9 +42,6 @@ bool IsPaused() const override { return paused_; } bool IsDetached() const override { return false; } bool IsLoadComplete() const override { return load_complete_; } - bool ShouldBlockLoadingMainResource() const override { - return should_block_loading_main_resource_; - } bool ShouldBlockLoadingSubResource() const override { return should_block_loading_sub_resource_; } @@ -56,9 +53,6 @@ void SetServiceWorkerId(int64_t id) { service_worker_id_ = id; } void SetIsPaused(bool value) { paused_ = value; } void SetIsLoadComplete(bool value) { load_complete_ = value; } - void SetShouldBlockLoadingMainResource(bool value) { - should_block_loading_main_resource_ = value; - } void SetShouldBlockLoadingSubResource(bool value) { should_block_loading_sub_resource_ = value; } @@ -71,7 +65,6 @@ int64_t service_worker_id_ = 0; bool paused_ = false; bool load_complete_ = false; - bool should_block_loading_main_resource_ = false; bool should_block_loading_sub_resource_ = false; };
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index 5c2bc18..c515a10 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -435,6 +435,7 @@ // PostedMessage can be used for navigation, so we shouldn't defer it // when expecting a user gesture. case TaskType::kPostedMessage: + case TaskType::kServiceWorkerClientMessage: case TaskType::kWorkerAnimation: // UserInteraction tasks should be run even when expecting a user gesture. case TaskType::kUserInteraction:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc index 39530c12..a4cd8be 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
@@ -73,6 +73,8 @@ return "BackgroundFetch"; case TaskType::kPermission: return "Permission"; + case TaskType::kServiceWorkerClientMessage: + return "ServiceWorkerClientMessage"; case TaskType::kInternalDefault: return "InternalDefault"; case TaskType::kInternalLoading:
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc index b4dfcaa..251719bf 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -193,6 +193,7 @@ case TaskType::kExperimentalWebSchedulingUserInteraction: case TaskType::kExperimentalWebSchedulingBestEffort: case TaskType::kInternalTranslation: + case TaskType::kServiceWorkerClientMessage: case TaskType::kCount: NOTREACHED(); break;
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint index a710eef..6ae9a59 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -2,7 +2,6 @@ # See: https://docs.google.com/document/d/1QCM912Dr6u38DqyQqd7pxQxDy8FFOoWMMDq7uAXqKdA/view # We are focused on fast/, compositing/, and svg/ with all other directories skipped (for now). Bug(none) editing/input [ Skip ] -Bug(none) http/tests/devtools/layers/ [ Skip ] Bug(none) http/tests/devtools/tracing/ [ Skip ] Bug(none) printing/ [ Skip ] Bug(none) scrollbars/ [ Skip ] @@ -182,8 +181,6 @@ Bug(none) fragmentation/outline-crossing-columns.html [ Crash ] Bug(none) fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html [ Failure ] Bug(none) http/tests/misc/slow-loading-mask.html [ Failure ] -Bug(none) inspector-protocol/layers/paint-profiler.js [ Failure ] -Bug(none) inspector-protocol/layers/get-layers.js [ Timeout ] Bug(none) paint/pagination/pagination-change-clip-crash.html [ Failure ] # Less invalidations or different invalidations without pixel failures. @@ -304,7 +301,6 @@ Bug(none) fast/borders/overflow-hidden-border-radius-force-backing-store.html [ Failure ] # virtual/threaded variants of sub-directories and tests already skipped or marked as failing above. -Bug(none) virtual/threaded/http/tests/devtools/tracing/ [ Skip ] Bug(none) virtual/threaded/fast/events/pinch/gesture-pinch-zoom-scroll-bubble.html [ Timeout ] Bug(none) virtual/threaded/fast/events/pinch/pinch-zoom-pan-within-zoomed-viewport.html [ Failure ] Bug(none) virtual/threaded/fast/events/pinch/scroll-visual-viewport-send-boundary-events.html [ Timeout ] @@ -445,3 +441,11 @@ Bug(none) css3/filters/blur-filter-page-scroll-self.html [ Failure ] crbug.com/921729 paint/invalidation/compositing/composited-layer-move.html [ Failure ] + +# Crash during PictureLayer::GetPicture() when DisplayItemList is finished twice. +Bug(none) http/tests/devtools/layers/layer-canvas-log.js [ Crash ] +Bug(none) http/tests/devtools/layers/layer-replay-scale.js [ Crash ] +# Missing compositing reasons +Bug(none) http/tests/devtools/layers/layer-compositing-reasons.js [ Failure ] +# Missing WheelEventHandler +Bug(none) http/tests/devtools/layers/layer-scroll-rects-get.js [ Failure ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index e55b134..93233d7 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -92,8 +92,10 @@ crbug.com/420008 virtual/threaded/http/tests/devtools/tracing/ [ Slow ] crbug.com/902685 http/tests/devtools/isolated-code-cache/same-origin-test.js [ Slow ] crbug.com/902685 http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Slow ] +crbug.com/902685 http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Slow ] crbug.com/902685 virtual/site-isolated-code-cache/http/tests/devtools/isolated-code-cache/same-origin-test.js [ Slow ] crbug.com/902685 virtual/site-isolated-code-cache/http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Slow ] +crbug.com/902685 virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Slow ] crbug.com/902685 virtual/not-site-per-process/http/tests/devtools/isolated-code-cache/same-origin-test.js [ Slow ] crbug.com/902685 virtual/not-site-per-process/http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index c5a9bbbe..cb10f09 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -375,7 +375,8 @@ Bug(none) virtual/stable/compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Failure ] Bug(none) virtual/stable/compositing/overflow/nested-border-radius-clipping.html [ Failure ] -# These tests are no longer applicable with layer list mode (BGPT). Move to NeverFixTests later. +# These tests are no longer applicable with layer list mode (BGPT). +# TODO(wangxianzhu): Remove them when we remove non-BGPT code. Bug(none) http/tests/devtools/layers/layer-sticky-position-constraint-get.js [ Skip ] Bug(none) inspector-protocol/layers/get-layers.js [ Skip ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 3b92d6c..a6d90ec 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -778,6 +778,13 @@ "--site-per-process"] }, { + "prefix": "wasm-site-isolated-code-cache", + "base": "http/tests/devtools/wasm-isolated-code-cache", + "args": ["--enable-features=IsolatedCodeCache,WasmCodeCache", + "--disable-features=WebAssemblyBaseline", + "--site-per-process"] + }, + { "prefix": "not-site-per-process", "base": "http/tests/devtools/isolated-code-cache", "args": ["--disable-site-isolation-trials"]
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit-expected.html new file mode 100644 index 0000000..9801e1a --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit-expected.html
@@ -0,0 +1,18 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log">PASS</div> +<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit.html new file mode 100644 index 0000000..ccff550 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit.html
@@ -0,0 +1,50 @@ +<!doctype HTML> + +<!-- +Runs an acquire, and calls updateAndCommit without waiting for the acquire promise. +--> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log"></div> +<div id="container"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.getElementById("container"); + container.displayLock.acquire({ timeout: Infinity }); + + let child = document.createElement("div"); + child.id = "child"; + container.appendChild(child); + + container.displayLock.updateAndCommit().then( + () => { finishTest("PASS"); }, + () => { finishTest("FAIL"); }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit-expected.html new file mode 100644 index 0000000..9801e1a --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit-expected.html
@@ -0,0 +1,18 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log">PASS</div> +<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit.html new file mode 100644 index 0000000..2ff1ffd --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit.html
@@ -0,0 +1,52 @@ +<!doctype HTML> + +<!-- +Runs an acquire, appends a child, and calls updateAndCommit. +--> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.displayLock.acquire({ timeout: Infinity }).then(() => { + let child = document.createElement("div"); + child.id = "child"; + container.appendChild(child); + + container.id = "container"; + document.body.appendChild(container); + + container.displayLock.updateAndCommit().then( + () => { finishTest("PASS"); }, + () => { finishTest("FAIL"); }); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit-expected.html new file mode 100644 index 0000000..9801e1a --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit-expected.html
@@ -0,0 +1,18 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log">PASS</div> +<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit.html new file mode 100644 index 0000000..ca6f5084 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit.html
@@ -0,0 +1,48 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.displayLock.acquire({ timeout: Infinity }).then(() => { + let child = document.createElement("div"); + child.id = "child"; + container.appendChild(child); + + container.id = "container"; + document.body.appendChild(container); + + let first_promise = container.displayLock.commit(); + let second_promise = container.displayLock.updateAndCommit(); + Promise.all([first_promise, second_promise]).then(() => finishTest("PASS")); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit-expected.html new file mode 100644 index 0000000..9801e1a --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit-expected.html
@@ -0,0 +1,18 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log">PASS</div> +<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit.html new file mode 100644 index 0000000..f881f209 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit.html
@@ -0,0 +1,50 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.displayLock.acquire({ timeout: Infinity }).then(() => { + let child = document.createElement("div"); + child.id = "child"; + container.appendChild(child); + + container.id = "container"; + document.body.appendChild(container); + + let promises = [] + for (let i = 0; i < 10; ++i) { + promises.push(container.displayLock.updateAndCommit()); + } + Promise.all(promises).then(() => finishTest("PASS")); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-expected.html new file mode 100644 index 0000000..a1a74ba --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-expected.html
@@ -0,0 +1,3 @@ +<!doctype HTML> + +<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit-expected.html new file mode 100644 index 0000000..9801e1a --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit-expected.html
@@ -0,0 +1,18 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log">PASS</div> +<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit.html new file mode 100644 index 0000000..9e56578f --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit.html
@@ -0,0 +1,48 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.displayLock.acquire({ timeout: Infinity }).then(() => { + let child = document.createElement("div"); + child.id = "child"; + container.appendChild(child); + + container.id = "container"; + document.body.appendChild(container); + + let first_promise = container.displayLock.updateAndCommit(); + let second_promise = container.displayLock.commit(); + Promise.all([first_promise, second_promise]).then(() => finishTest("PASS")); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update-expected.html new file mode 100644 index 0000000..9801e1a --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update-expected.html
@@ -0,0 +1,18 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log">PASS</div> +<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update.html new file mode 100644 index 0000000..f0d2b63 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update.html
@@ -0,0 +1,48 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.displayLock.acquire({ timeout: Infinity }).then(() => { + let child = document.createElement("div"); + child.id = "child"; + container.appendChild(child); + + container.id = "container"; + document.body.appendChild(container); + + let first_promise = container.displayLock.updateAndCommit(); + let second_promise = container.displayLock.update(); + Promise.all([first_promise, second_promise]).then(() => finishTest("PASS")); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit.html new file mode 100644 index 0000000..0ea2539 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit.html
@@ -0,0 +1,39 @@ +<!doctype HTML> + +<!-- +Runs an updateAndCommit() without acquiring, which fails. +--> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.id = "container"; + container.displayLock.updateAndCommit().then( + () => { finishTest("FAIL"); }, + () => { finishTest("PASS"); }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit-expected.html new file mode 100644 index 0000000..9801e1a --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit-expected.html
@@ -0,0 +1,18 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log">PASS</div> +<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit.html new file mode 100644 index 0000000..0e40582 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit.html
@@ -0,0 +1,48 @@ +<!doctype HTML> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.displayLock.acquire({ timeout: Infinity }).then(() => { + let child = document.createElement("div"); + child.id = "child"; + container.appendChild(child); + + container.id = "container"; + document.body.appendChild(container); + + let first_promise = container.displayLock.update(); + let second_promise = container.displayLock.updateAndCommit(); + Promise.all([first_promise, second_promise]).then(() => finishTest("PASS")); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/resources/biquad-testing.js b/third_party/blink/web_tests/external/wpt/webaudio/resources/biquad-testing.js index 7a0b6e6c..7f90a1f 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/resources/biquad-testing.js +++ b/third_party/blink/web_tests/external/wpt/webaudio/resources/biquad-testing.js
@@ -5,15 +5,16 @@ let renderedBuffer; let renderedData; -let sampleRate = 44100.0; +// Use a power of two to eliminate round-off in converting frame to time +let sampleRate = 32768; let pulseLengthFrames = .1 * sampleRate; // Maximum allowed error for the test to succeed. Experimentally determined. let maxAllowedError = 5.9e-8; -// This must be large enough so that the filtered result is -// essentially zero. See comments for createTestAndRun. -let timeStep = .1; +// This must be large enough so that the filtered result is essentially zero. +// See comments for createTestAndRun. This must be a whole number of frames. +let timeStep = Math.ceil(.1 * sampleRate) / sampleRate; // Maximum number of filters we can process (mostly for setting the // render length correctly.)
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/resources/distance-model-testing.js b/third_party/blink/web_tests/external/wpt/webaudio/resources/distance-model-testing.js index 1b9adde..f8a6cf9 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/resources/distance-model-testing.js +++ b/third_party/blink/web_tests/external/wpt/webaudio/resources/distance-model-testing.js
@@ -1,10 +1,13 @@ -let sampleRate = 44100.0; +// Use a power of two to eliminate round-off when converting frames to time and +// vice versa. +let sampleRate = 32768; // How many panner nodes to create for the test. let nodesToCreate = 100; -// Time step when each panner node starts. -let timeStep = 0.001; +// Time step when each panner node starts. Make sure it starts on a frame +// boundary. +let timeStep = Math.floor(0.001 * sampleRate) / sampleRate; // Make sure we render long enough to get all of our nodes. let renderLengthSeconds = timeStep * (nodesToCreate + 1); @@ -134,7 +137,7 @@ // The max allowed error between the actual gain and the expected // value. This is determined experimentally. Set to 0 to see // what the actual errors are. - let maxAllowedError = 3.3e-6; + let maxAllowedError = 2.2720e-6; let success = true;
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/resources/note-grain-on-testing.js b/third_party/blink/web_tests/external/wpt/webaudio/resources/note-grain-on-testing.js index 1e941897..ad06316 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/resources/note-grain-on-testing.js +++ b/third_party/blink/web_tests/external/wpt/webaudio/resources/note-grain-on-testing.js
@@ -1,17 +1,23 @@ -let sampleRate = 44100.0; +// Use a power of two to eliminate round-off converting from frames to time. +let sampleRate = 32768; // How many grains to play. let numberOfTests = 100; -// Duration of each grain to be played -let duration = 0.01; +// Duration of each grain to be played. Make a whole number of frames +let duration = Math.floor(0.01 * sampleRate) / sampleRate; + +// A little extra bit of silence between grain boundaries. Must be a whole +// number of frames. +let grainGap = Math.floor(0.005 * sampleRate) / sampleRate; // Time step between the start of each grain. We need to add a little // bit of silence so we can detect grain boundaries -let timeStep = duration + .005; +let timeStep = duration + grainGap; -// Time step between the start for each grain. -let grainOffsetStep = 0.001; +// Time step between the start for each grain. Must be a whole number of +// frames. +let grainOffsetStep = Math.floor(0.001 * sampleRate) / sampleRate; // How long to render to cover all of the grains. let renderTime = (numberOfTests + 1) * timeStep;
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/resources/panner-model-testing.js b/third_party/blink/web_tests/external/wpt/webaudio/resources/panner-model-testing.js index 662fb1d6..4df3e17 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/resources/panner-model-testing.js +++ b/third_party/blink/web_tests/external/wpt/webaudio/resources/panner-model-testing.js
@@ -1,9 +1,12 @@ -let sampleRate = 44100.0; +// Use a power of two to eliminate round-off when converting frames to time and +// vice versa. +let sampleRate = 32768; let numberOfChannels = 1; -// Time step when each panner node starts. -let timeStep = 0.001; +// Time step when each panner node starts. Make sure it starts on a frame +// boundary. +let timeStep = Math.floor(0.001 * sampleRate) / sampleRate; // Length of the impulse signal. let pulseLengthFrames = Math.round(timeStep * sampleRate); @@ -114,7 +117,7 @@ // The max error we allow between the rendered impulse and the // expected value. This value is experimentally determined. Set // to 0 to make the test fail to see what the actual error is. - let maxAllowedError = 1.3e-6; + let maxAllowedError = 1.1597e-6; let success = true;
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/resources/stereopanner-testing.js b/third_party/blink/web_tests/external/wpt/webaudio/resources/stereopanner-testing.js index d6238a9c..2778493 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/resources/stereopanner-testing.js +++ b/third_party/blink/web_tests/external/wpt/webaudio/resources/stereopanner-testing.js
@@ -3,10 +3,12 @@ // Constants let PI_OVER_TWO = Math.PI * 0.5; - let gSampleRate = 44100; + // Use a power of two to eliminate any round-off when converting frames to + // time. + let gSampleRate = 32768; - // Time step when each panner node starts. - let gTimeStep = 0.001; + // Time step when each panner node starts. Make sure this is on a frame boundary. + let gTimeStep = Math.floor(0.001 * gSampleRate) / gSampleRate; // How many panner nodes to create for the test let gNodesToCreate = 100; @@ -77,7 +79,7 @@ // The max error we allow between the rendered impulse and the // expected value. This value is experimentally determined. Set // to 0 to make the test fail to see what the actual error is. - this.maxAllowedError = 1.3e-6; + this.maxAllowedError = 9.8015e-8; // Max (absolute) error and the index of the maxima for the left // and right channels.
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html index 58ee49e..5624054e 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html
@@ -74,6 +74,42 @@ .then(() => task.done()); }); + audit.define('subsample start with playback rate 0', (task, should) => { + let context = new OfflineAudioContext(1, renderLength, sampleRate); + let rampBuffer = new AudioBuffer( + {length: renderLength, sampleRate: context.sampleRate}); + let data = new Float32Array(renderLength); + let startValue = 5; + for (let k = 0; k < data.length; ++k) { + data[k] = k + startValue; + } + rampBuffer.copyToChannel(data, 0); + + let src = new AudioBufferSourceNode( + context, {buffer: rampBuffer, playbackRate: 0}); + + src.connect(context.destination); + + // Purposely start the source between frame boundaries + let startFrame = 27.3; + src.start(startFrame / context.sampleRate); + + context.startRendering() + .then(audioBuffer => { + let actualStartFrame = Math.ceil(startFrame); + let audio = audioBuffer.getChannelData(0); + + should( + audio.slice(0, actualStartFrame), + `output[0:${actualStartFrame - 1}]`) + .beConstantValueOf(0); + should( + audio.slice(actualStartFrame), `output[${actualStartFrame}:]`) + .beConstantValueOf(startValue); + }) + .then(() => task.done()); + }); + audit.run(); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffersourcenode-interface/resources/sub-sample-scheduling.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffersourcenode-interface/resources/sub-sample-scheduling.html new file mode 100644 index 0000000..27ac098 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffersourcenode-interface/resources/sub-sample-scheduling.html
@@ -0,0 +1,423 @@ +<!doctype html> +<html> + <head> + <title> + Test Sub-Sample Accurate Scheduling for ABSN + </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit-util.js"></script> + <script src="/webaudio/resources/audit.js"></script> + </head> + <body> + <script> + // Power of two so there's no roundoff converting from integer frames to + // time. + let sampleRate = 32768; + + let audit = Audit.createTaskRunner(); + + audit.define('sub-sample accurate start', (task, should) => { + // There are two channels, one for each source. Only need to render + // quanta for this test. + let context = new OfflineAudioContext( + {numberOfChannels: 2, length: 8192, sampleRate: sampleRate}); + let merger = new ChannelMergerNode( + context, {numberOfInputs: context.destination.channelCount}); + + merger.connect(context.destination); + + // Use a simple linear ramp for the sources with integer steps starting + // at 1 to make it easy to verify and test that have sub-sample accurate + // start. Ramp starts at 1 so we can easily tell when the source + // starts. + let rampBuffer = new AudioBuffer( + {length: context.length, sampleRate: context.sampleRate}); + let r = rampBuffer.getChannelData(0); + for (let k = 0; k < r.length; ++k) { + r[k] = k + 1; + } + + const src0 = new AudioBufferSourceNode(context, {buffer: rampBuffer}); + const src1 = new AudioBufferSourceNode(context, {buffer: rampBuffer}); + + // Frame where sources should start. This is pretty arbitrary, but one + // should be close to an integer and the other should be close to the + // next integer. We do this to catch the case where rounding of the + // start frame is being done. Rounding is incorrect. + const startFrame = 33; + const startFrame0 = startFrame + 0.1; + const startFrame1 = startFrame + 0.9; + + src0.connect(merger, 0, 0); + src1.connect(merger, 0, 1); + + src0.start(startFrame0 / context.sampleRate); + src1.start(startFrame1 / context.sampleRate); + + context.startRendering() + .then(audioBuffer => { + const output0 = audioBuffer.getChannelData(0); + const output1 = audioBuffer.getChannelData(1); + + // Compute the expected output by interpolating the ramp buffer of + // the sources if they started at the given frame. + const ramp = rampBuffer.getChannelData(0); + const expected0 = interpolateRamp(ramp, startFrame0); + const expected1 = interpolateRamp(ramp, startFrame1); + + // Verify output0 has the correct values + + // For information only + should(startFrame0, 'src0 start frame').beEqualTo(startFrame0); + + // Output must be zero before the source start frame, and it must + // be interpolated correctly after the start frame. The + // absoluteThreshold below is currently set for Chrome which does + // linear interpolation. This needs to be updated eventually if + // other browsers do not user interpolation. + should( + output0.slice(0, startFrame + 1), `output0[0:${startFrame}]`) + .beConstantValueOf(0); + should( + output0.slice(startFrame + 1, expected0.length), + `output0[${startFrame + 1}:${expected0.length - 1}]`) + .beCloseToArray( + expected0.slice(startFrame + 1), {absoluteThreshold: 0}); + + // Verify output1 has the correct values. Same approach as for + // output0. + should(startFrame1, 'src1 start frame').beEqualTo(startFrame1); + + should( + output1.slice(0, startFrame + 1), `output1[0:${startFrame}]`) + .beConstantValueOf(0); + should( + output1.slice(startFrame + 1, expected1.length), + `output1[${startFrame + 1}:${expected1.length - 1}]`) + .beCloseToArray( + expected1.slice(startFrame + 1), {absoluteThreshold: 0}); + }) + .then(() => task.done()); + }); + + audit.define('sub-sample accurate stop', (task, should) => { + // There are threes channesl, one for each source. Only need to render + // quanta for this test. + let context = new OfflineAudioContext( + {numberOfChannels: 3, length: 128, sampleRate: sampleRate}); + let merger = new ChannelMergerNode( + context, {numberOfInputs: context.destination.channelCount}); + + merger.connect(context.destination); + + // The source can be as simple constant for this test. + let buffer = new AudioBuffer( + {length: context.length, sampleRate: context.sampleRate}); + buffer.getChannelData(0).fill(1); + + const src0 = new AudioBufferSourceNode(context, {buffer: buffer}); + const src1 = new AudioBufferSourceNode(context, {buffer: buffer}); + const src2 = new AudioBufferSourceNode(context, {buffer: buffer}); + + // Frame where sources should start. This is pretty arbitrary, but one + // should be an integer, one should be close to an integer and the other + // should be close to the next integer. This is to catch the case where + // rounding is used for the end frame. Rounding is incorrect. + const endFrame = 33; + const endFrame1 = endFrame + 0.1; + const endFrame2 = endFrame + 0.9; + + src0.connect(merger, 0, 0); + src1.connect(merger, 0, 1); + src2.connect(merger, 0, 2); + + src0.start(0); + src1.start(0); + src2.start(0); + src0.stop(endFrame / context.sampleRate); + src1.stop(endFrame1 / context.sampleRate); + src2.stop(endFrame2 / context.sampleRate); + + context.startRendering() + .then(audioBuffer => { + let actual0 = audioBuffer.getChannelData(0); + let actual1 = audioBuffer.getChannelData(1); + let actual2 = audioBuffer.getChannelData(2); + + // Just verify that we stopped at the right time. + + // This is case where the end frame is an integer. Since the first + // output ends on an exact frame, the output must be zero at that + // frame number. We print the end frame for information only; it + // makes interpretation of the rest easier. + should(endFrame - 1, 'src0 end frame') + .beEqualTo(endFrame - 1); + should(actual0[endFrame - 1], `output0[${endFrame - 1}]`) + .notBeEqualTo(0); + should(actual0.slice(endFrame), + `output0[${endFrame}:]`) + .beConstantValueOf(0); + + // The case where the end frame is just a little above an integer. + // The output must not be zero just before the end and must be zero + // after. + should(endFrame1, 'src1 end frame') + .beEqualTo(endFrame1); + should(actual1[endFrame], `output1[${endFrame}]`) + .notBeEqualTo(0); + should(actual1.slice(endFrame + 1), + `output1[${endFrame + 1}:]`) + .beConstantValueOf(0); + + // The case where the end frame is just a little below an integer. + // The output must not be zero just before the end and must be zero + // after. + should(endFrame2, 'src2 end frame') + .beEqualTo(endFrame2); + should(actual2[endFrame], `output2[${endFrame}]`) + .notBeEqualTo(0); + should(actual2.slice(endFrame + 1), + `output2[${endFrame + 1}:]`) + .beConstantValueOf(0); + }) + .then(() => task.done()); + }); + + audit.define('sub-sample-grain', (task, should) => { + let context = new OfflineAudioContext( + {numberOfChannels: 2, length: 128, sampleRate: sampleRate}); + + let merger = new ChannelMergerNode( + context, {numberOfInputs: context.destination.channelCount}); + + merger.connect(context.destination); + + // The source can be as simple constant for this test. + let buffer = new AudioBuffer( + {length: context.length, sampleRate: context.sampleRate}); + buffer.getChannelData(0).fill(1); + + let src0 = new AudioBufferSourceNode(context, {buffer: buffer}); + let src1 = new AudioBufferSourceNode(context, {buffer: buffer}); + + src0.connect(merger, 0, 0); + src1.connect(merger, 0, 1); + + // Start a short grain. + const src0StartGrain = 3.1; + const src0EndGrain = 37.2; + src0.start( + src0StartGrain / context.sampleRate, 0, + (src0EndGrain - src0StartGrain) / context.sampleRate); + + const src1StartGrain = 5.8; + const src1EndGrain = 43.9; + src1.start( + src1StartGrain / context.sampleRate, 0, + (src1EndGrain - src1StartGrain) / context.sampleRate); + + context.startRendering() + .then(audioBuffer => { + let output0 = audioBuffer.getChannelData(0); + let output1 = audioBuffer.getChannelData(1); + + let expected = new Float32Array(context.length); + + // Compute the expected output for output0 and verify the actual + // output matches. + expected.fill(1); + for (let k = 0; k <= Math.floor(src0StartGrain); ++k) { + expected[k] = 0; + } + for (let k = Math.ceil(src0EndGrain); k < expected.length; ++k) { + expected[k] = 0; + } + + verifyGrain(should, output0, { + startGrain: src0StartGrain, + endGrain: src0EndGrain, + sourceName: 'src0', + outputName: 'output0' + }); + + verifyGrain(should, output1, { + startGrain: src1StartGrain, + endGrain: src1EndGrain, + sourceName: 'src1', + outputName: 'output1' + }); + }) + .then(() => task.done()); + }); + + audit.define( + 'sub-sample accurate start with playbackRate', (task, should) => { + // There are two channels, one for each source. Only need to render + // quanta for this test. + let context = new OfflineAudioContext( + {numberOfChannels: 2, length: 8192, sampleRate: sampleRate}); + let merger = new ChannelMergerNode( + context, {numberOfInputs: context.destination.channelCount}); + + merger.connect(context.destination); + + // Use a simple linear ramp for the sources with integer steps + // starting at 1 to make it easy to verify and test that have + // sub-sample accurate start. Ramp starts at 1 so we can easily + // tell when the source starts. + let buffer = new AudioBuffer( + {length: context.length, sampleRate: context.sampleRate}); + let r = buffer.getChannelData(0); + for (let k = 0; k < r.length; ++k) { + r[k] = k + 1; + } + + // Two sources with different playback rates + const src0 = new AudioBufferSourceNode( + context, {buffer: buffer, playbackRate: .25}); + const src1 = new AudioBufferSourceNode( + context, {buffer: buffer, playbackRate: 4}); + + // Frame where sources start. Pretty arbitrary but should not be an + // integer. + const startFrame = 17.8; + + src0.connect(merger, 0, 0); + src1.connect(merger, 0, 1); + + src0.start(startFrame / context.sampleRate); + src1.start(startFrame / context.sampleRate); + + context.startRendering() + .then(audioBuffer => { + const output0 = audioBuffer.getChannelData(0); + const output1 = audioBuffer.getChannelData(1); + + const frameBefore = Math.floor(startFrame); + const frameAfter = frameBefore + 1; + + // Informative message so we know what the following output + // indices really mean. + should(startFrame, 'Source start frame') + .beEqualTo(startFrame); + + // Verify the output + + // With a startFrame of 17.8, the first output is at frame 18, + // but the actual start is at 17.8. So we would interpolate + // the output 0.2 fraction of the way between 17.8 and 18, for + // an output of 1.2 for our ramp. But the playback rate is + // 0.25, so we're really only 1/4 as far along as we think so + // the output is .2*0.25 of the way between 1 and 2 or 1.05. + + const ramp0 = buffer.getChannelData(0)[0]; + const ramp1 = buffer.getChannelData(0)[1]; + + const src0Output = ramp0 + + (ramp1 - ramp0) * (frameAfter - startFrame) * + src0.playbackRate.value; + + let playbackMessage = + `With playbackRate ${src0.playbackRate.value}:`; + + should( + output0[frameBefore], + `${playbackMessage} output0[${frameBefore}]`) + .beEqualTo(0); + should( + output0[frameAfter], + `${playbackMessage} output0[${frameAfter}]`) + .beCloseTo(src0Output, {threshold: 4.542e-8}); + + const src1Output = ramp0 + + (ramp1 - ramp0) * (frameAfter - startFrame) * + src1.playbackRate.value; + + playbackMessage = + `With playbackRate ${src1.playbackRate.value}:`; + + should( + output1[frameBefore], + `${playbackMessage} output1[${frameBefore}]`) + .beEqualTo(0); + should( + output1[frameAfter], + `${playbackMessage} output1[${frameAfter}]`) + .beCloseTo(src1Output, {threshold: 4.542e-8}); + }) + .then(() => task.done()); + }); + + audit.run(); + + // Given an input ramp in |rampBuffer|, interpolate the signal assuming + // this ramp is used for an ABSN that starts at frame |startFrame|, which + // is not necessarily an integer. For simplicity we just use linear + // interpolation here. The interpolation is not part of the spec but + // this should be pretty close to whatever interpolation is being done. + function interpolateRamp(rampBuffer, startFrame) { + // |start| is the last zero sample before the ABSN actually starts. + const start = Math.floor(startFrame); + // One less than the rampBuffer because we can't linearly interpolate + // the last frame. + let result = new Float32Array(rampBuffer.length - 1); + + for (let k = 0; k <= start; ++k) { + result[k] = 0; + } + + // Now start linear interpolation. + let frame = startFrame; + let index = 1; + for (let k = start + 1; k < result.length; ++k) { + let s0 = rampBuffer[index]; + let s1 = rampBuffer[index - 1]; + let delta = frame - k; + let s = s1 - delta * (s0 - s1); + result[k] = s; + ++frame; + ++index; + } + + return result; + } + + function verifyGrain(should, output, options) { + let {startGrain, endGrain, sourceName, outputName} = options; + let expected = new Float32Array(output.length); + // Compute the expected output for output and verify the actual + // output matches. + expected.fill(1); + for (let k = 0; k <= Math.floor(startGrain); ++k) { + expected[k] = 0; + } + for (let k = Math.ceil(endGrain); k < expected.length; ++k) { + expected[k] = 0; + } + + should(startGrain, `${sourceName} grain start`).beEqualTo(startGrain); + should(endGrain - startGrain, `${sourceName} grain duration`) + .beEqualTo(endGrain - startGrain); + should(endGrain, `${sourceName} grain end`).beEqualTo(endGrain); + should(output, outputName).beEqualToArray(expected); + should( + output[Math.floor(startGrain)], + `${outputName}[${Math.floor(startGrain)}]`) + .beEqualTo(0); + should( + output[1 + Math.floor(startGrain)], + `${outputName}[${1 + Math.floor(startGrain)}]`) + .notBeEqualTo(0); + should( + output[Math.floor(endGrain)], + `${outputName}[${Math.floor(endGrain)}]`) + .notBeEqualTo(0); + should( + output[1 + Math.floor(endGrain)], + `${outputName}[${1 + Math.floor(endGrain)}]`) + .beEqualTo(0); + } + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audionode-interface/audionode-channel-rules.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audionode-interface/audionode-channel-rules.html index a1c3273..9067e68 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audionode-interface/audionode-channel-rules.html +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audionode-interface/audionode-channel-rules.html
@@ -14,7 +14,8 @@ <script id="layout-test-code"> let audit = Audit.createTaskRunner(); let context = 0; - let sampleRate = 44100; + // Use a power of two to eliminate round-off converting frames to time. + let sampleRate = 32768; let renderNumberOfChannels = 8; let singleTestFrameLength = 8; let testBuffers;
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-biquadfilternode-interface/biquad-lowpass.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-biquadfilternode-interface/biquad-lowpass.html index d20786e..69dc85a 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-biquadfilternode-interface/biquad-lowpass.html +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-biquadfilternode-interface/biquad-lowpass.html
@@ -34,7 +34,7 @@ createTestAndRun(context, 'lowpass', { should: should, - threshold: 9.7869e-8, + threshold: 4.6943e-8, filterParameters: filterParameters }).then(task.done.bind(task)); });
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/gain.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/gain.html index cff609de..c1ee024 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/gain.html +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-gainnode-interface/gain.html
@@ -18,11 +18,19 @@ let audit = Audit.createTaskRunner(); - let sampleRate = 44100.0; - let bufferDurationSeconds = 0.125; + // Use a power of two to eliminate any round-off when converting frame to + // time. + let sampleRate = 32768; + // Make sure the buffer duration and spacing are all exact frame lengths + // so that the note spacing is also on frame boundaries to eliminate + // sub-sample accurate start of a ABSN. + let bufferDurationSeconds = Math.floor(0.125 * sampleRate) / sampleRate; let numberOfNotes = 11; - let noteSpacing = bufferDurationSeconds + - 0.020; // leave 20ms of silence between each "note" + // Leave about 20ms of silence, being sure this is an exact frame + // duration. + let noteSilence = Math.floor(0.020 * sampleRate) / sampleRate; + let noteSpacing = bufferDurationSeconds + noteSilence; + let lengthInSeconds = numberOfNotes * noteSpacing; let context = 0; @@ -131,18 +139,18 @@ // Verify the channels are clsoe to the reference. should(actual0, 'Left output from gain node') .beCloseToArray( - reference0, {relativeThreshold: 1.1908e-7}); + reference0, {relativeThreshold: 1.1877e-7}); should(actual1, 'Right output from gain node') .beCloseToArray( - reference1, {relativeThreshold: 1.1908e-7}); + reference1, {relativeThreshold: 1.1877e-7}); // Test the SNR too for both channels. let snr0 = 10 * Math.log10(computeSNR(actual0, reference0)); let snr1 = 10 * Math.log10(computeSNR(actual1, reference1)); should(snr0, 'Left SNR (in dB)') - .beGreaterThanOrEqualTo(148.69); + .beGreaterThanOrEqualTo(148.71); should(snr1, 'Right SNR (in dB)') - .beGreaterThanOrEqualTo(148.69); + .beGreaterThanOrEqualTo(148.71); }) .then(() => task.done()); ;
diff --git a/third_party/blink/web_tests/fast/css/rem-display-none-crash.html b/third_party/blink/web_tests/fast/css/rem-display-none-crash.html new file mode 100644 index 0000000..8b9cd6a9 --- /dev/null +++ b/third_party/blink/web_tests/fast/css/rem-display-none-crash.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<style> + :root { font-size: 10px } + div { font-size: 2rem } +</style> +<div id="rem">2rem</div> +<script> + test(() => { + document.documentElement.offsetTop; + document.documentElement.style.display = "none"; + assert_equals(getComputedStyle(rem).fontSize, "20px"); + }, "Root element set to display:none should not crash updating rem units."); +</script>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/http/tests/devtools/layers/layer-tree-model-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/http/tests/devtools/layers/layer-tree-model-expected.txt new file mode 100644 index 0000000..fdc330c --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/http/tests/devtools/layers/layer-tree-model-expected.txt
@@ -0,0 +1,26 @@ +Tests general layer tree model functionality +Initial layer tree +<invalid node id> 0x0 (0) + #document (1) + div#a 200x200 (1) + div#b1 100x150 (1) + div#b2 110x140 (1) + div#c 90x100 (1) + div#b3 110x140 (1) +Updated layer tree +<invalid node id> 0x0 (0) + #document (1) + div#a 200x200 (1) + div#b2 110x140 (1) + div#c 90x100 + div#b1 100x150 + div#b4 88x77 +Updated layer geometry +<invalid node id> 0x0 (0) + #document (1) + div#a 200x200 (1) + div#b2 110x140 (1) + div#c 90x80 + div#b1 100x150 + div#b4 88x77 +
diff --git a/third_party/blink/web_tests/http/tests/devtools/layers/layer-tree-model-expected.txt b/third_party/blink/web_tests/http/tests/devtools/layers/layer-tree-model-expected.txt index defb215..0f7cb832 100644 --- a/third_party/blink/web_tests/http/tests/devtools/layers/layer-tree-model-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/layers/layer-tree-model-expected.txt
@@ -25,10 +25,10 @@ #document 200x200 (1) div#subframe1 80x80 (1) div#a 200x200 (1) - div#b1 100x150 (1) div#b2 110x140 (1) div#c 90x100 (1) - div#b3 110x140 (1) + div#b1 100x150 + div#b4 88x77 Updated layer geometry <invalid node id> 0x0 (0) <invalid node id> (1) @@ -43,5 +43,5 @@ div#b2 110x140 (1) div#c 90x80 (1) div#b1 100x150 - div#b4 0x0 + div#b4 88x77
diff --git a/third_party/blink/web_tests/http/tests/devtools/layers/layer-tree-model.js b/third_party/blink/web_tests/http/tests/devtools/layers/layer-tree-model.js index b45a87e6..c48489f 100644 --- a/third_party/blink/web_tests/http/tests/devtools/layers/layer-tree-model.js +++ b/third_party/blink/web_tests/http/tests/devtools/layers/layer-tree-model.js
@@ -10,10 +10,11 @@ .layer { transform: translateZ(10px); opacity: 0.8; + background: blue; } #frame { - width: 200px; - height: 200px; + width: 200px; + height: 200px; } </style> <div id="a" style="width: 200px; height: 200px" class="layer"> @@ -34,6 +35,8 @@ var b4 = document.createElement("div"); b4.id = "b4"; b4.className = "layer"; + b4.style.width = "77px"; + b4.style.height = "88px"; document.getElementById("a").appendChild(b4); }
diff --git a/third_party/blink/web_tests/http/tests/devtools/layers/no-overlay-layers.js b/third_party/blink/web_tests/http/tests/devtools/layers/no-overlay-layers.js index eed66a14..78b1647 100644 --- a/third_party/blink/web_tests/http/tests/devtools/layers/no-overlay-layers.js +++ b/third_party/blink/web_tests/http/tests/devtools/layers/no-overlay-layers.js
@@ -11,6 +11,7 @@ .layer { transform: translateZ(10px); opacity: 0.8; + background: blue; } </style> <div id="a" style="width: 200px; height: 200px" class="layer">
diff --git a/third_party/blink/web_tests/http/tests/devtools/layers/resources/compositing-reasons.html b/third_party/blink/web_tests/http/tests/devtools/layers/resources/compositing-reasons.html index 26102d18c..d67c7080 100644 --- a/third_party/blink/web_tests/http/tests/devtools/layers/resources/compositing-reasons.html +++ b/third_party/blink/web_tests/http/tests/devtools/layers/resources/compositing-reasons.html
@@ -10,6 +10,12 @@ 50% { rotate: 180deg; } 100% { rotate: 360deg; } } +div { + /* to avoid empty layers */ + min-width: 100px; + min-height: 20px; + background: blue; +} </style> <script type="application/x-javascript"> if (window.internals)
diff --git a/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test-expected.txt b/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test-expected.txt new file mode 100644 index 0000000..4b10d7a --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test-expected.txt
@@ -0,0 +1,88 @@ +Tests V8 code cache for WebAssembly resources. + +---First navigation - produce and consume code cache ------ + +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} + +--- Second navigation - from a different origin ------ + +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +
diff --git a/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js b/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js new file mode 100644 index 0000000..8d90680 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js
@@ -0,0 +1,85 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult(`Tests V8 code cache for WebAssembly resources.\n`); + await TestRunner.loadModule('performance_test_runner'); + await TestRunner.showPanel('timeline'); + + // Clear browser cache to avoid any existing entries for the fetched + // scripts in the cache. + SDK.multitargetNetworkManager.clearBrowserCache(); + + function runTests() { + // Loads a WASM module that is smaller than the threshold twice. It should + // compile and not be cached. + function loadSmallWasmModule(iframe_window) { + const url = 'http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=small.wasm&cors' + return iframe_window.instantiateModule(url) + .then(() => iframe_window.instantiateModule(url)); + } + // Loads a WASM module that is larger than the caching threshold. It + // should be cached the first run and bypass compilation the second. + function loadLargeWasmModule(iframe_window) { + const url = 'http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=large.wasm&cors' + return iframe_window.instantiateModule(url) + .then(() => iframe_window.instantiateModule(url)); + } + // Load the same large WASM module with a different URL. It should miss + // the cache, compile and be cached. + function loadOtherLargeWasmModule(iframe_window) { + const url = 'http://localhost:8000/wasm/resources/load-wasm.php?name=large.wasm&cors' + return iframe_window.instantiateModule(url); + } + + let script = document.createElement('script'); + script.type = 'module'; + script.text = 'window.finishTest()'; + document.body.appendChild(script); + + const frameId = 'frame_id'; + const iframe_window = document.getElementById(frameId).contentWindow; + + // These functions must be called in this order. + return loadSmallWasmModule(iframe_window) + .then(() => loadLargeWasmModule(iframe_window)) + .then(() => loadOtherLargeWasmModule(iframe_window)); + } + + await TestRunner.evaluateInPagePromise(runTests.toString()); + + TestRunner.addResult( + '---First navigation - produce and consume code cache ------\n'); + + // Create a same origin iframe. + const scope = 'http://127.0.0.1:8000/wasm/resources/wasm-cache-iframe.html'; + await TestRunner.addIframe(scope, {id: 'frame_id'}); + + await PerformanceTestRunner.invokeAsyncWithTimeline('runTests'); + + const events = new Set([ + TimelineModel.TimelineModel.RecordType.WasmStreamFromResponseCallback, + TimelineModel.TimelineModel.RecordType.WasmCompiledModule, + TimelineModel.TimelineModel.RecordType.WasmCachedModule, + TimelineModel.TimelineModel.RecordType.WasmModuleCacheHit, + TimelineModel.TimelineModel.RecordType.WasmModuleCacheInvalid]); + const tracingModel = PerformanceTestRunner.tracingModel(); + + tracingModel.sortedProcesses().forEach(p => p.sortedThreads().forEach(t => + t.events().filter(event => events.has(event.name)).forEach(PerformanceTestRunner.printTraceEventProperties))); + + // Second navigation + TestRunner.addResult( + '\n--- Second navigation - from a different origin ------\n'); + + const other_scope = 'http://localhost:8000/wasm/resources/wasm-cache-iframe.html'; + await TestRunner.addIframe(other_scope, {id: 'frame_id'}); + + await PerformanceTestRunner.invokeAsyncWithTimeline('runTests'); + + tracingModel.sortedProcesses().forEach(p => p.sortedThreads().forEach(t => + t.events().filter(event => events.has(event.name)).forEach(PerformanceTestRunner.printTraceEventProperties))); + + TestRunner.completeTest(); +})();
diff --git a/third_party/blink/web_tests/http/tests/wasm/resources/large.wasm b/third_party/blink/web_tests/http/tests/wasm/resources/large.wasm new file mode 100644 index 0000000..fe5e206 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/wasm/resources/large.wasm Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/wasm/resources/load-wasm.php b/third_party/blink/web_tests/http/tests/wasm/resources/load-wasm.php index 9b1ac01..14967b94 100644 --- a/third_party/blink/web_tests/http/tests/wasm/resources/load-wasm.php +++ b/third_party/blink/web_tests/http/tests/wasm/resources/load-wasm.php
@@ -4,7 +4,16 @@ if (isset($_GET['name'])) { $fileName = $_GET['name']; } + $last_modified = "Tue, 18 Dec 2018 23:15:53 GMT"; + if (isset($_GET['last-modified'])) { + $last_modified = $_GET['last-modified']; + } header("Content-Type: application/wasm"); + header("Last-Modified: ".$last_modified); + + if (isset($_GET['cors'])) { + header("Access-Control-Allow-Origin: *"); + } require($fileName); ?>
diff --git a/third_party/blink/web_tests/http/tests/wasm/resources/small.wasm b/third_party/blink/web_tests/http/tests/wasm/resources/small.wasm new file mode 100644 index 0000000..f8b2262 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/wasm/resources/small.wasm Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/wasm/resources/wasm-cache-iframe.html b/third_party/blink/web_tests/http/tests/wasm/resources/wasm-cache-iframe.html new file mode 100644 index 0000000..8a62a7aa --- /dev/null +++ b/third_party/blink/web_tests/http/tests/wasm/resources/wasm-cache-iframe.html
@@ -0,0 +1,10 @@ +<script src="../../../resources/testharness.js"></script> +<script> +// Instantiate a WASM test module and make sure it works. +function instantiateModule(url) +{ + return WebAssembly.instantiateStreaming(fetch(url)).then( + ({module, instance}) => assert_equals(instance.exports.exported_func(), 42)); +} +</script> +
diff --git a/third_party/WebKit/LayoutTests/media/controls/accessibility-volume-slider.html b/third_party/blink/web_tests/media/controls/accessibility-volume-slider.html similarity index 100% rename from third_party/WebKit/LayoutTests/media/controls/accessibility-volume-slider.html rename to third_party/blink/web_tests/media/controls/accessibility-volume-slider.html
diff --git a/third_party/blink/web_tests/virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/README.txt b/third_party/blink/web_tests/virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/README.txt new file mode 100644 index 0000000..4ebf844c --- /dev/null +++ b/third_party/blink/web_tests/virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/README.txt
@@ -0,0 +1,4 @@ +# This suite runs the tests in http/tests/devtools/wasm-isolated-code-cache with +# --enable-features=IsolatedCodeCache,WasmCodeCache --site-per-process. +# This feature is required for security to enforce site isolation on V8 +# code caches. Tracking bug: crbug.com/812168
diff --git a/third_party/blink/web_tests/virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test-expected.txt b/third_party/blink/web_tests/virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test-expected.txt new file mode 100644 index 0000000..c0d97ff --- /dev/null +++ b/third_party/blink/web_tests/virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test-expected.txt
@@ -0,0 +1,216 @@ +Tests V8 code cache for WebAssembly resources. + +---First navigation - produce and consume code cache ------ + +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.compiledModule Properties: +{ + data : { + url : http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=small.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.compiledModule" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.compiledModule Properties: +{ + data : { + url : http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=small.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.compiledModule" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.compiledModule Properties: +{ + data : { + url : http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=large.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.compiledModule" +} +v8.wasm.cachedModule Properties: +{ + data : { + producedCacheSize : <number> + } + endTime : <number> + startTime : <number> + type : "v8.wasm.cachedModule" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.moduleCacheHit Properties: +{ + data : { + consumedCacheSize : <number> + url : http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=large.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.moduleCacheHit" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.compiledModule Properties: +{ + data : { + url : http://localhost:8000/wasm/resources/load-wasm.php?name=large.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.compiledModule" +} +v8.wasm.cachedModule Properties: +{ + data : { + producedCacheSize : <number> + } + endTime : <number> + startTime : <number> + type : "v8.wasm.cachedModule" +} + +--- Second navigation - from a different origin ------ + +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.compiledModule Properties: +{ + data : { + url : http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=small.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.compiledModule" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.compiledModule Properties: +{ + data : { + url : http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=small.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.compiledModule" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.compiledModule Properties: +{ + data : { + url : http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=large.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.compiledModule" +} +v8.wasm.cachedModule Properties: +{ + data : { + producedCacheSize : <number> + } + endTime : <number> + startTime : <number> + type : "v8.wasm.cachedModule" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.moduleCacheHit Properties: +{ + data : { + consumedCacheSize : <number> + url : http://127.0.0.1:8000/wasm/resources/load-wasm.php?name=large.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.moduleCacheHit" +} +v8.wasm.streamFromResponseCallback Properties: +{ + data : { + } + endTime : <number> + startTime : <number> + type : "v8.wasm.streamFromResponseCallback" +} +v8.wasm.compiledModule Properties: +{ + data : { + url : http://localhost:8000/wasm/resources/load-wasm.php?name=large.wasm&cors + } + endTime : <number> + startTime : <number> + type : "v8.wasm.compiledModule" +} +v8.wasm.cachedModule Properties: +{ + data : { + producedCacheSize : <number> + } + endTime : <number> + startTime : <number> + type : "v8.wasm.cachedModule" +} +
diff --git a/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive.html b/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive.html index ab332e7..476df826 100644 --- a/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive.html +++ b/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive.html
@@ -224,7 +224,7 @@ ]; - let sampleRate = 44100; + let sampleRate = 32768; let buffer; let bufferFrameLength = 8; let testSpacingFrames = 32;
diff --git a/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html b/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html index d50c6fc6a..d63eff8 100644 --- a/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html +++ b/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html
@@ -11,16 +11,22 @@ <script src="../../resources/testharnessreport.js"></script> <script src="../resources/audit-util.js"></script> <script src="../resources/audit.js"></script> + <script src="../resources/audio-file-utils.js"></script> </head> <body> <script id="layout-test-code"> let audit = Audit.createTaskRunner(); - let sampleRate = 44100.0; + // Use power of two to eliminate round-off in computing frames from time + // and vice versa. + let sampleRate = 32768; let numberOfNotes = 60; // play over a 5 octave range - let noteDuration = 0.025; - let noteSpacing = - noteDuration + 0.005; // leave 5ms of silence between each "note" + // Make sure noteDuration, noteSilence, and noteSpacing are exactly whole + // frames. + let noteDuration = Math.floor(0.025 * sampleRate) / sampleRate; + // Leave about 5ms of silence between each "note" + let noteSilence = Math.floor(0.005 * sampleRate) / sampleRate; + let noteSpacing = noteDuration + noteSilence; let lengthInSeconds = numberOfNotes * noteSpacing; let context = 0; @@ -139,7 +145,7 @@ // in ULP. This is experimentally determined. Assuming that // the reference file is a 16-bit wav file, the max values in // the wave file are +/- 32768. - let maxUlp = 0.9999; + let maxUlp = 0; let threshold = maxUlp / 32768; for (let k = 0; k < renderedAudio.numberOfChannels; ++k) { @@ -150,6 +156,11 @@ expectedAudio.getChannelData(k), {absoluteThreshold: threshold}); } + + const filename = 'audiobuffersource-loop-points-actual.wav'; + if (downloadAudioBuffer(renderedAudio, filename, true)) { + should(true, 'Saved reference file').message(filename, ''); + } }) .then(() => task.done()); });
diff --git a/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-playbackrate.html b/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-playbackrate.html index a0084ae..b3b531d 100644 --- a/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-playbackrate.html +++ b/third_party/blink/web_tests/webaudio/AudioBufferSource/audiobuffersource-playbackrate.html
@@ -16,22 +16,22 @@ // Any sample rate mutiple of 128 is valid for this test, but here it uses // 48000Hz because it is a commonly used number that happens to be // multiple of 128. - let sampleRate = 48000; + let sampleRate = 32768; // The test iterates over 60 pitches starting from 36. (MIDI pitch of C2) let fundamentalPitch = 36; let numberOfPitches = 60; - let noteDuration = 0.025; + let noteDuration = Math.floor(0.025 * sampleRate) / sampleRate; let totalDuration = noteDuration * numberOfPitches; // Test constraints for each octave. let testConstraints = [ - {thresholdSNR: 103.8508, thresholdDiffULP: 0.3028}, - {thresholdSNR: 103.8657, thresholdDiffULP: 0.3029}, - {thresholdSNR: 103.8141, thresholdDiffULP: 0.3047}, - {thresholdSNR: 103.6818, thresholdDiffULP: 0.3262}, - {thresholdSNR: 103.1514, thresholdDiffULP: 0.3946} + {thresholdSNR: 97.215, thresholdDiffULP: 0.6446}, + {thresholdSNR: 97.212, thresholdDiffULP: 0.6446}, + {thresholdSNR: 97.217, thresholdDiffULP: 0.6446}, + {thresholdSNR: 97.196, thresholdDiffULP: 0.6485}, + {thresholdSNR: 97.074, thresholdDiffULP: 0.6915} ]; function pitchToFrequency(midiPitch) {
diff --git a/third_party/blink/web_tests/webaudio/AudioBufferSource/resources/audiobuffersource-loop-points-expected.wav b/third_party/blink/web_tests/webaudio/AudioBufferSource/resources/audiobuffersource-loop-points-expected.wav index 7f7d8646..9a5e0440e 100644 --- a/third_party/blink/web_tests/webaudio/AudioBufferSource/resources/audiobuffersource-loop-points-expected.wav +++ b/third_party/blink/web_tests/webaudio/AudioBufferSource/resources/audiobuffersource-loop-points-expected.wav Binary files differ
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js index 801b17a..53dc7d7 100644 --- a/third_party/closure_compiler/externs/automation.js +++ b/third_party/closure_compiler/externs/automation.js
@@ -1189,6 +1189,12 @@ chrome.automation.AutomationNode.prototype.language; /** + * The detected language code for this subtree. + * @type {(string|undefined)} + */ +chrome.automation.AutomationNode.prototype.detectedLanguage; + +/** * Indicates the availability and type of interactive popup element true - the popup is a menu menu - the popup is a menu listbox - the popup is a listbox tree - the popup is a tree grid - the popup is a grid dialog - the popup is a dialog * @type {(string|undefined)} * @see https://developer.chrome.com/extensions/automation#type-hasPopup
diff --git a/third_party/closure_compiler/externs/chrome_extensions.js b/third_party/closure_compiler/externs/chrome_extensions.js index 6039cc2..8800ee7a 100644 --- a/third_party/closure_compiler/externs/chrome_extensions.js +++ b/third_party/closure_compiler/externs/chrome_extensions.js
@@ -10343,6 +10343,193 @@ /** * @const + * @see https://cs.chromium.org/chromium/src/extensions/common/api/bluetooth_private.idl + */ +chrome.bluetoothPrivate = {}; + + + +/** @constructor */ +chrome.bluetoothPrivate.PairingEvent = function() {}; + + +/** @type {string} */ +chrome.bluetoothPrivate.PairingEvent.prototype.pairing; + + +/** @type {!chrome.bluetooth.Device} */ +chrome.bluetoothPrivate.PairingEvent.prototype.device; + + +/** @type {string|undefined} */ +chrome.bluetoothPrivate.PairingEvent.prototype.pincode; + + +/** @type {number|undefined} */ +chrome.bluetoothPrivate.PairingEvent.prototype.passkey; + + +/** @type {number|undefined} */ +chrome.bluetoothPrivate.PairingEvent.prototype.enteredKey; + + +/** + * @typedef {{ + * name: (string|undefined), + * powered: (boolean|undefined), + * discoverable: (boolean|undefined) + * }} + */ +chrome.bluetoothPrivate.NewAdapterState; + + +/** + * @typedef {{ + * device: !chrome.bluetooth.Device, + * response: (string|undefined), + * pincode: (string|undefined), + * passkey: (number|undefined), + * enteredKey: (number|undefined) + * }} + */ +chrome.bluetoothPrivate.SetPairingResponseOptions; + + +/** + * @param {!chrome.bluetoothPrivate.NewAdapterState} adapterState + * @param {function()} callback + * @return {undefined} + */ +chrome.bluetoothPrivate.setAdapterState = function(adapterState, callback) {}; + + +/** + * @param {!chrome.bluetoothPrivate.SetPairingResponseOptions} options + * @param {function()} callback + * @return {undefined} + */ +chrome.bluetoothPrivate.setPairingResponse = function(options, callback) {}; + + +/** + * @param {string} deviceAddress + * @param {function():void=} callback + */ +chrome.bluetoothPrivate.disconnectAll = function(deviceAddress, callback) {}; + + +/** + * @param {string} deviceAddress + * @param {function():void=} callback + * @return {undefined} + */ +chrome.bluetoothPrivate.forgetDevice = function(deviceAddress, callback) {}; + + +/** + * @typedef {{ + * transport: (!chrome.bluetoothPrivate.TransportType|undefined), + * uuids: ((string|!Array<string>)|undefined), + * rssi: (number|undefined), + * pathloss: (number|undefined) + * }} + */ +chrome.bluetoothPrivate.DiscoveryFilter; + + +/** + * Set or clear discovery filter. + * @param {!chrome.bluetoothPrivate.DiscoveryFilter} discoveryFilter + * @param {function():void=} callback + */ +chrome.bluetoothPrivate.setDiscoveryFilter = function( + discoveryFilter, callback) {}; + + +/** + * Event whose listeners take a PairingEvent parameter. + * @interface + * @extends {ChromeBaseEvent<function(!chrome.bluetoothPrivate.PairingEvent)>} + */ +chrome.bluetoothPrivate.PairingEventEvent = function() {}; + + +/** @type {!chrome.bluetoothPrivate.PairingEventEvent} */ +chrome.bluetoothPrivate.onPairing; + + +/** + * @param {string} deviceAddress + * @param {function(number, string): void=} opt_callback + */ +chrome.bluetoothPrivate.pair = function(deviceAddress, opt_callback) {}; + + +/** + * @enum {string} + * @see https://developer.chrome.com/extensions/bluetoothPrivate#type-PairingResponse + */ +chrome.bluetoothPrivate.PairingResponse = { + CONFIRM: '', + REJECT: '', + CANCEL: '', +}; + + +/** + * @enum {string} + * @see https://developer.chrome.com/extensions/bluetoothPrivate#type-PairingEventType + */ +chrome.bluetoothPrivate.PairingEventType = { + REQUEST_PINCODE: '', + DISPLAY_PINCODE: '', + REQUEST_PASSKEY: '', + DISPLAY_PASSKEY: '', + KEYS_ENTERED: '', + CONFIRM_PASSKEY: '', + REQUEST_AUTHORIZATION: '', + COMPLETE: '', +}; + + +/** + * @enum {string} + * @see https://developer.chrome.com/extensions/bluetoothPrivate#type-ConnectResultType + */ +chrome.bluetoothPrivate.ConnectResultType = { + ALREADY_CONNECTED: '', + ATTRIBUTE_LENGTH_INVALID: '', + AUTH_CANCELED: '', + AUTH_FAILED: '', + AUTH_REJECTED: '', + AUTH_TIMEOUT: '', + CONNECTION_CONGESTED: '', + FAILED: '', + IN_PROGRESS: '', + INSUFFICIENT_ENCRYPTION: '', + OFFSET_INVALID: '', + READ_NOT_PERMITTED: '', + REQUEST_NOT_SUPPORTED: '', + SUCCESS: '', + UNKNOWN_ERROR: '', + UNSUPPORTED_DEVICE: '', + WRITE_NOT_PERMITTED: '', +}; + + +/** + * @enum {string} + * @see https://developer.chrome.com/extensions/bluetoothPrivate#type-TransportType + */ +chrome.bluetoothPrivate.TransportType = { + LE: '', + BREDR: '', + DUAL: '', +}; + + +/** + * @const * @see http://goo.gl/XmVdHm */ chrome.inlineInstallPrivate = {};
diff --git a/third_party/closure_compiler/externs/pending.js b/third_party/closure_compiler/externs/pending.js index f09f3948..d567fa8 100644 --- a/third_party/closure_compiler/externs/pending.js +++ b/third_party/closure_compiler/externs/pending.js
@@ -46,6 +46,34 @@ } /** + * TODO(dstockwell): Remove this once it is added to Closure Compiler itself. + * @see https://drafts.fxtf.org/geometry/#DOMMatrix + */ +class DOMMatrix { + /** + * @param {number} x + * @param {number} y + */ + translateSelf(x, y) {} + /** + * @param {number} x + * @param {number} y + * @param {number} z + */ + rotateSelf(x, y, z) {} + /** + * @param {number} x + * @param {number} y + */ + scaleSelf(x, y) {} + /** + * @param {{x: number, y: number}} point + * @return {{x: number, y: number}} + */ + transformPoint(point) {} +} + +/** * @see https://wicg.github.io/ResizeObserver/#resizeobserverentry * @typedef {{contentRect: DOMRectReadOnly, * target: Element}}
diff --git a/third_party/fuchsia-sdk/BUILD.gn b/third_party/fuchsia-sdk/BUILD.gn index f9618f3..9a6dfad 100644 --- a/third_party/fuchsia-sdk/BUILD.gn +++ b/third_party/fuchsia-sdk/BUILD.gn
@@ -4,6 +4,7 @@ assert(is_fuchsia) +import("//build/toolchain/toolchain.gni") import("fuchsia_sdk_pkg.gni") config("sdk_lib_dirs_config") { @@ -11,6 +12,29 @@ lib_dirs = [ "sdk/arch/${target_cpu}/lib" ] } +# Copy the loader to place it at the expected path in the final package. +copy("sysroot_dist_libs") { + sources = [ + "sdk/arch/${target_cpu}/sysroot/dist/lib/ld.so.1", + ] + + outputs = [ + "${root_out_dir}${shlib_subdir}/{{source_file_part}}", + ] +} + +# This adds the runtime deps for //build/config/compiler:runtime_library +# as that is a config target and thus cannot include data_deps. +group("runtime_library") { + data_deps = [ + ":sysroot_dist_libs", + + # This is used directly from //build/config/fuchsia:compiler and thus + # also needs to be included by default. + "sdk:fdio_dist_libs", + ] +} + copy("vulkan_base_configs") { sources = [ "sdk/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_image_pipe_swapchain.json", @@ -21,21 +45,21 @@ ] } -copy("vulkan_base_libs") { +copy("vulkan_image_pipe") { sources = [ "sdk/arch/${target_cpu}/dist/libVkLayer_image_pipe_swapchain.so", - "sdk/arch/${target_cpu}/dist/libvulkan.so", ] outputs = [ - "${root_out_dir}/{{source_file_part}}", + "${root_out_dir}${shlib_subdir}/{{source_file_part}}", ] } group("vulkan_base") { data_deps = [ ":vulkan_base_configs", - ":vulkan_base_libs", + ":vulkan_image_pipe", + "sdk:vulkan_dist_libs", ] } @@ -64,7 +88,7 @@ ] outputs = [ - "${root_out_dir}/{{source_file_part}}", + "${root_out_dir}${shlib_subdir}/{{source_file_part}}", ] }
diff --git a/third_party/fuchsia-sdk/LICENSE b/third_party/fuchsia-sdk/LICENSE new file mode 100644 index 0000000..6d6ddbcc --- /dev/null +++ b/third_party/fuchsia-sdk/LICENSE
@@ -0,0 +1,27 @@ +// Copyright 2019 The Fuchsia Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni b/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni index 371e622e..32c8c89 100644 --- a/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni +++ b/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni
@@ -5,6 +5,7 @@ assert(is_fuchsia) import("//build/config/fuchsia/fidl_library.gni") +import("//build/toolchain/toolchain.gni") # Templates for Fuchsia SDK packages. @@ -48,19 +49,38 @@ # is not specified explicitly. # sources - List of sources relative to sdk/pkg/${name}. # deps - List of dependencies. -# libs - List of precompiled libraries. +# shared_libs - List of precompiled shared libraries. +# static_libs - List of precompiled static libraries. template("fuchsia_sdk_pkg") { config("${target_name}_config") { forward_variables_from(invoker, [ "include_dirs" ]) visibility = [ ":${invoker.target_name}" ] } + if (defined(invoker.shared_libs)) { + if (defined(invoker.sdk_dist_dir)) { + sdk_dist_dir = invoker.sdk_dist_dir + } else { + sdk_dist_dir = "arch/${target_cpu}/dist" + } + + copy("${target_name}_dist_libs") { + sources = [] + foreach(lib, invoker.shared_libs) { + sources += [ "${sdk_dist_dir}/lib${lib}.so" ] + } + + outputs = [ + "${root_out_dir}${shlib_subdir}/{{source_file_part}}", + ] + } + } + static_library(target_name) { forward_variables_from(invoker, [ "data", "deps", - "libs", "public_deps", "sources", "testonly", @@ -69,8 +89,14 @@ public_configs = [ ":${invoker.target_name}_config" ] - if (defined(libs)) { + if (defined(invoker.shared_libs)) { configs += [ "//third_party/fuchsia-sdk:sdk_lib_dirs_config" ] + libs = invoker.shared_libs + data_deps = [ + ":${target_name}_dist_libs", + ] + } else if (defined(invoker.static_libs)) { + libs = invoker.static_libs } } }
diff --git a/third_party/fuchsia-sdk/gen_build_defs.py b/third_party/fuchsia-sdk/gen_build_defs.py index a6389545..ec501c7 100755 --- a/third_party/fuchsia-sdk/gen_build_defs.py +++ b/third_party/fuchsia-sdk/gen_build_defs.py
@@ -121,9 +121,13 @@ converted = ConvertCommonFields(json) converted['type'] = 'fuchsia_sdk_pkg' converted['sources'] = json['headers'] - converted['libs'] = [json['name']] converted['include_dirs'] = [json['root'] + '/include'] + if json['format'] == 'shared': + converted['shared_libs'] = [json['name']] + else: + converted['static_libs'] = [json['name']] + return converted def ConvertCcSourceLibrary(json):
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 0b2dd12b..f3f27b0 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -2200,6 +2200,8 @@ </action> <action name="Arc.SmartTextSelection.Request"> + <owner>linben@chromium.org</owner> + <owner>djacobo@chromium.org</owner> <owner>jorgegil@google.com</owner> <description> Recorded when a request to the ARC++ container to generate Smart Text
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a761b4b..baa83fc 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -8260,6 +8260,8 @@ <int value="44" label="USB guard"/> <int value="45" label="Background fetch"/> <int value="46" label="Intent picker display"/> + <int value="47" label="Serial guard"/> + <int value="48" label="Serial permission data"/> </enum> <enum name="ContentTypeParseableResult"> @@ -10992,6 +10994,7 @@ <int value="16" label="Squid"/> <int value="17" label="Web Store"/> <int value="18" label="YouTube"/> + <int value="19" label="Screensaver"/> </enum> <enum name="DemoModeIdleLogoutWarningEvent"> @@ -12702,6 +12705,26 @@ <int value="319" label="pyo"/> <int value="320" label="desktop"/> <int value="321" label="cpi"/> + <int value="322" label="jpg"/> + <int value="323" label="jpeg"/> + <int value="324" label="mp3"/> + <int value="325" label="mp4"/> + <int value="326" label="png"/> + <int value="327" label="xls"/> + <int value="328" label="doc"/> + <int value="329" label="pptx"/> + <int value="330" label="csv"/> + <int value="331" label="ica"/> + <int value="332" label="ppt"/> + <int value="333" label="gif"/> + <int value="334" label="txt"/> + <int value="335" label="package"/> + <int value="336" label="tif"/> + <int value="337" label="rtf"/> + <int value="338" label="webp"/> + <int value="339" label="mkv"/> + <int value="340" label="wav"/> + <int value="341" label="mov"/> </enum> <enum name="DownloadItem.DangerType"> @@ -43702,6 +43725,7 @@ <int value="11" label="INVITATION_AVAILABLE"/> <int value="12" label="INVITATION_ACCEPTED"/> <int value="13" label="INVITATION_REJECTED"/> + <int value="14" label="MANAGE_BUTTON_CLICKED"/> </enum> <enum name="PrintPreviewPrintDocumentTypeBuckets"> @@ -46883,6 +46907,28 @@ <int value="317" label="OXT"/> <int value="318" label="PYD"/> <int value="319" label="PYO"/> + <int value="320" label="DESKTOP"/> + <int value="321" label="CPI"/> + <int value="322" label="JPG"/> + <int value="323" label="JPEG"/> + <int value="324" label="MP3"/> + <int value="325" label="MP4"/> + <int value="326" label="PNG"/> + <int value="327" label="XLS"/> + <int value="328" label="DOC"/> + <int value="329" label="PPTX"/> + <int value="330" label="CSV"/> + <int value="331" label="ICA"/> + <int value="332" label="PPT"/> + <int value="333" label="GIF"/> + <int value="334" label="TXT"/> + <int value="335" label="PACKAGE"/> + <int value="336" label="TIF"/> + <int value="337" label="RTF"/> + <int value="338" label="WEBP"/> + <int value="339" label="MKV"/> + <int value="340" label="WAV"/> + <int value="341" label="MOV"/> </enum> <enum name="SBClientDownloadIsSignedBinary">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index feaf30b..6bcc0de 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -9705,6 +9705,16 @@ <summary>Records whenever a Blimp tab toggles visibility.</summary> </histogram> +<histogram name="Blink.Animate.UpdateTime" units="microseconds"> + <owner>paint-dev@chromium.org</owner> + <summary> + Time spent processing main frame animations during a main frame update. + + This histogram does not record metrics on machines with low-resolution + clocks. + </summary> +</histogram> + <histogram name="Blink.Binding.CreateV8ContextForMainFrame" units="microseconds"> <owner>peria@chromium.org</owner> @@ -10650,6 +10660,16 @@ </summary> </histogram> +<histogram name="Blink.HandleInputEvents.UpdateTime" units="microseconds"> + <owner>paint-dev@chromium.org</owner> + <summary> + Time spent processing rAF-aligned input during a main frame update. + + This histogram does not record metrics on machines with low-resolution + clocks. + </summary> +</histogram> + <histogram name="Blink.ImageDecoders.Jpeg.Area" units="pixels"> <owner>andrescj@chromium.org</owner> <summary> @@ -57109,17 +57129,20 @@ </histogram> <histogram name="Net.BidirectionalStream.ReceivedBytes" units="bytes"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary>Number of bytes received over this stream.</summary> </histogram> <histogram name="Net.BidirectionalStream.SentBytes" units="bytes"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary>Number of bytes sent over this stream.</summary> </histogram> <histogram name="Net.BidirectionalStream.TimeToReadEnd" units="ms"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> How long it takes from starting the request to reading the end of the response. @@ -57127,7 +57150,8 @@ </histogram> <histogram name="Net.BidirectionalStream.TimeToReadStart" units="ms"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> How long it takes from starting the request to reading the start of the response. @@ -57135,14 +57159,16 @@ </histogram> <histogram name="Net.BidirectionalStream.TimeToSendEnd" units="ms"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> How long it takes from starting the request to when the last byte is sent. </summary> </histogram> <histogram name="Net.BidirectionalStream.TimeToSendStart" units="ms"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> How long it takes from starting the request to when we can start sending data. @@ -57995,7 +58021,8 @@ </histogram> <histogram name="Net.ContentDecodingFailed2" enum="NetFilterType2"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> For each CONTENT_DECODING_FAILED, record the filter that failed. </summary> @@ -58005,7 +58032,8 @@ <obsolete> Obsoleted in favor of Net.ContentDecodingFailed2 above. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> For each CONTENT_DECODING_FAILED, record the filter that failed. </summary> @@ -60305,7 +60333,8 @@ <obsolete> Deprecated as of 1/2018. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary>Reports the next state that the Alternative Job is in.</summary> </histogram> @@ -60314,7 +60343,8 @@ <obsolete> Deprecated as of 1/2018. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary>Reports the state that the Alternative Job is in.</summary> </histogram> @@ -60323,7 +60353,8 @@ <obsolete> Deprecated as of 1/2018. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary>Reports the next state that the Main Job is in.</summary> </histogram> @@ -60332,7 +60363,8 @@ <obsolete> Deprecated as of 1/2018. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary>Reports the state that the Main Job is in.</summary> </histogram> @@ -60691,7 +60723,8 @@ <histogram name="Net.NetworkConfigWatcherMac.SCDynamicStore.Create" enum="SCStatusCode"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> This is logged when SCDynamicStoreCreate fails in network_config_watcher_mac.cc. @@ -60701,7 +60734,8 @@ <histogram name="Net.NetworkConfigWatcherMac.SCDynamicStore.Create.RunLoopSource" enum="SCStatusCode"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> This is logged when SCDynamicStoreCreateRunLoopSource fails in network_config_watcher_mac.cc. @@ -60710,7 +60744,8 @@ <histogram name="Net.NetworkConfigWatcherMac.SCDynamicStore.NumRetry" units="retries"> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> This is logged when retrying SCDynamicStore has stopped after either receiving a success or hitting the maximum number of retries in @@ -63547,7 +63582,8 @@ <obsolete> Removed from Chromium as of 2018/7. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> The largest number of outstanding requests that are handled by the resource dispatcher host for a single process. @@ -63559,7 +63595,8 @@ <obsolete> Removed from Chromium as of 2018/7. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> The largest number of outstanding requests that are handled by the resource dispatcher host across all processes. @@ -63714,7 +63751,8 @@ <obsolete> Deprecated as of 9/2017. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> Whether an idle socket is reused, timed out, or closed to make room for new sockets. @@ -63736,7 +63774,8 @@ <obsolete> Deprecated as of 11/2016. </obsolete> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <summary> Number of milliseconds an idle socket saved in connection establishment because it is reused. @@ -136168,7 +136207,8 @@ <histogram_suffixes name="Net.BidirectionalStreamExperiment" separator="."> <suffix name="HTTP2" label="Bidirectional stream that use HTTP2 protocol"/> - <owner>xunjieli@chromium.org</owner> + <owner>mef@chromium.org</owner> + <owner>pauljensen@chromium.org</owner> <suffix name="QUIC" label="Bidirectional streams that use QUIC protocol"/> <affected-histogram name="Net.BidirectionalStream.ReceivedBytes"/> <affected-histogram name="Net.BidirectionalStream.SentBytes"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 807e80c9..12bb1fec 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -457,6 +457,11 @@ ith type was detected. Multiple types are possible. </summary> </metric> + <metric name="HasUpiVpaField"> + <summary> + True for forms containing a UPI/VPA field. + </summary> + </metric> <metric name="IsForCreditCard"> <summary> True for credit card forms, false for address/profile forms. See @@ -654,6 +659,39 @@ compositing, and layout update times. The metrics are recorded once per 30 seconds and at the destruction of the local frame root. </summary> + <metric name="Animate.Average"> + <summary> + The average time taken for main frame animation in microseconds in the + event period. + </summary> + <aggregation> + <history> + <index fields="profile.country"/> + <statistics> + <quantiles type="std-percentiles"/> + </statistics> + </history> + </aggregation> + </metric> + <metric name="Animate.AverageRatio"> + <summary> + The average over frames within the sample window of the ratio of time + taken for main frame animation to the total time for the main frame. An + int in the range [0,100]. + </summary> + </metric> + <metric name="Animate.WorstCase"> + <summary> + The longest single time taken for main frame animation in microseconds in + the event period. + </summary> + </metric> + <metric name="Animate.WorstCaseRatio"> + <summary> + The highest proportion of a frame ever used for main frame animation + within the sample window. An int in the range [0,100]. + </summary> + </metric> <metric name="Compositing.Average"> <summary> The average time taken by the compositing phase in microseconds in the @@ -755,6 +793,40 @@ frame. An int in the range [0,100]. </summary> </metric> + <metric name="HandleInputEvents.Average"> + <summary> + The average time taken to process rAF-aligned input for the main frame in + microseconds in the event period. + </summary> + <aggregation> + <history> + <index fields="profile.country"/> + <statistics> + <quantiles type="std-percentiles"/> + </statistics> + </history> + </aggregation> + </metric> + <metric name="HandleInputEvents.AverageRatio"> + <summary> + The average over frames within the sample window of the ratio of time + taken to process rAF-aligned input for the main frame to the total time + for the main frame. An int in the range [0,100]. + </summary> + </metric> + <metric name="HandleInputEvents.WorstCase"> + <summary> + The longest single time taken to process rAF-aligned input for the main + frame in microseconds in the event period. + </summary> + </metric> + <metric name="HandleInputEvents.WorstCaseRatio"> + <summary> + The highest proportion of a frame ever taken to process rAF-aligned input + for the main frame to the total time for the main frame. An int in the + range [0,100]. + </summary> + </metric> <metric name="IntersectionObservation.Average"> <summary> The average time taken to compute IntersectionObserver observations in
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv index a47990f..f5721c6 100644 --- a/tools/perf/benchmark.csv +++ b/tools/perf/benchmark.csv
@@ -26,7 +26,7 @@ load_library_perf_tests,"xhwang@chromium.org, crouleau@chromium.org",Internals>Media>Encrypted,, loading.desktop,"kouhei@chromium.org, ksakamoto@chromium.org",,https://bit.ly/loading-benchmarks,"cache_temperature_cold,cache_temperature_warm,international,intl_ar_fa_he,intl_es_fr_pt_BR,intl_hi_ru,intl_ja_zh,intl_ko_th_vi,typical" loading.mobile,"kouhei@chromium.org, ksakamoto@chromium.org",,https://bit.ly/loading-benchmarks,"cache_temperature_cold,cache_temperature_hot,cache_temperature_warm,easy_ttfmp,easy_tti,global,pwa,tough_ttfmp,tough_tti" -media.desktop,dalecurtis@chromium.org,Internals>Media,,"aac,audio_only,audio_video,background,beginning_to_end,busyjs,cns,h264,is_4k,is_50fps,mp3,mse,opus,pcm,seek,src,video_only,vorbis,vp8,vp9" +media.desktop,dalecurtis@chromium.org,Internals>Media,,"aac,audio_only,audio_video,av1,background,beginning_to_end,busyjs,cns,h264,is_4k,is_50fps,mp3,mse,opus,pcm,seek,src,video_only,vorbis,vp8,vp9" media.mobile,dalecurtis@chromium.org,Internals>Media,,"aac,audio_only,audio_video,background,beginning_to_end,busyjs,cns,h264,mp3,mse,opus,pcm,seek,src,video_only,vorbis,vp9" media_perftests,"crouleau@chromium.org, dalecurtis@chromium.org",Internals>Media,, memory.desktop,erikchen@chromium.org,,,
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 544a19f..968d173 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -931,27 +931,20 @@ return test_args + def generate_non_telemetry_args(test_name): # --gtest-benchmark-name so the benchmark name is consistent with the test # step's name. This is not always the same as the test binary's name (see # crbug.com/870692). - # --non-telemetry tells run_performance_tests.py that this test needs - # to be executed differently - # --migrated-test tells run_performance_test_wrapper that this has - # non-telemetry test has been migrated to the new recipe. return [ '--gtest-benchmark-name', test_name, - '--non-telemetry=true', - '--migrated-test=true' ] + def generate_performance_test(tester_config, test): isolate_name = test['isolate'] - # Check to see if the name is different than the isolate - test_suite = isolate_name - if test.get('test_suite', False): - test_suite = test['test_suite'] + test_suite = test.get('test_suite', isolate_name) if test.get('telemetry', True): test_args = generate_telemetry_args(tester_config)
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py index 9925042..2e6b27e2 100644 --- a/tools/perf/core/perf_data_generator_unittest.py +++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -72,8 +72,7 @@ expected_generated_test = { 'override_compile_targets': ['angle_perftest'], 'isolate_name': 'angle_perftest', - 'args': ['--gtest-benchmark-name', 'angle_perftest', - '--non-telemetry=true', '--migrated-test=true'], + 'args': ['--gtest-benchmark-name', 'angle_perftest'], 'trigger_script': { 'args': [ '--multiple-dimension-script-verbose', @@ -121,7 +120,8 @@ 'override_compile_targets': ['performance_test_suite'], 'isolate_name': 'performance_test_suite', 'args': ['-v', '--browser=android-webview', '--upload-results', - '--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk', + '--webview-embedder-apk=../../out/Release' + '/apks/SystemWebViewShell.apk', '--run-ref-build', '--test-shard-map-filename=shard_map.json'], 'trigger_script': {
diff --git a/tools/perf/page_sets/media_cases.py b/tools/perf/page_sets/media_cases.py index 37993cf..5f213b8 100644 --- a/tools/perf/page_sets/media_cases.py +++ b/tools/perf/page_sets/media_cases.py
@@ -24,6 +24,7 @@ 'vorbis', 'opus', # Video codecs. + 'av1', 'h264', 'vp8', 'vp9', @@ -204,7 +205,24 @@ raise RuntimeError(action_runner.EvaluateJavaScript('window.__testError')) -def _GetMediaPages(page_set): +def _GetDesktopOnlyMediaPages(page_set): + return [ + _BeginningToEndPlayPage( + url=_URL_BASE + 'video.html?src=tulip0.av1.mp4', + page_set=page_set, + tags=['av1', 'video_only']), + _SeekPage( + url=_URL_BASE + 'video.html?src=tulip0.av1.mp4&seek', + page_set=page_set, + tags=['av1', 'video_only', 'seek']), + _MSEPage( + url=_URL_BASE + 'mse.html?media=tulip0.av1.mp4', + page_set=page_set, + tags=['av1', 'video_only']), + ] + + +def _GetCrossPlatformMediaPages(page_set): return [ _BeginningToEndPlayPage( url=_URL_BASE + 'video.html?src=crowd.ogg&type=audio', @@ -349,7 +367,8 @@ many other media-specific and generic metrics. """ def _BuildPages(self): - return iter(_GetMediaPages(self)) + return iter( + _GetCrossPlatformMediaPages(self) + _GetDesktopOnlyMediaPages(self)) class MediaCasesMobileStorySet(_MediaCasesStorySet): @@ -361,7 +380,7 @@ devices. """ def _BuildPages(self): - for page in _GetMediaPages(self): + for page in _GetCrossPlatformMediaPages(self): if 'is_4k' in page.tags or 'is_50fps' in page.tags: continue yield page
diff --git a/tools/perf/page_sets/media_cases/mse.js b/tools/perf/page_sets/media_cases/mse.js index 3d16fba5..6a097f8 100644 --- a/tools/perf/page_sets/media_cases/mse.js +++ b/tools/perf/page_sets/media_cases/mse.js
@@ -12,6 +12,7 @@ const MEDIA_MIMES = { "aac_audio.mp4": "audio/mp4; codecs=\"mp4a.40.2\"", "h264_video.mp4": "video/mp4; codecs=\"avc1.640028\"", + "tulip0.av1.mp4": "video/mp4; codecs=\"av01.0.05M.08\"", }; const testParams = {}
diff --git a/tools/perf/page_sets/media_cases/tulip0.av1.mp4.sha1 b/tools/perf/page_sets/media_cases/tulip0.av1.mp4.sha1 new file mode 100644 index 0000000..8936683 --- /dev/null +++ b/tools/perf/page_sets/media_cases/tulip0.av1.mp4.sha1
@@ -0,0 +1 @@ +5f93fb72701a3924b2ba719f5a1a4ae49e678fc6 \ No newline at end of file
diff --git a/ui/aura/mus/embed_root.cc b/ui/aura/mus/embed_root.cc index 32fa6b5..e0262c58 100644 --- a/ui/aura/mus/embed_root.cc +++ b/ui/aura/mus/embed_root.cc
@@ -55,22 +55,35 @@ } void FocusWindowImpl(Window* window) { - Window* previously_focused_window = focused_window_; + Window* lost_focus = focused_window_; - if (previously_focused_window) - previously_focused_window->RemoveObserver(this); + if (lost_focus) + lost_focus->RemoveObserver(this); focused_window_ = window; if (focused_window_) focused_window_->AddObserver(this); WindowTracker window_tracker; - if (previously_focused_window) - window_tracker.Add(previously_focused_window); + if (lost_focus) + window_tracker.Add(lost_focus); + for (auto& observer : observers_) { observer.OnWindowFocused( - focused_window_, window_tracker.Contains(previously_focused_window) - ? previously_focused_window - : nullptr); + focused_window_, + window_tracker.Contains(lost_focus) ? lost_focus : nullptr); + } + if (window_tracker.Contains(lost_focus)) { + client::FocusChangeObserver* observer = + client::GetFocusChangeObserver(lost_focus); + if (observer) + observer->OnWindowFocused(focused_window_, lost_focus); + } + client::FocusChangeObserver* observer = + client::GetFocusChangeObserver(focused_window_); + if (observer) { + observer->OnWindowFocused( + focused_window_, + window_tracker.Contains(lost_focus) ? lost_focus : nullptr); } }
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 74e8d5b78..b4639d8 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -562,7 +562,7 @@ SendDamagedRectsRecursive(child); } -void Compositor::UpdateLayerTreeHost(bool record_main_frame_metrics) { +void Compositor::UpdateLayerTreeHost() { if (!root_layer()) return; SendDamagedRectsRecursive(root_layer());
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index 313431f..99f547c 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h
@@ -370,7 +370,7 @@ void BeginMainFrame(const viz::BeginFrameArgs& args) override; void BeginMainFrameNotExpectedSoon() override; void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override; - void UpdateLayerTreeHost(bool record_main_frame_metrics) override; + void UpdateLayerTreeHost() override; void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override { } void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel, @@ -391,6 +391,7 @@ void DidPresentCompositorFrame( uint32_t frame_token, const gfx::PresentationFeedback& feedback) override; + void RecordStartOfFrameMetrics() override {} void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override {} void DidGenerateLocalSurfaceIdAllocation( const viz::LocalSurfaceIdAllocation& allocation) override;
diff --git a/ui/display/display_switches.cc b/ui/display/display_switches.cc index 40b7fa1..9e2d1f0 100644 --- a/ui/display/display_switches.cc +++ b/ui/display/display_switches.cc
@@ -2,17 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" #include "ui/display/display_switches.h" +#include "build/build_config.h" namespace switches { // TODO(rjkroege): Some of these have an "ash" prefix. When ChromeOS startup // scripts have been updated, the leading "ash" prefix should be removed. -// Disables mirroring across multiple displays. -const char kDisableMultiMirroring[] = "disable-multi-mirroring"; - // Enables software based mirroring. const char kEnableSoftwareMirroring[] = "ash-enable-software-mirroring";
diff --git a/ui/display/display_switches.h b/ui/display/display_switches.h index 0079182..70fac73 100644 --- a/ui/display/display_switches.h +++ b/ui/display/display_switches.h
@@ -13,7 +13,6 @@ namespace switches { // Keep sorted. -DISPLAY_EXPORT extern const char kDisableMultiMirroring[]; DISPLAY_EXPORT extern const char kEnableSoftwareMirroring[]; DISPLAY_EXPORT extern const char kEnsureForcedColorProfile[]; DISPLAY_EXPORT extern const char kForceDeviceScaleFactor[];
diff --git a/ui/display/manager/display_change_observer.cc b/ui/display/manager/display_change_observer.cc index e99d15e4..73657edf 100644 --- a/ui/display/manager/display_change_observer.cc +++ b/ui/display/manager/display_change_observer.cc
@@ -43,11 +43,8 @@ // Update the list of zoom levels whenever a new device scale factor is added // here. See zoom level list in /ui/display/manager/display_util.cc const DeviceScaleFactorDPIThreshold kThresholdTableForInternal[] = { - {270.0f, 2.25f}, - {220.0f, 2.0f}, - {180.0f, 1.6f}, - {150.0f, 1.25f}, - {0.0f, 1.0f}, + {270.0f, 2.25f}, {220.0f, 2.0f}, {180.0f, 1.6f}, + {150.0f, 1.25f}, {0.0f, 1.0f}, }; } // namespace @@ -137,14 +134,6 @@ UpdateInternalDisplay(display_states); if (display_states.size() == 1) return MULTIPLE_DISPLAY_STATE_SINGLE; - if (!display_manager_->is_multi_mirroring_enabled() && - display_states.size() > 2) { - // TODO(weidongg/774795): Remove this condition when multi-mirroring is - // enabled by default. - // When multi-mirroring is disabled, mirroring across 3+ displays are not - // supported, so default to EXTENDED. - return MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED; - } DisplayIdList list = GenerateDisplayIdList(display_states.begin(), display_states.end(), [](const DisplaySnapshot* display_state) {
diff --git a/ui/display/manager/display_configurator.cc b/ui/display/manager/display_configurator.cc index 4d184bb..a114d43 100644 --- a/ui/display/manager/display_configurator.cc +++ b/ui/display/manager/display_configurator.cc
@@ -298,12 +298,8 @@ return false; } - bool can_set_mirror_mode = - configurator_->is_multi_mirroring_enabled_ - ? (states.size() > 1 && - (num_on_displays == 0 || num_on_displays > 1)) - : (states.size() == 2 && - (num_on_displays == 0 || num_on_displays == 2)); + const bool can_set_mirror_mode = + states.size() > 1 && num_on_displays != 1; if (!can_set_mirror_mode) { LOG(WARNING) << "Ignoring request to enter mirrored mode with " << states.size() << " connected display(s) and " @@ -379,9 +375,8 @@ const DisplaySnapshot& display) const { gfx::Size size; const DisplayMode* selected_mode = nullptr; - if (GetStateController() && - GetStateController()->GetResolutionForDisplayId(display.display_id(), - &size)) { + if (GetStateController() && GetStateController()->GetResolutionForDisplayId( + display.display_id(), &size)) { selected_mode = FindDisplayModeMatchingSize(display, size); } @@ -540,9 +535,6 @@ display_control_changing_(false), displays_suspended_(false), layout_manager_(new DisplayLayoutManagerImpl(this)), - is_multi_mirroring_enabled_( - !base::CommandLine::ForCurrentProcess()->HasSwitch( - ::switches::kDisableMultiMirroring)), weak_ptr_factory_(this) {} DisplayConfigurator::~DisplayConfigurator() { @@ -1061,9 +1053,10 @@ // This gives a chance to wait for all displays to be added and detected // before configuration is performed, so we won't immediately resize the // desktops and the windows on it to fit on a single display. - configure_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds( - kResumeConfigureMultiDisplayDelayMs), - this, &DisplayConfigurator::ConfigureDisplays); + configure_timer_.Start( + FROM_HERE, + base::TimeDelta::FromMilliseconds(kResumeConfigureMultiDisplayDelayMs), + this, &DisplayConfigurator::ConfigureDisplays); } // TODO(crbug.com/794831): Solve the issue of mirror mode on display resume.
diff --git a/ui/display/manager/display_configurator.h b/ui/display/manager/display_configurator.h index 3e55655..5e69a3c3 100644 --- a/ui/display/manager/display_configurator.h +++ b/ui/display/manager/display_configurator.h
@@ -302,16 +302,12 @@ // Returns the requested power state if set or the default power state. chromeos::DisplayPowerState GetRequestedPowerState() const; - void set_is_multi_mirroring_enabled_for_test(bool enabled) { - is_multi_mirroring_enabled_ = enabled; - } - void reset_requested_power_state_for_test() { requested_power_state_ = base::nullopt; } - base::Optional<chromeos::DisplayPowerState> - GetRequestedPowerStateForTest() const { + base::Optional<chromeos::DisplayPowerState> GetRequestedPowerStateForTest() + const { return requested_power_state_; } @@ -478,8 +474,6 @@ std::unique_ptr<UpdateDisplayConfigurationTask> configuration_task_; - bool is_multi_mirroring_enabled_; - // This must be the last variable. base::WeakPtrFactory<DisplayConfigurator> weak_ptr_factory_;
diff --git a/ui/display/manager/display_configurator_unittest.cc b/ui/display/manager/display_configurator_unittest.cc index 699fe63..76b5c6fa 100644 --- a/ui/display/manager/display_configurator_unittest.cc +++ b/ui/display/manager/display_configurator_unittest.cc
@@ -699,11 +699,10 @@ configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); EXPECT_EQ(kNoDelay, config_waiter_.Wait()); EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); - EXPECT_EQ( - JoinActions( - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), - nullptr), - log_->GetActionsAndClear()); + EXPECT_EQ(JoinActions( + GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), + nullptr), + log_->GetActionsAndClear()); // No resume delay in single display mode. config_waiter_.Reset(); @@ -724,11 +723,10 @@ config_waiter_.on_configuration_callback()); EXPECT_EQ(kNoDelay, config_waiter_.Wait()); EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); - EXPECT_EQ( - JoinActions( - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), - nullptr), - log_->GetActionsAndClear()); + EXPECT_EQ(JoinActions( + GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), + nullptr), + log_->GetActionsAndClear()); config_waiter_.Reset(); configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); @@ -938,7 +936,6 @@ EXPECT_EQ(outputs_[1]->current_mode(), cached[1]->current_mode()); } - TEST_F(DisplayConfiguratorTest, ContentProtection) { Init(false); configurator_.ForceInitialConfigure(); @@ -1017,11 +1014,10 @@ configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); EXPECT_EQ(kNoDelay, config_waiter_.Wait()); EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); - EXPECT_EQ( - JoinActions( - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), - nullptr), - log_->GetActionsAndClear()); + EXPECT_EQ(JoinActions( + GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), + nullptr), + log_->GetActionsAndClear()); // The configuration timer should not be started when the displays // are suspended. @@ -1074,11 +1070,10 @@ configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); EXPECT_EQ(kNoDelay, config_waiter_.Wait()); EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); - EXPECT_EQ( - JoinActions( - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), - nullptr), - log_->GetActionsAndClear()); + EXPECT_EQ(JoinActions( + GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), + nullptr), + log_->GetActionsAndClear()); EXPECT_FALSE(test_api_.TriggerConfigureTimeout()); EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); @@ -1424,11 +1419,10 @@ base::BindOnce(&DisplayConfiguratorTest::OnDisplayControlUpdated, base::Unretained(this))); EXPECT_EQ(CALLBACK_SUCCESS, PopDisplayControlResult()); - EXPECT_EQ( - JoinActions( - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), - kRelinquishDisplayControl, nullptr), - log_->GetActionsAndClear()); + EXPECT_EQ(JoinActions( + GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), + kRelinquishDisplayControl, nullptr), + log_->GetActionsAndClear()); configurator_.TakeControl( base::BindOnce(&DisplayConfiguratorTest::OnDisplayControlUpdated, base::Unretained(this))); @@ -1799,10 +1793,7 @@ DisplayConfiguratorMultiMirroringTest() = default; ~DisplayConfiguratorMultiMirroringTest() override = default; - void SetUp() override { - configurator_.set_is_multi_mirroring_enabled_for_test(true); - DisplayConfiguratorTest::SetUp(); - } + void SetUp() override { DisplayConfiguratorTest::SetUp(); } // Test that setting mirror mode with current outputs, all displays are set to // expected mirror mode.
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc index 43d520a6..045f5e5 100644 --- a/ui/display/manager/display_manager.cc +++ b/ui/display/manager/display_manager.cc
@@ -320,9 +320,6 @@ DisplayManager::DisplayManager(std::unique_ptr<Screen> screen) : screen_(std::move(screen)), layout_store_(new DisplayLayoutStore), - is_multi_mirroring_enabled_( - !base::CommandLine::ForCurrentProcess()->HasSwitch( - ::switches::kDisableMultiMirroring)), weak_ptr_factory_(this) { #if defined(OS_CHROMEOS) configure_displays_ = chromeos::IsRunningAsSystemCompositor(); @@ -412,13 +409,6 @@ DisplayIdList display_id_list = CreateDisplayIdList(active_display_list_); if (IsInSoftwareMirrorMode()) { - if (!is_multi_mirroring_enabled_) { - CHECK_EQ(2u, num_connected_displays()); - // This comment is to make it easy to distinguish the crash - // between two checks. - CHECK_EQ(1u, active_display_list_.size()); - } - DisplayIdList software_mirroring_display_id_list = CreateDisplayIdList(software_mirroring_display_list_); display_id_list.insert(display_id_list.end(), @@ -983,8 +973,9 @@ // the layout. // Using display.bounds() and display.work_area() would fail most of the // time. - if (force_bounds_changed_ || (current_display_info.bounds_in_native() != - new_display_info.bounds_in_native()) || + if (force_bounds_changed_ || + (current_display_info.bounds_in_native() != + new_display_info.bounds_in_native()) || (current_display_info.GetOverscanInsetsInPixel() != new_display_info.GetOverscanInsetsInPixel()) || current_display.size() != new_display.size()) { @@ -1339,10 +1330,8 @@ void DisplayManager::SetMirrorMode( MirrorMode mode, const base::Optional<MixedMirrorModeParams>& mixed_params) { - if ((is_multi_mirroring_enabled_ && num_connected_displays() < 2) || - (!is_multi_mirroring_enabled_ && num_connected_displays() != 2)) { + if (num_connected_displays() < 2) return; - } if (mode == MirrorMode::kMixed) { // Set mixed mirror mode parameters. This will be used to do two things: @@ -1713,10 +1702,8 @@ // mirrored. switch (multi_display_mode_) { case MIRRORING: { - if ((is_multi_mirroring_enabled_ && display_info_list->size() < 2) || - (!is_multi_mirroring_enabled_ && display_info_list->size() != 2)) { + if (display_info_list->size() < 2) return; - } std::set<int64_t> destination_ids; int64_t source_id = kInvalidDisplayId;
diff --git a/ui/display/manager/display_manager.h b/ui/display/manager/display_manager.h index 9efea193..aa03457 100644 --- a/ui/display/manager/display_manager.h +++ b/ui/display/manager/display_manager.h
@@ -41,7 +41,7 @@ namespace gfx { class Insets; class Rect; -} +} // namespace gfx namespace display { class DisplayLayoutStore; @@ -139,10 +139,6 @@ } #endif - bool is_multi_mirroring_enabled() const { - return is_multi_mirroring_enabled_; - } - const UnifiedDesktopLayoutMatrix& current_unified_desktop_matrix() const { return current_unified_desktop_matrix_; } @@ -680,9 +676,6 @@ base::CancelableCallback<void()> on_display_zoom_modify_timeout_; #endif - // Whether mirroring across multiple displays is enabled. - bool is_multi_mirroring_enabled_; - base::WeakPtrFactory<DisplayManager> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DisplayManager);
diff --git a/ui/file_manager/file_manager/background/js/file_operation_util.js b/ui/file_manager/file_manager/background/js/file_operation_util.js index 2ee3c90..c4f7b6db 100644 --- a/ui/file_manager/file_manager/background/js/file_operation_util.js +++ b/ui/file_manager/file_manager/background/js/file_operation_util.js
@@ -1097,12 +1097,13 @@ fileOperationUtil.MoveTask.processEntry_ = function( sourceEntry, destinationEntry, entryChangedCallback, successCallback, errorCallback) { + const destination = + /** @type{!DirectoryEntry} */ ( + assert(util.unwrapEntry(destinationEntry))); fileOperationUtil.deduplicatePath( - destinationEntry, - sourceEntry.name, - function(destinationName) { + destination, sourceEntry.name, function(destinationName) { sourceEntry.moveTo( - destinationEntry, destinationName, + destination, destinationName, function(movedEntry) { entryChangedCallback(util.EntryChangedKind.CREATED, movedEntry); entryChangedCallback(util.EntryChangedKind.DELETED, sourceEntry); @@ -1112,8 +1113,7 @@ errorCallback(new fileOperationUtil.Error( util.FileOperationErrorType.FILESYSTEM_ERROR, error)); }); - }, - errorCallback); + }, errorCallback); }; /**
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js index 80642ca16..c76a84b 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -763,11 +763,14 @@ item.dirEntry_ = modelItem.entry; item.parentTree_ = tree; + const icon = queryRequiredElement('.icon', item); if (window.IN_TEST && item.entry && item.entry.volumeInfo) { item.setAttribute( 'volume-type-for-testing', item.entry.volumeInfo.volumeType); + // TODO(crbug.com/880130) Remove volume-type-icon from here once + // MyFilesVolume flag is removed. + icon.setAttribute('volume-type-icon', rootType); } - const icon = queryRequiredElement('.icon', item); icon.classList.add('item-icon'); icon.setAttribute('root-type-icon', rootType); return item;
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.js index d026247..e7c503cd 100644 --- a/ui/file_manager/integration_tests/file_manager/quick_view.js +++ b/ui/file_manager/integration_tests/file_manager/quick_view.js
@@ -659,6 +659,140 @@ }; /** + * Tests opening Quick View with multiple files and using the up/down arrow + * keys to select and view their content. + */ +testcase.openQuickViewKeyboardUpDownChangesView = async function() { + const caller = getCaller(); + + /** + * The text <webview> resides in the #quick-view shadow DOM, as a child of + * the #dialog element. + */ + const webView = ['#quick-view', '#dialog[open] webview.text-content']; + + // Open Files app on Downloads containing two text files. + const files = [ENTRIES.hello, ENTRIES.tallText]; + const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); + + // Open the last file in Quick View. + await openQuickView(appId, ENTRIES.tallText.nameText); + + // Wait for the Quick View <webview> to load and display its content. + function checkWebViewTextLoaded(elements) { + let haveElements = Array.isArray(elements) && elements.length === 1; + if (haveElements) { + haveElements = elements[0].styles.display.includes('block'); + } + if (!haveElements || !elements[0].attributes.src) { + return pending(caller, 'Waiting for <webview> to load.'); + } + return; + } + await repeatUntil(async () => { + return checkWebViewTextLoaded(await remoteCall.callRemoteTestUtil( + 'deepQueryAllElements', appId, [webView, ['display']])); + }); + + // Press the down arrow key to select the next file. + const downArrow = ['#quick-view', 'ArrowDown', false, false, false]; + chrome.test.assertTrue( + await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, downArrow)); + + // Wait until the <webview> displays that file's content. + await repeatUntil(async () => { + const getTextContent = 'window.document.body.textContent'; + const text = await remoteCall.callRemoteTestUtil( + 'deepExecuteScriptInWebView', appId, [webView, getTextContent]); + if (!text || !text[0].includes('This is a sample file')) { + return pending(caller, 'Waiting for <webview> content.'); + } + }); + + // Press the up arrow key to select the previous file. + const upArrow = ['#quick-view', 'ArrowUp', false, false, false]; + chrome.test.assertTrue( + await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, upArrow)); + + // Wait until the <webview> displays that file's content. + await repeatUntil(async () => { + const getTextContent = 'window.document.body.textContent'; + const text = await remoteCall.callRemoteTestUtil( + 'deepExecuteScriptInWebView', appId, [webView, getTextContent]); + if (!text || !text[0].includes('42 tall text')) { + return pending(caller, 'Waiting for <webview> content.'); + } + }); +}; + +/** + * Tests opening Quick View with multiple files and using the left/right arrow + * keys to select and view their content. + */ +testcase.openQuickViewKeyboardLeftRightChangesView = async function() { + const caller = getCaller(); + + /** + * The text <webview> resides in the #quick-view shadow DOM, as a child of + * the #dialog element. + */ + const webView = ['#quick-view', '#dialog[open] webview.text-content']; + + // Open Files app on Downloads containing two text files. + const files = [ENTRIES.hello, ENTRIES.tallText]; + const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); + + // Open the last file in Quick View. + await openQuickView(appId, ENTRIES.tallText.nameText); + + // Wait for the Quick View <webview> to load and display its content. + function checkWebViewTextLoaded(elements) { + let haveElements = Array.isArray(elements) && elements.length === 1; + if (haveElements) { + haveElements = elements[0].styles.display.includes('block'); + } + if (!haveElements || !elements[0].attributes.src) { + return pending(caller, 'Waiting for <webview> to load.'); + } + return; + } + await repeatUntil(async () => { + return checkWebViewTextLoaded(await remoteCall.callRemoteTestUtil( + 'deepQueryAllElements', appId, [webView, ['display']])); + }); + + // Press the right arrow key to select the next file item. + const rightArrow = ['#quick-view', 'ArrowRight', false, false, false]; + chrome.test.assertTrue( + await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, rightArrow)); + + // Wait until the <webview> displays that file's content. + await repeatUntil(async () => { + const getTextContent = 'window.document.body.textContent'; + const text = await remoteCall.callRemoteTestUtil( + 'deepExecuteScriptInWebView', appId, [webView, getTextContent]); + if (!text || !text[0].includes('This is a sample file')) { + return pending(caller, 'Waiting for <webview> content.'); + } + }); + + // Press the left arrow key to select the previous file item. + const leftArrow = ['#quick-view', 'ArrowLeft', false, false, false]; + chrome.test.assertTrue( + await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, leftArrow)); + + // Wait until the <webview> displays that file's content. + await repeatUntil(async () => { + const getTextContent = 'window.document.body.textContent'; + const text = await remoteCall.callRemoteTestUtil( + 'deepExecuteScriptInWebView', appId, [webView, getTextContent]); + if (!text || !text[0].includes('42 tall text')) { + return pending(caller, 'Waiting for <webview> content.'); + } + }); +}; + +/** * Tests close/open metadata info via Enter key. */ testcase.pressEnterOnInfoBoxToOpenClose = async function() {
diff --git a/ui/file_manager/integration_tests/file_manager/transfer.js b/ui/file_manager/integration_tests/file_manager/transfer.js index 9ee771d2..979d2a7 100644 --- a/ui/file_manager/integration_tests/file_manager/transfer.js +++ b/ui/file_manager/integration_tests/file_manager/transfer.js
@@ -171,7 +171,7 @@ 'selectFile', appId, [transferInfo.fileToTransfer.nameText])); // Copy the file. - let transferCommand = transferInfo.isMove ? 'move' : 'copy'; + let transferCommand = transferInfo.isMove ? 'cut' : 'copy'; chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( 'execCommand', appId, [transferCommand])); @@ -181,8 +181,8 @@ appId, [transferInfo.destination.volumeName])); // Wait for the expected files to appear in the file list. - await remoteCall.waitForFiles(appId, dstContents); - + await remoteCall.waitForFiles( + appId, dstContents, {ignoreFileSize: true, ignoreLastModifiedTime: true}); // Paste the file. chrome.test.assertTrue( await remoteCall.callRemoteTestUtil('execCommand', appId, ['paste'])); @@ -204,7 +204,8 @@ transferInfo.source.volumeName == 'drive_shared_with_me' || transferInfo.source.volumeName == 'drive_offline' || transferInfo.destination.volumeName == 'drive_shared_with_me' || - transferInfo.destination.volumeName == 'drive_offline'; + transferInfo.destination.volumeName == 'drive_offline' || + transferInfo.destination.volumeName == 'my_files'; // If we expected the transfer to succeed, add the pasted file to the list // of expected rows. @@ -262,8 +263,37 @@ isTeamDrive: true, initialEntries: TEAM_DRIVE_ENTRY_SET }), -}); + my_files: new TransferLocationInfo({ + volumeName: 'my_files', + initialEntries: [ + new TestEntryInfo({ + type: EntryType.DIRECTORY, + targetPath: 'Play files', + nameText: 'Play files', + lastModifiedTime: 'Jan 1, 1980, 11:59 PM', + sizeText: '--', + typeText: 'Folder' + }), + new TestEntryInfo({ + type: EntryType.DIRECTORY, + targetPath: 'Downloads', + nameText: 'Downloads', + lastModifiedTime: 'Jan 1, 1980, 11:59 PM', + sizeText: '--', + typeText: 'Folder' + }), + new TestEntryInfo({ + type: EntryType.DIRECTORY, + targetPath: 'Linux files', + nameText: 'Linux files', + lastModifiedTime: '...', + sizeText: '--', + typeText: 'Folder' + }), + ] + }), +}); /** * Tests copying from Drive to Downloads. @@ -277,6 +307,30 @@ }; /** + * Tests moving files from MyFiles/Downloads to MyFiles crbug.com/925175. + */ +testcase.transferFromDownloadsToMyFilesMove = function() { + return transferBetweenVolumes(new TransferInfo({ + fileToTransfer: ENTRIES.hello, + source: TRANSFER_LOCATIONS.downloads, + destination: TRANSFER_LOCATIONS.my_files, + isMove: true, + })); +}; + +/** + * Tests copying files from MyFiles/Downloads to MyFiles crbug.com/925175. + */ +testcase.transferFromDownloadsToMyFiles = function() { + return transferBetweenVolumes(new TransferInfo({ + fileToTransfer: ENTRIES.hello, + source: TRANSFER_LOCATIONS.downloads, + destination: TRANSFER_LOCATIONS.my_files, + isMove: false, + })); +}; + +/** * Tests copying from Downloads to Drive. */ testcase.transferFromDownloadsToDrive = function() {
diff --git a/ui/file_manager/integration_tests/remote_call.js b/ui/file_manager/integration_tests/remote_call.js index 902d93ce..0e6a89e 100644 --- a/ui/file_manager/integration_tests/remote_call.js +++ b/ui/file_manager/integration_tests/remote_call.js
@@ -398,13 +398,18 @@ expected.sort(); } for (var i = 0; i < Math.min(files.length, expected.length); i++) { + // Change the value received from the UI to match when comparing. if (options.ignoreFileSize) { - files[i][1] = ''; - expected[i][1] = ''; + files[i][1] = expected[i][1]; } if (options.ignoreLastModifiedTime) { - files[i][3] = ''; - expected[i][3] = ''; + if (expected[i].length < 4) { + // expected sometimes doesn't include the modified time at all, so + // just remove from the data from UI. + files[i].splice(3, 1); + } else { + files[i][3] = expected[i][3]; + } } } if (!chrome.test.checkDeepEq(expected, files)) {
diff --git a/ui/file_manager/video_player/js/video_player_native_controls.js b/ui/file_manager/video_player/js/video_player_native_controls.js index bb92bda..70eb6443b 100644 --- a/ui/file_manager/video_player/js/video_player_native_controls.js +++ b/ui/file_manager/video_player/js/video_player_native_controls.js
@@ -39,17 +39,123 @@ this.videoElement_.addEventListener('pause', this.onPause_.bind(this)); + this.preparePlayList_(); + this.addKeyControls_(); +}; + +/** + * 10 seconds should be skipped when J/L key is pressed. + */ +NativeControlsVideoPlayer.PROGRESS_MAX_SECONDS_TO_SKIP = 10; + +/** + * 20% of duration should be skipped when the video is too short to skip 10 + * seconds. + */ +NativeControlsVideoPlayer.PROGRESS_MAX_RATIO_TO_SKIP = 0.2; + +/** + * Attach arrow box for previous/next track to document and set + * 'multiple' attribute if user opens more than 1 videos. + */ +NativeControlsVideoPlayer.prototype.preparePlayList_ = function() { let videoPlayerElement = getRequiredElement('video-player'); - if (videos.length > 1) { + if (this.videos_.length > 1) { videoPlayerElement.setAttribute('multiple', true); } else { videoPlayerElement.removeAttribute('multiple'); } let arrowRight = queryRequiredElement('.arrow-box .arrow.right'); - arrowRight.addEventListener('click', this.advance_.wrap(this, 1)); + arrowRight.addEventListener( + 'click', this.advance_.wrap(this, true /* next track */)); let arrowLeft = queryRequiredElement('.arrow-box .arrow.left'); - arrowLeft.addEventListener('click', this.advance_.wrap(this, 0)); + arrowLeft.addEventListener( + 'click', this.advance_.wrap(this, false /* previous track */)); +}; + +/** + * Add keyboard controls to document. + */ +NativeControlsVideoPlayer.prototype.addKeyControls_ = function() { + document.addEventListener('keydown', function(e) { + switch (util.getKeyModifiers(e) + e.key) { + // Handle debug shortcut keys. + case 'Ctrl-Shift-I': // Ctrl+Shift+I + chrome.fileManagerPrivate.openInspector('normal'); + break; + case 'Ctrl-Shift-J': // Ctrl+Shift+J + chrome.fileManagerPrivate.openInspector('console'); + break; + case 'Ctrl-Shift-C': // Ctrl+Shift+C + chrome.fileManagerPrivate.openInspector('element'); + break; + case 'Ctrl-Shift-B': // Ctrl+Shift+B + chrome.fileManagerPrivate.openInspector('background'); + break; + + case 'k': + case 'MediaPlayPause': + this.togglePlayState_(); + break; + case 'Escape': + util.toggleFullScreen( + chrome.app.window.current(), + false); // Leave the full screen mode. + break; + case 'MediaTrackNext': + this.advance_(true /* next track */); + break; + case 'MediaTrackPrevious': + this.advance_(false /* previous track */); + break; + case 'l': + this.skip_(true /* forward */); + break; + case 'j': + this.skip_(false /* backward */); + break; + case 'BrowserBack': + chrome.app.window.current().close(); + break; + case 'MediaStop': + // TODO: Define "Stop" behavior. + break; + } + }.wrap(this)); +}; + +/** + * Skips forward/backward. + * @param {boolean} forward Whether to skip forward or backward. + * @private + */ +NativeControlsVideoPlayer.prototype.skip_ = function(forward) { + let secondsToSkip = Math.min( + NativeControlsVideoPlayer.PROGRESS_MAX_SECONDS_TO_SKIP, + this.videoElement_.duration * + NativeControlsVideoPlayer.PROGRESS_MAX_RATIO_TO_SKIP); + + if (!forward) { + secondsToSkip *= -1; + } + + this.videoElement_.currentTime = Math.max( + Math.min( + this.videoElement_.currentTime + secondsToSkip, + this.videoElement_.duration), + 0); +}; + +/** + * Toggle play/pause. + */ +NativeControlsVideoPlayer.prototype.togglePlayState_ = function() { + if (this.videoElement_.paused) { + this.videoElement_.play(); + } else { + this.videoElement_.pause(); + } }; /** @@ -106,6 +212,7 @@ Math.max(0, Math.round(oldTop - (newHeight - oldHeight) / 2)); appWindow.show(); + this.videoElement_.focus(); this.videoElement_.play(); };
diff --git a/ui/gl/android/android_surface_control_compat.cc b/ui/gl/android/android_surface_control_compat.cc index 26c981c..6bfaba1 100644 --- a/ui/gl/android/android_surface_control_compat.cc +++ b/ui/gl/android/android_surface_control_compat.cc
@@ -7,16 +7,21 @@ #include <dlfcn.h> #include "base/android/build_info.h" +#include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/no_destructor.h" extern "C" { +typedef struct ASurfaceTransactionStats ASurfaceTransactionStats; +typedef void (*ASurfaceTransaction_OnComplete)(void* context, + ASurfaceTransactionStats* stats); + // ASurface using pASurfaceControl_createFromWindow = ASurfaceControl* (*)(ANativeWindow* parent, const char* name); using pASurfaceControl_create = ASurfaceControl* (*)(ASurfaceControl* parent, const char* name); -using pASurfaceControl_destroy = void (*)(ASurfaceControl*); +using pASurfaceControl_release = void (*)(ASurfaceControl*); // ASurfaceTransaction enums enum { @@ -61,6 +66,18 @@ ASurfaceControl* surface, const ARect rects[], uint32_t count); + +// ASurfaceTransactionStats +using pASurfaceTransactionStats_getPresentFenceFd = + int (*)(ASurfaceTransactionStats* stats); +using pASurfaceTransactionStats_getASurfaceControls = + void (*)(ASurfaceTransactionStats* stats, + ASurfaceControl*** surface_controls, + size_t* size); +using pASurfaceTransactionStats_releaseASurfaceControls = + void (*)(ASurfaceControl** surface_controls); +using pASurfaceTransactionStats_getPreviousReleaseFenceFd = + int (*)(ASurfaceTransactionStats* stats, ASurfaceControl* surface_control); } namespace gl { @@ -92,7 +109,7 @@ LOAD_FUNCTION(main_dl_handle, ASurfaceControl_createFromWindow); LOAD_FUNCTION(main_dl_handle, ASurfaceControl_create); - LOAD_FUNCTION(main_dl_handle, ASurfaceControl_destroy); + LOAD_FUNCTION(main_dl_handle, ASurfaceControl_release); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_create); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_delete); @@ -104,6 +121,13 @@ LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setGeometry); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setBufferTransparency); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setDamageRegion); + + LOAD_FUNCTION(main_dl_handle, ASurfaceTransactionStats_getPresentFenceFd); + LOAD_FUNCTION(main_dl_handle, ASurfaceTransactionStats_getASurfaceControls); + LOAD_FUNCTION(main_dl_handle, + ASurfaceTransactionStats_releaseASurfaceControls); + LOAD_FUNCTION(main_dl_handle, + ASurfaceTransactionStats_getPreviousReleaseFenceFd); } ~SurfaceControlMethods() = default; @@ -112,7 +136,7 @@ // Surface methods. pASurfaceControl_createFromWindow ASurfaceControl_createFromWindowFn; pASurfaceControl_create ASurfaceControl_createFn; - pASurfaceControl_destroy ASurfaceControl_destroyFn; + pASurfaceControl_release ASurfaceControl_releaseFn; // Transaction methods. pASurfaceTransaction_create ASurfaceTransaction_createFn; @@ -126,6 +150,16 @@ pASurfaceTransaction_setBufferTransparency ASurfaceTransaction_setBufferTransparencyFn; pASurfaceTransaction_setDamageRegion ASurfaceTransaction_setDamageRegionFn; + + // TransactionStats methods. + pASurfaceTransactionStats_getPresentFenceFd + ASurfaceTransactionStats_getPresentFenceFdFn; + pASurfaceTransactionStats_getASurfaceControls + ASurfaceTransactionStats_getASurfaceControlsFn; + pASurfaceTransactionStats_releaseASurfaceControls + ASurfaceTransactionStats_releaseASurfaceControlsFn; + pASurfaceTransactionStats_getPreviousReleaseFenceFd + ASurfaceTransactionStats_getPreviousReleaseFenceFdFn; }; ARect RectToARect(const gfx::Rect& rect) { @@ -153,6 +187,56 @@ NOTREACHED(); return ANATIVEWINDOW_TRANSFORM_IDENTITY; } + +SurfaceControl::TransactionStats ToTransactionStats( + ASurfaceTransactionStats* stats) { + SurfaceControl::TransactionStats transaction_stats; + transaction_stats.present_fence = base::ScopedFD( + SurfaceControlMethods::Get().ASurfaceTransactionStats_getPresentFenceFdFn( + stats)); + + ASurfaceControl** surface_controls = nullptr; + size_t size = 0u; + SurfaceControlMethods::Get().ASurfaceTransactionStats_getASurfaceControlsFn( + stats, &surface_controls, &size); + transaction_stats.surface_stats.resize(size); + for (size_t i = 0u; i < size; ++i) { + transaction_stats.surface_stats[i].surface = surface_controls[i]; + int fence_fd = SurfaceControlMethods::Get() + .ASurfaceTransactionStats_getPreviousReleaseFenceFdFn( + stats, surface_controls[i]); + if (fence_fd != -1) { + transaction_stats.surface_stats[i].fence = base::ScopedFD(fence_fd); + } + } + SurfaceControlMethods::Get() + .ASurfaceTransactionStats_releaseASurfaceControlsFn(surface_controls); + + return transaction_stats; +} + +struct TransactionAckCtx { + scoped_refptr<base::SingleThreadTaskRunner> task_runner; + SurfaceControl::Transaction::OnCompleteCb callback; +}; + +// Note that the framework API states that this callback can be dispatched on +// any thread (in practice it should be the binder thread). +void OnTransactionCompletedOnAnyThread(void* context, + ASurfaceTransactionStats* stats) { + auto* ack_ctx = static_cast<TransactionAckCtx*>(context); + auto transaction_stats = ToTransactionStats(stats); + + if (ack_ctx->task_runner) { + ack_ctx->task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(ack_ctx->callback), + std::move(transaction_stats))); + } else { + std::move(ack_ctx->callback).Run(std::move(transaction_stats)); + } + + delete ack_ctx; +} }; // static @@ -185,22 +269,23 @@ SurfaceControl::Surface::~Surface() { if (surface_) - SurfaceControlMethods::Get().ASurfaceControl_destroyFn(surface_); + SurfaceControlMethods::Get().ASurfaceControl_releaseFn(surface_); } -SurfaceControl::Surface::Surface(Surface&& other) { - surface_ = other.surface_; - other.surface_ = nullptr; -} +SurfaceControl::SurfaceStats::SurfaceStats() = default; +SurfaceControl::SurfaceStats::~SurfaceStats() = default; -SurfaceControl::Surface& SurfaceControl::Surface::operator=(Surface&& other) { - if (surface_) - SurfaceControlMethods::Get().ASurfaceControl_destroyFn(surface_); +SurfaceControl::SurfaceStats::SurfaceStats(SurfaceStats&& other) = default; +SurfaceControl::SurfaceStats& SurfaceControl::SurfaceStats::operator=( + SurfaceStats&& other) = default; - surface_ = other.surface_; - other.surface_ = nullptr; - return *this; -} +SurfaceControl::TransactionStats::TransactionStats() = default; +SurfaceControl::TransactionStats::~TransactionStats() = default; + +SurfaceControl::TransactionStats::TransactionStats(TransactionStats&& other) = + default; +SurfaceControl::TransactionStats& SurfaceControl::TransactionStats::operator=( + TransactionStats&& other) = default; SurfaceControl::Transaction::Transaction() { transaction_ = SurfaceControlMethods::Get().ASurfaceTransaction_createFn(); @@ -254,11 +339,15 @@ transaction_, surface.surface(), &a_rect, 1u); } -void SurfaceControl::Transaction::SetOnCompleteFunc( - ASurfaceTransaction_OnComplete func, - void* ctx) { - SurfaceControlMethods::Get().ASurfaceTransaction_setOnCompleteFn(transaction_, - ctx, func); +void SurfaceControl::Transaction::SetOnCompleteCb( + OnCompleteCb cb, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + TransactionAckCtx* ack_ctx = new TransactionAckCtx; + ack_ctx->callback = std::move(cb); + ack_ctx->task_runner = std::move(task_runner); + + SurfaceControlMethods::Get().ASurfaceTransaction_setOnCompleteFn( + transaction_, ack_ctx, &OnTransactionCompletedOnAnyThread); } void SurfaceControl::Transaction::Apply() {
diff --git a/ui/gl/android/android_surface_control_compat.h b/ui/gl/android/android_surface_control_compat.h index 111f7d5..bec240d 100644 --- a/ui/gl/android/android_surface_control_compat.h +++ b/ui/gl/android/android_surface_control_compat.h
@@ -11,6 +11,8 @@ #include <android/native_window.h> #include "base/files/scoped_file.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/overlay_transform.h" #include "ui/gl/gl_export.h" @@ -18,8 +20,6 @@ extern "C" { typedef struct ASurfaceControl ASurfaceControl; typedef struct ASurfaceTransaction ASurfaceTransaction; -typedef void (*ASurfaceTransaction_OnComplete)(void* context, - int32_t present_fence); } namespace gl { @@ -28,20 +28,52 @@ public: static bool IsSupported(); - class GL_EXPORT Surface { + class GL_EXPORT Surface : public base::RefCounted<Surface> { public: Surface(); Surface(const Surface& parent, const char* name); Surface(ANativeWindow* parent, const char* name); - ~Surface(); - - Surface(Surface&& other); - Surface& operator=(Surface&& other); ASurfaceControl* surface() const { return surface_; } private: + friend class base::RefCounted<Surface>; + ~Surface(); + ASurfaceControl* surface_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(Surface); + }; + + struct GL_EXPORT SurfaceStats { + SurfaceStats(); + ~SurfaceStats(); + + SurfaceStats(SurfaceStats&& other); + SurfaceStats& operator=(SurfaceStats&& other); + + ASurfaceControl* surface = nullptr; + + // The fence which is signaled when the reads for the previous buffer for + // the given |surface| are finished. + base::ScopedFD fence; + }; + + struct GL_EXPORT TransactionStats { + public: + TransactionStats(); + ~TransactionStats(); + + TransactionStats(TransactionStats&& other); + TransactionStats& operator=(TransactionStats&& other); + + // The fence which is signaled when this transaction is presented by the + // display. + base::ScopedFD present_fence; + std::vector<SurfaceStats> surface_stats; + + private: + DISALLOW_COPY_AND_ASSIGN(TransactionStats); }; class GL_EXPORT Transaction { @@ -60,7 +92,16 @@ gfx::OverlayTransform transform); void SetOpaque(const Surface& surface, bool opaque); void SetDamageRect(const Surface& surface, const gfx::Rect& rect); - void SetOnCompleteFunc(ASurfaceTransaction_OnComplete func, void* ctx); + + // Sets the callback which will be dispatched when the transaction is acked + // by the framework. + // |task_runner| provides an optional task runner on which the callback + // should be run. + using OnCompleteCb = base::OnceCallback<void(TransactionStats stats)>; + void SetOnCompleteCb( + OnCompleteCb cb, + scoped_refptr<base::SingleThreadTaskRunner> task_runner); + void Apply(); private:
diff --git a/ui/gl/gl_image_ahardwarebuffer.cc b/ui/gl/gl_image_ahardwarebuffer.cc index 1f2b248..1d037ef96 100644 --- a/ui/gl/gl_image_ahardwarebuffer.cc +++ b/ui/gl/gl_image_ahardwarebuffer.cc
@@ -3,14 +3,37 @@ // found in the LICENSE file. #include "ui/gl/gl_image_ahardwarebuffer.h" + #include "base/android/android_hardware_buffer_compat.h" #include "base/android/scoped_hardware_buffer_fence_sync.h" - #include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_fence_android_native_fence_sync.h" namespace gl { namespace { +class ScopedHardwareBufferFenceSyncImpl + : public base::android::ScopedHardwareBufferFenceSync { + public: + ScopedHardwareBufferFenceSyncImpl( + base::android::ScopedHardwareBufferHandle handle, + base::ScopedFD fence_fd) + : ScopedHardwareBufferFenceSync(std::move(handle), std::move(fence_fd)) {} + ~ScopedHardwareBufferFenceSyncImpl() override = default; + + void SetReadFence(base::ScopedFD fence_fd) override { + // Insert a service wait for this fence to ensure any resource reuse is + // after it is signaled. + gfx::GpuFenceHandle handle; + handle.type = gfx::GpuFenceHandleType::kAndroidNativeFenceSync; + handle.native_fd = + base::FileDescriptor(fence_fd.release(), /*auto_close=*/true); + gfx::GpuFence gpu_fence(handle); + auto gl_fence = GLFence::CreateFromGpuFence(gpu_fence); + gl_fence->ServerWait(); + } +}; + uint32_t GetBufferFormat(const AHardwareBuffer* buffer) { AHardwareBuffer_Desc desc = {}; base::AndroidHardwareBufferCompat::GetInstance().Describe(buffer, &desc); @@ -86,7 +109,7 @@ std::unique_ptr<base::android::ScopedHardwareBufferFenceSync> GLImageAHardwareBuffer::GetAHardwareBuffer() { - return std::make_unique<base::android::ScopedHardwareBufferFenceSync>( + return std::make_unique<ScopedHardwareBufferFenceSyncImpl>( base::android::ScopedHardwareBufferHandle::Create(handle_.get()), base::ScopedFD()); }
diff --git a/ui/gl/gl_image_egl.cc b/ui/gl/gl_image_egl.cc index e229679..3386eae 100644 --- a/ui/gl/gl_image_egl.cc +++ b/ui/gl/gl_image_egl.cc
@@ -50,8 +50,7 @@ DCHECK_EQ(BIND, ShouldBindOrCopy()); glEGLImageTargetTexture2DOES(target, egl_image_); - DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); - return true; + return glGetError() == static_cast<GLenum>(GL_NO_ERROR); } } // namespace gl
diff --git a/ui/gl/gl_surface_egl_surface_control.cc b/ui/gl/gl_surface_egl_surface_control.cc index 4972591..e617b2a 100644 --- a/ui/gl/gl_surface_egl_surface_control.cc +++ b/ui/gl/gl_surface_egl_surface_control.cc
@@ -9,7 +9,7 @@ #include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" #include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gl/gl_fence_android_native_fence_sync.h" +#include "ui/gl/gl_context.h" #include "ui/gl/gl_image_ahardwarebuffer.h" namespace gl { @@ -24,27 +24,12 @@ return gfx::Size(desc.width, desc.height); } -struct TransactionAckCtx { - scoped_refptr<base::SingleThreadTaskRunner> task_runner; - base::OnceCallback<void(int32_t)> callback; -}; - -// Note that the framework API states that this callback can be dispatched on -// any thread (in practice it should be the binder thread), so we need to post -// a task back to the GPU thread. -void OnTransactionCompletedOnAnyThread(void* ctx, int32_t present_fence) { - auto* ack_ctx = static_cast<TransactionAckCtx*>(ctx); - ack_ctx->task_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(ack_ctx->callback), present_fence)); - delete ack_ctx; -} - } // namespace GLSurfaceEGLSurfaceControl::GLSurfaceEGLSurfaceControl( ANativeWindow* window, scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : root_surface_(window, kRootSurfaceName), + : root_surface_(new SurfaceControl::Surface(window, kRootSurfaceName)), gpu_task_runner_(std::move(task_runner)), weak_factory_(this) {} @@ -63,7 +48,7 @@ void GLSurfaceEGLSurfaceControl::Destroy() { pending_transaction_.reset(); surface_list_.clear(); - root_surface_ = SurfaceControl::Surface(); + root_surface_.reset(); } bool GLSurfaceEGLSurfaceControl::Resize(const gfx::Size& size, @@ -116,18 +101,11 @@ current_frame_resources_.swap(pending_frame_resources_); pending_frame_resources_.clear(); - // Set up the callback to be notified when the frame is presented by the - // framework. Note that it is assumed that all GPU/display work for this frame - // is finished when the callback is dispatched, and all resources from the - // previous frame can be reused. - TransactionAckCtx* ack_ctx = new TransactionAckCtx; - ack_ctx->task_runner = gpu_task_runner_; - ack_ctx->callback = + SurfaceControl::Transaction::OnCompleteCb callback = base::BindOnce(&GLSurfaceEGLSurfaceControl::OnTransactionAckOnGpuThread, weak_factory_.GetWeakPtr(), completion_callback, present_callback, std::move(resources_to_release)); - pending_transaction_->SetOnCompleteFunc(&OnTransactionCompletedOnAnyThread, - ack_ctx); + pending_transaction_->SetOnCompleteCb(std::move(callback), gpu_task_runner_); pending_transaction_->Apply(); pending_transaction_.reset(); @@ -142,6 +120,7 @@ } bool GLSurfaceEGLSurfaceControl::OnMakeCurrent(GLContext* context) { + context_ = context; return true; } @@ -159,14 +138,14 @@ bool uninitialized = false; if (pending_surfaces_count_ == surface_list_.size()) { uninitialized = true; - surface_list_.emplace_back(root_surface_); + surface_list_.emplace_back(*root_surface_); } pending_surfaces_count_++; auto& surface_state = surface_list_.at(pending_surfaces_count_ - 1); if (uninitialized || surface_state.z_order != z_order) { surface_state.z_order = z_order; - pending_transaction_->SetZOrder(surface_state.surface, z_order); + pending_transaction_->SetZOrder(*surface_state.surface, z_order); } AHardwareBuffer* hardware_buffer = nullptr; @@ -175,7 +154,13 @@ if (scoped_hardware_buffer) { hardware_buffer = scoped_hardware_buffer->buffer(); fence_fd = scoped_hardware_buffer->TakeFence(); - pending_frame_resources_.push_back(std::move(scoped_hardware_buffer)); + + auto* a_surface = surface_state.surface->surface(); + DCHECK_EQ(pending_frame_resources_.count(a_surface), 0u); + + auto& resource_ref = pending_frame_resources_[a_surface]; + resource_ref.surface = surface_state.surface; + resource_ref.scoped_buffer = std::move(scoped_hardware_buffer); } if (uninitialized || surface_state.hardware_buffer != hardware_buffer) { @@ -188,7 +173,7 @@ fence_fd = base::ScopedFD(fence_handle.native_fd.fd); } - pending_transaction_->SetBuffer(surface_state.surface, + pending_transaction_->SetBuffer(*surface_state.surface, surface_state.hardware_buffer, std::move(fence_fd)); } @@ -209,7 +194,7 @@ surface_state.src = src; surface_state.dst = dst; surface_state.transform = transform; - pending_transaction_->SetGeometry(surface_state.surface, src, dst, + pending_transaction_->SetGeometry(*surface_state.surface, src, dst, transform); } } @@ -217,7 +202,7 @@ bool opaque = !enable_blend; if (uninitialized || surface_state.opaque != opaque) { surface_state.opaque = opaque; - pending_transaction_->SetOpaque(surface_state.surface, opaque); + pending_transaction_->SetOpaque(*surface_state.surface, opaque); } return true; @@ -256,34 +241,32 @@ SwapCompletionCallback completion_callback, PresentationCallback presentation_callback, ResourceRefs released_resources, - int32_t present_fence) { + SurfaceControl::TransactionStats transaction_stats) { DCHECK(gpu_task_runner_->BelongsToCurrentThread()); - - // Insert a service wait for this fence to ensure any resource reuse is after - // it is signaled. - gfx::GpuFenceHandle handle; - handle.type = gfx::GpuFenceHandleType::kAndroidNativeFenceSync; - handle.native_fd = base::FileDescriptor(present_fence, /*auto_close=*/true); - gfx::GpuFence gpu_fence(handle); - // TODO(khushalsagar): But what about vulkan? - auto gl_fence = GLFence::CreateFromGpuFence(gpu_fence); - gl_fence->ServerWait(); + context_->MakeCurrent(this); // The presentation feedback callback must run after swap completion. completion_callback.Run(gfx::SwapResult::SWAP_ACK, nullptr); - // TODO(khushalsagar): Maintain a queue of fences so we poll to see if they - // are signaled every frame, and get a signal timestamp to feed into this + // TODO(khushalsagar): Maintain a queue of present fences so we poll to see if + // they are signaled every frame, and get a signal timestamp to feed into this // feedback. gfx::PresentationFeedback feedback(base::TimeTicks::Now(), base::TimeDelta(), 0 /* flags */); presentation_callback.Run(feedback); + + for (auto& surface_stat : transaction_stats.surface_stats) { + auto it = released_resources.find(surface_stat.surface); + DCHECK(it != released_resources.end()); + if (surface_stat.fence.is_valid()) + it->second.scoped_buffer->SetReadFence(std::move(surface_stat.fence)); + } released_resources.clear(); } GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState( const SurfaceControl::Surface& parent) - : surface(parent, kChildSurfaceName) {} + : surface(new SurfaceControl::Surface(parent, kChildSurfaceName)) {} GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState() = default; GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState(SurfaceState&& other) = @@ -294,4 +277,12 @@ GLSurfaceEGLSurfaceControl::SurfaceState::~SurfaceState() = default; +GLSurfaceEGLSurfaceControl::ResourceRef::ResourceRef() = default; +GLSurfaceEGLSurfaceControl::ResourceRef::~ResourceRef() = default; +GLSurfaceEGLSurfaceControl::ResourceRef::ResourceRef(ResourceRef&& other) = + default; +GLSurfaceEGLSurfaceControl::ResourceRef& +GLSurfaceEGLSurfaceControl::ResourceRef::operator=(ResourceRef&& other) = + default; + } // namespace gl
diff --git a/ui/gl/gl_surface_egl_surface_control.h b/ui/gl/gl_surface_egl_surface_control.h index 5542d504..ca7b9f08 100644 --- a/ui/gl/gl_surface_egl_surface_control.h +++ b/ui/gl/gl_surface_egl_surface_control.h
@@ -9,6 +9,7 @@ #include <memory> #include "base/android/scoped_hardware_buffer_handle.h" +#include "base/containers/flat_map.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "ui/gl/android/android_surface_control_compat.h" @@ -25,7 +26,7 @@ namespace gl { -class GL_EXPORT GLSurfaceEGLSurfaceControl : public gl::GLSurfaceEGL { +class GL_EXPORT GLSurfaceEGLSurfaceControl : public GLSurfaceEGL { public: explicit GLSurfaceEGLSurfaceControl( ANativeWindow* window, @@ -33,7 +34,7 @@ // GLSurface implementation. int GetBufferCount() const override; - bool Initialize(gl::GLSurfaceFormat format) override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; bool Resize(const gfx::Size& size, float scale_factor, @@ -50,10 +51,10 @@ const SwapCompletionCallback& completion_callback, const PresentationCallback& presentation_callback) override; gfx::Size GetSize() override; - bool OnMakeCurrent(gl::GLContext* context) override; + bool OnMakeCurrent(GLContext* context) override; bool ScheduleOverlayPlane(int z_order, gfx::OverlayTransform transform, - gl::GLImage* image, + GLImage* image, const gfx::Rect& bounds_rect, const gfx::RectF& crop_rect, bool enable_blend, @@ -85,11 +86,20 @@ gfx::OverlayTransform transform = gfx::OVERLAY_TRANSFORM_NONE; bool opaque = true; - gl::SurfaceControl::Surface surface; + scoped_refptr<SurfaceControl::Surface> surface; }; - using ResourceRefs = std::vector< - std::unique_ptr<base::android::ScopedHardwareBufferFenceSync>>; + struct ResourceRef { + ResourceRef(); + ~ResourceRef(); + + ResourceRef(ResourceRef&& other); + ResourceRef& operator=(ResourceRef&& other); + + scoped_refptr<SurfaceControl::Surface> surface; + std::unique_ptr<base::android::ScopedHardwareBufferFenceSync> scoped_buffer; + }; + using ResourceRefs = base::flat_map<ASurfaceControl*, ResourceRef>; void CommitPendingTransaction( const SwapCompletionCallback& completion_callback, @@ -97,13 +107,14 @@ // Called on the |gpu_task_runner_| when a transaction is acked by the // framework. - void OnTransactionAckOnGpuThread(SwapCompletionCallback completion_callback, - PresentationCallback presentation_callback, - ResourceRefs released_resources, - int32_t present_fence); + void OnTransactionAckOnGpuThread( + SwapCompletionCallback completion_callback, + PresentationCallback presentation_callback, + ResourceRefs released_resources, + SurfaceControl::TransactionStats transaction_stats); // Holds the surface state changes made since the last call to SwapBuffers. - base::Optional<gl::SurfaceControl::Transaction> pending_transaction_; + base::Optional<SurfaceControl::Transaction> pending_transaction_; // The list of Surfaces and the corresponding state. The initial // |pending_surfaces_count_| surfaces in this list are surfaces with state @@ -128,7 +139,10 @@ // The root surface tied to the ANativeWindow that places the content of this // GLSurface in the java view tree. - gl::SurfaceControl::Surface root_surface_; + scoped_refptr<SurfaceControl::Surface> root_surface_; + + // The last context made current with this surface. + scoped_refptr<GLContext> context_; scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_; base::WeakPtrFactory<GLSurfaceEGLSurfaceControl> weak_factory_;
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index cb42418..ab92b68 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -274,6 +274,10 @@ ActivateKeyboardInContainer( layout_delegate_->GetContainerForDefaultDisplay()); + + // Start preloading the virtual keyboard UI in the background, so that it + // shows up faster when needed. + LoadKeyboardWindowInBackground(); } void KeyboardController::DisableKeyboard() {
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h index b60125c..7ea3eed 100644 --- a/ui/keyboard/keyboard_controller.h +++ b/ui/keyboard/keyboard_controller.h
@@ -87,6 +87,7 @@ static bool HasInstance(); // Enables the virtual keyboard with a specified |ui| and |delegate|. + // Immediately starts pre-loading the keyboard window in the background. // Disables and re-enables the keyboard if it is already enabled. void EnableKeyboard(std::unique_ptr<KeyboardUI> ui, KeyboardLayoutDelegate* delegate); @@ -177,10 +178,6 @@ // lock the keyboard void ShowKeyboardInDisplay(const display::Display& display); - // Loads the keyboard window in the background, but does not display - // the keyboard. - void LoadKeyboardWindowInBackground(); - // Returns the bounds in screen for the visible portion of the keyboard. An // empty rectangle will get returned when the keyboard is hidden. const gfx::Rect& visual_bounds_in_screen() const { @@ -322,6 +319,10 @@ // keyboard if it is currently visible. void DeactivateKeyboard(); + // Loads the keyboard window in the background, but does not display + // the keyboard. + void LoadKeyboardWindowInBackground(); + // Show virtual keyboard immediately with animation. void ShowKeyboardInternal(aura::Window* target_container); void PopulateKeyboardContent(aura::Window* target_container,
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc index 5281d79..a8aaaa0 100644 --- a/ui/keyboard/keyboard_controller_unittest.cc +++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -282,8 +282,6 @@ TEST_F(KeyboardControllerTest, KeyboardSize) { root_window()->SetLayoutManager(new KeyboardLayoutManager(&controller())); - controller().LoadKeyboardWindowInBackground(); - // The keyboard window should not be visible. aura::Window* keyboard_window = controller().GetKeyboardWindow(); EXPECT_FALSE(keyboard_window->IsVisible()); @@ -317,7 +315,6 @@ ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE); base::RunLoop run_loop; - controller().LoadKeyboardWindowInBackground(); aura::Window* keyboard_window = controller().GetKeyboardWindow(); auto keyboard_container_observer = std::make_unique<KeyboardContainerObserver>(keyboard_window, &run_loop); @@ -360,7 +357,6 @@ ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE); base::RunLoop run_loop; - controller().LoadKeyboardWindowInBackground(); aura::Window* keyboard_window = controller().GetKeyboardWindow(); auto keyboard_container_observer = std::make_unique<KeyboardContainerObserver>(keyboard_window, &run_loop); @@ -398,7 +394,6 @@ ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); base::RunLoop run_loop; - controller().LoadKeyboardWindowInBackground(); aura::Window* keyboard_window = controller().GetKeyboardWindow(); auto keyboard_container_observer = std::make_unique<KeyboardContainerObserver>(keyboard_window, &run_loop); @@ -457,7 +452,6 @@ ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); base::RunLoop run_loop; - controller().LoadKeyboardWindowInBackground(); aura::Window* keyboard_window = controller().GetKeyboardWindow(); auto keyboard_container_observer = std::make_unique<KeyboardContainerObserver>(keyboard_window, &run_loop); @@ -496,7 +490,6 @@ // Tests that disabling the keyboard will get a corresponding event. TEST_F(KeyboardControllerTest, DisableKeyboard) { - controller().LoadKeyboardWindowInBackground(); aura::Window* keyboard_window = controller().GetKeyboardWindow(); ShowKeyboard(); @@ -508,7 +501,6 @@ } TEST_F(KeyboardControllerTest, SetOccludedBoundsChangesFullscreenBounds) { - controller().LoadKeyboardWindowInBackground(); // Keyboard is hidden, so SetContainerType should be synchronous. controller().SetContainerType(mojom::ContainerType::kFullscreen, @@ -547,8 +539,6 @@ KeyboardControllerTest::SetUp(); - // Preload the keyboard contents so that we can set its bounds. - controller().LoadKeyboardWindowInBackground(); // Wait for the keyboard contents to load. base::RunLoop().RunUntilIdle(); keyboard_window()->SetBounds(root_window()->bounds()); @@ -711,7 +701,6 @@ ui::TEXT_INPUT_MODE_NONE); base::RunLoop run_loop; - controller().LoadKeyboardWindowInBackground(); aura::Window* keyboard_window = controller().GetKeyboardWindow(); auto keyboard_container_observer = std::make_unique<KeyboardContainerObserver>(keyboard_window, &run_loop);
diff --git a/ui/keyboard/test/keyboard_test_util.cc b/ui/keyboard/test/keyboard_test_util.cc index efeda891..73d71ba 100644 --- a/ui/keyboard/test/keyboard_test_util.cc +++ b/ui/keyboard/test/keyboard_test_util.cc
@@ -48,6 +48,21 @@ } // namespace +namespace test { + +bool WaitUntilLoaded() { + // In tests, the keyboard window is mocked out so it usually "loads" within a + // single RunUntilIdle call. + base::RunLoop run_loop; + while (KeyboardController::Get()->GetStateForTest() == + KeyboardControllerState::LOADING_EXTENSION) { + run_loop.RunUntilIdle(); + } + return true; +} + +} // namespace test + bool WaitUntilShown() { // KeyboardController send a visibility update once the show animation // finishes.
diff --git a/ui/keyboard/test/keyboard_test_util.h b/ui/keyboard/test/keyboard_test_util.h index 0cacd08..d85a9810 100644 --- a/ui/keyboard/test/keyboard_test_util.h +++ b/ui/keyboard/test/keyboard_test_util.h
@@ -13,6 +13,14 @@ namespace keyboard { +// TODO(shend): Move other methods into test namespace. +namespace test { + +// Waits until the keyboard window finishes loading. +bool WaitUntilLoaded(); + +} // namespace test + // Waits until the keyboard is fully shown, with no pending animations. bool WaitUntilShown();
diff --git a/ui/views/animation/ink_drop_impl_unittest.cc b/ui/views/animation/ink_drop_impl_unittest.cc index dbe46ff2..e990c733 100644 --- a/ui/views/animation/ink_drop_impl_unittest.cc +++ b/ui/views/animation/ink_drop_impl_unittest.cc
@@ -323,7 +323,7 @@ typedef InkDropImplAutoHighlightTest InkDropImplCommonAutoHighlightTest; // Note: First argument is optional and intentionally left blank. // (it's a prefix for the generated test cases) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( , InkDropImplCommonAutoHighlightTest, testing::Values(InkDropImpl::AutoHighlightMode::NONE, @@ -371,9 +371,9 @@ typedef InkDropImplAutoHighlightTest InkDropImplNoAutoHighlightTest; // Note: First argument is optional and intentionally left blank. // (it's a prefix for the generated test cases) -INSTANTIATE_TEST_CASE_P(, - InkDropImplNoAutoHighlightTest, - testing::Values(InkDropImpl::AutoHighlightMode::NONE)); +INSTANTIATE_TEST_SUITE_P(, + InkDropImplNoAutoHighlightTest, + testing::Values(InkDropImpl::AutoHighlightMode::NONE)); TEST_P(InkDropImplNoAutoHighlightTest, VisibleHighlightDuringRippleAnimations) { test_api()->SetShouldHighlight(true); @@ -407,7 +407,7 @@ typedef InkDropImplAutoHighlightTest InkDropImplHideAutoHighlightTest; // Note: First argument is optional and intentionally left blank. // (it's a prefix for the generated test cases) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( , InkDropImplHideAutoHighlightTest, testing::Values(InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE)); @@ -567,7 +567,7 @@ typedef InkDropImplAutoHighlightTest InkDropImplShowAutoHighlightTest; // Note: First argument is optional and intentionally left blank. // (it's a prefix for the generated test cases) -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( , InkDropImplShowAutoHighlightTest, testing::Values(InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE));
diff --git a/ui/views/controls/image_view_unittest.cc b/ui/views/controls/image_view_unittest.cc index 5e4d4a5..399ed9c 100644 --- a/ui/views/controls/image_view_unittest.cc +++ b/ui/views/controls/image_view_unittest.cc
@@ -141,8 +141,8 @@ EXPECT_EQ(image_view_bounds, image_view()->bounds()); } -INSTANTIATE_TEST_CASE_P(, - ImageViewTest, - ::testing::Values(Axis::kHorizontal, Axis::kVertical)); +INSTANTIATE_TEST_SUITE_P(, + ImageViewTest, + ::testing::Values(Axis::kHorizontal, Axis::kVertical)); } // namespace views
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc index bda7ba1..5d3a78a 100644 --- a/ui/views/controls/menu/menu_controller.cc +++ b/ui/views/controls/menu/menu_controller.cc
@@ -2528,6 +2528,10 @@ if (item->GetSubmenu()->GetMenuItemCount() > 0) to_select = FindInitialSelectableMenuItem(item, INCREMENT_SELECTION_DOWN); if (to_select) { + // Selection is going from the ACTIONABLE to the SUBMENU region of the + // ACTIONABLE_SUBMENU, so highlight the SUBMENU area. + if (item->type_ == MenuItemView::ACTIONABLE_SUBMENU) + item->SetSelectionOfActionableSubmenu(true); SetSelection(to_select, SELECTION_UPDATE_IMMEDIATELY); return; }
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc index 2da29295..41565d3 100644 --- a/ui/views/controls/scroll_view_unittest.cc +++ b/ui/views/controls/scroll_view_unittest.cc
@@ -1725,12 +1725,12 @@ EXPECT_EQ(gfx::ScrollOffset(0, 10), test_api.CurrentOffset()); } -INSTANTIATE_TEST_CASE_P(, - WidgetScrollViewTestRTLAndLayers, - ::testing::Values(UiConfig::kLtr, - UiConfig::kRtl, - UiConfig::kLtrWithLayers, - UiConfig::kRtlWithLayers), - &UiConfigToString); +INSTANTIATE_TEST_SUITE_P(, + WidgetScrollViewTestRTLAndLayers, + ::testing::Values(UiConfig::kLtr, + UiConfig::kRtl, + UiConfig::kLtrWithLayers, + UiConfig::kRtlWithLayers), + &UiConfigToString); } // namespace views
diff --git a/ui/views/focus/focus_manager_unittest.cc b/ui/views/focus/focus_manager_unittest.cc index 91414af..0687a18 100644 --- a/ui/views/focus/focus_manager_unittest.cc +++ b/ui/views/focus/focus_manager_unittest.cc
@@ -660,7 +660,7 @@ // Instantiate the Boolean which is used to toggle RTL in // the parameterized tests. -INSTANTIATE_TEST_CASE_P(, FocusManagerArrowKeyTraversalTest, testing::Bool()); +INSTANTIATE_TEST_SUITE_P(, FocusManagerArrowKeyTraversalTest, testing::Bool()); } // namespace
diff --git a/ui/views/mus/remote_view/BUILD.gn b/ui/views/mus/remote_view/BUILD.gn index 8b33332..dd53a6e 100644 --- a/ui/views/mus/remote_view/BUILD.gn +++ b/ui/views/mus/remote_view/BUILD.gn
@@ -56,6 +56,7 @@ ":remote_view_provider", ":test_support", "//base", + "//base/test:test_support", "//testing/gtest", "//ui/aura", "//ui/aura:test_support",
diff --git a/ui/views/mus/remote_view/remote_view_provider_unittest.cc b/ui/views/mus/remote_view/remote_view_provider_unittest.cc index 1d727f6..0ff8e8f3 100644 --- a/ui/views/mus/remote_view/remote_view_provider_unittest.cc +++ b/ui/views/mus/remote_view/remote_view_provider_unittest.cc
@@ -10,7 +10,9 @@ #include "base/bind_helpers.h" #include "base/macros.h" #include "base/run_loop.h" +#include "base/test/bind_test_util.h" #include "base/unguessable_token.h" +#include "ui/aura/client/focus_change_observer.h" #include "ui/aura/mus/window_mus.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/mus/test_window_tree.h" @@ -22,6 +24,30 @@ namespace views { +class TestFocusChangeObserver : public aura::client::FocusChangeObserver { + public: + explicit TestFocusChangeObserver(aura::Window* window) : window_(window) { + aura::client::SetFocusChangeObserver(window_, this); + } + ~TestFocusChangeObserver() override { + aura::client::SetFocusChangeObserver(window_, nullptr); + } + + // aura::client::FocusChangeObserver: + void OnWindowFocused(aura::Window* gained_focus, + aura::Window* lost_focus) override { + on_window_focused_called_ = true; + } + + bool on_window_focused_called() const { return on_window_focused_called_; } + + private: + aura::Window* const window_; + bool on_window_focused_called_ = false; + + DISALLOW_COPY_AND_ASSIGN(TestFocusChangeObserver); +}; + class RemoteViewProviderTest : public aura::test::AuraTestBase { public: RemoteViewProviderTest() = default; @@ -55,13 +81,11 @@ base::UnguessableToken GetEmbedToken() { base::RunLoop run_loop; base::UnguessableToken token; - provider_->GetEmbedToken(base::BindOnce( - [](base::RunLoop* run_loop, base::UnguessableToken* out_token, - const base::UnguessableToken& token) { - *out_token = token; - run_loop->Quit(); - }, - &run_loop, &token)); + provider_->GetEmbedToken( + base::BindLambdaForTesting([&](const base::UnguessableToken& in_token) { + token = in_token; + run_loop.Quit(); + })); run_loop.Run(); return token; } @@ -73,13 +97,10 @@ base::RunLoop run_loop; aura::Window* embedder = nullptr; provider_->SetCallbacks( - base::BindRepeating( - [](base::RunLoop* run_loop, aura::Window** out_embedder, - aura::Window* embedder) { - *out_embedder = embedder; - run_loop->Quit(); - }, - &run_loop, &embedder), + base::BindLambdaForTesting([&](aura::Window* in_embedder) { + embedder = in_embedder; + run_loop.Quit(); + }), base::DoNothing() /* OnUnembedCallback */); window_tree()->AddEmbedRootForToken(token); run_loop.Run(); @@ -102,8 +123,7 @@ base::RunLoop run_loop; provider_->SetCallbacks( base::DoNothing() /* OnEmbedCallback */, - base::BindRepeating([](base::RunLoop* run_loop) { run_loop->Quit(); }, - &run_loop)); + base::BindLambdaForTesting([&]() { run_loop.Quit(); })); const ws::Id embedder_window_id = aura::WindowMus::Get(embedder)->server_id(); @@ -191,4 +211,14 @@ EXPECT_EQ(root_bounds.origin(), root_window->GetBoundsInScreen().origin()); } +TEST_F(RemoteViewProviderTest, FocusChangeObserver) { + SimulateEmbed(); + + TestFocusChangeObserver observer(embedded_.get()); + ASSERT_FALSE(observer.on_window_focused_called()); + + embedded_->Focus(); + EXPECT_TRUE(observer.on_window_focused_called()); +} + } // namespace views
diff --git a/ui/views/test/DEPS b/ui/views/test/DEPS index 98b1137..2ba6d7d 100644 --- a/ui/views/test/DEPS +++ b/ui/views/test/DEPS
@@ -7,6 +7,6 @@ "+services/service_manager/background/background_service_manager.h", "+services/service_manager/public", "+services/ws/ime/test_ime_driver/manifest.h", - "+services/ws/test_ws/manifest.h", + "+services/ws/test_ws/test_manifest.h", ] }
diff --git a/ui/views/test/platform_test_helper_mus.cc b/ui/views/test/platform_test_helper_mus.cc index 505067e..342c0b8b 100644 --- a/ui/views/test/platform_test_helper_mus.cc +++ b/ui/views/test/platform_test_helper_mus.cc
@@ -16,7 +16,7 @@ #include "services/service_manager/public/cpp/service_binding.h" #include "services/ws/ime/test_ime_driver/manifest.h" #include "services/ws/public/mojom/constants.mojom.h" -#include "services/ws/test_ws/manifest.h" +#include "services/ws/test_ws/test_manifest.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/test/env_test_helper.h"
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc index ca9e496..7e8621d 100644 --- a/ui/views/widget/widget_unittest.cc +++ b/ui/views/widget/widget_unittest.cc
@@ -630,7 +630,7 @@ InvokeWidgetMethods(&widget); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( PlatformWidgetWithDestroyedNativeViewTest, WidgetWithDestroyedNativeViewTest, ::testing::Values(ViewsTestBase::NativeWidgetType::kDefault,
diff --git a/ui/wm/core/accelerator_filter.cc b/ui/wm/core/accelerator_filter.cc index 21f10d5..598b141 100644 --- a/ui/wm/core/accelerator_filter.cc +++ b/ui/wm/core/accelerator_filter.cc
@@ -28,16 +28,29 @@ AcceleratorFilter::~AcceleratorFilter() { } +bool AcceleratorFilter::ShouldFilter(ui::KeyEvent* event) { + const ui::EventType type = event->type(); + if (!event->target() || + (type != ui::ET_KEY_PRESSED && type != ui::ET_KEY_RELEASED) || + event->is_char() || !event->target() || + // Key events with key code of VKEY_PROCESSKEY, usually created by virtual + // keyboard (like handwriting input), have no effect on accelerator and + // they may disturb the accelerator history. So filter them out. (see + // https://crbug.com/918317) + event->key_code() == ui::VKEY_PROCESSKEY) { + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////// // AcceleratorFilter, EventFilter implementation: void AcceleratorFilter::OnKeyEvent(ui::KeyEvent* event) { - const ui::EventType type = event->type(); DCHECK(event->target()); - if ((type != ui::ET_KEY_PRESSED && type != ui::ET_KEY_RELEASED) || - event->is_char() || !event->target()) { + if (ShouldFilter(event)) return; - } ui::Accelerator accelerator(*event); accelerator_history_->StoreCurrentAccelerator(accelerator);
diff --git a/ui/wm/core/accelerator_filter.h b/ui/wm/core/accelerator_filter.h index 86bdf77e2..18f27645 100644 --- a/ui/wm/core/accelerator_filter.h +++ b/ui/wm/core/accelerator_filter.h
@@ -28,6 +28,9 @@ ui::AcceleratorHistory* accelerator_history); ~AcceleratorFilter() override; + // If the return value is true, |event| should be filtered out. + static bool ShouldFilter(ui::KeyEvent* event); + // Overridden from ui::EventHandler: void OnKeyEvent(ui::KeyEvent* event) override; void OnMouseEvent(ui::MouseEvent* event) override;