diff --git a/DEPS b/DEPS index 4e7d417..35decb4 100644 --- a/DEPS +++ b/DEPS
@@ -308,7 +308,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1413d75bc71561db4dd2f9085650c6b58a77161f', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2a1ca3f68bc97c69537d46890348bfc79483ed60', # DevTools node modules. Used on Linux buildbots only. 'src/third_party/devtools-node-modules': {
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 62449fd..d682d8434 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -102,6 +102,8 @@ "display/display_configuration_controller.h", "display/display_error_observer_chromeos.cc", "display/display_error_observer_chromeos.h", + "display/display_move_window_util.cc", + "display/display_move_window_util.h", "display/display_util.cc", "display/display_util.h", "display/event_transformation_handler.cc", @@ -1254,6 +1256,7 @@ "display/display_configuration_controller_unittest.cc", "display/display_error_observer_chromeos_unittest.cc", "display/display_manager_unittest.cc", + "display/display_move_window_util_unittest.cc", "display/display_util_unittest.cc", "display/extended_mouse_warp_controller_unittest.cc", "display/mirror_window_controller_unittest.cc",
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 89225e0..e6d29be5 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -13,6 +13,7 @@ #include "ash/accessibility/accessibility_delegate.h" #include "ash/accessibility_types.h" #include "ash/display/display_configuration_controller.h" +#include "ash/display/display_move_window_util.h" #include "ash/focus_cycler.h" #include "ash/ime/ime_controller.h" #include "ash/ime/ime_switch_type.h" @@ -257,6 +258,22 @@ Shell::Get()->media_controller()->HandleMediaPrevTrack(); } +void HandleMoveWindowBetweenDisplays(const ui::Accelerator& accelerator) { + ui::KeyboardCode key_code = accelerator.key_code(); + DisplayMoveWindowDirection direction; + if (key_code == ui::VKEY_LEFT) { + direction = DisplayMoveWindowDirection::kLeft; + } else if (key_code == ui::VKEY_UP) { + direction = DisplayMoveWindowDirection::kAbove; + } else if (key_code == ui::VKEY_RIGHT) { + direction = DisplayMoveWindowDirection::kRight; + } else { + DCHECK(key_code == ui::VKEY_DOWN); + direction = DisplayMoveWindowDirection::kBelow; + } + HandleMoveWindowToDisplay(direction); +} + void HandleToggleMirrorMode() { base::RecordAction(UserMetricsAction("Accel_Toggle_Mirror_Mode")); bool mirror = !Shell::Get()->display_manager()->IsInMirrorMode(); @@ -613,6 +630,14 @@ Shell::Get()->session_controller()->LockScreen(); } +bool CanHandleMoveWindowBetweenDisplays() { + display::DisplayManager* display_manager = Shell::Get()->display_manager(); + // Accelerators to move window between displays on unified desktop mode and + // mirror mode is disabled. + return !display_manager->IsInUnifiedMode() && + !display_manager->IsInMirrorMode(); +} + PaletteTray* GetPaletteTray() { return Shelf::ForWindow(Shell::GetRootWindowForNewWindows()) ->GetStatusAreaWidget() @@ -1073,6 +1098,11 @@ return CanHandleDisableCapsLock(previous_accelerator); case LOCK_SCREEN: return CanHandleLock(); + case MOVE_WINDOW_TO_ABOVE_DISPLAY: + case MOVE_WINDOW_TO_BELOW_DISPLAY: + case MOVE_WINDOW_TO_LEFT_DISPLAY: + case MOVE_WINDOW_TO_RIGHT_DISPLAY: + return CanHandleMoveWindowBetweenDisplays(); case NEW_INCOGNITO_WINDOW: return CanHandleNewIncognitoWindow(); case NEXT_IME: @@ -1287,6 +1317,12 @@ case MEDIA_PREV_TRACK: HandleMediaPrevTrack(); break; + case MOVE_WINDOW_TO_ABOVE_DISPLAY: + case MOVE_WINDOW_TO_BELOW_DISPLAY: + case MOVE_WINDOW_TO_LEFT_DISPLAY: + case MOVE_WINDOW_TO_RIGHT_DISPLAY: + HandleMoveWindowBetweenDisplays(accelerator); + break; case NEW_INCOGNITO_WINDOW: HandleNewIncognitoWindow(); break;
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc index c53d39b..f1fad7e 100644 --- a/ash/accelerators/accelerator_table.cc +++ b/ash/accelerators/accelerator_table.cc
@@ -156,6 +156,16 @@ {true, ui::VKEY_BROWSER_FORWARD, ui::EF_CONTROL_DOWN, FOCUS_NEXT_PANE}, {true, ui::VKEY_BROWSER_BACK, ui::EF_CONTROL_DOWN, FOCUS_PREVIOUS_PANE}, + // Window movement between displays shortcuts. + {true, ui::VKEY_UP, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, + MOVE_WINDOW_TO_ABOVE_DISPLAY}, + {true, ui::VKEY_DOWN, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, + MOVE_WINDOW_TO_BELOW_DISPLAY}, + {true, ui::VKEY_LEFT, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, + MOVE_WINDOW_TO_LEFT_DISPLAY}, + {true, ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, + MOVE_WINDOW_TO_RIGHT_DISPLAY}, + // Media Player shortcuts. {true, ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE, MEDIA_NEXT_TRACK}, {true, ui::VKEY_MEDIA_PLAY_PAUSE, ui::EF_NONE, MEDIA_PLAY_PAUSE},
diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h index d82b970..9fa6d638 100644 --- a/ash/accelerators/accelerator_table.h +++ b/ash/accelerators/accelerator_table.h
@@ -95,6 +95,10 @@ MEDIA_NEXT_TRACK, MEDIA_PLAY_PAUSE, MEDIA_PREV_TRACK, + MOVE_WINDOW_TO_ABOVE_DISPLAY, + MOVE_WINDOW_TO_BELOW_DISPLAY, + MOVE_WINDOW_TO_LEFT_DISPLAY, + MOVE_WINDOW_TO_RIGHT_DISPLAY, NEW_INCOGNITO_WINDOW, NEW_TAB, NEW_WINDOW,
diff --git a/ash/accelerators/accelerator_table_unittest.cc b/ash/accelerators/accelerator_table_unittest.cc index 63f2a9b..f9f2a17 100644 --- a/ash/accelerators/accelerator_table_unittest.cc +++ b/ash/accelerators/accelerator_table_unittest.cc
@@ -19,8 +19,10 @@ constexpr int kNonSearchAcceleratorsNum = 93; // The hash of non-Search-based accelerators as of 2017-10-26. // See HashAcceleratorData(). +// TODO: adding Search-based accelerators should not update this hash +// (crbug.com/778432). constexpr char kNonSearchAcceleratorsHash[] = - "f49b50d5990e0d2af99160176c6215f7"; + "ccfca1c73d60f4837cef74800374a1c9"; struct Cmp { bool operator()(const AcceleratorData& lhs, const AcceleratorData& rhs) {
diff --git a/ash/display/display_move_window_util.cc b/ash/display/display_move_window_util.cc new file mode 100644 index 0000000..eae60ba --- /dev/null +++ b/ash/display/display_move_window_util.cc
@@ -0,0 +1,148 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/display/display_move_window_util.h" + +#include <stdint.h> +#include <array> + +#include "ash/wm/window_util.h" +#include "ui/aura/window.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/display/types/display_constants.h" + +namespace ash { + +namespace { + +// Calculate the vertical offset between two displays' center points. +int GetVerticalOffset(const display::Display& display1, + const display::Display& display2) { + DCHECK(display1.is_valid()); + DCHECK(display2.is_valid()); + return std::abs(display1.bounds().CenterPoint().y() - + display2.bounds().CenterPoint().y()); +} + +// Calculate the horizontal offset between two displays' center points. +int GetHorizontalOffset(const display::Display& display1, + const display::Display& display2) { + DCHECK(display1.is_valid()); + DCHECK(display2.is_valid()); + return std::abs(display1.bounds().CenterPoint().x() - + display2.bounds().CenterPoint().x()); +} + +// Returns true if |candidate_display| is not completely off the bounds of +// |original_display| in the moving direction or cycled direction. +bool IsWithinBounds(const display::Display& candidate_display, + const display::Display& origin_display, + DisplayMoveWindowDirection direction) { + const gfx::Rect& candidate_bounds = candidate_display.bounds(); + const gfx::Rect& origin_bounds = origin_display.bounds(); + if (direction == DisplayMoveWindowDirection::kLeft || + direction == DisplayMoveWindowDirection::kRight) { + return GetHorizontalOffset(candidate_display, origin_display) < + (candidate_bounds.width() + origin_bounds.width()) / 2; + } + + return GetVerticalOffset(candidate_display, origin_display) < + (candidate_bounds.height() + origin_bounds.height()) / 2; +} + +// Gets the space between displays. The calculation is based on |direction|. +// Non-negative value indicates |kInMovementDirection| and negative value +// indicates |kInCycledDirection|. +int GetSpaceBetweenDisplays(const display::Display& candidate_display, + const display::Display& origin_display, + DisplayMoveWindowDirection direction) { + switch (direction) { + case DisplayMoveWindowDirection::kAbove: + return origin_display.bounds().y() - candidate_display.bounds().bottom(); + case DisplayMoveWindowDirection::kBelow: + return candidate_display.bounds().y() - origin_display.bounds().bottom(); + case DisplayMoveWindowDirection::kLeft: + return origin_display.bounds().x() - candidate_display.bounds().right(); + case DisplayMoveWindowDirection::kRight: + return candidate_display.bounds().x() - origin_display.bounds().right(); + } + NOTREACHED(); + return 0; +} + +// Gets the orthogonal offset between displays, which is vertical offset for +// left/right, horizontal offset for above/below. +int GetOrthogonalOffsetBetweenDisplays( + const display::Display& candidate_display, + const display::Display& origin_display, + DisplayMoveWindowDirection direction) { + if (direction == DisplayMoveWindowDirection::kLeft || + direction == DisplayMoveWindowDirection::kRight) { + return GetVerticalOffset(candidate_display, origin_display); + } + return GetHorizontalOffset(candidate_display, origin_display); +} + +// Gets the display id of next display of |origin_display| on the moving +// |direction|. Cycled direction result is returned if the moving |direction| +// doesn't contain eligible candidate displays. +int64_t GetNextDisplay(const display::Display& origin_display, + DisplayMoveWindowDirection direction) { + // Saves the next display found in the specified movement direction. + display::Display next_movement_display; + // Saves the next display found in the cycled movement direction. + display::Display next_cycled_display; + for (const auto& candidate_display : + display::Screen::GetScreen()->GetAllDisplays()) { + if (candidate_display.id() == origin_display.id()) + continue; + // Ignore the candidate display if |IsWithinBounds| returns true. This + // ensures that |candidate_space| calculated below represents the real + // layout apart distance. + if (IsWithinBounds(candidate_display, origin_display, direction)) + continue; + const int candidate_space = + GetSpaceBetweenDisplays(candidate_display, origin_display, direction); + display::Display& next_display = + candidate_space >= 0 ? next_movement_display : next_cycled_display; + + if (!next_display.is_valid()) { + next_display = candidate_display; + continue; + } + + const int current_space = + GetSpaceBetweenDisplays(next_display, origin_display, direction); + if (candidate_space < current_space) { + next_display = candidate_display; + } else if (candidate_space == current_space) { + const int candidate_orthogonal_offset = + GetOrthogonalOffsetBetweenDisplays(candidate_display, origin_display, + direction); + const int current_orthogonal_offset = GetOrthogonalOffsetBetweenDisplays( + next_display, origin_display, direction); + if (candidate_orthogonal_offset < current_orthogonal_offset) + next_display = candidate_display; + } + } + + return next_movement_display.is_valid() ? next_movement_display.id() + : next_cycled_display.id(); +} + +} // namespace + +void HandleMoveWindowToDisplay(DisplayMoveWindowDirection direction) { + aura::Window* window = wm::GetActiveWindow(); + if (!window) + return; + + display::Display origin_display = + display::Screen::GetScreen()->GetDisplayNearestWindow(window); + int64_t dest_display_id = GetNextDisplay(origin_display, direction); + wm::MoveWindowToDisplay(window, dest_display_id); +} + +} // namespace ash
diff --git a/ash/display/display_move_window_util.h b/ash/display/display_move_window_util.h new file mode 100644 index 0000000..4aa695be --- /dev/null +++ b/ash/display/display_move_window_util.h
@@ -0,0 +1,20 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_DISPLAY_DISPLAY_MOVE_WINDOW_UTIL_H_ +#define ASH_DISPLAY_DISPLAY_MOVE_WINDOW_UTIL_H_ + +#include "ash/ash_export.h" + +namespace ash { + +enum class DisplayMoveWindowDirection { kAbove, kBelow, kLeft, kRight }; + +// Handles moving current active window from its display to another display +// specified by |Direction|. +ASH_EXPORT void HandleMoveWindowToDisplay(DisplayMoveWindowDirection direction); + +} // namespace ash + +#endif // ASH_DISPLAY_DISPLAY_MOVE_WINDOW_UTIL_H_
diff --git a/ash/display/display_move_window_util_unittest.cc b/ash/display/display_move_window_util_unittest.cc new file mode 100644 index 0000000..a25dfef6 --- /dev/null +++ b/ash/display/display_move_window_util_unittest.cc
@@ -0,0 +1,216 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/display/display_move_window_util.h" + +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "ash/wm/window_util.h" +#include "base/macros.h" +#include "ui/aura/test/test_windows.h" +#include "ui/display/display.h" +#include "ui/display/display_layout.h" +#include "ui/display/display_layout_builder.h" +#include "ui/display/manager/display_layout_store.h" +#include "ui/display/manager/display_manager.h" +#include "ui/display/screen.h" +#include "ui/display/test/display_manager_test_api.h" + +namespace ash { + +using DisplayMoveWindowUtilTest = AshTestBase; + +// Tests that window bounds are not changing after moving to another display. It +// is added as a child window to another root window with the same origin. +TEST_F(DisplayMoveWindowUtilTest, WindowBounds) { + display::Screen* screen = display::Screen::GetScreen(); + int64_t primary_id = screen->GetPrimaryDisplay().id(); + display::DisplayIdList list = + display::test::CreateDisplayIdList2(primary_id, primary_id + 1); + // Layout: [p][1] + display::DisplayLayoutBuilder builder(primary_id); + builder.AddDisplayPlacement(list[1], primary_id, + display::DisplayPlacement::RIGHT, 0); + display_manager()->layout_store()->RegisterLayoutForDisplayIdList( + list, builder.Build()); + UpdateDisplay("400x300,400x300"); + EXPECT_EQ(2U, display_manager()->GetNumDisplays()); + EXPECT_EQ(gfx::Rect(0, 0, 400, 300), + display_manager()->GetDisplayAt(0).bounds()); + EXPECT_EQ(gfx::Rect(400, 0, 400, 300), + display_manager()->GetDisplayAt(1).bounds()); + + aura::Window* window = + CreateTestWindowInShellWithBounds(gfx::Rect(10, 20, 200, 100)); + wm::ActivateWindow(window); + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kRight); + EXPECT_EQ(gfx::Rect(410, 20, 200, 100), window->GetBoundsInScreen()); +} + +// A horizontal layout for three displays. They are perfectly horizontally +// aligned with no vertical offset. +TEST_F(DisplayMoveWindowUtilTest, ThreeDisplaysHorizontalLayout) { + display::Screen* screen = display::Screen::GetScreen(); + int64_t primary_id = screen->GetPrimaryDisplay().id(); + display::DisplayIdList list = display::test::CreateDisplayIdListN( + 3, primary_id, primary_id + 1, primary_id + 2); + // Layout: [p][1][2] + display::DisplayLayoutBuilder builder(primary_id); + builder.AddDisplayPlacement(list[1], primary_id, + display::DisplayPlacement::RIGHT, 0); + builder.AddDisplayPlacement(list[2], list[1], + display::DisplayPlacement::RIGHT, 0); + display_manager()->layout_store()->RegisterLayoutForDisplayIdList( + list, builder.Build()); + UpdateDisplay("400x300,400x300,400x300"); + EXPECT_EQ(3U, display_manager()->GetNumDisplays()); + EXPECT_EQ(gfx::Rect(0, 0, 400, 300), + display_manager()->GetDisplayAt(0).bounds()); + EXPECT_EQ(gfx::Rect(400, 0, 400, 300), + display_manager()->GetDisplayAt(1).bounds()); + EXPECT_EQ(gfx::Rect(800, 0, 400, 300), + display_manager()->GetDisplayAt(2).bounds()); + + aura::Window* window = + CreateTestWindowInShellWithBounds(gfx::Rect(10, 20, 200, 100)); + wm::ActivateWindow(window); + ASSERT_EQ(list[0], screen->GetDisplayNearestWindow(window).id()); + + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kLeft); + EXPECT_EQ(list[2], screen->GetDisplayNearestWindow(window).id()); + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kLeft); + EXPECT_EQ(list[1], screen->GetDisplayNearestWindow(window).id()); + + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kRight); + EXPECT_EQ(list[2], screen->GetDisplayNearestWindow(window).id()); + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kRight); + EXPECT_EQ(list[0], screen->GetDisplayNearestWindow(window).id()); + + // No-op for above/below movement since no display is in the above/below of + // primary display. + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kAbove); + EXPECT_EQ(list[0], screen->GetDisplayNearestWindow(window).id()); + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kBelow); + EXPECT_EQ(list[0], screen->GetDisplayNearestWindow(window).id()); +} + +// A vertical layout for three displays. They are laid out with horizontal +// offset. +TEST_F(DisplayMoveWindowUtilTest, ThreeDisplaysVerticalLayoutWithOffset) { + display::Screen* screen = display::Screen::GetScreen(); + int64_t primary_id = screen->GetPrimaryDisplay().id(); + display::DisplayIdList list = display::test::CreateDisplayIdListN( + 3, primary_id, primary_id + 1, primary_id + 2); + // Layout: [P] + // [2] + // [1] + // Note that display [1] is completely in the right of display [p]. + display::DisplayLayoutBuilder builder(primary_id); + builder.AddDisplayPlacement(list[1], list[2], + display::DisplayPlacement::BOTTOM, 200); + builder.AddDisplayPlacement(list[2], primary_id, + display::DisplayPlacement::BOTTOM, 200); + display_manager()->layout_store()->RegisterLayoutForDisplayIdList( + list, builder.Build()); + UpdateDisplay("400x300,400x300,400x300"); + EXPECT_EQ(3U, display_manager()->GetNumDisplays()); + EXPECT_EQ(gfx::Rect(0, 0, 400, 300), + display_manager()->GetDisplayAt(0).bounds()); + EXPECT_EQ(gfx::Rect(200, 300, 400, 300), + display_manager()->GetDisplayAt(2).bounds()); + EXPECT_EQ(gfx::Rect(400, 600, 400, 300), + display_manager()->GetDisplayAt(1).bounds()); + + aura::Window* window = + CreateTestWindowInShellWithBounds(gfx::Rect(10, 20, 200, 100)); + wm::ActivateWindow(window); + ASSERT_EQ(list[0], screen->GetDisplayNearestWindow(window).id()); + + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kAbove); + EXPECT_EQ(list[1], screen->GetDisplayNearestWindow(window).id()); + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kAbove); + EXPECT_EQ(list[2], screen->GetDisplayNearestWindow(window).id()); + + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kBelow); + EXPECT_EQ(list[1], screen->GetDisplayNearestWindow(window).id()); + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kBelow); + EXPECT_EQ(list[0], screen->GetDisplayNearestWindow(window).id()); + + // Left/Right is able to be applied between display [p] and [1]. + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kRight); + EXPECT_EQ(list[1], screen->GetDisplayNearestWindow(window).id()); + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kLeft); + EXPECT_EQ(list[0], screen->GetDisplayNearestWindow(window).id()); +} + +// A more than three displays layout to verify the select closest strategy. +TEST_F(DisplayMoveWindowUtilTest, SelectClosestCandidate) { + display::Screen* screen = display::Screen::GetScreen(); + int64_t primary_id = screen->GetPrimaryDisplay().id(); + // Layout: + // +--------+ + // | 5 |----+ + // +---+----+ 3 | + // | 4 |--+----+----+ + // +----+ | P | 1 | + // +----+----+ + // | 2 | + // +----+ + display::DisplayIdList list = display::test::CreateDisplayIdListN( + 6, primary_id, primary_id + 1, primary_id + 2, primary_id + 3, + primary_id + 4, primary_id + 5); + display::DisplayLayoutBuilder builder(primary_id); + builder.AddDisplayPlacement(list[1], primary_id, + display::DisplayPlacement::RIGHT, 0); + builder.AddDisplayPlacement(list[2], list[1], + display::DisplayPlacement::BOTTOM, 0); + builder.AddDisplayPlacement(list[3], primary_id, + display::DisplayPlacement::TOP, -200); + builder.AddDisplayPlacement(list[4], list[3], display::DisplayPlacement::LEFT, + 200); + builder.AddDisplayPlacement(list[5], list[3], display::DisplayPlacement::LEFT, + -100); + display_manager()->layout_store()->RegisterLayoutForDisplayIdList( + list, builder.Build()); + UpdateDisplay("400x300,400x300,400x300,400x300,400x300,800x300"); + EXPECT_EQ(6U, display_manager()->GetNumDisplays()); + EXPECT_EQ(gfx::Rect(0, 0, 400, 300), + display_manager()->GetDisplayAt(0).bounds()); + EXPECT_EQ(gfx::Rect(400, 0, 400, 300), + display_manager()->GetDisplayAt(1).bounds()); + EXPECT_EQ(gfx::Rect(400, 300, 400, 300), + display_manager()->GetDisplayAt(2).bounds()); + EXPECT_EQ(gfx::Rect(-200, -300, 400, 300), + display_manager()->GetDisplayAt(3).bounds()); + EXPECT_EQ(gfx::Rect(-600, -100, 400, 300), + display_manager()->GetDisplayAt(4).bounds()); + EXPECT_EQ(gfx::Rect(-1000, -400, 800, 300), + display_manager()->GetDisplayAt(5).bounds()); + + aura::Window* window = + CreateTestWindowInShellWithBounds(gfx::Rect(10, 20, 200, 100)); + wm::ActivateWindow(window); + ASSERT_EQ(list[0], screen->GetDisplayNearestWindow(window).id()); + + // Moving window to left display, we have [4] and [5] candidate displays in + // the left direction. They have the same left space but [4] is selected since + // it is vertically closer to display [p]. + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kLeft); + EXPECT_EQ(list[4], screen->GetDisplayNearestWindow(window).id()); + + // Moving window to left display, we don't have candidate displays in the left + // direction. [1][2][3][p] are candidate displays in the cycled direction. + // [1][2] have the same left space but [1] is selected since it is vertically + // closer to display [4]. + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kLeft); + EXPECT_EQ(list[1], screen->GetDisplayNearestWindow(window).id()); + + // Moving window to right display, we don't have candidate displays in the + // right direction. [p][3][4][5] are candidate displays in the cycled + // direction. [5] has the furthest right space so it is selected. + HandleMoveWindowToDisplay(DisplayMoveWindowDirection::kRight); + EXPECT_EQ(list[5], screen->GetDisplayNearestWindow(window).id()); +} + +} // namespace ash
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java index 49df28d..b9cd81f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java
@@ -236,4 +236,12 @@ mTabSaver.destroy(); sInstance = null; } + + /** + * Add a {@link TabPersistentStoreObserver} to {@link TabPersistentStore}. + * @param observer The observer to add. + */ + public void addTabPersistentStoreObserver(TabPersistentStoreObserver observer) { + mTabSaver.addObserver(observer); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java index 58d50d3..40363fe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
@@ -416,4 +416,12 @@ public TabPersistentStore getTabPersistentStoreForTesting() { return mTabSaver; } + + /** + * Add a {@link TabPersistentStoreObserver} to {@link TabPersistentStore}. + * @param observer The observer to add. + */ + public void addTabPersistentStoreObserver(TabPersistentStoreObserver observer) { + mTabSaver.addObserver(observer); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java index b8f21c4..9c6b38f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -19,6 +19,7 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.Log; +import org.chromium.base.ObserverList; import org.chromium.base.StreamUtil; import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; @@ -132,8 +133,9 @@ /** * Called when the metadata file has been saved out asynchronously. * This currently does not get called when the metadata file is saved out on the UI thread. + * @param modelSelectorMetadata The saved metadata of current tab model selector. */ - public void onMetadataSavedAsynchronously() {} + public void onMetadataSavedAsynchronously(TabModelSelectorMetadata modelSelectorMetadata) {} } /** Stores information about a TabModel. */ @@ -162,7 +164,7 @@ private final TabPersistencePolicy mPersistencePolicy; private final TabModelSelector mTabModelSelector; private final TabCreatorManager mTabCreatorManager; - private TabPersistentStoreObserver mObserver; + private ObserverList<TabPersistentStoreObserver> mObservers; private final Deque<Tab> mTabsToSave; private final Deque<TabRestoreDetails> mTabsToRestore; @@ -212,7 +214,8 @@ mTabsToSave = new ArrayDeque<>(); mTabsToRestore = new ArrayDeque<>(); mTabIdsToRestore = new HashSet<>(); - mObserver = observer; + mObservers = new ObserverList<>(); + mObservers.addObserver(observer); mPreferences = ContextUtils.getAppSharedPreferences(); mPrefetchTabListToMergeTasks = new ArrayList<>(); @@ -280,7 +283,7 @@ // it looked when the SaveListTask was first created. if (mSaveListTask != null) mSaveListTask.cancel(true); try { - saveListToFile(serializeTabMetadata()); + saveListToFile(serializeTabMetadata().listData); } catch (IOException e) { Log.w(TAG, "Error while saving tabs state; will attempt to continue...", e); } @@ -414,7 +417,9 @@ } mPersistencePolicy.notifyStateLoaded(mTabsToRestore.size()); - if (mObserver != null) mObserver.onInitialized(mTabsToRestore.size()); + for (TabPersistentStoreObserver observer : mObservers) { + observer.onInitialized(mTabsToRestore.size()); + } } /** @@ -795,7 +800,7 @@ // done as part of the standard tab removal process. } - private byte[] serializeTabMetadata() throws IOException { + private TabModelSelectorMetadata serializeTabMetadata() throws IOException { List<TabRestoreDetails> tabsToRestore = new ArrayList<>(); // The metadata file may be being written out before all of the Tabs have been restored. @@ -813,10 +818,11 @@ * and selected indices. * @param selector The {@link TabModelSelector} to serialize. * @param tabsBeingRestored Tabs that are in the process of being restored. - * @return {@code byte[]} containing the serialized state of {@code selector}. + * @return {@link TabModelSelectorMetadata} containing the meta data and + * serialized state of {@code selector}. */ @VisibleForTesting - public static byte[] serializeTabModelSelector(TabModelSelector selector, + public static TabModelSelectorMetadata serializeTabModelSelector(TabModelSelector selector, List<TabRestoreDetails> tabsBeingRestored) throws IOException { ThreadUtils.assertOnUiThread(); @@ -844,7 +850,8 @@ ContextUtils.getAppSharedPreferences().edit().putInt( PREF_ACTIVE_TAB_ID, activeTabId).apply(); - return serializeMetadata(normalInfo, incognitoInfo, tabsBeingRestored); + byte[] listData = serializeMetadata(normalInfo, incognitoInfo, tabsBeingRestored); + return new TabModelSelectorMetadata(listData, normalInfo, incognitoInfo, tabsBeingRestored); } /** @@ -975,8 +982,8 @@ mTabsToRestore.addLast(details); } - if (mObserver != null) { - mObserver.onDetailsRead( + for (TabPersistentStoreObserver observer : mObservers) { + observer.onDetailsRead( index, id, url, isStandardActiveIndex, isIncognitoActiveIndex); } } @@ -1155,43 +1162,65 @@ } } + /** Stores meta data about the TabModelSelector which has been serialized to disk. */ + public static class TabModelSelectorMetadata { + public final byte[] listData; + public final TabModelMetadata normalModelMetadata; + public final TabModelMetadata incognitoModelMetadata; + public final List<TabRestoreDetails> tabsBeingRestored; + + public TabModelSelectorMetadata(byte[] listData, TabModelMetadata normalModelMetadata, + TabModelMetadata incognitoModelMetadata, + List<TabRestoreDetails> tabsBeingRestored) { + this.listData = listData; + this.normalModelMetadata = normalModelMetadata; + this.incognitoModelMetadata = incognitoModelMetadata; + this.tabsBeingRestored = tabsBeingRestored; + } + } + private class SaveListTask extends AsyncTask<Void, Void, Void> { - byte[] mListData; + TabModelSelectorMetadata mMetadata; @Override protected void onPreExecute() { if (mDestroyed || isCancelled()) return; try { - mListData = serializeTabMetadata(); + mMetadata = serializeTabMetadata(); } catch (IOException e) { - mListData = null; + mMetadata = null; } } @Override protected Void doInBackground(Void... voids) { - if (mListData == null || isCancelled()) return null; - saveListToFile(mListData); - mListData = null; + if (mMetadata == null || isCancelled()) return null; + saveListToFile(mMetadata.listData); return null; } @Override protected void onPostExecute(Void v) { - if (mDestroyed || isCancelled()) return; + if (mDestroyed || isCancelled()) { + mMetadata = null; + return; + } if (mSaveListTask == this) { mSaveListTask = null; - if (mObserver != null) mObserver.onMetadataSavedAsynchronously(); + for (TabPersistentStoreObserver observer : mObservers) { + observer.onMetadataSavedAsynchronously(mMetadata); + } + mMetadata = null; } } } private void onStateLoaded() { - if (mObserver != null) { + for (TabPersistentStoreObserver observer : mObservers) { // mergeState() starts an AsyncTask to call this and this calls // onTabStateInitialized which should be called from the UI thread. - ThreadUtils.runOnUiThread( () -> mObserver.onStateLoaded() ); + ThreadUtils.runOnUiThread(() -> observer.onStateLoaded()); } } @@ -1228,7 +1257,7 @@ for (String mergedFileName : new HashSet<String>(mMergedFileNames)) { deleteFileAsync(mergedFileName); } - if (mObserver != null) mObserver.onStateMerged(); + for (TabPersistentStoreObserver observer : mObservers) observer.onStateMerged(); } cleanUpPersistentData(); @@ -1410,8 +1439,16 @@ } @VisibleForTesting - public void setObserverForTesting(TabPersistentStoreObserver observer) { - mObserver = observer; + public void addObserver(TabPersistentStoreObserver observer) { + mObservers.addObserver(observer); + } + + /** + * Removes a {@link TabPersistentStoreObserver}. + * @param observer The {@link TabPersistentStoreObserver} to remove. + */ + public void removeObserver(TabPersistentStoreObserver observer) { + mObservers.removeObserver(observer); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 95f111c..00a8625 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -260,6 +260,12 @@ // TODO(yusufo): Consider not initializing these for WebAPKs. mBrowserSessionDataProvider = new BrowserSessionDataProvider(intent); mTrustedWebContentProvider = new TrustedWebContentProvider(); + + // When turning on TalkBack on Android, hitting app switcher to bring a WebappActivity to + // front will speak "Web App", which is the label of WebappActivity. Therefore, we set title + // of the WebappActivity explicitly to make it speak the short name of the Web App. + setTitle(mWebappInfo.shortName()); + super.preInflationStartup(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java index ce0649ed..c4e8628 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java
@@ -279,7 +279,7 @@ public byte[] call() throws Exception { TabModelSelectorImpl selectorImpl = buildTestTabModelSelector(new int[] {111, 222, 333}, null); - return TabPersistentStore.serializeTabModelSelector(selectorImpl, null); + return TabPersistentStore.serializeTabModelSelector(selectorImpl, null).listData; } }); FileOutputStream fos = null;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java index 53eef43..a1c9e8e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java
@@ -49,7 +49,8 @@ new Callable<byte[]>() { @Override public byte[] call() throws Exception { - return TabPersistentStore.serializeTabModelSelector(selector, null); + return TabPersistentStore.serializeTabModelSelector(selector, null) + .listData; } }); File f = TabbedModeTabPersistencePolicy.getOrCreateTabbedModeStateDirectory();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java index 7cbf6d6b..1ead798 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java
@@ -322,7 +322,7 @@ MockTabPersistentStoreObserver mockObserver = new MockTabPersistentStoreObserver(); TabModelSelectorImpl tabModelSelector = (TabModelSelectorImpl) mActivity2.getTabModelSelector(); - tabModelSelector.getTabPersistentStoreForTesting().setObserverForTesting(mockObserver); + tabModelSelector.getTabPersistentStoreForTesting().addObserver(mockObserver); // Merge tabs into ChromeTabbedActivity2. Wait for the merge to finish, ensuring the // tab metadata file for ChromeTabbedActivity gets deleted before attempting to merge
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java index 65ec5db..4d6a39e6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -37,6 +37,7 @@ import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; +import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelSelectorMetadata; import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver; import org.chromium.chrome.browser.tabmodel.TestTabModelDirectory.TabModelMetaDataInfo; import org.chromium.chrome.browser.test.ChromeBrowserTestRule; @@ -259,7 +260,7 @@ } @Override - public void onMetadataSavedAsynchronously() { + public void onMetadataSavedAsynchronously(TabModelSelectorMetadata metadata) { listWrittenCallback.notifyCalled(); } }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 6b9fdc5..9994a99 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -3379,6 +3379,18 @@ <message name="IDS_KEYBOARD_OVERLAY_BRIGHT_UP_KEY_LABEL" desc="The text in the keyboard overlay to show the label of the 'bright up' key that turns the screen's brightness up."> bright up </message> + <message name="IDS_KEYBOARD_OVERLAY_MOVE_WINDOW_TO_ABOVE_DISPLAY" desc="The text in the keyboard overlay to explain the shortcut (move active window to above display)."> + Window up + </message> + <message name="IDS_KEYBOARD_OVERLAY_MOVE_WINDOW_TO_BELOW_DISPLAY" desc="The text in the keyboard overlay to explain the shortcut (move active window to below display)."> + Window down + </message> + <message name="IDS_KEYBOARD_OVERLAY_MOVE_WINDOW_TO_LEFT_DISPLAY" desc="The text in the keyboard overlay to explain the shortcut (move active window to left display)."> + Window left + </message> + <message name="IDS_KEYBOARD_OVERLAY_MOVE_WINDOW_TO_RIGHT_DISPLAY" desc="The text in the keyboard overlay to explain the shortcut (move active window to right display)."> + Window right + </message> <message name="IDS_KEYBOARD_OVERLAY_MUTE_KEY_LABEL" desc="The text in the keyboard overlay to show the label of the 'mute' key that mutes the system's sound."> mute </message>
diff --git a/chrome/browser/chromeos/events/event_rewriter_unittest.cc b/chrome/browser/chromeos/events/event_rewriter_unittest.cc index e2e53566..3b298e5 100644 --- a/chrome/browser/chromeos/events/event_rewriter_unittest.cc +++ b/chrome/browser/chromeos/events/event_rewriter_unittest.cc
@@ -1365,19 +1365,7 @@ ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::DomKey::ARROW_DOWN}, {ui::VKEY_END, ui::DomCode::END, ui::EF_NONE, ui::DomKey::END}}, - // Search+Alt+Up -> Alt+Up - {ui::ET_KEY_PRESSED, - {ui::VKEY_UP, ui::DomCode::ARROW_UP, - ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::ARROW_UP}, - {ui::VKEY_UP, ui::DomCode::ARROW_UP, ui::EF_ALT_DOWN, - ui::DomKey::ARROW_UP}}, - // Search+Alt+Down -> Alt+Down - {ui::ET_KEY_PRESSED, - {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN, - ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, ui::DomKey::ARROW_DOWN}, - {ui::VKEY_DOWN, ui::DomCode::ARROW_DOWN, ui::EF_ALT_DOWN, - ui::DomKey::ARROW_DOWN}}, - // Search+Ctrl+Alt+Up -> Search+Ctrl+Alt+Up + // Search+Ctrl+Alt+Up -> Ctrl+Alt+Up {ui::ET_KEY_PRESSED, {ui::VKEY_UP, ui::DomCode::ARROW_UP, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
diff --git a/chrome/browser/previews/previews_browsertest.cc b/chrome/browser/previews/previews_browsertest.cc index ce4bbe9..afda20443 100644 --- a/chrome/browser/previews/previews_browsertest.cc +++ b/chrome/browser/previews/previews_browsertest.cc
@@ -55,7 +55,6 @@ } } - base::test::ScopedFeatureList scoped_feature_list_; net::EmbeddedTestServer https_server_; GURL test_url_; bool noscript_css_requested_; @@ -76,14 +75,15 @@ // This test class enables NoScriptPreviews via command line addition. class PreviewsNoScriptBrowserTest : public PreviewsBrowserTest { public: - PreviewsNoScriptBrowserTest() {} + PreviewsNoScriptBrowserTest() { + scoped_feature_list_.InitAndEnableFeature( + previews::features::kNoScriptPreviews); + } ~PreviewsNoScriptBrowserTest() override {} - void SetUpCommandLine(base::CommandLine* cmd) override { - PreviewsBrowserTest::SetUpCommandLine(cmd); - cmd->AppendSwitchASCII("enable-features", "NoScriptPreviews"); - } + private: + base::test::ScopedFeatureList scoped_feature_list_; }; // Previews InfoBar (which this test triggers) does not work on Mac.
diff --git a/chrome/browser/resources/chromeos/keyboard_overlay_data.js b/chrome/browser/resources/chromeos/keyboard_overlay_data.js index d064083e..98afa85 100644 --- a/chrome/browser/resources/chromeos/keyboard_overlay_data.js +++ b/chrome/browser/resources/chromeos/keyboard_overlay_data.js
@@ -4180,6 +4180,7 @@ 'd<>CTRL': 'keyboardOverlayBookmarkCurrentPage', 'd<>CTRL<>SHIFT': 'keyboardOverlayBookmarkAllTabs', 'down<>ALT': 'keyboardOverlayPageDown', + 'down<>ALT<>SEARCH': 'keyboardOverlayMoveWindowToBelowDisplay', 'down<>ALT<>CTRL': 'keyboardOverlayEnd', 'down<>SEARCH': 'keyboardOverlayPageDown', 'e<>ALT': 'keyboardOverlayShowWrenchMenu', @@ -4236,6 +4237,7 @@ 'l<>SEARCH': 'keyboardOverlayLockScreen', 'l<>SEARCH<>SHIFT': 'keyboardOverlaySuspend', 'left<>ALT': 'keyboardOverlayGoBack', + 'left<>ALT<>SEARCH': 'keyboardOverlayMoveWindowToLeftDisplay', 'left<>CTRL': 'keyboardOverlayPreviousWord', 'left<>CTRL<>SHIFT': 'keyboardOverlaySelectWordAtATime', 'left<>SEARCH': 'keyboardOverlayHome', @@ -4257,6 +4259,7 @@ 'reload<>CTRL<>SHIFT': 'keyboardOverlayRotateScreen', 'reload<>SEARCH': 'keyboardOverlayF3', 'right<>ALT': 'keyboardOverlayGoForward', + 'right<>ALT<>SEARCH': 'keyboardOverlayMoveWindowToRightDisplay', 'right<>CTRL': 'keyboardOverlayNextWord', 'right<>CTRL<>SHIFT': 'keyboardOverlaySelectWordAtATime', 'right<>SEARCH': 'keyboardOverlayEnd', @@ -4280,6 +4283,7 @@ 'u<>CTRL': 'keyboardOverlayViewSource', 'u<>CTRL<>SHIFT': 'keyboardOverlayInputUnicodeCharacters', 'up<>ALT': 'keyboardOverlayPageUp', + 'up<>ALT<>SEARCH': 'keyboardOverlayMoveWindowToAboveDisplay', 'up<>ALT<>CTRL': 'keyboardOverlayHome', 'up<>SEARCH': 'keyboardOverlayPageUp', 'v<>CTRL': 'keyboardOverlayPaste',
diff --git a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc index 762336e..5ee538c 100644 --- a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc +++ b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
@@ -208,6 +208,16 @@ {"keyboardOverlayMaximizeWindow", IDS_KEYBOARD_OVERLAY_MAXIMIZE_WINDOW}, {"keyboardOverlayMinimizeWindow", IDS_KEYBOARD_OVERLAY_MINIMIZE_WINDOW}, {"keyboardOverlayMirrorMonitors", IDS_KEYBOARD_OVERLAY_MIRROR_MONITORS}, + // TODO(warx): keyboard overlay name for move window between displays + // shortcuts need to be updated when new keyboard shortcuts helper is there. + {"keyboardOverlayMoveWindowToAboveDisplay", + IDS_KEYBOARD_OVERLAY_MOVE_WINDOW_TO_ABOVE_DISPLAY}, + {"keyboardOverlayMoveWindowToBelowDisplay", + IDS_KEYBOARD_OVERLAY_MOVE_WINDOW_TO_BELOW_DISPLAY}, + {"keyboardOverlayMoveWindowToLeftDisplay", + IDS_KEYBOARD_OVERLAY_MOVE_WINDOW_TO_LEFT_DISPLAY}, + {"keyboardOverlayMoveWindowToRightDisplay", + IDS_KEYBOARD_OVERLAY_MOVE_WINDOW_TO_RIGHT_DISPLAY}, {"keyboardOverlayNewIncognitoWindow", IDS_KEYBOARD_OVERLAY_NEW_INCOGNITO_WINDOW}, {"keyboardOverlayNewTab", IDS_KEYBOARD_OVERLAY_NEW_TAB},
diff --git a/components/autofill/ios/browser/autofill_client_ios.h b/components/autofill/ios/browser/autofill_client_ios.h index 30758ec..02da756f 100644 --- a/components/autofill/ios/browser/autofill_client_ios.h +++ b/components/autofill/ios/browser/autofill_client_ios.h
@@ -91,6 +91,9 @@ bool IsAutofillSupported() override; void ExecuteCommand(int id) override; + protected: + web::WebState* web_state() { return web_state_; } + private: PrefService* pref_service_; PersonalDataManager* personal_data_manager_;
diff --git a/components/autofill/ios/browser/autofill_client_ios.mm b/components/autofill/ios/browser/autofill_client_ios.mm index c6a030f..5803427 100644 --- a/components/autofill/ios/browser/autofill_client_ios.mm +++ b/components/autofill/ios/browser/autofill_client_ios.mm
@@ -142,9 +142,7 @@ } void AutofillClientIOS::DidInteractWithNonsecureCreditCardInput( - content::RenderFrameHost* rfh) { - web_state_->OnCreditCardInputShownOnHttp(); -} + content::RenderFrameHost* rfh) {} bool AutofillClientIOS::IsContextSecure() { // This implementation differs slightly from other platforms. Other platforms'
diff --git a/components/autofill/ios/browser/autofill_driver_ios.mm b/components/autofill/ios/browser/autofill_driver_ios.mm index d7fb2db..54f6012 100644 --- a/components/autofill/ios/browser/autofill_driver_ios.mm +++ b/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -84,8 +84,10 @@ } void AutofillDriverIOS::DidInteractWithCreditCardForm() { - if (!web::IsOriginSecure(web_state_->GetLastCommittedURL())) - web_state_->OnCreditCardInputShownOnHttp(); + if (!web::IsOriginSecure(web_state_->GetLastCommittedURL())) { + autofill_manager_.client()->DidInteractWithNonsecureCreditCardInput( + nullptr); + } } void AutofillDriverIOS::RendererShouldClearFilledForm() {
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc index 99effbf..decf9a18 100644 --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc
@@ -356,10 +356,13 @@ observer.OnWillChangeBookmarkNode(this, node); // The title index doesn't support changing the title, instead we remove then - // add it back. - index_->Remove(node); + // add it back. Only do this for URL nodes. A directory node can have its + // title changed but should be excluded from the index. + if (node->is_url()) + index_->Remove(node); AsMutable(node)->SetTitle(title); - index_->Add(node); + if (node->is_url()) + index_->Add(node); if (store_.get()) store_->ScheduleSave();
diff --git a/components/bookmarks/browser/bookmark_model_unittest.cc b/components/bookmarks/browser/bookmark_model_unittest.cc index a3b70780..bb5bd40 100644 --- a/components/bookmarks/browser/bookmark_model_unittest.cc +++ b/components/bookmarks/browser/bookmark_model_unittest.cc
@@ -25,6 +25,7 @@ #include "components/bookmarks/browser/bookmark_model_observer.h" #include "components/bookmarks/browser/bookmark_undo_delegate.h" #include "components/bookmarks/browser/bookmark_utils.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "components/bookmarks/test/bookmark_test_helpers.h" #include "components/bookmarks/test/test_bookmark_client.h" #include "components/favicon_base/favicon_callback.h" @@ -1200,6 +1201,24 @@ EXPECT_EQ(user, model_->GetMostRecentlyAddedUserNodeForURL(url)); } +// Verifies that renaming a bookmark folder does not add the folder node to the +// autocomplete index. crbug.com/778266 +TEST_F(BookmarkModelTest, RenamedFolderNodeExcludedFromIndex) { + // Add a folder. + const BookmarkNode* folder = + model_->AddFolder(model_->other_node(), 0, ASCIIToUTF16("MyFavorites")); + + // Change the folder title. + model_->SetTitle(folder, ASCIIToUTF16("MyBookmarks")); + + // There should be no matching bookmarks. + std::vector<TitledUrlMatch> matches; + model_->GetBookmarksMatching(ASCIIToUTF16("MyB"), /*max_count = */ 1, + query_parser::MatchingAlgorithm::DEFAULT, + &matches); + EXPECT_TRUE(matches.empty()); +} + TEST(BookmarkNodeTest, NodeMetaInfo) { GURL url; BookmarkNode node(url);
diff --git a/components/security_state/ios/BUILD.gn b/components/security_state/ios/BUILD.gn new file mode 100644 index 0000000..2e052ef --- /dev/null +++ b/components/security_state/ios/BUILD.gn
@@ -0,0 +1,16 @@ +# 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. + +source_set("ios") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "ssl_status_input_event_data.h", + "ssl_status_input_event_data.mm", + ] + deps = [ + "//base", + "//components/security_state/core/", + "//ios/web/public/", + ] +}
diff --git a/components/security_state/ios/DEPS b/components/security_state/ios/DEPS new file mode 100644 index 0000000..0eca071 --- /dev/null +++ b/components/security_state/ios/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+components/security_state/core", + "+ios/web/public", +]
diff --git a/components/security_state/ios/ssl_status_input_event_data.h b/components/security_state/ios/ssl_status_input_event_data.h new file mode 100644 index 0000000..f21113d --- /dev/null +++ b/components/security_state/ios/ssl_status_input_event_data.h
@@ -0,0 +1,40 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SECURITY_STATE_IOS_SSL_STATUS_INPUT_EVENT_DATA_H_ +#define COMPONENTS_SECURITY_STATE_IOS_SSL_STATUS_INPUT_EVENT_DATA_H_ + +#include <memory> + +#include "base/memory/ptr_util.h" +#include "components/security_state/core/insecure_input_event_data.h" +#include "ios/web/public/ssl_status.h" + +namespace security_state { + +using web::SSLStatus; + +// Stores flags about Input Events in the SSLStatus UserData to +// influence the Security Level of the page. +class SSLStatusInputEventData : public SSLStatus::UserData { + public: + SSLStatusInputEventData(); + explicit SSLStatusInputEventData( + const security_state::InsecureInputEventData& initial_data); + ~SSLStatusInputEventData() override; + + security_state::InsecureInputEventData* input_events(); + + // SSLStatus::UserData: + std::unique_ptr<SSLStatus::UserData> Clone() override; + + private: + security_state::InsecureInputEventData data_; + + DISALLOW_COPY_AND_ASSIGN(SSLStatusInputEventData); +}; + +} // namespace security_state + +#endif // COMPONENTS_SECURITY_STATE_IOS_SSL_STATUS_INPUT_EVENT_DATA_H_
diff --git a/components/security_state/ios/ssl_status_input_event_data.mm b/components/security_state/ios/ssl_status_input_event_data.mm new file mode 100644 index 0000000..3b84a2f --- /dev/null +++ b/components/security_state/ios/ssl_status_input_event_data.mm
@@ -0,0 +1,26 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/security_state/ios/ssl_status_input_event_data.h" + +namespace security_state { + +SSLStatusInputEventData::SSLStatusInputEventData() {} + +SSLStatusInputEventData::SSLStatusInputEventData( + const security_state::InsecureInputEventData& initial_data) + : data_(initial_data) {} + +SSLStatusInputEventData::~SSLStatusInputEventData() {} + +security_state::InsecureInputEventData* +SSLStatusInputEventData::input_events() { + return &data_; +} + +std::unique_ptr<web::SSLStatus::UserData> SSLStatusInputEventData::Clone() { + return base::MakeUnique<SSLStatusInputEventData>(data_); +} + +} // namespace security_state
diff --git a/components/translate/OWNERS b/components/translate/OWNERS index 3cf2d4d1..b481dc685 100644 --- a/components/translate/OWNERS +++ b/components/translate/OWNERS
@@ -2,11 +2,12 @@ # Android, CLD and language detection: andrewhayden@chromium.org # Componentization and iOS: droger@chromium.org # "Bubble" UI and translate internals: groby@chromium.org -# hajimehoshi@chromium.org +# hajimehoshi@chromium.org # CSP and isolated worlds: toyoshim@chromium.org andrewhayden@chromium.org droger@chromium.org groby@chromium.org hajimehoshi@chromium.org +martis@chromium.org napper@chromium.org toyoshim@chromium.org
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index e879c69..7a479a0 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -39,14 +39,14 @@ # on master.tryserver.chromium.linux with these. name: "master.tryserver.chromium.chromiumos" builders { name: "chromeos-amd64-generic-rel" } - #builders { - # name: "chromeos-daisy-rel" - # experiment_percentage: 3 - #} - #builders { - # name: "linux-chromeos-rel" - # experiment_percentage: 3 - #} + builders { + name: "chromeos-daisy-rel" + experiment_percentage: 50 + } + builders { + name: "linux-chromeos-rel" + experiment_percentage: 50 + } } buckets { name: "master.tryserver.chromium.linux"
diff --git a/ios/chrome/browser/autofill/BUILD.gn b/ios/chrome/browser/autofill/BUILD.gn index 4b1869af..379313f3 100644 --- a/ios/chrome/browser/autofill/BUILD.gn +++ b/ios/chrome/browser/autofill/BUILD.gn
@@ -119,9 +119,11 @@ "//components/autofill/ios/browser", "//components/infobars/core", "//components/keyed_service/core", + "//components/security_state/ios", "//ios/chrome/browser", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/infobars", + "//ios/chrome/browser/ssl", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/autofill", "//ios/chrome/browser/ui/settings:test_support",
diff --git a/ios/chrome/browser/autofill/autofill_controller_unittest.mm b/ios/chrome/browser/autofill/autofill_controller_unittest.mm index 33105b22..4f3640e 100644 --- a/ios/chrome/browser/autofill/autofill_controller_unittest.mm +++ b/ios/chrome/browser/autofill/autofill_controller_unittest.mm
@@ -23,10 +23,12 @@ #include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar_manager.h" #include "components/keyed_service/core/service_access_type.h" +#include "components/security_state/ios/ssl_status_input_event_data.h" #import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h" #import "ios/chrome/browser/autofill/form_suggestion_controller.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h" +#include "ios/chrome/browser/ssl/insecure_input_tab_helper.h" #import "ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h" #include "ios/chrome/browser/ui/settings/personal_data_manager_data_changed_observer.h" #import "ios/chrome/browser/web/chrome_web_test.h" @@ -120,7 +122,7 @@ // An HTML page without a card-type form. static NSString* kNoCreditCardFormHtml = - @"<h2>The rain in Spain stays <i>mainly</i> in the plain.</h2>"; + @"<input type=\"text\" autofocus autocomplete=\"username\"></form>"; // A credit card-type form with the autofocus attribute (which is detected at // page load). @@ -607,48 +609,63 @@ }; // Checks that an HTTP page containing a credit card results in a navigation -// entry with the "credit card displayed" bit set to true. -// TODO(crbug.com/689082): disabled due to flakyness. -TEST_F(AutofillControllerTest, DISABLED_HttpCreditCard) { +// entry with the "credit card interaction" bit set to true. +TEST_F(AutofillControllerTest, HttpCreditCard) { LoadHtml(kCreditCardAutofocusFormHtml, GURL("http://chromium.test")); + WaitForSuggestionRetrieval(); web::SSLStatus ssl_status = web_state()->GetNavigationManager()->GetLastCommittedItem()->GetSSL(); - EXPECT_TRUE(ssl_status.content_status & - web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl_status.user_data.get()); + EXPECT_TRUE(input_events && + input_events->input_events()->credit_card_field_edited); }; // Checks that an HTTP page without a credit card form does not result in a -// navigation entry with the "credit card displayed" bit set to true. +// navigation entry with the "credit card interaction" bit set to true. TEST_F(AutofillControllerTest, HttpNoCreditCard) { LoadHtml(kNoCreditCardFormHtml, GURL("http://chromium.test")); + WaitForSuggestionRetrieval(); web::SSLStatus ssl_status = web_state()->GetNavigationManager()->GetLastCommittedItem()->GetSSL(); - EXPECT_FALSE(ssl_status.content_status & - web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl_status.user_data.get()); + EXPECT_FALSE(input_events && + input_events->input_events()->credit_card_field_edited); }; // Checks that an HTTPS page containing a credit card form does not result in a -// navigation entry with the "credit card displayed" bit set to true. +// navigation entry with the "credit card interaction" bit set to true. TEST_F(AutofillControllerTest, HttpsCreditCard) { LoadHtml(kCreditCardAutofocusFormHtml, GURL("https://chromium.test")); + WaitForSuggestionRetrieval(); web::SSLStatus ssl_status = web_state()->GetNavigationManager()->GetLastCommittedItem()->GetSSL(); - EXPECT_FALSE(ssl_status.content_status & - web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl_status.user_data.get()); + EXPECT_FALSE(input_events && + input_events->input_events()->credit_card_field_edited); }; // Checks that an HTTPS page without a credit card form does not result in a -// navigation entry with the "credit card displayed" bit set to true. +// navigation entry with the "credit card interaction" bit set to true. TEST_F(AutofillControllerTest, HttpsNoCreditCard) { LoadHtml(kNoCreditCardFormHtml, GURL("https://chromium.test")); + WaitForSuggestionRetrieval(); web::SSLStatus ssl_status = web_state()->GetNavigationManager()->GetLastCommittedItem()->GetSSL(); - EXPECT_FALSE(ssl_status.content_status & - web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl_status.user_data.get()); + EXPECT_FALSE(input_events && + input_events->input_events()->credit_card_field_edited); }; } // namespace
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn index 4da33a7..4bedc8a 100644 --- a/ios/chrome/browser/passwords/BUILD.gn +++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -131,6 +131,7 @@ "//components/password_manager/core/common", "//components/prefs", "//components/prefs:test_support", + "//components/security_state/ios", "//google_apis", "//ios/chrome/browser/autofill", "//ios/chrome/browser/browser_state:test_support",
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index 6cd92ed..72f845f 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -41,6 +41,7 @@ #import "ios/chrome/browser/passwords/js_password_manager.h" #import "ios/chrome/browser/passwords/notify_auto_signin_view_controller.h" #import "ios/chrome/browser/passwords/password_form_filler.h" +#import "ios/chrome/browser/ssl/insecure_input_tab_helper.h" #include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #include "ios/chrome/browser/web/tab_id_tab_helper.h" @@ -632,7 +633,8 @@ if (webStateObserverBridge_) { web::WebState* web_state = webStateObserverBridge_->web_state(); if (web_state && !web::IsOriginSecure(web_state->GetLastCommittedURL())) { - web_state->OnPasswordInputShownOnHttp(); + InsecureInputTabHelper::GetOrCreateForWebState(web_state) + ->DidShowPasswordFieldInInsecureContext(); } }
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index f3d3718..772f8174 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -25,11 +25,13 @@ #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" +#include "components/security_state/ios/ssl_status_input_event_data.h" #import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h" #import "ios/chrome/browser/autofill/form_suggestion_controller.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/passwords/js_password_manager.h" #import "ios/chrome/browser/passwords/password_form_filler.h" +#import "ios/chrome/browser/ssl/insecure_input_tab_helper.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/ssl_status.h" @@ -1331,47 +1333,59 @@ } // Tests that an HTTP page without a password field does not update the SSL -// status to indicate DISPLAYED_PASSWORD_FIELD_ON_HTTP. +// status to indicate |password_field_shown|. TEST_F(PasswordControllerTest, HTTPNoPassword) { LoadHtml(kHtmlWithoutPasswordForm, GURL("http://chromium.test")); web::SSLStatus ssl_status = web_state()->GetNavigationManager()->GetLastCommittedItem()->GetSSL(); - EXPECT_FALSE(ssl_status.content_status & - web::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl_status.user_data.get()); + EXPECT_FALSE(input_events && + input_events->input_events()->password_field_shown); } // Tests that an HTTP page with a password field updates the SSL status -// to indicate DISPLAYED_PASSWORD_FIELD_ON_HTTP. +// to indicate |password_field_shown|. TEST_F(PasswordControllerTest, HTTPPassword) { LoadHtml(kHtmlWithPasswordForm, GURL("http://chromium.test")); web::SSLStatus ssl_status = web_state()->GetNavigationManager()->GetLastCommittedItem()->GetSSL(); - EXPECT_TRUE(ssl_status.content_status & - web::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl_status.user_data.get()); + ASSERT_TRUE(input_events); + EXPECT_TRUE(input_events->input_events()->password_field_shown); } // Tests that an HTTPS page without a password field does not update the SSL -// status to indicate DISPLAYED_PASSWORD_FIELD_ON_HTTP. +// status to indicate |password_field_shown|. TEST_F(PasswordControllerTest, HTTPSNoPassword) { LoadHtml(kHtmlWithoutPasswordForm, GURL("https://chromium.test")); web::SSLStatus ssl_status = web_state()->GetNavigationManager()->GetLastCommittedItem()->GetSSL(); - EXPECT_FALSE(ssl_status.content_status & - web::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl_status.user_data.get()); + EXPECT_FALSE(input_events && + input_events->input_events()->password_field_shown); } // Tests that an HTTPS page with a password field does not update the SSL status -// to indicate DISPLAYED_PASSWORD_FIELD_ON_HTTP. +// to indicate |password_field_shown|. TEST_F(PasswordControllerTest, HTTPSPassword) { LoadHtml(kHtmlWithPasswordForm, GURL("https://chromium.test")); web::SSLStatus ssl_status = web_state()->GetNavigationManager()->GetLastCommittedItem()->GetSSL(); - EXPECT_FALSE(ssl_status.content_status & - web::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl_status.user_data.get()); + EXPECT_FALSE(input_events && + input_events->input_events()->password_field_shown); } // Checks that when the user set a focus on a field of a password form which was
diff --git a/ios/chrome/browser/ssl/BUILD.gn b/ios/chrome/browser/ssl/BUILD.gn index 3be96a6..aa3b294 100644 --- a/ios/chrome/browser/ssl/BUILD.gn +++ b/ios/chrome/browser/ssl/BUILD.gn
@@ -8,6 +8,8 @@ "captive_portal_detector_tab_helper.h", "captive_portal_detector_tab_helper.mm", "captive_portal_detector_tab_helper_delegate.h", + "insecure_input_tab_helper.h", + "insecure_input_tab_helper.mm", "ios_captive_portal_blocking_page.h", "ios_captive_portal_blocking_page.mm", "ios_security_state_tab_helper.h", @@ -24,6 +26,7 @@ "//components/captive_portal", "//components/security_interstitials/core", "//components/security_state/core", + "//components/security_state/ios", "//components/strings", "//components/url_formatter", "//ios/chrome/app/strings", @@ -55,10 +58,12 @@ testonly = true sources = [ "ios_captive_portal_blocking_page_unittest.mm", + "ios_security_state_tab_helper_unittest.mm", "ios_ssl_error_handler_unittest.mm", ] deps = [ ":ssl", + "//components/security_state/core", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/web:test_support", "//ios/testing:ios_test_support",
diff --git a/ios/chrome/browser/ssl/insecure_input_tab_helper.h b/ios/chrome/browser/ssl/insecure_input_tab_helper.h new file mode 100644 index 0000000..7fddf26 --- /dev/null +++ b/ios/chrome/browser/ssl/insecure_input_tab_helper.h
@@ -0,0 +1,53 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_SSL_INSECURE_INPUT_TAB_HELPER_H_ +#define IOS_CHROME_BROWSER_SSL_INSECURE_INPUT_TAB_HELPER_H_ + +#include <string> + +#include "base/macros.h" +#include "ios/web/public/web_state/web_state_observer.h" +#import "ios/web/public/web_state/web_state_user_data.h" + +// Observes user activity on forms and receives notifications about page content +// from autofill and updates the page's |SSLStatusUserData| to track insecure +// input events. Such events may change the page's Security Level. +class InsecureInputTabHelper + : public web::WebStateObserver, + public web::WebStateUserData<InsecureInputTabHelper> { + public: + ~InsecureInputTabHelper() override; + + static InsecureInputTabHelper* GetOrCreateForWebState( + web::WebState* web_state); + + // This method should be called when a form containing a password field is + // parsed in a non-secure context. + void DidShowPasswordFieldInInsecureContext(); + + // This method should be called when the autofill component detects a credit + // card field was interacted with in a non-secure context. + void DidInteractWithNonsecureCreditCardInput(); + + // This method should be called when the user edits a field in a non-secure + // context. + void DidEditFieldInInsecureContext(); + + private: + friend class web::WebStateUserData<InsecureInputTabHelper>; + explicit InsecureInputTabHelper(web::WebState* web_state); + + // WebStateObserver implementation. + void FormActivityRegistered(web::WebState* web_state, + const std::string& form_name, + const std::string& field_name, + const std::string& type, + const std::string& value, + bool input_missing) override; + + DISALLOW_COPY_AND_ASSIGN(InsecureInputTabHelper); +}; + +#endif // IOS_CHROME_BROWSER_SSL_INSECURE_INPUT_TAB_HELPER_H_
diff --git a/ios/chrome/browser/ssl/insecure_input_tab_helper.mm b/ios/chrome/browser/ssl/insecure_input_tab_helper.mm new file mode 100644 index 0000000..e1264bb --- /dev/null +++ b/ios/chrome/browser/ssl/insecure_input_tab_helper.mm
@@ -0,0 +1,128 @@ +// 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. + +#import "ios/chrome/browser/ssl/insecure_input_tab_helper.h" + +#import <Foundation/Foundation.h> + +#include "base/memory/ptr_util.h" +#include "components/security_state/ios/ssl_status_input_event_data.h" +#import "ios/web/public/navigation_item.h" +#import "ios/web/public/navigation_manager.h" +#import "ios/web/public/origin_util.h" +#import "ios/web/public/web_state/web_state.h" +#import "ios/web/public/web_state/web_state_user_data.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +// Creates or retrieves the |user_data| object in the SSLStatus attached to the +// WebState's NavigationItem. +security_state::SSLStatusInputEventData* GetOrCreateSSLStatusInputEventData( + web::WebState* web_state) { + web::NavigationItem* item = + web_state->GetNavigationManager()->GetLastCommittedItem(); + + // We aren't guaranteed to always have a navigation item. + if (!item) + return nullptr; + + web::SSLStatus& ssl = item->GetSSL(); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl.user_data.get()); + if (!input_events) { + ssl.user_data = base::MakeUnique<security_state::SSLStatusInputEventData>(); + input_events = static_cast<security_state::SSLStatusInputEventData*>( + ssl.user_data.get()); + } + return input_events; +} + +} // namespace + +DEFINE_WEB_STATE_USER_DATA_KEY(InsecureInputTabHelper); + +InsecureInputTabHelper::~InsecureInputTabHelper() = default; + +// static +InsecureInputTabHelper* InsecureInputTabHelper::GetOrCreateForWebState( + web::WebState* web_state) { + InsecureInputTabHelper* helper = FromWebState(web_state); + if (!helper) { + CreateForWebState(web_state); + helper = FromWebState(web_state); + DCHECK(helper); + } + return helper; +} + +void InsecureInputTabHelper::DidShowPasswordFieldInInsecureContext() { + DCHECK(!web::IsOriginSecure(web_state()->GetLastCommittedURL())); + + security_state::SSLStatusInputEventData* input_events = + GetOrCreateSSLStatusInputEventData(web_state()); + if (!input_events) + return; + + // If the first password field for the web contents was just + // shown, update the SSLStatusInputEventData. + if (!input_events->input_events()->password_field_shown) { + input_events->input_events()->password_field_shown = true; + web_state()->DidChangeVisibleSecurityState(); + } +} + +void InsecureInputTabHelper::DidInteractWithNonsecureCreditCardInput() { + DCHECK(!web::IsOriginSecure(web_state()->GetLastCommittedURL())); + + security_state::SSLStatusInputEventData* input_events = + GetOrCreateSSLStatusInputEventData(web_state()); + if (!input_events) + return; + + // If the first credit card field for the web contents was just + // shown, update the SSLStatusInputEventData. + if (!input_events->input_events()->credit_card_field_edited) { + input_events->input_events()->credit_card_field_edited = true; + web_state()->DidChangeVisibleSecurityState(); + } +} + +void InsecureInputTabHelper::DidEditFieldInInsecureContext() { + DCHECK(!web::IsOriginSecure(web_state()->GetLastCommittedURL())); + + security_state::SSLStatusInputEventData* input_events = + GetOrCreateSSLStatusInputEventData(web_state()); + if (!input_events) + return; + + // If the first field edit in the web contents was just performed, + // update the SSLStatusInputEventData. + if (!input_events->input_events()->insecure_field_edited) { + input_events->input_events()->insecure_field_edited = true; + web_state()->DidChangeVisibleSecurityState(); + } +} + +InsecureInputTabHelper::InsecureInputTabHelper(web::WebState* web_state) + : web::WebStateObserver(web_state) { + DCHECK(web_state); +} + +void InsecureInputTabHelper::FormActivityRegistered( + web::WebState* web_state, + const std::string& form_name, + const std::string& field_name, + const std::string& type, + const std::string& value, + bool input_missing) { + if (type == "input" && + !web::IsOriginSecure(web_state->GetLastCommittedURL())) { + DidEditFieldInInsecureContext(); + } +}
diff --git a/ios/chrome/browser/ssl/ios_security_state_tab_helper.mm b/ios/chrome/browser/ssl/ios_security_state_tab_helper.mm index 7a76ea49..68659a69 100644 --- a/ios/chrome/browser/ssl/ios_security_state_tab_helper.mm +++ b/ios/chrome/browser/ssl/ios_security_state_tab_helper.mm
@@ -10,6 +10,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" #include "components/security_state/core/security_state.h" +#include "components/security_state/ios/ssl_status_input_event_data.h" #include "ios/web/public/browser_state.h" #include "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" @@ -55,15 +56,13 @@ state->displayed_mixed_content = (ssl.content_status & web::SSLStatus::DISPLAYED_INSECURE_CONTENT) ? true : false; - state->insecure_input_events.password_field_shown = - (ssl.content_status & web::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP) - ? true - : false; - state->insecure_input_events.credit_card_field_edited = - (ssl.content_status & web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP) - ? true - : false; state->is_incognito = web_state_->GetBrowserState()->IsOffTheRecord(); + security_state::SSLStatusInputEventData* input_events = + static_cast<security_state::SSLStatusInputEventData*>( + ssl.user_data.get()); + if (input_events) + state->insecure_input_events = *input_events->input_events(); + return state; }
diff --git a/ios/chrome/browser/ssl/ios_security_state_tab_helper_unittest.mm b/ios/chrome/browser/ssl/ios_security_state_tab_helper_unittest.mm new file mode 100644 index 0000000..533c7195 --- /dev/null +++ b/ios/chrome/browser/ssl/ios_security_state_tab_helper_unittest.mm
@@ -0,0 +1,84 @@ +// 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. + +#import "ios/chrome/browser/ssl/ios_security_state_tab_helper.h" + +#include "components/security_state/core/security_state.h" +#import "ios/chrome/browser/ssl/insecure_input_tab_helper.h" +#import "ios/web/public/navigation_item.h" +#import "ios/web/public/navigation_manager.h" +#include "ios/web/public/ssl_status.h" +#import "ios/web/public/test/web_test_with_web_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// This test fixture creates an IOSSecurityStateTabHelper and an +// InsecureInputTabHelper for the WebState, then loads a non-secure +// HTML document. +class IOSSecurityStateTabHelperTest : public web::WebTestWithWebState { + protected: + void SetUp() override { + web::WebTestWithWebState::SetUp(); + InsecureInputTabHelper::CreateForWebState(web_state()); + insecure_input_ = InsecureInputTabHelper::FromWebState(web_state()); + ASSERT_TRUE(insecure_input_); + + IOSSecurityStateTabHelper::CreateForWebState(web_state()); + LoadHtml(@"<html><body></body></html>", GURL("http://chromium.test")); + } + + // Returns the InsecureInputEventData for current WebState(). + security_state::InsecureInputEventData GetInsecureInput() const { + security_state::SecurityInfo info; + IOSSecurityStateTabHelper::FromWebState(web_state()) + ->GetSecurityInfo(&info); + return info.insecure_input_events; + } + + InsecureInputTabHelper* insecure_input_; +}; + +// Ensures that |insecure_field_edited| is set only when an editing event has +// been reported. +TEST_F(IOSSecurityStateTabHelperTest, SecurityInfoAfterEditing) { + // Verify |insecure_field_edited| is not set prematurely. + security_state::InsecureInputEventData events = GetInsecureInput(); + EXPECT_FALSE(events.insecure_field_edited); + + // Simulate an edit and verify |insecure_field_edited| is noted in the + // insecure_input_events. + insecure_input_->DidEditFieldInInsecureContext(); + events = GetInsecureInput(); + EXPECT_TRUE(events.insecure_field_edited); +} + +// Ensures that |password_field_shown| is set only when a password field has +// been reported. +TEST_F(IOSSecurityStateTabHelperTest, SecurityInfoWithInsecurePasswordField) { + // Verify |password_field_shown| is not set prematurely. + security_state::InsecureInputEventData events = GetInsecureInput(); + EXPECT_FALSE(events.password_field_shown); + + // Simulate a password field display and verify |password_field_shown| + // is noted in the insecure_input_events. + insecure_input_->DidShowPasswordFieldInInsecureContext(); + events = GetInsecureInput(); + EXPECT_TRUE(events.password_field_shown); +} + +// Ensures that |credit_card_field_edited| is set only when a credit card field +// interaction has been reported. +TEST_F(IOSSecurityStateTabHelperTest, SecurityInfoWithInsecureCreditCardField) { + // Verify |credit_card_field_edited| is not set prematurely. + security_state::InsecureInputEventData events = GetInsecureInput(); + EXPECT_FALSE(events.credit_card_field_edited); + + // Simulate a credit card field display and verify |credit_card_field_edited| + // is noted in the insecure_input_events. + insecure_input_->DidInteractWithNonsecureCreditCardInput(); + events = GetInsecureInput(); + EXPECT_TRUE(events.credit_card_field_edited); +}
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm index fcb73e9..e85ca331 100644 --- a/ios/chrome/browser/tabs/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -29,6 +29,7 @@ #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/reading_list/reading_list_web_state_observer.h" #import "ios/chrome/browser/sessions/ios_chrome_session_tab_helper.h" +#import "ios/chrome/browser/ssl/insecure_input_tab_helper.h" #import "ios/chrome/browser/ssl/ios_security_state_tab_helper.h" #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" #import "ios/chrome/browser/sync/ios_chrome_synced_tab_delegate.h" @@ -119,6 +120,8 @@ ->GetAccessoryViewProvider(), ]); + InsecureInputTabHelper::CreateForWebState(web_state); + // Allow the embedder to attach tab helpers. ios::GetChromeBrowserProvider()->AttachTabHelpers(web_state, tab);
diff --git a/ios/chrome/browser/ui/autofill/BUILD.gn b/ios/chrome/browser/ui/autofill/BUILD.gn index 628ff9eb..02a46ae 100644 --- a/ios/chrome/browser/ui/autofill/BUILD.gn +++ b/ios/chrome/browser/ui/autofill/BUILD.gn
@@ -31,6 +31,7 @@ "//ios/chrome/browser/autofill", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/infobars", + "//ios/chrome/browser/ssl", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/autofill/cells", "//ios/chrome/browser/ui/collection_view/cells",
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h index 60f2f38..798df62 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
@@ -67,6 +67,8 @@ void PropagateAutofillPredictions( content::RenderFrameHost* rfh, const std::vector<FormStructure*>& forms) override; + void DidInteractWithNonsecureCreditCardInput( + content::RenderFrameHost* rfh) override; private: infobars::InfoBarManager* infobar_manager_;
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm index d407b3d0..a3fc5a4 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -24,9 +24,11 @@ #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/infobars/infobar_utils.h" +#import "ios/chrome/browser/ssl/insecure_input_tab_helper.h" #include "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h" #include "ios/chrome/browser/web_data_service_factory.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/web/public/web_state/web_state.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -128,4 +130,10 @@ } } +void ChromeAutofillClientIOS::DidInteractWithNonsecureCreditCardInput( + content::RenderFrameHost* rfh) { + InsecureInputTabHelper::GetOrCreateForWebState(web_state()) + ->DidInteractWithNonsecureCreditCardInput(); +} + } // namespace autofill
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index a4253c9..a0dec62 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -347,6 +347,7 @@ "public/origin_util_unittest.mm", "public/referrer_util_unittest.cc", "public/serializable_user_data_manager_unittest.mm", + "public/ssl_status_unittest.cc", "public/user_agent_unittest.mm", "public/web_state/page_viewport_state_unittest.mm", ]
diff --git a/ios/web/public/ssl_status.cc b/ios/web/public/ssl_status.cc index f2abd73a..c7513c6 100644 --- a/ios/web/public/ssl_status.cc +++ b/ios/web/public/ssl_status.cc
@@ -13,7 +13,25 @@ content_status(NORMAL_CONTENT) { } -SSLStatus::SSLStatus(const SSLStatus& other) = default; +SSLStatus::SSLStatus(const SSLStatus& other) + : security_style(other.security_style), + certificate(other.certificate), + cert_status(other.cert_status), + connection_status(other.connection_status), + content_status(other.content_status), + cert_status_host(other.cert_status_host), + user_data(other.user_data ? other.user_data->Clone() : nullptr) {} + +SSLStatus& SSLStatus::operator=(SSLStatus other) { + security_style = other.security_style; + certificate = other.certificate; + cert_status = other.cert_status; + connection_status = other.connection_status; + content_status = other.content_status; + cert_status_host = other.cert_status_host; + user_data = other.user_data ? other.user_data->Clone() : nullptr; + return *this; +} SSLStatus::~SSLStatus() {}
diff --git a/ios/web/public/ssl_status.h b/ios/web/public/ssl_status.h index 12848fc..1c5df45 100644 --- a/ios/web/public/ssl_status.h +++ b/ios/web/public/ssl_status.h
@@ -5,6 +5,7 @@ #ifndef IOS_WEB_PUBLIC_SSL_STATUS_H_ #define IOS_WEB_PUBLIC_SSL_STATUS_H_ +#include <memory> #include <string> #include "ios/web/public/security_style.h" @@ -15,6 +16,20 @@ // Collects the SSL information for this NavigationItem. struct SSLStatus { + // SSLStatus consumers can attach instances of derived UserData classes to an + // SSLStatus. This allows an embedder to attach data to the NavigationItem + // without SSLStatus having to know about it. Derived UserData classes have to + // be cloneable since NavigationItems are cloned during navigations. + class UserData { + public: + UserData() {} + virtual ~UserData() = default; + virtual std::unique_ptr<UserData> Clone() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(UserData); + }; + // Flags used for the page security content status. enum ContentStatusFlags { // HTTP page, or HTTPS page with no insecure content. @@ -25,18 +40,11 @@ // The RAN_INSECURE_CONTENT flag is intentionally omitted on iOS because // there is no way to tell when insecure content is run in a web view. - - // HTTP page containing a password input, used to adjust UI on nonsecure - // pages that collect sensitive data. - DISPLAYED_PASSWORD_FIELD_ON_HTTP = 1 << 4, - - // HTTP page containing a credit card input, used to adjust UI on nonsecure - // pages that collect sensitive data. - DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP = 1 << 5, }; SSLStatus(); SSLStatus(const SSLStatus& other); + SSLStatus& operator=(SSLStatus other); ~SSLStatus(); bool Equals(const SSLStatus& status) const { @@ -47,6 +55,7 @@ cert_status == status.cert_status && content_status == status.content_status; // |cert_status_host| is not used for comparison intentionally. + // |user_data| also not used for comparison. } web::SecurityStyle security_style; @@ -60,6 +69,10 @@ // Used to check if |cert_status| is still valid or needs to be recalculated // (e.g. after redirect). std::string cert_status_host; + // Embedder-specific data attached to the SSLStatus is cloned when an + // |SSLStatus| is assigned or copy-constructed, and is cleared when a + // navigation commits. + std::unique_ptr<UserData> user_data; }; } // namespace web
diff --git a/ios/web/public/ssl_status_unittest.cc b/ios/web/public/ssl_status_unittest.cc new file mode 100644 index 0000000..53588a8f --- /dev/null +++ b/ios/web/public/ssl_status_unittest.cc
@@ -0,0 +1,78 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/web/public/ssl_status.h" + +#include "base/memory/ptr_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace web { + +using SSLStatusTest = PlatformTest; + +// The TrivialUserData class stores an integer and copies that integer when +// its Clone() method is called. +class TrivialUserData : public SSLStatus::UserData { + public: + TrivialUserData() : value_(0) {} + explicit TrivialUserData(int value) : value_(value) {} + ~TrivialUserData() override {} + + int value() { return value_; } + + std::unique_ptr<SSLStatus::UserData> Clone() override { + return base::MakeUnique<TrivialUserData>(value_); + } + + private: + int value_; + DISALLOW_COPY_AND_ASSIGN(TrivialUserData); +}; + +// Tests the Equals() method of the SSLStatus class. +TEST_F(SSLStatusTest, SSLStatusEqualityTest) { + SSLStatus status; + EXPECT_EQ(SECURITY_STYLE_UNKNOWN, status.security_style); + EXPECT_EQ(0u, status.cert_status); + EXPECT_EQ(0, status.connection_status); + EXPECT_EQ(SSLStatus::NORMAL_CONTENT, status.content_status); + + // Verify that the Equals() method returns false if two SSLStatus objects + // have different ContentStatusFlags. + SSLStatus other_status; + other_status.content_status = + SSLStatus::ContentStatusFlags::DISPLAYED_INSECURE_CONTENT; + EXPECT_FALSE(status.Equals(other_status)); + EXPECT_FALSE(other_status.Equals(status)); + + // Verify a copied SSLStatus Equals() the original. + SSLStatus copied_status = status; + EXPECT_TRUE(status.Equals(copied_status)); + EXPECT_TRUE(copied_status.Equals(status)); + + // Verify a copied SSLStatus still Equals() the original after a UserData is + // assigned to it. + copied_status.user_data = base::MakeUnique<TrivialUserData>(); + EXPECT_TRUE(status.Equals(copied_status)); + EXPECT_TRUE(copied_status.Equals(status)); +} + +// Tests that copying a SSLStatus class clones its UserData. +TEST_F(SSLStatusTest, SSLStatusCloningTest) { + const int kMagic = 1234; + SSLStatus status; + status.user_data = base::MakeUnique<TrivialUserData>(kMagic); + + // Verify that copying a SSLStatus with a UserData assigned will Clone() + // the UserData to the new copy. + SSLStatus copied_status = status; + EXPECT_TRUE(status.Equals(copied_status)); + EXPECT_TRUE(copied_status.Equals(status)); + TrivialUserData* data = + static_cast<TrivialUserData*>(copied_status.user_data.get()); + EXPECT_EQ(kMagic, data->value()); +} + +} // namespace web
diff --git a/ios/web/public/test/fakes/test_web_state.h b/ios/web/public/test/fakes/test_web_state.h index fce4734..57f5bec 100644 --- a/ios/web/public/test/fakes/test_web_state.h +++ b/ios/web/public/test/fakes/test_web_state.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <memory> #include <string> #include "base/observer_list.h" @@ -70,8 +71,6 @@ CRWWebViewProxyType GetWebViewProxy() const override; bool IsShowingWebInterstitial() const override; WebInterstitial* GetWebInterstitial() const override; - void OnPasswordInputShownOnHttp() override {} - void OnCreditCardInputShownOnHttp() override {} void AddObserver(WebStateObserver* observer) override; @@ -80,6 +79,7 @@ void AddPolicyDecider(WebStatePolicyDecider* decider) override {} void RemovePolicyDecider(WebStatePolicyDecider* decider) override {} WebStateInterfaceProvider* GetWebStateInterfaceProvider() override; + void DidChangeVisibleSecurityState() override {} bool HasOpener() const override; void SetHasOpener(bool has_opener) override; void TakeSnapshot(const SnapshotCallback& callback,
diff --git a/ios/web/public/web_state/web_state.h b/ios/web/public/web_state/web_state.h index 527e740..ddc9bbf 100644 --- a/ios/web/public/web_state/web_state.h +++ b/ios/web/public/web_state/web_state.h
@@ -7,7 +7,9 @@ #include <stdint.h> +#include <memory> #include <string> +#include <utility> #include <vector> #include "base/callback_forward.h" @@ -234,16 +236,6 @@ // Returns the currently visible WebInterstitial if one is shown. virtual WebInterstitial* GetWebInterstitial() const = 0; - // Called when the WebState has displayed a password field on an HTTP page. - // This method modifies the appropriate NavigationEntry's SSLStatus to record - // the sensitive input field, so that embedders can adjust the UI if desired. - virtual void OnPasswordInputShownOnHttp() = 0; - - // Called when the WebState has displayed a credit card field on an HTTP page. - // This method modifies the appropriate NavigationEntry's SSLStatus to record - // the sensitive input field, so that embedders can adjust the UI if desired. - virtual void OnCreditCardInputShownOnHttp() = 0; - // Callback used to handle script commands. // The callback must return true if the command was handled, and false // otherwise. @@ -270,6 +262,15 @@ // Returns Mojo interface registry for this WebState. virtual WebStateInterfaceProvider* GetWebStateInterfaceProvider() = 0; + // Typically an embedder will: + // - Implement this method to receive notification of changes to the page's + // |VisibleSecurityState|, updating security UI (e.g. a lock icon) to + // reflect the current security state of the page. + // ...and optionally: + // - Invoke this method upon detection of an event that will change + // the security state (e.g. a non-secure form element is edited). + virtual void DidChangeVisibleSecurityState() = 0; + protected: // Binds |interface_pipe| to an implementation of |interface_name| that is // scoped to this WebState instance (if that such an implementation is
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h index 4833accf2..5b9b054 100644 --- a/ios/web/web_state/ui/crw_web_controller.h +++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -212,14 +212,6 @@ // Notifies the CRWWebController that it has been shown. - (void)wasShown; -// Notifies the CRWWebController that the current page is an HTTP page -// containing a password field. -- (void)didShowPasswordInputOnHTTP; - -// Notifies the CRWWebController that the current page is an HTTP page -// containing a credit card field. -- (void)didShowCreditCardInputOnHTTP; - // Notifies the CRWWebController that it has been hidden. - (void)wasHidden;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index d1e496eb..f66028f 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -3699,24 +3699,6 @@ hasOnlySecureContent:hasOnlySecureContent]; } -- (void)didShowPasswordInputOnHTTP { - DCHECK(!web::IsOriginSecure(self.webState->GetLastCommittedURL())); - web::NavigationItem* item = - _webStateImpl->GetNavigationManager()->GetLastCommittedItem(); - item->GetSSL().content_status |= - web::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP; - _webStateImpl->OnVisibleSecurityStateChange(); -} - -- (void)didShowCreditCardInputOnHTTP { - DCHECK(!web::IsOriginSecure(self.webState->GetLastCommittedURL())); - web::NavigationItem* item = - _webStateImpl->GetNavigationManager()->GetLastCommittedItem(); - item->GetSSL().content_status |= - web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP; - _webStateImpl->OnVisibleSecurityStateChange(); -} - - (void)handleSSLCertError:(NSError*)error forNavigation:(WKNavigation*)navigation { CHECK(web::IsWKWebViewSSLCertError(error)); @@ -3792,7 +3774,7 @@ } })); - _webStateImpl->OnVisibleSecurityStateChange(); + _webStateImpl->DidChangeVisibleSecurityState(); [self loadCancelled]; } @@ -4760,7 +4742,7 @@ web::NavigationItem* lastCommittedNavigationItem = _webStateImpl->GetNavigationManager()->GetLastCommittedItem(); if (navigationItem == lastCommittedNavigationItem) { - _webStateImpl->OnVisibleSecurityStateChange(); + _webStateImpl->DidChangeVisibleSecurityState(); } }
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm index dcca2b3f..95018df4 100644 --- a/ios/web/web_state/ui/crw_web_controller_unittest.mm +++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -512,40 +512,6 @@ // Test fixture for testing visible security state. typedef WebTestWithWebState CRWWebStateSecurityStateTest; -// Tests that OnPasswordInputShownOnHttp updates the SSLStatus to indicate that -// a password field has been displayed on an HTTP page. -TEST_F(CRWWebStateSecurityStateTest, HttpPassword) { - LoadHtml(@"<html><body></body></html>", GURL("http://chromium.test")); - NavigationManager* nav_manager = web_state()->GetNavigationManager(); - EXPECT_FALSE(nav_manager->GetLastCommittedItem()->GetSSL().content_status & - SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); - TestWebStateObserver observer(web_state()); - ASSERT_FALSE(observer.did_change_visible_security_state_info()); - web_state()->OnPasswordInputShownOnHttp(); - EXPECT_TRUE(nav_manager->GetLastCommittedItem()->GetSSL().content_status & - SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); - ASSERT_TRUE(observer.did_change_visible_security_state_info()); - EXPECT_EQ(web_state(), - observer.did_change_visible_security_state_info()->web_state); -} - -// Tests that OnCreditCardInputShownOnHttp updates the SSLStatus to indicate -// that a credit card field has been displayed on an HTTP page. -TEST_F(CRWWebStateSecurityStateTest, HttpCreditCard) { - LoadHtml(@"<html><body></body></html>", GURL("http://chromium.test")); - NavigationManager* nav_manager = web_state()->GetNavigationManager(); - EXPECT_FALSE(nav_manager->GetLastCommittedItem()->GetSSL().content_status & - SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP); - TestWebStateObserver observer(web_state()); - ASSERT_FALSE(observer.did_change_visible_security_state_info()); - web_state()->OnCreditCardInputShownOnHttp(); - EXPECT_TRUE(nav_manager->GetLastCommittedItem()->GetSSL().content_status & - SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP); - ASSERT_TRUE(observer.did_change_visible_security_state_info()); - EXPECT_EQ(web_state(), - observer.did_change_visible_security_state_info()->web_state); -} - // Tests that loading HTTP page updates the SSLStatus. TEST_F(CRWWebStateSecurityStateTest, LoadHttpPage) { TestWebStateObserver observer(web_state());
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h index a0122e7..78cf19c 100644 --- a/ios/web/web_state/web_state_impl.h +++ b/ios/web/web_state/web_state_impl.h
@@ -66,7 +66,7 @@ class WebStateImpl : public WebState, public NavigationManagerDelegate { public: // Constructor for WebStateImpls created for new sessions. - WebStateImpl(const CreateParams& params); + explicit WebStateImpl(const CreateParams& params); // Constructor for WebStatesImpls created for deserialized sessions WebStateImpl(const CreateParams& params, CRWSessionStorage* session_storage); ~WebStateImpl() override; @@ -84,9 +84,6 @@ // Called when page title was changed. void OnTitleChanged(); - // Called when the visible security state of the page changes. - void OnVisibleSecurityStateChange(); - // Called when a dialog or child window open request was suppressed. void OnDialogSuppressed(); @@ -220,13 +217,12 @@ void ShowTransientContentView(CRWContentView* content_view) override; bool IsShowingWebInterstitial() const override; WebInterstitial* GetWebInterstitial() const override; - void OnPasswordInputShownOnHttp() override; - void OnCreditCardInputShownOnHttp() override; void AddScriptCommandCallback(const ScriptCommandCallback& callback, const std::string& command_prefix) override; void RemoveScriptCommandCallback(const std::string& command_prefix) override; id<CRWWebViewProxy> GetWebViewProxy() const override; WebStateInterfaceProvider* GetWebStateInterfaceProvider() override; + void DidChangeVisibleSecurityState() override; void BindInterfaceRequestFromMainFrame( const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override;
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm index 8aff03e..36b3caa 100644 --- a/ios/web/web_state/web_state_impl.mm +++ b/ios/web/web_state/web_state_impl.mm
@@ -182,11 +182,6 @@ observer.TitleWasSet(this); } -void WebStateImpl::OnVisibleSecurityStateChange() { - for (auto& observer : observers_) - observer.DidChangeVisibleSecurityState(this); -} - void WebStateImpl::OnDialogSuppressed() { DCHECK(ShouldSuppressDialogs()); for (auto& observer : observers_) @@ -352,14 +347,6 @@ return interstitial_; } -void WebStateImpl::OnPasswordInputShownOnHttp() { - [web_controller_ didShowPasswordInputOnHTTP]; -} - -void WebStateImpl::OnCreditCardInputShownOnHttp() { - [web_controller_ didShowCreditCardInputOnHTTP]; -} - net::HttpResponseHeaders* WebStateImpl::GetHttpResponseHeaders() const { return http_response_headers_.get(); } @@ -540,6 +527,11 @@ return web_state_interface_provider_.get(); } +void WebStateImpl::DidChangeVisibleSecurityState() { + for (auto& observer : observers_) + observer.DidChangeVisibleSecurityState(this); +} + void WebStateImpl::BindInterfaceRequestFromMainFrame( const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) {
diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm index dc86ff56..a3fa9bc 100644 --- a/ios/web/web_state/web_state_impl_unittest.mm +++ b/ios/web/web_state/web_state_impl_unittest.mm
@@ -299,7 +299,7 @@ // Test that DidChangeVisibleSecurityState() is called. ASSERT_FALSE(observer->did_change_visible_security_state_info()); - web_state_->OnVisibleSecurityStateChange(); + web_state_->DidChangeVisibleSecurityState(); ASSERT_TRUE(observer->did_change_visible_security_state_info()); EXPECT_EQ(web_state_.get(), observer->did_change_visible_security_state_info()->web_state);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/elements/classes-pane-widget-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/classes-pane-widget-expected.txt new file mode 100644 index 0000000..1c92ae4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/classes-pane-widget-expected.txt
@@ -0,0 +1,21 @@ +Tests that classes pane widget shows correct suggestions. + + +Completion for prefix: . +.a1 +.a2 +.abc +.b + +Completion for prefix: a +a1 +a2 +abc + +Adding class "abc" + +Completion for prefix: a +a1 +a2 +abc +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/elements/classes-pane-widget.js b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/classes-pane-widget.js new file mode 100644 index 0000000..13fefc4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/classes-pane-widget.js
@@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult(`Tests that classes pane widget shows correct suggestions.\n`); + + await TestRunner.loadModule('elements_test_runner'); + await TestRunner.showPanel('elements'); + + await TestRunner.loadHTML(` + <style> + .b { width: 1px; } + .abc { width: 1px; } + .a1 { width: 1px; } + .a2 { width: 1px; } + </style> + <div id="myDiv"></div> + `); + + var classesPane = new Elements.ClassesPaneWidget(); + ElementsTestRunner.selectNodeWithId('myDiv', onNodeSelected); + + async function onNodeSelected() { + await testCompletion('.'); + await testCompletion('a'); + TestRunner.addResult('\nAdding class "abc"'); + await testCompletion('a'); + TestRunner.completeTest(); + } + + /** + * @param {string} prefix + */ + async function testCompletion(prefix) { + TestRunner.addResult('\nCompletion for prefix: ' + prefix); + var completions = await classesPane._prompt._buildClassNameCompletions('', prefix); + for (var completion of completions) + TestRunner.addResult(completion.text); + } +})();
diff --git a/third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp b/third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp index cfe742fb..624102a6 100644 --- a/third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp
@@ -232,7 +232,7 @@ std::unique_ptr<RejectedPromises::MessageQueue> RejectedPromises::CreateMessageQueue() { - return WTF::MakeUnique<MessageQueue>(); + return std::make_unique<MessageQueue>(); } void RejectedPromises::Dispose() {
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp index b64a2e73..900586fb 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -627,7 +627,7 @@ CodeGenerationCheckCallbackInMainThread); if (RuntimeEnabledFeatures::V8IdleTasksEnabled()) { V8PerIsolateData::EnableIdleTasks( - isolate, WTF::MakeUnique<V8IdleTaskRunner>(scheduler)); + isolate, std::make_unique<V8IdleTaskRunner>(scheduler)); } isolate->SetPromiseRejectCallback(PromiseRejectHandlerInMainThread); @@ -645,7 +645,7 @@ ScriptWrappableVisitor::PerformCleanup); V8PerIsolateData::From(isolate)->SetThreadDebugger( - WTF::MakeUnique<MainThreadDebugger>(isolate)); + std::make_unique<MainThreadDebugger>(isolate)); BindingSecurity::InitWrapperCreationSecurityCheck(); }
diff --git a/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp b/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp index 176ef28..b0d86a9 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp +++ b/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp
@@ -405,7 +405,7 @@ // Check that one can decrypt data encrypted with the other. Vector<unsigned char> iv(16, 0); WebCryptoAlgorithm encrypt_algorithm( - kWebCryptoAlgorithmIdAesCbc, WTF::MakeUnique<WebCryptoAesCbcParams>(iv)); + kWebCryptoAlgorithmIdAesCbc, std::make_unique<WebCryptoAesCbcParams>(iv)); Vector<unsigned char> plaintext{1, 2, 3}; WebVector<uint8_t> ciphertext = SyncEncrypt(script_state, encrypt_algorithm, key->Key(), plaintext); @@ -436,7 +436,7 @@ Vector<uint8_t> ciphertext{0x33, 0x26, 0xe7, 0x64, 0x11, 0x5e, 0xf4, 0x60, 0x96, 0x08, 0x11, 0xaf, 0x65, 0x8b, 0x87, 0x04}; WebCryptoAlgorithm encrypt_algorithm( - kWebCryptoAlgorithmIdAesCbc, WTF::MakeUnique<WebCryptoAesCbcParams>(iv)); + kWebCryptoAlgorithmIdAesCbc, std::make_unique<WebCryptoAesCbcParams>(iv)); WebVector<uint8_t> plaintext = SyncDecrypt(script_state, encrypt_algorithm, new_key->Key(), ciphertext); EXPECT_THAT(plaintext, ElementsAre(1, 2, 3)); @@ -551,7 +551,7 @@ // Check that one can verify a message signed by the other. Vector<uint8_t> message{1, 2, 3}; WebCryptoAlgorithm algorithm(kWebCryptoAlgorithmIdRsaPss, - WTF::MakeUnique<WebCryptoRsaPssParams>(16)); + std::make_unique<WebCryptoRsaPssParams>(16)); WebVector<uint8_t> signature = SyncSign(script_state, algorithm, new_private_key->Key(), message); EXPECT_TRUE(SyncVerifySignature(script_state, algorithm, public_key->Key(), @@ -602,7 +602,7 @@ 0xeb, 0x17, 0x68, 0x1f, 0xbd, 0xfa, 0xf7, 0xd6, 0x1f, 0xa4, 0x7c, 0x9e, 0x9e, 0xb1, 0x96, 0x8f, 0xe6, 0x5e, 0x89, 0x99}; WebCryptoAlgorithm algorithm(kWebCryptoAlgorithmIdRsaPss, - WTF::MakeUnique<WebCryptoRsaPssParams>(16)); + std::make_unique<WebCryptoRsaPssParams>(16)); EXPECT_TRUE(SyncVerifySignature(script_state, algorithm, new_public_key->Key(), signature, message)); } @@ -643,7 +643,7 @@ WebCryptoAlgorithm hash(kWebCryptoAlgorithmIdSha256, nullptr); Vector<uint8_t> message{1, 2, 3}; WebCryptoAlgorithm algorithm(kWebCryptoAlgorithmIdEcdsa, - WTF::MakeUnique<WebCryptoEcdsaParams>(hash)); + std::make_unique<WebCryptoEcdsaParams>(hash)); WebVector<uint8_t> signature = SyncSign(script_state, algorithm, new_private_key->Key(), message); EXPECT_TRUE(SyncVerifySignature(script_state, algorithm, public_key->Key(), @@ -684,7 +684,7 @@ 0x83, 0x27, 0x37, 0x69, 0x4d, 0x32, 0x63, 0x1e, 0x82}; WebCryptoAlgorithm hash(kWebCryptoAlgorithmIdSha256, nullptr); WebCryptoAlgorithm algorithm(kWebCryptoAlgorithmIdEcdsa, - WTF::MakeUnique<WebCryptoEcdsaParams>(hash)); + std::make_unique<WebCryptoEcdsaParams>(hash)); EXPECT_TRUE(SyncVerifySignature(script_state, algorithm, new_public_key->Key(), signature, message)); }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js index 5b66cbf..3157a13 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
@@ -14,7 +14,7 @@ this.setDefaultFocusedElement(this._input); this._classesContainer = this.contentElement.createChild('div', 'source-code'); this._classesContainer.classList.add('styles-element-classes-container'); - this._prompt = new Elements.ClassesPaneWidget.ClassNamePrompt(); + this._prompt = new Elements.ClassesPaneWidget.ClassNamePrompt(this._nodeClasses.bind(this)); this._prompt.setAutocompletionTimeout(0); this._prompt.renderAsBlock(); @@ -262,8 +262,12 @@ * @unrestricted */ Elements.ClassesPaneWidget.ClassNamePrompt = class extends UI.TextPrompt { - constructor() { + /** + * @param {function(!SDK.DOMNode):!Map<string, boolean>} nodeClasses + */ + constructor(nodeClasses) { super(); + this._nodeClasses = nodeClasses; this.initialize(this._buildClassNameCompletions.bind(this), ' '); this.disableDefaultSuggestionForEmptyInput(); this._selectedFrameId = ''; @@ -313,9 +317,12 @@ this._classNamesPromise = this._getClassNames(selectedNode); return this._classNamesPromise.then(completions => { + var classesMap = this._nodeClasses(/** @type {!SDK.DOMNode} */ (selectedNode)); + completions = completions.filter(value => !classesMap.get(value)); + if (prefix[0] === '.') completions = completions.map(value => '.' + value); - return completions.filter(value => value.startsWith(prefix)).map(completion => ({text: completion})); + return completions.filter(value => value.startsWith(prefix)).sort().map(completion => ({text: completion})); }); } };
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js index a9a0e1c..5777cf9 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -128,6 +128,17 @@ } /** + * @param {!Object} headers + * @return {!Object<string, string>} + */ + static _lowercaseHeaders(headers) { + var newHeaders = {}; + for (var headerName in headers) + newHeaders[headerName.toLowerCase()] = headers[headerName]; + return newHeaders; + } + + /** * @param {string} url * @return {!SDK.NetworkRequest} */ @@ -421,6 +432,7 @@ */ responseReceived(requestId, loaderId, time, resourceType, response, frameId) { var networkRequest = this._inflightRequestsById[requestId]; + var lowercaseHeaders = SDK.NetworkManager._lowercaseHeaders(response.headers); if (!networkRequest) { // We missed the requestWillBeSent. var eventData = {}; @@ -429,7 +441,7 @@ eventData.loaderId = loaderId; eventData.resourceType = resourceType; eventData.mimeType = response.mimeType; - var lastModifiedHeader = response.headers['last-modified']; + var lastModifiedHeader = lowercaseHeaders['last-modified']; eventData.lastModified = lastModifiedHeader ? new Date(lastModifiedHeader) : null; this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestUpdateDropped, eventData); return; @@ -439,7 +451,7 @@ networkRequest.setResourceType(Common.resourceTypes[resourceType]); // net::ParsedCookie::kMaxCookieSize = 4096 (net/cookies/parsed_cookie.h) - if ('Set-Cookie' in response.headers && response.headers['Set-Cookie'].length > 4096) { + if ('set-cookie' in lowercaseHeaders && lowercaseHeaders['set-cookie'].length > 4096) { var message = Common.UIString( 'Set-Cookie header is ignored in response from url: %s. Cookie length should be less than or equal to 4096 characters.', response.url);
diff --git a/third_party/WebKit/Source/platform/WebThreadSupportingGC.cpp b/third_party/WebKit/Source/platform/WebThreadSupportingGC.cpp index 3223833e..551296f 100644 --- a/third_party/WebKit/Source/platform/WebThreadSupportingGC.cpp +++ b/third_party/WebKit/Source/platform/WebThreadSupportingGC.cpp
@@ -51,7 +51,7 @@ void WebThreadSupportingGC::InitializeOnThread() { DCHECK(thread_->IsCurrentThread()); ThreadState::AttachCurrentThread(); - gc_task_runner_ = WTF::MakeUnique<GCTaskRunner>(thread_); + gc_task_runner_ = std::make_unique<GCTaskRunner>(thread_); } void WebThreadSupportingGC::ShutdownOnThread() {
diff --git a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp index 8bf50418..47c621d8 100644 --- a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp +++ b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp
@@ -13,13 +13,13 @@ namespace blink { std::unique_ptr<CompositorAnimationPlayer> CompositorAnimationPlayer::Create() { - return WTF::MakeUnique<CompositorAnimationPlayer>( + return std::make_unique<CompositorAnimationPlayer>( cc::AnimationPlayer::Create(cc::AnimationIdProvider::NextPlayerId())); } std::unique_ptr<CompositorAnimationPlayer> CompositorAnimationPlayer::CreateWorkletPlayer(const String& name) { - return WTF::MakeUnique<CompositorAnimationPlayer>( + return std::make_unique<CompositorAnimationPlayer>( cc::WorkletAnimationPlayer::Create( cc::AnimationIdProvider::NextPlayerId(), std::string(name.Ascii().data(), name.length())));
diff --git a/third_party/WebKit/Source/platform/bindings/RuntimeCallStats.cpp b/third_party/WebKit/Source/platform/bindings/RuntimeCallStats.cpp index 43e92f6..032e03b2 100644 --- a/third_party/WebKit/Source/platform/bindings/RuntimeCallStats.cpp +++ b/third_party/WebKit/Source/platform/bindings/RuntimeCallStats.cpp
@@ -153,7 +153,7 @@ CounterMap::iterator it = counter_map_.find(name); if (it != counter_map_.end()) return it->value.get(); - return counter_map_.insert(name, WTF::MakeUnique<RuntimeCallCounter>(name)) + return counter_map_.insert(name, std::make_unique<RuntimeCallCounter>(name)) .stored_value->value.get(); }
diff --git a/third_party/WebKit/Source/platform/bindings/V8PerContextData.cpp b/third_party/WebKit/Source/platform/bindings/V8PerContextData.cpp index ed5cbd7..98602dd3 100644 --- a/third_party/WebKit/Source/platform/bindings/V8PerContextData.cpp +++ b/third_party/WebKit/Source/platform/bindings/V8PerContextData.cpp
@@ -46,7 +46,7 @@ : isolate_(context->GetIsolate()), wrapper_boilerplates_(isolate_), constructor_map_(isolate_), - context_holder_(WTF::MakeUnique<gin::ContextHolder>(isolate_)), + context_holder_(std::make_unique<gin::ContextHolder>(isolate_)), context_(isolate_, context), activity_logger_(nullptr) { context_holder_->SetContext(context);
diff --git a/third_party/WebKit/Source/platform/blob/BlobBytesProviderTest.cpp b/third_party/WebKit/Source/platform/blob/BlobBytesProviderTest.cpp index 9ba8d4f..8044064 100644 --- a/third_party/WebKit/Source/platform/blob/BlobBytesProviderTest.cpp +++ b/third_party/WebKit/Source/platform/blob/BlobBytesProviderTest.cpp
@@ -4,6 +4,10 @@ #include "platform/blob/BlobBytesProvider.h" +#include <algorithm> +#include <memory> +#include <utility> + #include "base/files/file.h" #include "base/files/file_util.h" #include "base/run_loop.h" @@ -50,7 +54,7 @@ }; TEST_F(BlobBytesProviderTest, RequestAsReply) { - auto provider = WTF::MakeUnique<BlobBytesProvider>(test_data1_); + auto provider = std::make_unique<BlobBytesProvider>(test_data1_); Vector<uint8_t> received_bytes; provider->RequestAsReply( base::Bind([](Vector<uint8_t>* bytes_out, @@ -59,7 +63,7 @@ EXPECT_EQ(test_bytes1_, received_bytes); received_bytes.clear(); - provider = WTF::MakeUnique<BlobBytesProvider>(test_data1_); + provider = std::make_unique<BlobBytesProvider>(test_data1_); provider->AppendData(test_data2_); provider->AppendData(test_data3_); provider->RequestAsReply( @@ -83,7 +87,7 @@ public: void SetUp() override { BlobBytesProviderTest::SetUp(); - test_provider_ = WTF::MakeUnique<BlobBytesProvider>(test_data1_); + test_provider_ = std::make_unique<BlobBytesProvider>(test_data1_); test_provider_->AppendData(test_data2_); test_provider_->AppendData(test_data3_); @@ -213,7 +217,7 @@ ::testing::ValuesIn(file_tests)); TEST_F(BlobBytesProviderTest, RequestAsFile_MultipleChunks) { - auto provider = WTF::MakeUnique<BlobBytesProvider>(test_data1_); + auto provider = std::make_unique<BlobBytesProvider>(test_data1_); provider->AppendData(test_data2_); provider->AppendData(test_data3_); @@ -245,7 +249,7 @@ } TEST_F(BlobBytesProviderTest, RequestAsFile_InvaldFile) { - auto provider = WTF::MakeUnique<BlobBytesProvider>(test_data1_); + auto provider = std::make_unique<BlobBytesProvider>(test_data1_); provider->RequestAsFile( 0, 16, base::File(), 0, @@ -255,7 +259,7 @@ } TEST_F(BlobBytesProviderTest, RequestAsFile_UnwritableFile) { - auto provider = WTF::MakeUnique<BlobBytesProvider>(test_data1_); + auto provider = std::make_unique<BlobBytesProvider>(test_data1_); base::FilePath path; base::CreateTemporaryFile(&path); @@ -273,7 +277,7 @@ } TEST_F(BlobBytesProviderTest, RequestAsStream) { - auto provider = WTF::MakeUnique<BlobBytesProvider>(test_data1_); + auto provider = std::make_unique<BlobBytesProvider>(test_data1_); provider->AppendData(test_data2_); provider->AppendData(test_data3_);
diff --git a/third_party/WebKit/Source/platform/blob/BlobData.cpp b/third_party/WebKit/Source/platform/blob/BlobData.cpp index 42350fb..10c3756 100644 --- a/third_party/WebKit/Source/platform/blob/BlobData.cpp +++ b/third_party/WebKit/Source/platform/blob/BlobData.cpp
@@ -343,7 +343,7 @@ last_bytes_provider->AppendData(item.data); } else { BytesProviderPtr bytes_provider; - auto provider = WTF::MakeUnique<BlobBytesProvider>(item.data); + auto provider = std::make_unique<BlobBytesProvider>(item.data); last_bytes_provider = provider.get(); if (file_runner) { // TODO(mek): Considering binding BytesProvider on the IO thread
diff --git a/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp b/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp index b6e72c0..c75c2f65 100644 --- a/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp +++ b/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp
@@ -67,7 +67,7 @@ explicit MockBlob(const String& uuid) : uuid_(uuid) {} void Clone(BlobRequest request) override { - mojo::MakeStrongBinding(WTF::MakeUnique<MockBlob>(uuid_), + mojo::MakeStrongBinding(std::make_unique<MockBlob>(uuid_), std::move(request)); } @@ -101,7 +101,7 @@ RegisterCallback callback) override { registrations.push_back(Registration{ uuid, content_type, content_disposition, std::move(elements)}); - mojo::MakeStrongBinding(WTF::MakeUnique<MockBlob>(uuid), std::move(blob)); + mojo::MakeStrongBinding(std::make_unique<MockBlob>(uuid), std::move(blob)); std::move(callback).Run(); } @@ -109,7 +109,7 @@ const String& uuid, GetBlobFromUUIDCallback callback) override { binding_requests.push_back(BindingRequest{uuid}); - mojo::MakeStrongBinding(WTF::MakeUnique<MockBlob>(uuid), std::move(blob)); + mojo::MakeStrongBinding(std::make_unique<MockBlob>(uuid), std::move(blob)); std::move(callback).Run(); } @@ -158,7 +158,7 @@ public: explicit MojoBlobTestPlatform(BlobRegistry* mock_registry) : interface_provider_( - WTF::MakeUnique<MojoBlobInterfaceProvider>(mock_registry)) {} + std::make_unique<MojoBlobInterfaceProvider>(mock_registry)) {} InterfaceProvider* GetInterfaceProvider() override { return interface_provider_.get();
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp index e6e6afd..1cbcf849 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -489,7 +489,7 @@ CompositedLayerRasterInvalidator& GraphicsLayer::EnsureRasterInvalidator() { if (!raster_invalidator_) { - raster_invalidator_ = WTF::MakeUnique<CompositedLayerRasterInvalidator>( + raster_invalidator_ = std::make_unique<CompositedLayerRasterInvalidator>( [this](const IntRect& r) { SetNeedsDisplayInRectInternal(r); }); raster_invalidator_->SetTracksRasterInvalidations( client_->IsTrackingRasterInvalidations());
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.cpp b/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.cpp index 5bb5753..137b27b 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.cpp
@@ -4,6 +4,10 @@ #include "platform/graphics/compositing/CompositedLayerRasterInvalidator.h" +#include <algorithm> +#include <memory> +#include <utility> + #include "platform/graphics/paint/GeometryMapper.h" namespace blink { @@ -222,7 +226,7 @@ RasterInvalidationTracking& CompositedLayerRasterInvalidator::EnsureTracking() { if (!tracking_info_) - tracking_info_ = WTF::MakeUnique<RasterInvalidationTrackingInfo>(); + tracking_info_ = std::make_unique<RasterInvalidationTrackingInfo>(); return tracking_info_->tracking; }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp index 0755547..4708cac 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp
@@ -25,9 +25,9 @@ protected: void SetUp() override { IntSize initial_size(kInitialWidth, kInitialHeight); - auto gl = WTF::MakeUnique<GLES2InterfaceForTests>(); + auto gl = std::make_unique<GLES2InterfaceForTests>(); auto provider = - WTF::MakeUnique<WebGraphicsContext3DProviderForTests>(std::move(gl)); + std::make_unique<WebGraphicsContext3DProviderForTests>(std::move(gl)); GLES2InterfaceForTests* gl_ = static_cast<GLES2InterfaceForTests*>(provider->ContextGL()); bool gpu_compositing = false;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp index d2b3369..ce54bf3 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -73,9 +73,9 @@ void Init(UseMultisampling use_multisampling) { IntSize initial_size(kInitialWidth, kInitialHeight); - auto gl = WTF::MakeUnique<GLES2InterfaceForTests>(); + auto gl = std::make_unique<GLES2InterfaceForTests>(); auto provider = - WTF::MakeUnique<WebGraphicsContext3DProviderForTests>(std::move(gl)); + std::make_unique<WebGraphicsContext3DProviderForTests>(std::move(gl)); GLES2InterfaceForTests* gl_ = static_cast<GLES2InterfaceForTests*>(provider->ContextGL()); bool gpu_compositing = true; @@ -400,9 +400,9 @@ platform_.reset(new ScopedTestingPlatformSupport<FakePlatformSupport>); IntSize initial_size(kInitialWidth, kInitialHeight); - auto gl = WTF::MakeUnique<GLES2InterfaceForTests>(); + auto gl = std::make_unique<GLES2InterfaceForTests>(); auto provider = - WTF::MakeUnique<WebGraphicsContext3DProviderForTests>(std::move(gl)); + std::make_unique<WebGraphicsContext3DProviderForTests>(std::move(gl)); GLES2InterfaceForTests* gl_ = static_cast<GLES2InterfaceForTests*>(provider->ContextGL()); image_id0_ = gl_->NextImageIdToBeCreated(); @@ -648,10 +648,10 @@ for (size_t i = 0; i < WTF_ARRAY_LENGTH(cases); i++) { SCOPED_TRACE(cases[i].test_case_name); - auto gl = WTF::MakeUnique<DepthStencilTrackingGLES2Interface>(); + auto gl = std::make_unique<DepthStencilTrackingGLES2Interface>(); DepthStencilTrackingGLES2Interface* tracking_gl = gl.get(); auto provider = - WTF::MakeUnique<WebGraphicsContext3DProviderForTests>(std::move(gl)); + std::make_unique<WebGraphicsContext3DProviderForTests>(std::move(gl)); DrawingBuffer::PreserveDrawingBuffer preserve = DrawingBuffer::kPreserve; bool premultiplied_alpha = false;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp index 26d6f07c..cc9585e 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp
@@ -67,7 +67,7 @@ Platform::Current()->CreateOffscreenGraphicsContext3DProvider( context_attributes, WebURL(), nullptr, &graphics_info); if (context_provider) { - *wrapper = WTF::MakeUnique<WebGraphicsContext3DProviderWrapper>( + *wrapper = std::make_unique<WebGraphicsContext3DProviderWrapper>( std::move(context_provider)); } waitable_event->Signal(); @@ -100,7 +100,7 @@ context_provider_factory_.Run(&is_gpu_compositing_disabled_); if (context_provider) { context_provider_wrapper_ = - WTF::MakeUnique<WebGraphicsContext3DProviderWrapper>( + std::make_unique<WebGraphicsContext3DProviderWrapper>( std::move(context_provider)); } } else if (IsMainThread()) { @@ -112,7 +112,7 @@ Platform::Current()->CreateSharedOffscreenGraphicsContext3DProvider(); if (context_provider) { context_provider_wrapper_ = - WTF::MakeUnique<WebGraphicsContext3DProviderWrapper>( + std::make_unique<WebGraphicsContext3DProviderWrapper>( std::move(context_provider)); } } else {
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp index dd44dfe..6340fe0 100644 --- a/third_party/WebKit/Source/platform/heap/Heap.cpp +++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -148,7 +148,7 @@ ThreadHeap::ThreadHeap(ThreadState* thread_state) : thread_state_(thread_state), - region_tree_(WTF::MakeUnique<RegionTree>()), + region_tree_(std::make_unique<RegionTree>()), heap_does_not_contain_cache_( WTF::WrapUnique(new HeapDoesNotContainCache)), free_page_pool_(WTF::WrapUnique(new PagePool)),
diff --git a/third_party/WebKit/Source/platform/heap/HeapTest.cpp b/third_party/WebKit/Source/platform/heap/HeapTest.cpp index 93692e3..99bf5dd8 100644 --- a/third_party/WebKit/Source/platform/heap/HeapTest.cpp +++ b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
@@ -1202,7 +1202,7 @@ ObserverMap::AddResult result = map.insert(&target, nullptr); if (result.is_new_entry) { result.stored_value->value = - WTF::MakeUnique<FinalizationObserverWithHashMap>(target); + std::make_unique<FinalizationObserverWithHashMap>(target); } else { DCHECK(result.stored_value->value); } @@ -6367,7 +6367,7 @@ TEST(HeapTest, WeakPersistent) { Persistent<IntWrapper> object = new IntWrapper(20); std::unique_ptr<WeakPersistentHolder> holder = - WTF::MakeUnique<WeakPersistentHolder>(object); + std::make_unique<WeakPersistentHolder>(object); PreciselyCollectGarbage(); EXPECT_TRUE(holder->Object()); object = nullptr;
diff --git a/third_party/WebKit/Source/platform/heap/SparseHeapBitmap.cpp b/third_party/WebKit/Source/platform/heap/SparseHeapBitmap.cpp index eb947b9..72216bc 100644 --- a/third_party/WebKit/Source/platform/heap/SparseHeapBitmap.cpp +++ b/third_party/WebKit/Source/platform/heap/SparseHeapBitmap.cpp
@@ -95,7 +95,7 @@ void SparseHeapBitmap::CreateBitmap() { DCHECK(!bitmap_ && size() == 1); - bitmap_ = WTF::MakeUnique<std::bitset<kBitmapChunkSize>>(); + bitmap_ = std::make_unique<std::bitset<kBitmapChunkSize>>(); size_ = kBitmapChunkRange; bitmap_->set(0); }
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp index 5a8582c..e68c4ab 100644 --- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp +++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -104,7 +104,7 @@ ThreadState::ThreadState() : thread_(CurrentThread()), - persistent_region_(WTF::MakeUnique<PersistentRegion>()), + persistent_region_(std::make_unique<PersistentRegion>()), start_of_stack_(reinterpret_cast<intptr_t*>(WTF::GetStackStart())), end_of_stack_(reinterpret_cast<intptr_t*>(WTF::GetStackStart())), safe_point_scope_marker_(nullptr),
diff --git a/third_party/WebKit/Source/platform/heap/Visitor.cpp b/third_party/WebKit/Source/platform/heap/Visitor.cpp index fe347a3..61462f64 100644 --- a/third_party/WebKit/Source/platform/heap/Visitor.cpp +++ b/third_party/WebKit/Source/platform/heap/Visitor.cpp
@@ -13,7 +13,7 @@ namespace blink { std::unique_ptr<Visitor> Visitor::Create(ThreadState* state, MarkingMode mode) { - return WTF::MakeUnique<Visitor>(state, mode); + return std::make_unique<Visitor>(state, mode); } Visitor::Visitor(ThreadState* state, MarkingMode marking_mode)
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp index 1879171..90193853 100644 --- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -262,7 +262,7 @@ return; if (!reader_) { - reader_ = WTF::MakeUnique<GIFImageReader>(this); + reader_ = std::make_unique<GIFImageReader>(this); reader_->SetData(data_); }
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp index 3f5ad37..620e0edc 100644 --- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp
@@ -347,7 +347,7 @@ if (!IsDataSizeDefined() || !IsHeaderDefined()) return true; - lzw_context_ = WTF::MakeUnique<GIFLZWContext>(client, this); + lzw_context_ = std::make_unique<GIFLZWContext>(client, this); if (!lzw_context_->PrepareToDecode()) { lzw_context_.reset(); return false;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/BufferingDataPipeWriterTest.cpp b/third_party/WebKit/Source/platform/loader/fetch/BufferingDataPipeWriterTest.cpp index 6d6e3c91..b1143ab 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/BufferingDataPipeWriterTest.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/BufferingDataPipeWriterTest.cpp
@@ -40,7 +40,7 @@ for (size_t i = 0; i < total; ++i) input.push_back(static_cast<char>(engine() % 26 + 'A')); - auto writer = WTF::MakeUnique<BufferingDataPipeWriter>( + auto writer = std::make_unique<BufferingDataPipeWriter>( std::move(producer), platform->CurrentThread()->GetWebTaskRunner()); for (size_t i = 0; i < total;) {
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp b/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp index 8b1b0d7..11b09e6d 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp
@@ -25,6 +25,8 @@ #include "platform/loader/fetch/FetchParameters.h" +#include <memory> + #include "platform/loader/fetch/ResourceFetcher.h" #include "platform/weborigin/KURL.h" #include "platform/weborigin/SecurityOrigin.h" @@ -151,7 +153,7 @@ std::unique_ptr<CrossThreadFetchParametersData> FetchParameters::CopyData() const { - auto data = WTF::MakeUnique<CrossThreadFetchParametersData>(); + auto data = std::make_unique<CrossThreadFetchParametersData>(); data->resource_request = resource_request_.CopyData(); data->decoder_options = decoder_options_; data->options = CrossThreadResourceLoaderOptionsData(options_);
diff --git a/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp b/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp index 63bccc6..86b37442 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp
@@ -299,7 +299,7 @@ data_consumer_handle_ = Platform::Current()->CreateDataConsumerHandle(std::move(consumer)); - data_pipe_writer_ = WTF::MakeUnique<BufferingDataPipeWriter>( + data_pipe_writer_ = std::make_unique<BufferingDataPipeWriter>( std::move(producer), task_runner); if (Data()) {
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp index 7d33b129..d5537605 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
@@ -130,7 +130,7 @@ std::unique_ptr<CrossThreadResourceRequestData> ResourceRequest::CopyData() const { std::unique_ptr<CrossThreadResourceRequestData> data = - WTF::MakeUnique<CrossThreadResourceRequestData>(); + std::make_unique<CrossThreadResourceRequestData>(); data->url_ = Url().Copy(); data->timeout_interval_ = TimeoutInterval(); data->site_for_cookies_ = SiteForCookies().Copy();
diff --git a/third_party/WebKit/Source/platform/threading/BackgroundTaskRunnerTest.cpp b/third_party/WebKit/Source/platform/threading/BackgroundTaskRunnerTest.cpp index f2e525238..3e2f3d70 100644 --- a/third_party/WebKit/Source/platform/threading/BackgroundTaskRunnerTest.cpp +++ b/third_party/WebKit/Source/platform/threading/BackgroundTaskRunnerTest.cpp
@@ -24,7 +24,7 @@ TEST(BackgroundTaskRunnerTest, RunOnBackgroundThread) { base::test::ScopedTaskEnvironment scoped_task_environment; - std::unique_ptr<WaitableEvent> done_event = WTF::MakeUnique<WaitableEvent>(); + std::unique_ptr<WaitableEvent> done_event = std::make_unique<WaitableEvent>(); BackgroundTaskRunner::PostOnBackgroundThread( BLINK_FROM_HERE, CrossThreadBind(&PingPongTask, CrossThreadUnretained(done_event.get())));
diff --git a/third_party/WebKit/Source/platform/transforms/TransformationMatrix.h b/third_party/WebKit/Source/platform/transforms/TransformationMatrix.h index aa376da7..78d85c11 100644 --- a/third_party/WebKit/Source/platform/transforms/TransformationMatrix.h +++ b/third_party/WebKit/Source/platform/transforms/TransformationMatrix.h
@@ -76,11 +76,11 @@ #endif static std::unique_ptr<TransformationMatrix> Create() { - return WTF::MakeUnique<TransformationMatrix>(); + return std::make_unique<TransformationMatrix>(); } static std::unique_ptr<TransformationMatrix> Create( const TransformationMatrix& t) { - return WTF::MakeUnique<TransformationMatrix>(t); + return std::make_unique<TransformationMatrix>(t); } static std::unique_ptr<TransformationMatrix> Create(double a, double b, @@ -88,7 +88,7 @@ double d, double e, double f) { - return WTF::MakeUnique<TransformationMatrix>(a, b, c, d, e, f); + return std::make_unique<TransformationMatrix>(a, b, c, d, e, f); } static std::unique_ptr<TransformationMatrix> Create(double m11, double m12,
diff --git a/tools/cfi/blacklist.txt b/tools/cfi/blacklist.txt index e1f2a22..d903f7e6 100644 --- a/tools/cfi/blacklist.txt +++ b/tools/cfi/blacklist.txt
@@ -181,6 +181,9 @@ # net/cert/cert_verify_proc_nss.cc fun:*CertVerifyProcNSS*VerifyInternalImpl* +# third_party/skia/include/gpu/gl/GrGLFunctions.h +fun:*GrGLFunction* + ######### Function pointers cast to incorrect type signatures # libicu is currently compiled such that in libicu the 'UChar' type is a
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 0bd3b8bb..7bb024c 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -35,7 +35,7 @@ CLANG_REVISION = 'HEAD' # This is incremented when pushing a new build of Clang at the same revision. -CLANG_SUB_REVISION=2 +CLANG_SUB_REVISION=3 PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION) @@ -799,7 +799,7 @@ for f in glob.glob(os.path.join(toolchain_dir, 'include/c++/*/unwind.h')): os.remove(f) - # Build ASan runtime for Android in a separate build tree. + # Build sanitizer runtimes for Android in a separate build tree. build_dir = os.path.join(LLVM_BUILD_DIR, 'android-' + target_arch) if not os.path.exists(build_dir): os.mkdir(os.path.join(build_dir)) @@ -817,13 +817,11 @@ '-DANDROID=1'] RmCmakeCache('.') RunCommand(['cmake'] + android_args + [COMPILER_RT_DIR]) - RunCommand(['ninja', 'libclang_rt.asan-%s-android.so' % target_arch]) + RunCommand(['ninja', 'asan', 'ubsan']) - # And copy it into the main build tree. - runtime = 'libclang_rt.asan-%s-android.so' % target_arch - for root, _, files in os.walk(build_dir): - if runtime in files: - shutil.copy(os.path.join(root, runtime), asan_rt_lib_dst_dir) + # And copy them into the main build tree. + for f in glob.glob(os.path.join(build_dir, 'lib/linux/*.so')): + shutil.copy(f, asan_rt_lib_dst_dir) # Run tests. if args.run_tests or use_head_revision:
diff --git a/tools/perf/page_sets/media_cases.py b/tools/perf/page_sets/media_cases.py index cd4b97267..8ef404a 100644 --- a/tools/perf/page_sets/media_cases.py +++ b/tools/perf/page_sets/media_cases.py
@@ -90,7 +90,6 @@ traffic_setting=traffic_setting_module.NONE): tags.append('beginning_to_end') tags.append('src') - self.add_browser_metrics = True super(_BeginningToEndPlayPage, self).__init__( url, page_set, tags, extra_browser_args, traffic_setting=traffic_setting) @@ -112,7 +111,6 @@ traffic_setting=traffic_setting_module.NONE): tags.append('seek') tags.append('src') - self.skip_basic_metrics = True self._action_timeout = action_timeout_in_seconds super(_SeekPage, self).__init__( url, page_set, tags, extra_browser_args, @@ -146,7 +144,6 @@ background_time=10, traffic_setting=traffic_setting_module.NONE): self._background_time = background_time - self.skip_basic_metrics = True tags.append('background') tags.append('src') # disable-media-suspend is required since for Android background playback
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn index f03bba2..2024d6fe 100644 --- a/ui/app_list/BUILD.gn +++ b/ui/app_list/BUILD.gn
@@ -25,6 +25,8 @@ "app_list_model_observer.h", "app_list_switches.cc", "app_list_switches.h", + "app_list_util.cc", + "app_list_util.h", "app_list_view_delegate.h", "folder_image.cc", "folder_image.h",
diff --git a/ui/app_list/app_list_util.cc b/ui/app_list/app_list_util.cc new file mode 100644 index 0000000..ffd0671 --- /dev/null +++ b/ui/app_list/app_list_util.cc
@@ -0,0 +1,79 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/app_list/app_list_util.h" + +#include "ui/views/controls/textfield/textfield.h" +#include "ui/views/focus/focus_manager.h" + +namespace app_list { + +bool CanProcessLeftRightKeyTraversal(const ui::KeyEvent& event) { + if (event.handled() || event.type() != ui::ET_KEY_PRESSED) + return false; + + if (event.key_code() != ui::VKEY_LEFT && event.key_code() != ui::VKEY_RIGHT) + return false; + + if (event.IsShiftDown() || event.IsControlDown() || event.IsAltDown()) + return false; + + return true; +} + +bool CanProcessUpDownKeyTraversal(const ui::KeyEvent& event) { + if (event.handled() || event.type() != ui::ET_KEY_PRESSED) + return false; + + if (event.key_code() != ui::VKEY_UP && event.key_code() != ui::VKEY_DOWN) + return false; + + if (event.IsShiftDown() || event.IsControlDown() || event.IsAltDown()) + return false; + + return true; +} + +bool ProcessLeftRightKeyTraversalForTextfield(views::Textfield* textfield, + const ui::KeyEvent& key_event) { + DCHECK(CanProcessLeftRightKeyTraversal(key_event)); + + const bool move_focus_reverse = base::i18n::IsRTL() + ? key_event.key_code() == ui::VKEY_RIGHT + : key_event.key_code() == ui::VKEY_LEFT; + if (textfield->text().empty()) { + textfield->GetFocusManager()->AdvanceFocus(move_focus_reverse); + return true; + } + + if (textfield->HasSelection()) + return false; + + if (textfield->GetCursorPosition() != 0 && + textfield->GetCursorPosition() != textfield->text().length()) { + return false; + } + + // For RTL language, the beginning position of the cursor will be at the right + // side and it grows towards left as we are typing. + const bool text_rtl = + textfield->GetTextDirection() == base::i18n::RIGHT_TO_LEFT; + const bool cursor_at_beginning = textfield->GetCursorPosition() == 0; + const bool move_cursor_reverse = + (text_rtl && key_event.key_code() == ui::VKEY_RIGHT) || + (!text_rtl && key_event.key_code() == ui::VKEY_LEFT); + + if ((cursor_at_beginning && !move_cursor_reverse) || + (!cursor_at_beginning && move_cursor_reverse)) { + // Cursor is at either the beginning or the end of the textfield, and it + // will move inward. + return false; + } + + // Move focus outside the textfield. + textfield->GetFocusManager()->AdvanceFocus(move_focus_reverse); + return true; +} + +} // namespace app_list
diff --git a/ui/app_list/app_list_util.h b/ui/app_list/app_list_util.h new file mode 100644 index 0000000..377142d --- /dev/null +++ b/ui/app_list/app_list_util.h
@@ -0,0 +1,33 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_APP_LIST_APP_LIST_UTIL_H_ +#define UI_APP_LIST_APP_LIST_UTIL_H_ + +#include "ui/app_list/app_list_export.h" +#include "ui/events/event.h" + +namespace views { +class Textfield; +} + +namespace app_list { + +// Returns true if the key event can be handled to do left or right focus +// traversal. +APP_LIST_EXPORT bool CanProcessLeftRightKeyTraversal(const ui::KeyEvent& event); + +// Returns true if the key event can be handled to do up or down focus +// traversal. +APP_LIST_EXPORT bool CanProcessUpDownKeyTraversal(const ui::KeyEvent& event); + +// Processes left/right key traversal for the given Textfield. Returns true +// if focus is moved. +APP_LIST_EXPORT bool ProcessLeftRightKeyTraversalForTextfield( + views::Textfield* textfield, + const ui::KeyEvent& key_event); + +} // namespace app_list + +#endif // UI_APP_LIST_APP_LIST_UTIL_H_
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc index 20f3097..e46eaa3 100644 --- a/ui/app_list/views/app_list_view.cc +++ b/ui/app_list/views/app_list_view.cc
@@ -21,6 +21,7 @@ #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_model.h" +#include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/speech_ui_model.h" #include "ui/app_list/views/app_list_folder_view.h" @@ -1131,29 +1132,7 @@ } void AppListView::OnKeyEvent(ui::KeyEvent* event) { - views::Textfield* search_box = search_box_view_->search_box(); - bool is_search_box_focused = search_box->HasFocus(); - bool is_folder_header_view_focused = app_list_main_view_->contents_view() - ->apps_container_view() - ->app_list_folder_view() - ->folder_header_view() - ->HasTextFocus(); - if (is_app_list_focus_enabled_ && !is_search_box_focused && - !is_folder_header_view_focused && !SearchBoxView::IsArrowKey(*event)) { - views::Textfield* search_box = search_box_view_->search_box(); - // Redirect key event to |search_box_|. - search_box->OnKeyEvent(event); - if (event->handled()) { - // Set search box focused if the key event is consumed. - search_box->RequestFocus(); - return; - } - if (event->type() == ui::ET_KEY_PRESSED) { - // Insert it into search box if the key event is a character. Released - // key should not be handled to prevent inserting duplicate character. - search_box->InsertChar(*event); - } - } + RedirectKeyEventToSearchBox(event); } void AppListView::OnTabletModeChanged(bool started) { @@ -1401,6 +1380,47 @@ Layout(); } +void AppListView::RedirectKeyEventToSearchBox(ui::KeyEvent* event) { + if (!is_app_list_focus_enabled_) + return; + + if (event->handled()) + return; + + views::Textfield* search_box = search_box_view_->search_box(); + const bool is_search_box_focused = search_box->HasFocus(); + const bool is_folder_header_view_focused = + app_list_main_view_->contents_view() + ->apps_container_view() + ->app_list_folder_view() + ->folder_header_view() + ->HasTextFocus(); + if (is_search_box_focused || is_folder_header_view_focused) { + // Do not redirect the key event to the |search_box_| when focus is on a + // text field. + return; + } + + if (CanProcessLeftRightKeyTraversal(*event) || + CanProcessUpDownKeyTraversal(*event)) { + // Do not redirect the arrow keys that are used to do focus traversal. + return; + } + + // Redirect key event to |search_box_|. + search_box->OnKeyEvent(event); + if (event->handled()) { + // Set search box focused if the key event is consumed. + search_box->RequestFocus(); + return; + } + if (event->type() == ui::ET_KEY_PRESSED) { + // Insert it into search box if the key event is a character. Released + // key should not be handled to prevent inserting duplicate character. + search_box->InsertChar(*event); + } +} + void AppListView::OnSpeechRecognitionStateChanged( SpeechRecognitionState new_state) { if (!speech_view_)
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h index ba117f96..2896da07 100644 --- a/ui/app_list/views/app_list_view.h +++ b/ui/app_list/views/app_list_view.h
@@ -189,6 +189,11 @@ // Layouts the app list during dragging. void DraggingLayout(); + // The search box cannot actively listen to all key events. To control and + // input into the search box when it does not have focus, we need to redirect + // necessary key events to the search box. + void RedirectKeyEventToSearchBox(ui::KeyEvent* event); + // Sets |is_in_drag_| and updates the visibility of app list items. void SetIsInDrag(bool is_in_drag);
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc index 92a61c5..498097e 100644 --- a/ui/app_list/views/app_list_view_unittest.cc +++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -177,7 +177,8 @@ // TODO(weidongg/766807) Remove all old focus tests after the flag is enabled // by default. -class AppListViewFocusTest : public views::ViewsTestBase { +class AppListViewFocusTest : public views::ViewsTestBase, + public testing::WithParamInterface<bool> { public: AppListViewFocusTest() = default; ~AppListViewFocusTest() override = default; @@ -186,6 +187,13 @@ void SetUp() override { views::ViewsTestBase::SetUp(); + // Setup right to left environment if necessary. + if (testing::UnitTest::GetInstance()->current_test_info()->value_param()) { + is_rtl_ = GetParam(); + if (is_rtl_) + base::i18n::SetICUDefaultLocale("he"); + } + // Enable app list focus. scoped_feature_list_.InitAndEnableFeature(features::kEnableAppListFocus); @@ -296,6 +304,111 @@ } } + // Test the behavior triggered by left and right key when focus is on the + // |textfield|. |text_rtl| indicates whether to type RTL or non-RTL text in + // the |textfield| during the test. + void TestLeftAndRightKeyOnTextfield(views::Textfield* textfield, + bool text_rtl) { + EXPECT_TRUE(textfield->text().empty()); + EXPECT_EQ(textfield, focused_view()); + + views::View* next_view = + view_->GetWidget()->GetFocusManager()->GetNextFocusableView( + textfield, view_->GetWidget(), false, false); + views::View* prev_view = + view_->GetWidget()->GetFocusManager()->GetNextFocusableView( + textfield, view_->GetWidget(), true, false); + + // Only need to hit left or right key once to move focus outside the + // textfield when it is empty. + SimulateKeyPress(ui::VKEY_RIGHT, false); + EXPECT_EQ(is_rtl_ ? prev_view : next_view, focused_view()); + + SimulateKeyPress(ui::VKEY_LEFT, false); + EXPECT_EQ(textfield, focused_view()); + + SimulateKeyPress(ui::VKEY_LEFT, false); + EXPECT_EQ(is_rtl_ ? next_view : prev_view, focused_view()); + + SimulateKeyPress(ui::VKEY_RIGHT, false); + EXPECT_EQ(textfield, focused_view()); + + // Type something in textfield. + base::string16 text = + text_rtl + // Arabic word of "test". + ? base::UTF8ToUTF16( + "\xd8\xa7\xd8\xae\xd8\xaa\xd8\xa8\xd8\xa7\xd8\xb1") + : base::UTF8ToUTF16("test"); + textfield->InsertText(text); + next_view = view_->GetWidget()->GetFocusManager()->GetNextFocusableView( + textfield, view_->GetWidget(), false, false); + prev_view = view_->GetWidget()->GetFocusManager()->GetNextFocusableView( + textfield, view_->GetWidget(), true, false); + EXPECT_EQ(text.length(), textfield->GetCursorPosition()); + EXPECT_FALSE(textfield->HasSelection()); + EXPECT_EQ(textfield, focused_view()); + + const ui::KeyboardCode backward_key = + text_rtl ? ui::VKEY_RIGHT : ui::VKEY_LEFT; + const ui::KeyboardCode forward_key = + text_rtl ? ui::VKEY_LEFT : ui::VKEY_RIGHT; + + // Move cursor backward. + SimulateKeyPress(backward_key, false); + EXPECT_EQ(text.length() - 1, textfield->GetCursorPosition()); + EXPECT_EQ(textfield, focused_view()); + + // Move cursor forward. + SimulateKeyPress(forward_key, false); + EXPECT_EQ(text.length(), textfield->GetCursorPosition()); + EXPECT_EQ(textfield, focused_view()); + + // Hit forward key to move focus outside the textfield. + SimulateKeyPress(forward_key, false); + EXPECT_EQ((!is_rtl_ && !text_rtl) || (is_rtl_ && text_rtl) ? next_view + : prev_view, + focused_view()); + + // Hit backward key to move focus back to textfield and select all text. + SimulateKeyPress(backward_key, false); + EXPECT_EQ(text, textfield->GetSelectedText()); + EXPECT_EQ(textfield, focused_view()); + + // Hit backward key to move cursor to the beginning. + SimulateKeyPress(backward_key, false); + EXPECT_EQ(0U, textfield->GetCursorPosition()); + EXPECT_FALSE(textfield->HasSelection()); + EXPECT_EQ(textfield, focused_view()); + + // Hit backward key to move focus outside the textfield. + SimulateKeyPress(backward_key, false); + EXPECT_EQ((!is_rtl_ && !text_rtl) || (is_rtl_ && text_rtl) ? prev_view + : next_view, + focused_view()); + + // Hit forward key to move focus back to textfield and select all text. + SimulateKeyPress(forward_key, false); + EXPECT_EQ(text, textfield->GetSelectedText()); + EXPECT_EQ(textfield, focused_view()); + + // Hit forward key to move cursor to the end. + SimulateKeyPress(forward_key, false); + EXPECT_EQ(text.length(), textfield->GetCursorPosition()); + EXPECT_FALSE(textfield->HasSelection()); + EXPECT_EQ(textfield, focused_view()); + + // Hitt forward key to move focus outside the textfield. + SimulateKeyPress(forward_key, false); + EXPECT_EQ((!is_rtl_ && !text_rtl) || (is_rtl_ && text_rtl) ? next_view + : prev_view, + focused_view()); + + // Clean up + textfield->SetText(base::UTF8ToUTF16("")); + textfield->RequestFocus(); + } + AppListView* app_list_view() { return view_; } AppListMainView* main_view() { return view_->app_list_main_view(); } @@ -332,6 +445,9 @@ return view_->GetWidget()->GetFocusManager()->GetFocusedView(); } + protected: + bool is_rtl_ = false; + private: AppListView* view_ = nullptr; // Owned by native widget. std::unique_ptr<AppListTestViewDelegate> delegate_; @@ -341,6 +457,10 @@ DISALLOW_COPY_AND_ASSIGN(AppListViewFocusTest); }; +// Instantiate the Boolean which is used to toggle RTL in the parameterized +// tests. +INSTANTIATE_TEST_CASE_P(, AppListViewFocusTest, testing::Bool()); + } // namespace // Tests that the initial focus is on search box. @@ -350,7 +470,7 @@ } // Tests the linear focus traversal in PEEKING state. -TEST_F(AppListViewFocusTest, LinearFocusTraversalInPeekingState) { +TEST_P(AppListViewFocusTest, LinearFocusTraversalInPeekingState) { Show(); SetAppListState(AppListView::PEEKING); @@ -369,21 +489,17 @@ // Test traversal triggered by shift+tab. TestFocusTraversal(backward_view_list, ui::VKEY_TAB, true); - // Test traversal triggered by right, Left and right key are handled by - // search box when focus is on it, so focus will not move. Move focus to - // next element before testing. - forward_view_list.erase(forward_view_list.begin()); - forward_view_list.front()->RequestFocus(); - TestFocusTraversal(forward_view_list, ui::VKEY_RIGHT, false); + // Test traversal triggered by right. + TestFocusTraversal(is_rtl_ ? backward_view_list : forward_view_list, + ui::VKEY_RIGHT, false); // Test traversal triggered by left. - backward_view_list.erase(backward_view_list.begin()); - backward_view_list.front()->RequestFocus(); - TestFocusTraversal(backward_view_list, ui::VKEY_LEFT, false); + TestFocusTraversal(is_rtl_ ? forward_view_list : backward_view_list, + ui::VKEY_LEFT, false); } // Tests the linear focus traversal in FULLSCREEN_ALL_APPS state. -TEST_F(AppListViewFocusTest, LinearFocusTraversalInFullscreenAllAppsState) { +TEST_P(AppListViewFocusTest, LinearFocusTraversalInFullscreenAllAppsState) { Show(); SetAppListState(AppListView::FULLSCREEN_ALL_APPS); @@ -405,21 +521,17 @@ // Test traversal triggered by shift+tab. TestFocusTraversal(backward_view_list, ui::VKEY_TAB, true); - // Test traversal triggered by right, Left and right key are handled by - // search box when focus is on it, so focus will not move. Move focus to - // next element before testing. - forward_view_list.erase(forward_view_list.begin()); - forward_view_list.front()->RequestFocus(); - TestFocusTraversal(forward_view_list, ui::VKEY_RIGHT, false); + // Test traversal triggered by right. + TestFocusTraversal(is_rtl_ ? backward_view_list : forward_view_list, + ui::VKEY_RIGHT, false); // Test traversal triggered by left. - backward_view_list.erase(backward_view_list.begin()); - backward_view_list.front()->RequestFocus(); - TestFocusTraversal(backward_view_list, ui::VKEY_LEFT, false); + TestFocusTraversal(is_rtl_ ? forward_view_list : backward_view_list, + ui::VKEY_LEFT, false); } // Tests the linear focus traversal in HALF state with opened search box. -TEST_F(AppListViewFocusTest, LinearFocusTraversalInHalfState) { +TEST_P(AppListViewFocusTest, LinearFocusTraversalInHalfState) { Show(); // Type something in search box to transition to HALF state and populate @@ -454,21 +566,24 @@ // Test traversal triggered by shift+tab. TestFocusTraversal(backward_view_list, ui::VKEY_TAB, true); - // Test traversal triggered by right, Left and right key are handled by - // search box when focus is on it, so focus will not move. Move focus to - // next element before testing. - forward_view_list.erase(forward_view_list.begin()); - forward_view_list.front()->RequestFocus(); - TestFocusTraversal(forward_view_list, ui::VKEY_RIGHT, false); + // Test traversal triggered by right. When the search box is focused, all + // text are selected. Hitting right key will move the cursor to the right end + // and unselect the text. Hitting right key again will move the focus to the + // next view. Left key is handled in similar way. + forward_view_list.insert(forward_view_list.begin(), + search_box_view()->search_box()); + backward_view_list.insert(backward_view_list.begin(), + search_box_view()->search_box()); + TestFocusTraversal(is_rtl_ ? backward_view_list : forward_view_list, + ui::VKEY_RIGHT, false); // Test traversal triggered by left. - backward_view_list.erase(backward_view_list.begin()); - backward_view_list.front()->RequestFocus(); - TestFocusTraversal(backward_view_list, ui::VKEY_LEFT, false); + TestFocusTraversal(is_rtl_ ? forward_view_list : backward_view_list, + ui::VKEY_LEFT, false); } // Tests the linear focus traversal in FULLSCREEN_ALL_APPS state within folder. -TEST_F(AppListViewFocusTest, LinearFocusTraversalInFolder) { +TEST_P(AppListViewFocusTest, LinearFocusTraversalInFolder) { Show(); // Transition to FULLSCREEN_ALL_APPS state and open the folder. @@ -496,19 +611,13 @@ // Test traversal triggered by shift+tab. TestFocusTraversal(backward_view_list, ui::VKEY_TAB, true); - // Test traversal triggered by right, Left and right key are handled by - // search box when focus is on it, so focus will not move. Move focus to - // non-textfield element before testing. - forward_view_list.erase(forward_view_list.begin(), - forward_view_list.begin() + 2); - forward_view_list.front()->RequestFocus(); - TestFocusTraversal(forward_view_list, ui::VKEY_RIGHT, false); + // Test traversal triggered by right. + TestFocusTraversal(is_rtl_ ? backward_view_list : forward_view_list, + ui::VKEY_RIGHT, false); // Test traversal triggered by left. - backward_view_list.erase(backward_view_list.begin()); - backward_view_list.erase(backward_view_list.end() - 1); - backward_view_list.front()->RequestFocus(); - TestFocusTraversal(backward_view_list, ui::VKEY_LEFT, false); + TestFocusTraversal(is_rtl_ ? forward_view_list : backward_view_list, + ui::VKEY_LEFT, false); } // Tests the vertical focus traversal by in PEEKING state. @@ -882,6 +991,32 @@ EXPECT_TRUE(search_box_view()->search_box()->HasFocus()); } +// Tests the left and right key when focus is on the textfield. +TEST_P(AppListViewFocusTest, HittingLeftRightWhenFocusOnTextfield) { + Show(); + + // Transition to FULLSCREEN_ALL_APPS state and open the folder. + SetAppListState(AppListView::FULLSCREEN_ALL_APPS); + folder_item_view()->RequestFocus(); + SimulateKeyPress(ui::VKEY_RETURN, false); + + // Set focus on the folder name. + views::Textfield* folder_name_view = static_cast<views::Textfield*>( + app_list_folder_view()->folder_header_view()->GetFolderNameViewForTest()); + folder_name_view->RequestFocus(); + + // Test folder name. + TestLeftAndRightKeyOnTextfield(folder_name_view, false); + TestLeftAndRightKeyOnTextfield(folder_name_view, true); + + // Set focus on the search box. + search_box_view()->search_box()->RequestFocus(); + + // Test search box. + TestLeftAndRightKeyOnTextfield(search_box_view()->search_box(), false); + TestLeftAndRightKeyOnTextfield(search_box_view()->search_box(), true); +} + // Tests that opening the app list opens in peeking mode by default. TEST_F(AppListViewTest, ShowPeekingByDefault) { Initialize(0, false, false);
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc index 3e11c857..6d0f532 100644 --- a/ui/app_list/views/apps_grid_view.cc +++ b/ui/app_list/views/apps_grid_view.cc
@@ -18,6 +18,7 @@ #include "ui/app_list/app_list_folder_item.h" #include "ui/app_list/app_list_item.h" #include "ui/app_list/app_list_switches.h" +#include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/pagination_controller.h" #include "ui/app_list/views/app_list_drag_and_drop_host.h" @@ -956,7 +957,7 @@ bool AppsGridView::OnKeyPressed(const ui::KeyEvent& event) { if (is_app_list_focus_enabled_) { // Let the FocusManager handle Left/Right keys. - if (event.key_code() != ui::VKEY_UP && event.key_code() != ui::VKEY_DOWN) + if (!CanProcessUpDownKeyTraversal(event)) return false; AppListView::AppListState state =
diff --git a/ui/app_list/views/folder_header_view.cc b/ui/app_list/views/folder_header_view.cc index 08e8b8f..2ae63be 100644 --- a/ui/app_list/views/folder_header_view.cc +++ b/ui/app_list/views/folder_header_view.cc
@@ -12,6 +12,7 @@ #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_folder_item.h" #include "ui/app_list/app_list_switches.h" +#include "ui/app_list/app_list_util.h" #include "ui/app_list/views/app_list_folder_view.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" @@ -255,6 +256,15 @@ Layout(); } +bool FolderHeaderView::HandleKeyEvent(views::Textfield* sender, + const ui::KeyEvent& key_event) { + if (!features::IsAppListFocusEnabled()) + return false; + if (!CanProcessLeftRightKeyTraversal(key_event)) + return false; + return ProcessLeftRightKeyTraversalForTextfield(folder_name_view_, key_event); +} + void FolderHeaderView::ButtonPressed(views::Button* sender, const ui::Event& event) { delegate_->NavigateBack(folder_item_, event);
diff --git a/ui/app_list/views/folder_header_view.h b/ui/app_list/views/folder_header_view.h index cdbdcd0..89ec638 100644 --- a/ui/app_list/views/folder_header_view.h +++ b/ui/app_list/views/folder_header_view.h
@@ -73,6 +73,8 @@ // views::TextfieldController overrides: void ContentsChanged(views::Textfield* sender, const base::string16& new_contents) override; + bool HandleKeyEvent(views::Textfield* sender, + const ui::KeyEvent& key_event) override; // views::ButtonListener overrides: void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index 89f50b8a..257fc23 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -14,6 +14,7 @@ #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_switches.h" +#include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/resources/grit/app_list_resources.h" #include "ui/app_list/search_box_model.h" @@ -674,12 +675,9 @@ } void SearchBoxView::OnKeyEvent(ui::KeyEvent* event) { - app_list_view_->OnKeyEvent(event); + app_list_view_->RedirectKeyEventToSearchBox(event); - if (event->handled() || event->type() != ui::ET_KEY_PRESSED) - return; - - if (event->key_code() != ui::VKEY_UP && event->key_code() != ui::VKEY_DOWN) + if (!CanProcessUpDownKeyTraversal(*event)) return; // If focus is in search box view, up key moves focus to the last element of @@ -882,7 +880,11 @@ SetSearchBoxActive(true); return true; } + return false; } + + if (CanProcessLeftRightKeyTraversal(key_event)) + return ProcessLeftRightKeyTraversalForTextfield(search_box_, key_event); return false; } // TODO(weidongg/766807) Remove everything below when the flag is enabled by
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc index 45f5b6e..60efe86 100644 --- a/ui/app_list/views/search_result_page_view.cc +++ b/ui/app_list/views/search_result_page_view.cc
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" +#include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/views/app_list_main_view.h" #include "ui/app_list/views/contents_view.h" @@ -226,11 +227,16 @@ bool SearchResultPageView::OnKeyPressed(const ui::KeyEvent& event) { if (is_app_list_focus_enabled_) { + // Let the FocusManager handle Left/Right keys. + if (!CanProcessUpDownKeyTraversal(event)) + return false; + views::View* next_focusable_view = nullptr; if (event.key_code() == ui::VKEY_UP) { next_focusable_view = GetFocusManager()->GetNextFocusableView( GetFocusManager()->GetFocusedView(), GetWidget(), true, false); - } else if (event.key_code() == ui::VKEY_DOWN) { + } else { + DCHECK_EQ(event.key_code(), ui::VKEY_DOWN); next_focusable_view = GetFocusManager()->GetNextFocusableView( GetFocusManager()->GetFocusedView(), GetWidget(), false, false); }
diff --git a/ui/app_list/views/search_result_tile_item_list_view.cc b/ui/app_list/views/search_result_tile_item_list_view.cc index 8688a28..882b737 100644 --- a/ui/app_list/views/search_result_tile_item_list_view.cc +++ b/ui/app_list/views/search_result_tile_item_list_view.cc
@@ -9,6 +9,7 @@ #include "base/i18n/rtl.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" +#include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/search_result.h" #include "ui/app_list/views/search_result_page_view.h" @@ -195,6 +196,10 @@ bool SearchResultTileItemListView::OnKeyPressed(const ui::KeyEvent& event) { if (features::IsAppListFocusEnabled()) { + // Let the FocusManager handle Left/Right keys. + if (!CanProcessUpDownKeyTraversal(event)) + return false; + views::View* next_focusable_view = nullptr; // Since search result tile item views have horizontal layout, hitting @@ -209,7 +214,8 @@ search_box_->RequestFocus(); return true; } - } else if (event.key_code() == ui::VKEY_DOWN) { + } else { + DCHECK_EQ(event.key_code(), ui::VKEY_DOWN); next_focusable_view = GetFocusManager()->GetNextFocusableView( tile_views_.back(), GetWidget(), false, false); } @@ -218,6 +224,9 @@ next_focusable_view->RequestFocus(); return true; } + + // Return false to let FocusManager to handle default focus move by key + // events. return false; } // TODO(weidongg/766807) Remove everything below when the flag is enabled by
diff --git a/ui/chromeos/events/event_rewriter_chromeos.cc b/ui/chromeos/events/event_rewriter_chromeos.cc index 4ef27cc..269d235 100644 --- a/ui/chromeos/events/event_rewriter_chromeos.cc +++ b/ui/chromeos/events/event_rewriter_chromeos.cc
@@ -871,6 +871,26 @@ key_event.type() == ui::ET_KEY_RELEASED); MutableKeyState incoming = *state; + if ((incoming.flags & + (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN)) == + (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) { + // Search + Alt + Arrow keys are used to move window between displays, do + // not do remappings on these. + static const KeyboardRemapping::Condition kUseExistingKeys[] = { + {// Alt+Left + ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_LEFT}, + {// Alt+Right + ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_RIGHT}, + {// Alt+Up + ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_UP}, + {// Alt+Down + ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_DOWN}}; + for (const auto& condition : kUseExistingKeys) { + if (MatchKeyboardRemapping(*state, condition)) + return; + } + } + if ((incoming.flags & (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) == (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) { // Allow Search to avoid rewriting extended keys. @@ -881,13 +901,9 @@ {// Control+Alt+Up ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_UP}, - {// Alt+Up - ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_UP}, {// Control+Alt+Down ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN, - ui::VKEY_DOWN}, - {// Alt+Down - ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_DOWN}}; + ui::VKEY_DOWN}}; for (const auto& condition : kAvoidRemappings) { if (MatchKeyboardRemapping(*state, condition)) { state->flags = incoming.flags & ~ui::EF_COMMAND_DOWN;
diff --git a/ui/gfx/icc_profile.cc b/ui/gfx/icc_profile.cc index 75fdec5..8edac94 100644 --- a/ui/gfx/icc_profile.cc +++ b/ui/gfx/icc_profile.cc
@@ -54,17 +54,6 @@ if (!icc_profile->id_) icc_profile->id_ = next_unused_id_++; - // Ensure that GetColorSpace() point back to this ICCProfile. - gfx::ColorSpace& color_space = icc_profile->color_space_; - color_space.icc_profile_id_ = icc_profile->id_; - - // Ensure that the GetParametricColorSpace() point back to this ICCProfile - // only if the parametric version is accurate. - if (color_space.primaries_ != ColorSpace::PrimaryID::ICC_BASED && - color_space.transfer_ != ColorSpace::TransferID::ICC_BASED) { - icc_profile->parametric_color_space_.icc_profile_id_ = icc_profile->id_; - } - Entry entry; entry.icc_profile = *icc_profile; id_to_icc_profile_mru_.Put(icc_profile->id_, entry); @@ -201,76 +190,59 @@ } // namespace -// static -ICCProfile::AnalyzeResult ICCProfile::ExtractColorSpaces( - const std::vector<char>& data, - gfx::ColorSpace* parametric_color_space, - float* parametric_tr_fn_max_error, - sk_sp<SkColorSpace>* useable_sk_color_space) { - // Initialize the output parameters as invalid. - *parametric_color_space = gfx::ColorSpace(); - *parametric_tr_fn_max_error = 0; - *useable_sk_color_space = nullptr; +ICCProfile::AnalyzeResult ICCProfile::Initialize() { + // Start out with no parametric data. // Parse the profile and attempt to create a SkColorSpaceXform out of it. sk_sp<SkColorSpace> sk_srgb_color_space = SkColorSpace::MakeSRGB(); - sk_sp<SkICC> sk_icc = SkICC::Make(data.data(), data.size()); + sk_sp<SkICC> sk_icc = SkICC::Make(data_.data(), data_.size()); if (!sk_icc) { DLOG(ERROR) << "Failed to parse ICC profile to SkICC."; return kICCFailedToParse; } - sk_sp<SkColorSpace> sk_icc_color_space = - SkColorSpace::MakeICC(data.data(), data.size()); - if (!sk_icc_color_space) { + sk_color_space_ = SkColorSpace::MakeICC(data_.data(), data_.size()); + if (!sk_color_space_) { DLOG(ERROR) << "Failed to parse ICC profile to SkColorSpace."; return kICCFailedToExtractSkColorSpace; } std::unique_ptr<SkColorSpaceXform> sk_color_space_xform = - SkColorSpaceXform::New(sk_srgb_color_space.get(), - sk_icc_color_space.get()); + SkColorSpaceXform::New(sk_srgb_color_space.get(), sk_color_space_.get()); if (!sk_color_space_xform) { DLOG(ERROR) << "Parsed ICC profile but can't create SkColorSpaceXform."; return kICCFailedToCreateXform; } - // Because this SkColorSpace can be used to construct a transform, mark it - // as "useable". Mark the "best approximation" as sRGB to start. - *useable_sk_color_space = sk_icc_color_space; - *parametric_color_space = ColorSpace::CreateSRGB(); + // Because this SkColorSpace can be used to construct a transform, we can use + // it to create a LUT based color transform, at the very least. If we fail to + // get any better approximation, we'll use sRGB as our approximation. + ColorSpace::CreateSRGB().GetPrimaryMatrix(&to_XYZD50_); + ColorSpace::CreateSRGB().GetTransferFunction(&transfer_fn_); // If our SkColorSpace representation is sRGB then return that. - if (SkColorSpace::Equals(sk_srgb_color_space.get(), - sk_icc_color_space.get())) { + if (sk_color_space_->isSRGB()) return kICCExtractedSRGBColorSpace; - } - // A primary matrix is required for our parametric approximation. + // A primary matrix is required for our parametric representations. Use it if + // it exists. SkMatrix44 to_XYZD50_matrix; if (!sk_icc->toXYZD50(&to_XYZD50_matrix)) { DLOG(ERROR) << "Failed to extract ICC profile primary matrix."; return kICCFailedToExtractMatrix; } + to_XYZD50_ = to_XYZD50_matrix; - // Try to directly extract a numerical transfer function. + // Try to directly extract a numerical transfer function. Use it if it + // exists. SkColorSpaceTransferFn exact_tr_fn; if (sk_icc->isNumericalTransferFn(&exact_tr_fn)) { - *parametric_color_space = - gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, exact_tr_fn); + transfer_fn_ = exact_tr_fn; return kICCExtractedMatrixAndAnalyticTrFn; } - // If we fail to get a transfer function, use the sRGB transfer function, - // and return false to indicate that the gfx::ColorSpace isn't accurate, but - // we can construct accurate LUT transforms using the underlying - // SkColorSpace. - *parametric_color_space = gfx::ColorSpace::CreateCustom( - to_XYZD50_matrix, ColorSpace::TransferID::IEC61966_2_1); - // Attempt to fit a parametric transfer function to the table data in the // profile. SkColorSpaceTransferFn approx_tr_fn; - if (!SkApproximateTransferFn(sk_icc, parametric_tr_fn_max_error, - &approx_tr_fn)) { + if (!SkApproximateTransferFn(sk_icc, &transfer_fn_error_, &approx_tr_fn)) { DLOG(ERROR) << "Failed approximate transfer function."; return kICCFailedToConvergeToApproximateTrFn; } @@ -278,16 +250,15 @@ // If this converged, but has too high error, use the sRGB transfer function // from above. const float kMaxError = 2.f / 256.f; - if (*parametric_tr_fn_max_error >= kMaxError) { + if (transfer_fn_error_ >= kMaxError) { DLOG(ERROR) << "Failed to accurately approximate transfer function, error: " - << 256.f * (*parametric_tr_fn_max_error) << "/256"; + << 256.f * transfer_fn_error_ << "/256"; return kICCFailedToApproximateTrFnAccurately; }; // If the error is sufficiently low, declare that the approximation is // accurate. - *parametric_color_space = - gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, approx_tr_fn); + transfer_fn_ = approx_tr_fn; return kICCExtractedMatrixAndApproximatedTrFn; } @@ -306,18 +277,6 @@ return !(*this == other); } -bool ICCProfile::IsValid() const { - switch (analyze_result_) { - case kICCFailedToParse: - case kICCFailedToExtractSkColorSpace: - case kICCFailedToCreateXform: - return false; - default: - break; - } - return true; -} - // static ICCProfile ICCProfile::FromData(const void* data, size_t size) { return FromDataWithId(data, size, 0); @@ -346,14 +305,40 @@ return data_; } -const ColorSpace& ICCProfile::GetColorSpace() const { +ColorSpace ICCProfile::GetColorSpace() const { g_cache.Get().TouchEntry(*this); - return color_space_; + + if (!is_valid_) + return ColorSpace(); + + gfx::ColorSpace color_space; + if (is_parametric_) { + color_space = GetParametricColorSpace(); + color_space.icc_profile_sk_color_space_ = sk_color_space_; + } else { + color_space.matrix_ = ColorSpace::MatrixID::RGB; + color_space.range_ = ColorSpace::RangeID::FULL; + color_space.primaries_ = ColorSpace::PrimaryID::ICC_BASED; + color_space.transfer_ = ColorSpace::TransferID::ICC_BASED; + color_space.icc_profile_id_ = id_; + color_space.icc_profile_sk_color_space_ = sk_color_space_; + } + return color_space; } -const ColorSpace& ICCProfile::GetParametricColorSpace() const { +ColorSpace ICCProfile::GetParametricColorSpace() const { g_cache.Get().TouchEntry(*this); - return parametric_color_space_; + + if (!is_valid_) + return ColorSpace(); + + ColorSpace color_space = + sk_color_space_->isSRGB() + ? ColorSpace::CreateSRGB() + : ColorSpace::CreateCustom(to_XYZD50_, transfer_fn_); + if (is_parametric_) + color_space.icc_profile_id_ = id_; + return color_space; } // static @@ -376,32 +361,29 @@ return; // Parse the ICC profile - sk_sp<SkColorSpace> useable_sk_color_space; - analyze_result_ = - ExtractColorSpaces(data_, ¶metric_color_space_, - ¶metric_tr_fn_error_, &useable_sk_color_space); + analyze_result_ = Initialize(); switch (analyze_result_) { case kICCExtractedSRGBColorSpace: case kICCExtractedMatrixAndAnalyticTrFn: case kICCExtractedMatrixAndApproximatedTrFn: // Successfully and accurately extracted color space. - color_space_ = parametric_color_space_; + is_valid_ = true; + is_parametric_ = true; break; case kICCFailedToExtractRawTrFn: case kICCFailedToExtractMatrix: case kICCFailedToConvergeToApproximateTrFn: case kICCFailedToApproximateTrFnAccurately: // Successfully but extracted a color space, but it isn't accurate enough. - color_space_ = ColorSpace(ColorSpace::PrimaryID::ICC_BASED, - ColorSpace::TransferID::ICC_BASED); - color_space_.icc_profile_sk_color_space_ = useable_sk_color_space; + is_valid_ = true; + is_parametric_ = false; break; case kICCFailedToParse: case kICCFailedToExtractSkColorSpace: case kICCFailedToCreateXform: // Can't even use this color space as a LUT. - DCHECK(!parametric_color_space_.IsValid()); - color_space_ = parametric_color_space_; + is_valid_ = false; + is_parametric_ = false; break; } @@ -429,7 +411,7 @@ if (nonlinear_fit_converged) { UMA_HISTOGRAM_CUSTOM_COUNTS( "Blink.ColorSpace.Destination.NonlinearFitError", - static_cast<int>(parametric_tr_fn_error_ * 255), 0, 127, 16); + static_cast<int>(transfer_fn_error_ * 255), 0, 127, 16); } }
diff --git a/ui/gfx/icc_profile.h b/ui/gfx/icc_profile.h index bfbdc4e..bb601d5 100644 --- a/ui/gfx/icc_profile.h +++ b/ui/gfx/icc_profile.h
@@ -41,7 +41,7 @@ bool operator!=(const ICCProfile& other) const; // Returns true if this profile was successfully parsed by SkICC. - bool IsValid() const; + bool IsValid() const { return is_valid_; } #if defined(OS_MACOSX) static ICCProfile FromCGColorSpace(CGColorSpaceRef cg_color_space); @@ -52,12 +52,12 @@ // Return a ColorSpace that references this ICCProfile. ColorTransforms // created using this ColorSpace will match this ICCProfile precisely. - const ColorSpace& GetColorSpace() const; + ColorSpace GetColorSpace() const; // Return a ColorSpace that is the best parametric approximation of this // ICCProfile. The resulting ColorSpace will reference this ICCProfile only // if the parametric approximation is almost exact. - const ColorSpace& GetParametricColorSpace() const; + ColorSpace GetParametricColorSpace() const; const std::vector<char>& GetData() const; @@ -103,12 +103,7 @@ size_t size, uint64_t id); - static AnalyzeResult ExtractColorSpaces( - const std::vector<char>& data, - gfx::ColorSpace* parametric_color_space, - float* parametric_tr_fn_max_error, - sk_sp<SkColorSpace>* useable_sk_color_space); - + AnalyzeResult Initialize(); void ComputeColorSpaceAndCache(); // This globally identifies this ICC profile. It is used to look up this ICC @@ -120,18 +115,27 @@ // The result of attepting to extract a color space from the color profile. AnalyzeResult analyze_result_ = kICCFailedToParse; - // |color_space| always links back to this ICC profile, and its SkColorSpace - // is always equal to the SkColorSpace created from this ICCProfile. - gfx::ColorSpace color_space_; + // True iff we can create a valid ColorSpace (and ColorTransform) from this + // object. The transform may be LUT-based (using an SkColorSpaceXform to + // compute the lut). + bool is_valid_ = false; - // |parametric_color_space_| will only link back to this ICC profile if it - // is accurate, and its SkColorSpace will always be parametrically created. - gfx::ColorSpace parametric_color_space_; + // True iff |to_XYZD50_| and |transfer_fn_| are accurate representations of + // the data in this profile. In this case ColorTransforms created from this + // profile will be analytic and not LUT-based. + bool is_parametric_ = false; + + // Results of Skia parsing the ICC profile data. + sk_sp<SkColorSpace> sk_color_space_; + + // The best-fit parametric primaries and transfer function. + SkMatrix44 to_XYZD50_; + SkColorSpaceTransferFn transfer_fn_; // The L-infinity error of the parametric color space fit. This is undefined // unless |analyze_result_| is kICCFailedToApproximateTrFnAccurately or // kICCExtractedMatrixAndApproximatedTrFn. - float parametric_tr_fn_error_ = -1; + float transfer_fn_error_ = 0; FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, BT709toSRGBICC); FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, GetColorSpace);