diff --git a/BUILD.gn b/BUILD.gn index c01e2de..a1a2108f 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -25,8 +25,8 @@ import("//ui/base/ui_features.gni") import("//ui/ozone/ozone.gni") import("//ui/webui/webui_features.gni") +import("//v8/gni/snapshot_toolchain.gni") import("//v8/gni/v8.gni") -import("//v8/snapshot_toolchain.gni") if (is_android) { import("//build/config/android/config.gni")
diff --git a/DEPS b/DEPS index c235f55c..61496b2 100644 --- a/DEPS +++ b/DEPS
@@ -133,11 +133,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'b3c0bf6426134223910708040943ba23bc32c2ea', + 'skia_revision': 'f0ced62f913f99e5fc0805e283dd8e49ff7d6880', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '9d8a97f7ece30ae9a93f6766960375fc514e78d1', + 'v8_revision': '9eb5d77ec8d2d0de8a192e4917c853ce8f3c9514', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -145,11 +145,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '6ddb7768fa254329632ee91bf18a87b0c8589600', + 'angle_revision': '60cc751a8db16f257f869884042dd63ead0ec356', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'd61595f367af5ccb0bbe8bb168534e47758adfb9', + 'swiftshader_revision': '3ff0e8c51451dbb5b3da7df1952b27287af75af5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -196,7 +196,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'd84db82ff326ef6ee2817af545a86e0e79f3a789', + 'catapult_revision': '89ec6c772dbe1f6069051fb4210b31b5376324bf', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -268,7 +268,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '61c0db71de93ac46677b61c98ea5aeeedc6ce80f', + 'dawn_revision': 'e4c0a82ecfd5f3c78dc90e7ea3c57568f7ac44ae', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1177,7 +1177,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd208655f57ca31b296a8642f89461d89f08a3653', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '10c98fe0cfae669f71610d97e9da94260a6da173', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1345,7 +1345,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6f0b34abee8dba611c253738d955c59f703c147a', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '9a7970de2813d43155321756b1da3d875a22b8f9', + Var('webrtc_git') + '/src.git' + '@' + 'f2047874785a18bc2653ea8ab119945142f49ac2', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1386,7 +1386,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@142d91dc58f5217085efa0bd2c1be038875d9581', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ec4b448207cd7788876c96c965530014e2814604', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 941dc21..4e76eb37 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -2380,7 +2380,8 @@ 'jamescook+watch@chromium.org'], 'media': ['feature-media-reviews@chromium.org'], 'media_capture_from_element': ['emircan+watch+capturefromdom@chromium.org'], - 'media_controls': ['steimel+watch-mediacontrols@chromium.org'], + 'media_controls': ['steimel+watch-mediacontrols@chromium.org', + 'shihken@microsoft.com'], 'media_galleries': ['thestig@chromium.org', 'tommycli@chromium.org'], 'media_gpu': ['hiroh+watch@chromium.org'],
diff --git a/ash/display/screen_ash.cc b/ash/display/screen_ash.cc index 9578af9..8baad56 100644 --- a/ash/display/screen_ash.cc +++ b/ash/display/screen_ash.cc
@@ -15,10 +15,8 @@ #include "base/logging.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/env.h" -#include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" -#include "ui/base/ui_base_features.h" #include "ui/display/display.h" #include "ui/display/display_finder.h" #include "ui/display/manager/display_manager.h" @@ -124,21 +122,6 @@ if (!window) return GetPrimaryDisplay(); - if (::features::IsSingleProcessMash()) { - // In IsSingleProcessMash() ScreenAsh is also called from non-ash code. - // Non-ash code creates aura Windows that are not parented to Ash's root - // Windows. Check for this first. - aura::WindowTreeHostMus* window_tree_host_mus = - aura::WindowTreeHostMus::ForWindow(window); - if (window_tree_host_mus) { - // WindowTreeHostMus::GetDisplay() can return an invalid display (i.e. - // with ID == |kInvalidDisplayID|) if that display is being removed. Use - // the primary display instead. - const auto display = window_tree_host_mus->GetDisplay(); - return display.is_valid() ? display : GetPrimaryDisplay(); - } - } - const aura::Window* root_window = window->GetRootWindow(); if (!root_window) return GetPrimaryDisplay();
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc index 5142652..bd16e8a 100644 --- a/ash/display/window_tree_host_manager.cc +++ b/ash/display/window_tree_host_manager.cc
@@ -93,13 +93,7 @@ const char* GetUICompositorMemoryLimitMB() { bool uses_shader_rounded_corner = features::ShouldUseShaderRoundedCorner(); - // TODO(oshima): Cleanup once new rounded corners and SPM are launched. - - // The upper limit of the gpu memory each compositor in mus can use on - // chromeos. Please see crbug.com/930163 for more info. - if (::features::IsUsingWindowService() && uses_shader_rounded_corner) - return "144"; - + // TODO(oshima): Cleanup once new rounded corners is launched. // Uses 512mb which is default. if (uses_shader_rounded_corner) return "512";
diff --git a/ash/frame/header_view.cc b/ash/frame/header_view.cc index 3a81c97..008ab7b 100644 --- a/ash/frame/header_view.cc +++ b/ash/frame/header_view.cc
@@ -16,7 +16,6 @@ #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_state.h" #include "ui/aura/client/aura_constants.h" -#include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/window.h" #include "ui/base/ui_base_features.h" #include "ui/views/controls/image_view.h"
diff --git a/ash/keyboard/ui/public/OWNERS b/ash/keyboard/ui/public/OWNERS deleted file mode 100644 index 08850f4..0000000 --- a/ash/keyboard/ui/public/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/ash/login/ui/arrow_button_view.cc b/ash/login/ui/arrow_button_view.cc index 36b59c25..16caa92 100644 --- a/ash/login/ui/arrow_button_view.cc +++ b/ash/login/ui/arrow_button_view.cc
@@ -5,7 +5,6 @@ #include "ash/login/ui/arrow_button_view.h" #include "ash/resources/vector_icons/vector_icons.h" -#include "ui/accessibility/ax_node_data.h" #include "ui/gfx/canvas.h" #include "ui/gfx/paint_vector_icon.h" @@ -46,11 +45,6 @@ // Draw arrow icon. views::ImageButton::PaintButtonContents(canvas); } -void ArrowButtonView::GetAccessibleNodeData(ui::AXNodeData* node_data) { - // TODO(tbarzic): Fix this - https://crbug.com/961930. - if (GetAccessibleName().empty()) - node_data->SetNameExplicitlyEmpty(); -} void ArrowButtonView::SetBackgroundColor(SkColor color) { background_color_ = color;
diff --git a/ash/login/ui/arrow_button_view.h b/ash/login/ui/arrow_button_view.h index ff61ccc..441b044 100644 --- a/ash/login/ui/arrow_button_view.h +++ b/ash/login/ui/arrow_button_view.h
@@ -20,7 +20,6 @@ // views::Button: void PaintButtonContents(gfx::Canvas* canvas) override; - void GetAccessibleNodeData(ui::AXNodeData* node_data) override; // Set background color of the button. void SetBackgroundColor(SkColor color);
diff --git a/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.cc b/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.cc index b343010..afa193e 100644 --- a/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.cc +++ b/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.cc
@@ -6,43 +6,10 @@ #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller_delegate.h" -#include "base/run_loop.h" #include "ui/aura/env.h" -#include "ui/aura/event_injector.h" #include "ui/aura/window.h" #include "ui/events/base_event_utils.h" #include "ui/gfx/geometry/rect.h" -#include "ui/views/widget/widget.h" - -namespace { - -// Update mouse location for |window|. For local window, update its aura::Env -// directly. For remote window, update aura::Env by injecting a mouse move -// event. EventInjector is used so that the Window Service side code under mash -// sees the updated mouse location as well. -void UpdateMouseLocation(aura::Window* window, - const gfx::Point& screen_location, - bool wait) { - if (window->env()->mode() == aura::Env::Mode::LOCAL) { - window->env()->SetLastMouseLocation(screen_location); - return; - } - - ui::MouseEvent event(ui::ET_MOUSE_MOVED, screen_location, screen_location, - ui::EventTimeForNow(), ui::EF_NONE, 0); - if (!wait) { - aura::EventInjector().Inject(window->GetHost(), &event); - return; - } - - // Ensure the mouse event goes through when |wait| is set. - aura::EventInjector event_injector; - base::RunLoop run_loop; - event_injector.Inject(window->GetHost(), &event, run_loop.QuitClosure()); - run_loop.Run(); -} - -} // namespace namespace ash { @@ -53,8 +20,7 @@ ImmersiveFullscreenControllerTestApi::~ImmersiveFullscreenControllerTestApi() = default; -void ImmersiveFullscreenControllerTestApi::SetupForTest( - bool wait_for_mouse_event) { +void ImmersiveFullscreenControllerTestApi::SetupForTest() { immersive_fullscreen_controller_->animations_disabled_for_test_ = true; // Move the mouse off of the top-of-window views so that it does not keep the @@ -68,9 +34,7 @@ bottommost_in_screen = bounds_in_screen[i].bottom(); } gfx::Point cursor_pos(0, bottommost_in_screen + 10); - UpdateMouseLocation( - immersive_fullscreen_controller_->widget()->GetNativeView(), cursor_pos, - wait_for_mouse_event); + aura::Env::GetInstance()->SetLastMouseLocation(cursor_pos); immersive_fullscreen_controller_->UpdateLocatedEventRevealedLock(); }
diff --git a/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h b/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h index 6d510fa..d8fb97e 100644 --- a/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h +++ b/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h
@@ -30,11 +30,8 @@ }; // Disables animations and moves the mouse so that it is not over the - // top-of-window views for the sake of testing. |wait_for_mouse_move| should - // normally be true to wait for the generated mouse events to go through under - // mash. It is provided for tests that call SetupForTest under the scope of - // TestMockTimeTaskRunner::ScopedContext that does not allow RunLoop::Run(). - void SetupForTest(bool wait_for_mouse_event = true); + // top-of-window views for the sake of testing. + void SetupForTest(); bool IsTopEdgeHoverTimerRunning() const;
diff --git a/ash/public/cpp/window_properties.cc b/ash/public/cpp/window_properties.cc index 1aafd21..5e3a4a7 100644 --- a/ash/public/cpp/window_properties.cc +++ b/ash/public/cpp/window_properties.cc
@@ -10,16 +10,7 @@ #include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/window_pin_type.mojom.h" #include "ash/public/interfaces/window_properties.mojom.h" -#include "base/bind.h" -#include "base/unguessable_token.h" -#include "services/ws/public/mojom/window_manager.mojom.h" -#include "ui/accessibility/platform/aura_window_properties.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/mus/property_converter.h" #include "ui/aura/window.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/image/image_skia.h" #include "ui/wm/core/window_properties.h" DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_PUBLIC_EXPORT, @@ -29,123 +20,6 @@ ash::BackdropWindowMode) namespace ash { -namespace { - -bool IsValidWindowVisibilityAnimationTransition(int64_t value) { - return value == wm::ANIMATE_SHOW || value == wm::ANIMATE_HIDE || - value == wm::ANIMATE_BOTH || value == wm::ANIMATE_NONE; -} - -bool IsValidWindowPinType(int64_t value) { - return value == static_cast<int64_t>(mojom::WindowPinType::NONE) || - value == static_cast<int64_t>(mojom::WindowPinType::PINNED) || - value == static_cast<int64_t>(mojom::WindowPinType::TRUSTED_PINNED); -} - -} // namespace - -void RegisterWindowProperties(aura::PropertyConverter* property_converter) { - property_converter->RegisterStringProperty( - kArcPackageNameKey, ws::mojom::WindowManager::kArcPackageName_Property); - property_converter->RegisterPrimitiveProperty( - aura::client::kAppType, mojom::kAppType_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kBlockedForAssistantSnapshotKey, - mojom::kBlockedForAssistantSnapshot_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kCanAttachToAnotherWindowKey, mojom::kCanAttachToAnotherWindow_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kCanConsumeSystemKeysKey, mojom::kCanConsumeSystemKeys_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterStringProperty( - ui::kChildAXTreeID, ws::mojom::WindowManager::kChildAXTreeID_Property); - property_converter->RegisterPrimitiveProperty( - kFrameActiveColorKey, - ws::mojom::WindowManager::kFrameActiveColor_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kFrameInactiveColorKey, - ws::mojom::WindowManager::kFrameInactiveColor_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kHideInOverviewKey, mojom::kHideInOverview_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kHideShelfWhenFullscreenKey, mojom::kHideShelfWhenFullscreen_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kImmersiveImpliedByFullscreen, - mojom::kImmersiveImpliedByFullscreen_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kImmersiveIsActive, mojom::kImmersiveIsActive_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterRectProperty( - kImmersiveTopContainerBoundsInScreen, - mojom::kImmersiveTopContainerBoundsInScreen_Property); - property_converter->RegisterPrimitiveProperty( - kIsDeferredTabDraggingTargetWindowKey, - mojom::kIsDeferredTabDraggingTargetWindow_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kIsDraggingTabsKey, mojom::kIsDraggingTabs_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kIsShowingInOverviewKey, mojom::kIsShowingInOverview_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kRenderTitleAreaProperty, - ws::mojom::WindowManager::kRenderParentTitleArea_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kShelfItemTypeKey, ws::mojom::WindowManager::kShelfItemType_Property, - base::BindRepeating(&IsValidShelfItemType)); - property_converter->RegisterPrimitiveProperty( - aura::client::kTopViewInset, mojom::kTopViewInset_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - kWindowPinTypeKey, mojom::kWindowPinType_Property, - base::BindRepeating(&IsValidWindowPinType)); - property_converter->RegisterPrimitiveProperty( - kWindowPositionManagedTypeKey, mojom::kWindowPositionManaged_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterStringProperty( - kShelfIDKey, ws::mojom::WindowManager::kShelfID_Property); - property_converter->RegisterRectProperty( - kRestoreBoundsOverrideKey, mojom::kRestoreBoundsOverride_Property); - property_converter->RegisterPrimitiveProperty( - kRestoreWindowStateTypeOverrideKey, - mojom::kRestoreWindowStateTypeOverride_Property, - base::BindRepeating(&IsValidWindowStateType)); - property_converter->RegisterPrimitiveProperty( - aura::client::kTitleShownKey, - ws::mojom::WindowManager::kWindowTitleShown_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterWindowPtrProperty( - kTabDraggingSourceWindowKey, mojom::kTabDraggingSourceWindow_Property); - property_converter->RegisterPrimitiveProperty( - kWindowPipTypeKey, mojom::kIsWindowPip_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterTimeDeltaProperty( - wm::kWindowVisibilityAnimationDurationKey, - ws::mojom::WindowManager::kWindowVisibilityAnimationDuration_Property); - property_converter->RegisterPrimitiveProperty( - wm::kWindowVisibilityAnimationTransitionKey, - ws::mojom::WindowManager::kWindowVisibilityAnimationTransition_Property, - base::BindRepeating(&IsValidWindowVisibilityAnimationTransition)); - property_converter->RegisterPrimitiveProperty( - wm::kWindowVisibilityAnimationTypeKey, - ws::mojom::WindowManager::kWindowVisibilityAnimationType_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); - property_converter->RegisterPrimitiveProperty( - wm::kWindowVisibilityAnimationVerticalPositionKey, - ws::mojom::WindowManager:: - kWindowVisibilityAnimationVerticalPosition_Property, - aura::PropertyConverter::CreateAcceptAnyValueCallback()); -} DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kArcPackageNameKey, nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(BackdropWindowMode,
diff --git a/ash/public/cpp/window_properties.h b/ash/public/cpp/window_properties.h index 56e8f7e..b4e895b6 100644 --- a/ash/public/cpp/window_properties.h +++ b/ash/public/cpp/window_properties.h
@@ -13,7 +13,6 @@ #include "ui/base/class_property.h" namespace aura { -class PropertyConverter; class Window; template <typename T> using WindowProperty = ui::ClassProperty<T>; @@ -37,11 +36,6 @@ kAuto, // The window manager decides if the window should have a backdrop. }; -// Registers Ash's properties with the given PropertyConverter. This allows Ash -// and other services (eg. Chrome) to exchange Ash window property values. -ASH_PUBLIC_EXPORT void RegisterWindowProperties( - aura::PropertyConverter* property_converter); - // Shell-specific window property keys for use by ash and its clients. // Alphabetical sort.
diff --git a/ash/wm/collision_detection/collision_detection_utils.cc b/ash/wm/collision_detection/collision_detection_utils.cc index 0543e19..d7314e60 100644 --- a/ash/wm/collision_detection/collision_detection_utils.cc +++ b/ash/wm/collision_detection/collision_detection_utils.cc
@@ -9,7 +9,6 @@ #include "ash/shell.h" #include "ash/wm/work_area_insets.h" #include "base/macros.h" -#include "ui/aura/mus/property_converter.h" #include "ui/base/class_property.h" #include "ui/wm/core/coordinate_conversion.h"
diff --git a/base/BUILD.gn b/base/BUILD.gn index 4831633..5e65bd0 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -846,8 +846,6 @@ "task/thread_pool/thread_group_native_mac.mm", "task/thread_pool/thread_group_native_win.cc", "task/thread_pool/thread_group_native_win.h", - "task/thread_pool/thread_group_params.cc", - "task/thread_pool/thread_group_params.h", "task/thread_pool/thread_pool.cc", "task/thread_pool/thread_pool.h", "task/thread_pool/thread_pool_impl.cc", @@ -856,7 +854,6 @@ "task/thread_pool/worker_thread.cc", "task/thread_pool/worker_thread.h", "task/thread_pool/worker_thread_observer.h", - "task/thread_pool/worker_thread_params.h", "task/thread_pool/worker_thread_stack.cc", "task/thread_pool/worker_thread_stack.h", "task_runner.cc", @@ -864,8 +861,6 @@ "task_runner_util.h", "template_util.h", "test/malloc_wrapper.h", - "third_party/cityhash/city.cc", - "third_party/cityhash/city.h", "third_party/dmg_fp/dmg_fp.h", "third_party/dmg_fp/dtoa_wrapper.cc", "third_party/dmg_fp/g_fmt.cc",
diff --git a/base/hash/hash.cc b/base/hash/hash.cc index 778aa6f2..988daea5a 100644 --- a/base/hash/hash.cc +++ b/base/hash/hash.cc
@@ -4,9 +4,6 @@ #include "base/hash/hash.h" -#include "base/third_party/cityhash/city.h" -#include "build/build_config.h" - // Definition in base/third_party/superfasthash/superfasthash.c. (Third-party // code did not come with its own header file, so declaring the function here.) // Note: This algorithm is also in Blink under Source/wtf/StringHasher.h. @@ -14,26 +11,6 @@ namespace base { -size_t FastHash(base::span<const uint8_t> data) { - // We use the updated CityHash within our namespace (not the deprecated - // version from third_party/smhasher). -#if defined(ARCH_CPU_64_BITS) - return base::internal::cityhash_v111::CityHash64( - reinterpret_cast<const char*>(data.data()), data.size()); -#else - return base::internal::cityhash_v111::CityHash32( - reinterpret_cast<const char*>(data.data()), data.size()); -#endif -} - -size_t FastHash(const std::string& str) { -#if defined(ARCH_CPU_64_BITS) - return base::internal::cityhash_v111::CityHash64(str.data(), str.size()); -#else - return base::internal::cityhash_v111::CityHash32(str.data(), str.size()); -#endif -} - uint32_t Hash(const void* data, size_t length) { // Currently our in-memory hash is the same as the persistent hash. The // split between in-memory and persistent hash functions is maintained to
diff --git a/base/hash/hash.h b/base/hash/hash.h index 0f98e4f5..4bf6829 100644 --- a/base/hash/hash.h +++ b/base/hash/hash.h
@@ -13,32 +13,20 @@ #include <utility> #include "base/base_export.h" -#include "base/containers/span.h" #include "base/logging.h" #include "base/strings/string16.h" namespace base { -// WARNING: This hash functions should not be used for any cryptographic -// purpose. - -// Deprecated: Computes a hash of a memory buffer, use FastHash() instead. -// If you need to persist a change on disk or between computers, use -// PersistentHash(). -// TODO(cavalcantii): Migrate client code to new hash function. +// Computes a hash of a memory buffer. This hash function is subject to change +// in the future, so use only for temporary in-memory structures. If you need +// to persist a change on disk or between computers, use PersistentHash(). +// +// WARNING: This hash function should not be used for any cryptographic purpose. BASE_EXPORT uint32_t Hash(const void* data, size_t length); BASE_EXPORT uint32_t Hash(const std::string& str); BASE_EXPORT uint32_t Hash(const string16& str); -// Really *fast* and high quality hash. -// Recommended hash function for general use, we pick the best performant -// hash for each build target. -// It is prone to be updated whenever a newer/faster hash function is -// publicly available. -// May changed without warning, do not expect stability of outputs. -BASE_EXPORT size_t FastHash(base::span<const uint8_t> data); -BASE_EXPORT size_t FastHash(const std::string& str); - // Computes a hash of a memory buffer. This hash function must not change so // that code can use the hashed values for persistent storage purposes or // sending across the network. If a new persistent hash function is desired, a
diff --git a/base/task/promise/abstract_promise.cc b/base/task/promise/abstract_promise.cc index d52997d..0bd5f01 100644 --- a/base/task/promise/abstract_promise.cc +++ b/base/task/promise/abstract_promise.cc
@@ -398,6 +398,10 @@ return; } + // The executor could be keeping a promise alive, but it's never going to run + // so clear it. + value_ = unique_any(); + #if DCHECK_IS_ON() { CheckedAutoLock lock(GetCheckedLock());
diff --git a/base/task/promise/abstract_promise.h b/base/task/promise/abstract_promise.h index 6656229..33dde53 100644 --- a/base/task/promise/abstract_promise.h +++ b/base/task/promise/abstract_promise.h
@@ -24,9 +24,16 @@ // contain the empty type Void. This is the same idea as std::monospace. struct Void {}; +// Signals that a promise doesn't resolve. E.g. Promise<NoResolve, int> +struct NoResolve {}; + // Signals that a promise doesn't reject. E.g. Promise<int, NoReject> struct NoReject {}; +// A promise for either |ResolveType| if successful or |RejectType| on error. +template <typename ResolveType, typename RejectType> +class Promise; + // This enum is used to configure AbstractPromise's uncaught reject detection. // Usually not catching a reject reason is a coding error, but at times that can // become onerous. When that happens kCatchNotRequired should be used. @@ -42,7 +49,13 @@ struct BASE_EXPORT Resolved { using Type = T; - Resolved() = default; + static_assert(!std::is_same<T, NoReject>::value, + "Can't have Resolved<NoReject>"); + + Resolved() { + static_assert(!std::is_same<T, NoResolve>::value, + "Can't have Resolved<NoResolve>"); + } template <typename... Args> Resolved(Args&&... args) noexcept : value(std::forward<Args>(args)...) {} @@ -64,10 +77,19 @@ using Type = T; T value; - Rejected() = default; + static_assert(!std::is_same<T, NoResolve>::value, + "Can't have Rejected<NoResolve>"); + + Rejected() { + static_assert(!std::is_same<T, NoReject>::value, + "Can't have Rejected<NoReject>"); + } template <typename... Args> - Rejected(Args&&... args) noexcept : value(std::forward<Args>(args)...) {} + Rejected(Args&&... args) noexcept : value(std::forward<Args>(args)...) { + static_assert(!std::is_same<T, NoReject>::value, + "Can't have Rejected<NoReject>"); + } }; template <>
diff --git a/base/task/promise/abstract_promise_unittest.cc b/base/task/promise/abstract_promise_unittest.cc index fab3f5b..387eb235 100644 --- a/base/task/promise/abstract_promise_unittest.cc +++ b/base/task/promise/abstract_promise_unittest.cc
@@ -1850,8 +1850,6 @@ FROM_HERE, BindOnce(&AbstractPromise::Execute, p2)); p->emplace(p2); p->OnResolved(); - - EXPECT_TRUE(p3->IsResolvedWithPromise()); })); scoped_refptr<AbstractPromise> p4 =
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc index a457c288..f0f221b9 100644 --- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc +++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -3817,7 +3817,7 @@ [](base::OnceClosure task, scoped_refptr<TestTaskQueue> task_queue) { task_queue->task_runner()->PostTask(FROM_HERE, std::move(task)); }, - base::Passed(std::move(task)), task_queue)); + std::move(task), task_queue)); } } // namespace
diff --git a/base/task/task_features.h b/base/task/task_features.h index cc24bd69..169fa098 100644 --- a/base/task/task_features.h +++ b/base/task/task_features.h
@@ -25,6 +25,12 @@ extern const BASE_EXPORT Feature kMayBlockWithoutDelay; #if defined(OS_WIN) || defined(OS_MACOSX) +#define HAS_NATIVE_THREAD_POOL() 1 +#else +#define HAS_NATIVE_THREAD_POOL() 0 +#endif + +#if HAS_NATIVE_THREAD_POOL() // Under this feature, ThreadPool will use a ThreadGroup backed by a // native thread pool implementation. The Windows Thread Pool API and // libdispatch are used on Windows and macOS/iOS respectively.
diff --git a/base/task/thread_pool/pooled_single_thread_task_runner_manager_unittest.cc b/base/task/thread_pool/pooled_single_thread_task_runner_manager_unittest.cc index 8de4fe9e..8015f13 100644 --- a/base/task/thread_pool/pooled_single_thread_task_runner_manager_unittest.cc +++ b/base/task/thread_pool/pooled_single_thread_task_runner_manager_unittest.cc
@@ -17,7 +17,6 @@ #include "base/task/thread_pool/environment_config.h" #include "base/task/thread_pool/task_tracker.h" #include "base/task/thread_pool/test_utils.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/test/bind_test_util.h" #include "base/test/gtest_util.h" #include "base/test/test_timeouts.h"
diff --git a/base/task/thread_pool/test_utils.h b/base/task/thread_pool/test_utils.h index d4f33c0..c894bb8 100644 --- a/base/task/thread_pool/test_utils.h +++ b/base/task/thread_pool/test_utils.h
@@ -6,6 +6,7 @@ #define BASE_TASK_THREAD_POOL_TEST_UTILS_H_ #include "base/task/common/checked_lock.h" +#include "base/task/task_features.h" #include "base/task/task_traits.h" #include "base/task/thread_pool/delayed_task_manager.h" #include "base/task/thread_pool/pooled_task_runner_delegate.h" @@ -74,7 +75,7 @@ // thread_pool tests. enum class PoolType { GENERIC, -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() NATIVE, #endif };
diff --git a/base/task/thread_pool/thread_group.cc b/base/task/thread_pool/thread_group.cc index b3b5177..0a38cbe0 100644 --- a/base/task/thread_pool/thread_group.cc +++ b/base/task/thread_pool/thread_group.cc
@@ -12,6 +12,13 @@ #include "base/task/thread_pool/task_tracker.h" #include "base/threading/thread_local.h" +#if defined(OS_WIN) +#include "base/win/com_init_check_hook.h" +#include "base/win/scoped_com_initializer.h" +#include "base/win/scoped_winrt_initializer.h" +#include "base/win/windows_version.h" +#endif + namespace base { namespace internal { @@ -148,5 +155,38 @@ replacement_thread_group_ = destination_thread_group; } +#if defined(OS_WIN) +// static +std::unique_ptr<win::ScopedWindowsThreadEnvironment> +ThreadGroup::GetScopedWindowsThreadEnvironment(WorkerEnvironment environment) { + std::unique_ptr<win::ScopedWindowsThreadEnvironment> scoped_environment; + switch (environment) { + case WorkerEnvironment::COM_MTA: { + if (win::GetVersion() >= win::Version::WIN8) { + scoped_environment = std::make_unique<win::ScopedWinrtInitializer>(); + } else { + scoped_environment = std::make_unique<win::ScopedCOMInitializer>( + win::ScopedCOMInitializer::kMTA); + } + break; + } + case WorkerEnvironment::COM_STA: { + // When defined(COM_INIT_CHECK_HOOK_ENABLED), ignore + // WorkerEnvironment::COM_STA to find incorrect uses of + // COM that should be running in a COM STA Task Runner. +#if !defined(COM_INIT_CHECK_HOOK_ENABLED) + scoped_environment = std::make_unique<win::ScopedCOMInitializer>(); +#endif + break; + } + default: + break; + } + + DCHECK(!scoped_environment || scoped_environment->Succeeded()); + return scoped_environment; +} +#endif + } // namespace internal } // namespace base
diff --git a/base/task/thread_pool/thread_group.h b/base/task/thread_pool/thread_group.h index 3550b190..38a081e 100644 --- a/base/task/thread_pool/thread_group.h +++ b/base/task/thread_pool/thread_group.h
@@ -14,6 +14,10 @@ #include "base/task/thread_pool/tracked_ref.h" #include "build/build_config.h" +#if defined(OS_WIN) +#include "base/win/scoped_windows_thread_environment.h" +#endif + namespace base { namespace internal { @@ -41,6 +45,8 @@ #if defined(OS_WIN) // Initialize a COM MTA on the worker. COM_MTA, + // Initialize a COM STA on the worker. + COM_STA, #endif // defined(OS_WIN) }; @@ -151,6 +157,11 @@ TrackedRef<Delegate> delegate, ThreadGroup* predecessor_thread_group = nullptr); +#if defined(OS_WIN) + static std::unique_ptr<win::ScopedWindowsThreadEnvironment> + GetScopedWindowsThreadEnvironment(WorkerEnvironment environment); +#endif + const TrackedRef<TaskTracker> task_tracker_; const TrackedRef<Delegate> delegate_;
diff --git a/base/task/thread_pool/thread_group_impl.cc b/base/task/thread_pool/thread_group_impl.cc index 4912b4e1..ab777c6 100644 --- a/base/task/thread_pool/thread_group_impl.cc +++ b/base/task/thread_pool/thread_group_impl.cc
@@ -26,7 +26,6 @@ #include "base/task/task_features.h" #include "base/task/task_traits.h" #include "base/task/thread_pool/task_tracker.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/threading/platform_thread.h" #include "base/threading/scoped_blocking_call.h" #include "base/threading/thread_checker.h" @@ -382,8 +381,9 @@ } void ThreadGroupImpl::Start( - const ThreadGroupParams& params, + int max_tasks, int max_best_effort_tasks, + TimeDelta suggested_reclaim_time, scoped_refptr<TaskRunner> service_thread_task_runner, WorkerThreadObserver* worker_thread_observer, WorkerEnvironment worker_environment, @@ -407,13 +407,12 @@ priority_hint_ == ThreadPriority::NORMAL ? kForegroundBlockedWorkersPoll : kBackgroundBlockedWorkersPoll; - max_tasks_ = params.max_tasks(); + max_tasks_ = max_tasks; DCHECK_GE(max_tasks_, 1U); in_start().initial_max_tasks = max_tasks_; DCHECK_LE(in_start().initial_max_tasks, kMaxNumberOfWorkers); max_best_effort_tasks_ = max_best_effort_tasks; - in_start().suggested_reclaim_time = params.suggested_reclaim_time(); - in_start().backward_compatibility = params.backward_compatibility(); + in_start().suggested_reclaim_time = suggested_reclaim_time; in_start().worker_environment = worker_environment; in_start().service_thread_task_runner = std::move(service_thread_task_runner); in_start().worker_thread_observer = worker_thread_observer; @@ -569,17 +568,8 @@ } #if defined(OS_WIN) - if (outer_->after_start().worker_environment == WorkerEnvironment::COM_MTA) { - if (win::GetVersion() >= win::Version::WIN8) { - worker_only().win_thread_environment = - std::make_unique<win::ScopedWinrtInitializer>(); - } else { - worker_only().win_thread_environment = - std::make_unique<win::ScopedCOMInitializer>( - win::ScopedCOMInitializer::kMTA); - } - DCHECK(worker_only().win_thread_environment->Succeeded()); - } + worker_only().win_thread_environment = GetScopedWindowsThreadEnvironment( + outer_->after_start().worker_environment); #endif // defined(OS_WIN) DCHECK_EQ(worker_only().num_tasks_since_last_wait, 0U); @@ -989,11 +979,11 @@ // WorkerThread needs |lock_| as a predecessor for its thread lock // because in WakeUpOneWorker, |lock_| is first acquired and then // the thread lock is acquired when WakeUp is called on the worker. - scoped_refptr<WorkerThread> worker = MakeRefCounted<WorkerThread>( - priority_hint_, - std::make_unique<WorkerThreadDelegateImpl>( - tracked_ref_factory_.GetTrackedRef()), - task_tracker_, &lock_, after_start().backward_compatibility); + scoped_refptr<WorkerThread> worker = + MakeRefCounted<WorkerThread>(priority_hint_, + std::make_unique<WorkerThreadDelegateImpl>( + tracked_ref_factory_.GetTrackedRef()), + task_tracker_, &lock_); workers_.push_back(worker); executor->ScheduleStart(worker);
diff --git a/base/task/thread_pool/thread_group_impl.h b/base/task/thread_pool/thread_group_impl.h index 0542525..b640d91 100644 --- a/base/task/thread_pool/thread_group_impl.h +++ b/base/task/thread_pool/thread_group_impl.h
@@ -36,7 +36,6 @@ class HistogramBase; class WorkerThreadObserver; -class ThreadGroupParams; namespace internal { @@ -64,10 +63,11 @@ TrackedRef<TaskTracker> task_tracker, TrackedRef<Delegate> delegate); - // Creates workers following the |params| specification, allowing existing and - // future tasks to run. The thread group runs at most |max_best_effort_tasks| - // unblocked BEST_EFFORT tasks concurrently, uses |service_thread_task_runner| - // to monitor for blocked tasks, and, if specified, notifies + // Creates threads, allowing existing and future tasks to run. The thread + // group runs at most |max_tasks| / |max_best_effort_tasks| unblocked task + // with any / BEST_EFFORT priority concurrently. It reclaims unused threads + // after |suggested_reclaim_time|. It uses |service_thread_task_runner| to + // monitor for blocked tasks. If specified, it notifies // |worker_thread_observer| when a worker enters and exits its main function // (the observer must not be destroyed before JoinForTesting() has returned). // |worker_environment| specifies the environment in which tasks are executed. @@ -75,8 +75,9 @@ // ScopedBlockingCall is considered blocked (the thread group will choose an // appropriate value if none is specified). Can only be called once. CHECKs on // failure. - void Start(const ThreadGroupParams& params, + void Start(int max_tasks, int max_best_effort_tasks, + TimeDelta suggested_reclaim_time, scoped_refptr<TaskRunner> service_thread_task_runner, WorkerThreadObserver* worker_thread_observer, WorkerEnvironment worker_environment, @@ -228,8 +229,6 @@ // Suggested reclaim time for workers. TimeDelta suggested_reclaim_time; - WorkerThreadBackwardCompatibility backward_compatibility; - // Environment to be initialized per worker. WorkerEnvironment worker_environment = WorkerEnvironment::NONE;
diff --git a/base/task/thread_pool/thread_group_impl_unittest.cc b/base/task/thread_pool/thread_group_impl_unittest.cc index d87f681..87e63e71 100644 --- a/base/task/thread_pool/thread_group_impl_unittest.cc +++ b/base/task/thread_pool/thread_group_impl_unittest.cc
@@ -35,7 +35,6 @@ #include "base/task/thread_pool/task_tracker.h" #include "base/task/thread_pool/test_task_factory.h" #include "base/task/thread_pool/test_utils.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/task/thread_pool/worker_thread_observer.h" #include "base/task_runner.h" #include "base/test/bind_test_util.h" @@ -102,9 +101,9 @@ Optional<TimeDelta> may_block_threshold = nullopt) { ASSERT_TRUE(thread_group_); thread_group_->Start( - ThreadGroupParams(max_tasks, suggested_reclaim_time), + max_tasks, max_best_effort_tasks ? max_best_effort_tasks.value() : max_tasks, - service_thread_.task_runner(), worker_observer, + suggested_reclaim_time, service_thread_.task_runner(), worker_observer, ThreadGroup::WorkerEnvironment::NONE, may_block_threshold); } @@ -1716,9 +1715,9 @@ void SetUp() override { CreateThreadGroup(); - thread_group_->Start(ThreadGroupParams(kMaxTasks, base::TimeDelta::Max()), - kMaxBestEffortTasks, service_thread_.task_runner(), - nullptr, ThreadGroup::WorkerEnvironment::NONE); + thread_group_->Start(kMaxTasks, kMaxBestEffortTasks, base::TimeDelta::Max(), + service_thread_.task_runner(), nullptr, + ThreadGroup::WorkerEnvironment::NONE); } void TearDown() override { ThreadGroupImplImplTestBase::CommonTearDown(); } @@ -1801,10 +1800,10 @@ constexpr TimeDelta kReclaimTimeForRacyCleanupTest = TimeDelta::FromMilliseconds(10); - thread_group_->Start( - ThreadGroupParams(kLocalMaxTasks, kReclaimTimeForRacyCleanupTest), - kLocalMaxTasks, service_thread_.task_runner(), nullptr, - ThreadGroup::WorkerEnvironment::NONE); + thread_group_->Start(kLocalMaxTasks, kLocalMaxTasks, + kReclaimTimeForRacyCleanupTest, + service_thread_.task_runner(), nullptr, + ThreadGroup::WorkerEnvironment::NONE); scoped_refptr<TaskRunner> task_runner = test::CreateTaskRunnerWithTraits( {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
diff --git a/base/task/thread_pool/thread_group_native_win.cc b/base/task/thread_pool/thread_group_native_win.cc index 317293f1..4b8c5d2 100644 --- a/base/task/thread_pool/thread_group_native_win.cc +++ b/base/task/thread_pool/thread_group_native_win.cc
@@ -88,9 +88,8 @@ // Windows Thread Pool API best practices state that all resources created // in the callback function should be cleaned up before returning from the // function. This includes COM initialization. - Optional<win::ScopedCOMInitializer> com_initializer; - if (thread_group->worker_environment_ == WorkerEnvironment::COM_MTA) - com_initializer.emplace(win::ScopedCOMInitializer::kMTA); + auto win_thread_environment = thread_group->GetScopedWindowsThreadEnvironment( + thread_group->worker_environment_); ScopedCallbackMayRunLongObserver callback_may_run_long_observer( callback_instance);
diff --git a/base/task/thread_pool/thread_group_params.cc b/base/task/thread_pool/thread_group_params.cc deleted file mode 100644 index 3ff314b9..0000000 --- a/base/task/thread_pool/thread_group_params.cc +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/task/thread_pool/thread_group_params.h" - -namespace base { - -ThreadGroupParams::ThreadGroupParams( - int max_tasks, - TimeDelta suggested_reclaim_time, - WorkerThreadBackwardCompatibility backward_compatibility) - : max_tasks_(max_tasks), - suggested_reclaim_time_(suggested_reclaim_time), - backward_compatibility_(backward_compatibility) {} - -ThreadGroupParams::ThreadGroupParams(const ThreadGroupParams& other) = default; - -ThreadGroupParams& ThreadGroupParams::operator=( - const ThreadGroupParams& other) = default; - -} // namespace base
diff --git a/base/task/thread_pool/thread_group_params.h b/base/task/thread_pool/thread_group_params.h deleted file mode 100644 index 8b3df3b0f..0000000 --- a/base/task/thread_pool/thread_group_params.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TASK_THREAD_POOL_THREAD_GROUP_PARAMS_H_ -#define BASE_TASK_THREAD_POOL_THREAD_GROUP_PARAMS_H_ - -#include "base/task/thread_pool/worker_thread_params.h" -#include "base/time/time.h" - -namespace base { - -class BASE_EXPORT ThreadGroupParams final { - public: - // Constructs a set of params used to initialize a ThreadGroup. The - // ThreadGroup will run concurrently at most |max_tasks| that aren't blocked - // (ScopedBlockingCall). |suggested_reclaim_time| sets a suggestion on when to - // reclaim idle threads. The ThreadGroup is free to ignore this value for - // performance or correctness reasons. |backward_compatibility| indicates - // whether backward compatibility is enabled. - ThreadGroupParams(int max_tasks, - TimeDelta suggested_reclaim_time, - WorkerThreadBackwardCompatibility backward_compatibility = - WorkerThreadBackwardCompatibility::DISABLED); - - ThreadGroupParams(const ThreadGroupParams& other); - ThreadGroupParams& operator=(const ThreadGroupParams& other); - - int max_tasks() const { return max_tasks_; } - TimeDelta suggested_reclaim_time() const { return suggested_reclaim_time_; } - WorkerThreadBackwardCompatibility backward_compatibility() const { - return backward_compatibility_; - } - - private: - int max_tasks_; - TimeDelta suggested_reclaim_time_; - WorkerThreadBackwardCompatibility backward_compatibility_; -}; - -} // namespace base - -#endif // BASE_TASK_THREAD_POOL_THREAD_GROUP_PARAMS_H_
diff --git a/base/task/thread_pool/thread_group_unittest.cc b/base/task/thread_pool/thread_group_unittest.cc index 42cc66f..3a84ca8f 100644 --- a/base/task/thread_pool/thread_group_unittest.cc +++ b/base/task/thread_pool/thread_group_unittest.cc
@@ -19,7 +19,6 @@ #include "base/task/thread_pool/test_task_factory.h" #include "base/task/thread_pool/test_utils.h" #include "base/task/thread_pool/thread_group_impl.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/task_runner.h" #include "base/test/bind_test_util.h" #include "base/test/test_timeouts.h" @@ -33,6 +32,7 @@ #if defined(OS_WIN) #include "base/task/thread_pool/thread_group_native_win.h" +#include "base/win/com_init_check_hook.h" #include "base/win/com_init_util.h" #elif defined(OS_MACOSX) #include "base/task/thread_pool/thread_group_native_mac.h" @@ -43,7 +43,7 @@ namespace { -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() using ThreadGroupNativeType = #if defined(OS_WIN) ThreadGroupNativeWin; @@ -129,7 +129,7 @@ task_tracker_.GetTrackedRef(), tracked_ref_factory_.GetTrackedRef()); break; -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() case test::PoolType::NATIVE: thread_group_ = std::make_unique<ThreadGroupNativeType>( task_tracker_.GetTrackedRef(), @@ -150,11 +150,11 @@ ThreadGroupImpl* thread_group_impl = static_cast<ThreadGroupImpl*>(thread_group_.get()); thread_group_impl->Start( - ThreadGroupParams(kMaxTasks, TimeDelta::Max()), kMaxBestEffortTasks, + kMaxTasks, kMaxBestEffortTasks, TimeDelta::Max(), service_thread_.task_runner(), nullptr, worker_environment); break; } -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() case test::PoolType::NATIVE: { ThreadGroupNativeType* thread_group_native_impl = static_cast<ThreadGroupNativeType*>(thread_group_.get()); @@ -476,6 +476,28 @@ task_ran.Wait(); } +TEST_P(ThreadGroupTest, COMSTAWorkerEnvironment) { + StartThreadGroup(ThreadGroup::WorkerEnvironment::COM_STA); + auto task_runner = test::CreateTaskRunnerWithExecutionMode( + GetParam().execution_mode, &mock_pooled_task_runner_delegate_); + + WaitableEvent task_ran; + task_runner->PostTask( + FROM_HERE, BindOnce( + [](WaitableEvent* task_ran) { + // COM STA is ignored when defined(COM_INIT_CHECK_HOOK_ENABLED). See comment + // in ThreadGroup::GetScopedWindowsThreadEnvironment(). +#if defined(COM_INIT_CHECK_HOOK_ENABLED) + win::AssertComApartmentType(win::ComApartmentType::NONE); +#else + win::AssertComApartmentType(win::ComApartmentType::STA); +#endif + task_ran->Signal(); + }, + Unretained(&task_ran))); + task_ran.Wait(); +} + TEST_P(ThreadGroupTest, NoWorkerEnvironment) { StartThreadGroup(ThreadGroup::WorkerEnvironment::NONE); auto task_runner = test::CreateTaskRunnerWithExecutionMode( @@ -504,7 +526,7 @@ test::PoolType::GENERIC, TaskSourceExecutionMode::kSequenced})); -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() INSTANTIATE_TEST_SUITE_P(NativeParallel, ThreadGroupTest, ::testing::Values(PoolExecutionType{
diff --git a/base/task/thread_pool/thread_pool.cc b/base/task/thread_pool/thread_pool.cc index 36d9103a..300e16ed 100644 --- a/base/task/thread_pool/thread_pool.cc +++ b/base/task/thread_pool/thread_pool.cc
@@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/system/sys_info.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/task/thread_pool/thread_pool_impl.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" @@ -23,13 +22,8 @@ } // namespace -ThreadPool::InitParams::InitParams( - const ThreadGroupParams& background_thread_group_params_in, - const ThreadGroupParams& foreground_thread_group_params_in, - CommonThreadPoolEnvironment common_thread_pool_environment_in) - : background_thread_group_params(background_thread_group_params_in), - foreground_thread_group_params(foreground_thread_group_params_in), - common_thread_pool_environment(common_thread_pool_environment_in) {} +ThreadPool::InitParams::InitParams(int max_num_foreground_threads_in) + : max_num_foreground_threads(max_num_foreground_threads_in) {} ThreadPool::InitParams::~InitParams() = default; @@ -58,15 +52,8 @@ // * The main thread is assumed to be busy, cap foreground workers at // |num_cores - 1|. const int num_cores = SysInfo::NumberOfProcessors(); - - // TODO(etiennep): Change this to 2. - constexpr int kBackgroundMaxThreads = 3; - const int kForegroundMaxThreads = std::max(3, num_cores - 1); - - constexpr TimeDelta kSuggestedReclaimTime = TimeDelta::FromSeconds(30); - - Start({{kBackgroundMaxThreads, kSuggestedReclaimTime}, - {kForegroundMaxThreads, kSuggestedReclaimTime}}); + const int max_num_foreground_threads = std::max(3, num_cores - 1); + Start({max_num_foreground_threads}); } #endif // !defined(OS_NACL)
diff --git a/base/task/thread_pool/thread_pool.h b/base/task/thread_pool/thread_pool.h index 15a71f0..c141741c 100644 --- a/base/task/thread_pool/thread_pool.h +++ b/base/task/thread_pool/thread_pool.h
@@ -18,7 +18,6 @@ #include "base/task/single_thread_task_runner_thread_mode.h" #include "base/task/task_executor.h" #include "base/task/task_traits.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/task_runner.h" #include "base/time/time.h" #include "build/build_config.h" @@ -58,18 +57,28 @@ #if defined(OS_WIN) // Place the pool's workers in a COM MTA. COM_MTA, + // Place the pool's *foreground* workers in a COM STA. This exists to + // mimic the behavior of SequencedWorkerPool and BrowserThreadImpl that + // ThreadPool has replaced. Tasks that need a COM STA should use + // CreateCOMSTATaskRunnerWithTraits() instead of + // Create(Sequenced)TaskRunnerWithTraits() + this init param. + DEPRECATED_COM_STA_IN_FOREGROUND_GROUP, #endif // defined(OS_WIN) }; - InitParams(const ThreadGroupParams& background_thread_group_params_in, - const ThreadGroupParams& foreground_thread_group_params_in, - CommonThreadPoolEnvironment common_thread_pool_environment_in = - CommonThreadPoolEnvironment::DEFAULT); + InitParams(int max_num_foreground_threads_in); ~InitParams(); - ThreadGroupParams background_thread_group_params; - ThreadGroupParams foreground_thread_group_params; - CommonThreadPoolEnvironment common_thread_pool_environment; + // Maximum number of unblocked tasks that can run concurrently in the + // foreground thread group. + int max_num_foreground_threads; + + // Whether COM is initialized when running sequenced and parallel tasks. + CommonThreadPoolEnvironment common_thread_pool_environment = + CommonThreadPoolEnvironment::DEFAULT; + + // Suggested time after which an unused thread can be reclaimed. + TimeDelta suggested_reclaim_time = TimeDelta::FromSeconds(30); }; // A ScopedExecutionFence prevents any new task from being scheduled in
diff --git a/base/task/thread_pool/thread_pool_impl.cc b/base/task/thread_pool/thread_pool_impl.cc index 3bf56c9..6c48c81 100644 --- a/base/task/thread_pool/thread_pool_impl.cc +++ b/base/task/thread_pool/thread_pool_impl.cc
@@ -26,7 +26,6 @@ #include "base/task/thread_pool/task.h" #include "base/task/thread_pool/task_source.h" #include "base/task/thread_pool/thread_group_impl.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" @@ -49,6 +48,8 @@ constexpr EnvironmentParams kBackgroundPoolEnvironmentParams{ "Background", base::ThreadPriority::BACKGROUND}; +constexpr int kMaxBestEffortTasks = 2; + // Indicates whether BEST_EFFORT tasks are disabled by a command line switch. bool HasDisableBestEffortTasksSwitch() { // The CommandLine might not be initialized if TaskScheduler is initialized @@ -112,12 +113,17 @@ internal::InitializeThreadPrioritiesFeature(); + // The max number of concurrent BEST_EFFORT tasks is |kMaxBestEffortTasks|, + // unless the max number of foreground threads is lower. + const int max_best_effort_tasks = + std::min(kMaxBestEffortTasks, init_params.max_num_foreground_threads); + // This is set in Start() and not in the constructor because variation params // are usually not ready when ThreadPoolImpl is instantiated in a process. if (FeatureList::IsEnabled(kAllTasksUserBlocking)) all_tasks_user_blocking_.Set(); -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() if (FeatureList::IsEnabled(kUseNativeThreadPool)) { std::unique_ptr<ThreadGroup> pool = std::move(foreground_thread_group_); foreground_thread_group_ = std::make_unique<ThreadGroupNativeImpl>( @@ -154,17 +160,23 @@ single_thread_task_runner_manager_.Start(worker_thread_observer); - const ThreadGroup::WorkerEnvironment worker_environment = + ThreadGroup::WorkerEnvironment worker_environment; + switch (init_params.common_thread_pool_environment) { + case InitParams::CommonThreadPoolEnvironment::DEFAULT: + worker_environment = ThreadGroup::WorkerEnvironment::NONE; + break; #if defined(OS_WIN) - init_params.common_thread_pool_environment == - InitParams::CommonThreadPoolEnvironment::COM_MTA - ? ThreadGroup::WorkerEnvironment::COM_MTA - : ThreadGroup::WorkerEnvironment::NONE; -#else - ThreadGroup::WorkerEnvironment::NONE; + case InitParams::CommonThreadPoolEnvironment::COM_MTA: + worker_environment = ThreadGroup::WorkerEnvironment::COM_MTA; + break; + case InitParams::CommonThreadPoolEnvironment:: + DEPRECATED_COM_STA_IN_FOREGROUND_GROUP: + worker_environment = ThreadGroup::WorkerEnvironment::COM_STA; + break; #endif + } -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() if (FeatureList::IsEnabled(kUseNativeThreadPool)) { static_cast<ThreadGroupNative*>(foreground_thread_group_.get()) ->Start(worker_environment); @@ -172,27 +184,29 @@ #endif { // On platforms that can't use the background thread priority, best-effort - // tasks run in foreground pools. A cap is set on the number of background + // tasks run in foreground pools. A cap is set on the number of best-effort // tasks that can run in foreground pools to ensure that there is always // room for incoming foreground tasks and to minimize the performance impact // of best-effort tasks. - - const int max_best_effort_tasks_in_foreground_thread_group = std::max( - 1, - std::min(init_params.background_thread_group_params.max_tasks(), - init_params.foreground_thread_group_params.max_tasks() / 2)); static_cast<ThreadGroupImpl*>(foreground_thread_group_.get()) - ->Start(init_params.foreground_thread_group_params, - max_best_effort_tasks_in_foreground_thread_group, - service_thread_task_runner, worker_thread_observer, - worker_environment); + ->Start(init_params.max_num_foreground_threads, max_best_effort_tasks, + init_params.suggested_reclaim_time, service_thread_task_runner, + worker_thread_observer, worker_environment); } if (background_thread_group_) { background_thread_group_->Start( - init_params.background_thread_group_params, - init_params.background_thread_group_params.max_tasks(), - service_thread_task_runner, worker_thread_observer, worker_environment); + max_best_effort_tasks, max_best_effort_tasks, + init_params.suggested_reclaim_time, service_thread_task_runner, + worker_thread_observer, +#if defined(OS_WIN) + // COM STA is a backward-compatibility feature for the foreground thread + // group only. + worker_environment == ThreadGroup::WorkerEnvironment::COM_STA + ? ThreadGroup::WorkerEnvironment::NONE + : +#endif + worker_environment); } started_ = true;
diff --git a/base/task/thread_pool/thread_pool_impl_unittest.cc b/base/task/thread_pool/thread_pool_impl_unittest.cc index 08a10180..8b1de64 100644 --- a/base/task/thread_pool/thread_pool_impl_unittest.cc +++ b/base/task/thread_pool/thread_pool_impl_unittest.cc
@@ -25,7 +25,6 @@ #include "base/task/thread_pool/environment_config.h" #include "base/task/thread_pool/test_task_factory.h" #include "base/task/thread_pool/test_utils.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/task/thread_pool/worker_thread_observer.h" #include "base/test/bind_test_util.h" #include "base/test/gtest_util.h" @@ -59,6 +58,8 @@ namespace { +constexpr int kMaxNumForegroundThreads = 4; + struct ThreadPoolImplTestParams { ThreadPoolImplTestParams(const TaskTraits& traits, TaskSourceExecutionMode execution_mode, @@ -100,7 +101,7 @@ (current_thread_name.find("SingleThread") != std::string::npos); const bool is_best_effort = (traits.priority() == TaskPriority::BEST_EFFORT); -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() // Native thread groups do not provide the ability to name threads. if (pool_type == test::PoolType::NATIVE && !is_single_threaded && !is_best_effort) { @@ -230,7 +231,7 @@ const test::PoolType pool_types[] = { test::PoolType::GENERIC, -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() test::PoolType::NATIVE, #endif }; @@ -266,15 +267,15 @@ worker_thread_observer_ = worker_thread_observer; } - void StartThreadPool(TimeDelta reclaim_time = TimeDelta::FromSeconds(30)) { - constexpr int kMaxNumBackgroundThreads = 1; - constexpr int kMaxNumForegroundThreads = 4; - + void StartThreadPool( + int max_num_foreground_threads = kMaxNumForegroundThreads, + TimeDelta reclaim_time = TimeDelta::FromSeconds(30)) { SetupFeatures(); - thread_pool_.Start({{kMaxNumBackgroundThreads, reclaim_time}, - {kMaxNumForegroundThreads, reclaim_time}}, - worker_thread_observer_); + ThreadPool::InitParams init_params(max_num_foreground_threads); + init_params.suggested_reclaim_time = reclaim_time; + + thread_pool_.Start(init_params, worker_thread_observer_); } void TearDown() override { @@ -295,7 +296,7 @@ if (should_enable_all_tasks_user_blocking_) features.push_back(kAllTasksUserBlocking); -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() if (GetParam().pool_type == test::PoolType::NATIVE) features.push_back(kUseNativeThreadPool); #endif @@ -564,10 +565,6 @@ did_run.Wait(); } -INSTANTIATE_TEST_SUITE_P(, - ThreadPoolImplTest, - ::testing::ValuesIn(GetThreadPoolImplTestParams())); - // Spawns threads that simultaneously post Tasks to TaskRunners with various // TaskTraits and ExecutionModes. Verifies that each Task runs on a thread with // the expected priority and I/O restrictions and respects the characteristics @@ -592,7 +589,7 @@ GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated) { StartThreadPool(); -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() if (GetParam().pool_type == test::PoolType::NATIVE) return; #endif @@ -911,7 +908,7 @@ } TEST_P(ThreadPoolImplTest, WorkerThreadObserver) { -#if defined(OS_WIN) || defined(OS_MACOSX) +#if HAS_NATIVE_THREAD_POOL() // WorkerThreads are not created (and hence not observed) when using the // native thread pools. We still start the ThreadPool in this case since // JoinForTesting is always called on TearDown, and DCHECKs that all thread @@ -943,7 +940,7 @@ // Infinite detach time to prevent workers from invoking // OnWorkerThreadMainExit() earlier than expected. - StartThreadPool(TimeDelta::Max()); + StartThreadPool(kMaxNumForegroundThreads, TimeDelta::Max()); std::vector<scoped_refptr<SingleThreadTaskRunner>> task_runners; @@ -1055,170 +1052,115 @@ EXPECT_TRUE(was_destroyed); } -class ThreadPoolPriorityUpdateTest - : public testing::TestWithParam<ThreadPoolImplTestParams> { - protected: - struct PoolBlockingEvents { - PoolBlockingEvents(const TaskTraits& pool_traits) - : pool_traits(pool_traits) {} - const TaskTraits pool_traits; - WaitableEvent scheduled; - WaitableEvent blocked; - }; +namespace { - struct TaskRunnerAndEvents { - TaskRunnerAndEvents( - scoped_refptr<UpdateableSequencedTaskRunner> task_runner, - const TaskPriority updated_priority, - WaitableEvent* expected_previous_event) - : task_runner(std::move(task_runner)), - updated_priority(updated_priority), - expected_previous_event(expected_previous_event) {} - scoped_refptr<UpdateableSequencedTaskRunner> task_runner; - const TaskPriority updated_priority; - WaitableEvent scheduled; - WaitableEvent blocked; - WaitableEvent task_ran; - WaitableEvent* expected_previous_event; - }; - - ThreadPoolPriorityUpdateTest() : thread_pool_("Test") {} - - void StartThreadPoolWithNumThreadsPerGroup(int threads_per_group) { - constexpr TimeDelta kSuggestedReclaimTime = TimeDelta::FromSeconds(30); - - thread_pool_.Start({{threads_per_group, kSuggestedReclaimTime}, - {threads_per_group, kSuggestedReclaimTime}}, - nullptr); - } - - // Create a series of sample task runners that will post tasks at various - // initial priorities, then update priority. - void CreateTaskRunnersAndEvents() { - // Task runner that will start as USER_VISIBLE and update to USER_BLOCKING. - // Its task is expected to run first. - task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>( - thread_pool_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( - TaskTraits({TaskPriority::USER_VISIBLE})), - TaskPriority::USER_BLOCKING, nullptr)); - - // Task runner that will start as BEST_EFFORT and update to USER_VISIBLE. - // Its task is expected to run after the USER_BLOCKING task runner's task. - task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>( - thread_pool_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( - TaskTraits({TaskPriority::BEST_EFFORT})), - TaskPriority::USER_VISIBLE, - &task_runners_and_events_.back()->task_ran)); - - // Task runner that will start as USER_BLOCKING and update to BEST_EFFORT. - // Its task is expected to run asynchronously with the other two task task - // runners' tasks if background thread groups exist, or after the - // USER_VISIBLE task runner's task if not. - task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>( - thread_pool_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( - TaskTraits({TaskPriority::USER_BLOCKING})), - TaskPriority::BEST_EFFORT, - CanUseBackgroundPriorityForWorkerThread() - ? nullptr - : &task_runners_and_events_.back()->task_ran)); - } - - void TearDown() override { - thread_pool_.FlushForTesting(); - thread_pool_.JoinForTesting(); - } - - ThreadPoolImpl thread_pool_; - - std::vector<std::unique_ptr<TaskRunnerAndEvents>> task_runners_and_events_; - - DISALLOW_COPY_AND_ASSIGN(ThreadPoolPriorityUpdateTest); +struct TaskRunnerAndEvents { + TaskRunnerAndEvents(scoped_refptr<UpdateableSequencedTaskRunner> task_runner, + const TaskPriority updated_priority, + WaitableEvent* expected_previous_event) + : task_runner(std::move(task_runner)), + updated_priority(updated_priority), + expected_previous_event(expected_previous_event) {} + scoped_refptr<UpdateableSequencedTaskRunner> task_runner; + const TaskPriority updated_priority; + WaitableEvent scheduled; + WaitableEvent blocked; + WaitableEvent task_ran; + WaitableEvent* expected_previous_event; }; +// Create a series of sample task runners that will post tasks at various +// initial priorities, then update priority. +std::vector<std::unique_ptr<TaskRunnerAndEvents>> CreateTaskRunnersAndEvents( + ThreadPoolImpl* thread_pool) { + std::vector<std::unique_ptr<TaskRunnerAndEvents>> task_runners_and_events; + // Task runner that will start as USER_VISIBLE and update to USER_BLOCKING. + // Its task is expected to run first. + task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>( + thread_pool->CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( + TaskTraits({TaskPriority::USER_VISIBLE})), + TaskPriority::USER_BLOCKING, nullptr)); + + // Task runner that will start as BEST_EFFORT and update to USER_VISIBLE. + // Its task is expected to run after the USER_BLOCKING task runner's task. + task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>( + thread_pool->CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( + TaskTraits({TaskPriority::BEST_EFFORT})), + TaskPriority::USER_VISIBLE, &task_runners_and_events.back()->task_ran)); + + // Task runner that will start as USER_BLOCKING and update to BEST_EFFORT. + // Its task is expected to run asynchronously with the other two task task + // runners' tasks if background thread groups exist, or after the + // USER_VISIBLE task runner's task if not. + task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>( + thread_pool->CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( + TaskTraits({TaskPriority::USER_BLOCKING})), + TaskPriority::BEST_EFFORT, + CanUseBackgroundPriorityForWorkerThread() + ? nullptr + : &task_runners_and_events.back()->task_ran)); + + return task_runners_and_events; +} + +} // namespace + // Update the priority of a sequence when it is not scheduled. -// -// TODO(adityakeerthi): Parameterize this test once we have a way to prevent -// sequences from being scheduled without flooding the thread pool. It is not -// possible to flood the native thread pools. -TEST_F(ThreadPoolPriorityUpdateTest, UpdatePrioritySequenceNotScheduled) { - StartThreadPoolWithNumThreadsPerGroup(1); +TEST_P(ThreadPoolImplTest, UpdatePrioritySequenceNotScheduled) { + // This test verifies that tasks run in priority order. With more than 1 + // thread per pool, it is possible that tasks don't run in order even if + // threads got tasks from the PriorityQueue in order. Therefore, enforce a + // maximum of 1 thread per pool. + constexpr int kLocalMaxNumForegroundThreads = 1; - // Schedule blocking tasks on all threads to prevent tasks from being - // scheduled later in the test. - std::vector<std::unique_ptr<PoolBlockingEvents>> pool_blocking_events; + StartThreadPool(kLocalMaxNumForegroundThreads); + auto task_runners_and_events = CreateTaskRunnersAndEvents(&thread_pool_); - pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>( - TaskTraits({TaskPriority::USER_BLOCKING}))); - if (CanUseBackgroundPriorityForWorkerThread()) { - pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>( - TaskTraits({TaskPriority::BEST_EFFORT}))); - } - - // When all blocking tasks signal |scheduled|, there is a task blocked in each - // thread group. - for (auto& pool_blocking_event : pool_blocking_events) { - thread_pool_ - .CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( - pool_blocking_event->pool_traits) - ->PostTask( - FROM_HERE, BindLambdaForTesting([&]() { - pool_blocking_event->scheduled.Signal(); - test::WaitWithoutBlockingObserver(&pool_blocking_event->blocked); - })); - - test::WaitWithoutBlockingObserver(&pool_blocking_event->scheduled); - } - - CreateTaskRunnersAndEvents(); + // Prevent tasks from running. + thread_pool_.SetCanRun(false); // Post tasks to multiple task runners while they are at initial priority. - for (auto& task_runner_and_events : task_runners_and_events_) { + // They won't run immediately because of the call to SetCanRun(false) above. + for (auto& task_runner_and_events : task_runners_and_events) { task_runner_and_events->task_runner->PostTask( FROM_HERE, BindOnce(&VerifyOrderAndTaskEnvironmentAndSignalEvent, - task_runner_and_events->updated_priority, - test::PoolType::GENERIC, - Unretained(task_runner_and_events->expected_previous_event), + task_runner_and_events->updated_priority, GetParam().pool_type, + // Native pools ignore the maximum number of threads per pool + // and therefore don't guarantee that tasks run in priority + // order (see comment at beginning of test). + Unretained( +#if HAS_NATIVE_THREAD_POOL() + GetParam().pool_type == test::PoolType::NATIVE + ? nullptr + : +#endif + task_runner_and_events->expected_previous_event), Unretained(&task_runner_and_events->task_ran))); } // Update the priorities of the task runners that posted the tasks. - for (auto& task_runner_and_events : task_runners_and_events_) { + for (auto& task_runner_and_events : task_runners_and_events) { task_runner_and_events->task_runner->UpdatePriority( task_runner_and_events->updated_priority); } - // Unblock the task blocking each thread group, allowing the posted tasks to - // run. Each posted task will verify that it has been posted with updated - // priority when it runs. - for (auto& pool_blocking_event : pool_blocking_events) { - pool_blocking_event->blocked.Signal(); - } + // Allow tasks to run. + thread_pool_.SetCanRun(true); - for (auto& task_runner_and_events : task_runners_and_events_) { + for (auto& task_runner_and_events : task_runners_and_events) test::WaitWithoutBlockingObserver(&task_runner_and_events->task_ran); - } } // Update the priority of a sequence when it is scheduled, i.e. not currently // in a priority queue. -TEST_P(ThreadPoolPriorityUpdateTest, UpdatePrioritySequenceScheduled) { -#if defined(OS_WIN) || defined(OS_MACOSX) - base::test::ScopedFeatureList feature_list; - if (GetParam().pool_type == test::PoolType::NATIVE) { - feature_list.InitWithFeatures({kUseNativeThreadPool}, {}); - } else { - feature_list.InitWithFeatures({}, {kUseNativeThreadPool}); - } -#endif - - StartThreadPoolWithNumThreadsPerGroup(5); - - CreateTaskRunnersAndEvents(); +TEST_P(ThreadPoolImplTest, UpdatePrioritySequenceScheduled) { + StartThreadPool(); + auto task_runners_and_events = CreateTaskRunnersAndEvents(&thread_pool_); // Post blocking tasks to all task runners to prevent tasks from being // scheduled later in the test. - for (auto& task_runner_and_events : task_runners_and_events_) { + for (auto& task_runner_and_events : task_runners_and_events) { task_runner_and_events->task_runner->PostTask( FROM_HERE, BindLambdaForTesting([&]() { ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives; @@ -1232,13 +1174,13 @@ // Update the priorities of the task runners while they are scheduled and // blocked. - for (auto& task_runner_and_events : task_runners_and_events_) { + for (auto& task_runner_and_events : task_runners_and_events) { task_runner_and_events->task_runner->UpdatePriority( task_runner_and_events->updated_priority); } // Post an additional task to each task runner. - for (auto& task_runner_and_events : task_runners_and_events_) { + for (auto& task_runner_and_events : task_runners_and_events) { task_runner_and_events->task_runner->PostTask( FROM_HERE, BindOnce(&VerifyOrderAndTaskEnvironmentAndSignalEvent, @@ -1251,14 +1193,14 @@ // Unblock the task blocking each task runner, allowing the additional posted // tasks to run. Each posted task will verify that it has been posted with // updated priority when it runs. - for (auto& task_runner_and_events : task_runners_and_events_) { + for (auto& task_runner_and_events : task_runners_and_events) { task_runner_and_events->blocked.Signal(); test::WaitWithoutBlockingObserver(&task_runner_and_events->task_ran); } } INSTANTIATE_TEST_SUITE_P(, - ThreadPoolPriorityUpdateTest, + ThreadPoolImplTest, ::testing::ValuesIn(GetThreadPoolImplTestParams())); } // namespace internal
diff --git a/base/task/thread_pool/thread_pool_perftest.cc b/base/task/thread_pool/thread_pool_perftest.cc index dc87ee0c..cd955c95 100644 --- a/base/task/thread_pool/thread_pool_perftest.cc +++ b/base/task/thread_pool/thread_pool_perftest.cc
@@ -120,13 +120,7 @@ void StartThreadPool(size_t num_running_threads, size_t num_posting_threads, base::RepeatingClosure post_action) { - constexpr TimeDelta kSuggestedReclaimTime = TimeDelta::FromSeconds(30); - constexpr int kMaxNumBackgroundThreads = 1; - - ThreadPool::GetInstance()->Start( - {{kMaxNumBackgroundThreads, kSuggestedReclaimTime}, - {num_running_threads, kSuggestedReclaimTime}}, - nullptr); + ThreadPool::GetInstance()->Start({num_running_threads}); base::RepeatingClosure done = BarrierClosure( num_posting_threads,
diff --git a/base/task/thread_pool/worker_thread.cc b/base/task/thread_pool/worker_thread.cc index b860645b..57d0c84 100644 --- a/base/task/thread_pool/worker_thread.cc +++ b/base/task/thread_pool/worker_thread.cc
@@ -18,9 +18,6 @@ #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" -#elif defined(OS_WIN) -#include "base/win/com_init_check_hook.h" -#include "base/win/scoped_com_initializer.h" #endif namespace base { @@ -38,22 +35,15 @@ } } -WorkerThread::WorkerThread( - ThreadPriority priority_hint, - std::unique_ptr<Delegate> delegate, - TrackedRef<TaskTracker> task_tracker, - const CheckedLock* predecessor_lock, - WorkerThreadBackwardCompatibility backward_compatibility) +WorkerThread::WorkerThread(ThreadPriority priority_hint, + std::unique_ptr<Delegate> delegate, + TrackedRef<TaskTracker> task_tracker, + const CheckedLock* predecessor_lock) : thread_lock_(predecessor_lock), delegate_(std::move(delegate)), task_tracker_(std::move(task_tracker)), priority_hint_(priority_hint), - current_thread_priority_(GetDesiredThreadPriority()) -#if defined(OS_WIN) && !defined(COM_INIT_CHECK_HOOK_ENABLED) - , - backward_compatibility_(backward_compatibility) -#endif -{ + current_thread_priority_(GetDesiredThreadPriority()) { DCHECK(delegate_); DCHECK(task_tracker_); DCHECK(CanUseBackgroundPriorityForWorkerThread() || @@ -307,16 +297,6 @@ TRACE_EVENT_BEGIN0("thread_pool", "WorkerThreadThread active"); } -// When defined(COM_INIT_CHECK_HOOK_ENABLED), ignore -// WorkerThreadBackwardCompatibility::INIT_COM_STA to find incorrect uses of -// COM that should be running in a COM STA Task Runner. -#if defined(OS_WIN) && !defined(COM_INIT_CHECK_HOOK_ENABLED) - std::unique_ptr<win::ScopedCOMInitializer> com_initializer; - if (backward_compatibility_ == - WorkerThreadBackwardCompatibility::INIT_COM_STA) - com_initializer = std::make_unique<win::ScopedCOMInitializer>(); -#endif - while (!ShouldExit()) { #if defined(OS_MACOSX) mac::ScopedNSAutoreleasePool autorelease_pool;
diff --git a/base/task/thread_pool/worker_thread.h b/base/task/thread_pool/worker_thread.h index f7dbd8e..06fb141 100644 --- a/base/task/thread_pool/worker_thread.h +++ b/base/task/thread_pool/worker_thread.h
@@ -15,16 +15,11 @@ #include "base/task/common/checked_lock.h" #include "base/task/thread_pool/task_source.h" #include "base/task/thread_pool/tracked_ref.h" -#include "base/task/thread_pool/worker_thread_params.h" #include "base/thread_annotations.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "build/build_config.h" -#if defined(OS_WIN) -#include "base/win/com_init_check_hook.h" -#endif - namespace base { class WorkerThreadObserver; @@ -110,9 +105,7 @@ WorkerThread(ThreadPriority priority_hint, std::unique_ptr<Delegate> delegate, TrackedRef<TaskTracker> task_tracker, - const CheckedLock* predecessor_lock = nullptr, - WorkerThreadBackwardCompatibility backward_compatibility = - WorkerThreadBackwardCompatibility::DISABLED); + const CheckedLock* predecessor_lock = nullptr); // Creates a thread to back the WorkerThread. The thread will be in a wait // state pending a WakeUp() call. No thread will be created if Cleanup() was @@ -238,10 +231,6 @@ // construction accesses occur on the thread. ThreadPriority current_thread_priority_; -#if defined(OS_WIN) && !defined(COM_INIT_CHECK_HOOK_ENABLED) - const WorkerThreadBackwardCompatibility backward_compatibility_; -#endif - // Set once JoinForTesting() has been called. AtomicFlag join_called_for_testing_;
diff --git a/base/task/thread_pool/worker_thread_params.h b/base/task/thread_pool/worker_thread_params.h deleted file mode 100644 index d864ce9..0000000 --- a/base/task/thread_pool/worker_thread_params.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TASK_THREAD_POOL_WORKER_THREAD_PARAMS_H_ -#define BASE_TASK_THREAD_POOL_WORKER_THREAD_PARAMS_H_ - -namespace base { - -enum class WorkerThreadBackwardCompatibility { - // No backward compatibility. - DISABLED, - - // On Windows, initialize COM STA to mimic SequencedWorkerPool and - // BrowserThreadImpl. Behaves like DISABLED on other platforms. - // TODO(fdoray): Get rid of this and force tasks that care about a - // CoInitialized environment to request one explicitly (via an upcoming - // execution mode). - INIT_COM_STA, -}; - -} // namespace base - -#endif // BASE_TASK_THREAD_POOL_WORKER_THREAD_PARAMS_H_
diff --git a/base/task/thread_pool/worker_thread_unittest.cc b/base/task/thread_pool/worker_thread_unittest.cc index 08b98cd..35ed670 100644 --- a/base/task/thread_pool/worker_thread_unittest.cc +++ b/base/task/thread_pool/worker_thread_unittest.cc
@@ -31,12 +31,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_WIN) -#include <objbase.h> - -#include "base/win/com_init_check_hook.h" -#endif - using testing::_; using testing::Mock; using testing::Ne; @@ -816,88 +810,5 @@ Mock::VerifyAndClear(&observer); } -#if defined(OS_WIN) - -namespace { - -class CoInitializeDelegate : public WorkerThreadDefaultDelegate { - public: - CoInitializeDelegate() = default; - - scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override { - EXPECT_FALSE(get_work_returned_.IsSignaled()); - EXPECT_EQ(E_UNEXPECTED, coinitialize_hresult_); - - coinitialize_hresult_ = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - if (SUCCEEDED(coinitialize_hresult_)) - CoUninitialize(); - - get_work_returned_.Signal(); - return nullptr; - } - - void WaitUntilGetWorkReturned() { get_work_returned_.Wait(); } - - HRESULT coinitialize_hresult() const { return coinitialize_hresult_; } - - private: - WaitableEvent get_work_returned_; - HRESULT coinitialize_hresult_ = E_UNEXPECTED; - - DISALLOW_COPY_AND_ASSIGN(CoInitializeDelegate); -}; - -} // namespace - -TEST(ThreadPoolWorkerTest, BackwardCompatibilityEnabled) { - TaskTracker task_tracker("Test"); - auto delegate = std::make_unique<CoInitializeDelegate>(); - CoInitializeDelegate* const delegate_raw = delegate.get(); - - // Create a worker with backward compatibility ENABLED. Wake it up and wait - // until GetWork() returns. - auto worker = MakeRefCounted<WorkerThread>( - ThreadPriority::NORMAL, std::move(delegate), task_tracker.GetTrackedRef(), - nullptr, WorkerThreadBackwardCompatibility::INIT_COM_STA); - worker->Start(); - worker->WakeUp(); - delegate_raw->WaitUntilGetWorkReturned(); - -// The call to CoInitializeEx() should have returned S_FALSE to indicate that -// the COM library was already initialized on the thread. -// See WorkerThread::Thread::ThreadMain for why we expect two different -// results here. -#if defined(COM_INIT_CHECK_HOOK_ENABLED) - EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult()); -#else - EXPECT_EQ(S_FALSE, delegate_raw->coinitialize_hresult()); -#endif - - worker->JoinForTesting(); -} - -TEST(ThreadPoolWorkerTest, BackwardCompatibilityDisabled) { - TaskTracker task_tracker("Test"); - auto delegate = std::make_unique<CoInitializeDelegate>(); - CoInitializeDelegate* const delegate_raw = delegate.get(); - - // Create a worker with backward compatibility DISABLED. Wake it up and wait - // until GetWork() returns. - auto worker = MakeRefCounted<WorkerThread>( - ThreadPriority::NORMAL, std::move(delegate), task_tracker.GetTrackedRef(), - nullptr, WorkerThreadBackwardCompatibility::DISABLED); - worker->Start(); - worker->WakeUp(); - delegate_raw->WaitUntilGetWorkReturned(); - - // The call to CoInitializeEx() should have returned S_OK to indicate that the - // COM library wasn't already initialized on the thread. - EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult()); - - worker->JoinForTesting(); -} - -#endif // defined(OS_WIN) - } // namespace internal } // namespace base
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index 66a9242..6f91488 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc
@@ -1274,17 +1274,8 @@ } void TestLauncher::CreateAndStartThreadPool(int num_parallel_jobs) { - // These values are taken from ThreadPool::StartWithDefaultParams(), which - // is not used directly to allow a custom number of threads in the foreground - // pool. - // TODO(etiennep): Change this to 2 in future CL. - constexpr int kMaxBackgroundThreads = 3; - constexpr base::TimeDelta kSuggestedReclaimTime = - base::TimeDelta::FromSeconds(30); base::ThreadPool::Create("TestLauncher"); - base::ThreadPool::GetInstance()->Start( - {{kMaxBackgroundThreads, kSuggestedReclaimTime}, - {num_parallel_jobs, kSuggestedReclaimTime}}); + base::ThreadPool::GetInstance()->Start({num_parallel_jobs}); } void TestLauncher::CombinePositiveTestFilters(
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc index 562d49c..26a96c2 100644 --- a/base/test/scoped_task_environment.cc +++ b/base/test/scoped_task_environment.cc
@@ -386,32 +386,29 @@ // ScopedBlockingCall. It also allows enough concurrency to allow TSAN to spot // data races. constexpr int kMaxThreads = 4; - const TimeDelta kSuggestedReclaimTime = TimeDelta::Max(); - const ThreadGroupParams thread_group_params(kMaxThreads, - kSuggestedReclaimTime); + ThreadPool::InitParams init_params(kMaxThreads); + init_params.suggested_reclaim_time = TimeDelta::Max(); +#if defined(OS_WIN) + // Enable the MTA in unit tests to match the browser process' ThreadPool + // configuration. + // + // This has the adverse side-effect of enabling the MTA in non-browser unit + // tests as well but the downside there is not as bad as not having it in + // browser unit tests. It just means some COM asserts may pass in unit tests + // where they wouldn't in integration tests or prod. That's okay because unit + // tests are already generally very loose on allowing I/O, waits, etc. Such + // misuse will still be caught in later phases (and COM usage should already + // be pretty much inexistent in sandboxed processes). + init_params.common_thread_pool_environment = + ThreadPool::InitParams::CommonThreadPoolEnvironment::COM_MTA; +#endif + auto task_tracker = std::make_unique<TestTaskTracker>(); task_tracker_ = task_tracker.get(); ThreadPool::SetInstance(std::make_unique<internal::ThreadPoolImpl>( "ScopedTaskEnvironment", std::move(task_tracker))); thread_pool_ = ThreadPool::GetInstance(); - ThreadPool::GetInstance()->Start({ - thread_group_params, thread_group_params -#if defined(OS_WIN) - , - // Enable the MTA in unit tests to match the browser process' - // ThreadPool configuration. - // - // This has the adverse side-effect of enabling the MTA in non-browser - // unit tests as well but the downside there is not as bad as not having - // it in browser unit tests. It just means some COM asserts may pass in - // unit tests where they wouldn't in integration tests or prod. That's - // okay because unit tests are already generally very loose on allowing - // I/O, waits, etc. Such misuse will still be caught in later phases - // (and COM usage should already be pretty much inexistent in sandboxed - // processes). - ThreadPool::InitParams::CommonThreadPoolEnvironment::COM_MTA -#endif - }); + ThreadPool::GetInstance()->Start(init_params); } void ScopedTaskEnvironment::CompleteInitialization() {
diff --git a/base/third_party/cityhash/COPYING b/base/third_party/cityhash/COPYING deleted file mode 100644 index bf15194..0000000 --- a/base/third_party/cityhash/COPYING +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 2011 Google, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE.
diff --git a/base/third_party/cityhash/README b/base/third_party/cityhash/README deleted file mode 100644 index 0ec19171..0000000 --- a/base/third_party/cityhash/README +++ /dev/null
@@ -1,196 +0,0 @@ -CityHash, a family of hash functions for strings. - - -Introduction -============ - -CityHash provides hash functions for strings. The functions mix the -input bits thoroughly but are not suitable for cryptography. See -"Hash Quality," below, for details on how CityHash was tested and so on. - -We provide reference implementations in C++, with a friendly MIT license. - -CityHash32() returns a 32-bit hash. - -CityHash64() and similar return a 64-bit hash. - -CityHash128() and similar return a 128-bit hash and are tuned for -strings of at least a few hundred bytes. Depending on your compiler -and hardware, it's likely faster than CityHash64() on sufficiently long -strings. It's slower than necessary on shorter strings, but we expect -that case to be relatively unimportant. - -CityHashCrc128() and similar are variants of CityHash128() that depend -on _mm_crc32_u64(), an intrinsic that compiles to a CRC32 instruction -on some CPUs. However, none of the functions we provide are CRCs. - -CityHashCrc256() is a variant of CityHashCrc128() that also depends -on _mm_crc32_u64(). It returns a 256-bit hash. - -All members of the CityHash family were designed with heavy reliance -on previous work by Austin Appleby, Bob Jenkins, and others. -For example, CityHash32 has many similarities with Murmur3a. - -Performance on long strings: 64-bit CPUs -======================================== - -We are most excited by the performance of CityHash64() and its variants on -short strings, but long strings are interesting as well. - -CityHash is intended to be fast, under the constraint that it hash very -well. For CPUs with the CRC32 instruction, CRC is speedy, but CRC wasn't -designed as a hash function and shouldn't be used as one. CityHashCrc128() -is not a CRC, but it uses the CRC32 machinery. - -On a single core of a 2.67GHz Intel Xeon X5550, CityHashCrc256 peaks at about -5 to 5.5 bytes/cycle. The other CityHashCrc functions are wrappers around -CityHashCrc256 and should have similar performance on long strings. -(CityHashCrc256 in v1.0.3 was even faster, but we decided it wasn't as thorough -as it should be.) CityHash128 peaks at about 4.3 bytes/cycle. The fastest -Murmur variant on that hardware, Murmur3F, peaks at about 2.4 bytes/cycle. -We expect the peak speed of CityHash128 to dominate CityHash64, which is -aimed more toward short strings or use in hash tables. - -For long strings, a new function by Bob Jenkins, SpookyHash, is just -slightly slower than CityHash128 on Intel x86-64 CPUs, but noticeably -faster on AMD x86-64 CPUs. For hashing long strings on AMD CPUs -and/or CPUs without the CRC instruction, SpookyHash may be just as -good or better than any of the CityHash variants. - -Performance on short strings: 64-bit CPUs -========================================= - -For short strings, e.g., most hash table keys, CityHash64 is faster than -CityHash128, and probably faster than all the aforementioned functions, -depending on the mix of string lengths. Here are a few results from that -same hardware, where we (unrealistically) tested a single string length over -and over again: - -Hash Results ------------------------------------------------------------------------------- -CityHash64 v1.0.3 7ns for 1 byte, or 6ns for 8 bytes, or 9ns for 64 bytes -Murmur2 (64-bit) 6ns for 1 byte, or 6ns for 8 bytes, or 15ns for 64 bytes -Murmur3F 14ns for 1 byte, or 15ns for 8 bytes, or 23ns for 64 bytes - -We don't have CityHash64 benchmarks results for v1.1, but we expect the -numbers to be similar. - -Performance: 32-bit CPUs -======================== - -CityHash32 is the newest variant of CityHash. It is intended for -32-bit hardware in general but has been mostly tested on x86. Our benchmarks -suggest that Murmur3 is the nearest competitor to CityHash32 on x86. -We don't know of anything faster that has comparable quality. The speed rankings -in our testing: CityHash32 > Murmur3f > Murmur3a (for long strings), and -CityHash32 > Murmur3a > Murmur3f (for short strings). - -Installation -============ - -We provide reference implementations of several CityHash functions, written -in C++. The build system is based on autoconf. It defaults the C++ -compiler flags to "-g -O2", which is probably slower than -O3 if you are -using gcc. YMMV. - -On systems with gcc, we generally recommend: - -./configure -make all check CXXFLAGS="-g -O3" -sudo make install - -Or, if your system has the CRC32 instruction, and you want to build everything: - -./configure --enable-sse4.2 -make all check CXXFLAGS="-g -O3 -msse4.2" -sudo make install - -Note that our build system doesn't try to determine the appropriate compiler -flag for enabling SSE4.2. For gcc it is "-msse4.2". The --enable-sse4.2 -flag to the configure script controls whether citycrc.h is installed when -you "make install." In general, picking the right compiler flags can be -tricky, and may depend on your compiler, your hardware, and even how you -plan to use the library. - -For generic information about how to configure this software, please try: - -./configure --help - -Failing that, please work from city.cc and city*.h, as they contain all the -necessary code. - - -Usage -===== - -The above installation instructions will produce a single library. It will -contain CityHash32(), CityHash64(), and CityHash128(), and their variants, -and possibly CityHashCrc128(), CityHashCrc128WithSeed(), and -CityHashCrc256(). The functions with Crc in the name are declared in -citycrc.h; the rest are declared in city.h. - - -Limitations -=========== - -1) CityHash32 is intended for little-endian 32-bit code, and everything else in -the current version of CityHash is intended for little-endian 64-bit CPUs. - -All functions that don't use the CRC32 instruction should work in -little-endian 32-bit or 64-bit code. CityHash should work on big-endian CPUs -as well, but we haven't tested that very thoroughly yet. - -2) CityHash is fairly complex. As a result of its complexity, it may not -perform as expected on some compilers. For example, preliminary reports -suggest that some Microsoft compilers compile CityHash to assembly that's -10-20% slower than it could be. - - -Hash Quality -============ - -We like to test hash functions with SMHasher, among other things. -SMHasher isn't perfect, but it seems to find almost any significant flaw. -SMHasher is available at http://code.google.com/p/smhasher/ - -SMHasher is designed to pass a 32-bit seed to the hash functions it tests. -No CityHash function is designed to work that way, so we adapt as follows: -For our functions that accept a seed, we use the given seed directly (padded -with zeroes); for our functions that don't accept a seed, we hash the -concatenation of the given seed and the input string. - -The CityHash functions have the following flaws according to SMHasher: - -(1) CityHash64: none - -(2) CityHash64WithSeed: none - -(3) CityHash64WithSeeds: did not test - -(4) CityHash128: none - -(5) CityHash128WithSeed: none - -(6) CityHashCrc128: none - -(7) CityHashCrc128WithSeed: none - -(8) CityHashCrc256: none - -(9) CityHash32: none - -Some minor flaws in 32-bit and 64-bit functions are harmless, as we -expect the primary use of these functions will be in hash tables. We -may have gone slightly overboard in trying to please SMHasher and other -similar tests, but we don't want anyone to choose a different hash function -because of some minor issue reported by a quality test. - - -For more information -==================== - -http://code.google.com/p/cityhash/ - -cityhash-discuss@googlegroups.com - -Please feel free to send us comments, questions, bug reports, or patches.
diff --git a/base/third_party/cityhash/README.chromium b/base/third_party/cityhash/README.chromium deleted file mode 100644 index 667d2a9d..0000000 --- a/base/third_party/cityhash/README.chromium +++ /dev/null
@@ -1,24 +0,0 @@ -Name: CityHash -URL: https://github.com/google/cityhash -Version: 1.1.1 -Revision: 8af9b8c -License: MIT -License File: COPYING -Security Critical: yes - -Description: -This is a fast non-cryptographic hash function. - -There are currently two distinct sets of CityHash functions: -v1.0.3 and v1.1+ that produce distinct outputs. - -The version in //third_party/smhasher is 1.0.3 and has some hash -quality issues that led to non-backwards compatible changes in v1.1+. - -Local changes: -- guarded function declaration (i.e. CityHash64) within a namespace -(base::internal::cityhash_v111). -- defined bswap_32/bswap_64 to use compiler builtins to make 'native_client' -build pass. -- remove unneeded CRC32 stuff. -- formating to make 'git cl format' happy.
diff --git a/base/third_party/cityhash/city.cc b/base/third_party/cityhash/city.cc deleted file mode 100644 index f0af5bbd..0000000 --- a/base/third_party/cityhash/city.cc +++ /dev/null
@@ -1,530 +0,0 @@ -// Copyright (c) 2011 Google, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// CityHash, by Geoff Pike and Jyrki Alakuijala -// -// This file provides CityHash64() and related functions. -// -// It's probably possible to create even faster hash functions by -// writing a program that systematically explores some of the space of -// possible hash functions, by using SIMD instructions, or by -// compromising on hash quality. - -#include "city.h" - -#include <string.h> // for memcpy and memset -#include <algorithm> - -namespace base { -namespace internal { -namespace cityhash_v111 { -using namespace std; - -static uint64 UNALIGNED_LOAD64(const char* p) { - uint64 result; - memcpy(&result, p, sizeof(result)); - return result; -} - -static uint32 UNALIGNED_LOAD32(const char* p) { - uint32 result; - memcpy(&result, p, sizeof(result)); - return result; -} - -#ifdef _MSC_VER - -#include <stdlib.h> -#define bswap_32(x) _byteswap_ulong(x) -#define bswap_64(x) _byteswap_uint64(x) - -#elif defined(__APPLE__) - -// Mac OS X / Darwin features -#include <libkern/OSByteOrder.h> -#define bswap_32(x) OSSwapInt32(x) -#define bswap_64(x) OSSwapInt64(x) - -#elif defined(__sun) || defined(sun) - -#include <sys/byteorder.h> -#define bswap_32(x) BSWAP_32(x) -#define bswap_64(x) BSWAP_64(x) - -#elif defined(__FreeBSD__) - -#include <sys/endian.h> -#define bswap_32(x) bswap32(x) -#define bswap_64(x) bswap64(x) - -#elif defined(__OpenBSD__) - -#include <sys/types.h> -#define bswap_32(x) swap32(x) -#define bswap_64(x) swap64(x) - -#elif defined(__NetBSD__) - -#include <machine/bswap.h> -#include <sys/types.h> -#if defined(__BSWAP_RENAME) && !defined(__bswap_32) -#define bswap_32(x) bswap32(x) -#define bswap_64(x) bswap64(x) -#endif - -#else - -// XXX(cavalcanti): building 'native_client' fails with this header. -//#include <byteswap.h> - -// Falling back to compiler builtins instead. -#define bswap_32(x) __builtin_bswap32(x) -#define bswap_64(x) __builtin_bswap64(x) - -#endif - -#ifdef WORDS_BIGENDIAN -#define uint32_in_expected_order(x) (bswap_32(x)) -#define uint64_in_expected_order(x) (bswap_64(x)) -#else -#define uint32_in_expected_order(x) (x) -#define uint64_in_expected_order(x) (x) -#endif - -#if !defined(LIKELY) -#if HAVE_BUILTIN_EXPECT -#define LIKELY(x) (__builtin_expect(!!(x), 1)) -#else -#define LIKELY(x) (x) -#endif -#endif - -static uint64 Fetch64(const char* p) { - return uint64_in_expected_order(UNALIGNED_LOAD64(p)); -} - -static uint32 Fetch32(const char* p) { - return uint32_in_expected_order(UNALIGNED_LOAD32(p)); -} - -// Some primes between 2^63 and 2^64 for various uses. -static const uint64 k0 = 0xc3a5c85c97cb3127ULL; -static const uint64 k1 = 0xb492b66fbe98f273ULL; -static const uint64 k2 = 0x9ae16a3b2f90404fULL; - -// Magic numbers for 32-bit hashing. Copied from Murmur3. -static const uint32 c1 = 0xcc9e2d51; -static const uint32 c2 = 0x1b873593; - -// A 32-bit to 32-bit integer hash copied from Murmur3. -static uint32 fmix(uint32 h) { - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - return h; -} - -static uint32 Rotate32(uint32 val, int shift) { - // Avoid shifting by 32: doing so yields an undefined result. - return shift == 0 ? val : ((val >> shift) | (val << (32 - shift))); -} - -#undef PERMUTE3 -#define PERMUTE3(a, b, c) \ - do { \ - std::swap(a, b); \ - std::swap(a, c); \ - } while (0) - -static uint32 Mur(uint32 a, uint32 h) { - // Helper from Murmur3 for combining two 32-bit values. - a *= c1; - a = Rotate32(a, 17); - a *= c2; - h ^= a; - h = Rotate32(h, 19); - return h * 5 + 0xe6546b64; -} - -static uint32 Hash32Len13to24(const char* s, size_t len) { - uint32 a = Fetch32(s - 4 + (len >> 1)); - uint32 b = Fetch32(s + 4); - uint32 c = Fetch32(s + len - 8); - uint32 d = Fetch32(s + (len >> 1)); - uint32 e = Fetch32(s); - uint32 f = Fetch32(s + len - 4); - uint32 h = len; - - return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h))))))); -} - -static uint32 Hash32Len0to4(const char* s, size_t len) { - uint32 b = 0; - uint32 c = 9; - for (size_t i = 0; i < len; i++) { - signed char v = s[i]; - b = b * c1 + v; - c ^= b; - } - return fmix(Mur(b, Mur(len, c))); -} - -static uint32 Hash32Len5to12(const char* s, size_t len) { - uint32 a = len, b = len * 5, c = 9, d = b; - a += Fetch32(s); - b += Fetch32(s + len - 4); - c += Fetch32(s + ((len >> 1) & 4)); - return fmix(Mur(c, Mur(b, Mur(a, d)))); -} - -uint32 CityHash32(const char* s, size_t len) { - if (len <= 24) { - return len <= 12 - ? (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) - : Hash32Len13to24(s, len); - } - - // len > 24 - uint32 h = len, g = c1 * len, f = g; - uint32 a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2; - uint32 a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2; - uint32 a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2; - uint32 a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2; - uint32 a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2; - h ^= a0; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - h ^= a2; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - g ^= a1; - g = Rotate32(g, 19); - g = g * 5 + 0xe6546b64; - g ^= a3; - g = Rotate32(g, 19); - g = g * 5 + 0xe6546b64; - f += a4; - f = Rotate32(f, 19); - f = f * 5 + 0xe6546b64; - size_t iters = (len - 1) / 20; - do { - a0 = Rotate32(Fetch32(s) * c1, 17) * c2; - a1 = Fetch32(s + 4); - a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2; - a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2; - a4 = Fetch32(s + 16); - h ^= a0; - h = Rotate32(h, 18); - h = h * 5 + 0xe6546b64; - f += a1; - f = Rotate32(f, 19); - f = f * c1; - g += a2; - g = Rotate32(g, 18); - g = g * 5 + 0xe6546b64; - h ^= a3 + a1; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - g ^= a4; - g = bswap_32(g) * 5; - h += a4 * 5; - h = bswap_32(h); - f += a0; - PERMUTE3(f, h, g); - s += 20; - } while (--iters != 0); - g = Rotate32(g, 11) * c1; - g = Rotate32(g, 17) * c1; - f = Rotate32(f, 11) * c1; - f = Rotate32(f, 17) * c1; - h = Rotate32(h + g, 19); - h = h * 5 + 0xe6546b64; - h = Rotate32(h, 17) * c1; - h = Rotate32(h + f, 19); - h = h * 5 + 0xe6546b64; - h = Rotate32(h, 17) * c1; - return h; -} - -// Bitwise right rotate. Normally this will compile to a single -// instruction, especially if the shift is a manifest constant. -static uint64 Rotate(uint64 val, int shift) { - // Avoid shifting by 64: doing so yields an undefined result. - return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); -} - -static uint64 ShiftMix(uint64 val) { - return val ^ (val >> 47); -} - -static uint64 HashLen16(uint64 u, uint64 v) { - return Hash128to64(uint128(u, v)); -} - -static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) { - // Murmur-inspired hashing. - uint64 a = (u ^ v) * mul; - a ^= (a >> 47); - uint64 b = (v ^ a) * mul; - b ^= (b >> 47); - b *= mul; - return b; -} - -static uint64 HashLen0to16(const char* s, size_t len) { - if (len >= 8) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) + k2; - uint64 b = Fetch64(s + len - 8); - uint64 c = Rotate(b, 37) * mul + a; - uint64 d = (Rotate(a, 25) + b) * mul; - return HashLen16(c, d, mul); - } - if (len >= 4) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch32(s); - return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul); - } - if (len > 0) { - uint8 a = s[0]; - uint8 b = s[len >> 1]; - uint8 c = s[len - 1]; - uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8); - uint32 z = len + (static_cast<uint32>(c) << 2); - return ShiftMix(y * k2 ^ z * k0) * k2; - } - return k2; -} - -// This probably works well for 16-byte strings as well, but it may be overkill -// in that case. -static uint64 HashLen17to32(const char* s, size_t len) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) * k1; - uint64 b = Fetch64(s + 8); - uint64 c = Fetch64(s + len - 8) * mul; - uint64 d = Fetch64(s + len - 16) * k2; - return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, - a + Rotate(b + k2, 18) + c, mul); -} - -// Return a 16-byte hash for 48 bytes. Quick and dirty. -// Callers do best to use "random-looking" values for a and b. -static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, - uint64 x, - uint64 y, - uint64 z, - uint64 a, - uint64 b) { - a += w; - b = Rotate(b + a + z, 21); - uint64 c = a; - a += x; - a += y; - b += Rotate(a, 44); - return make_pair(a + z, b + c); -} - -// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. -static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, - uint64 a, - uint64 b) { - return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), - Fetch64(s + 24), a, b); -} - -// Return an 8-byte hash for 33 to 64 bytes. -static uint64 HashLen33to64(const char* s, size_t len) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) * k2; - uint64 b = Fetch64(s + 8); - uint64 c = Fetch64(s + len - 24); - uint64 d = Fetch64(s + len - 32); - uint64 e = Fetch64(s + 16) * k2; - uint64 f = Fetch64(s + 24) * 9; - uint64 g = Fetch64(s + len - 8); - uint64 h = Fetch64(s + len - 16) * mul; - uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9; - uint64 v = ((a + g) ^ d) + f + 1; - uint64 w = bswap_64((u + v) * mul) + h; - uint64 x = Rotate(e + f, 42) + c; - uint64 y = (bswap_64((v + w) * mul) + g) * mul; - uint64 z = e + f + c; - a = bswap_64((x + z) * mul + y) + b; - b = ShiftMix((z + a) * mul + d + h) * mul; - return b + x; -} - -uint64 CityHash64(const char* s, size_t len) { - if (len <= 32) { - if (len <= 16) { - return HashLen0to16(s, len); - } else { - return HashLen17to32(s, len); - } - } else if (len <= 64) { - return HashLen33to64(s, len); - } - - // For strings over 64 bytes we hash the end first, and then as we - // loop we keep 56 bytes of state: v, w, x, y, and z. - uint64 x = Fetch64(s + len - 40); - uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); - uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); - pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z); - pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); - x = x * k1 + Fetch64(s); - - // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. - len = (len - 1) & ~static_cast<size_t>(63); - do { - x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; - y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; - x ^= w.second; - y += v.first + Fetch64(s + 40); - z = Rotate(z + w.first, 33) * k1; - v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); - w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); - std::swap(z, x); - s += 64; - len -= 64; - } while (len != 0); - return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, - HashLen16(v.second, w.second) + x); -} - -uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) { - return CityHash64WithSeeds(s, len, k2, seed); -} - -uint64 CityHash64WithSeeds(const char* s, - size_t len, - uint64 seed0, - uint64 seed1) { - return HashLen16(CityHash64(s, len) - seed0, seed1); -} - -// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings -// of any length representable in signed long. Based on City and Murmur. -static uint128 CityMurmur(const char* s, size_t len, uint128 seed) { - uint64 a = Uint128Low64(seed); - uint64 b = Uint128High64(seed); - uint64 c = 0; - uint64 d = 0; - signed long l = len - 16; - if (l <= 0) { // len <= 16 - a = ShiftMix(a * k1) * k1; - c = b * k1 + HashLen0to16(s, len); - d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c)); - } else { // len > 16 - c = HashLen16(Fetch64(s + len - 8) + k1, a); - d = HashLen16(b + len, c + Fetch64(s + len - 16)); - a += d; - do { - a ^= ShiftMix(Fetch64(s) * k1) * k1; - a *= k1; - b ^= a; - c ^= ShiftMix(Fetch64(s + 8) * k1) * k1; - c *= k1; - d ^= c; - s += 16; - l -= 16; - } while (l > 0); - } - a = HashLen16(a, c); - b = HashLen16(d, b); - return uint128(a ^ b, HashLen16(b, a)); -} - -uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) { - if (len < 128) { - return CityMurmur(s, len, seed); - } - - // We expect len >= 128 to be the common case. Keep 56 bytes of state: - // v, w, x, y, and z. - pair<uint64, uint64> v, w; - uint64 x = Uint128Low64(seed); - uint64 y = Uint128High64(seed); - uint64 z = len * k1; - v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); - v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); - w.first = Rotate(y + z, 35) * k1 + x; - w.second = Rotate(x + Fetch64(s + 88), 53) * k1; - - // This is the same inner loop as CityHash64(), manually unrolled. - do { - x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; - y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; - x ^= w.second; - y += v.first + Fetch64(s + 40); - z = Rotate(z + w.first, 33) * k1; - v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); - w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); - std::swap(z, x); - s += 64; - x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; - y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; - x ^= w.second; - y += v.first + Fetch64(s + 40); - z = Rotate(z + w.first, 33) * k1; - v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); - w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); - std::swap(z, x); - s += 64; - len -= 128; - } while (LIKELY(len >= 128)); - x += Rotate(v.first + z, 49) * k0; - y = y * k0 + Rotate(w.second, 37); - z = z * k0 + Rotate(w.first, 27); - w.first *= 9; - v.first *= k0; - // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. - for (size_t tail_done = 0; tail_done < len;) { - tail_done += 32; - y = Rotate(x + y, 42) * k0 + v.second; - w.first += Fetch64(s + len - tail_done + 16); - x = x * k0 + w.first; - z += w.second + Fetch64(s + len - tail_done); - w.second += v.first; - v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second); - v.first *= k0; - } - // At this point our 56 bytes of state should contain more than - // enough information for a strong 128-bit hash. We use two - // different 56-byte-to-8-byte hashes to get a 16-byte final result. - x = HashLen16(x, v.first); - y = HashLen16(y + z, w.first); - return uint128(HashLen16(x + v.second, w.second) + y, - HashLen16(x + w.second, y + v.second)); -} - -uint128 CityHash128(const char* s, size_t len) { - return len >= 16 - ? CityHash128WithSeed(s + 16, len - 16, - uint128(Fetch64(s), Fetch64(s + 8) + k0)) - : CityHash128WithSeed(s, len, uint128(k0, k1)); -} - -} // namespace cityhash_v111 -} // namespace internal -} // namespace base
diff --git a/base/third_party/cityhash/city.h b/base/third_party/cityhash/city.h deleted file mode 100644 index 3e3dcaaa..0000000 --- a/base/third_party/cityhash/city.h +++ /dev/null
@@ -1,129 +0,0 @@ -// Copyright (c) 2011 Google, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// CityHash, by Geoff Pike and Jyrki Alakuijala -// -// http://code.google.com/p/cityhash/ -// -// This file provides a few functions for hashing strings. All of them are -// high-quality functions in the sense that they pass standard tests such -// as Austin Appleby's SMHasher. They are also fast. -// -// For 64-bit x86 code, on short strings, we don't know of anything faster than -// CityHash64 that is of comparable quality. We believe our nearest competitor -// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash -// tables and most other hashing (excluding cryptography). -// -// For 64-bit x86 code, on long strings, the picture is more complicated. -// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc., -// CityHashCrc128 appears to be faster than all competitors of comparable -// quality. CityHash128 is also good but not quite as fast. We believe our -// nearest competitor is Bob Jenkins' Spooky. We don't have great data for -// other 64-bit CPUs, but for long strings we know that Spooky is slightly -// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example. -// Note that CityHashCrc128 is declared in citycrc.h. -// -// For 32-bit x86 code, we don't know of anything faster than CityHash32 that -// is of comparable quality. We believe our nearest competitor is Murmur3A. -// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.) -// -// Functions in the CityHash family are not suitable for cryptography. -// -// Please see CityHash's README file for more details on our performance -// measurements and so on. -// -// WARNING: This code has been only lightly tested on big-endian platforms! -// It is known to work well on little-endian platforms that have a small penalty -// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs. -// It should work on all 32-bit and 64-bit platforms that allow unaligned reads; -// bug reports are welcome. -// -// By the way, for some hash functions, given strings a and b, the hash -// of a+b is easily derived from the hashes of a and b. This property -// doesn't hold for any hash functions in this file. - -#ifndef BASE_THIRD_PARTY_CITYHASH_CITY_H_ -#define BASE_THIRD_PARTY_CITYHASH_CITY_H_ - -#include <stdint.h> -#include <stdlib.h> // for size_t. -#include <utility> - -// XXX(cavalcantii): Declaring it inside of the 'base' namespace allows to -// handle linker symbol clash error with deprecated CityHash from -// third_party/smhasher in a few unit tests. -namespace base { -namespace internal { -namespace cityhash_v111 { - -typedef uint8_t uint8; -typedef uint32_t uint32; -typedef uint64_t uint64; -typedef std::pair<uint64, uint64> uint128; - -inline uint64 Uint128Low64(const uint128& x) { - return x.first; -} -inline uint64 Uint128High64(const uint128& x) { - return x.second; -} - -// Hash function for a byte array. -uint64 CityHash64(const char* buf, size_t len); - -// Hash function for a byte array. For convenience, a 64-bit seed is also -// hashed into the result. -uint64 CityHash64WithSeed(const char* buf, size_t len, uint64 seed); - -// Hash function for a byte array. For convenience, two seeds are also -// hashed into the result. -uint64 CityHash64WithSeeds(const char* buf, - size_t len, - uint64 seed0, - uint64 seed1); - -// Hash function for a byte array. -uint128 CityHash128(const char* s, size_t len); - -// Hash function for a byte array. For convenience, a 128-bit seed is also -// hashed into the result. -uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed); - -// Hash function for a byte array. Most useful in 32-bit binaries. -uint32 CityHash32(const char* buf, size_t len); - -// Hash 128 input bits down to 64 bits of output. -// This is intended to be a reasonably good hash function. -inline uint64 Hash128to64(const uint128& x) { - // Murmur-inspired hashing. - const uint64 kMul = 0x9ddfea08eb382d69ULL; - uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; - a ^= (a >> 47); - uint64 b = (Uint128High64(x) ^ a) * kMul; - b ^= (b >> 47); - b *= kMul; - return b; -} - -} // namespace cityhash_v111 -} // namespace internal -} // namespace base - -#endif // CITY_HASH_H_
diff --git a/base/third_party/cityhash/patches/0000-build-bots.patch b/base/third_party/cityhash/patches/0000-build-bots.patch deleted file mode 100644 index 23a7156..0000000 --- a/base/third_party/cityhash/patches/0000-build-bots.patch +++ /dev/null
@@ -1,227 +0,0 @@ -diff --git a/base/third_party/cityhash/city.cc b/base/third_party/cityhash/city.cc -index 41cd5ee16993..be08dc99cf18 100644 ---- a/base/third_party/cityhash/city.cc -+++ b/base/third_party/cityhash/city.cc -@@ -27,12 +27,14 @@ - // possible hash functions, by using SIMD instructions, or by - // compromising on hash quality. - --#include "config.h" --#include <city.h> -+#include "city.h" - - #include <algorithm> - #include <string.h> // for memcpy and memset - -+namespace base { -+namespace internal { -+namespace cityhash_v111 { - using namespace std; - - static uint64 UNALIGNED_LOAD64(const char *p) { -@@ -89,7 +91,12 @@ static uint32 UNALIGNED_LOAD32(const char *p) { - - #else - --#include <byteswap.h> -+// XXX(cavalcanti): building 'native_client' fails with this header. -+//#include <byteswap.h> -+ -+// Falling back to compiler builtins instead. -+#define bswap_32(x) __builtin_bswap32(x) -+#define bswap_64(x) __builtin_bswap64(x) - - #endif - -@@ -217,11 +224,11 @@ uint32 CityHash32(const char *s, size_t len) { - f = f * 5 + 0xe6546b64; - size_t iters = (len - 1) / 20; - do { -- uint32 a0 = Rotate32(Fetch32(s) * c1, 17) * c2; -- uint32 a1 = Fetch32(s + 4); -- uint32 a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2; -- uint32 a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2; -- uint32 a4 = Fetch32(s + 16); -+ a0 = Rotate32(Fetch32(s) * c1, 17) * c2; -+ a1 = Fetch32(s + 4); -+ a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2; -+ a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2; -+ a4 = Fetch32(s + 16); - h ^= a0; - h = Rotate32(h, 18); - h = h * 5 + 0xe6546b64; -@@ -512,135 +519,7 @@ uint128 CityHash128(const char *s, size_t len) { - CityHash128WithSeed(s, len, uint128(k0, k1)); - } - --#ifdef __SSE4_2__ --#include <citycrc.h> --#include <nmmintrin.h> -- --// Requires len >= 240. --static void CityHashCrc256Long(const char *s, size_t len, -- uint32 seed, uint64 *result) { -- uint64 a = Fetch64(s + 56) + k0; -- uint64 b = Fetch64(s + 96) + k0; -- uint64 c = result[0] = HashLen16(b, len); -- uint64 d = result[1] = Fetch64(s + 120) * k0 + len; -- uint64 e = Fetch64(s + 184) + seed; -- uint64 f = 0; -- uint64 g = 0; -- uint64 h = c + d; -- uint64 x = seed; -- uint64 y = 0; -- uint64 z = 0; -- -- // 240 bytes of input per iter. -- size_t iters = len / 240; -- len -= iters * 240; -- do { --#undef CHUNK --#define CHUNK(r) \ -- PERMUTE3(x, z, y); \ -- b += Fetch64(s); \ -- c += Fetch64(s + 8); \ -- d += Fetch64(s + 16); \ -- e += Fetch64(s + 24); \ -- f += Fetch64(s + 32); \ -- a += b; \ -- h += f; \ -- b += c; \ -- f += d; \ -- g += e; \ -- e += z; \ -- g += x; \ -- z = _mm_crc32_u64(z, b + g); \ -- y = _mm_crc32_u64(y, e + h); \ -- x = _mm_crc32_u64(x, f + a); \ -- e = Rotate(e, r); \ -- c += e; \ -- s += 40 -- -- CHUNK(0); PERMUTE3(a, h, c); -- CHUNK(33); PERMUTE3(a, h, f); -- CHUNK(0); PERMUTE3(b, h, f); -- CHUNK(42); PERMUTE3(b, h, d); -- CHUNK(0); PERMUTE3(b, h, e); -- CHUNK(33); PERMUTE3(a, h, e); -- } while (--iters > 0); -- -- while (len >= 40) { -- CHUNK(29); -- e ^= Rotate(a, 20); -- h += Rotate(b, 30); -- g ^= Rotate(c, 40); -- f += Rotate(d, 34); -- PERMUTE3(c, h, g); -- len -= 40; -- } -- if (len > 0) { -- s = s + len - 40; -- CHUNK(33); -- e ^= Rotate(a, 43); -- h += Rotate(b, 42); -- g ^= Rotate(c, 41); -- f += Rotate(d, 40); -- } -- result[0] ^= h; -- result[1] ^= g; -- g += h; -- a = HashLen16(a, g + z); -- x += y << 32; -- b += x; -- c = HashLen16(c, z) + h; -- d = HashLen16(d, e + result[0]); -- g += e; -- h += HashLen16(x, f); -- e = HashLen16(a, d) + g; -- z = HashLen16(b, c) + a; -- y = HashLen16(g, h) + c; -- result[0] = e + z + y + x; -- a = ShiftMix((a + y) * k0) * k0 + b; -- result[1] += a + result[0]; -- a = ShiftMix(a * k0) * k0 + c; -- result[2] = a + result[1]; -- a = ShiftMix((a + e) * k0) * k0; -- result[3] = a + result[2]; --} -- --// Requires len < 240. --static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) { -- char buf[240]; -- memcpy(buf, s, len); -- memset(buf + len, 0, 240 - len); -- CityHashCrc256Long(buf, 240, ~static_cast<uint32>(len), result); --} -- --void CityHashCrc256(const char *s, size_t len, uint64 *result) { -- if (LIKELY(len >= 240)) { -- CityHashCrc256Long(s, len, 0, result); -- } else { -- CityHashCrc256Short(s, len, result); -- } --} -- --uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { -- if (len <= 900) { -- return CityHash128WithSeed(s, len, seed); -- } else { -- uint64 result[4]; -- CityHashCrc256(s, len, result); -- uint64 u = Uint128High64(seed) + result[0]; -- uint64 v = Uint128Low64(seed) + result[1]; -- return uint128(HashLen16(u, v + result[2]), -- HashLen16(Rotate(v, 32), u * k0 + result[3])); -- } --} -+} // namespace cityhash_v111 -+} // namespace internal -+} // namespace base - --uint128 CityHashCrc128(const char *s, size_t len) { -- if (len <= 900) { -- return CityHash128(s, len); -- } else { -- uint64 result[4]; -- CityHashCrc256(s, len, result); -- return uint128(result[2], result[3]); -- } --} -- --#endif -diff --git a/base/third_party/cityhash/city.h b/base/third_party/cityhash/city.h -index 94499ce419c7..e4672f6d44da 100644 ---- a/base/third_party/cityhash/city.h -+++ b/base/third_party/cityhash/city.h -@@ -59,13 +59,20 @@ - // of a+b is easily derived from the hashes of a and b. This property - // doesn't hold for any hash functions in this file. - --#ifndef CITY_HASH_H_ --#define CITY_HASH_H_ -+#ifndef BASE_THIRD_PARTY_CITYHASH_CITY_H_ -+#define BASE_THIRD_PARTY_CITYHASH_CITY_H_ - - #include <stdlib.h> // for size_t. - #include <stdint.h> - #include <utility> - -+// XXX(cavalcantii): Declaring it inside of the 'base' namespace allows to -+// handle linker symbol clash error with deprecated CityHash from -+// third_party/smhasher in a few unit tests. -+namespace base { -+namespace internal { -+namespace cityhash_v111 { -+ - typedef uint8_t uint8; - typedef uint32_t uint32; - typedef uint64_t uint64; -@@ -109,4 +116,8 @@ inline uint64 Hash128to64(const uint128& x) { - return b; - } - -+} // namespace cityhash_v111 -+} // namespace internal -+} // namespace base -+ - #endif // CITY_HASH_H_
diff --git a/base/third_party/cityhash/patches/0001-format-style.patch b/base/third_party/cityhash/patches/0001-format-style.patch deleted file mode 100644 index ba29530..0000000 --- a/base/third_party/cityhash/patches/0001-format-style.patch +++ /dev/null
@@ -1,309 +0,0 @@ -diff --git a/base/third_party/cityhash/city.cc b/base/third_party/cityhash/city.cc -index be08dc99cf18..f0af5bbd8507 100644 ---- a/base/third_party/cityhash/city.cc -+++ b/base/third_party/cityhash/city.cc -@@ -29,21 +29,21 @@ - - #include "city.h" - --#include <algorithm> - #include <string.h> // for memcpy and memset -+#include <algorithm> - - namespace base { - namespace internal { - namespace cityhash_v111 { - using namespace std; - --static uint64 UNALIGNED_LOAD64(const char *p) { -+static uint64 UNALIGNED_LOAD64(const char* p) { - uint64 result; - memcpy(&result, p, sizeof(result)); - return result; - } - --static uint32 UNALIGNED_LOAD32(const char *p) { -+static uint32 UNALIGNED_LOAD32(const char* p) { - uint32 result; - memcpy(&result, p, sizeof(result)); - return result; -@@ -82,8 +82,8 @@ static uint32 UNALIGNED_LOAD32(const char *p) { - - #elif defined(__NetBSD__) - --#include <sys/types.h> - #include <machine/bswap.h> -+#include <sys/types.h> - #if defined(__BSWAP_RENAME) && !defined(__bswap_32) - #define bswap_32(x) bswap32(x) - #define bswap_64(x) bswap64(x) -@@ -116,11 +116,11 @@ static uint32 UNALIGNED_LOAD32(const char *p) { - #endif - #endif - --static uint64 Fetch64(const char *p) { -+static uint64 Fetch64(const char* p) { - return uint64_in_expected_order(UNALIGNED_LOAD64(p)); - } - --static uint32 Fetch32(const char *p) { -+static uint32 Fetch32(const char* p) { - return uint32_in_expected_order(UNALIGNED_LOAD32(p)); - } - -@@ -134,8 +134,7 @@ static const uint32 c1 = 0xcc9e2d51; - static const uint32 c2 = 0x1b873593; - - // A 32-bit to 32-bit integer hash copied from Murmur3. --static uint32 fmix(uint32 h) --{ -+static uint32 fmix(uint32 h) { - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; -@@ -150,7 +149,11 @@ static uint32 Rotate32(uint32 val, int shift) { - } - - #undef PERMUTE3 --#define PERMUTE3(a, b, c) do { std::swap(a, b); std::swap(a, c); } while (0) -+#define PERMUTE3(a, b, c) \ -+ do { \ -+ std::swap(a, b); \ -+ std::swap(a, c); \ -+ } while (0) - - static uint32 Mur(uint32 a, uint32 h) { - // Helper from Murmur3 for combining two 32-bit values. -@@ -162,7 +165,7 @@ static uint32 Mur(uint32 a, uint32 h) { - return h * 5 + 0xe6546b64; - } - --static uint32 Hash32Len13to24(const char *s, size_t len) { -+static uint32 Hash32Len13to24(const char* s, size_t len) { - uint32 a = Fetch32(s - 4 + (len >> 1)); - uint32 b = Fetch32(s + 4); - uint32 c = Fetch32(s + len - 8); -@@ -174,7 +177,7 @@ static uint32 Hash32Len13to24(const char *s, size_t len) { - return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h))))))); - } - --static uint32 Hash32Len0to4(const char *s, size_t len) { -+static uint32 Hash32Len0to4(const char* s, size_t len) { - uint32 b = 0; - uint32 c = 9; - for (size_t i = 0; i < len; i++) { -@@ -185,7 +188,7 @@ static uint32 Hash32Len0to4(const char *s, size_t len) { - return fmix(Mur(b, Mur(len, c))); - } - --static uint32 Hash32Len5to12(const char *s, size_t len) { -+static uint32 Hash32Len5to12(const char* s, size_t len) { - uint32 a = len, b = len * 5, c = 9, d = b; - a += Fetch32(s); - b += Fetch32(s + len - 4); -@@ -193,11 +196,11 @@ static uint32 Hash32Len5to12(const char *s, size_t len) { - return fmix(Mur(c, Mur(b, Mur(a, d)))); - } - --uint32 CityHash32(const char *s, size_t len) { -+uint32 CityHash32(const char* s, size_t len) { - if (len <= 24) { -- return len <= 12 ? -- (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) : -- Hash32Len13to24(s, len); -+ return len <= 12 -+ ? (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) -+ : Hash32Len13to24(s, len); - } - - // len > 24 -@@ -287,7 +290,7 @@ static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) { - return b; - } - --static uint64 HashLen0to16(const char *s, size_t len) { -+static uint64 HashLen0to16(const char* s, size_t len) { - if (len >= 8) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) + k2; -@@ -314,7 +317,7 @@ static uint64 HashLen0to16(const char *s, size_t len) { - - // This probably works well for 16-byte strings as well, but it may be overkill - // in that case. --static uint64 HashLen17to32(const char *s, size_t len) { -+static uint64 HashLen17to32(const char* s, size_t len) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) * k1; - uint64 b = Fetch64(s + 8); -@@ -326,8 +329,12 @@ static uint64 HashLen17to32(const char *s, size_t len) { - - // Return a 16-byte hash for 48 bytes. Quick and dirty. - // Callers do best to use "random-looking" values for a and b. --static pair<uint64, uint64> WeakHashLen32WithSeeds( -- uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) { -+static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, -+ uint64 x, -+ uint64 y, -+ uint64 z, -+ uint64 a, -+ uint64 b) { - a += w; - b = Rotate(b + a + z, 21); - uint64 c = a; -@@ -338,18 +345,15 @@ static pair<uint64, uint64> WeakHashLen32WithSeeds( - } - - // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. --static pair<uint64, uint64> WeakHashLen32WithSeeds( -- const char* s, uint64 a, uint64 b) { -- return WeakHashLen32WithSeeds(Fetch64(s), -- Fetch64(s + 8), -- Fetch64(s + 16), -- Fetch64(s + 24), -- a, -- b); -+static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, -+ uint64 a, -+ uint64 b) { -+ return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), -+ Fetch64(s + 24), a, b); - } - - // Return an 8-byte hash for 33 to 64 bytes. --static uint64 HashLen33to64(const char *s, size_t len) { -+static uint64 HashLen33to64(const char* s, size_t len) { - uint64 mul = k2 + len * 2; - uint64 a = Fetch64(s) * k2; - uint64 b = Fetch64(s + 8); -@@ -370,7 +374,7 @@ static uint64 HashLen33to64(const char *s, size_t len) { - return b + x; - } - --uint64 CityHash64(const char *s, size_t len) { -+uint64 CityHash64(const char* s, size_t len) { - if (len <= 32) { - if (len <= 16) { - return HashLen0to16(s, len); -@@ -408,18 +412,20 @@ uint64 CityHash64(const char *s, size_t len) { - HashLen16(v.second, w.second) + x); - } - --uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) { -+uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) { - return CityHash64WithSeeds(s, len, k2, seed); - } - --uint64 CityHash64WithSeeds(const char *s, size_t len, -- uint64 seed0, uint64 seed1) { -+uint64 CityHash64WithSeeds(const char* s, -+ size_t len, -+ uint64 seed0, -+ uint64 seed1) { - return HashLen16(CityHash64(s, len) - seed0, seed1); - } - - // A subroutine for CityHash128(). Returns a decent 128-bit hash for strings - // of any length representable in signed long. Based on City and Murmur. --static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { -+static uint128 CityMurmur(const char* s, size_t len, uint128 seed) { - uint64 a = Uint128Low64(seed); - uint64 b = Uint128High64(seed); - uint64 c = 0; -@@ -449,7 +455,7 @@ static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { - return uint128(a ^ b, HashLen16(b, a)); - } - --uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { -+uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) { - if (len < 128) { - return CityMurmur(s, len, seed); - } -@@ -493,7 +499,7 @@ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { - w.first *= 9; - v.first *= k0; - // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. -- for (size_t tail_done = 0; tail_done < len; ) { -+ for (size_t tail_done = 0; tail_done < len;) { - tail_done += 32; - y = Rotate(x + y, 42) * k0 + v.second; - w.first += Fetch64(s + len - tail_done + 16); -@@ -512,14 +518,13 @@ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { - HashLen16(x + w.second, y + v.second)); - } - --uint128 CityHash128(const char *s, size_t len) { -- return len >= 16 ? -- CityHash128WithSeed(s + 16, len - 16, -- uint128(Fetch64(s), Fetch64(s + 8) + k0)) : -- CityHash128WithSeed(s, len, uint128(k0, k1)); -+uint128 CityHash128(const char* s, size_t len) { -+ return len >= 16 -+ ? CityHash128WithSeed(s + 16, len - 16, -+ uint128(Fetch64(s), Fetch64(s + 8) + k0)) -+ : CityHash128WithSeed(s, len, uint128(k0, k1)); - } - - } // namespace cityhash_v111 - } // namespace internal - } // namespace base -- -diff --git a/base/third_party/cityhash/city.h b/base/third_party/cityhash/city.h -index e4672f6d44da..3e3dcaaaa9a5 100644 ---- a/base/third_party/cityhash/city.h -+++ b/base/third_party/cityhash/city.h -@@ -62,8 +62,8 @@ - #ifndef BASE_THIRD_PARTY_CITYHASH_CITY_H_ - #define BASE_THIRD_PARTY_CITYHASH_CITY_H_ - --#include <stdlib.h> // for size_t. - #include <stdint.h> -+#include <stdlib.h> // for size_t. - #include <utility> - - // XXX(cavalcantii): Declaring it inside of the 'base' namespace allows to -@@ -78,30 +78,36 @@ typedef uint32_t uint32; - typedef uint64_t uint64; - typedef std::pair<uint64, uint64> uint128; - --inline uint64 Uint128Low64(const uint128& x) { return x.first; } --inline uint64 Uint128High64(const uint128& x) { return x.second; } -+inline uint64 Uint128Low64(const uint128& x) { -+ return x.first; -+} -+inline uint64 Uint128High64(const uint128& x) { -+ return x.second; -+} - - // Hash function for a byte array. --uint64 CityHash64(const char *buf, size_t len); -+uint64 CityHash64(const char* buf, size_t len); - - // Hash function for a byte array. For convenience, a 64-bit seed is also - // hashed into the result. --uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed); -+uint64 CityHash64WithSeed(const char* buf, size_t len, uint64 seed); - - // Hash function for a byte array. For convenience, two seeds are also - // hashed into the result. --uint64 CityHash64WithSeeds(const char *buf, size_t len, -- uint64 seed0, uint64 seed1); -+uint64 CityHash64WithSeeds(const char* buf, -+ size_t len, -+ uint64 seed0, -+ uint64 seed1); - - // Hash function for a byte array. --uint128 CityHash128(const char *s, size_t len); -+uint128 CityHash128(const char* s, size_t len); - - // Hash function for a byte array. For convenience, a 128-bit seed is also - // hashed into the result. --uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed); -+uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed); - - // Hash function for a byte array. Most useful in 32-bit binaries. --uint32 CityHash32(const char *buf, size_t len); -+uint32 CityHash32(const char* buf, size_t len); - - // Hash 128 input bits down to 64 bits of output. - // This is intended to be a reasonably good hash function.
diff --git a/base/util/BUILD.gn b/base/util/BUILD.gn index 24a8de6..8f61230 100644 --- a/base/util/BUILD.gn +++ b/base/util/BUILD.gn
@@ -6,7 +6,7 @@ test("base_util_unittests") { deps = [ - "type-safety:tests", + "type_safety:tests", "values:unittests", "//base/test:run_all_base_unittests", ]
diff --git a/base/util/type-safety/BUILD.gn b/base/util/type_safety/BUILD.gn similarity index 91% rename from base/util/type-safety/BUILD.gn rename to base/util/type_safety/BUILD.gn index 8b7b05e..61ffb6d 100644 --- a/base/util/type-safety/BUILD.gn +++ b/base/util/type_safety/BUILD.gn
@@ -7,7 +7,7 @@ # Change this target's type to jumbo_component if it starts to contain more than # just headers. Header-only targets cannot be compiled to libraries, so it must # remain a source_set for now. -source_set("type-safety") { +source_set("type_safety") { sources = [ "id_type.h", ] @@ -20,7 +20,7 @@ ] deps = [ - ":type-safety", + ":type_safety", "//testing/gtest", ] }
diff --git a/base/util/type-safety/DEPS b/base/util/type_safety/DEPS similarity index 63% rename from base/util/type-safety/DEPS rename to base/util/type_safety/DEPS index d8f89b0..22f5998 100644 --- a/base/util/type-safety/DEPS +++ b/base/util/type_safety/DEPS
@@ -1,5 +1,5 @@ include_rules = [ "-base", - "+base/util/type-safety", + "+base/util/type_safety", "-third_party", ]
diff --git a/base/util/type-safety/OWNERS b/base/util/type_safety/OWNERS similarity index 100% rename from base/util/type-safety/OWNERS rename to base/util/type_safety/OWNERS
diff --git a/base/util/type-safety/id_type.h b/base/util/type_safety/id_type.h similarity index 100% rename from base/util/type-safety/id_type.h rename to base/util/type_safety/id_type.h
diff --git a/base/util/type-safety/id_type_unittest.cc b/base/util/type_safety/id_type_unittest.cc similarity index 99% rename from base/util/type-safety/id_type_unittest.cc rename to base/util/type_safety/id_type_unittest.cc index 9320951..735426d 100644 --- a/base/util/type-safety/id_type_unittest.cc +++ b/base/util/type_safety/id_type_unittest.cc
@@ -9,7 +9,7 @@ #include <type_traits> #include <unordered_map> -#include "base/util/type-safety/id_type.h" +#include "base/util/type_safety/id_type.h" #include "testing/gtest/include/gtest/gtest.h" namespace util {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index e73ad25a..f40e4157 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8913354158598190208 \ No newline at end of file +8913327733065821920 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 0b45600..8197c92 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8913377758345255248 \ No newline at end of file +8913329721043066224 \ No newline at end of file
diff --git a/cc/trees/transform_node.h b/cc/trees/transform_node.h index e15aa20..5a19cce 100644 --- a/cc/trees/transform_node.h +++ b/cc/trees/transform_node.h
@@ -105,8 +105,12 @@ bool should_be_snapped : 1; - // These are used by the cc property tree builder to position nodes w.r.t. the - // right and/or bottom of the outer viewport. + // These are used by the compositor to determine which layers need to be + // repositioned by the compositor as a result of browser controls + // expanding/contracting the outer viewport size before Blink repositions the + // fixed layers. + // TODO(bokan): Note: we never change bounds_delta in the x direction so we + // can remove this variable. bool moved_by_outer_viewport_bounds_delta_x : 1; bool moved_by_outer_viewport_bounds_delta_y : 1;
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index b3b17c2..dcdd1355 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -91,6 +91,14 @@ "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsModel.java", "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java", "java/src/org/chromium/chrome/browser/autofill_assistant/details/ImageClickthroughData.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCoordinator.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCounter.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCounterInput.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormDelegate.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormInput.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormModel.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormSelectionInput.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormSelectionChoice.java", "java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java", "java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java", @@ -126,6 +134,9 @@ "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java", "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java", "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsModel.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormDelegate.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormInput.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormModel.java", "java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java", "java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBox.java", "java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBoxModel.java",
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_counter.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_counter.xml new file mode 100644 index 0000000..f9315222 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_counter.xml
@@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_gravity="center_horizontal"> + <TextView + android:id="@+id/label" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1"/> + <Button + android:id="@+id/decrease_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="-" + tools:ignore="HardcodedText"/> + <Button + android:id="@+id/increase_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="+" + tools:ignore="HardcodedText"/> +</LinearLayout>
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_counter_input.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_counter_input.xml new file mode 100644 index 0000000..def484f4 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_counter_input.xml
@@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + <TextView + android:id="@+id/label" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + <LinearLayout + android:id="@+id/expandable_section" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:visibility="gone"/> + <TextView + android:id="@+id/expand_label" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone"/> +</LinearLayout>
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_selection_input.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_selection_input.xml new file mode 100644 index 0000000..22b241f --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_form_selection_input.xml
@@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + <TextView + android:id="@+id/label" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> +</LinearLayout>
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java index ff03574..f7425f3 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantSuggestionsCarouselCoordinator; import org.chromium.chrome.browser.autofill_assistant.details.AssistantDetailsCoordinator; +import org.chromium.chrome.browser.autofill_assistant.form.AssistantFormCoordinator; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderCoordinator; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel; import org.chromium.chrome.browser.autofill_assistant.infobox.AssistantInfoBoxCoordinator; @@ -47,6 +48,7 @@ // Child coordinators. private final AssistantHeaderCoordinator mHeaderCoordinator; private final AssistantDetailsCoordinator mDetailsCoordinator; + private final AssistantFormCoordinator mFormCoordinator; private final AssistantCarouselCoordinator mSuggestionsCoordinator; private final AssistantCarouselCoordinator mActionsCoordinator; private final AssistantPeekHeightCoordinator mPeekHeightCoordinator; @@ -67,12 +69,16 @@ mContent = new AssistantBottomSheetContent(activity); // Instantiate child components. + int childSpacing = activity.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_bottombar_vertical_spacing); mHeaderCoordinator = new AssistantHeaderCoordinator( activity, mContent.mBottomBarView, model.getHeaderModel()); mInfoBoxCoordinator = new AssistantInfoBoxCoordinator(activity, model.getInfoBoxModel()); mDetailsCoordinator = new AssistantDetailsCoordinator(activity, model.getDetailsModel()); mPaymentRequestCoordinator = new AssistantPaymentRequestCoordinator(activity, model.getPaymentRequestModel()); + mFormCoordinator = + new AssistantFormCoordinator(activity, model.getFormModel(), childSpacing); mSuggestionsCoordinator = new AssistantSuggestionsCarouselCoordinator(activity, model.getSuggestionsModel()); mActionsCoordinator = @@ -86,6 +92,7 @@ mContent.mBottomBarView.addView(mInfoBoxCoordinator.getView()); mContent.mBottomBarView.addView(mDetailsCoordinator.getView()); mContent.mBottomBarView.addView(mPaymentRequestCoordinator.getView()); + mContent.mBottomBarView.addView(mFormCoordinator.getView()); mContent.mBottomBarView.addView(mSuggestionsCoordinator.getView()); mContent.mBottomBarView.addView(mActionsCoordinator.getView()); @@ -94,8 +101,6 @@ // do not hide them because there is an incompatibility bug between the animateLayoutChanges // attribute set on mBottomBarView and the animations ran by the carousels // RecyclerView. - int childSpacing = activity.getResources().getDimensionPixelSize( - R.dimen.autofill_assistant_bottombar_vertical_spacing); setChildMarginTop(mDetailsCoordinator.getView(), childSpacing); setChildMarginTop(mPaymentRequestCoordinator.getView(), childSpacing); setCarouselMarginTop(mSuggestionsCoordinator.getView(), @@ -103,11 +108,11 @@ setCarouselMarginTop(mActionsCoordinator.getView(), model.getActionsModel().getChipsModel(), childSpacing); - // We set the horizontal margins of the details and info box. We don't set a padding - // to the container and the payment request as we want the carousels children and PR - // sections to be full-width. + // Set the horizontal margins of children. We don't set them on the payment request and the + // carousels to allow them to take the full width of the sheet. setHorizontalMargins(mInfoBoxCoordinator.getView()); setHorizontalMargins(mDetailsCoordinator.getView()); + setHorizontalMargins(mFormCoordinator.getView()); View bottomSheetContainer = bottomSheet.findViewById(org.chromium.chrome.R.id.bottom_sheet_content); @@ -224,6 +229,7 @@ mDetailsCoordinator.setForceInvisible(showOnlyCarousels); mModel.getPaymentRequestModel().set( AssistantPaymentRequestModel.FORCE_INVISIBLE, showOnlyCarousels); + mFormCoordinator.setForceInvisible(showOnlyCarousels); } @Override @@ -334,6 +340,10 @@ return mPaymentRequestCoordinator.getScrollView().getScrollY(); } + if (mFormCoordinator.getView().isShown()) { + return mFormCoordinator.getView().getScrollY(); + } + return 0; }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java index edb190d2..4a71a5c 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java
@@ -8,6 +8,7 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantCarouselModel; import org.chromium.chrome.browser.autofill_assistant.details.AssistantDetailsModel; +import org.chromium.chrome.browser.autofill_assistant.form.AssistantFormModel; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel; import org.chromium.chrome.browser.autofill_assistant.infobox.AssistantInfoBoxModel; import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayModel; @@ -28,6 +29,7 @@ private final AssistantInfoBoxModel mInfoBoxModel = new AssistantInfoBoxModel(); private final AssistantPaymentRequestModel mPaymentRequestModel = new AssistantPaymentRequestModel(); + private final AssistantFormModel mFormModel = new AssistantFormModel(); private final AssistantCarouselModel mSuggestionsModel = new AssistantCarouselModel(); private final AssistantCarouselModel mActionsModel = new AssistantCarouselModel(); @@ -60,6 +62,11 @@ return mPaymentRequestModel; } + @CalledByNative + public AssistantFormModel getFormModel() { + return mFormModel; + } + public AssistantCarouselModel getSuggestionsModel() { return mSuggestionsModel; }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCoordinator.java new file mode 100644 index 0000000..79d1c72 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCoordinator.java
@@ -0,0 +1,75 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.form; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.ScrollView; + +import org.chromium.chrome.browser.autofill_assistant.AbstractListObserver; + +/** + * A coordinator responsible for showing a form to the user. + * + * See http://go/aa-form-action for more information. + */ +public class AssistantFormCoordinator { + private final AssistantFormModel mModel; + private final ScrollView mView; + private final LinearLayout mContainerView; + + private boolean mForceInvisible; + + public AssistantFormCoordinator( + Context context, AssistantFormModel model, int verticalSpacingPx) { + mModel = model; + mView = new ScrollView(context); + mContainerView = new LinearLayout(context); + mView.setLayoutParams( + new LinearLayout.LayoutParams(/* width= */ ViewGroup.LayoutParams.MATCH_PARENT, + /* height= */ 0, /* weight= */ 1)); + mContainerView.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + mContainerView.setOrientation(LinearLayout.VERTICAL); + mView.addView(mContainerView); + + updateVisibility(); + mModel.getInputsModel().addObserver(new AbstractListObserver<Void>() { + @Override + public void onDataSetChanged() { + mContainerView.removeAllViews(); + for (AssistantFormInput input : mModel.getInputsModel()) { + // Add the views to the linear layout (not the scroll view). + View view = input.createView(context, mContainerView); + mContainerView.addView(view); + ((LinearLayout.LayoutParams) view.getLayoutParams()).topMargin = + verticalSpacingPx; + } + updateVisibility(); + } + }); + } + + /** Return the view associated to this coordinator. */ + public ScrollView getView() { + return mView; + } + + /** Force the view of this coordinator to be invisible. */ + public void setForceInvisible(boolean forceInvisible) { + if (mForceInvisible == forceInvisible) return; + + mForceInvisible = forceInvisible; + updateVisibility(); + } + + private void updateVisibility() { + int visibility = + !mForceInvisible && mModel.getInputsModel().size() > 0 ? View.VISIBLE : View.GONE; + mView.setVisibility(visibility); + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCounter.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCounter.java new file mode 100644 index 0000000..c6f4684a --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCounter.java
@@ -0,0 +1,47 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.form; + +import java.text.ChoiceFormat; + +class AssistantFormCounter { + private final String mLabel; + private final ChoiceFormat mLabelChoiceFormat; + private final int mMinValue; + private final int mMaxValue; + private int mValue; + + AssistantFormCounter(String label, int initialValue, int minValue, int maxValue) { + mLabel = label; + mLabelChoiceFormat = new ChoiceFormat(label); + mValue = initialValue; + mMinValue = minValue; + mMaxValue = maxValue; + } + + String getLabel() { + return mLabel; + } + + ChoiceFormat getLabelChoiceFormat() { + return mLabelChoiceFormat; + } + + int getMinValue() { + return mMinValue; + } + + int getMaxValue() { + return mMaxValue; + } + + int getValue() { + return mValue; + } + + public void setValue(int value) { + mValue = value; + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCounterInput.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCounterInput.java new file mode 100644 index 0000000..b439067 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormCounterInput.java
@@ -0,0 +1,137 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.form; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.chromium.chrome.autofill_assistant.R; + +import java.util.List; +import java.util.regex.Pattern; + +/** A form input that allows to modify one or multiple counters. */ +class AssistantFormCounterInput extends AssistantFormInput { + private static final String QUOTED_VALUE = Pattern.quote("{value}"); + + interface Delegate { + void onCounterChanged(int counterIndex, int value); + } + + private final String mLabel; + private final List<AssistantFormCounter> mCounters; + private final int mMinimizedCount; + private final Delegate mDelegate; + + AssistantFormCounterInput(String label, List<AssistantFormCounter> counters, int minimizedCount, + Delegate delegate) { + mLabel = label; + mCounters = counters; + mMinimizedCount = minimizedCount; + mDelegate = delegate; + } + + @Override + public View createView(Context context, ViewGroup parent) { + ViewGroup root = (ViewGroup) LayoutInflater.from(context).inflate( + R.layout.autofill_assistant_form_counter_input, parent, /* attachToRoot= */ false); + TextView label = root.findViewById(R.id.label); + if (mLabel.isEmpty()) { + label.setVisibility(View.GONE); + } else { + label.setText(mLabel); + } + + ViewGroup expandableSection = root.findViewById(R.id.expandable_section); + int labelIndex = root.indexOfChild(label); + for (int i = 0; i < mCounters.size(); i++) { + View counterView = createCounterView(context, mCounters.get(i), i); + if (i < mMinimizedCount) { + // Add the counters below the label. + root.addView(counterView, labelIndex + i + 1); + } else { + expandableSection.addView(counterView); + } + } + + // If some counters are in the expandable section, show the "Show more" label that will + // expand it when clicked. + if (expandableSection.getChildCount() > 0) { + TextView expandLabel = root.findViewById(R.id.expand_label); + expandLabel.setVisibility(View.VISIBLE); + + String expandString = + context.getResources().getString(R.string.autofill_assistant_form_show_more); + String shrinkString = + context.getResources().getString(R.string.autofill_assistant_form_show_less); + expandLabel.setText(expandString); + expandLabel.setOnClickListener(unusedView -> { + boolean expanded = expandableSection.getVisibility() == View.VISIBLE; + if (expanded) { + // Shrink. + expandableSection.setVisibility(View.GONE); + expandLabel.setText(expandString); + } else { + // Expand. + expandableSection.setVisibility(View.VISIBLE); + expandLabel.setText(shrinkString); + } + }); + } + + return root; + } + + private View createCounterView( + Context context, AssistantFormCounter counter, int counterIndex) { + View view = LayoutInflater.from(context).inflate( + R.layout.autofill_assistant_form_counter, /*root= */ null); + TextView labelView = view.findViewById(R.id.label); + updateLabel(counter, labelView); + + View decreaseButton = view.findViewById(R.id.decrease_button); + View increaseButton = view.findViewById(R.id.increase_button); + updateCounterState(counter, decreaseButton, increaseButton); + + decreaseButton.setOnClickListener(unusedView + -> updateCounter( + counter, counterIndex, labelView, -1, decreaseButton, increaseButton)); + + increaseButton.setOnClickListener(unusedView + -> updateCounter( + counter, counterIndex, labelView, +1, decreaseButton, increaseButton)); + + return view; + } + + private void updateLabel(AssistantFormCounter counter, TextView labelView) { + String label = counter.getLabel(); + if (counter.getLabelChoiceFormat().getLimits().length > 0) { + label = counter.getLabelChoiceFormat().format(counter.getValue()); + } + label = label.replaceAll(QUOTED_VALUE, Integer.toString(counter.getValue())); + labelView.setText(label); + } + + private void updateCounter(AssistantFormCounter counter, int counterIndex, TextView labelView, + int delta, View decreaseButton, View increaseButton) { + counter.setValue(counter.getValue() + delta); + counter.setValue(Math.max(counter.getMinValue(), counter.getValue())); + counter.setValue(Math.min(counter.getMaxValue(), counter.getValue())); + updateCounterState(counter, decreaseButton, increaseButton); + + updateLabel(counter, labelView); + mDelegate.onCounterChanged(counterIndex, counter.getValue()); + } + + private void updateCounterState( + AssistantFormCounter counter, View decreaseButton, View increaseButton) { + decreaseButton.setEnabled(counter.getValue() > counter.getMinValue()); + increaseButton.setEnabled(counter.getValue() < counter.getMaxValue()); + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormDelegate.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormDelegate.java new file mode 100644 index 0000000..3f77fbe --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormDelegate.java
@@ -0,0 +1,45 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.form; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** Delegate for the form UI. */ +@JNINamespace("autofill_assistant") +class AssistantFormDelegate { + private long mNativeAssistantFormDelegate; + + @CalledByNative + private static AssistantFormDelegate create(long nativeAssistantFormDelegate) { + return new AssistantFormDelegate(nativeAssistantFormDelegate); + } + + private AssistantFormDelegate(long nativeAssistantFormDelegate) { + mNativeAssistantFormDelegate = nativeAssistantFormDelegate; + } + + void onCounterChanged(int inputIndex, int counterIndex, int value) { + if (mNativeAssistantFormDelegate != 0) { + nativeOnCounterChanged(mNativeAssistantFormDelegate, inputIndex, counterIndex, value); + } + } + void onChoiceSelectionChanged(int inputIndex, int choiceIndex, boolean selected) { + if (mNativeAssistantFormDelegate != 0) { + nativeOnChoiceSelectionChanged( + mNativeAssistantFormDelegate, inputIndex, choiceIndex, selected); + } + } + + @CalledByNative + private void clearNativePtr() { + mNativeAssistantFormDelegate = 0; + } + + private native void nativeOnCounterChanged(long nativeAssistantFormDelegate, int inputIndex, + int counterIndex, long nativeAssistantOverlayDelegate); + private native void nativeOnChoiceSelectionChanged( + long nativeAssistantFormDelegate, int inputIndex, int choiceIndex, boolean selected); +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormInput.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormInput.java new file mode 100644 index 0000000..8c8a68a --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormInput.java
@@ -0,0 +1,76 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.form; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +import java.util.ArrayList; +import java.util.List; + +/** An input in a form. */ +@JNINamespace("autofill_assistant") +public abstract class AssistantFormInput { + /** Create a view associated to this input. */ + public abstract View createView(Context context, ViewGroup parent); + + // TODO(crbug.com/806868): Check if it's possible to create generic methods createList, add, etc + // to manipulate java lists from native code, or reuse if they already exist. + @CalledByNative + private static List<AssistantFormCounter> createCounterList() { + return new ArrayList<>(); + } + + @CalledByNative + private static List<AssistantFormSelectionChoice> createChoiceList() { + return new ArrayList<>(); + } + + @CalledByNative + private static void addCounter( + List<AssistantFormCounter> counters, AssistantFormCounter counter) { + counters.add(counter); + } + + @CalledByNative + private static void addChoice( + List<AssistantFormSelectionChoice> choices, AssistantFormSelectionChoice choice) { + choices.add(choice); + } + + @CalledByNative + private static AssistantFormCounter createCounter( + String label, int initialValue, int minValue, int maxValue) { + return new AssistantFormCounter(label, initialValue, minValue, maxValue); + } + + @CalledByNative + private static AssistantFormSelectionChoice createChoice( + String label, boolean initiallySelected) { + return new AssistantFormSelectionChoice(label, initiallySelected); + } + + @CalledByNative + private static AssistantFormCounterInput createCounterInput(int inputIndex, String label, + List<AssistantFormCounter> counters, int minimizedCount, + AssistantFormDelegate delegate) { + return new AssistantFormCounterInput(label, counters, minimizedCount, + (counterIndex, + value) -> delegate.onCounterChanged(inputIndex, counterIndex, value)); + } + + @CalledByNative + private static AssistantFormSelectionInput createSelectionInput(int inputIndex, String label, + List<AssistantFormSelectionChoice> choices, boolean allowMultipleChoices, + AssistantFormDelegate delegate) { + return new AssistantFormSelectionInput(label, choices, allowMultipleChoices, + (choiceIndex, selected) + -> delegate.onChoiceSelectionChanged(inputIndex, choiceIndex, selected)); + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormModel.java new file mode 100644 index 0000000..199dc78 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormModel.java
@@ -0,0 +1,43 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.form; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.ui.modelutil.ListModel; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** A model for the assistant form. */ +@JNINamespace("autofill_assistant") +public class AssistantFormModel { + private final ListModel<AssistantFormInput> mInputsModel = new ListModel<>(); + + ListModel<AssistantFormInput> getInputsModel() { + return mInputsModel; + } + + @CalledByNative + private void setInputs(List<AssistantFormInput> inputs) { + mInputsModel.set(inputs); + } + + @CalledByNative + private void clearInputs() { + mInputsModel.set(Arrays.asList()); + } + + @CalledByNative + private static List<AssistantFormInput> createInputList() { + return new ArrayList<>(); + } + + @CalledByNative + private static void addInput(List<AssistantFormInput> inputs, AssistantFormInput input) { + inputs.add(input); + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormSelectionChoice.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormSelectionChoice.java new file mode 100644 index 0000000..f3c7fa0 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormSelectionChoice.java
@@ -0,0 +1,23 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.form; + +class AssistantFormSelectionChoice { + private final String mLabel; + private final boolean mIsInitiallySelected; + + public AssistantFormSelectionChoice(String label, boolean isInitiallySelected) { + mLabel = label; + mIsInitiallySelected = isInitiallySelected; + } + + public String getLabel() { + return mLabel; + } + + public boolean isInitiallySelected() { + return mIsInitiallySelected; + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormSelectionInput.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormSelectionInput.java new file mode 100644 index 0000000..72ed63b --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/form/AssistantFormSelectionInput.java
@@ -0,0 +1,92 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.form; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; + +import java.util.List; + +/** A form input that allows to choose between multiple choices. */ +class AssistantFormSelectionInput extends AssistantFormInput { + interface Delegate { + void onChoiceSelectionChanged(int choiceIndex, boolean selected); + } + + private final String mLabel; + private final List<AssistantFormSelectionChoice> mChoices; + private final boolean mAllowMultipleChoices; + private final Delegate mDelegate; + + public AssistantFormSelectionInput(String label, List<AssistantFormSelectionChoice> choices, + boolean allowMultipleChoices, Delegate delegate) { + mLabel = label; + mChoices = choices; + mAllowMultipleChoices = allowMultipleChoices; + mDelegate = delegate; + } + + @Override + public View createView(Context context, ViewGroup parent) { + ViewGroup root = (ViewGroup) LayoutInflater.from(context).inflate( + org.chromium.chrome.autofill_assistant.R.layout + .autofill_assistant_form_selection_input, + parent, /* attachToRoot= */ false); + TextView label = root.findViewById(org.chromium.chrome.autofill_assistant.R.id.label); + if (mLabel.isEmpty()) { + label.setVisibility(View.GONE); + } else { + label.setText(mLabel); + } + + LinearLayout container; + if (mAllowMultipleChoices) { + container = new LinearLayout(context); + for (int i = 0; i < mChoices.size(); i++) { + CheckBox checkBox = new CheckBox(context); + initChoiceView(container, checkBox, i); + checkBox.setChecked(mChoices.get(i).isInitiallySelected()); + } + } else { + // If only one choice can be selected, we need the parent to be a RadioGroup to make + // sure there is always at most one selected choice. + RadioGroup radioGroup = new RadioGroup(context); + container = radioGroup; + for (int i = 0; i < mChoices.size(); i++) { + RadioButton radioButton = new RadioButton(context); + initChoiceView(container, radioButton, i); + + if (mChoices.get(i).isInitiallySelected()) { + // We can't use the CompoundButton#setChecked method for radio buttons as this + // will not update the state of the parent RadioGroup, so we need to use the + // RadioGroup#check method instead. + radioGroup.check(radioButton.getId()); + } + } + } + + container.setOrientation(LinearLayout.VERTICAL); + container.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + root.addView(container); + return root; + } + + private void initChoiceView(LinearLayout container, CompoundButton view, int index) { + container.addView(view); + AssistantFormSelectionChoice choice = mChoices.get(index); + view.setText(choice.getLabel()); + view.setOnCheckedChangeListener( + (unusedView, isChecked) -> mDelegate.onChoiceSelectionChanged(index, isChecked)); + } +}
diff --git a/chrome/android/features/autofill_assistant/java/strings/android_chrome_autofill_assistant_strings.grd b/chrome/android/features/autofill_assistant/java/strings/android_chrome_autofill_assistant_strings.grd index 13e8378..ee5392d 100644 --- a/chrome/android/features/autofill_assistant/java/strings/android_chrome_autofill_assistant_strings.grd +++ b/chrome/android/features/autofill_assistant/java/strings/android_chrome_autofill_assistant_strings.grd
@@ -165,6 +165,12 @@ <message name="IDS_AUTOFILL_ASSISTANT_SHEET_CLOSED" desc="Text announced when the Autofill Assistant sheet is closed."> Google Assistant in Chrome closed. </message> + <message name="IDS_AUTOFILL_ASSISTANT_FORM_SHOW_MORE" desc="Text shown when displaying a form with an expandable section that is minimized."> + Show more + </message> + <message name="IDS_AUTOFILL_ASSISTANT_FORM_SHOW_LESS" desc="Text shown when displaying a form with an expandable section that can be minimized."> + Show less + </message> </messages> </release> </grit>
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingComponentBridge.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingComponentBridge.java index 6419e5d..92e2b72f 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingComponentBridge.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingComponentBridge.java
@@ -67,6 +67,7 @@ : "Controller has been destroyed but the bridge wasn't cleaned up!"; ManualFillingMetricsRecorder.recordActionSelected( AccessoryAction.GENERATE_PASSWORD_AUTOMATIC); + mManualFillingComponent.dismiss(); nativeOnGenerationRequested(mNativeView); })}; } else { @@ -153,6 +154,11 @@ nativeCachePasswordSheetDataForTesting(webContents, userNames, passwords); } + @VisibleForTesting + public static void signalAutoGenerationStatus(WebContents webContents, boolean available) { + nativeSignalAutoGenerationStatusForTesting(webContents, available); + } + private native void nativeOnFaviconRequested(long nativeManualFillingViewAndroid, int desiredSizeInPx, Callback<Bitmap> faviconCallback); private native void nativeOnFillingTriggered( @@ -163,4 +169,6 @@ private static native void nativeCachePasswordSheetDataForTesting( WebContents webContents, String[] userNames, String[] passwords); + private static native void nativeSignalAutoGenerationStatusForTesting( + WebContents webContents, boolean available); }
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java index f0c3a3b71..107b4ee 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java
@@ -178,6 +178,29 @@ @Test @SmallTest @Features.DisableFeatures(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY) + public void testAccessoryHiddenAfterTappingAutoGenerationButton() + throws InterruptedException, TimeoutException { + mHelper.loadTestPage(false); + + // Focus the field to bring up the accessory and add the generation button. + mHelper.focusPasswordField(); + mHelper.signalAutoGenerationStatus(true); + mHelper.waitForKeyboardAccessoryToBeShown(); + + // Click the tab to show the sheet and hide the keyboard. + whenDisplayed(isKeyboardAccessoryTabLayout()).perform(selectTabAtPosition(0)); + mHelper.waitForKeyboardToDisappear(); + whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); + + // Click the generation button. This should hide the accessory sheet and bar. + onView(withText(R.string.password_generation_accessory_button)).perform(click()); + waitToBeHidden(withChild(withId(R.id.keyboard_accessory_sheet))); + waitToBeHidden(withId(R.id.keyboard_accessory)); + } + + @Test + @SmallTest + @Features.DisableFeatures(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY) public void testHidingSheetBringsBackKeyboard() throws InterruptedException, TimeoutException { mHelper.loadTestPage(false);
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java index 37ea094..8ea0030 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java
@@ -416,4 +416,11 @@ AccessoryAction.GENERATE_PASSWORD_AUTOMATIC, result -> {})}); }); } + + public void signalAutoGenerationStatus(boolean available) { + TestThreadUtils.runOnUiThreadBlocking(() -> { + ManualFillingComponentBridge.signalAutoGenerationStatus( + mActivityTestRule.getWebContents(), available); + }); + } }
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java index e5ae3ff..e66e707 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java
@@ -17,6 +17,7 @@ import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition; import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; +import android.os.Build; import android.support.test.filters.SmallTest; import org.junit.After; @@ -26,6 +27,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; @@ -82,6 +84,7 @@ @Test @SmallTest @EnableFeatures({ChromeFeatureList.PASSWORDS_KEYBOARD_ACCESSORY}) + @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.LOLLIPOP, message = "crbug.com/958631") public void testPasswordSheetDisplaysProvidedItems() throws InterruptedException, TimeoutException { mHelper.loadTestPage(false); @@ -116,6 +119,7 @@ @Test @SmallTest @EnableFeatures({ChromeFeatureList.PASSWORDS_KEYBOARD_ACCESSORY}) + @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.LOLLIPOP, message = "crbug.com/958631") public void testFillsPasswordOnTap() throws InterruptedException, TimeoutException { mHelper.loadTestPage(false); mHelper.cacheCredentials("mpark@abc.com", "ShorterPassword");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 43a3475..10dd057 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -1338,7 +1338,7 @@ } /** - * Tests that page load metrice are sent. + * Tests that page load metrics are sent. */ @Test @SmallTest @@ -2724,7 +2724,11 @@ public void extraCallback(String callbackName, Bundle args) { if (callbackName.equals(CustomTabsConnection.ON_WARMUP_COMPLETED)) return; - assertEquals(CustomTabsConnection.PAGE_LOAD_METRICS_CALLBACK, callbackName); + // Check if the callback name is either the Bottom Bar Scroll, or Page Load Metrics. + // See https://crbug.com/963538 for why it might be either. + if (!CustomTabsConnection.BOTTOM_BAR_SCROLL_STATE_CALLBACK.equals(callbackName)) { + assertEquals(CustomTabsConnection.PAGE_LOAD_METRICS_CALLBACK, callbackName); + } if (-1 != args.getLong(PageLoadMetrics.EFFECTIVE_CONNECTION_TYPE, -1)) { sawNetworkQualityEstimates.set(true); }
diff --git a/chrome/app/app_management_strings.grdp b/chrome/app/app_management_strings.grdp index 90aac942..3c20cf7d 100644 --- a/chrome/app/app_management_strings.grdp +++ b/chrome/app/app_management_strings.grdp
@@ -76,4 +76,7 @@ <message name="IDS_APP_MANAGEMENT_VERSION" desc="Label for version of an app in the app settings page."> Version: <ph name="VERSION">$1<ex>4.0</ex></ph> </message> + <message name="IDS_APP_MANAGEMENT_PIN_ENFORCED_BY_POLICY" desc="Short text for the pin/unpin context menu to tell user the setting is enforced by policy of an app."> + Pinned by administrator + </message> </grit-part>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 3d12ebde..12b4bf43 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1996,7 +1996,6 @@ "//components/sync_bookmarks", "//components/sync_preferences", "//components/sync_sessions", - "//components/thread_pool_util", "//components/tracing:startup_tracing", "//components/translate/content/browser", "//components/translate/core/browser", @@ -2144,6 +2143,8 @@ "android/android_theme_resources.h", "android/app_hooks.cc", "android/app_hooks.h", + "android/autofill_assistant/assistant_form_delegate.cc", + "android/autofill_assistant/assistant_form_delegate.h", "android/autofill_assistant/assistant_overlay_delegate.cc", "android/autofill_assistant/assistant_overlay_delegate.h", "android/autofill_assistant/assistant_payment_request_delegate.cc", @@ -2808,8 +2809,6 @@ "apps/intent_helper/intent_picker_auto_display_service.h", "apps/intent_helper/intent_picker_auto_display_service_factory.cc", "apps/intent_helper/intent_picker_auto_display_service_factory.h", - "apps/intent_helper/intent_picker_controller.cc", - "apps/intent_helper/intent_picker_controller.h", "apps/intent_helper/page_transition_util.cc", "apps/intent_helper/page_transition_util.h", "background/background_contents.cc",
diff --git a/chrome/browser/android/autofill_assistant/assistant_form_delegate.cc b/chrome/browser/android/autofill_assistant/assistant_form_delegate.cc new file mode 100644 index 0000000..a17c3502 --- /dev/null +++ b/chrome/browser/android/autofill_assistant/assistant_form_delegate.cc
@@ -0,0 +1,48 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/autofill_assistant/assistant_form_delegate.h" + +#include "chrome/browser/android/autofill_assistant/ui_controller_android.h" +#include "jni/AssistantFormDelegate_jni.h" + +using base::android::AttachCurrentThread; + +namespace autofill_assistant { + +AssistantFormDelegate::AssistantFormDelegate(UiControllerAndroid* ui_controller) + : ui_controller_(ui_controller) { + java_assistant_form_delegate_ = Java_AssistantFormDelegate_create( + AttachCurrentThread(), reinterpret_cast<intptr_t>(this)); +} + +AssistantFormDelegate::~AssistantFormDelegate() { + Java_AssistantFormDelegate_clearNativePtr(AttachCurrentThread(), + java_assistant_form_delegate_); +} + +void AssistantFormDelegate::OnCounterChanged( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jint input_index, + jint counter_index, + jint value) { + ui_controller_->OnCounterChanged(input_index, counter_index, value); +} + +void AssistantFormDelegate::OnChoiceSelectionChanged( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jint input_index, + jint choice_index, + jboolean selected) { + ui_controller_->OnChoiceSelectionChanged(input_index, choice_index, selected); +} + +base::android::ScopedJavaGlobalRef<jobject> +AssistantFormDelegate::GetJavaObject() { + return java_assistant_form_delegate_; +} + +} // namespace autofill_assistant
diff --git a/chrome/browser/android/autofill_assistant/assistant_form_delegate.h b/chrome/browser/android/autofill_assistant/assistant_form_delegate.h new file mode 100644 index 0000000..0d9c140 --- /dev/null +++ b/chrome/browser/android/autofill_assistant/assistant_form_delegate.h
@@ -0,0 +1,41 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_AUTOFILL_ASSISTANT_ASSISTANT_FORM_DELEGATE_H_ +#define CHROME_BROWSER_ANDROID_AUTOFILL_ASSISTANT_ASSISTANT_FORM_DELEGATE_H_ + +#include "base/android/scoped_java_ref.h" + +namespace autofill_assistant { +class UiControllerAndroid; +// Delegate class for the assistant form. +class AssistantFormDelegate { + public: + explicit AssistantFormDelegate(UiControllerAndroid* ui_controller); + ~AssistantFormDelegate(); + + void OnCounterChanged(JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jint input_index, + jint counter_index, + jint value); + + void OnChoiceSelectionChanged( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jint input_index, + jint choice_index, + jboolean selected); + + base::android::ScopedJavaGlobalRef<jobject> GetJavaObject(); + + private: + UiControllerAndroid* ui_controller_; + + // Java-side AssistantFormDelegate object. + base::android::ScopedJavaGlobalRef<jobject> java_assistant_form_delegate_; +}; +} // namespace autofill_assistant + +#endif // CHROME_BROWSER_ANDROID_AUTOFILL_ASSISTANT_ASSISTANT_FORM_DELEGATE_H_
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 57ad2f6..819e6578 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -38,6 +38,8 @@ #include "google_apis/google_api_keys.h" #include "jni/AssistantDetailsModel_jni.h" #include "jni/AssistantDetails_jni.h" +#include "jni/AssistantFormInput_jni.h" +#include "jni/AssistantFormModel_jni.h" #include "jni/AssistantHeaderModel_jni.h" #include "jni/AssistantInfoBoxModel_jni.h" #include "jni/AssistantInfoBox_jni.h" @@ -79,6 +81,7 @@ const base::android::JavaRef<jobject>& jactivity) : overlay_delegate_(this), payment_request_delegate_(this), + form_delegate_(this), weak_ptr_factory_(this) { java_object_ = Java_AutofillAssistantUiController_create( env, jactivity, @@ -131,6 +134,7 @@ OnTouchableAreaChanged(area); OnResizeViewportChanged(ui_delegate->GetResizeViewport()); OnPeekModeChanged(ui_delegate->GetPeekMode()); + OnFormChanged(ui_delegate->GetForm()); UiDelegate::OverlayColors colors; ui_delegate->GetOverlayColors(&colors); @@ -638,6 +642,96 @@ state->terms_and_conditions); } +// FormProto related methods. +base::android::ScopedJavaLocalRef<jobject> UiControllerAndroid::GetFormModel() { + return Java_AssistantModel_getFormModel(AttachCurrentThread(), GetModel()); +} + +void UiControllerAndroid::OnFormChanged(const FormProto* form) { + JNIEnv* env = AttachCurrentThread(); + + if (!form) { + Java_AssistantFormModel_clearInputs(env, GetFormModel()); + return; + } + + auto jinput_list = Java_AssistantFormModel_createInputList(env); + for (int i = 0; i < form->inputs_size(); i++) { + const FormInputProto input = form->inputs(i); + + switch (input.input_type_case()) { + case FormInputProto::InputTypeCase::kCounter: { + CounterInputProto counter_input = input.counter(); + + auto jcounters = Java_AssistantFormInput_createCounterList(env); + for (const CounterInputProto::Counter counter : + counter_input.counters()) { + Java_AssistantFormInput_addCounter( + env, jcounters, + Java_AssistantFormInput_createCounter( + env, + base::android::ConvertUTF8ToJavaString(env, counter.label()), + counter.initial_value(), counter.min_value(), + counter.max_value())); + } + + Java_AssistantFormModel_addInput( + env, jinput_list, + Java_AssistantFormInput_createCounterInput( + env, i, + base::android::ConvertUTF8ToJavaString(env, + counter_input.label()), + jcounters, counter_input.minimized_count(), + form_delegate_.GetJavaObject())); + break; + } + case FormInputProto::InputTypeCase::kSelection: { + SelectionInputProto selection_input = input.selection(); + + auto jchoices = Java_AssistantFormInput_createChoiceList(env); + for (const SelectionInputProto::Choice choice : + selection_input.choices()) { + Java_AssistantFormInput_addChoice( + env, jchoices, + Java_AssistantFormInput_createChoice( + env, + base::android::ConvertUTF8ToJavaString(env, choice.label()), + choice.selected())); + } + + Java_AssistantFormModel_addInput( + env, jinput_list, + Java_AssistantFormInput_createSelectionInput( + env, i, + base::android::ConvertUTF8ToJavaString(env, + selection_input.label()), + jchoices, selection_input.allow_multiple(), + form_delegate_.GetJavaObject())); + break; + } + case FormInputProto::InputTypeCase::INPUT_TYPE_NOT_SET: + NOTREACHED(); + break; + // Intentionally no default case to make compilation fail if a new value + // was added to the enum but not to this list. + } + + Java_AssistantFormModel_setInputs(env, GetFormModel(), jinput_list); + } +} + +void UiControllerAndroid::OnCounterChanged(int input_index, + int counter_index, + int value) { + ui_delegate_->SetCounterValue(input_index, counter_index, value); +} + +void UiControllerAndroid::OnChoiceSelectionChanged(int input_index, + int choice_index, + bool selected) { + ui_delegate_->SetChoiceSelected(input_index, choice_index, selected); +} + // Details related method. base::android::ScopedJavaLocalRef<jobject>
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index 9b24314..c2b52e3 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -11,6 +11,7 @@ #include "base/android/scoped_java_ref.h" #include "base/macros.h" +#include "chrome/browser/android/autofill_assistant/assistant_form_delegate.h" #include "chrome/browser/android/autofill_assistant/assistant_overlay_delegate.h" #include "chrome/browser/android/autofill_assistant/assistant_payment_request_delegate.h" #include "components/autofill_assistant/browser/chip.h" @@ -76,6 +77,7 @@ void OnPeekModeChanged( ConfigureBottomSheetProto::PeekMode peek_mode) override; void OnOverlayColorsChanged(const UiDelegate::OverlayColors& colors) override; + void OnFormChanged(const FormProto* form) override; // Called by AssistantOverlayDelegate: void OnUnexpectedTaps(); @@ -93,6 +95,12 @@ void OnCreditCardChanged(std::unique_ptr<autofill::CreditCard> card); void OnTermsAndConditionsChanged(TermsAndConditionsState state); + // Called by AssistantFormDelegate: + void OnCounterChanged(int input_index, int counter_index, int value); + void OnChoiceSelectionChanged(int input_index, + int choice_index, + bool selected); + // Called by Java. void SnackbarResult(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, @@ -132,6 +140,7 @@ UiDelegate* ui_delegate_ = nullptr; AssistantOverlayDelegate overlay_delegate_; AssistantPaymentRequestDelegate payment_request_delegate_; + AssistantFormDelegate form_delegate_; // What to do if undo is not pressed on the current snackbar. base::OnceCallback<void()> snackbar_action_; @@ -142,6 +151,7 @@ base::android::ScopedJavaLocalRef<jobject> GetDetailsModel(); base::android::ScopedJavaLocalRef<jobject> GetInfoBoxModel(); base::android::ScopedJavaLocalRef<jobject> GetPaymentRequestModel(); + base::android::ScopedJavaLocalRef<jobject> GetFormModel(); void SetOverlayState(OverlayState state); void AllowShowingSoftKeyboard(bool enabled);
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index 392abcf..522f968e 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -138,13 +138,15 @@ } void UpdateAppPermissions( - const base::flat_map<arc::mojom::AppPermission, bool>& new_permissions, + const base::flat_map<arc::mojom::AppPermission, + arc::mojom::PermissionStatePtr>& new_permissions, std::vector<apps::mojom::PermissionPtr>* permissions) { for (const auto& new_permission : new_permissions) { auto permission = apps::mojom::Permission::New(); permission->permission_id = static_cast<uint32_t>(new_permission.first); permission->value_type = apps::mojom::PermissionValueType::kBool; - permission->value = static_cast<uint32_t>(new_permission.second); + permission->value = static_cast<uint32_t>(new_permission.second->granted); + permission->is_managed = new_permission.second->managed; permissions->push_back(std::move(permission)); }
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc index 7451a66..5d0669b 100644 --- a/chrome/browser/apps/app_service/extension_apps.cc +++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -28,6 +28,7 @@ #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/services/app_service/public/mojom/types.mojom.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" #include "extensions/browser/extension_prefs.h" @@ -466,10 +467,16 @@ setting_val = apps::mojom::TriState::kAsk; } + content_settings::SettingInfo setting_info; + host_content_settings_map->GetWebsiteSetting(url, url, type, std::string(), + &setting_info); + auto permission = apps::mojom::Permission::New(); permission->permission_id = static_cast<uint32_t>(type); permission->value_type = apps::mojom::PermissionValueType::kTriState; permission->value = static_cast<uint32_t>(setting_val); + permission->is_managed = + setting_info.source == content_settings::SETTING_SOURCE_POLICY; target->push_back(std::move(permission)); }
diff --git a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc index 031870cf..9cb209d 100644 --- a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc +++ b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/extensions/application_launch.h" +#include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/common/chrome_features.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" @@ -235,10 +236,8 @@ AppsNavigationThrottle::WillStartRequest() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); starting_url_ = GetStartingGURL(navigation_handle()); - Browser* browser = - chrome::FindBrowserWithWebContents(navigation_handle()->GetWebContents()); - if (browser) - browser->window()->SetIntentPickerViewVisibility(/*visible=*/false); + IntentPickerTabHelper::SetShouldShowIcon( + navigation_handle()->GetWebContents(), false); return HandleRequest(); } @@ -360,7 +359,7 @@ switch (picker_show_state) { case PickerShowState::kOmnibox: ui_displayed_ = false; - browser->window()->SetIntentPickerViewVisibility(true); + IntentPickerTabHelper::SetShouldShowIcon(web_contents, true); break; case PickerShowState::kPopOut: ShowIntentPickerBubbleForApps(web_contents, std::move(apps),
diff --git a/chrome/browser/apps/intent_helper/intent_picker_controller.cc b/chrome/browser/apps/intent_helper/intent_picker_controller.cc deleted file mode 100644 index 97aa75b..0000000 --- a/chrome/browser/apps/intent_helper/intent_picker_controller.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/apps/intent_helper/intent_picker_controller.h" - -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" - -namespace apps { - -IntentPickerController::IntentPickerController(Browser* browser) - : browser_(browser) { - browser_->tab_strip_model()->AddObserver(this); -} - -IntentPickerController::~IntentPickerController() { - browser_->tab_strip_model()->RemoveObserver(this); -} - -void IntentPickerController::OnTabStripModelChanged( - TabStripModel* tab_strip_model, - const TabStripModelChange& change, - const TabStripSelectionChange& selection) { - if (tab_strip_model->empty()) - return; - - if (selection.selection_changed()) - ResetVisibility(); -} - -void IntentPickerController::ResetVisibility() { - browser_->window()->SetIntentPickerViewVisibility(/*visible=*/false); -} - -} // namespace apps
diff --git a/chrome/browser/apps/intent_helper/intent_picker_controller.h b/chrome/browser/apps/intent_helper/intent_picker_controller.h deleted file mode 100644 index 865ef514..0000000 --- a/chrome/browser/apps/intent_helper/intent_picker_controller.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_APPS_INTENT_HELPER_INTENT_PICKER_CONTROLLER_H_ -#define CHROME_BROWSER_APPS_INTENT_HELPER_INTENT_PICKER_CONTROLLER_H_ - -#include "base/macros.h" -#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" - -class Browser; - -namespace apps { - -// Controls the visibility of IntentPickerView by watching whenever the current -// tab is switched. An object of this class is owned by IntentPickerView. -class IntentPickerController : public TabStripModelObserver { - public: - explicit IntentPickerController(Browser* browser); - ~IntentPickerController() override; - - private: - // TabStripModelObserver: - void OnTabStripModelChanged( - TabStripModel* tab_strip_model, - const TabStripModelChange& change, - const TabStripSelectionChange& selection) override; - - void ResetVisibility(); - - Browser* const browser_; - - DISALLOW_COPY_AND_ASSIGN(IntentPickerController); -}; - -} // namespace apps - -#endif // CHROME_BROWSER_APPS_INTENT_HELPER_INTENT_PICKER_CONTROLLER_H_
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 0181308..5cf5b77 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -262,7 +262,6 @@ #include "components/signin/core/browser/account_consistency_method.h" #include "components/spellcheck/spellcheck_buildflags.h" #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" -#include "components/thread_pool_util/variations_util.h" #include "components/translate/core/common/translate_switches.h" #include "components/url_formatter/url_fixer.h" #include "components/variations/variations_associated_data.h" @@ -4643,11 +4642,6 @@ } #endif // BUILDFLAG(ENABLE_MEDIA_REMOTING) -std::unique_ptr<base::ThreadPool::InitParams> -ChromeContentBrowserClient::GetThreadPoolInitParams() { - return thread_pool_util::GetThreadPoolInitParamsForBrowser(); -} - base::FilePath ChromeContentBrowserClient::GetLoggingFileName( const base::CommandLine& command_line) { return logging::GetLogFileName(command_line);
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 31f4e73..5e41c50 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -454,8 +454,6 @@ media::mojom::RemotingSourcePtr source, media::mojom::RemoterRequest request) final; #endif // BUILDFLAG(ENABLE_MEDIA_REMOTING) - std::unique_ptr<base::ThreadPool::InitParams> GetThreadPoolInitParams() - override; base::FilePath GetLoggingFileName( const base::CommandLine& command_line) override; std::vector<std::unique_ptr<content::URLLoaderThrottle>>
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc b/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc index afa56f4b..7c13350 100644 --- a/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc +++ b/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/intent_picker_tab_helper.h" #include "components/arc/arc_service_manager.h" #include "components/arc/session/arc_bridge_service.h" #include "content/public/browser/browser_context.h" @@ -368,11 +369,8 @@ WebContents* web_contents = tab_util::GetWebContentsByID(render_process_host_id, routing_id); - Browser* browser = - web_contents ? chrome::FindBrowserWithWebContents(web_contents) : nullptr; - - if (browser) - browser->window()->SetIntentPickerViewVisibility(/*visible=*/false); + if (web_contents) + IntentPickerTabHelper::SetShouldShowIcon(web_contents, false); // If the user selected an app to continue the navigation, confirm that the // |package_name| matches a valid option and return the index. @@ -470,11 +468,11 @@ Browser* browser = web_contents ? chrome::FindBrowserWithWebContents(web_contents) : nullptr; - if (!browser) + if (!web_contents || !browser) return; - browser->window()->SetIntentPickerViewVisibility(/*visible=*/true); const bool stay_in_chrome = IsChromeAnAppCandidate(handlers); + IntentPickerTabHelper::SetShouldShowIcon(web_contents, true); browser->window()->ShowIntentPickerBubble( std::move(app_info), stay_in_chrome, /*show_remember_selection=*/true, base::BindOnce(OnIntentPickerClosed, render_process_host_id, routing_id,
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.cc b/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.cc index cf3e5954..dd9ad2e 100644 --- a/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.cc +++ b/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "components/arc/arc_service_manager.h" #include "components/arc/intent_helper/arc_intent_helper_bridge.h" @@ -311,9 +312,7 @@ if (!instance) { close_reason = apps::IntentPickerCloseReason::PICKER_ERROR; } else if (ArcIntentHelperBridge::IsIntentHelperPackage(package_name)) { - Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); - if (browser) - browser->window()->SetIntentPickerViewVisibility(/*visible=*/true); + IntentPickerTabHelper::SetShouldShowIcon(web_contents(), true); preferred_platform = apps::PreferredPlatform::NATIVE_CHROME; } else { instance->HandleUrl(url.spec(), package_name);
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc index aa789590..f9c4de5 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -588,12 +588,12 @@ weak_ptr_factory_(this) { DCHECK(!profile_->IsOffTheRecord()); GetCiceroneClient()->AddObserver(this); - GetConciergeClient()->AddObserver(this); + GetConciergeClient()->AddContainerObserver(this); } CrostiniManager::~CrostiniManager() { GetCiceroneClient()->RemoveObserver(this); - GetConciergeClient()->RemoveObserver(this); + GetConciergeClient()->RemoveContainerObserver(this); } // static
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h index ffeb8af0..18806a4 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.h +++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -207,7 +207,7 @@ // possible. The existence of Cicerone is abstracted behind this class and // only the Concierge name is exposed outside of here. class CrostiniManager : public KeyedService, - public chromeos::ConciergeClient::Observer, + public chromeos::ConciergeClient::ContainerObserver, public chromeos::CiceroneClient::Observer { public: using CrostiniResultCallback =
diff --git a/chrome/browser/chromeos/extensions/info_private_api.cc b/chrome/browser/chromeos/extensions/info_private_api.cc index 5d0c79a..b0c214f 100644 --- a/chrome/browser/chromeos/extensions/info_private_api.cc +++ b/chrome/browser/chromeos/extensions/info_private_api.cc
@@ -52,6 +52,9 @@ // Key which corresponds to the customization ID setting. const char kPropertyCustomizationID[] = "customizationId"; +// Key which corresponds to the oem_device_requisition setting. +const char kPropertyDeviceRequisition[] = "deviceRequisition"; + // Key which corresponds to the home provider property. const char kPropertyHomeProvider[] = "homeProvider"; @@ -294,6 +297,15 @@ return std::make_unique<base::Value>(customization_id); } + if (property_name == kPropertyDeviceRequisition) { + std::string device_requisition; + chromeos::system::StatisticsProvider* provider = + chromeos::system::StatisticsProvider::GetInstance(); + provider->GetMachineStatistic(chromeos::system::kOemDeviceRequisitionKey, + &device_requisition); + return std::make_unique<base::Value>(device_requisition); + } + if (property_name == kPropertyHomeProvider) { const chromeos::DeviceState* cellular_device = NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType(
diff --git a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc index 089bc80..dec97be 100644 --- a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc +++ b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
@@ -19,11 +19,8 @@ #include "chrome/browser/chromeos/login/screens/recommend_apps/scoped_test_recommend_apps_fetcher_factory.h" #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h" #include "chrome/browser/chromeos/login/screens/update_screen.h" -#include "chrome/browser/chromeos/login/test/device_state_mixin.h" -#include "chrome/browser/chromeos/login/test/embedded_test_server_mixin.h" #include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h" #include "chrome/browser/chromeos/login/test/js_checker.h" -#include "chrome/browser/chromeos/login/test/login_manager_mixin.h" #include "chrome/browser/chromeos/login/test/oobe_base_test.h" #include "chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" @@ -41,7 +38,6 @@ #include "chrome/browser/ui/webui/chromeos/login/network_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" -#include "chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/update_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h" #include "chromeos/constants/chromeos_switches.h" @@ -121,7 +117,12 @@ ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver); }; -class OobeEndToEndTestSetupMixin : public InProcessBrowserTestMixin { +} // namespace + +class OobeInteractiveUITest + : public OobeBaseTest, + public extensions::QuickUnlockPrivateGetAuthTokenFunction::TestObserver, + public ::testing::WithParamInterface<std::tuple<bool, bool, ArcState>> { public: struct Parameters { bool is_tablet; @@ -136,30 +137,33 @@ } }; - explicit OobeEndToEndTestSetupMixin( - InProcessBrowserTestMixinHost* mixin_host, - net::EmbeddedTestServer* arc_tos_server, - const std::tuple<bool, bool, ArcState>& parameters) - : InProcessBrowserTestMixin(mixin_host), arc_tos_server_(arc_tos_server) { - std::tie(params_.is_tablet, params_.is_quick_unlock_enabled, - params_.arc_state) = parameters; - } - ~OobeEndToEndTestSetupMixin() override = default; + OobeInteractiveUITest() = default; + ~OobeInteractiveUITest() override = default; - // InProcessBrowserTestMixin: void SetUp() override { - LOG(INFO) << "OOBE end-to-end test started with params " - << params_.ToString(); - - if (params_.arc_state != ArcState::kNotAvailable) + params_ = Parameters(); + std::tie(params_->is_tablet, params_->is_quick_unlock_enabled, + params_->arc_state) = GetParam(); + LOG(INFO) << "OobeInteractiveUITest() started with params " + << params_->ToString(); + if (params_->arc_state != ArcState::kNotAvailable) feature_list_.InitAndEnableFeature(switches::kAssistantFeature); + OobeBaseTest::SetUp(); + } + + void TearDown() override { + quick_unlock::EnabledForTesting(false); + OobeBaseTest::TearDown(); + params_.reset(); } void SetUpCommandLine(base::CommandLine* command_line) override { - if (params_.is_tablet) + OobeBaseTest::SetUpCommandLine(command_line); + + if (params_->is_tablet) command_line->AppendSwitch(ash::switches::kAshEnableTabletMode); - if (params_.arc_state != ArcState::kNotAvailable) { + if (params_->arc_state != ArcState::kNotAvailable) { arc::SetArcAvailableCommandLineForTesting(command_line); // Prevent encryption migration screen from showing up after user login // with ARC available. @@ -168,44 +172,54 @@ } void SetUpInProcessBrowserTestFixture() override { - if (params_.is_quick_unlock_enabled) + OobeBaseTest::SetUpInProcessBrowserTestFixture(); + + if (params_->is_quick_unlock_enabled) quick_unlock::EnabledForTesting(true); - if (params_.arc_state != ArcState::kNotAvailable) { + if (params_->arc_state != ArcState::kNotAvailable) { recommend_apps_fetcher_factory_ = std::make_unique<ScopedTestRecommendAppsFetcherFactory>( base::BindRepeating(&CreateRecommendAppsFetcher)); - if (arc_tos_server_) { - arc_tos_server_->RegisterRequestHandler( - base::BindRepeating(&OobeEndToEndTestSetupMixin::HandleRequest, - base::Unretained(this))); - } + arc_tos_server_.RegisterRequestHandler(base::BindRepeating( + &OobeInteractiveUITest::HandleRequest, base::Unretained(this))); } } void SetUpOnMainThread() override { - if (params_.is_tablet) + OobeBaseTest::SetUpOnMainThread(); + + if (params_->is_tablet) TabletModeClient::Get()->OnTabletModeToggled(true); - if (params_.arc_state != ArcState::kNotAvailable) { + if (params_->arc_state != ArcState::kNotAvailable) { // Init ArcSessionManager for testing. arc::ArcServiceLauncher::Get()->ResetForTesting(); arc::ArcSessionManager::Get()->SetArcSessionRunnerForTesting( std::make_unique<arc::ArcSessionRunner>( base::BindRepeating(arc::FakeArcSession::Create))); - if (arc_tos_server_) { - test::OobeJS().Evaluate(base::StringPrintf( - "login.ArcTermsOfServiceScreen.setTosHostNameForTesting('%s');", - arc_tos_server_->GetURL("/arc-tos").spec().c_str())); - } + test::OobeJS().Evaluate(base::StringPrintf( + "login.ArcTermsOfServiceScreen.setTosHostNameForTesting('%s');", + arc_tos_server_.GetURL("/arc-tos").spec().c_str())); } } - void TearDownInProcessBrowserTestFixture() override { - recommend_apps_fetcher_factory_.reset(); + + void TearDownOnMainThread() override { + // If the login display is still showing, exit gracefully. + if (LoginDisplayHost::default_host()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&chrome::AttemptExit)); + RunUntilBrowserProcessQuits(); + } + + OobeBaseTest::TearDownOnMainThread(); } - void TearDown() override { quick_unlock::EnabledForTesting(false); } + void TearDownInProcessBrowserTestFixture() override { + recommend_apps_fetcher_factory_.reset(); + OobeBaseTest::TearDownInProcessBrowserTestFixture(); + } std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { auto response = std::make_unique<BasicHttpResponse>(); @@ -219,46 +233,6 @@ return response; } - bool is_tablet() const { return params_.is_tablet; } - - bool is_quick_unlock_enabled() const { - return params_.is_quick_unlock_enabled; - } - - ArcState arc_state() const { return params_.arc_state; } - - private: - Parameters params_; - - base::test::ScopedFeatureList feature_list_; - std::unique_ptr<ScopedTestRecommendAppsFetcherFactory> - recommend_apps_fetcher_factory_; - net::EmbeddedTestServer* arc_tos_server_; - - DISALLOW_COPY_AND_ASSIGN(OobeEndToEndTestSetupMixin); -}; - -} // namespace - -class OobeInteractiveUITest - : public OobeBaseTest, - public extensions::QuickUnlockPrivateGetAuthTokenFunction::TestObserver, - public ::testing::WithParamInterface<std::tuple<bool, bool, ArcState>> { - public: - OobeInteractiveUITest() = default; - ~OobeInteractiveUITest() override = default; - - // OobeInteractiveUITest: - void TearDownOnMainThread() override { - // If the login display is still showing, exit gracefully. - if (LoginDisplayHost::default_host()) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&chrome::AttemptExit)); - RunUntilBrowserProcessQuits(); - } - OobeBaseTest::TearDownOnMainThread(); - } - // QuickUnlockPrivateGetAuthTokenFunction::TestObserver: void OnGetAuthTokenCalled(const std::string& password) override { quick_unlock_private_get_auth_token_password_ = password; @@ -600,9 +574,9 @@ void SimpleEndToEnd(); - const OobeEndToEndTestSetupMixin* test_setup() const { return &setup_; } - base::Optional<std::string> quick_unlock_private_get_auth_token_password_; + base::Optional<Parameters> params_; + base::test::ScopedFeatureList feature_list_; private: FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()}; @@ -610,12 +584,15 @@ net::EmbeddedTestServer arc_tos_server_{net::EmbeddedTestServer::TYPE_HTTPS}; EmbeddedTestServerSetupMixin arc_tos_server_setup_{&mixin_host_, &arc_tos_server_}; - OobeEndToEndTestSetupMixin setup_{&mixin_host_, &arc_tos_server_, GetParam()}; + + std::unique_ptr<ScopedTestRecommendAppsFetcherFactory> + recommend_apps_fetcher_factory_; DISALLOW_COPY_AND_ASSIGN(OobeInteractiveUITest); }; void OobeInteractiveUITest::SimpleEndToEnd() { + ASSERT_TRUE(params_.has_value()); ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver scoped_observer(this); WaitForOobeWelcomeScreen(); @@ -642,7 +619,7 @@ // may cause flaky load failures. // TODO(https://crbug/com/959902): Fix ARC terms of service screen to better // handle this case. - if (test_setup()->arc_state() != ArcState::kNotAvailable) { + if (params_->arc_state != ArcState::kNotAvailable) { test::OobeJS() .CreateHasClassWaiter(true, "arc-tos-loaded", {"arc-tos-root", "arc-tos-dialog"}) @@ -656,29 +633,28 @@ ExitScreenSyncConsent(); #endif - if (test_setup()->is_quick_unlock_enabled()) { + if (quick_unlock::IsEnabledForTesting()) { WaitForFingerprintScreen(); RunFingerprintScreenChecks(); ExitFingerprintPinSetupScreen(); } - if (test_setup()->is_tablet()) { + if (params_->is_tablet) { WaitForDiscoverScreen(); RunDiscoverScreenChecks(); ExitDiscoverPinSetupScreen(); } - if (test_setup()->arc_state() != ArcState::kNotAvailable) { - HandleArcTermsOfServiceScreen(test_setup()->arc_state() == - ArcState::kAcceptTerms); + if (params_->arc_state != ArcState::kNotAvailable) { + HandleArcTermsOfServiceScreen(params_->arc_state == ArcState::kAcceptTerms); } - if (test_setup()->arc_state() == ArcState::kAcceptTerms) { + if (params_->arc_state == ArcState::kAcceptTerms) { HandleRecommendAppsScreen(); HandleAppDownloadingScreen(); } - if (test_setup()->arc_state() != ArcState::kNotAvailable) { + if (params_->arc_state != ArcState::kNotAvailable) { HandleAssistantOptInScreen(); } @@ -698,102 +674,4 @@ ArcState::kAcceptTerms, ArcState::kDeclineTerms))); -class PublicSessionOobeTest - : public MixinBasedInProcessBrowserTest, - public ::testing::WithParamInterface<std::tuple<bool, bool, ArcState>> { - public: - PublicSessionOobeTest() - : PublicSessionOobeTest(false /*requires_terms_of_service*/) {} - - explicit PublicSessionOobeTest(bool requires_terms_of_service) - : requires_terms_of_service_(requires_terms_of_service) {} - - ~PublicSessionOobeTest() override = default; - - void SetUpInProcessBrowserTestFixture() override { - std::unique_ptr<ScopedDevicePolicyUpdate> device_policy_update = - device_state_.RequestDevicePolicyUpdate(); - - const std::string kAccountId = "public-session@test"; - - enterprise_management::DeviceLocalAccountsProto* const - device_local_accounts = device_policy_update->policy_payload() - ->mutable_device_local_accounts(); - - // Add public session account. - enterprise_management::DeviceLocalAccountInfoProto* const account = - device_local_accounts->add_account(); - account->set_account_id(kAccountId); - account->set_type(enterprise_management::DeviceLocalAccountInfoProto:: - ACCOUNT_TYPE_PUBLIC_SESSION); - - // Set the public session to auto-launch. - device_local_accounts->set_auto_login_id(kAccountId); - device_policy_update.reset(); - - std::unique_ptr<ScopedUserPolicyUpdate> device_local_account_policy_update = - device_state_.RequestDeviceLocalAccountPolicyUpdate(kAccountId); - // Specify terms of service if needed. - if (requires_terms_of_service_) { - device_local_account_policy_update->policy_payload() - ->mutable_termsofserviceurl() - ->set_value(embedded_test_server() - ->GetURL("/chromeos/enterprise/tos.txt") - .spec()); - } - device_local_account_policy_update.reset(); - - MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture(); - } - - LoginManagerMixin login_manager_{&mixin_host_, {}}; - - private: - const bool requires_terms_of_service_; - - OobeEndToEndTestSetupMixin setup_{&mixin_host_, nullptr, GetParam()}; - DeviceStateMixin device_state_{ - &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED}; -}; - -IN_PROC_BROWSER_TEST_P(PublicSessionOobeTest, NoTermsOfService) { - login_manager_.WaitForActiveSession(); -} - -INSTANTIATE_TEST_SUITE_P( - PublicSessionOobeTestImpl, - PublicSessionOobeTest, - testing::Combine(testing::Bool(), - testing::Bool(), - testing::Values(ArcState::kNotAvailable, - ArcState::kDeclineTerms))); - -class PublicSessionWithTermsOfServiceOobeTest : public PublicSessionOobeTest { - public: - PublicSessionWithTermsOfServiceOobeTest() - : PublicSessionOobeTest(true /*requires_terms_od_service*/) {} - ~PublicSessionWithTermsOfServiceOobeTest() override = default; - - // Use embedded test server to serve Public session Terms of Service. - EmbeddedTestServerSetupMixin embedded_test_server_setup_{ - &mixin_host_, embedded_test_server()}; -}; - -IN_PROC_BROWSER_TEST_P(PublicSessionWithTermsOfServiceOobeTest, - AcceptTermsOfService) { - OobeScreenWaiter(TermsOfServiceScreenView::kScreenId).Wait(); - test::OobeJS().ClickOnPath({"tos-accept-button"}); - OobeScreenExitWaiter(TermsOfServiceScreenView::kScreenId).Wait(); - - login_manager_.WaitForActiveSession(); -} - -INSTANTIATE_TEST_SUITE_P( - PublicSessionWithTermsOfServiceOobeTestImpl, - PublicSessionWithTermsOfServiceOobeTest, - testing::Combine(testing::Bool(), - testing::Bool(), - testing::Values(ArcState::kNotAvailable, - ArcState::kDeclineTerms))); - } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.cc b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.cc index 49456b1..b54f02c 100644 --- a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.cc +++ b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.cc
@@ -8,14 +8,23 @@ #include "base/bind.h" #include "base/strings/string16.h" #include "base/strings/string_util.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/notifications/notification_common.h" #include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/chrome_new_window_client.h" +#include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" +#include "chromeos/login/auth/saml_password_attributes.h" #include "chromeos/strings/grit/chromeos_strings.h" +#include "components/prefs/pref_service.h" #include "components/vector_icons/vector_icons.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "ui/base/l10n/l10n_util.h" #include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/public/cpp/notification_delegate.h" @@ -95,9 +104,108 @@ return base::JoinString(body_lines, *kLineSeparator); } +// A time delta of length zero. +const base::TimeDelta kZeroTimeDelta = base::TimeDelta(); +// A time delta of length one hour. +const base::TimeDelta kOneHour = base::TimeDelta::FromHours(1); + +// Traits for running RecheckTask. Runs from the UI thread to show notification. +const base::TaskTraits kRecheckTaskTraits = { + content::BrowserThread::UI, base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}; + +// A task to check again if the notification should be shown at a later time. +// This has weak pointers so that it pending tasks can be canceled. +class RecheckTask { + public: + void Run(Profile* profile) { + MaybeShowSamlPasswordExpiryNotification(profile); + } + + // Check again whether to show notification for |profile| after |delay|. + void PostDelayed(Profile* profile, base::TimeDelta delay) { + base::PostDelayedTaskWithTraits( + FROM_HERE, kRecheckTaskTraits, + base::BindOnce(&RecheckTask::Run, weak_ptr_factory.GetWeakPtr(), + profile), + delay); + } + + // Cancel any scheduled tasks to check again. + void CancelIfPending() { weak_ptr_factory.InvalidateWeakPtrs(); } + + private: + base::WeakPtrFactory<RecheckTask> weak_ptr_factory{this}; +}; + +// Keep only a single instance of the RecheckTask, so that we can easily cancel +// all pending tasks just by invalidating weak pointers to this one task. +base::NoDestructor<RecheckTask> recheck_task_instance; + } // namespace +void MaybeShowSamlPasswordExpiryNotification(Profile* profile) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // This cancels any pending RecheckTask - we don't want a situation where + // accidentally this function more than once means lots of identical + // RecheckTasks are added to the work queue. + recheck_task_instance->CancelIfPending(); + + // This could be run after a long delay. Check it still makes sense to run. + ProfileManager* profile_manager = g_browser_process->profile_manager(); + if (!profile_manager || !profile_manager->IsValidProfile(profile)) { + return; + } + + SamlPasswordAttributes attrs = + SamlPasswordAttributes::LoadFromPrefs(profile->GetPrefs()); + if (!attrs.has_expiration_time()) { + // No reason to believe the password will ever expire. + // Hide the notification (just in case it is shown) and return. + DismissSamlPasswordExpiryNotification(profile); + return; + } + + const base::TimeDelta time_until_expiry = + attrs.expiration_time() - base::Time::Now(); + if (time_until_expiry <= kZeroTimeDelta) { + // The password has expired, so we show the notification now. + ShowSamlPasswordExpiryNotification(profile, /*less_than_n_days=*/0); + return; + } + + // The password has not expired, but it will in the future. + const int less_than_n_days = time_until_expiry.InDaysFloored() + 1; + int advance_warning_days = profile->GetPrefs()->GetInteger( + prefs::kSamlPasswordExpirationAdvanceWarningDays); + advance_warning_days = std::max(advance_warning_days, 0); + + if (less_than_n_days <= advance_warning_days) { + // The password will expire in less than |advance_warning_days|, so we show + // a notification now explaining the password will expire soon. + ShowSamlPasswordExpiryNotification(profile, less_than_n_days); + return; + } + + // We have not even reached the advance warning threshold. Run this code again + // once we have arrived at expiry_time minus advance_warning_days... + base::TimeDelta recheck_delay = + time_until_expiry - base::TimeDelta::FromDays(advance_warning_days); + // But, wait an extra hour so that when this code is next run, it is clear we + // are now inside advance_warning_days (and not right on the boundary). + recheck_delay += kOneHour; + // And never wait less than an hour before running again - we don't want some + // bug causing this code to run every millisecond... + recheck_delay = std::max(recheck_delay, kOneHour); + + // Check again whether to show notification after recheck_delay. + recheck_task_instance->PostDelayed(profile, recheck_delay); +} + void ShowSamlPasswordExpiryNotification(Profile* profile, int lessThanNDays) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + const base::string16 title = GetTitleText(lessThanNDays); const base::string16 body = GetBodyText(lessThanNDays); @@ -111,6 +219,7 @@ } void DismissSamlPasswordExpiryNotification(Profile* profile) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); NotificationDisplayServiceFactory::GetForProfile(profile)->Close( kNotificationHandlerType, kNotificationId); }
diff --git a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.h b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.h index eeb13c6..0fe152a 100644 --- a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.h +++ b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification.h
@@ -11,6 +11,13 @@ // Utility functions to show or hide a password expiry notification. +// Show a password expiry notification if the user's password has expired or +// soon expires (that is, within pref kSamlPasswordExpirationAdvanceWarningDays +// time). Otherwise, if the user's password will expire in the more distant +// future, in that case a notification will be shown in the future. Nothing is +// shown if the password is not expected to expire. +void MaybeShowSamlPasswordExpiryNotification(Profile* profile); + // Shows a password expiry notification. |lessThanNDays| should be 1 if the // password expires in less than 1 day, 0 if it has already expired, etc. // Negative numbers are treated the same as zero.
diff --git a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification_unittest.cc b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification_unittest.cc index f293fbe..f766c48 100644 --- a/chrome/browser/chromeos/login/saml/saml_password_expiry_notification_unittest.cc +++ b/chrome/browser/chromeos/login/saml/saml_password_expiry_notification_unittest.cc
@@ -5,9 +5,15 @@ #include "chrome/browser/chromeos/login/saml/saml_password_expiry_notification.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/notifications/notification_display_service_impl.h" #include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/login/auth/saml_password_attributes.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -16,11 +22,19 @@ namespace chromeos { +constexpr base::TimeDelta kTimeAdvance = base::TimeDelta::FromMilliseconds(1); + class SamlPasswordExpiryNotificationTest : public testing::Test { public: void SetUp() override { + // Advance time a little bit so that Time::Now().is_null() becomes false. + test_environment_.FastForwardBy(kTimeAdvance); + + ASSERT_TRUE(profile_manager_.SetUp()); + profile_ = profile_manager_.CreateTestingProfile("test"); + display_service_tester_ = - std::make_unique<NotificationDisplayServiceTester>(&profile_); + std::make_unique<NotificationDisplayServiceTester>(profile_); } void TearDown() override { display_service_tester_.reset(); } @@ -31,14 +45,21 @@ "saml.password-expiry-notification"); } - content::TestBrowserThreadBundle thread_bundle_; - TestingProfile profile_; + void SetExpirationTime(base::Time expiration_time) { + SamlPasswordAttributes attrs(base::Time(), expiration_time, ""); + attrs.SaveToPrefs(profile_->GetPrefs()); + } + content::TestBrowserThreadBundle test_environment_{ + base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME, + base::test::ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME}; + TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()}; + TestingProfile* profile_; std::unique_ptr<NotificationDisplayServiceTester> display_service_tester_; }; TEST_F(SamlPasswordExpiryNotificationTest, ShowAlreadyExpired) { - ShowSamlPasswordExpiryNotification(&profile_, 0); + ShowSamlPasswordExpiryNotification(profile_, 0); ASSERT_TRUE(Notification().has_value()); EXPECT_EQ(base::ASCIIToUTF16("Password has expired"), @@ -47,12 +68,12 @@ "Click here to choose a new password"), Notification()->message()); - DismissSamlPasswordExpiryNotification(&profile_); + DismissSamlPasswordExpiryNotification(profile_); EXPECT_FALSE(Notification().has_value()); } TEST_F(SamlPasswordExpiryNotificationTest, ShowWillSoonExpire) { - ShowSamlPasswordExpiryNotification(&profile_, 14); + ShowSamlPasswordExpiryNotification(profile_, 14); ASSERT_TRUE(Notification().has_value()); EXPECT_EQ(base::ASCIIToUTF16("Password will soon expire"), @@ -62,8 +83,84 @@ "Click here to choose a new password"), Notification()->message()); - DismissSamlPasswordExpiryNotification(&profile_); + DismissSamlPasswordExpiryNotification(profile_); EXPECT_FALSE(Notification().has_value()); } +TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_WillNotExpire) { + SamlPasswordAttributes::DeleteFromPrefs(profile_->GetPrefs()); + MaybeShowSamlPasswordExpiryNotification(profile_); + + EXPECT_FALSE(Notification().has_value()); + // No notification shown now and nothing shown in the next 10,000 days. + test_environment_.FastForwardBy(base::TimeDelta::FromDays(10000)); + EXPECT_FALSE(Notification().has_value()); +} + +TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_AlreadyExpired) { + SetExpirationTime(base::Time::Now() - base::TimeDelta::FromDays(30)); + MaybeShowSamlPasswordExpiryNotification(profile_); + + // Notification is shown immediately since password has expired. + EXPECT_TRUE(Notification().has_value()); + EXPECT_EQ(base::ASCIIToUTF16("Password has expired"), + Notification()->title()); +} + +TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_WillSoonExpire) { + SetExpirationTime(base::Time::Now() + base::TimeDelta::FromDays(5)); + MaybeShowSamlPasswordExpiryNotification(profile_); + + // Notification is shown immediately since password will soon expire. + EXPECT_TRUE(Notification().has_value()); + EXPECT_EQ(base::ASCIIToUTF16("Password will soon expire"), + Notification()->title()); +} + +TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_WillEventuallyExpire) { + SetExpirationTime(base::Time::Now() + base::TimeDelta::FromDays(95)); + MaybeShowSamlPasswordExpiryNotification(profile_); + + // Notification is not shown immediately. + EXPECT_FALSE(Notification().has_value()); + + // But, it will be shown eventually. + test_environment_.FastForwardBy(base::TimeDelta::FromDays(90)); + EXPECT_TRUE(Notification().has_value()); + EXPECT_EQ(base::ASCIIToUTF16("Password will soon expire"), + Notification()->title()); +} + +TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_DeleteExpirationTime) { + SetExpirationTime(base::Time::Now() + base::TimeDelta::FromDays(95)); + MaybeShowSamlPasswordExpiryNotification(profile_); + + // Notification is not shown immediately. + EXPECT_FALSE(Notification().has_value()); + + // Since expiration time is now removed, it is not shown later either. + SamlPasswordAttributes::DeleteFromPrefs(profile_->GetPrefs()); + test_environment_.FastForwardBy(base::TimeDelta::FromDays(90)); + EXPECT_FALSE(Notification().has_value()); +} + +TEST_F(SamlPasswordExpiryNotificationTest, MaybeShow_Idempotent) { + SetExpirationTime(base::Time::Now() + base::TimeDelta::FromDays(95)); + + // Calling MaybeShowSamlPasswordExpiryNotification should only add one task - + // to maybe show the notification in about 90 days. + int baseline_task_count = test_environment_.GetPendingMainThreadTaskCount(); + MaybeShowSamlPasswordExpiryNotification(profile_); + int new_task_count = test_environment_.GetPendingMainThreadTaskCount(); + EXPECT_EQ(1, new_task_count - baseline_task_count); + + // Calling it many times shouldn't create more tasks - we only need one task + // to show the notification in about 90 days. + for (int i = 0; i < 10; i++) { + MaybeShowSamlPasswordExpiryNotification(profile_); + } + new_task_count = test_environment_.GetPendingMainThreadTaskCount(); + EXPECT_EQ(1, new_task_count - baseline_task_count); +} + } // namespace chromeos
diff --git a/chrome/browser/drive/drive_notification_manager_factory.cc b/chrome/browser/drive/drive_notification_manager_factory.cc index ce59af4..cc47df75 100644 --- a/chrome/browser/drive/drive_notification_manager_factory.cc +++ b/chrome/browser/drive/drive_notification_manager_factory.cc
@@ -6,14 +6,40 @@ #include "base/logging.h" #include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h" +#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/common/chrome_features.h" #include "components/drive/drive_notification_manager.h" #include "components/invalidation/impl/profile_invalidation_provider.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/sync/driver/sync_driver_switches.h" namespace drive { +namespace { + +constexpr char kDriveFcmSenderId[] = "947318989803"; + +invalidation::InvalidationService* GetInvalidationService(Profile* profile) { + if (base::FeatureList::IsEnabled(features::kDriveFcmInvalidations)) { + if (!invalidation::ProfileInvalidationProviderFactory::GetForProfile( + profile)) { + return nullptr; + } + return invalidation::ProfileInvalidationProviderFactory::GetForProfile( + profile) + ->GetInvalidationServiceForCustomSender(kDriveFcmSenderId); + } + if (!invalidation::DeprecatedProfileInvalidationProviderFactory:: + GetForProfile(profile)) { + return nullptr; + } + return invalidation::DeprecatedProfileInvalidationProviderFactory:: + GetForProfile(profile) + ->GetInvalidationService(); +} + +} // namespace // static DriveNotificationManager* @@ -29,8 +55,7 @@ content::BrowserContext* context) { if (!switches::IsSyncAllowedByFlag()) return NULL; - if (!invalidation::DeprecatedProfileInvalidationProviderFactory:: - GetForProfile(Profile::FromBrowserContext(context))) { + if (!GetInvalidationService(Profile::FromBrowserContext(context))) { // Do not create a DriveNotificationManager for |context|s that do not // support invalidation. return NULL; @@ -53,19 +78,16 @@ DependsOn(ProfileSyncServiceFactory::GetInstance()); DependsOn(invalidation::DeprecatedProfileInvalidationProviderFactory:: GetInstance()); + DependsOn(invalidation::ProfileInvalidationProviderFactory::GetInstance()); } DriveNotificationManagerFactory::~DriveNotificationManagerFactory() {} KeyedService* DriveNotificationManagerFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - invalidation::ProfileInvalidationProvider* invalidation_provider = - invalidation::DeprecatedProfileInvalidationProviderFactory::GetForProfile( - Profile::FromBrowserContext(context)); - DCHECK(invalidation_provider); - DCHECK(invalidation_provider->GetInvalidationService()); return new DriveNotificationManager( - invalidation_provider->GetInvalidationService()); + GetInvalidationService(Profile::FromBrowserContext(context)), + base::FeatureList::IsEnabled(features::kDriveFcmInvalidations)); } } // namespace drive
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 1ea3de2..db74e228 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2026,15 +2026,18 @@ }, { "name": "force-text-direction", - "owners": [ "pbos", "ellyjones" ], + "owners": [ "krb", "pbos", "ellyjones" ], // This flag is used for developers who don't speak an RTL language to QA - // RTL UI layout. + // RTL text regardless of UI layout direction. This for instance impacts the + // Omnibox where arbitrary text directions may be entered. "expiry_milestone": -1 }, { "name": "force-ui-direction", - // "owners": [ "your-team" ], - "expiry_milestone": 76 + "owners": [ "pbos", "ellyjones" ], + // This flag is used for developers who don't speak an RTL language to QA + // RTL UI layout. + "expiry_milestone": -1 }, { "name": "force-update-menu-type",
diff --git a/chrome/browser/flag-never-expire-list.json b/chrome/browser/flag-never-expire-list.json index d727742f..f7310f8 100644 --- a/chrome/browser/flag-never-expire-list.json +++ b/chrome/browser/flag-never-expire-list.json
@@ -57,6 +57,7 @@ "force-effective-connection-type", "force-show-update-menu-badge", "force-text-direction", + "force-ui-direction", "force-update-menu-type", "ignore-gpu-blacklist", "ignore-previews-blocklist",
diff --git a/chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.cc b/chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.cc index 1812382..172052d 100644 --- a/chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.cc +++ b/chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.cc
@@ -174,7 +174,7 @@ new InvalidatorStorage(profile->GetPrefs()))); return new ProfileInvalidationProvider(std::move(service), - std::move(identity_provider)); + std::move(identity_provider), {}); #endif }
diff --git a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc index 4c30e390..3052b9b 100644 --- a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc +++ b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc
@@ -43,6 +43,30 @@ #endif namespace invalidation { +namespace { + +std::unique_ptr<InvalidationService> CreateInvalidationServiceForSenderId( + Profile* profile, + IdentityProvider* identity_provider, + const std::string& sender_id) { + auto service = std::make_unique<FCMInvalidationService>( + identity_provider, + gcm::GCMProfileServiceFactory::GetForProfile(profile)->driver(), + instance_id::InstanceIDProfileServiceFactory::GetForProfile(profile) + ->driver(), + profile->GetPrefs(), + base::BindRepeating( + data_decoder::SafeJsonParser::Parse, + content::ServiceManagerConnection::GetForProcess()->GetConnector()), + content::BrowserContext::GetDefaultStoragePartition(profile) + ->GetURLLoaderFactoryForBrowserProcess() + .get(), + sender_id); + service->Init(); + return service; +} + +} // namespace // static ProfileInvalidationProvider* ProfileInvalidationProviderFactory::GetForProfile( @@ -110,22 +134,14 @@ identity_provider.reset(new ProfileIdentityProvider( IdentityManagerFactory::GetForProfile(profile))); } - std::unique_ptr<FCMInvalidationService> service = - std::make_unique<FCMInvalidationService>( - identity_provider.get(), - gcm::GCMProfileServiceFactory::GetForProfile(profile)->driver(), - instance_id::InstanceIDProfileServiceFactory::GetForProfile(profile) - ->driver(), - profile->GetPrefs(), - base::BindRepeating(data_decoder::SafeJsonParser::Parse, - content::ServiceManagerConnection::GetForProcess() - ->GetConnector()), - content::BrowserContext::GetDefaultStoragePartition(profile) - ->GetURLLoaderFactoryForBrowserProcess() - .get()); - service->Init(); + auto service = + CreateInvalidationServiceForSenderId(profile, identity_provider.get(), + /* sender_id = */ ""); + auto custom_sender_id_factory = base::BindRepeating( + &CreateInvalidationServiceForSenderId, profile, identity_provider.get()); return new ProfileInvalidationProvider(std::move(service), - std::move(identity_provider)); + std::move(identity_provider), + std::move(custom_sender_id_factory)); } } // namespace invalidation
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc index a79607c..64e4a85 100644 --- a/chrome/browser/profiles/profile_downloader.cc +++ b/chrome/browser/profiles/profile_downloader.cc
@@ -71,7 +71,9 @@ return; } - account_id_ = account_id.empty() ? identity_manager_->GetPrimaryAccountId() + // TODO(triploblastic@): Remove explicit conversion once ProfileDownloader + // has been fixed to use CoreAccountId. + account_id_ = account_id.empty() ? identity_manager_->GetPrimaryAccountId().id : account_id; StartFetchingOAuth2AccessToken(); }
diff --git a/chrome/browser/resources/app_management/browser_proxy.js b/chrome/browser/resources/app_management/browser_proxy.js index 84c80eda..cb6dc812 100644 --- a/chrome/browser/resources/app_management/browser_proxy.js +++ b/chrome/browser/resources/app_management/browser_proxy.js
@@ -18,6 +18,18 @@ this.handler = new app_management.FakePageHandler( this.callbackRouter.createProxy()); + const permissionOptions = {}; + permissionOptions[PwaPermissionType.CONTENT_SETTINGS_TYPE_GEOLOCATION] = + { + permissionValue: TriState.kAllow, + isManaged: true, + }; + permissionOptions[PwaPermissionType + .CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA] = { + permissionValue: TriState.kBlock, + isManaged: true + }; + const /** @type {!Array<App>}*/ appList = [ app_management.FakePageHandler.createApp( 'blpcfgokakmgnkcojhhkbfblekacnbeo', @@ -68,9 +80,14 @@ app_management.FakePageHandler.createApp( 'aapocclcgogkmnckokdopfmhonfmgok', { - title: 'Web App, policy installed', + title: 'Web App, policy applied', type: AppType.kWeb, - installSource: InstallSource.kPolicy, + isPinned: apps.mojom.OptionalBool.kTrue, + isPolicyPinned: apps.mojom.OptionalBool.kTrue, + installSource: apps.mojom.InstallSource.kPolicy, + permissions: + app_management.FakePageHandler.createWebPermissions( + permissionOptions), }, ), ];
diff --git a/chrome/browser/resources/app_management/fake_page_handler.js b/chrome/browser/resources/app_management/fake_page_handler.js index 9a06d5f..db437db1 100644 --- a/chrome/browser/resources/app_management/fake_page_handler.js +++ b/chrome/browser/resources/app_management/fake_page_handler.js
@@ -8,9 +8,10 @@ */ class FakePageHandler { /** + * @param {Object=} options * @return {!Object<number, Permission>} */ - static createWebPermissions() { + static createWebPermissions(options) { const permissionIds = [ PwaPermissionType.CONTENT_SETTINGS_TYPE_GEOLOCATION, PwaPermissionType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS, @@ -21,8 +22,17 @@ const permissions = {}; for (const permissionId of permissionIds) { + let permissionValue = TriState.kAllow; + let isManaged = false; + + if (options && options[permissionId]) { + const opts = options[permissionId]; + permissionValue = opts.permissionValue || permissionValue; + isManaged = opts.isManaged || isManaged; + } permissions[permissionId] = app_management.util.createPermission( - permissionId, PermissionValueType.kTriState, TriState.kAllow); + permissionId, PermissionValueType.kTriState, permissionValue, + isManaged); } return permissions; @@ -44,7 +54,8 @@ for (const permissionId of permissionIds) { permissions[permissionId] = app_management.util.createPermission( - permissionId, PermissionValueType.kBool, Bool.kTrue); + permissionId, PermissionValueType.kBool, Bool.kTrue, + false /*is_managed*/); } return permissions; @@ -79,6 +90,7 @@ version: '5.1', size: '9.0MB', isPinned: apps.mojom.OptionalBool.kFalse, + isPolicyPinned: apps.mojom.OptionalBool.kFalse, installSource: apps.mojom.InstallSource.kUser, permissions: {}, };
diff --git a/chrome/browser/resources/app_management/metadata_view.html b/chrome/browser/resources/app_management/metadata_view.html index aad0dd4f..43948ae 100644 --- a/chrome/browser/resources/app_management/metadata_view.html +++ b/chrome/browser/resources/app_management/metadata_view.html
@@ -15,6 +15,7 @@ } #shelf-switch { + align-items: center; display: flex; justify-content: space-between; } @@ -36,13 +37,27 @@ display: flex; justify-content: space-around; } + + #policy-indicator { + fill: var(--google-grey-refresh-700); + margin-inline-end: 12px; + } </style> <template is="dom-if" if="[[pinToShelfToggleVisible_(app_)]]"> <div id="shelf-switch-row"> <span id="shelf-switch" class="header-text"> + <template is="dom-if" if="[[isPolicyPinned_(app_)]]"> + <iron-icon id="policy-indicator" icon="cr:domain" tabindex="0" + aria-describedby="tooltip"> + </iron-icon> + <paper-tooltip id="tooltip" for="policy-indicator" + position="top" fit-to-visible-bounds> + $i18n{pinControlledByPolicy} + </paper-tooltip> + </template> $i18n{pinToShelf} <cr-toggle id="pin-to-shelf-toggle" checked="[[isPinned_(app_)]]" - on-change="togglePinned_"> + on-change="togglePinned_" disabled$="[[isPolicyPinned_(app_)]]"> </cr-toggle> </span> </div> @@ -51,7 +66,6 @@ <div id="metadata-overview" class="secondary-text"> <span>[[versionString_(app_)]]</span> <span>[[sizeString_(app_)]]</span> - <!--TODO(ceciliani): Placeholder for legal declaration--> </div> </template> <script src="metadata_view.js"></script>
diff --git a/chrome/browser/resources/app_management/metadata_view.js b/chrome/browser/resources/app_management/metadata_view.js index 8e460439..d063cdc 100644 --- a/chrome/browser/resources/app_management/metadata_view.js +++ b/chrome/browser/resources/app_management/metadata_view.js
@@ -41,6 +41,10 @@ return app.isPinned === OptionalBool.kTrue; }, + isPolicyPinned_: function(app) { + return app.isPolicyPinned === OptionalBool.kTrue; + }, + /** @private */ togglePinned_: function() { let newPinnedValue;
diff --git a/chrome/browser/resources/app_management/permission_toggle.html b/chrome/browser/resources/app_management/permission_toggle.html index c7a3017..15d2a807 100644 --- a/chrome/browser/resources/app_management/permission_toggle.html +++ b/chrome/browser/resources/app_management/permission_toggle.html
@@ -1,11 +1,34 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/policy/cr_tooltip_icon.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <dom-module id="app-management-permission-toggle"> <template> + <style> + :host { + align-items: center; + display: flex; + } + + #policy-indicator { + fill: var(--google-grey-refresh-700); + padding-inline-end: 12px; + } + </style> + <template is="dom-if" + if="[[isPermissionManaged_(app, permissionType)]]"> + <iron-icon id="policy-indicator" icon="cr:domain" tabindex="0" + aria-describedby="tooltip"> + </iron-icon> + <paper-tooltip id="tooltip" for="policy-indicator" + position="top" fit-to-visible-bounds> + $i18n{controlledByPolicy} + </paper-tooltip> + </template> <cr-toggle checked="[[getPermissionValueBool_(app, permissionType)]]" - on-change="togglePermission_"> + on-change="togglePermission_" + disabled$="[[isPermissionManaged_(app, permissionType)]]"> </cr-toggle> </template> <script src="permission_toggle.js"></script>
diff --git a/chrome/browser/resources/app_management/permission_toggle.js b/chrome/browser/resources/app_management/permission_toggle.js index a8908cb..7856395 100644 --- a/chrome/browser/resources/app_management/permission_toggle.js +++ b/chrome/browser/resources/app_management/permission_toggle.js
@@ -34,6 +34,22 @@ return app_management.util.getPermissionValueBool(app, permissionType); }, + /** + * @param {App} app + * @param {string} permissionType + * @return {boolean} + */ + isPermissionManaged_: function(app, permissionType) { + if (app === undefined || permissionType === undefined) { + return false; + } + + assert(app); + + const permission = app_management.util.getPermission(app, permissionType); + assert(permission); + return permission.isManaged; + }, togglePermission_: function() { assert(this.app); @@ -67,8 +83,10 @@ */ getNewPermissionBoolean_: function(app, permissionType) { let newPermissionValue; + const currentPermission = + app_management.util.getPermission(app, permissionType); - switch (app_management.util.getPermission(app, permissionType).value) { + switch (currentPermission.value) { case Bool.kFalse: newPermissionValue = Bool.kTrue; break; @@ -82,7 +100,8 @@ assert(newPermissionValue !== undefined); return app_management.util.createPermission( app_management.util.permissionTypeHandle(app, permissionType), - PermissionValueType.kBool, newPermissionValue); + PermissionValueType.kBool, newPermissionValue, + currentPermission.isManaged); }, /** @@ -93,8 +112,10 @@ */ getNewPermissionTriState_: function(app, permissionType) { let newPermissionValue; + const currentPermission = + app_management.util.getPermission(app, permissionType); - switch (app_management.util.getPermission(app, permissionType).value) { + switch (currentPermission.value) { case TriState.kBlock: newPermissionValue = TriState.kAllow; break; @@ -115,6 +136,7 @@ assert(newPermissionValue !== undefined); return app_management.util.createPermission( app_management.util.permissionTypeHandle(app, permissionType), - PermissionValueType.kTriState, newPermissionValue); + PermissionValueType.kTriState, newPermissionValue, + currentPermission.isManaged); }, });
diff --git a/chrome/browser/resources/app_management/permission_view_header.html b/chrome/browser/resources/app_management/permission_view_header.html index f2e1358..cf696b0 100644 --- a/chrome/browser/resources/app_management/permission_view_header.html +++ b/chrome/browser/resources/app_management/permission_view_header.html
@@ -39,8 +39,8 @@ } #policy-indicator { - fill: var(--google-grey-refresh-500); - padding-inline-end: 10px; + fill: var(--google-grey-refresh-700); + margin-inline-end: 12px; } </style> <cr-icon-button class="icon-arrow-back" id="backButton"
diff --git a/chrome/browser/resources/app_management/util.js b/chrome/browser/resources/app_management/util.js index 5330b4d..57402cb 100644 --- a/chrome/browser/resources/app_management/util.js +++ b/chrome/browser/resources/app_management/util.js
@@ -58,13 +58,15 @@ * @param {number} permissionId * @param {!PermissionValueType} valueType * @param {number} value + * @param {boolean} isManaged * @return {!Permission} */ - function createPermission(permissionId, valueType, value) { + function createPermission(permissionId, valueType, value, isManaged) { return { - permissionId: permissionId, - valueType: valueType, - value: value, + permissionId, + valueType, + value, + isManaged, }; }
diff --git a/chrome/browser/resources/chromeos/camera/src/css/main.css b/chrome/browser/resources/chromeos/camera/src/css/main.css index fa068304..bcee2f2a 100644 --- a/chrome/browser/resources/chromeos/camera/src/css/main.css +++ b/chrome/browser/resources/chromeos/camera/src/css/main.css
@@ -1110,7 +1110,7 @@ } #intro-dialog .dialog-title-icon { - background-image: url(../images/dialog_new_cca_icon.svg); + background-image: url(../images/dialog_intro_icon.svg); background-size: cover; height: 32px; width: 32px;
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc index 0e65c846..e6aca9e 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
@@ -312,7 +312,9 @@ } std::string AdvancedProtectionStatusManager::GetPrimaryAccountId() const { - return identity_manager_ ? identity_manager_->GetPrimaryAccountId() + // TODO(triploblastic@): Remove explicit conversion once + // AdvancedProtectionStatusManager has been fixed to use CoreAccountId. + return identity_manager_ ? identity_manager_->GetPrimaryAccountId().id : std::string(); }
diff --git a/chrome/browser/signin/account_consistency_mode_manager.cc b/chrome/browser/signin/account_consistency_mode_manager.cc index 73c32d5..ae4cea93 100644 --- a/chrome/browser/signin/account_consistency_mode_manager.cc +++ b/chrome/browser/signin/account_consistency_mode_manager.cc
@@ -188,8 +188,6 @@ // profiles. This profile manually sets the kSigninAllowed prference, which // causes crashes if the AccountConsistencyModeManager is instantiated. See // https://crbug.com/940026 - // TODO(https://crbug.com/947933): IsRegularProfile implies !IsGuestSession, - // update the code and documentation. return profile->IsRegularProfile() && !profile->IsGuestSession() && !profile->IsSystemProfile(); }
diff --git a/chrome/browser/signin/consistency_cookie_browsertest.cc b/chrome/browser/signin/consistency_cookie_browsertest.cc new file mode 100644 index 0000000..97b61b5 --- /dev/null +++ b/chrome/browser/signin/consistency_cookie_browsertest.cc
@@ -0,0 +1,179 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/signin/core/browser/consistency_cookie_manager_base.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/callback.h" +#include "base/run_loop.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/account_reconcilor_factory.h" +#include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/ssl/cert_verifier_browser_test.h" +#include "chrome/browser/ssl/chrome_mock_cert_verifier.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/signin/core/browser/consistency_cookie_manager_base.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "google_apis/gaia/gaia_switches.h" +#include "google_apis/gaia/gaia_urls.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "net/cookies/canonical_cookie.h" +#include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/default_handlers.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace { + +const char kConsistencyCookieName[] = "CHROME_ID_CONSISTENCY_STATE"; + +// Subclass of ConsistencyCookieManagerBase allowing to manually control the +// value of the cookie. +class TestConsistencyCookieManager + : public signin::ConsistencyCookieManagerBase, + public network::mojom::CookieChangeListener { + public: + TestConsistencyCookieManager(SigninClient* client, + AccountReconcilor* reconcilor) + : signin::ConsistencyCookieManagerBase(client, reconcilor), + cookie_listener_binding_(this) { + // Listen to cookie changes. + network::mojom::CookieChangeListenerPtr listener_ptr; + cookie_listener_binding_.Bind(mojo::MakeRequest(&listener_ptr)); + client->GetCookieManager()->AddCookieChangeListener( + GaiaUrls::GetInstance()->gaia_url(), kConsistencyCookieName, + std::move(listener_ptr)); + // Subclasses have to call UpdateCookie() in the constructor. + UpdateCookie(); + // Wait for the initial cookie to be set. + WaitForCookieChange(); + } + + // Sets a new value for the consistency cookie. + void SetValue(const std::string& value) { + value_ = value; + UpdateCookie(); + WaitForCookieChange(); + } + + private: + // Waits until OnCookieChange is called. + void WaitForCookieChange() { + base::RunLoop loop; + run_loop_quit_closure_ = loop.QuitClosure(); + loop.Run(); + } + + // CookieChangeListener: + void OnCookieChange(const net::CanonicalCookie& cookie, + network::mojom::CookieChangeCause cause) override { + ASSERT_EQ(kConsistencyCookieName, cookie.Name()); + if (!run_loop_quit_closure_.is_null()) + std::move(run_loop_quit_closure_).Run(); + } + + // ConsistencyCookieManagerBase: + std::string CalculateCookieValue() override { return value_; } + + std::string value_ = "initial_value"; + mojo::Binding<network::mojom::CookieChangeListener> cookie_listener_binding_; + base::OnceClosure run_loop_quit_closure_; +}; + +} // namespace + +class ConsistencyCookieBrowserTest : public CertVerifierBrowserTest { + public: + ConsistencyCookieBrowserTest() + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { + net::test_server::RegisterDefaultHandlers(&https_server_); + } + + ~ConsistencyCookieBrowserTest() override {} + + // Updates the cookie through the consistency cookie manager and blocks until + // it completes. + void SetCookieValue(const std::string& cookie_value) { + consistency_cookie_manager_->SetValue(cookie_value); + } + + // Checks the cookie both in HTTP and javascript. + void CheckCookieValue(const std::string& expected_cookie) { + // Check that the cookie is set in HTTP. + ui_test_utils::NavigateToURL( + browser(), + https_server_.GetURL(GaiaUrls::GetInstance()->gaia_url().host(), + "/echoheader?Cookie")); + std::string http_cookie = + content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), + "document.body.innerText") + .ExtractString(); + EXPECT_EQ(expected_cookie, http_cookie); + + // Check that the cookie is available in javascript. + std::string javascript_cookie = + content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), + "document.cookie") + .ExtractString(); + EXPECT_EQ(expected_cookie, javascript_cookie); + } + + private: + // CertVerifierBrowserTest: + void SetUp() override { + ASSERT_TRUE(https_server_.InitializeAndListen()); + CertVerifierBrowserTest::SetUp(); + } + + void SetUpOnMainThread() override { + CertVerifierBrowserTest::SetUpOnMainThread(); + + // Configure the embedded test server. + // DNS rule for the Gaia URL. + host_resolver()->AddRule(GaiaUrls::GetInstance()->gaia_url().host(), + https_server_.base_url().host()); + // Whitelist all certs for the HTTPS server to prevent SSL errors. + auto cert = https_server_.GetCertificate(); + net::CertVerifyResult verify_result; + verify_result.cert_status = 0; + verify_result.is_issued_by_known_root = true; + verify_result.verified_cert = cert; + mock_cert_verifier()->AddResultForCert(cert.get(), verify_result, net::OK); + // Start the server. + https_server_.StartAcceptingConnections(); + + Profile* profile = browser()->profile(); + // Setup the CookieConsistencyCookieManager + AccountReconcilor* reconcilor = + AccountReconcilorFactory::GetForProfile(profile); + std::unique_ptr<TestConsistencyCookieManager> consistency_cookie_manager = + std::make_unique<TestConsistencyCookieManager>( + ChromeSigninClientFactory::GetForProfile(profile), reconcilor); + consistency_cookie_manager_ = consistency_cookie_manager.get(); + reconcilor->SetConsistencyCookieManager( + std::move(consistency_cookie_manager)); + } + + net::EmbeddedTestServer https_server_; + TestConsistencyCookieManager* consistency_cookie_manager_; +}; + +// Tests that the ConsistencyCookieManager can set and change the cookie in HTTP +// and javascript. +IN_PROC_BROWSER_TEST_F(ConsistencyCookieBrowserTest, Basic) { + // Check the initial value. + CheckCookieValue(std::string(kConsistencyCookieName) + "=initial_value"); + // Change the cookie. + SetCookieValue("new_value"); + CheckCookieValue(std::string(kConsistencyCookieName) + "=new_value"); +}
diff --git a/chrome/browser/sync/sync_ui_util_unittest.cc b/chrome/browser/sync/sync_ui_util_unittest.cc index d5d71cc..db436df 100644 --- a/chrome/browser/sync/sync_ui_util_unittest.cc +++ b/chrome/browser/sync/sync_ui_util_unittest.cc
@@ -164,7 +164,7 @@ // This test ensures that each distinctive SyncService status will return a // unique combination of status and link messages from GetStatusLabels(). // Crashes on Win and Mac. https://crbug.com/954365 -TEST_F(SyncUIUtilTest, DISABLED_DistinctCasesReportUniqueMessageSets) { +TEST_F(SyncUIUtilTest, DistinctCasesReportUniqueMessageSets) { std::set<base::string16> messages; for (int idx = 0; idx != NUMBER_OF_STATUS_CASES; idx++) { std::unique_ptr<Profile> profile = BuildTestingProfile();
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc index a423dc2..c01f6c3 100644 --- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -236,45 +236,6 @@ } } - void ExpectAddressesDiffInHistograms(int added, int removed) { - histogram_tester_.ExpectUniqueSample("Autofill.WalletAddresses2.Added", - /*bucket=*/added, - /*count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.WalletAddresses2.Removed", - /*bucket=*/removed, - /*count=*/1); - histogram_tester_.ExpectUniqueSample( - "Autofill.WalletAddresses2.AddedOrRemoved", - /*bucket=*/added + removed, - /*count=*/1); - } - - void ExpectNoHistogramsForAddressesDiff() { - histogram_tester_.ExpectTotalCount("Autofill.WalletAddresses2.Added", 0); - histogram_tester_.ExpectTotalCount("Autofill.WalletAddresses2.Removed", 0); - histogram_tester_.ExpectTotalCount( - "Autofill.WalletAddresses2.AddedOrRemoved", 0); - } - - void ExpectCardsDiffInHistograms(int added, int removed) { - histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.Added", - /*bucket=*/added, - /*count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.Removed", - /*bucket=*/removed, - /*count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.AddedOrRemoved", - /*bucket=*/added + removed, - /*count=*/1); - } - - void ExpectNoHistogramsForCardsDiff() { - histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.Added", 0); - histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.Removed", 0); - histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.AddedOrRemoved", - 0); - } - void AdvanceAutofillClockByOneDay() { test_clock_.Advance(base::TimeDelta::FromDays(1)); } @@ -324,10 +285,6 @@ // Check that the data is stored in the profile storage. EXPECT_EQ(1U, GetServerCards(GetProfileWebDataService(0)).size()); EXPECT_EQ(1U, GetServerProfiles(GetProfileWebDataService(0)).size()); - - // No histograms for initial sync. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } class SingleClientWalletWithAccountStorageSyncTest @@ -461,10 +418,6 @@ EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); EXPECT_EQ(1U, GetServerCardsMetadata(0).size()); EXPECT_EQ(1U, GetServerAddressesMetadata(0).size()); - - // No histograms for initial sync & for clearing. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } // Wallet data should get cleared from the database when sync is (temporarily) @@ -506,10 +459,6 @@ EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); EXPECT_EQ(1U, GetServerCardsMetadata(0).size()); EXPECT_EQ(1U, GetServerAddressesMetadata(0).size()); - - // No histograms for initial sync & for clearing. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } // ChromeOS does not sign out, so the test below does not apply. @@ -541,10 +490,6 @@ EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData()); EXPECT_EQ(0U, GetServerCardsMetadata(0).size()); EXPECT_EQ(0U, GetServerAddressesMetadata(0).size()); - - // No histograms for initial sync & for clearing. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } #endif // !defined(OS_CHROMEOS) @@ -571,10 +516,6 @@ profiles[0]->GetRawInfo(autofill::COMPANY_NAME)))); EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); - // No histograms for initial sync. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); - // Put some completely new data in the sync server. GetFakeServer()->SetWalletData( {CreateSyncWalletCard(/*name=*/"new-card", /*last_four=*/"0002", @@ -599,10 +540,6 @@ EXPECT_EQ("Company-2", TruncateUTF8(base::UTF16ToUTF8( profiles[0]->GetRawInfo(autofill::COMPANY_NAME)))); EXPECT_EQ("newid", pdm->GetPaymentsCustomerData()->customer_id); - - // Expect correct histograms are reported for the update. - ExpectCardsDiffInHistograms(/*added=*/1, /*removed=*/1); - ExpectAddressesDiffInHistograms(/*added=*/1, /*removed=*/1); } // Wallet is not using incremental updates. The server either sends a non-empty @@ -652,10 +589,6 @@ EXPECT_EQ("Company-1", TruncateUTF8(base::UTF16ToUTF8( profiles[0]->GetRawInfo(autofill::COMPANY_NAME)))); EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); - - // No histograms for initial sync, nor for an empty update. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } // Check on top of EmptyUpdatesAreIgnored that the new progress marker is stored @@ -698,10 +631,6 @@ CreateDefaultSyncPaymentsCustomerData()}); ASSERT_TRUE(SetupSync()); - // No histograms for initial sync. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); - // Refresh the pdm so that it gets data from autofill table. autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); @@ -744,10 +673,6 @@ profiles[0]->GetRawInfo(autofill::COMPANY_NAME)))); EXPECT_EQ("different", pdm->GetPaymentsCustomerData()->customer_id); - // Expect correct histograms for the (no) update. - ExpectCardsDiffInHistograms(/*added=*/0, /*removed=*/0); - ExpectAddressesDiffInHistograms(/*added=*/0, /*removed=*/0); - // Test that the non-default metadata values stayed around. std::map<std::string, AutofillMetadata> cards_metadata = GetServerCardsMetadata(0); @@ -813,10 +738,6 @@ EXPECT_EQ("Company-1", TruncateUTF8(base::UTF16ToUTF8( profiles[0]->GetRawInfo(autofill::COMPANY_NAME)))); - // Expect correct histograms for the (remove&add) update. - ExpectCardsDiffInHistograms(/*added=*/1, /*removed=*/1); - ExpectAddressesDiffInHistograms(/*added=*/1, /*removed=*/1); - // Test that the non-default metadata values stayed around. std::map<std::string, AutofillMetadata> cards_metadata = GetServerCardsMetadata(0); @@ -847,9 +768,6 @@ CreateDefaultSyncPaymentsCustomerData()}); ASSERT_TRUE(SetupSync()); - // No histograms for initial sync. - ExpectNoHistogramsForCardsDiff(); - // Check we have the card locally. autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); @@ -886,9 +804,6 @@ EXPECT_EQ(ASCIIToUTF16("0001"), cards[0]->LastFourDigits()); EXPECT_EQ(CreditCard::FULL_SERVER_CARD, cards[0]->record_type()); EXPECT_EQ("different", pdm->GetPaymentsCustomerData()->customer_id); - - // Expect correct histograms for the (no) update. - ExpectCardsDiffInHistograms(/*added=*/0, /*removed=*/0); } // Tests that we do not report any diff metric on startup without getting a new @@ -908,10 +823,6 @@ ASSERT_EQ(1uL, pdm->GetCreditCards().size()); ASSERT_EQ(1uL, pdm->GetServerProfiles().size()); ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); - - // No histograms for initial sync. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } IN_PROC_BROWSER_TEST_P(SingleClientWalletSyncTestWithDefaultFeatures, @@ -930,10 +841,6 @@ ASSERT_EQ(1uL, pdm->GetCreditCards().size()); ASSERT_EQ(1uL, pdm->GetServerProfiles().size()); ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); - - // No histograms for the startup, neither for the empty update. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } // Tests that we _do_ report one diff metric on startup when we get an update @@ -955,10 +862,6 @@ ASSERT_EQ(1uL, pdm->GetCreditCards().size()); ASSERT_EQ(1uL, pdm->GetServerProfiles().size()); ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); - - // No histograms for initial sync. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } IN_PROC_BROWSER_TEST_P(SingleClientWalletSyncTestWithDefaultFeatures, @@ -978,10 +881,6 @@ ASSERT_EQ(2uL, pdm->GetCreditCards().size()); ASSERT_EQ(1uL, pdm->GetServerProfiles().size()); ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); - - // One histogram for startup / full update. - ExpectCardsDiffInHistograms(/*added=*/1, /*removed=*/0); - ExpectAddressesDiffInHistograms(/*added=*/0, /*removed=*/0); } // Tests that we do report age metric on startup. @@ -1069,10 +968,6 @@ EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData()); EXPECT_EQ(0U, GetServerCardsMetadata(0).size()); EXPECT_EQ(0U, GetServerAddressesMetadata(0).size()); - - // No histograms for initial sync & for clearing. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } // Wallet data should get cleared from the database when the wallet autofill @@ -1105,10 +1000,6 @@ EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData()); EXPECT_EQ(0U, GetServerCardsMetadata(0).size()); EXPECT_EQ(0U, GetServerAddressesMetadata(0).size()); - - // No histograms for initial sync & for clearing. - ExpectNoHistogramsForCardsDiff(); - ExpectNoHistogramsForAddressesDiff(); } // Wallet data present on the client should be cleared in favor of the new data @@ -1173,10 +1064,6 @@ // The PaymentsCustomerData should still be there. EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id); - - // Expect correct histograms are reported for the update. - ExpectCardsDiffInHistograms(/*added=*/1, /*removed=*/1); - ExpectAddressesDiffInHistograms(/*added=*/0, /*removed=*/1); } // Wallet data present on the client should be cleared in favor of the new data
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 04eaa25..d7e63d5 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -900,6 +900,8 @@ "hats/hats_service_factory.h", "hung_renderer/hung_renderer_core.cc", "hung_renderer/hung_renderer_core.h", + "intent_picker_tab_helper.cc", + "intent_picker_tab_helper.h", "javascript_dialogs/javascript_dialog_views.cc", "javascript_dialogs/javascript_dialog_views.h", "layout_constants.cc",
diff --git a/chrome/browser/ui/android/passwords/manual_filling_view_android.cc b/chrome/browser/ui/android/passwords/manual_filling_view_android.cc index 9bcd9ce..57eb099a 100644 --- a/chrome/browser/ui/android/passwords/manual_filling_view_android.cc +++ b/chrome/browser/ui/android/passwords/manual_filling_view_android.cc
@@ -16,10 +16,12 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/bind.h" +#include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/autofill/manual_filling_controller.h" #include "chrome/browser/autofill/manual_filling_controller_impl.h" #include "chrome/browser/password_manager/password_accessory_controller.h" +#include "chrome/browser/password_manager/password_generation_controller.h" #include "components/autofill/core/browser/ui/accessory_sheet_data.h" #include "components/autofill/core/common/password_form.h" #include "jni/ManualFillingComponentBridge_jni.h" @@ -221,6 +223,25 @@ } // static +void JNI_ManualFillingComponentBridge_SignalAutoGenerationStatusForTesting( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& j_web_contents, + jboolean j_available) { + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(j_web_contents); + if (j_available) { + // The added generation button will call back to the generation controller + // so we need to make sure one exists. + ignore_result(PasswordGenerationController::GetOrCreate(web_contents)); + } + + // Bypass the generation controller when sending this status to the UI to + // avoid setup overhead, since its logic is currently not needed for tests. + ManualFillingControllerImpl::GetOrCreate(web_contents) + ->OnAutomaticGenerationStatusChanged(j_available); +} + +// static std::unique_ptr<ManualFillingViewInterface> ManualFillingViewInterface::Create( ManualFillingController* controller) { return std::make_unique<ManualFillingViewAndroid>(controller);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc index 8533891..c823485b 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -73,6 +73,8 @@ constexpr char kSystem[] = "system"; constexpr char kUninstalled[] = "uninstalled"; constexpr char kVPNProvider[] = "vpnprovider"; +constexpr char kPermissionStateGranted[] = "granted"; +constexpr char kPermissionStateManaged[] = "managed"; // Defines current version for app icons. This is used for invalidation icons in // case we change how app icons are produced on Android side. Can be updated in @@ -610,7 +612,8 @@ bool should_sync = false; bool system = false; bool vpn_provider = false; - base::flat_map<arc::mojom::AppPermission, bool> permissions; + base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr> + permissions; GetInt64FromPref(package, kLastBackupAndroidId, &last_backup_android_id); GetInt64FromPref(package, kLastBackupTime, &last_backup_time); @@ -618,6 +621,7 @@ package->GetBoolean(kShouldSync, &should_sync); package->GetBoolean(kSystem, &system); package->GetBoolean(kVPNProvider, &vpn_provider); + const base::Value* permission_val = package->FindKey(kPermissions); if (permission_val) { const base::DictionaryValue* permission_dict = nullptr; @@ -630,18 +634,33 @@ base::StringToInt64(iter.key(), &permission_type); DCHECK_NE(-1, permission_type); - bool value = false; - iter.value().GetAsBoolean(&value); + bool granted = false; + bool managed = false; + const base::Value& permission_state = iter.value(); + // Handle old pref structure. + if (permission_state.is_bool()) { + permission_state.GetAsBoolean(&granted); + } + + // Handle new pref structure. + if (permission_state.is_dict()) { + const base::DictionaryValue* permission_state_dict = nullptr; + permission_state.GetAsDictionary(&permission_state_dict); + permission_state_dict->GetBoolean(kPermissionStateGranted, &granted); + permission_state_dict->GetBoolean(kPermissionStateManaged, &managed); + } + + auto state = arc::mojom::PermissionState::New(granted, managed); arc::mojom::AppPermission permission = static_cast<arc::mojom::AppPermission>(permission_type); - permissions.insert(std::make_pair(permission, value)); + permissions.emplace(permission, std::move(state)); } } return std::make_unique<PackageInfo>( package_name, package_version, last_backup_android_id, last_backup_time, - should_sync, system, vpn_provider, permissions); + should_sync, system, vpn_provider, std::move(permissions)); } std::vector<std::string> ArcAppListPrefs::GetAppIds() const { @@ -1249,13 +1268,18 @@ package_dict->SetBoolean(kUninstalled, false); package_dict->SetBoolean(kVPNProvider, package.vpn_provider); if (package.permissions.has_value()) { - base::DictionaryValue permission_dict; + base::DictionaryValue permissions_dict; for (const auto& permission : package.permissions.value()) { - permission_dict.SetBoolean( + base::DictionaryValue permission_dict; + permission_dict.SetBoolean(kPermissionStateGranted, + permission.second->granted); + permission_dict.SetBoolean(kPermissionStateManaged, + permission.second->managed); + permissions_dict.SetKey( base::NumberToString(static_cast<int64_t>(permission.first)), - permission.second); + std::move(permission_dict)); } - package_dict->SetKey(kPermissions, std::move(permission_dict)); + package_dict->SetKey(kPermissions, std::move(permissions_dict)); } else { // Remove kPermissions from dict if there are no permissions. package_dict->RemoveKey(kPermissions); @@ -1892,7 +1916,8 @@ bool should_sync, bool system, bool vpn_provider, - const base::flat_map<arc::mojom::AppPermission, bool>& permissions) + base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr> + permissions) : package_name(package_name), package_version(package_version), last_backup_android_id(last_backup_android_id), @@ -1900,7 +1925,7 @@ should_sync(should_sync), system(system), vpn_provider(vpn_provider), - permissions(permissions) {} + permissions(std::move(permissions)) {} // Need to add explicit destructor for chromium style checker error: // Complex class/struct needs an explicit out-of-line destructor
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h index e025b74..c673b3f 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -116,15 +116,15 @@ }; struct PackageInfo { - PackageInfo( - const std::string& package_name, - int32_t package_version, - int64_t last_backup_android_id, - int64_t last_backup_time, - bool should_sync, - bool system, - bool vpn_provider, - const base::flat_map<arc::mojom::AppPermission, bool>& permissions); + PackageInfo(const std::string& package_name, + int32_t package_version, + int64_t last_backup_android_id, + int64_t last_backup_time, + bool should_sync, + bool system, + bool vpn_provider, + base::flat_map<arc::mojom::AppPermission, + arc::mojom::PermissionStatePtr> permissions); ~PackageInfo(); std::string package_name; @@ -134,8 +134,9 @@ bool should_sync; bool system; bool vpn_provider; - // Maps app permission to boolean values - base::flat_map<arc::mojom::AppPermission, bool> permissions; + // Maps app permission to permission states + base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr> + permissions; }; class Observer {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_test.cc b/chrome/browser/ui/app_list/arc/arc_app_test.cc index 71aa4a6..849f0ff 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_test.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_test.cc
@@ -172,27 +172,47 @@ app.sticky = true; fake_default_apps_.push_back(app); - base::flat_map<arc::mojom::AppPermission, bool> permissions; - permissions.insert(std::make_pair(arc::mojom::AppPermission::CAMERA, 0)); + base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr> + permissions1; + permissions1.emplace(arc::mojom::AppPermission::CAMERA, + arc::mojom::PermissionState::New(false /* granted */, + false /* managed */)); fake_packages_.emplace_back(arc::mojom::ArcPackageInfo::New( kPackageName1 /* package_name */, 1 /* package_version */, 1 /* last_backup_android_id */, 1 /* last_backup_time */, false /* sync */, false /* system */, false /* vpn_provider */, - nullptr /* web_app_info */, permissions)); + nullptr /* web_app_info */, std::move(permissions1))); - permissions.insert(std::make_pair(arc::mojom::AppPermission::MICROPHONE, 0)); + base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr> + permissions2; + permissions2.emplace(arc::mojom::AppPermission::CAMERA, + arc::mojom::PermissionState::New(false /* granted */, + false /* managed */)); + permissions2.emplace(arc::mojom::AppPermission::MICROPHONE, + arc::mojom::PermissionState::New(false /* granted */, + false /* managed */)); fake_packages_.emplace_back(arc::mojom::ArcPackageInfo::New( kPackageName2 /* package_name */, 2 /* package_version */, 2 /* last_backup_android_id */, 2 /* last_backup_time */, true /* sync */, false /* system */, false /* vpn_provider */, nullptr /* web_app_info */, - permissions)); + std::move(permissions2))); - permissions.insert(std::make_pair(arc::mojom::AppPermission::LOCATION, 1)); + base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr> + permissions3; + permissions3.emplace(arc::mojom::AppPermission::CAMERA, + arc::mojom::PermissionState::New(false /* granted */, + false /* managed */)); + permissions3.emplace(arc::mojom::AppPermission::MICROPHONE, + arc::mojom::PermissionState::New(false /* granted */, + false /* managed */)); + permissions3.emplace(arc::mojom::AppPermission::LOCATION, + arc::mojom::PermissionState::New(true /* granted */, + false /* managed */)); fake_packages_.emplace_back(arc::mojom::ArcPackageInfo::New( kPackageName3 /* package_name */, 3 /* package_version */, 3 /* last_backup_android_id */, 3 /* last_backup_time */, false /* sync */, false /* system */, false /* vpn_provider */, - nullptr /* web_app_info */, permissions)); + nullptr /* web_app_info */, std::move(permissions3))); for (int i = 0; i < 3; ++i) { arc::mojom::ShortcutInfo shortcut_info;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc index 1d73404..b9105b89 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -465,13 +465,19 @@ arc::mojom::ArcPackageInfoPtr CreatePackageWithVersion( const std::string& package_name, int package_version) { - base::flat_map<arc::mojom::AppPermission, bool> permissions; - permissions.insert(std::make_pair(arc::mojom::AppPermission::CAMERA, 0)); - permissions.insert(std::make_pair(arc::mojom::AppPermission::LOCATION, 1)); + base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr> + permissions; + permissions.emplace(arc::mojom::AppPermission::CAMERA, + arc::mojom::PermissionState::New(false /* granted */, + false /* managed */)); + permissions.emplace(arc::mojom::AppPermission::LOCATION, + arc::mojom::PermissionState::New(true /* granted */, + false /* managed */)); return arc::mojom::ArcPackageInfo::New( package_name, package_version, 1 /* last_backup_android_id */, 1 /* last_backup_time */, true /* sync */, false /* system */, - false /* vpn_provider */, nullptr /* web_app_info */, permissions); + false /* vpn_provider */, nullptr /* web_app_info */, + std::move(permissions)); } void AddPackage(const arc::mojom::ArcPackageInfoPtr& package) {
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index ed2e5978..031a43d3 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -64,8 +64,6 @@ #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/service_manager/public/cpp/connector.h" #include "services/ws/public/mojom/user_activity_monitor.mojom.h" -#include "ui/aura/mus/property_converter.h" -#include "ui/aura/mus/window_tree_client.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ui_base_features.h"
diff --git a/chrome/browser/ui/autofill/payments/autofill_ui_util.cc b/chrome/browser/ui/autofill/payments/autofill_ui_util.cc index d8d97b9..ed1fd3c2b 100644 --- a/chrome/browser/ui/autofill/payments/autofill_ui_util.cc +++ b/chrome/browser/ui/autofill/payments/autofill_ui_util.cc
@@ -52,6 +52,7 @@ ->UpdatePageActionIcon(icon_type); break; case PageActionIconType::kFind: + case PageActionIconType::kIntentPicker: case PageActionIconType::kPwaInstall: case PageActionIconType::kSendTabToSelf: case PageActionIconType::kTranslate:
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index a74d5c1..910dbe1 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h
@@ -334,7 +334,6 @@ bool show_stay_in_chrome, bool show_remember_selection, IntentPickerResponse callback) = 0; - virtual void SetIntentPickerViewVisibility(bool visible) = 0; #endif // !defined(OS_ANDROID) // Shows the Bookmark bubble. |url| is the URL being bookmarked,
diff --git a/chrome/browser/ui/intent_picker_tab_helper.cc b/chrome/browser/ui/intent_picker_tab_helper.cc new file mode 100644 index 0000000..496e2f9 --- /dev/null +++ b/chrome/browser/ui/intent_picker_tab_helper.cc
@@ -0,0 +1,32 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/intent_picker_tab_helper.h" + +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/page_action/page_action_icon_container.h" + +IntentPickerTabHelper::~IntentPickerTabHelper() = default; + +// static +void IntentPickerTabHelper::SetShouldShowIcon( + content::WebContents* web_contents, + bool should_show_icon) { + IntentPickerTabHelper* tab_helper = FromWebContents(web_contents); + if (!tab_helper) + return; + tab_helper->should_show_icon_ = should_show_icon; + Browser* browser = chrome::FindBrowserWithWebContents(web_contents); + if (!browser) + return; + browser->window()->GetOmniboxPageActionIconContainer()->UpdatePageActionIcon( + PageActionIconType::kIntentPicker); +} + +IntentPickerTabHelper::IntentPickerTabHelper(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) {} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(IntentPickerTabHelper)
diff --git a/chrome/browser/ui/intent_picker_tab_helper.h b/chrome/browser/ui/intent_picker_tab_helper.h new file mode 100644 index 0000000..f9db0763 --- /dev/null +++ b/chrome/browser/ui/intent_picker_tab_helper.h
@@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_INTENT_PICKER_TAB_HELPER_H_ +#define CHROME_BROWSER_UI_INTENT_PICKER_TAB_HELPER_H_ + +#include "base/macros.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +// Controls the visibility of IntentPickerView by updating the visibility based +// on stored state. +class IntentPickerTabHelper + : public content::WebContentsObserver, + public content::WebContentsUserData<IntentPickerTabHelper> { + public: + ~IntentPickerTabHelper() override; + + static void SetShouldShowIcon(content::WebContents* web_contents, + bool should_show_icon); + + bool should_show_icon() const { return should_show_icon_; } + + WEB_CONTENTS_USER_DATA_KEY_DECL(); + + private: + explicit IntentPickerTabHelper(content::WebContents* web_contents); + friend class content::WebContentsUserData<IntentPickerTabHelper>; + + bool should_show_icon_ = false; + + DISALLOW_COPY_AND_ASSIGN(IntentPickerTabHelper); +}; + +#endif // CHROME_BROWSER_UI_INTENT_PICKER_TAB_HELPER_H_
diff --git a/chrome/browser/ui/page_action/page_action_icon_container.h b/chrome/browser/ui/page_action/page_action_icon_container.h index 0fa8cb86..f09ce779 100644 --- a/chrome/browser/ui/page_action/page_action_icon_container.h +++ b/chrome/browser/ui/page_action/page_action_icon_container.h
@@ -11,6 +11,7 @@ kFind, kLocalCardMigration, kManagePasswords, + kIntentPicker, kPwaInstall, kSaveCard, kSendTabToSelf,
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 5b70f7a..c82f9342 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -109,6 +109,7 @@ #include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h" #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" #include "chrome/browser/ui/hung_plugin_tab_helper.h" +#include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/browser/ui/sad_tab_helper.h" #include "chrome/browser/ui/search/search_tab_helper.h" #include "chrome/browser/ui/sync/browser_synced_tab_delegate.h" @@ -289,6 +290,7 @@ extensions::WebNavigationTabObserver::CreateForWebContents(web_contents); FramebustBlockTabHelper::CreateForWebContents(web_contents); HungPluginTabHelper::CreateForWebContents(web_contents); + IntentPickerTabHelper::CreateForWebContents(web_contents); JavaScriptDialogTabHelper::CreateForWebContents(web_contents); ManagePasswordsUIController::CreateForWebContents(web_contents); pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index ff296a52a..a1f0bcdf 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -49,8 +49,6 @@ #include "ui/accessibility/ax_node_data.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" -#include "ui/aura/mus/window_mus.h" -#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window.h" #include "ui/base/hit_test.h" #include "ui/base/layout.h"
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 3f7dc68..ce415c82 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1312,18 +1312,6 @@ std::move(callback)); } -void BrowserView::SetIntentPickerViewVisibility(bool visible) { - LocationBarView* location_bar = GetLocationBarView(); - - if (!location_bar->intent_picker_view()) - return; - - if (location_bar->intent_picker_view()->GetVisible() != visible) { - location_bar->intent_picker_view()->SetVisible(visible); - location_bar->Layout(); - } -} - void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) { toolbar_->ShowBookmarkBubble(url, already_bookmarked, bookmark_bar_view_.get());
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 7045a8d2..be56992 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -367,7 +367,6 @@ bool show_stay_in_chrome, bool show_remember_selection, IntentPickerResponse callback) override; - void SetIntentPickerViewVisibility(bool visible) override; void ShowBookmarkBubble(const GURL& url, bool already_bookmarked) override; autofill::SaveCardBubbleView* ShowSaveCreditCardBubble( content::WebContents* contents,
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc index 2a35daa..c6cb007 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -20,10 +20,6 @@ #include "services/ws/public/cpp/property_type_converters.h" #include "services/ws/public/mojom/window_manager.mojom.h" #include "ui/aura/client/aura_constants.h" -#include "ui/aura/mus/mus_types.h" -#include "ui/aura/mus/property_converter.h" -#include "ui/aura/mus/window_port_mus.h" -#include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/window.h" #include "ui/aura/window_targeter.h" #include "ui/compositor/layer.h"
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc index 8aa66076..c4c1e9c 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
@@ -70,7 +70,7 @@ // which triggers an animation. ash::ImmersiveFullscreenControllerTestApi( static_cast<ImmersiveModeControllerAsh*>(controller_)->controller()) - .SetupForTest(/*wait_for_mouse_event=*/wait); + .SetupForTest(); browser_->window()->Show(); }
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc index dd2e15c..eb1b195 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc
@@ -6,10 +6,13 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/extensions/bookmark_app_navigation_browsertest.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/frame/toolbar_button_provider.h" #include "chrome/browser/ui/views/intent_picker_bubble_view.h" #include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" +#include "chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h" #include "chrome/common/chrome_features.h" #include "url/gurl.h" @@ -26,6 +29,16 @@ extensions::test::BookmarkAppNavigationBrowserTest::SetUp(); } + void OpenNewTab(const GURL& url) { + chrome::NewTab(browser()); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + NavigateToLaunchingPage(browser()); + TestTabActionDoesNotOpenAppWindow( + url, base::BindOnce(&ClickLinkAndWait, web_contents, url, + LinkTarget::SELF, GetParam())); + } + private: base::test::ScopedFeatureList scoped_feature_list_; }; @@ -46,10 +59,11 @@ in_scope_url, base::BindOnce(&ClickLinkAndWait, web_contents, in_scope_url, LinkTarget::SELF, GetParam())); - IntentPickerView* intent_picker_view = + PageActionIconView* intent_picker_view = BrowserView::GetBrowserViewForBrowser(browser()) - ->GetLocationBarView() - ->intent_picker_view(); + ->toolbar_button_provider() + ->GetOmniboxPageActionIconContainerView() + ->GetPageActionIconView(PageActionIconType::kIntentPicker); EXPECT_TRUE(intent_picker_view->GetVisible()); IntentPickerBubbleView* intent_picker = @@ -159,6 +173,36 @@ } } +// Tests that the intent icon updates its visibiliy when switching between +// tabs. +IN_PROC_BROWSER_TEST_P(IntentPickerBubbleViewBrowserTest, + IconVisibilityAfterTabSwitching) { + InstallTestBookmarkApp(); + + const GURL in_scope_url = + https_server().GetURL(GetAppUrlHost(), GetInScopeUrlPath()); + const GURL out_of_scope_url = + https_server().GetURL(GetAppUrlHost(), GetOutOfScopeUrlPath()); + + PageActionIconView* intent_picker_view = + BrowserView::GetBrowserViewForBrowser(browser()) + ->toolbar_button_provider() + ->GetOmniboxPageActionIconContainerView() + ->GetPageActionIconView(PageActionIconType::kIntentPicker); + + // OpenNewTab opens a new tab and focus on the new tab. + OpenNewTab(in_scope_url); + EXPECT_TRUE(intent_picker_view->GetVisible()); + OpenNewTab(out_of_scope_url); + EXPECT_FALSE(intent_picker_view->GetVisible()); + + chrome::SelectPreviousTab(browser()); + EXPECT_TRUE(intent_picker_view->GetVisible()); + + chrome::SelectNextTab(browser()); + EXPECT_FALSE(intent_picker_view->GetVisible()); +} + INSTANTIATE_TEST_SUITE_P( /* no prefix */, IntentPickerBubbleViewBrowserTest,
diff --git a/chrome/browser/ui/views/location_bar/intent_picker_view.cc b/chrome/browser/ui/views/location_bar/intent_picker_view.cc index b9daf2a..d45416d04 100644 --- a/chrome/browser/ui/views/location_bar/intent_picker_view.cc +++ b/chrome/browser/ui/views/location_bar/intent_picker_view.cc
@@ -5,10 +5,10 @@ #include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/browser/apps/intent_helper/apps_navigation_throttle.h" -#include "chrome/browser/apps/intent_helper/intent_picker_controller.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/bookmarks/bookmark_utils.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/views/intent_picker_bubble_view.h" #include "chrome/grit/generated_resources.h" @@ -26,53 +26,62 @@ IntentPickerView::IntentPickerView(Browser* browser, PageActionIconView::Delegate* delegate) : PageActionIconView(nullptr, 0, delegate), browser_(browser) { - if (browser_) { - intent_picker_controller_ = - std::make_unique<apps::IntentPickerController>(browser_); - } } IntentPickerView::~IntentPickerView() = default; -void IntentPickerView::SetVisible(bool visible) { - // Besides changing visibility, make sure that we don't leave an opened bubble - // when transitioning to !visible. - if (!visible) +bool IntentPickerView::Update() { + bool was_visible = GetVisible(); + + SetVisible(ShouldShowIcon()); + + if (!GetVisible()) IntentPickerBubbleView::CloseCurrentBubble(); - PageActionIconView::SetVisible(visible); + return was_visible != GetVisible(); } void IntentPickerView::OnExecuting( PageActionIconView::ExecuteSource execute_source) { - if (browser_ && !browser_->profile()->IsGuestSession() && - !IsIncognitoMode()) { - SetVisible(true); - content::WebContents* web_contents = - browser_->tab_strip_model()->GetActiveWebContents(); - const GURL& url = chrome::GetURLToBookmark(web_contents); + DCHECK(ShouldShowIcon()); + content::WebContents* web_contents = GetWebContents(); + const GURL& url = chrome::GetURLToBookmark(web_contents); #if defined(OS_CHROMEOS) - chromeos::ChromeOsAppsNavigationThrottle::ShowIntentPickerBubble( - web_contents, /*ui_auto_display_service=*/nullptr, url); + chromeos::ChromeOsAppsNavigationThrottle::ShowIntentPickerBubble( + web_contents, /*ui_auto_display_service=*/nullptr, url); #else - apps::AppsNavigationThrottle::ShowIntentPickerBubble( - web_contents, /*ui_auto_display_service=*/nullptr, url); + apps::AppsNavigationThrottle::ShowIntentPickerBubble( + web_contents, /*ui_auto_display_service=*/nullptr, url); #endif // defined(OS_CHROMEOS) - } else { - SetVisible(false); - } } views::BubbleDialogDelegateView* IntentPickerView::GetBubble() const { return IntentPickerBubbleView::intent_picker_bubble(); } -bool IntentPickerView::IsIncognitoMode() { +bool IntentPickerView::IsIncognitoMode() const { DCHECK(browser_); return browser_->profile()->IsOffTheRecord(); } +bool IntentPickerView::ShouldShowIcon() const { + if (IsIncognitoMode()) + return false; + + content::WebContents* web_contents = GetWebContents(); + if (!web_contents) + return false; + + IntentPickerTabHelper* tab_helper = + IntentPickerTabHelper::FromWebContents(web_contents); + + if (!tab_helper) + return false; + + return tab_helper->should_show_icon(); +} + const gfx::VectorIcon& IntentPickerView::GetVectorIcon() const { return omnibox::kOpenInNewIcon; }
diff --git a/chrome/browser/ui/views/location_bar/intent_picker_view.h b/chrome/browser/ui/views/location_bar/intent_picker_view.h index 758e4e7..8eae2ac 100644 --- a/chrome/browser/ui/views/location_bar/intent_picker_view.h +++ b/chrome/browser/ui/views/location_bar/intent_picker_view.h
@@ -5,15 +5,8 @@ #ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_INTENT_PICKER_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_INTENT_PICKER_VIEW_H_ -#include <memory> - -#include "base/macros.h" #include "chrome/browser/ui/views/page_action/page_action_icon_view.h" -namespace apps { -class IntentPickerController; -} // namespace apps - class Browser; // The entry point for the intent picker. @@ -23,7 +16,7 @@ ~IntentPickerView() override; // PageActionIconView: - void SetVisible(bool visible) override; + bool Update() override; protected: // PageActionIconView: @@ -33,9 +26,8 @@ base::string16 GetTextForTooltipAndAccessibleName() const override; private: - bool IsIncognitoMode(); - - std::unique_ptr<apps::IntentPickerController> intent_picker_controller_; + bool IsIncognitoMode() const; + bool ShouldShowIcon() const; Browser* const browser_;
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 985f4675..1a55ff4d 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -49,7 +49,6 @@ #include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h" -#include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_layout.h" #include "chrome/browser/ui/views/location_bar/location_icon_view.h" @@ -227,6 +226,7 @@ params.types_enabled.push_back(PageActionIconType::kManagePasswords); } params.types_enabled.push_back(PageActionIconType::kFind); + params.types_enabled.push_back(PageActionIconType::kIntentPicker); params.types_enabled.push_back(PageActionIconType::kTranslate); params.types_enabled.push_back(PageActionIconType::kZoom); if (base::FeatureList::IsEnabled(features::kDesktopPWAsOmniboxInstall)) @@ -259,9 +259,6 @@ page_action_icons_.push_back(local_card_migration_icon_view_); } - page_action_icons_.push_back(intent_picker_view_ = - new IntentPickerView(browser_, this)); - page_action_icons_.push_back( star_view_ = new StarView(command_updater(), browser_, this)); } @@ -557,8 +554,6 @@ if (star_view_) add_trailing_decoration(star_view_); add_trailing_decoration(omnibox_page_action_icon_container_view_); - if (intent_picker_view_) - add_trailing_decoration(intent_picker_view_); if (save_credit_card_icon_view_) add_trailing_decoration(save_credit_card_icon_view_); if (local_card_migration_icon_view_) @@ -794,8 +789,6 @@ IncrementalMinimumWidth(save_credit_card_icon_view_) + IncrementalMinimumWidth(local_card_migration_icon_view_); - trailing_width += IncrementalMinimumWidth(intent_picker_view_); - for (auto* content_setting_view : content_setting_views_) trailing_width += IncrementalMinimumWidth(content_setting_view);
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index 4a361f61..3d1c5c3 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -41,7 +41,6 @@ class CommandUpdater; class ContentSettingBubbleModelDelegate; class GURL; -class IntentPickerView; class KeywordHintView; class LocationIconView; enum class OmniboxPart; @@ -148,10 +147,6 @@ // Toggles the star on or off. void SetStarToggled(bool on); - // The intent picker, should not always be visible. It will be null when - // |browser_| is null. - IntentPickerView* intent_picker_view() { return intent_picker_view_; } - // The star. It may not be visible. It will be null when |browser_| is null. StarView* star_view() { return star_view_; } @@ -430,10 +425,6 @@ send_tab_to_self::SendTabToSelfIconView* send_tab_to_self_icon_view_ = nullptr; - // The intent picker for accessing apps. It will be null when - // |browser_| is null. - IntentPickerView* intent_picker_view_ = nullptr; - // The star for bookmarking. It will be null when |browser_| is null. StarView* star_view_ = nullptr;
diff --git a/chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.cc b/chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.cc index 0824697..a1072f3f 100644 --- a/chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.cc +++ b/chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/location_bar/find_bar_icon.h" +#include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h" #include "chrome/browser/ui/views/page_action/pwa_install_view.h" #include "chrome/browser/ui/views/page_action/zoom_view.h" @@ -44,6 +45,11 @@ params.command_updater, params.page_action_icon_delegate); page_action_icons_.push_back(manage_passwords_icon_); break; + case PageActionIconType::kIntentPicker: + intent_picker_view_ = new IntentPickerView( + params.browser, params.page_action_icon_delegate); + page_action_icons_.push_back(intent_picker_view_); + break; case PageActionIconType::kPwaInstall: DCHECK(params.command_updater); pwa_install_view_ = new PwaInstallView( @@ -98,6 +104,8 @@ return find_bar_icon_; case PageActionIconType::kManagePasswords: return manage_passwords_icon_; + case PageActionIconType::kIntentPicker: + return intent_picker_view_; case PageActionIconType::kPwaInstall: return pwa_install_view_; case PageActionIconType::kTranslate:
diff --git a/chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h b/chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h index 9c8aacb..c588322 100644 --- a/chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h +++ b/chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h
@@ -18,6 +18,7 @@ class Browser; class CommandUpdater; class FindBarIcon; +class IntentPickerView; class ManagePasswordsIconViews; class PwaInstallView; class TranslateIconView; @@ -81,6 +82,7 @@ ZoomView* zoom_view_ = nullptr; FindBarIcon* find_bar_icon_ = nullptr; ManagePasswordsIconViews* manage_passwords_icon_ = nullptr; + IntentPickerView* intent_picker_view_ = nullptr; PwaInstallView* pwa_install_view_ = nullptr; send_tab_to_self::SendTabToSelfIconView* send_tab_to_self_icon_view_ = nullptr;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc index 879f9e7..569a50e 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
@@ -196,9 +196,20 @@ ToolbarActionsBar::disable_animations_for_testing_ = false; } +// TODO(crbug.com/963678): fails on ChromeOS as it's assuming SendMouseMove() +// synchronously updates the location of the mouse (which is needed by +// SendMouseClick()). +#if defined(OS_CHROMEOS) +// TODO(pkasting): https://crbug.com/911374 Menu controller thinks the mouse is +// already down when handling the left click. +#define MAYBE_TestClickingOnOverflowedAction \ + DISABLED_TestClickingOnOverflowedAction +#else +#define MAYBE_TestClickingOnOverflowedAction TestClickingOnOverflowedAction +#endif // Tests clicking on an overflowed extension action. IN_PROC_BROWSER_TEST_F(ToolbarActionViewInteractiveUITest, - TestClickingOnOverflowedAction) { + MAYBE_TestClickingOnOverflowedAction) { // Load an extension. ASSERT_TRUE(LoadExtension( test_data_dir_.AppendASCII("ui").AppendASCII("browser_action_popup"))); @@ -356,8 +367,18 @@ EXPECT_EQ(nullptr, toolbar_actions_bar->popup_owner()); } +// TODO(crbug.com/963678): fails on ChromeOS as it's assuming SendMouseMove() +// synchronously updates the location of the mouse (which is needed by +// SendMouseClick()). +#if defined(OS_CHROMEOS) +#define MAYBE_ActivateOverflowedToolbarActionWithKeyboard \ + DISABLED_ActivateOverflowedToolbarActionWithKeyboard +#else +#define MAYBE_ActivateOverflowedToolbarActionWithKeyboard \ + ActivateOverflowedToolbarActionWithKeyboard +#endif IN_PROC_BROWSER_TEST_F(ToolbarActionViewInteractiveUITest, - ActivateOverflowedToolbarActionWithKeyboard) { + MAYBE_ActivateOverflowedToolbarActionWithKeyboard) { views::MenuController::TurnOffMenuSelectionHoldForTest(); // Load an extension with an action. ASSERT_TRUE(LoadExtension(
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 5925406..0231f8ab 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -29,6 +29,7 @@ #include "chrome/browser/ui/extensions/hosted_app_browser_controller.h" #include "chrome/browser/ui/global_error/global_error_service.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" +#include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/ui_features.h" @@ -38,9 +39,9 @@ #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/browser/ui/views/location_bar/star_view.h" #include "chrome/browser/ui/views/media_router/cast_toolbar_button.h" +#include "chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/toolbar/app_menu.h" #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" @@ -391,13 +392,13 @@ bool show_stay_in_chrome, bool show_remember_selection, IntentPickerResponse callback) { - IntentPickerView* intent_picker_view = location_bar()->intent_picker_view(); + PageActionIconView* intent_picker_view = + location_bar() + ->omnibox_page_action_icon_container_view() + ->GetPageActionIconView(PageActionIconType::kIntentPicker); if (intent_picker_view) { - if (!intent_picker_view->GetVisible()) { - intent_picker_view->SetVisible(true); - location_bar()->Layout(); - } - + if (!intent_picker_view->GetVisible()) + IntentPickerTabHelper::SetShouldShowIcon(GetWebContents(), true); IntentPickerBubbleView::ShowBubble( intent_picker_view, GetWebContents(), std::move(app_info), show_stay_in_chrome, show_remember_selection, std::move(callback));
diff --git a/chrome/browser/ui/webui/app_management/app_management.mojom b/chrome/browser/ui/webui/app_management/app_management.mojom index 9779a9e..a1c9e39b 100644 --- a/chrome/browser/ui/webui/app_management/app_management.mojom +++ b/chrome/browser/ui/webui/app_management/app_management.mojom
@@ -17,6 +17,7 @@ string? description; apps.mojom.OptionalBool is_pinned; + apps.mojom.OptionalBool is_policy_pinned; string? version; string? size; map<uint32, apps.mojom.Permission> permissions;
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc index 0766eed..3610d69e 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
@@ -197,6 +197,9 @@ app->is_pinned = shelf_delegate_.IsPinned(update.AppId()) ? OptionalBool::kTrue : OptionalBool::kFalse; + app->is_policy_pinned = shelf_delegate_.IsPolicyPinned(update.AppId()) + ? OptionalBool::kTrue + : OptionalBool::kFalse; #endif return app;
diff --git a/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.cc b/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.cc index 1070ace..cb7cfb7 100644 --- a/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.cc +++ b/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.cc
@@ -8,6 +8,7 @@ #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/shelf_types.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" +#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_util.h" #include "chrome/browser/ui/webui/app_management/app_management_page_handler.h" #include "chrome/services/app_service/public/mojom/types.mojom.h" @@ -27,6 +28,14 @@ return ChromeLauncherController::instance()->IsAppPinned(app_id); } +bool AppManagementShelfDelegate::IsPolicyPinned(const std::string& app_id) { + auto* shelf_item = + ChromeLauncherController::instance()->GetItem(ash::ShelfID(app_id)); + // If the app does not exist on the launcher, it has not been pinned by + // policy. + return shelf_item == nullptr ? false : shelf_item->pinned_by_policy; +} + void AppManagementShelfDelegate::SetPinned(const std::string& app_id, OptionalBool pinned) { if (pinned == OptionalBool::kTrue) {
diff --git a/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h b/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h index 40c3ba4..d692e29 100644 --- a/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h +++ b/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h
@@ -23,6 +23,8 @@ bool IsPinned(const std::string& app_id); void SetPinned(const std::string& app_id, apps::mojom::OptionalBool pinned); + bool IsPolicyPinned(const std::string& app_id); + private: // ash::ShelfModelObserver: void ShelfItemAdded(int index) override;
diff --git a/chrome/browser/ui/webui/app_management/app_management_ui.cc b/chrome/browser/ui/webui/app_management/app_management_ui.cc index d56ca35..5f321df6 100644 --- a/chrome/browser/ui/webui/app_management/app_management_ui.cc +++ b/chrome/browser/ui/webui/app_management/app_management_ui.cc
@@ -57,6 +57,10 @@ source->AddLocalizedString("title", IDS_APP_MANAGEMENT_TITLE); source->AddLocalizedString("uninstall", IDS_APP_MANAGEMENT_UNINSTALL); source->AddLocalizedString("version", IDS_APP_MANAGEMENT_VERSION); + source->AddLocalizedString("controlledByPolicy", + IDS_CONTROLLED_SETTING_POLICY); + source->AddLocalizedString("pinControlledByPolicy", + IDS_APP_MANAGEMENT_PIN_ENFORCED_BY_POLICY); source->AddResourcePath("app_management.mojom-lite.js", IDR_APP_MANAGEMENT_MOJO_LITE_JS);
diff --git a/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.cc b/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.cc index dc0f346..e87f533 100644 --- a/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.cc +++ b/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.cc
@@ -11,29 +11,60 @@ #include "base/macros.h" #include "base/values.h" #include "chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h" +#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" +#include "chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "chromeos/constants/chromeos_switches.h" +#include "chromeos/login/auth/saml_password_attributes.h" #include "components/prefs/pref_service.h" #include "components/user_manager/user_manager.h" namespace chromeos { +namespace { + +std::string GetPasswordChangeUrl(Profile* profile) { + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSamlPasswordChangeUrl)) { + return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kSamlPasswordChangeUrl); + } + + const policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager = + policy::UserPolicyManagerFactoryChromeOS::GetCloudPolicyManagerForProfile( + profile); + if (user_cloud_policy_manager) { + const enterprise_management::PolicyData* policy = + user_cloud_policy_manager->core()->store()->policy(); + if (policy->has_change_password_uri()) { + return policy->change_password_uri(); + } + } + + return SamlPasswordAttributes::LoadFromPrefs(profile->GetPrefs()) + .password_change_url(); +} + +} // namespace + InSessionPasswordChangeHandler::InSessionPasswordChangeHandler() = default; InSessionPasswordChangeHandler::~InSessionPasswordChangeHandler() = default; void InSessionPasswordChangeHandler::HandleInitialize( const base::ListValue* value) { - const Profile* profile = Profile::FromWebUI(web_ui()); + Profile* profile = Profile::FromWebUI(web_ui()); CHECK(profile->GetPrefs()->GetBoolean( prefs::kSamlInSessionPasswordChangeEnabled)); AllowJavascript(); base::Value params(base::Value::Type::DICTIONARY); - const std::string password_change_url = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kSamlPasswordChangeUrl); + const std::string password_change_url = GetPasswordChangeUrl(profile); + if (password_change_url.empty()) { + LOG(ERROR) << "Password change url is empty"; + return; + } params.SetKey("passwordChangeUrl", base::Value(password_change_url)); const user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile);
diff --git a/chrome/browser/web_applications/components/web_app_data_retriever.cc b/chrome/browser/web_applications/components/web_app_data_retriever.cc index a82d777..855ad55 100644 --- a/chrome/browser/web_applications/components/web_app_data_retriever.cc +++ b/chrome/browser/web_applications/components/web_app_data_retriever.cc
@@ -69,6 +69,7 @@ void WebAppDataRetriever::CheckInstallabilityAndRetrieveManifest( content::WebContents* web_contents, + bool bypass_service_worker_check, CheckInstallabilityCallback callback) { InstallableManager* installable_manager = InstallableManager::FromWebContents(web_contents); @@ -79,7 +80,8 @@ params.check_eligibility = true; params.valid_primary_icon = true; params.valid_manifest = true; - params.has_worker = true; + // Do not wait for a service worker if it doesn't exist. + params.has_worker = !bypass_service_worker_check; // Do not wait_for_worker. OnDidPerformInstallableCheck is always invoked. installable_manager->GetData( params, @@ -136,11 +138,12 @@ void WebAppDataRetriever::OnDidPerformInstallableCheck( CheckInstallabilityCallback callback, const InstallableData& data) { + DCHECK(data.manifest); DCHECK(data.manifest_url.is_valid() || data.manifest->IsEmpty()); const bool is_installable = data.errors.empty(); - std::move(callback).Run(*data.manifest, is_installable); + std::move(callback).Run(*data.manifest, data.valid_manifest, is_installable); } void WebAppDataRetriever::OnIconsDownloaded(GetIconsCallback callback,
diff --git a/chrome/browser/web_applications/components/web_app_data_retriever.h b/chrome/browser/web_applications/components/web_app_data_retriever.h index d7b5cfe..3cd60460 100644 --- a/chrome/browser/web_applications/components/web_app_data_retriever.h +++ b/chrome/browser/web_applications/components/web_app_data_retriever.h
@@ -40,7 +40,9 @@ base::OnceCallback<void(std::unique_ptr<WebApplicationInfo>)>; // |is_installable| is false if installability check failed. using CheckInstallabilityCallback = - base::OnceCallback<void(const blink::Manifest&, bool is_installable)>; + base::OnceCallback<void(const blink::Manifest&, + bool valid_manifest_for_web_app, + bool is_installable)>; // Returns empty map if error. using GetIconsCallback = base::OnceCallback<void(IconsMap)>; @@ -55,6 +57,7 @@ // Performs installability check and invokes |callback| with manifest. virtual void CheckInstallabilityAndRetrieveManifest( content::WebContents* web_contents, + bool bypass_service_worker_check, CheckInstallabilityCallback callback); // Downloads icons from |icon_urls|. Runs |callback| with a map of
diff --git a/chrome/browser/web_applications/components/web_app_data_retriever_unittest.cc b/chrome/browser/web_applications/components/web_app_data_retriever_unittest.cc index 69ac4a3..4f861f7 100644 --- a/chrome/browser/web_applications/components/web_app_data_retriever_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_data_retriever_unittest.cc
@@ -301,9 +301,10 @@ WebAppDataRetriever retriever; retriever.CheckInstallabilityAndRetrieveManifest( - web_contents(), + web_contents(), /*bypass_service_worker_check=*/false, base::BindLambdaForTesting( - [&](const blink::Manifest& result, bool is_installable) { + [&](const blink::Manifest& result, bool valid_manifest_for_web_app, + bool is_installable) { EXPECT_TRUE(is_installable); EXPECT_EQ(base::UTF8ToUTF16(manifest_short_name), @@ -334,13 +335,14 @@ WebAppDataRetriever retriever; retriever.CheckInstallabilityAndRetrieveManifest( - web_contents(), - base::BindLambdaForTesting( - [&](const blink::Manifest& result, bool is_installable) { - EXPECT_FALSE(is_installable); - callback_called = true; - run_loop.Quit(); - })); + web_contents(), /*bypass_service_worker_check=*/false, + base::BindLambdaForTesting([&](const blink::Manifest& result, + bool valid_manifest_for_web_app, + bool is_installable) { + EXPECT_FALSE(is_installable); + callback_called = true; + run_loop.Quit(); + })); run_loop.Run(); EXPECT_TRUE(callback_called);
diff --git a/chrome/browser/web_applications/test/test_data_retriever.cc b/chrome/browser/web_applications/test/test_data_retriever.cc index c99db08..641f938 100644 --- a/chrome/browser/web_applications/test/test_data_retriever.cc +++ b/chrome/browser/web_applications/test/test_data_retriever.cc
@@ -30,16 +30,18 @@ void TestDataRetriever::CheckInstallabilityAndRetrieveManifest( content::WebContents* web_contents, + bool bypass_service_worker_check, CheckInstallabilityCallback callback) { if (manifest_ == nullptr) { WebAppDataRetriever::CheckInstallabilityAndRetrieveManifest( - web_contents, std::move(callback)); + web_contents, bypass_service_worker_check, std::move(callback)); return; } base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::BindOnce(std::move(callback), *manifest_, is_installable_)); + base::BindOnce(std::move(callback), *manifest_, + /*valid_manifest_for_web_app=*/true, is_installable_)); } void TestDataRetriever::GetIcons(content::WebContents* web_contents,
diff --git a/chrome/browser/web_applications/test/test_data_retriever.h b/chrome/browser/web_applications/test/test_data_retriever.h index 7ed0e092..e835189 100644 --- a/chrome/browser/web_applications/test/test_data_retriever.h +++ b/chrome/browser/web_applications/test/test_data_retriever.h
@@ -28,6 +28,7 @@ GetWebApplicationInfoCallback callback) override; void CheckInstallabilityAndRetrieveManifest( content::WebContents* web_contents, + bool bypass_service_worker_check, CheckInstallabilityCallback callback) override; void GetIcons(content::WebContents* web_contents, const std::vector<GURL>& icon_urls,
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc index a471e30..c4d7cc6 100644 --- a/chrome/browser/web_applications/web_app_install_task.cc +++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -48,7 +48,7 @@ auto web_app_info = std::make_unique<WebApplicationInfo>(); data_retriever_->CheckInstallabilityAndRetrieveManifest( - web_contents(), + web_contents(), /*bypass_service_worker_check=*/false, base::BindOnce(&WebAppInstallTask::OnDidPerformInstallableCheck, base::Unretained(this), std::move(web_app_info), /*force_shortcut_app=*/false)); @@ -194,7 +194,7 @@ } data_retriever_->CheckInstallabilityAndRetrieveManifest( - web_contents(), + web_contents(), /*bypass_service_worker_check=*/false, base::BindOnce(&WebAppInstallTask::OnDidPerformInstallableCheck, base::Unretained(this), std::move(web_app_info), force_shortcut_app)); @@ -204,6 +204,7 @@ std::unique_ptr<WebApplicationInfo> web_app_info, bool force_shortcut_app, const blink::Manifest& manifest, + bool valid_manifest_for_web_app, bool is_installable) { if (ShouldStopInstall()) return;
diff --git a/chrome/browser/web_applications/web_app_install_task.h b/chrome/browser/web_applications/web_app_install_task.h index 80ab263d..6a0edd6 100644 --- a/chrome/browser/web_applications/web_app_install_task.h +++ b/chrome/browser/web_applications/web_app_install_task.h
@@ -105,6 +105,7 @@ std::unique_ptr<WebApplicationInfo> web_app_info, bool force_shortcut_app, const blink::Manifest& manifest, + bool valid_manifest_for_web_app, bool is_installable); void OnIconsRetrieved(std::unique_ptr<WebApplicationInfo> web_app_info, bool is_locally_installed,
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 5464f22..e5fe779b 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -248,6 +248,10 @@ base::FEATURE_ENABLED_BY_DEFAULT}; #endif +// If enabled, Drive will use FCM for its invalidations. +const base::Feature kDriveFcmInvalidations{"DriveFCMInvalidations", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Show the number of open incognito windows besides incognito icon on the // toolbar. const base::Feature kEnableIncognitoWindowCounter{
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index f261755..8aebd01 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -148,6 +148,9 @@ #endif COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kDriveFcmInvalidations; + +COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kEnableIncognitoWindowCounter; #if !defined(OS_ANDROID)
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 6a0e266..2bcc4d5 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -146,7 +146,6 @@ "//components/spellcheck:buildflags", "//components/startup_metric_utils/common:interfaces", "//components/subresource_filter/content/renderer", - "//components/thread_pool_util", "//components/translate/content/renderer", "//components/translate/core/common", "//components/translate/core/language_detection",
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS index 36707ddf..a8c1b1c 100644 --- a/chrome/renderer/DEPS +++ b/chrome/renderer/DEPS
@@ -41,7 +41,6 @@ "+components/subresource_filter/content/common", "+components/subresource_filter/content/renderer", "+components/subresource_filter/core/common/common_features.h", - "+components/thread_pool_util", "+components/translate/content/common", "+components/translate/content/renderer", "+components/translate/core/common",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 0d6ed14..2caf395c 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -90,7 +90,6 @@ #include "components/subresource_filter/content/renderer/subresource_filter_agent.h" #include "components/subresource_filter/content/renderer/unverified_ruleset_dealer.h" #include "components/subresource_filter/core/common/common_features.h" -#include "components/thread_pool_util/variations_util.h" #include "components/variations/net/variations_http_headers.h" #include "components/variations/variations_switches.h" #include "components/version_info/version_info.h" @@ -1546,11 +1545,6 @@ return FlashEmbedRewrite::RewriteFlashEmbedURL(url); } -std::unique_ptr<base::ThreadPool::InitParams> -ChromeContentRendererClient::GetThreadPoolInitParams() { - return thread_pool_util::GetThreadPoolInitParamsForRenderer(); -} - void ChromeContentRendererClient::CreateRendererService( service_manager::mojom::ServiceRequest service_request) { DCHECK(!service_binding_.is_bound());
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index d1d4e6f..a770be40 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -200,8 +200,6 @@ const std::string& header_name) override; bool ShouldEnforceWebRTCRoutingPreferences() override; GURL OverrideFlashEmbedWithHTML(const GURL& url) override; - std::unique_ptr<base::ThreadPool::InitParams> GetThreadPoolInitParams() - override; void CreateRendererService( service_manager::mojom::ServiceRequest service_request) override; std::unique_ptr<content::URLLoaderThrottleProvider>
diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc index 4d3b162..cde07a6 100644 --- a/chrome/service/service_process.cc +++ b/chrome/service/service_process.cc
@@ -25,7 +25,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/task/post_task.h" -#include "base/task/thread_pool/thread_group_params.h" #include "base/task/thread_pool/thread_pool.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -155,16 +154,18 @@ service_process_state_ = std::move(state); // Initialize ThreadPool. - constexpr int kMaxBackgroundThreads = 2; constexpr int kMaxForegroundThreads = 6; - constexpr base::TimeDelta kSuggestedReclaimTime = - base::TimeDelta::FromSeconds(30); + base::ThreadPool::InitParams thread_pool_init_params(kMaxForegroundThreads); +#if defined(OS_WIN) + // TODO(robliao): Remove DEPRECATED_COM_STA_IN_FOREGROUND_GROUP usage. + // WIP: https://chromium-review.googlesource.com/c/chromium/src/+/1271099 + thread_pool_init_params.common_thread_pool_environment = + base::ThreadPool::InitParams::CommonThreadPoolEnvironment:: + DEPRECATED_COM_STA_IN_FOREGROUND_GROUP; +#endif base::ThreadPool::Create("CloudPrintServiceProcess"); - base::ThreadPool::GetInstance()->Start( - {{kMaxBackgroundThreads, kSuggestedReclaimTime}, - {kMaxForegroundThreads, kSuggestedReclaimTime, - base::WorkerThreadBackwardCompatibility::INIT_COM_STA}}); + base::ThreadPool::GetInstance()->Start(thread_pool_init_params); // The NetworkChangeNotifier must be created after ThreadPool because it // posts tasks to it.
diff --git a/chrome/services/app_service/public/mojom/types.mojom b/chrome/services/app_service/public/mojom/types.mojom index 281117f8..471ac5b 100644 --- a/chrome/services/app_service/public/mojom/types.mojom +++ b/chrome/services/app_service/public/mojom/types.mojom
@@ -57,6 +57,8 @@ PermissionValueType value_type; // The semantics of value depends on the value_type. uint32 value; + // If the permission is managed by an enterprise policy. + bool is_managed; }; // The types of apps available in the registry.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 477c30c..e5970eb 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -892,6 +892,7 @@ "../browser/sessions/tab_restore_service_browsertest.cc", "../browser/sessions/tab_restore_service_load_waiter.cc", "../browser/sessions/tab_restore_service_load_waiter.h", + "../browser/signin/consistency_cookie_browsertest.cc", "../browser/site_isolation/chrome_site_per_process_browsertest.cc", "../browser/site_isolation/site_details_browsertest.cc", "../browser/ui/blocked_content/popup_tracker_browsertest.cc",
diff --git a/chrome/test/base/default_ash_event_generator_delegate.cc b/chrome/test/base/default_ash_event_generator_delegate.cc index 94c924ff..646300f8 100644 --- a/chrome/test/base/default_ash_event_generator_delegate.cc +++ b/chrome/test/base/default_ash_event_generator_delegate.cc
@@ -6,7 +6,6 @@ #include "ash/shell.h" #include "base/macros.h" -#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/test/default_event_generator_delegate.h" #include "ui/base/ui_base_features.h"
diff --git a/chrome/test/base/js2gtest.gni b/chrome/test/base/js2gtest.gni index 97e7cfd..157018bf 100644 --- a/chrome/test/base/js2gtest.gni +++ b/chrome/test/base/js2gtest.gni
@@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//v8/gni/snapshot_toolchain.gni") import("//v8/gni/v8.gni") -import("//v8/snapshot_toolchain.gni") # Variables: # test_type: One of 'webui', 'unit' or 'extension' indicating what
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index 95db497..54f25e2 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h
@@ -125,7 +125,6 @@ bool show_stay_in_chrome, bool show_remember_selection, IntentPickerResponse callback) override {} - void SetIntentPickerViewVisibility(bool visible) override {} #endif // !define(OS_ANDROID) autofill::SaveCardBubbleView* ShowSaveCreditCardBubble( content::WebContents* contents,
diff --git a/chrome/test/data/webui/app_management/app_management_browsertest.js b/chrome/test/data/webui/app_management/app_management_browsertest.js index 1b4db21a..e09303de 100644 --- a/chrome/test/data/webui/app_management/app_management_browsertest.js +++ b/chrome/test/data/webui/app_management/app_management_browsertest.js
@@ -139,3 +139,17 @@ TEST_F('AppManagementArcPermissionViewTest', 'All', function() { mocha.run(); }); + +function AppManagementManagedAppsTest() {} + +AppManagementManagedAppsTest.prototype = { + __proto__: AppManagementBrowserTest.prototype, + + extraLibraries: AppManagementBrowserTest.prototype.extraLibraries.concat([ + 'managed_apps_test.js', + ]), +}; + +TEST_F('AppManagementManagedAppsTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/app_management/arc_permission_view_test.js b/chrome/test/data/webui/app_management/arc_permission_view_test.js index df00817..6784ac2 100644 --- a/chrome/test/data/webui/app_management/arc_permission_view_test.js +++ b/chrome/test/data/webui/app_management/arc_permission_view_test.js
@@ -8,11 +8,6 @@ let arcPermissionView; let fakeHandler; - function getPermissionItemByPermissionType(permissionType) { - return arcPermissionView.root.querySelector( - '[permission-type=' + permissionType + ']'); - } - function expandPermissions() { arcPermissionView.root.querySelector('#subpermission-expand-row').click(); } @@ -22,20 +17,13 @@ arcPermissionView.app_, permissionType); } - function getPermissionToggleByType(permissionType) { - return arcPermissionView.root - .querySelector('[permission-type=' + permissionType + ']') - .root.querySelector('app-management-permission-toggle') - .root.querySelector('cr-toggle'); - } - async function clickPermissionToggle(permissionType) { - getPermissionToggleByType(permissionType).click(); + getPermissionCrToggleByType(arcPermissionView, permissionType).click(); await fakeHandler.$.flushForTesting(); } async function clickPermissionItem(permissionType) { - getPermissionItemByPermissionType(permissionType).click(); + getPermissionItemByType(arcPermissionView, permissionType).click(); await fakeHandler.$.flushForTesting(); } @@ -71,25 +59,30 @@ test('Permissions are hidden correctly', () => { expandPermissions(); - assertTrue(isHidden(getPermissionItemByPermissionType('MICROPHONE'))); - assertFalse(isHidden(getPermissionItemByPermissionType('LOCATION'))); - assertFalse(isHidden(getPermissionItemByPermissionType('CAMERA'))); + assertTrue( + isHidden(getPermissionItemByType(arcPermissionView, 'MICROPHONE'))); + assertFalse( + isHidden(getPermissionItemByType(arcPermissionView, 'LOCATION'))); + assertFalse(isHidden(getPermissionItemByType(arcPermissionView, 'CAMERA'))); }); test('Toggle works correctly', async () => { const checkPermissionToggle = async (permissionType) => { assertTrue(getPermissionBoolByType(permissionType)); - assertTrue(getPermissionToggleByType(permissionType).checked); + assertTrue(getPermissionCrToggleByType(arcPermissionView, permissionType) + .checked); // Toggle Off. await clickPermissionToggle(permissionType); assertFalse(getPermissionBoolByType(permissionType)); - assertFalse(getPermissionToggleByType(permissionType).checked); + assertFalse(getPermissionCrToggleByType(arcPermissionView, permissionType) + .checked); // Toggle On. await clickPermissionToggle(permissionType); assertTrue(getPermissionBoolByType(permissionType)); - assertTrue(getPermissionToggleByType(permissionType).checked); + assertTrue(getPermissionCrToggleByType(arcPermissionView, permissionType) + .checked); }; expandPermissions(); @@ -102,17 +95,20 @@ test('OnClick handler for permission item works correctly', async () => { const checkPermissionItemOnClick = async (permissionType) => { assertTrue(getPermissionBoolByType(permissionType)); - assertTrue(getPermissionToggleByType(permissionType).checked); + assertTrue(getPermissionCrToggleByType(arcPermissionView, permissionType) + .checked); // Toggle Off. await clickPermissionItem(permissionType); assertFalse(getPermissionBoolByType(permissionType)); - assertFalse(getPermissionToggleByType(permissionType).checked); + assertFalse(getPermissionCrToggleByType(arcPermissionView, permissionType) + .checked); // Toggle On. await clickPermissionItem(permissionType); assertTrue(getPermissionBoolByType(permissionType)); - assertTrue(getPermissionToggleByType(permissionType).checked); + assertTrue(getPermissionCrToggleByType(arcPermissionView, permissionType) + .checked); }; expandPermissions();
diff --git a/chrome/test/data/webui/app_management/managed_apps_test.js b/chrome/test/data/webui/app_management/managed_apps_test.js new file mode 100644 index 0000000..d78f054 --- /dev/null +++ b/chrome/test/data/webui/app_management/managed_apps_test.js
@@ -0,0 +1,71 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +suite('<app-management-managed-apps>', () => { + let appDetailView; + let fakeHandler; + + setup(async () => { + fakeHandler = setupFakeHandler(); + replaceStore(); + + // Create a Web app which is installed and pinned by policy + // and has location set to on and camera set to off by policy. + const permissionOptions = {}; + permissionOptions[PwaPermissionType.CONTENT_SETTINGS_TYPE_GEOLOCATION] = { + permissionValue: TriState.kAllow, + isManaged: true, + }; + permissionOptions[PwaPermissionType + .CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA] = { + permissionValue: TriState.kBlock, + isManaged: true + }; + const policyAppOptions = { + type: apps.mojom.AppType.kWeb, + isPinned: apps.mojom.OptionalBool.kTrue, + isPolicyPinned: apps.mojom.OptionalBool.kTrue, + installSource: apps.mojom.InstallSource.kPolicy, + permissions: app_management.FakePageHandler.createWebPermissions( + permissionOptions), + }; + const app = await fakeHandler.addApp(null, policyAppOptions); + // Select created app. + app_management.Store.getInstance().dispatch( + app_management.actions.changePage(PageType.DETAIL, app.id)); + appDetailView = + document.createElement('app-management-pwa-permission-view'); + replaceBody(appDetailView); + await PolymerTest.flushTasks(); + }); + + test('Uninstall button affected by policy', () => { + const uninstallWrapper = + appDetailView.$$('app-management-permission-view-header') + .$$('#uninstall-wrapper'); + expectTrue(!!uninstallWrapper.querySelector('#policy-indicator')); + }); + + test('Permission toggles affected by policy', () => { + function checkToggle(permissionType, policyAffected) { + const permissionToggle = + getPermissionToggleByType(appDetailView, permissionType); + expectTrue(permissionToggle.$$('cr-toggle').disabled === policyAffected); + expectTrue(!!permissionToggle.$$('#policy-indicator') === policyAffected); + } + checkToggle('CONTENT_SETTINGS_TYPE_NOTIFICATIONS', false); + checkToggle('CONTENT_SETTINGS_TYPE_GEOLOCATION', true); + checkToggle('CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA', true); + checkToggle('CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC', false); + }); + + test('Pin to shelf toggle effected by policy', () => { + const shelfSwitch = + appDetailView.$$('app-management-metadata-view').$$('#shelf-switch'); + expectTrue(!!shelfSwitch.querySelector('#policy-indicator')); + expectTrue(shelfSwitch.querySelector('#pin-to-shelf-toggle').disabled); + }); +});
diff --git a/chrome/test/data/webui/app_management/test_util.js b/chrome/test/data/webui/app_management/test_util.js index 32e3440..2a7b30a 100644 --- a/chrome/test/data/webui/app_management/test_util.js +++ b/chrome/test/data/webui/app_management/test_util.js
@@ -79,3 +79,32 @@ window.dispatchEvent(new CustomEvent('location-changed')); await PolymerTest.flushTasks(); } + +/** + * @param {Element} element + * @param {Object} permissionType + * @return {Element} + */ +function getPermissionItemByType(view, permissionType) { + return view.root.querySelector('[permission-type=' + permissionType + ']'); +} + +/** + * @param {Element} element + * @param {Object} permissionType + * @return {Element} + */ +function getPermissionToggleByType(view, permissionType) { + return getPermissionItemByType(view, permissionType) + .root.querySelector('app-management-permission-toggle'); +} + +/** + * @param {Element} element + * @param {Object} permissionType + * @return {Element} + */ +function getPermissionCrToggleByType(view, permissionType) { + return getPermissionToggleByType(view, permissionType) + .root.querySelector('cr-toggle'); +}
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc index 0578416..ef1a9d4 100644 --- a/chrome/updater/updater.cc +++ b/chrome/updater/updater.cc
@@ -21,7 +21,6 @@ #include "base/run_loop.h" #include "base/stl_util.h" #include "base/task/post_task.h" -#include "base/task/thread_pool/initialization_util.h" #include "base/task/thread_pool/thread_pool.h" #include "base/task_runner.h" #include "base/threading/platform_thread.h" @@ -51,16 +50,7 @@ 0x54, 0xf9, 0x56, 0xd3, 0xe7, 0x88, 0xba, 0x8c}; void ThreadPoolStart() { - base::ThreadPool::Create("Updater"); - const auto thread_pool_init_params = - std::make_unique<base::ThreadPool::InitParams>( - base::ThreadGroupParams( - base::RecommendedMaxNumberOfThreadsInThreadGroup(3, 8, 0.1, 0), - base::TimeDelta::FromSeconds(30)), - base::ThreadGroupParams( - base::RecommendedMaxNumberOfThreadsInThreadGroup(8, 32, 0.3, 0), - base::TimeDelta::FromSeconds(30))); - base::ThreadPool::GetInstance()->Start(*thread_pool_init_params); + base::ThreadPool::CreateAndStartWithDefaultParams("Updater"); } void ThreadPoolStop() {
diff --git a/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.cc b/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.cc index 388cfe0f..256a3a5 100644 --- a/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.cc +++ b/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.cc
@@ -37,38 +37,43 @@ } ExtensionFunction::ResponseAction -AccessibilityPrivateSetFocusRingFunction::Run() { +AccessibilityPrivateSetFocusRingsFunction::Run() { + std::unique_ptr<accessibility_private::SetFocusRings::Params> params( + accessibility_private::SetFocusRings::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + auto* accessibility_manager = chromecast::shell::CastBrowserProcess::GetInstance() ->accessibility_manager(); - std::unique_ptr<accessibility_private::SetFocusRing::Params> params( - accessibility_private::SetFocusRing::Params::Create(*args_)); - EXTENSION_FUNCTION_VALIDATE(params); + for (const accessibility_private::FocusRingInfo& focus_ring_info : + params->focus_rings) { + std::vector<gfx::Rect> rects; + for (const accessibility_private::ScreenRect& rect : + focus_ring_info.rects) { + rects.push_back(gfx::Rect(rect.left, rect.top, rect.width, rect.height)); + } - std::vector<gfx::Rect> rects; - for (const accessibility_private::ScreenRect& rect : params->rects) { - rects.push_back(gfx::Rect(rect.left, rect.top, rect.width, rect.height)); - } + if (focus_ring_info.color.length() > 0) { + SkColor color; + if (!extensions::image_util::ParseHexColorString(focus_ring_info.color, + &color)) + return RespondNow(Error("Could not parse hex color")); + accessibility_manager->SetFocusRingColor(color); + } else { + accessibility_manager->ResetFocusRingColor(); + } - if (params->color) { - SkColor color; - if (!extensions::image_util::ParseHexColorString(*(params->color), &color)) - return RespondNow(Error("Could not parse hex color")); - accessibility_manager->SetFocusRingColor(color); - } else { - accessibility_manager->ResetFocusRingColor(); - } + // Move the visible focus ring to cover all of these rects. + accessibility_manager->SetFocusRing( + rects, chromecast::FocusRingBehavior::PERSIST_FOCUS_RING); - // Move the visible focus ring to cover all of these rects. - accessibility_manager->SetFocusRing( - rects, chromecast::FocusRingBehavior::PERSIST_FOCUS_RING); - - // Also update the touch exploration controller so that synthesized - // touch events are anchored within the focused object. - if (!rects.empty()) { - accessibility_manager->SetTouchAccessibilityAnchorPoint( - rects[0].CenterPoint()); + // Also update the touch exploration controller so that synthesized + // touch events are anchored within the focused object. + if (!rects.empty()) { + accessibility_manager->SetTouchAccessibilityAnchorPoint( + rects[0].CenterPoint()); + } } return RespondNow(NoArguments());
diff --git a/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h b/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h index 0e2ae51..acec0be 100644 --- a/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h +++ b/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h
@@ -24,11 +24,11 @@ }; // API function that sets the location of the accessibility focus ring. -class AccessibilityPrivateSetFocusRingFunction +class AccessibilityPrivateSetFocusRingsFunction : public UIThreadExtensionFunction { - ~AccessibilityPrivateSetFocusRingFunction() override {} + ~AccessibilityPrivateSetFocusRingsFunction() override {} ResponseAction Run() override; - DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setFocusRing", + DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setFocusRings", ACCESSIBILITY_PRIVATE_SETFOCUSRING) };
diff --git a/chromecast/common/extensions_api/accessibility_private.json b/chromecast/common/extensions_api/accessibility_private.json index 0bee8ca..a337c8a 100644 --- a/chromecast/common/extensions_api/accessibility_private.json +++ b/chromecast/common/extensions_api/accessibility_private.json
@@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -82,10 +82,85 @@ "description": "Contains all active modifiers." } } + }, + { + "id": "SyntheticMouseEventType", + "type": "string", + "description": "The type of event to send", + "enum": ["press", "release", "drag", "move", "enter", "exit"] + }, + { + "id": "SyntheticMouseEvent", + "type": "object", + "properties": { + "type": {"$ref": "SyntheticMouseEventType"}, + "x": {"type": "integer", "description": "X coordinate for mouse event in global screen coordinates"}, + "y": {"type": "integer", "description": "Y coordinate for mouse event in global screen coordinates"} + } + }, + { + "id": "SelectToSpeakState", + "type": "string", + "description": "The state of the Select-to-Speak extension", + "enum": ["selecting", "speaking", "inactive"] + }, + { + "id": "FocusType", + "type": "string", + "description": "The type of visual appearance for the focus ring.", + "enum": ["glow", "solid", "dashed"] + }, + { + "id": "FocusRingInfo", + "type": "object", + "properties": { + "rects": { + "type": "array", + "items": { "$ref": "ScreenRect" }, + "description": "Array of rectangles to draw the accessibility focus ring around." + }, + "type": { + "$ref": "FocusType", + "description": "The FocusType for the ring." + }, + "color": { + "type": "string", + "description": "A CSS-style color string (e.g. #3F8213) that describes the primary color of the focus ring." + }, + "secondaryColor": { + "type": "string", + "description": "A CSS-style color string (e.g. #3F82E4) that describes the secondary color of the focus ring, if there is one.", + "optional": true + }, + "id": { + "type": "string", + "description": "An identifier for this focus ring, unique within the extension.", + "optional": true + } + } } ], "functions": [ { + "name": "getBatteryDescription", + "type": "function", + "description": "Called to request battery status from Chrome OS system.", + "parameters": [ + { + "name": "callback", + "type": "function", + "description": "Returns battery description as a string.", + "parameters": [ + { + "name": "batteryDescription", + "type": "string" + } + ] + } + ], + "platforms": ["chromeos"] + }, + { "name": "setNativeAccessibilityEnabled", "type": "function", "description": "Enables or disables native accessibility support. Once disabled, it is up to the calling extension to provide accessibility for web contents.", @@ -98,21 +173,15 @@ ] }, { - "name": "setFocusRing", + "name": "setFocusRings", "type": "function", - "description": "Sets the bounds of the accessibility focus ring.", + "description": "Sets the given accessibility focus rings for this extension.", "parameters": [ { - "name": "rects", + "name": "focusRings", "type": "array", - "items": { "$ref": "ScreenRect" }, - "description": "Array of rectangles to draw the accessibility focus ring around." - }, - { - "name": "color", - "type": "string", - "description": "CSS-style hex color string beginning with # like #FF9982 or #EEE.", - "optional": true + "items": { "$ref": "FocusRingInfo" }, + "description": "Array of focus rings to draw." } ] }, @@ -183,6 +252,41 @@ "platforms": ["chromeos"] }, { + "name": "setSwitchAccessMenuState", + "type": "function", + "description": "Shows or hides the Switch Access menu. If shown, it is at the indicated location.", + "parameters": [ + { + "name": "show", + "type": "boolean", + "description": "If true, show the menu. If false, hide the menu." + }, + { + "name": "element_bounds", + "$ref": "ScreenRect", + "description": "Position of an element, in global screen coordinates, to place the menu next to." + }, + { + "name": "item_count", + "type": "integer", + "description": "The number of items that need to be shown in the menu." + } + ], + "platforms": ["chromeos"] + }, + { + "name": "forwardKeyEventsToSwitchAccess", + "type": "function", + "description": "When enabled, forwards key events to the Switch Access extension", + "parameters": [ + { + "name": "shouldForward", + "type": "boolean" + } + ], + "platforms": ["chromeos"] + }, + { "name": "setNativeChromeVoxArcSupportForCurrentApp", "type": "function", "description": "Sets current ARC app to use native ARC support.", @@ -207,6 +311,63 @@ } ], "platforms": ["chromeos"] + }, + { + "name": "enableChromeVoxMouseEvents", + "type": "function", + "description": "Enables or disables mouse events in ChromeVox.", + "parameters": [ + { + "name": "enabled", + "type": "boolean", + "description": "True if ChromeVox should receive mouse events." + } + ], + "platforms": ["chromeos"] + }, + { + "name": "sendSyntheticMouseEvent", + "type": "function", + "description": "Sends a fabricated mouse event.", + "parameters": [ + { + "name": "mouseEvent", + "$ref": "SyntheticMouseEvent", + "description": "The event to send." + } + ], + "platforms": ["chromeos"] + }, + { + "name": "onSelectToSpeakStateChanged", + "type": "function", + "description": "Called by the Select-to-Speak extension when Select-to-Speak has changed states, between selecting with the mouse, speaking, and inactive.", + "parameters": [ + { + "name": "state", + "$ref": "SelectToSpeakState" + } + ], + "platforms": ["chromeos"] + }, + { + "name": "toggleDictation", + "type": "function", + "description": "Toggles dictation between active and inactive states.", + "parameters": [], + "platforms": ["chromeos"] + }, + { + "name": "setVirtualKeyboardVisible", + "type": "function", + "description": "Shows or hides the virtual keyboard.", + "parameters": [ + { + "name": "isVisible", + "type": "boolean" + } + ], + "platforms": ["chromeos"] } ], "events": [ @@ -235,8 +396,29 @@ { "name": "onTwoFingerTouchStop", "type": "function", - "description": "Fired when the user is no longer holding down two fingers (including releasing one, holding down three, or moving them).", + "description": "Fired when the user is no longer holding down two fingers (including releasing one, holding down three, or moving them).", "parameters": [] + }, + { + "name": "onSelectToSpeakStateChangeRequested", + "type": "function", + "description": "Called when Chrome OS wants to change the Select-to-Speak state, between selecting with the mouse, speaking, and inactive.", + "parameters": [], + "platforms": ["chromeos"] + }, + { + "name": "onAnnounceForAccessibility", + "type": "function", + "description": "Called when an internal component within accessibility wants to force speech output for an accessibility extension. Do not use without approval from accessibility owners.", + "parameters": [ + { + "name": "announceText", + "type": "array", + "items": { "type": "string" }, + "description": "Text to be announced." + } + ], + "platforms": ["chromeos"] } ] }
diff --git a/chromeos/dbus/concierge_client.cc b/chromeos/dbus/concierge_client.cc index d251b587..b1f43c9 100644 --- a/chromeos/dbus/concierge_client.cc +++ b/chromeos/dbus/concierge_client.cc
@@ -24,20 +24,30 @@ ~ConciergeClientImpl() override = default; - // ConciergeClient override. - void AddObserver(Observer* observer) override { - observer_list_.AddObserver(observer); + void AddContainerObserver(ContainerObserver* observer) override { + container_observer_list_.AddObserver(observer); } - // ConciergeClient override. - void RemoveObserver(Observer* observer) override { - observer_list_.RemoveObserver(observer); + void RemoveContainerObserver(ContainerObserver* observer) override { + container_observer_list_.RemoveObserver(observer); + } + + void AddDiskImageObserver(DiskImageObserver* observer) override { + disk_image_observer_list_.AddObserver(observer); + } + + void RemoveDiskImageObserver(DiskImageObserver* observer) override { + disk_image_observer_list_.RemoveObserver(observer); } bool IsContainerStartupFailedSignalConnected() override { return is_container_startup_failed_signal_connected_; } + bool IsDiskImageProgressSignalConnected() override { + return is_disk_import_progress_signal_connected_; + } + void CreateDiskImage( const vm_tools::concierge::CreateDiskImageRequest& request, DBusMethodCallback<vm_tools::concierge::CreateDiskImageResponse> callback) @@ -82,6 +92,53 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } + void ImportDiskImage( + base::ScopedFD fd, + const vm_tools::concierge::ImportDiskImageRequest& request, + DBusMethodCallback<vm_tools::concierge::ImportDiskImageResponse> callback) + override { + dbus::MethodCall method_call(vm_tools::concierge::kVmConciergeInterface, + vm_tools::concierge::kImportDiskImageMethod); + dbus::MessageWriter writer(&method_call); + + if (!writer.AppendProtoAsArrayOfBytes(request)) { + LOG(ERROR) << "Failed to encode ImportDiskImageRequest protobuf"; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), base::nullopt)); + return; + } + + writer.AppendFileDescriptor(fd.get()); + + concierge_proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::BindOnce(&ConciergeClientImpl::OnDBusProtoResponse< + vm_tools::concierge::ImportDiskImageResponse>, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + } + + void DiskImageStatus( + const vm_tools::concierge::DiskImageStatusRequest& request, + DBusMethodCallback<vm_tools::concierge::DiskImageStatusResponse> callback) + override { + dbus::MethodCall method_call(vm_tools::concierge::kVmConciergeInterface, + vm_tools::concierge::kDiskImageStatusMethod); + dbus::MessageWriter writer(&method_call); + + if (!writer.AppendProtoAsArrayOfBytes(request)) { + LOG(ERROR) << "Failed to encode DiskImageStatusRequest protobuf"; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), base::nullopt)); + return; + } + + concierge_proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::BindOnce(&ConciergeClientImpl::OnDBusProtoResponse< + vm_tools::concierge::DiskImageStatusResponse>, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + } + void ListVmDisks(const vm_tools::concierge::ListVmDisksRequest& request, DBusMethodCallback<vm_tools::concierge::ListVmDisksResponse> callback) override { @@ -262,6 +319,13 @@ weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&ConciergeClientImpl::OnSignalConnected, weak_ptr_factory_.GetWeakPtr())); + concierge_proxy_->ConnectToSignal( + vm_tools::concierge::kVmConciergeInterface, + vm_tools::concierge::kDiskImageProgressSignal, + base::BindRepeating(&ConciergeClientImpl::OnDiskImageProgress, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&ConciergeClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); } private: @@ -294,29 +358,54 @@ LOG(ERROR) << "Failed to parse proto from DBus Signal"; return; } - // Tell our Observers. - for (auto& observer : observer_list_) { + + for (auto& observer : container_observer_list_) { observer.OnContainerStartupFailed(container_startup_failed_signal); } } + void OnDiskImageProgress(dbus::Signal* signal) { + DCHECK_EQ(signal->GetInterface(), + vm_tools::concierge::kVmConciergeInterface); + DCHECK_EQ(signal->GetMember(), + vm_tools::concierge::kDiskImageProgressSignal); + + vm_tools::concierge::DiskImageStatusResponse + disk_image_status_response_signal; + dbus::MessageReader reader(signal); + if (!reader.PopArrayOfBytesAsProto(&disk_image_status_response_signal)) { + LOG(ERROR) << "Failed to parse proto from DBus Signal"; + return; + } + + for (auto& observer : disk_image_observer_list_) { + observer.OnDiskImageProgress(disk_image_status_response_signal); + } + } + void OnSignalConnected(const std::string& interface_name, const std::string& signal_name, bool is_connected) { DCHECK_EQ(interface_name, vm_tools::concierge::kVmConciergeInterface); - DCHECK_EQ(signal_name, vm_tools::concierge::kContainerStartupFailedSignal); - if (!is_connected) { - LOG(ERROR) << "Failed to connect to Signal. Async StartLxdContainer will " - "not work"; + if (!is_connected) + LOG(ERROR) << "Failed to connect to signal: " << signal_name; + + if (signal_name == vm_tools::concierge::kContainerStartupFailedSignal) { + is_container_startup_failed_signal_connected_ = is_connected; + } else if (signal_name == vm_tools::concierge::kDiskImageProgressSignal) { + is_disk_import_progress_signal_connected_ = is_connected; + } else { + NOTREACHED(); } - is_container_startup_failed_signal_connected_ = is_connected; } dbus::ObjectProxy* concierge_proxy_ = nullptr; - base::ObserverList<Observer>::Unchecked observer_list_; + base::ObserverList<ContainerObserver>::Unchecked container_observer_list_; + base::ObserverList<DiskImageObserver>::Unchecked disk_image_observer_list_; bool is_container_startup_failed_signal_connected_ = false; + bool is_disk_import_progress_signal_connected_ = false; // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed.
diff --git a/chromeos/dbus/concierge_client.h b/chromeos/dbus/concierge_client.h index f332016..9ec5bcdf 100644 --- a/chromeos/dbus/concierge_client.h +++ b/chromeos/dbus/concierge_client.h
@@ -17,10 +17,12 @@ namespace chromeos { // ConciergeClient is used to communicate with Concierge, which is used to -// start and stop VMs. +// start and stop VMs, as well as for disk image management. class COMPONENT_EXPORT(CHROMEOS_DBUS) ConciergeClient : public DBusClient { public: - class Observer { + // Used for observing all concierge signals related to running + // containers (e.g. startup). + class ContainerObserver { public: // OnContainerStartupFailed is signaled by Concierge after the long-running // container startup process's failure is detected. Note the signal protocol @@ -29,19 +31,41 @@ const vm_tools::concierge::ContainerStartedSignal& signal) = 0; protected: - virtual ~Observer() = default; + virtual ~ContainerObserver() = default; }; - // Adds an observer. - virtual void AddObserver(Observer* observer) = 0; + // Used for observing all concierge signals related to VM disk image + // operations, e.g. importing. + class DiskImageObserver { + public: + // OnDiskImageProgress is signaled by Concierge after an ImportDiskImage + // call has been made and an update about the status of the import + // is available. + virtual void OnDiskImageProgress( + const vm_tools::concierge::DiskImageStatusResponse& signal) = 0; + protected: + virtual ~DiskImageObserver() = default; + }; + + // Adds an observer for container startup. + virtual void AddContainerObserver(ContainerObserver* observer) = 0; // Removes an observer if added. - virtual void RemoveObserver(Observer* observer) = 0; + virtual void RemoveContainerObserver(ContainerObserver* observer) = 0; + + // Adds an observer for disk image operations. + virtual void AddDiskImageObserver(DiskImageObserver* observer) = 0; + // Adds an observer for disk image operations. + virtual void RemoveDiskImageObserver(DiskImageObserver* observer) = 0; // IsContainerStartupFailedSignalConnected must return true before // StartContainer is called. virtual bool IsContainerStartupFailedSignalConnected() = 0; + // IsDiskImageProgressSignalConnected must return true before + // ImportDiskImage is called. + virtual bool IsDiskImageProgressSignalConnected() = 0; + // Creates a disk image for the Termina VM. // |callback| is called after the method call finishes. virtual void CreateDiskImage( @@ -56,6 +80,21 @@ DBusMethodCallback<vm_tools::concierge::DestroyDiskImageResponse> callback) = 0; + // Import a VM disk image + // |callback| is called after the method call finishes. + virtual void ImportDiskImage( + base::ScopedFD fd, + const vm_tools::concierge::ImportDiskImageRequest& request, + DBusMethodCallback<vm_tools::concierge::ImportDiskImageResponse> + callback) = 0; + + // Retrieve the status of a disk image operation + // |callback| is called after the method call finishes. + virtual void DiskImageStatus( + const vm_tools::concierge::DiskImageStatusRequest& request, + DBusMethodCallback<vm_tools::concierge::DiskImageStatusResponse> + callback) = 0; + // Lists the Termina VMs. // |callback| is called after the method call finishes. virtual void ListVmDisks(
diff --git a/chromeos/dbus/fake_concierge_client.cc b/chromeos/dbus/fake_concierge_client.cc index d6311eb..d05e7c5 100644 --- a/chromeos/dbus/fake_concierge_client.cc +++ b/chromeos/dbus/fake_concierge_client.cc
@@ -18,21 +18,30 @@ } FakeConciergeClient::~FakeConciergeClient() = default; -// ConciergeClient override. -void FakeConciergeClient::AddObserver(Observer* observer) { - observer_list_.AddObserver(observer); +void FakeConciergeClient::AddContainerObserver(ContainerObserver* observer) { + container_observer_list_.AddObserver(observer); } -// ConciergeClient override. -void FakeConciergeClient::RemoveObserver(Observer* observer) { - observer_list_.RemoveObserver(observer); +void FakeConciergeClient::RemoveContainerObserver(ContainerObserver* observer) { + container_observer_list_.RemoveObserver(observer); } -// ConciergeClient override. +void FakeConciergeClient::AddDiskImageObserver(DiskImageObserver* observer) { + disk_image_observer_list_.AddObserver(observer); +} + +void FakeConciergeClient::RemoveDiskImageObserver(DiskImageObserver* observer) { + disk_image_observer_list_.RemoveObserver(observer); +} + bool FakeConciergeClient::IsContainerStartupFailedSignalConnected() { return is_container_startup_failed_signal_connected_; } +bool FakeConciergeClient::IsDiskImageProgressSignalConnected() { + return is_disk_image_progress_signal_connected_; +} + void FakeConciergeClient::CreateDiskImage( const vm_tools::concierge::CreateDiskImageRequest& request, DBusMethodCallback<vm_tools::concierge::CreateDiskImageResponse> callback) { @@ -52,6 +61,43 @@ base::BindOnce(std::move(callback), destroy_disk_image_response_)); } +void FakeConciergeClient::ImportDiskImage( + base::ScopedFD fd, + const vm_tools::concierge::ImportDiskImageRequest& request, + DBusMethodCallback<vm_tools::concierge::ImportDiskImageResponse> callback) { + import_disk_image_called_ = true; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&FakeConciergeClient::FakeImportCallbacks, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void FakeConciergeClient::FakeImportCallbacks( + DBusMethodCallback<vm_tools::concierge::ImportDiskImageResponse> callback) { + std::move(callback).Run(import_disk_image_response_); + // Trigger DiskImageStatus signals. + for (auto const& signal : disk_image_status_signals_) { + OnDiskImageProgress(signal); + } +} + +void FakeConciergeClient::OnDiskImageProgress( + const vm_tools::concierge::DiskImageStatusResponse& signal) { + for (auto& observer : disk_image_observer_list_) { + observer.OnDiskImageProgress(signal); + } +} + +void FakeConciergeClient::DiskImageStatus( + const vm_tools::concierge::DiskImageStatusRequest& request, + DBusMethodCallback<vm_tools::concierge::DiskImageStatusResponse> callback) { + disk_image_status_called_ = true; + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), disk_image_status_response_)); +} + void FakeConciergeClient::ListVmDisks( const vm_tools::concierge::ListVmDisksRequest& request, DBusMethodCallback<vm_tools::concierge::ListVmDisksResponse> callback) {
diff --git a/chromeos/dbus/fake_concierge_client.h b/chromeos/dbus/fake_concierge_client.h index 5aa7d162..9b4dee94 100644 --- a/chromeos/dbus/fake_concierge_client.h +++ b/chromeos/dbus/fake_concierge_client.h
@@ -19,16 +19,22 @@ FakeConciergeClient(); ~FakeConciergeClient() override; - // Adds an observer. - void AddObserver(Observer* observer) override; + void AddContainerObserver(ContainerObserver* observer) override; - // Removes an observer if added. - void RemoveObserver(Observer* observer) override; + void RemoveContainerObserver(ContainerObserver* observer) override; + + void AddDiskImageObserver(DiskImageObserver* observer) override; + + void RemoveDiskImageObserver(DiskImageObserver* observer) override; // IsContainerStartupFailedSignalConnected must return true before // StartLxdContainer is called. bool IsContainerStartupFailedSignalConnected() override; + // IsDiskImageProgressSignalConnected must return true before + // ImportDiskImage is called. + bool IsDiskImageProgressSignalConnected() override; + // Fake version of the method that creates a disk image for the Termina VM. // Sets create_disk_image_called_. |callback| is called after the method // call finishes. @@ -45,6 +51,23 @@ DBusMethodCallback<vm_tools::concierge::DestroyDiskImageResponse> callback) override; + // Fake version of the method that imports a VM disk image. + // This function can fake a series of callbacks. It always first runs the + // callback provided as an argument, and then optionally a series of fake + // status signal callbacks (use set_disk_image_status_signals to set up). + void ImportDiskImage( + base::ScopedFD fd, + const vm_tools::concierge::ImportDiskImageRequest& request, + DBusMethodCallback<vm_tools::concierge::ImportDiskImageResponse> callback) + override; + + // Fake version of the method that returns the status of a disk image + // operation. + void DiskImageStatus( + const vm_tools::concierge::DiskImageStatusRequest& request, + DBusMethodCallback<vm_tools::concierge::DiskImageStatusResponse> callback) + override; + // Fake version of the method that lists Termina VM disks. Sets // list_vm_disks_called_. |callback| is called after the method call // finishes. @@ -105,6 +128,8 @@ bool create_disk_image_called() const { return create_disk_image_called_; } // Indicates whether DestroyDiskImage has been called bool destroy_disk_image_called() const { return destroy_disk_image_called_; } + // Indicates whether ImportDiskImage has been called + bool import_disk_image_called() const { return import_disk_image_called_; } // Indicates whether ListVmDisks has been called bool list_vm_disks_called() const { return list_vm_disks_called_; } // Indicates whether StartTerminaVm has been called @@ -125,6 +150,9 @@ void set_container_startup_failed_signal_connected(bool connected) { is_container_startup_failed_signal_connected_ = connected; } + void set_disk_image_progress_signal_connected(bool connected) { + is_disk_image_progress_signal_connected_ = connected; + } void set_create_disk_image_response( const vm_tools::concierge::CreateDiskImageResponse& @@ -136,6 +164,16 @@ destroy_disk_image_response) { destroy_disk_image_response_ = destroy_disk_image_response; } + void set_import_disk_image_response( + const vm_tools::concierge::ImportDiskImageResponse& + import_disk_image_response) { + import_disk_image_response_ = import_disk_image_response; + } + void set_disk_image_status_response( + const vm_tools::concierge::DiskImageStatusResponse& + disk_image_status_response) { + disk_image_status_response_ = disk_image_status_response; + } void set_list_vm_disks_response( const vm_tools::concierge::ListVmDisksResponse& list_vm_disks_response) { list_vm_disks_response_ = list_vm_disks_response; @@ -169,6 +207,12 @@ list_usb_devices_response_ = list_usb_devices_response; } + void set_disk_image_status_signals( + const std::vector<vm_tools::concierge::DiskImageStatusResponse>& + disk_image_status_signals) { + disk_image_status_signals_ = disk_image_status_signals; + } + protected: void Init(dbus::Bus* bus) override {} @@ -178,8 +222,18 @@ void NotifyTremplinStarted( const vm_tools::cicerone::TremplinStartedSignal& signal); + // Fakes a sequence of progress callbacks. + void FakeImportCallbacks( + DBusMethodCallback<vm_tools::concierge::ImportDiskImageResponse> + callback); + // Notifies observers with a DiskImageStatus signal. + void OnDiskImageProgress( + const vm_tools::concierge::DiskImageStatusResponse& signal); + bool create_disk_image_called_ = false; bool destroy_disk_image_called_ = false; + bool import_disk_image_called_ = false; + bool disk_image_status_called_ = false; bool list_vm_disks_called_ = false; bool start_termina_vm_called_ = false; bool stop_vm_called_ = false; @@ -188,9 +242,12 @@ bool detach_usb_device_called_ = false; bool list_usb_devices_called_ = false; bool is_container_startup_failed_signal_connected_ = true; + bool is_disk_image_progress_signal_connected_ = true; vm_tools::concierge::CreateDiskImageResponse create_disk_image_response_; vm_tools::concierge::DestroyDiskImageResponse destroy_disk_image_response_; + vm_tools::concierge::ImportDiskImageResponse import_disk_image_response_; + vm_tools::concierge::DiskImageStatusResponse disk_image_status_response_; vm_tools::concierge::ListVmDisksResponse list_vm_disks_response_; vm_tools::concierge::StartVmResponse start_vm_response_; vm_tools::concierge::StopVmResponse stop_vm_response_; @@ -199,7 +256,13 @@ vm_tools::concierge::DetachUsbDeviceResponse detach_usb_device_response_; vm_tools::concierge::ListUsbDeviceResponse list_usb_devices_response_; - base::ObserverList<Observer>::Unchecked observer_list_; + // Can be set to fake a series of disk image status signals. + std::vector<vm_tools::concierge::DiskImageStatusResponse> + disk_image_status_signals_; + + base::ObserverList<ContainerObserver>::Unchecked container_observer_list_; + + base::ObserverList<DiskImageObserver>::Unchecked disk_image_observer_list_; // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed.
diff --git a/chromeos/services/device_sync/proto/BUILD.gn b/chromeos/services/device_sync/proto/BUILD.gn index 788020dc..68b728b 100644 --- a/chromeos/services/device_sync/proto/BUILD.gn +++ b/chromeos/services/device_sync/proto/BUILD.gn
@@ -7,6 +7,7 @@ proto_library("proto") { sources = [ "cryptauth_api.proto", + "cryptauth_better_together_device_metadata.proto", "cryptauth_better_together_feature_metadata.proto", "cryptauth_client_app_metadata.proto", "cryptauth_common.proto",
diff --git a/chromeos/services/device_sync/proto/cryptauth_better_together_device_metadata.proto b/chromeos/services/device_sync/proto/cryptauth_better_together_device_metadata.proto new file mode 100644 index 0000000..77e8a8d --- /dev/null +++ b/chromeos/services/device_sync/proto/cryptauth_better_together_device_metadata.proto
@@ -0,0 +1,38 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto3"; + +package cryptauthv2; + +option optimize_for = LITE_RUNTIME; + +// A seed used to feed an EID BLE advertisement for some time period. +// Next ID: 4 +message BeaconSeed { + // The beacon seed bytes. + bytes data = 1; + + // The time at which this key becomes active. + int64 start_time_millis = 2; + + // The time at which this key becomes inactive. + int64 end_time_millis = 3; +} + +// Device metadata relevant to the suite of multi-device (Better Together) +// features. This data is sent to and received from CryptAuth--using end-to-end +// encryption--as part of DeviceSync v2. +// Next ID: 4 +message BetterTogetherDeviceMetadata { + // A cryptographic public key associated with the device. + // The format of this key is a serialized SecureMessage.GenericPublicKey. + bytes public_key = 1; + + // A device model name that's guaranteed not to contain any PII. + string no_pii_device_name = 2; + + // A list of seeds for EID BLE advertisements targeting this device. + repeated BeaconSeed beacon_seeds = 3; +}
diff --git a/components/BUILD.gn b/components/BUILD.gn index a8c3dfbee..6eabe20 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -160,7 +160,6 @@ "//components/sync_sessions:unit_tests", "//components/sync_user_events:unit_tests", "//components/test:run_all_unittests", - "//components/thread_pool_util:unit_tests", "//components/translate/core/browser:unit_tests", "//components/translate/core/common:unit_tests", "//components/translate/core/language_detection:unit_tests",
diff --git a/components/arc/common/app.mojom b/components/arc/common/app.mojom index a453b9d2..50f54ae 100644 --- a/components/arc/common/app.mojom +++ b/components/arc/common/app.mojom
@@ -56,7 +56,7 @@ // If non-null, signifies this package represents a web app that should be // installed on the browser side. [MinVersion=38] WebAppInfo? web_app_info; - [MinVersion=41] map<AppPermission, bool>? permissions; + [MinVersion=42] map<AppPermission, PermissionState>? permissions; }; // Describes ARC app shortcut.
diff --git a/components/arc/common/app_permissions.mojom b/components/arc/common/app_permissions.mojom index 6c63abd..9421932 100644 --- a/components/arc/common/app_permissions.mojom +++ b/components/arc/common/app_permissions.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Next MinVersion: 1 +// Next MinVersion: 2 module arc.mojom; @@ -16,6 +16,11 @@ NOTIFICATIONS = 3, // Not a manifest permission }; +struct PermissionState { + bool granted; // If the permission has been granted + bool managed; // If the permission is managed by an enterprise policy +}; + // An interface for Chrome to manipulate app permissions in ARC. // Next method ID: 2 interface AppPermissionsInstance {
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc index 20cd4f53..c4b83cf 100644 --- a/components/autofill/core/browser/data_model/autofill_profile.cc +++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -320,7 +320,6 @@ return AutofillDataModel::IsDeletable() && !IsVerified(); } -// TODO(crbug.com/589535): Disambiguate similar field types before uploading. void AutofillProfile::GetMatchingTypes( const base::string16& text, const std::string& app_locale,
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 2e36977..4c79f2a 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -411,8 +411,6 @@ break; case PasswordAttribute::kHasSpecialSymbol: upload->set_password_has_special_symbol(password_attributes_vote.second); - if (password_attributes_vote.second) - upload->set_password_special_symbol(password_symbol_vote); break; case PasswordAttribute::kPasswordAttributesCount: NOTREACHED();
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc index bc8177f..0709338 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -9,7 +9,6 @@ #include "base/base64.h" #include "base/feature_list.h" #include "base/logging.h" -#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_profile_sync_util.h" @@ -265,20 +264,6 @@ active_callback_.Run(false); } - // Report count of entities to delete. This use case should be pretty rare - // so it is okay to read it from DB again. - // TODO(crbug.com/853688): Remove when wallet data is launched on USS, incl. - // the helper function SyncWalletDataRecordClearedEntitiesCount(). - std::vector<std::unique_ptr<AutofillProfile>> profiles; - std::vector<std::unique_ptr<CreditCard>> cards; - std::unique_ptr<PaymentsCustomerData> customer_data; - if (GetAutofillTable()->GetServerProfiles(&profiles) && - GetAutofillTable()->GetServerCreditCards(&cards) && - GetAutofillTable()->GetPaymentsCustomerData(&customer_data)) { - int count = profiles.size() + cards.size() + (customer_data ? 1 : 0); - SyncWalletDataRecordClearedEntitiesCount(count); - } - // Do not notify the metadata bridge because we do not want to upstream the // deletions. The metadata bridge deletes its data independently when sync // gets stopped. @@ -339,13 +324,11 @@ PopulateWalletTypesFromSyncData(entity_data, &wallet_cards, &wallet_addresses, &customer_data); - bool should_log_diff; + wallet_data_changed |= SetPaymentsCustomerData(std::move(customer_data)); wallet_data_changed |= - SetPaymentsCustomerData(std::move(customer_data), &should_log_diff); - wallet_data_changed |= SetWalletCards( - std::move(wallet_cards), should_log_diff, notify_metadata_bridge); - wallet_data_changed |= SetWalletAddresses( - std::move(wallet_addresses), should_log_diff, notify_metadata_bridge); + SetWalletCards(std::move(wallet_cards), notify_metadata_bridge); + wallet_data_changed |= + SetWalletAddresses(std::move(wallet_addresses), notify_metadata_bridge); // Commit the transaction to make sure the data and the metadata with the // new progress marker is written down (especially on Android where we @@ -360,7 +343,6 @@ bool AutofillWalletSyncBridge::SetWalletCards( std::vector<CreditCard> wallet_cards, - bool log_diff, bool notify_metadata_bridge) { // Users can set billing address of the server credit card locally, but that // information does not propagate to either Chrome Sync or Google Payments @@ -378,14 +360,6 @@ AutofillWalletDiff<CreditCard> diff = ComputeAutofillWalletDiff(existing_cards, wallet_cards); - if (log_diff) { - UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.Added", diff.items_added); - UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.Removed", - diff.items_removed); - UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCards2.AddedOrRemoved", - diff.items_added + diff.items_removed); - } - if (!diff.IsEmpty()) { if (base::FeatureList::IsEnabled( ::switches::kSyncUSSAutofillWalletMetadata)) { @@ -405,7 +379,6 @@ bool AutofillWalletSyncBridge::SetWalletAddresses( std::vector<AutofillProfile> wallet_addresses, - bool log_diff, bool notify_metadata_bridge) { // We do not have to CopyRelevantWalletMetadataFromDisk() because we will // never overwrite the same entity with different data (server_id is generated @@ -425,15 +398,6 @@ AutofillWalletDiff<AutofillProfile> diff = ComputeAutofillWalletDiff(existing_addresses, wallet_addresses); - if (log_diff) { - UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses2.Added", - diff.items_added); - UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses2.Removed", - diff.items_removed); - UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddresses2.AddedOrRemoved", - diff.items_added + diff.items_removed); - } - if (!diff.IsEmpty()) { if (base::FeatureList::IsEnabled( ::switches::kSyncUSSAutofillWalletMetadata)) { @@ -452,8 +416,7 @@ } bool AutofillWalletSyncBridge::SetPaymentsCustomerData( - std::vector<PaymentsCustomerData> customer_data, - bool* should_log_diff) { + std::vector<PaymentsCustomerData> customer_data) { AutofillTable* table = GetAutofillTable(); std::unique_ptr<PaymentsCustomerData> existing_entry; table->GetPaymentsCustomerData(&existing_entry); @@ -470,15 +433,6 @@ } #endif // DCHECK_IS_ON() - // We report the diff to metrics only if this is an incremental change where - // the user had sync set-up (having PaymentsCustomerData is a pre-requisite - // for having any other data) and continues to have sync set-up (continuing - // having a PaymentsCustomerData entity). As a side effect, this excludes - // reporting diffs for users that newly got a GPay account and sync - // PaymentsCustomerData for the first time but this is the best we can do to - // have the metrics consistent with Directory implementation. - *should_log_diff = existing_entry && new_entry; - if (!new_entry && existing_entry) { // Clear the existing entry in the DB. GetAutofillTable()->SetPaymentsCustomerData(nullptr);
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h index 3fbf638..8ca747f 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -94,28 +94,21 @@ bool notify_metadata_bridge); // Sets |customer_data| to this client and returns whether any change has been - // applied (i.e., whether |customer_data| was different from local data) and - // whether we |should_log_diff|, i.e. metrics for diffs in counts of addresses - // and cards. - bool SetPaymentsCustomerData(std::vector<PaymentsCustomerData> customer_data, - bool* should_log_diff); + // applied (i.e., whether |customer_data| was different from local data). + bool SetPaymentsCustomerData(std::vector<PaymentsCustomerData> customer_data); - // Sets |wallet_cards| to this client, records metrics about added/deleted - // data (if |log_diff| is true) and returns whether any change has been + // Sets |wallet_cards| to this client and returns whether any change has been // applied (i.e., whether |wallet_cards| was different from local data). If // |notify_metadata_bridge|, it also notifies via WebDataBackend about any // individual entity changes. bool SetWalletCards(std::vector<CreditCard> wallet_cards, - bool log_diff, bool notify_metadata_bridge); - // Sets |wallet_addresses| to this client, records metrics about added/deleted - // data (if |log_diff| is true) and returns whether any change has been - // applied (i.e., whether |wallet_addresses| was different from local data). - // If |notify_metadata_bridge|, it also notifies via WebDataBackend about any - // individual entity changes. + // Sets |wallet_addresses| to this client and returns whether any change has + // been applied (i.e., whether |wallet_addresses| was different from local + // data). If |notify_metadata_bridge|, it also notifies via WebDataBackend + // about any individual entity changes. bool SetWalletAddresses(std::vector<AutofillProfile> wallet_addresses, - bool log_diff, bool notify_metadata_bridge); // Computes a "diff" (items added, items removed) of two vectors of items,
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc index c5df8ba7b..92b6386 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -14,7 +14,6 @@ #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" -#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" @@ -278,45 +277,6 @@ real_processor_->OnUpdateReceived(state, std::move(initial_updates)); } - void ExpectAddressesDiffInHistograms(int added, int removed) { - histogram_tester_.ExpectUniqueSample("Autofill.WalletAddresses2.Added", - /*bucket=*/added, - /*count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.WalletAddresses2.Removed", - /*bucket=*/removed, - /*count=*/1); - histogram_tester_.ExpectUniqueSample( - "Autofill.WalletAddresses2.AddedOrRemoved", - /*bucket=*/added + removed, - /*count=*/1); - } - - void ExpectNoHistogramsForAddressesDiff() { - histogram_tester_.ExpectTotalCount("Autofill.WalletAddresses2.Added", 0); - histogram_tester_.ExpectTotalCount("Autofill.WalletAddresses2.Removed", 0); - histogram_tester_.ExpectTotalCount( - "Autofill.WalletAddresses2.AddedOrRemoved", 0); - } - - void ExpectCardsDiffInHistograms(int added, int removed) { - histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.Added", - /*bucket=*/added, - /*count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.Removed", - /*bucket=*/removed, - /*count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.WalletCards2.AddedOrRemoved", - /*bucket=*/added + removed, - /*count=*/1); - } - - void ExpectNoHistogramsForCardsDiff() { - histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.Added", 0); - histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.Removed", 0); - histogram_tester_.ExpectTotalCount("Autofill.WalletCards2.AddedOrRemoved", - 0); - } - void ExpectCountsOfWalletMetadataInDB(unsigned int cards_count, unsigned int addresses_count) { std::map<std::string, AutofillMetadata> cards_metadata; @@ -381,7 +341,6 @@ testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_; std::unique_ptr<syncer::ClientTagBasedModelTypeProcessor> real_processor_; std::unique_ptr<AutofillWalletSyncBridge> bridge_; - base::HistogramTester histogram_tester_; NiceMock<base::MockCallback<base::RepeatingCallback<void(bool)>>> active_callback_; @@ -510,8 +469,6 @@ UnorderedElementsAre(EqualsSpecifics(profile_specifics2), EqualsSpecifics(card_specifics2), EqualsSpecifics(customer_data_specifics))); - ExpectAddressesDiffInHistograms(/*added=*/1, /*removed=*/1); - ExpectCardsDiffInHistograms(/*added=*/1, /*removed=*/1); } // Tests that in initial sync, no metrics are recorded for new addresses and @@ -549,8 +506,6 @@ UnorderedElementsAre(EqualsSpecifics(profile_specifics), EqualsSpecifics(card_specifics), EqualsSpecifics(customer_data_specifics))); - ExpectNoHistogramsForAddressesDiff(); - ExpectNoHistogramsForCardsDiff(); } // Tests that when a new payments customer data is sent by the server, the @@ -585,8 +540,6 @@ UnorderedElementsAre(EqualsSpecifics(profile_specifics), EqualsSpecifics(card_specifics), EqualsSpecifics(customer_data_specifics2))); - ExpectAddressesDiffInHistograms(/*added=*/0, /*removed=*/0); - ExpectCardsDiffInHistograms(/*added=*/0, /*removed=*/0); } // Tests that when the server sends no cards or address, the client should @@ -613,9 +566,6 @@ } EXPECT_TRUE(GetAllLocalData().empty()); - // No diff metrics reported when new data is empty. - ExpectNoHistogramsForAddressesDiff(); - ExpectNoHistogramsForCardsDiff(); } // Test that when the server sends the same address and card as the client has, @@ -650,8 +600,6 @@ UnorderedElementsAre(EqualsSpecifics(profile_specifics), EqualsSpecifics(card_specifics), EqualsSpecifics(customer_data_specifics))); - ExpectAddressesDiffInHistograms(/*added=*/0, /*removed=*/0); - ExpectCardsDiffInHistograms(/*added=*/0, /*removed=*/0); } // Tests that when there are multiple changes happening at the same time, the @@ -700,8 +648,6 @@ UnorderedElementsAre(EqualsSpecifics(profile_specifics), EqualsSpecifics(card2_specifics), EqualsSpecifics(customer_data_specifics))); - ExpectAddressesDiffInHistograms(/*added=*/0, /*removed=*/1); - ExpectCardsDiffInHistograms(/*added=*/1, /*removed=*/1); } // Test that all field values for a address sent form the server are copied on @@ -841,9 +787,6 @@ } EXPECT_TRUE(GetAllLocalData().empty()); - // No diff metrics reported when clearing data. - ExpectNoHistogramsForAddressesDiff(); - ExpectNoHistogramsForCardsDiff(); } TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) { @@ -864,8 +807,6 @@ bridge()->ApplyStopSyncChanges(/*delete_metadata_change_list=*/nullptr); EXPECT_FALSE(GetAllLocalData().empty()); - ExpectNoHistogramsForAddressesDiff(); - ExpectNoHistogramsForCardsDiff(); } TEST_P(AutofillWalletSyncBridgeTest, NotifiesWhenActivelySyncing) {
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn index 3a437a9..179b562 100644 --- a/components/autofill_assistant/browser/BUILD.gn +++ b/components/autofill_assistant/browser/BUILD.gn
@@ -61,6 +61,8 @@ "actions/set_form_field_value_action.h", "actions/show_details_action.cc", "actions/show_details_action.h", + "actions/show_form_action.cc", + "actions/show_form_action.h", "actions/show_info_box_action.cc", "actions/show_info_box_action.h", "actions/show_progress_bar_action.cc",
diff --git a/components/autofill_assistant/browser/actions/action.cc b/components/autofill_assistant/browser/actions/action.cc index dd0397b..e82ad03 100644 --- a/components/autofill_assistant/browser/actions/action.cc +++ b/components/autofill_assistant/browser/actions/action.cc
@@ -118,6 +118,9 @@ case ActionProto::ActionInfoCase::kConfigureBottomSheet: out << "ConfigureBottomSheet"; break; + case ActionProto::ActionInfoCase::kShowForm: + out << "ShowForm"; + break; case ActionProto::ActionInfoCase::ACTION_INFO_NOT_SET: out << "ACTION_INFO_NOT_SET"; break;
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h index 8350176..eb9f95f 100644 --- a/components/autofill_assistant/browser/actions/action_delegate.h +++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -257,6 +257,15 @@ // Set the peek mode. virtual void SetPeekMode(ConfigureBottomSheetProto::PeekMode peek_mode) = 0; + // Show a form to the user and call |callback| with its values whenever there + // is a change. |callback| will be called directly with the initial values of + // the form directly after this call. Returns true if the form was correctly + // set, false otherwise. The latter can happen if the form contains + // unsupported or invalid inputs. + virtual bool SetForm( + std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback) = 0; + protected: ActionDelegate() = default; };
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h index 5caf36b..526db5a 100644 --- a/components/autofill_assistant/browser/actions/mock_action_delegate.h +++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -161,6 +161,10 @@ MOCK_METHOD1(SetResizeViewport, void(bool resize_viewport)); MOCK_METHOD1(SetPeekMode, void(ConfigureBottomSheetProto::PeekMode peek_mode)); + MOCK_METHOD2( + SetForm, + bool(std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback)); }; } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/show_form_action.cc b/components/autofill_assistant/browser/actions/show_form_action.cc new file mode 100644 index 0000000..2efbfde --- /dev/null +++ b/components/autofill_assistant/browser/actions/show_form_action.cc
@@ -0,0 +1,132 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill_assistant/browser/actions/show_form_action.h" + +#include <memory> +#include <utility> + +#include "base/callback.h" +#include "components/autofill_assistant/browser/actions/action_delegate.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" + +namespace autofill_assistant { + +ShowFormAction::ShowFormAction(const ActionProto& proto) + : Action(proto), weak_ptr_factory_(this) { + DCHECK(proto_.has_show_form() && proto_.show_form().has_form()); +} + +ShowFormAction::~ShowFormAction() {} + +void ShowFormAction::InternalProcessAction(ActionDelegate* delegate, + ProcessActionCallback callback) { + callback_ = std::move(callback); + + // Show the form. This will call OnFormValuesChanged with the initial result, + // which will in turn show the "Continue" chip. + if (!delegate->SetForm( + std::make_unique<FormProto>(proto_.show_form().form()), + base::BindRepeating(&ShowFormAction::OnFormValuesChanged, + weak_ptr_factory_.GetWeakPtr(), delegate))) { + // The form contains unsupported or invalid inputs. + UpdateProcessedAction(UNSUPPORTED); + std::move(callback_).Run(std::move(processed_action_proto_)); + return; + } +} + +void ShowFormAction::OnFormValuesChanged(ActionDelegate* delegate, + const FormProto::Result* form_result) { + // Copy the current values to the action result. + *processed_action_proto_->mutable_form_result() = *form_result; + + // Check form validity. + // TODO(crbug.com/806868): Only check validity of inputs whose value changed + // instead of all inputs. + bool form_is_valid = true; + const FormProto& form = proto_.show_form().form(); + for (int i = 0; i < form.inputs_size() && form_is_valid; i++) { + const FormInputProto& input = form.inputs(i); + const FormInputProto::Result& input_result = form_result->input_results(i); + + switch (input.input_type_case()) { + case FormInputProto::InputTypeCase::kCounter: { + DCHECK(input_result.has_counter()); + DCHECK_EQ(input.counter().counters_size(), + input_result.counter().values_size()); + + // A counter input is valid if at least one of its counters has a value + // different than its initial value. + bool input_is_valid = false; + for (int j = 0; j < input.counter().counters_size(); j++) { + if (input_result.counter().values(j) != + input.counter().counters(j).initial_value()) { + input_is_valid = true; + break; + } + } + + if (!input_is_valid) { + form_is_valid = false; + } + break; + } + case FormInputProto::InputTypeCase::kSelection: { + DCHECK(input_result.has_selection()); + DCHECK_EQ(input.selection().choices_size(), + input_result.selection().selected_size()); + + // A selection input is valid if the number of selected choices is + // greater or equal than |min_selected_choices|. + int min_selected = input.selection().min_selected_choices(); + if (min_selected == 0) + break; + + int n = 0; + for (bool selected : input_result.selection().selected()) { + if (selected && ++n >= min_selected) { + break; + } + } + + if (n < min_selected) { + form_is_valid = false; + } + break; + } + case FormInputProto::InputTypeCase::INPUT_TYPE_NOT_SET: + NOTREACHED(); + break; + // Intentionally no default case to make compilation fail if a new value + // was added to the enum but not to this list. + } + } + + // Show "Continue" chip. + // TODO(crbug.com/806868): Make this chip configurable. + auto chips = std::make_unique<std::vector<Chip>>(); + chips->emplace_back(); + chips->back().text = + l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_PAYMENT_INFO_CONFIRM); + chips->back().type = HIGHLIGHTED_ACTION; + chips->back().disabled = !form_is_valid; + if (form_is_valid) { + chips->back().callback = + base::BindOnce(&ShowFormAction::OnButtonClicked, + weak_ptr_factory_.GetWeakPtr(), delegate); + } + + delegate->Prompt(std::move(chips)); +} + +void ShowFormAction::OnButtonClicked(ActionDelegate* delegate) { + DCHECK(callback_); + delegate->SetForm(nullptr, base::DoNothing()); + UpdateProcessedAction(ACTION_APPLIED); + std::move(callback_).Run(std::move(processed_action_proto_)); +} + +} // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/show_form_action.h b/components/autofill_assistant/browser/actions/show_form_action.h new file mode 100644 index 0000000..a7e14063 --- /dev/null +++ b/components/autofill_assistant/browser/actions/show_form_action.h
@@ -0,0 +1,38 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_FORM_ACTION_H_ +#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_FORM_ACTION_H_ + +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/autofill_assistant/browser/actions/action.h" + +namespace autofill_assistant { +// An action to show a form than can be filled by the user. +class ShowFormAction : public Action { + public: + explicit ShowFormAction(const ActionProto& proto); + ~ShowFormAction() override; + + private: + // Overrides Action: + void InternalProcessAction(ActionDelegate* delegate, + ProcessActionCallback callback) override; + + void OnFormValuesChanged(ActionDelegate* delegate, + const FormProto::Result* form_result); + void OnButtonClicked(ActionDelegate* delegate); + + ProcessActionCallback callback_; + base::WeakPtrFactory<ShowFormAction> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ShowFormAction); +}; + +} // namespace autofill_assistant +#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_FORM_ACTION_H_
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index 51a31a1f..833f28f5 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -288,6 +288,114 @@ GetUiController()->OnPeekModeChanged(peek_mode); } +const FormProto* Controller::GetForm() const { + return form_.get(); +} + +bool Controller::SetForm( + std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback) { + form_.reset(); + form_result_.reset(); + form_callback_ = base::DoNothing(); + + if (!form) { + GetUiController()->OnFormChanged(nullptr); + return true; + } + + // Initialize form result. This will return false if the form is invalid or + // contains unsupported inputs. + auto form_result = std::make_unique<FormProto::Result>(); + for (FormInputProto& input : *form->mutable_inputs()) { + FormInputProto::Result* result = form_result->add_input_results(); + switch (input.input_type_case()) { + case FormInputProto::InputTypeCase::kCounter: + // Add the initial value of each counter into the form result. + for (const CounterInputProto::Counter& counter : + input.counter().counters()) { + result->mutable_counter()->add_values(counter.initial_value()); + } + break; + case FormInputProto::InputTypeCase::kSelection: { + // Add the initial selected state of each choice into the form result. + bool has_selected = false; + for (const SelectionInputProto::Choice& choice : + input.selection().choices()) { + if (choice.selected()) { + if (has_selected && !input.selection().allow_multiple()) { + // Multiple choices are initially selected even though it is not + // allowed by the input. + return false; + } + has_selected = true; + } + result->mutable_selection()->add_selected(choice.selected()); + } + break; + } + case FormInputProto::InputTypeCase::INPUT_TYPE_NOT_SET: + DVLOG(1) << "Encountered input with INPUT_TYPE_NOT_SET"; + return false; + // Intentionally no default case to make compilation fail if a new value + // was added to the enum but not to this list. + } + } + + // Form is valid. + form_ = std::move(form); + form_result_ = std::move(form_result); + form_callback_ = callback; + + // Call the callback with initial result. + form_callback_.Run(form_result_.get()); + + GetUiController()->OnFormChanged(form_.get()); + return true; +} + +void Controller::SetCounterValue(int input_index, + int counter_index, + int value) { + if (!form_result_ || input_index < 0 || + input_index >= form_result_->input_results_size()) { + NOTREACHED() << "Invalid input index: " << input_index; + return; + } + + FormInputProto::Result* input_result = + form_result_->mutable_input_results(input_index); + if (!input_result->has_counter() || counter_index < 0 || + counter_index >= input_result->counter().values_size()) { + NOTREACHED() << "Invalid counter index: " << counter_index; + return; + } + + input_result->mutable_counter()->set_values(counter_index, value); + form_callback_.Run(form_result_.get()); +} + +void Controller::SetChoiceSelected(int input_index, + int choice_index, + bool selected) { + if (!form_result_ || input_index < 0 || + input_index >= form_result_->input_results_size()) { + NOTREACHED() << "Invalid input index: " << input_index; + return; + } + + FormInputProto::Result* input_result = + form_result_->mutable_input_results(input_index); + if (!input_result->has_selection() || choice_index < 0 || + choice_index >= input_result->selection().selected_size()) { + NOTREACHED() << "Invalid choice index: " << choice_index; + return; + } + + input_result->mutable_selection()->set_selected(choice_index, selected); + form_callback_.Run(form_result_.get()); +} + bool Controller::GetResizeViewport() { return resize_viewport_; }
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h index 165989a..7b51297 100644 --- a/components/autofill_assistant/browser/controller.h +++ b/components/autofill_assistant/browser/controller.h
@@ -85,6 +85,9 @@ void SetChips(std::unique_ptr<std::vector<Chip>> chips) override; void SetResizeViewport(bool resize_viewport) override; void SetPeekMode(ConfigureBottomSheetProto::PeekMode peek_mode) override; + bool SetForm(std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback) + override; bool IsNavigatingToNewDocument() override; bool HasNavigationError() override; void AddListener(ScriptExecutorDelegate::Listener* listener) override; @@ -125,6 +128,11 @@ bool GetResizeViewport() override; ConfigureBottomSheetProto::PeekMode GetPeekMode() override; void GetOverlayColors(OverlayColors* colors) const override; + const FormProto* GetForm() const override; + void SetCounterValue(int input_index, int counter_index, int value) override; + void SetChoiceSelected(int input_index, + int choice_index, + bool selected) override; private: friend ControllerTest; @@ -292,6 +300,11 @@ std::unique_ptr<PaymentRequestOptions> payment_request_options_; std::unique_ptr<PaymentInformation> payment_request_info_; + std::unique_ptr<FormProto> form_; + std::unique_ptr<FormProto::Result> form_result_; + base::RepeatingCallback<void(const FormProto::Result*)> form_callback_ = + base::DoNothing(); + // Value for ScriptExecutorDelegate::IsNavigatingToNewDocument() bool navigating_to_new_document_ = false;
diff --git a/components/autofill_assistant/browser/fake_script_executor_delegate.cc b/components/autofill_assistant/browser/fake_script_executor_delegate.cc index 3fa9392..373ce2d9 100644 --- a/components/autofill_assistant/browser/fake_script_executor_delegate.cc +++ b/components/autofill_assistant/browser/fake_script_executor_delegate.cc
@@ -105,4 +105,10 @@ void FakeScriptExecutorDelegate::RemoveListener(Listener* listener) { listeners_.erase(listener); } + +bool FakeScriptExecutorDelegate::SetForm( + std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback) { + return true; +} } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/fake_script_executor_delegate.h b/components/autofill_assistant/browser/fake_script_executor_delegate.h index 3e7f245..b365d75 100644 --- a/components/autofill_assistant/browser/fake_script_executor_delegate.h +++ b/components/autofill_assistant/browser/fake_script_executor_delegate.h
@@ -46,6 +46,9 @@ std::unique_ptr<PaymentRequestOptions> options) override; void SetResizeViewport(bool resize_viewport) override; void SetPeekMode(ConfigureBottomSheetProto::PeekMode peek_mode) override; + bool SetForm(std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback) + override; bool HasNavigationError() override; bool IsNavigatingToNewDocument() override; void AddListener(Listener* listener) override;
diff --git a/components/autofill_assistant/browser/mock_ui_controller.h b/components/autofill_assistant/browser/mock_ui_controller.h index 65b206e..a40ea6f 100644 --- a/components/autofill_assistant/browser/mock_ui_controller.h +++ b/components/autofill_assistant/browser/mock_ui_controller.h
@@ -40,6 +40,7 @@ MOCK_METHOD1(OnResizeViewportChanged, void(bool resize_viewport)); MOCK_METHOD1(OnPeekModeChanged, void(ConfigureBottomSheetProto::PeekMode peek_mode)); + MOCK_METHOD1(OnFormChanged, void(const FormProto* form)); }; } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc index 980b17f..6622dc20 100644 --- a/components/autofill_assistant/browser/protocol_utils.cc +++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -22,6 +22,7 @@ #include "components/autofill_assistant/browser/actions/set_attribute_action.h" #include "components/autofill_assistant/browser/actions/set_form_field_value_action.h" #include "components/autofill_assistant/browser/actions/show_details_action.h" +#include "components/autofill_assistant/browser/actions/show_form_action.h" #include "components/autofill_assistant/browser/actions/show_info_box_action.h" #include "components/autofill_assistant/browser/actions/show_progress_bar_action.h" #include "components/autofill_assistant/browser/actions/stop_action.h" @@ -275,6 +276,10 @@ client_action = std::make_unique<ConfigureBottomSheetAction>(action); break; } + case ActionProto::ActionInfoCase::kShowForm: { + client_action = std::make_unique<ShowFormAction>(action); + break; + } case ActionProto::ActionInfoCase::ACTION_INFO_NOT_SET: { DVLOG(1) << "Encountered action with ACTION_INFO_NOT_SET"; client_action = std::make_unique<UnsupportedAction>(action);
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc index d3157b2..dc25b8c 100644 --- a/components/autofill_assistant/browser/script_executor.cc +++ b/components/autofill_assistant/browser/script_executor.cc
@@ -467,6 +467,12 @@ delegate_->SetPeekMode(peek_mode); } +bool ScriptExecutor::SetForm( + std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback) { + return delegate_->SetForm(std::move(form), std::move(callback)); +} + void ScriptExecutor::OnGetActions(bool result, const std::string& response) { bool success = result && ProcessNextActionResponse(response); DVLOG(2) << __func__ << " result=" << result;
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h index 4fed8fd..c16bfcc 100644 --- a/components/autofill_assistant/browser/script_executor.h +++ b/components/autofill_assistant/browser/script_executor.h
@@ -177,6 +177,9 @@ void SetProgressVisible(bool visible) override; void SetResizeViewport(bool resize_viewport) override; void SetPeekMode(ConfigureBottomSheetProto::PeekMode peek_mode) override; + bool SetForm(std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback) + override; private: // Helper for WaitForElementVisible that keeps track of the state required to
diff --git a/components/autofill_assistant/browser/script_executor_delegate.h b/components/autofill_assistant/browser/script_executor_delegate.h index 1f67522..ebb6a46 100644 --- a/components/autofill_assistant/browser/script_executor_delegate.h +++ b/components/autofill_assistant/browser/script_executor_delegate.h
@@ -67,6 +67,9 @@ virtual void SetChips(std::unique_ptr<std::vector<Chip>> chips) = 0; virtual void SetResizeViewport(bool resize_viewport) = 0; virtual void SetPeekMode(ConfigureBottomSheetProto::PeekMode peek_mode) = 0; + virtual bool SetForm( + std::unique_ptr<FormProto> form, + base::RepeatingCallback<void(const FormProto::Result*)> callback) = 0; // Makes no area of the screen touchable. void ClearTouchableElementArea() {
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index aea67cca..03b94c9 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -342,6 +342,7 @@ ExpectNavigationProto expect_navigation = 40; WaitForNavigationProto wait_for_navigation = 41; ConfigureBottomSheetProto configure_bottom_sheet = 42; + ShowFormProto show_form = 43; } // Set to true to make the client remove any contextual information if the @@ -374,6 +375,8 @@ PaymentDetails payment_details = 15; // Should be set as a result of SetFormFieldValueAction. SetFormFieldValueProto.Result set_form_field_value_result = 17; + // Should be set as a result of FormAction. + FormProto.Result form_result = 21; } // Reports information about navigation that happened while @@ -1109,4 +1112,110 @@ // resize_viewport is true or was set to true by a previous actions, the // viewport will be resized to match the new peek height. optional PeekMode peek_mode = 2; -} \ No newline at end of file +} + +// Allow scripts to display a form with multiple inputs. +message ShowFormProto { + // The form to display. + optional FormProto form = 1; +} + +message FormProto { + // A result associated to this form, such that |input_results[i]| is the + // result of |inputs[i]|. + message Result { repeated FormInputProto.Result input_results = 1; } + + // The different inputs to display. + repeated FormInputProto inputs = 1; +} + +message FormInputProto { + message Result { + oneof input_type { + CounterInputProto.Result counter = 1; + SelectionInputProto.Result selection = 2; + } + } + + oneof input_type { + CounterInputProto counter = 1; + SelectionInputProto selection = 2; + } +} + +// An input that is made of one or more counters. A CounterInputProto is +// considered valid if at least one of its counters value differs from its +// |initial_value|. +message CounterInputProto { + // A single counter. + message Counter { + // The label shown with the counter, that handles plurals using the format + // defined by java.text.ChoiceFormat. All occurrences of the '{value}' + // substring will be replaced by the current counter value. + optional string label = 1; + + // The minimum value this counter can have. + optional int32 min_value = 2 [default = -0x80000000]; // kint32min + + // The maximum value this counter can have. + optional int32 max_value = 3 [default = 0x7FFFFFFF]; // kint32max + + // The initial value of the counter. + optional int32 initial_value = 4 [default = 0]; + } + + // A result associated to this counter. + message Result { + // The values of all counters from this CounterInputProto, such that + // |values[i]| is the value of |counters[i]|. + repeated int32 values = 1; + } + + // An optional label shown above the different counters. + optional string label = 1; + + // The counters to display. + repeated Counter counters = 2; + + // If specified, the input will initially display maximum |minimized_count| + // counters. If |counters|.size > |minimized_count|, the remaining counters + // will be displayed in an expandable section below the first + // |minimized_count| counters. + optional int32 minimized_count = 3 [default = 0x7FFFFFFF]; // kint32max +} + +// An input that allows the user to choose one or multiple options. This input +// is considered valid if the number of selected choices is bigger or equal than +// |min_choices|. +message SelectionInputProto { + message Choice { + // The label of this choice. + optional string label = 1; + + // Whether this choice is selected by default. If |allow_multiple| is false, + // then maximum 1 Choice can have this set to true, otherwise the associated + // FormAction will fail. + optional bool selected = 2 [default = false]; + } + + message Result { + // Stores whether each choice was selected or not, such that |selected[i]| + // is true if |choices[i]| was selected. + repeated bool selected = 1; + } + + // An optional label shown above the different choices. + optional string label = 1; + + // The choices to display. + repeated Choice choices = 2; + + // Whether the user will be allowed to select multiple choices. If false, each + // choice will be displayed with a radio button. Otherwise, it will be + // displayed with checkboxes. + optional bool allow_multiple = 3 [default = false]; + + // The minimum number of choices that should be selected to consider this + // input valid. + optional int32 min_selected_choices = 4 [default = 1]; +}
diff --git a/components/autofill_assistant/browser/ui_controller.cc b/components/autofill_assistant/browser/ui_controller.cc index d825e7c..c91e081e 100644 --- a/components/autofill_assistant/browser/ui_controller.cc +++ b/components/autofill_assistant/browser/ui_controller.cc
@@ -31,5 +31,6 @@ ConfigureBottomSheetProto::PeekMode peek_mode) {} void UiController::OnOverlayColorsChanged( const UiDelegate::OverlayColors& colors) {} +void UiController::OnFormChanged(const FormProto* form) {} } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/ui_controller.h b/components/autofill_assistant/browser/ui_controller.h index 8461cb7..2050eef5 100644 --- a/components/autofill_assistant/browser/ui_controller.h +++ b/components/autofill_assistant/browser/ui_controller.h
@@ -89,6 +89,9 @@ // Called when the overlay colors have changed. virtual void OnOverlayColorsChanged(const UiDelegate::OverlayColors& colors); + + // Called when the form has changed. + virtual void OnFormChanged(const FormProto* form); }; } // namespace autofill_assistant #endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_UI_CONTROLLER_H_
diff --git a/components/autofill_assistant/browser/ui_delegate.h b/components/autofill_assistant/browser/ui_delegate.h index b8eb061..05d7e1f3 100644 --- a/components/autofill_assistant/browser/ui_delegate.h +++ b/components/autofill_assistant/browser/ui_delegate.h
@@ -123,6 +123,19 @@ // Fills in the overlay colors. virtual void GetOverlayColors(OverlayColors* colors) const = 0; + // Returns the current form. May be null if there is no form to show. + virtual const FormProto* GetForm() const = 0; + + // Sets a counter value. + virtual void SetCounterValue(int input_index, + int counter_index, + int value) = 0; + + // Sets whether a selection choice is selected. + virtual void SetChoiceSelected(int input_index, + int choice_index, + bool selected) = 0; + protected: UiDelegate() = default; };
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc index 7e20169..c737231 100644 --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -169,7 +169,7 @@ ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS); Register(CONTENT_SETTINGS_TYPE_PLUGINS, "plugins", CONTENT_SETTING_BLOCK, - WebsiteSettingsInfo::SYNCABLE, + WebsiteSettingsInfo::UNSYNCABLE, WhitelistedSchemes(kChromeUIScheme, kChromeDevToolsScheme), ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK,
diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h index 3eec8bad..ec22768b 100644 --- a/components/content_settings/core/browser/host_content_settings_map.h +++ b/components/content_settings/core/browser/host_content_settings_map.h
@@ -135,7 +135,7 @@ // the |SETTING_SOURCE_WHITELIST| and the |primary_pattern| and // |secondary_pattern| are set to a wildcard pattern. If there is no content // setting, NULL is returned and the |source| field of |info| is set to - // |SETTING_SOURCE_NONE|. The pattern fiels of |info| are set to empty + // |SETTING_SOURCE_NONE|. The pattern fields of |info| are set to empty // patterns. // May be called on any thread. std::unique_ptr<base::Value> GetWebsiteSetting(
diff --git a/components/cronet/ios/cronet_global_state_ios.mm b/components/cronet/ios/cronet_global_state_ios.mm index 46d5116..dfafdeb 100644 --- a/components/cronet/ios/cronet_global_state_ios.mm +++ b/components/cronet/ios/cronet_global_state_ios.mm
@@ -29,7 +29,7 @@ ios_global_state::CreateParams create_params; create_params.install_at_exit_manager = true; ios_global_state::Create(create_params); - ios_global_state::StartThreadPool(/*init_params=*/nullptr); + ios_global_state::StartThreadPool(); url::Initialize();
diff --git a/components/drive/drive_notification_manager.cc b/components/drive/drive_notification_manager.cc index 382021b..1de15b0 100644 --- a/components/drive/drive_notification_manager.cc +++ b/components/drive/drive_notification_manager.cc
@@ -35,22 +35,27 @@ // The sync invalidation object ID for Google Drive. const char kDriveInvalidationObjectId[] = "CHANGELOG"; +// The sync invalidation object ID for Google Drive. +const char kFcmDriveInvalidationObjectId[] = "Drive"; + // Team drive invalidation ID's are "TD:<team_drive_id>". constexpr char kTeamDriveChangePrefix[] = "TD:"; -constexpr size_t kTeamDriveChangePrefixLength = - base::CharTraits<char>::length(kTeamDriveChangePrefix); +// Team drive invalidation ID's from FCM are "team-drive-<team_drive_id>". +constexpr char kFcmTeamDriveChangePrefix[] = "team-drive-"; } // namespace DriveNotificationManager::DriveNotificationManager( invalidation::InvalidationService* invalidation_service, + bool use_fcm_object_ids, const base::TickClock* clock) : invalidation_service_(invalidation_service), push_notification_registered_(false), push_notification_enabled_(false), observers_notified_(false), batch_timer_(clock), + use_fcm_object_ids_(use_fcm_object_ids), weak_ptr_factory_(this) { DCHECK(invalidation_service_); RegisterDriveNotifications(); @@ -96,11 +101,9 @@ for (const auto& id : ids) { // Empty string indicates default change list. std::string unpacked_id; - if (id.name() != kDriveInvalidationObjectId) { - DCHECK(base::StartsWith(id.name(), kTeamDriveChangePrefix, - base::CompareCase::SENSITIVE)) - << "Unexpected ID " << id.name(); - unpacked_id = id.name().substr(kTeamDriveChangePrefixLength); + if (id.name() != GetDriveInvalidationObjectId()) { + unpacked_id = ExtractTeamDriveId(id.name()); + DCHECK(!unpacked_id.empty()) << "Unexpected ID " << id.name(); } auto invalidations = invalidation_map.ForObject(id); int64_t& invalidation_version = @@ -250,12 +253,12 @@ syncer::ObjectIdSet ids; ids.insert( invalidation::ObjectId(ipc::invalidation::ObjectSource::COSMO_CHANGELOG, - kDriveInvalidationObjectId)); + GetDriveInvalidationObjectId())); for (const auto& team_drive_id : team_drive_ids_) { ids.insert(invalidation::ObjectId( ipc::invalidation::ObjectSource::COSMO_CHANGELOG, - base::StrCat({kTeamDriveChangePrefix, team_drive_id}))); + GetTeamDriveInvalidationObjectId(team_drive_id))); } CHECK(invalidation_service_->UpdateRegisteredInvalidationIds(this, ids)); @@ -287,4 +290,26 @@ return ""; } +std::string DriveNotificationManager::GetDriveInvalidationObjectId() const { + return use_fcm_object_ids_ ? kFcmDriveInvalidationObjectId + : kDriveInvalidationObjectId; +} + +std::string DriveNotificationManager::GetTeamDriveInvalidationObjectId( + const std::string& team_drive_id) const { + return base::StrCat( + {use_fcm_object_ids_ ? kFcmTeamDriveChangePrefix : kTeamDriveChangePrefix, + team_drive_id}); +} + +std::string DriveNotificationManager::ExtractTeamDriveId( + base::StringPiece object_id) const { + base::StringPiece prefix = + use_fcm_object_ids_ ? kFcmTeamDriveChangePrefix : kTeamDriveChangePrefix; + if (!object_id.starts_with(prefix)) { + return {}; + } + return object_id.substr(prefix.size()).as_string(); +} + } // namespace drive
diff --git a/components/drive/drive_notification_manager.h b/components/drive/drive_notification_manager.h index ba6981b..2354759 100644 --- a/components/drive/drive_notification_manager.h +++ b/components/drive/drive_notification_manager.h
@@ -38,6 +38,7 @@ // |clock| can be injected for testing. explicit DriveNotificationManager( invalidation::InvalidationService* invalidation_service, + bool use_fcm_object_ids = false, const base::TickClock* clock = base::DefaultTickClock::GetInstance()); ~DriveNotificationManager() override; @@ -107,6 +108,11 @@ // Returns a string representation of NotificationSource. static std::string NotificationSourceToString(NotificationSource source); + std::string GetDriveInvalidationObjectId() const; + std::string GetTeamDriveInvalidationObjectId( + const std::string& team_drive_id) const; + std::string ExtractTeamDriveId(base::StringPiece object_id) const; + invalidation::InvalidationService* invalidation_service_; base::ObserverList<DriveNotificationObserver>::Unchecked observers_; @@ -133,6 +139,12 @@ // service, will be reset when when send the invalidations to the observers. std::map<std::string, int64_t> invalidated_change_ids_; + // Whether the FCM invalidation IDs should be used. This decides whether + // "Drive" or "CHANGELOG" is used for the Drive invalidations and whether + // the "TD:" or the "team-drive-" prefix is used. This value must match + // whether |invalidation_service_| is an FCMInvalidationService. + const bool use_fcm_object_ids_; + SEQUENCE_CHECKER(sequence_checker_); // Note: This should remain the last member so it'll be destroyed and
diff --git a/components/exo/wayland/zcr_remote_shell.cc b/components/exo/wayland/zcr_remote_shell.cc index 01d48ed..a8af32c 100644 --- a/components/exo/wayland/zcr_remote_shell.cc +++ b/components/exo/wayland/zcr_remote_shell.cc
@@ -946,8 +946,12 @@ bool resize, int bounds_change) { zcr_remote_surface_v1_bounds_change_reason reason = - resize ? ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE - : ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE; + ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE; + if (!resize) { + reason = current_state == ash::WindowStateType::kPip + ? ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE_PIP + : ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE; + } if (bounds_change & ash::WindowResizer::kBoundsChange_Resizes) { reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE; } else if (bounds_change & ash::WindowResizer::kBoundsChange_Repositions) {
diff --git a/components/exo/wayland/zcr_remote_shell.h b/components/exo/wayland/zcr_remote_shell.h index 7538c622..3d55ad7 100644 --- a/components/exo/wayland/zcr_remote_shell.h +++ b/components/exo/wayland/zcr_remote_shell.h
@@ -22,7 +22,7 @@ namespace exo { namespace wayland { -constexpr uint32_t kZcrRemoteShellVersion = 20; +constexpr uint32_t kZcrRemoteShellVersion = 21; void bind_remote_shell(wl_client* client, void* data,
diff --git a/components/history/core/browser/in_memory_database.cc b/components/history/core/browser/in_memory_database.cc index bc037b7..f8d2dcd 100644 --- a/components/history/core/browser/in_memory_database.cc +++ b/components/history/core/browser/in_memory_database.cc
@@ -30,9 +30,6 @@ // No reason to leave data behind in memory when rows are removed. ignore_result(db_.Execute("PRAGMA auto_vacuum=1")); - // Ensure this is really an in-memory-only cache. - ignore_result(db_.Execute("PRAGMA temp_store=MEMORY")); - // Create the URL table, but leave it empty for now. if (!CreateURLTable(false)) { NOTREACHED() << "Unable to create table";
diff --git a/components/invalidation/impl/fcm_invalidation_listener.cc b/components/invalidation/impl/fcm_invalidation_listener.cc index 02d44ad..f01896f 100644 --- a/components/invalidation/impl/fcm_invalidation_listener.cc +++ b/components/invalidation/impl/fcm_invalidation_listener.cc
@@ -75,12 +75,24 @@ // TODO(melandory): Report error and consider not to process with the // invalidation. } + // Note: |public_topic| is empty for some invalidations (e.g. Drive). Prefer + // using |*expected_public_topic| over |public_topic|. + base::Optional<std::string> expected_public_topic = + per_user_topic_registration_manager_ + ->LookupRegisteredPublicTopicByPrivateTopic(private_topic); + if (!expected_public_topic || + (!public_topic.empty() && public_topic != *expected_public_topic)) { + DVLOG(1) << "Unexpected invalidation for " << private_topic + << " with public topic " << public_topic << ". Expected " + << expected_public_topic.value_or("<None>"); + return; + } TopicInvalidationMap invalidations; Invalidation inv = - Invalidation::Init(ConvertTopicToId(public_topic), v, payload); + Invalidation::Init(ConvertTopicToId(*expected_public_topic), v, payload); inv.SetAckHandler(AsWeakPtr(), base::ThreadTaskRunnerHandle::Get()); DVLOG(1) << "Received invalidation with version " << inv.version() << " for " - << public_topic; + << *expected_public_topic; invalidations.Insert(inv); DispatchInvalidations(invalidations);
diff --git a/components/invalidation/impl/fcm_invalidation_listener_unittest.cc b/components/invalidation/impl/fcm_invalidation_listener_unittest.cc index a3920755..798645f0 100644 --- a/components/invalidation/impl/fcm_invalidation_listener_unittest.cc +++ b/components/invalidation/impl/fcm_invalidation_listener_unittest.cc
@@ -165,11 +165,17 @@ nullptr /* pref_service */, nullptr /* loader_factory */, base::BindRepeating(&syncer::JsonUnsafeParser::Parse), - "fake_sender_id") {} + "fake_sender_id", + false) { + ON_CALL(*this, LookupRegisteredPublicTopicByPrivateTopic) + .WillByDefault(testing::ReturnArg<0>()); + } ~MockRegistrationManager() override {} MOCK_METHOD2(UpdateRegisteredTopics, void(const TopicSet& topics, const std::string& token)); MOCK_METHOD0(Init, void()); + MOCK_CONST_METHOD1(LookupRegisteredPublicTopicByPrivateTopic, + base::Optional<Topic>(const std::string& private_topic)); }; class FCMInvalidationListenerTest : public testing::Test {
diff --git a/components/invalidation/impl/fcm_invalidation_service.cc b/components/invalidation/impl/fcm_invalidation_service.cc index 99ea617..b390c52f 100644 --- a/components/invalidation/impl/fcm_invalidation_service.cc +++ b/components/invalidation/impl/fcm_invalidation_service.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/i18n/time_formatting.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/strcat.h" #include "build/build_config.h" #include "components/gcm_driver/instance_id/instance_id_driver.h" #include "components/invalidation/impl/fcm_invalidator.h" @@ -21,8 +22,10 @@ #include "components/invalidation/public/invalidator_state.h" #include "components/invalidation/public/object_id_invalidation_map.h" #include "components/invalidation/public/topic_invalidation_map.h" +#include "components/prefs/scoped_user_pref_update.h" #include "google_apis/gaia/gaia_constants.h" +namespace invalidation { namespace { const char kApplicationName[] = "com.google.chrome.fcm.invalidations"; // Sender ID coming from the Firebase console. @@ -31,9 +34,20 @@ void ReportInvalidatorState(syncer::InvalidatorState state) { UMA_HISTOGRAM_ENUMERATION("Invalidations.StatusChanged", state); } + +// Added in M76. +void MigratePrefs(PrefService* prefs, const std::string& sender_id) { + if (!prefs->HasPrefPath(prefs::kFCMInvalidationClientIDCacheDeprecated)) { + return; + } + DictionaryPrefUpdate update(prefs, prefs::kInvalidationClientIDCache); + update->SetString( + sender_id, + prefs->GetString(prefs::kFCMInvalidationClientIDCacheDeprecated)); + prefs->ClearPref(prefs::kFCMInvalidationClientIDCacheDeprecated); } -namespace invalidation { +} // namespace FCMInvalidationService::FCMInvalidationService( IdentityProvider* identity_provider, @@ -41,8 +55,12 @@ instance_id::InstanceIDDriver* instance_id_driver, PrefService* pref_service, const syncer::ParseJSONCallback& parse_json, - network::mojom::URLLoaderFactory* loader_factory) - : invalidator_registrar_(pref_service), + network::mojom::URLLoaderFactory* loader_factory, + const std::string& sender_id) + : sender_id_(sender_id.empty() ? kInvalidationGCMSenderId : sender_id), + invalidator_registrar_(pref_service, + sender_id_, + sender_id_ == kInvalidationGCMSenderId), gcm_driver_(gcm_driver), instance_id_driver_(instance_id_driver), identity_provider_(identity_provider), @@ -198,7 +216,10 @@ } std::string FCMInvalidationService::GetOwnerName() const { - return "FCM"; + if (sender_id_ == kInvalidationGCMSenderId) { + return "FCM"; + } + return "FCM" + sender_id_; } bool FCMInvalidationService::IsReadyToStart() { @@ -236,8 +257,7 @@ DCHECK(IsReadyToStart()); diagnostic_info_.service_was_started = base::Time::Now(); auto network = std::make_unique<syncer::FCMNetworkHandler>( - gcm_driver_, instance_id_driver_, kInvalidationGCMSenderId, - kApplicationName); + gcm_driver_, instance_id_driver_, sender_id_, GetApplicationName()); // The order of calls is important. Do not change. // We should start listening before requesting the id, because // valid id is only generated, once there is an app handler @@ -247,7 +267,7 @@ // startup cached messages might exists. invalidator_ = std::make_unique<syncer::FCMInvalidator>( std::move(network), identity_provider_, pref_service_, loader_factory_, - parse_json_, kInvalidationGCMSenderId); + parse_json_, sender_id_, sender_id_ == kInvalidationGCMSenderId); PopulateClientID(); invalidator_->RegisterHandler(this); DoUpdateRegisteredIdsIfNeeded(); @@ -263,26 +283,35 @@ void FCMInvalidationService::PopulateClientID() { diagnostic_info_.instance_id_requested = base::Time::Now(); - client_id_ = pref_service_->GetString(prefs::kFCMInvalidationClientIDCache); + if (sender_id_ == kInvalidationGCMSenderId) { + MigratePrefs(pref_service_, sender_id_); + } + const std::string* client_id_pref = + pref_service_->GetDictionary(prefs::kInvalidationClientIDCache) + ->FindStringKey(sender_id_); + client_id_ = client_id_pref ? *client_id_pref : ""; instance_id::InstanceID* instance_id = - instance_id_driver_->GetInstanceID(kApplicationName); + instance_id_driver_->GetInstanceID(GetApplicationName()); instance_id->GetID(base::Bind(&FCMInvalidationService::OnInstanceIdRecieved, base::Unretained(this))); } void FCMInvalidationService::ResetClientID() { instance_id::InstanceID* instance_id = - instance_id_driver_->GetInstanceID(kApplicationName); + instance_id_driver_->GetInstanceID(GetApplicationName()); instance_id->DeleteID(base::Bind(&FCMInvalidationService::OnDeleteIDCompleted, base::Unretained(this))); - pref_service_->SetString(prefs::kFCMInvalidationClientIDCache, std::string()); + DictionaryPrefUpdate update(pref_service_, prefs::kInvalidationClientIDCache); + update->RemoveKey(sender_id_); } void FCMInvalidationService::OnInstanceIdRecieved(const std::string& id) { diagnostic_info_.instance_id_received = base::Time::Now(); if (client_id_ != id) { client_id_ = id; - pref_service_->SetString(prefs::kFCMInvalidationClientIDCache, id); + DictionaryPrefUpdate update(pref_service_, + prefs::kInvalidationClientIDCache); + update->SetStringKey(sender_id_, id); invalidator_registrar_.UpdateInvalidatorId(id); } } @@ -300,6 +329,15 @@ update_was_requested_ = false; } +const std::string FCMInvalidationService::GetApplicationName() { + // If using the default |sender_id_|, use the bare |kApplicationName|, so the + // old app name is maintained. + if (sender_id_ == kInvalidationGCMSenderId) { + return kApplicationName; + } + return base::StrCat({kApplicationName, "-", sender_id_}); +} + FCMInvalidationService::Diagnostics::Diagnostics() {} base::DictionaryValue FCMInvalidationService::Diagnostics::CollectDebugData()
diff --git a/components/invalidation/impl/fcm_invalidation_service.h b/components/invalidation/impl/fcm_invalidation_service.h index 476a0fd..d08dc45 100644 --- a/components/invalidation/impl/fcm_invalidation_service.h +++ b/components/invalidation/impl/fcm_invalidation_service.h
@@ -44,7 +44,8 @@ instance_id::InstanceIDDriver* client_id_driver, PrefService* pref_service, const syncer::ParseJSONCallback& parse_json, - network::mojom::URLLoaderFactory* loader_factory); + network::mojom::URLLoaderFactory* loader_factory, + const std::string& sender_id = {}); ~FCMInvalidationService() override; void Init(); @@ -113,6 +114,10 @@ void DoUpdateRegisteredIdsIfNeeded(); + const std::string GetApplicationName(); + + const std::string sender_id_; + syncer::InvalidatorRegistrarWithMemory invalidator_registrar_; std::unique_ptr<syncer::Invalidator> invalidator_;
diff --git a/components/invalidation/impl/fcm_invalidation_service_unittest.cc b/components/invalidation/impl/fcm_invalidation_service_unittest.cc index 30a1637..106bfd20 100644 --- a/components/invalidation/impl/fcm_invalidation_service_unittest.cc +++ b/components/invalidation/impl/fcm_invalidation_service_unittest.cc
@@ -104,8 +104,10 @@ public: FCMInvalidationServiceTestDelegate() { pref_service_.registry()->RegisterStringPref( - prefs::kFCMInvalidationClientIDCache, + prefs::kFCMInvalidationClientIDCacheDeprecated, /*default_value=*/std::string()); + pref_service_.registry()->RegisterDictionaryPref( + prefs::kInvalidationClientIDCache); syncer::InvalidatorRegistrarWithMemory::RegisterProfilePrefs( pref_service_.registry()); }
diff --git a/components/invalidation/impl/fcm_invalidator.cc b/components/invalidation/impl/fcm_invalidator.cc index e351848..be90afb 100644 --- a/components/invalidation/impl/fcm_invalidator.cc +++ b/components/invalidation/impl/fcm_invalidator.cc
@@ -20,10 +20,12 @@ PrefService* pref_service, network::mojom::URLLoaderFactory* loader_factory, const ParseJSONCallback& parse_json, - const std::string& project_id) + const std::string& project_id, + bool migrate_prefs) : invalidation_listener_(std::move(network_channel)) { auto registration_manager = std::make_unique<PerUserTopicRegistrationManager>( - identity_provider, pref_service, loader_factory, parse_json, project_id); + identity_provider, pref_service, loader_factory, parse_json, project_id, + migrate_prefs); invalidation_listener_.Start(this, std::move(registration_manager)); }
diff --git a/components/invalidation/impl/fcm_invalidator.h b/components/invalidation/impl/fcm_invalidator.h index 5ac250da..58af988 100644 --- a/components/invalidation/impl/fcm_invalidator.h +++ b/components/invalidation/impl/fcm_invalidator.h
@@ -33,7 +33,8 @@ PrefService* pref_service, network::mojom::URLLoaderFactory* loader_factory, const ParseJSONCallback& parse_json, - const std::string& project_id); + const std::string& project_id, + bool migrate_prefs); ~FCMInvalidator() override;
diff --git a/components/invalidation/impl/fcm_invalidator_unittest.cc b/components/invalidation/impl/fcm_invalidator_unittest.cc index d479016..370928aa 100644 --- a/components/invalidation/impl/fcm_invalidator_unittest.cc +++ b/components/invalidation/impl/fcm_invalidator_unittest.cc
@@ -54,8 +54,8 @@ invalidator_.reset(new FCMInvalidator( std::move(network_channel), identity_provider_.get(), &pref_service_, &url_loader_factory_, - base::BindRepeating(&syncer::JsonUnsafeParser::Parse), - "fake_sender_id")); + base::BindRepeating(&syncer::JsonUnsafeParser::Parse), "fake_sender_id", + false)); } Invalidator* GetInvalidator() { return invalidator_.get(); }
diff --git a/components/invalidation/impl/fcm_network_handler.cc b/components/invalidation/impl/fcm_network_handler.cc index 2220f5e..3bc63c9 100644 --- a/components/invalidation/impl/fcm_network_handler.cc +++ b/components/invalidation/impl/fcm_network_handler.cc
@@ -48,6 +48,30 @@ return value; } +// Unpacks the private topic included in messages to the form returned for +// subscription requests. +// +// Subscriptions for private topics generate a private topic from the public +// topic of the form "/private/${public_topic}-${something}. Messages include +// this as the sender in the form +// "/topics/private/${public_topic}-${something}". For such messages, strip the +// "/topics" prefix. +// +// Subscriptions for public topics pass-through the public topic unchanged: +// "${public_topic}". Messages include the sender in the form +// "/topics/${public_topic}". For these messages, strip the "/topics/" prefix. +// +// If the provided sender does not match either pattern, return it unchanged. +std::string UnpackPrivateTopic(base::StringPiece private_topic) { + if (private_topic.starts_with("/topics/private/")) { + return private_topic.substr(strlen("/topics")).as_string(); + } else if (private_topic.starts_with("/topics/")) { + return private_topic.substr(strlen("/topics/")).as_string(); + } else { + return private_topic.as_string(); + } +} + InvalidationParsingStatus ParseIncommingMessage( const gcm::IncomingMessage& message, std::string* payload, @@ -63,11 +87,7 @@ *public_topic = GetValueFromMessage(message, kPublicTopic); - // Public topic must always be there. - if (public_topic->empty()) - return InvalidationParsingStatus::kPublicTopicEmpty; - - *private_topic = message.sender_id; + *private_topic = UnpackPrivateTopic(message.sender_id); if (private_topic->empty()) return InvalidationParsingStatus::kPrivateTopicEmpty;
diff --git a/components/invalidation/impl/fcm_network_handler_unittests.cc b/components/invalidation/impl/fcm_network_handler_unittests.cc index 41decf4..a056964 100644 --- a/components/invalidation/impl/fcm_network_handler_unittests.cc +++ b/components/invalidation/impl/fcm_network_handler_unittests.cc
@@ -51,7 +51,6 @@ gcm::IncomingMessage message; message.data["payload"] = "payload"; message.data["version"] = "version"; - message.data["external_name"] = "public_topic"; message.sender_id = "private_topic"; return message; } @@ -333,15 +332,20 @@ std::unique_ptr<FCMNetworkHandler> handler = MakeHandlerReadyForMessage(mock_on_message_callback.Get()); EXPECT_CALL(mock_on_message_callback, + Run("payload", "private_topic", "", "version")) + .Times(1); + EXPECT_CALL(mock_on_message_callback, Run("payload", "private_topic", "public_topic", "version")) .Times(1); handler->OnMessage(kInvalidationsAppId, message); + message.data["external_name"] = "public_topic"; + handler->OnMessage(kInvalidationsAppId, message); EXPECT_THAT( histogram_tester.GetAllSamples("FCMInvalidations.FCMMessageStatus"), testing::ElementsAre(base::Bucket( static_cast<int>(InvalidationParsingStatus::kSuccess) /* min */, - 1 /* count */))); + 2 /* count */))); } TEST_F(FCMNetworkHandlerTest, @@ -365,27 +369,6 @@ } TEST_F(FCMNetworkHandlerTest, - ShouldNotInvokeMessageCallbackOnMessageWithEmptyPublicTopic) { - base::HistogramTester histogram_tester; - MockOnMessageCallback mock_on_message_callback; - gcm::IncomingMessage message = CreateValidMessage(); - // Clear public topic. - auto it = message.data.find("external_name"); - message.data.erase(it); - - std::unique_ptr<FCMNetworkHandler> handler = - MakeHandlerReadyForMessage(mock_on_message_callback.Get()); - EXPECT_CALL(mock_on_message_callback, Run(_, _, _, _)).Times(0); - handler->OnMessage(kInvalidationsAppId, message); - EXPECT_THAT( - histogram_tester.GetAllSamples("FCMInvalidations.FCMMessageStatus"), - testing::ElementsAre(base::Bucket( - static_cast<int>( - InvalidationParsingStatus::kPublicTopicEmpty) /* min */, - 1 /* count */))); -} - -TEST_F(FCMNetworkHandlerTest, ShouldNotInvokeMessageCallbackOnMessageWithEmptyPrivateTopic) { base::HistogramTester histogram_tester; MockOnMessageCallback mock_on_message_callback;
diff --git a/components/invalidation/impl/invalidation_prefs.cc b/components/invalidation/impl/invalidation_prefs.cc index 80278f5..17ffe6ce 100644 --- a/components/invalidation/impl/invalidation_prefs.cc +++ b/components/invalidation/impl/invalidation_prefs.cc
@@ -19,7 +19,12 @@ const char kInvalidatorSavedInvalidations[] = "invalidator.saved_invalidations"; // The prefference for storing client ID for the invalidator. -const char kFCMInvalidationClientIDCache[] = "fcm.invalidation.client_id_cache"; +const char kFCMInvalidationClientIDCacheDeprecated[] = + "fcm.invalidation.client_id_cache"; + +// The preference for storing client ID for the invalidator, keyed by sender ID. +const char kInvalidationClientIDCache[] = + "invalidation.per_sender_client_id_cache"; } // namespace prefs } // namespace invalidation
diff --git a/components/invalidation/impl/invalidation_prefs.h b/components/invalidation/impl/invalidation_prefs.h index ec6492d..35713c38 100644 --- a/components/invalidation/impl/invalidation_prefs.h +++ b/components/invalidation/impl/invalidation_prefs.h
@@ -14,7 +14,9 @@ extern const char kInvalidatorSavedInvalidations[]; -extern const char kFCMInvalidationClientIDCache[]; +extern const char kFCMInvalidationClientIDCacheDeprecated[]; + +extern const char kInvalidationClientIDCache[]; } // namespace prefs } // namespace invalidation
diff --git a/components/invalidation/impl/invalidator_registrar_with_memory.cc b/components/invalidation/impl/invalidator_registrar_with_memory.cc index 7596d09b..bca34ed 100644 --- a/components/invalidation/impl/invalidator_registrar_with_memory.cc +++ b/components/invalidation/impl/invalidator_registrar_with_memory.cc
@@ -10,6 +10,7 @@ #include <utility> #include "base/logging.h" +#include "base/values.h" #include "components/invalidation/public/object_id_invalidation_map.h" #include "components/invalidation/public/topic_invalidation_map.h" #include "components/prefs/pref_registry_simple.h" @@ -19,20 +20,47 @@ namespace { -const char kTopicsToHandler[] = "invalidation.topics_to_handler"; +const char kTopicsToHandlerDeprecated[] = "invalidation.topics_to_handler"; + +const char kTopicsToHandler[] = "invalidation.per_sender_topics_to_handler"; + +// Added in M76. +void MigratePrefs(PrefService* prefs, const std::string& sender_id) { + auto* old_prefs = prefs->GetDictionary(kTopicsToHandlerDeprecated); + if (old_prefs->empty()) { + return; + } + { + DictionaryPrefUpdate update(prefs, kTopicsToHandler); + update->SetKey(sender_id, old_prefs->Clone()); + } + prefs->ClearPref(kTopicsToHandlerDeprecated); +} } // namespace // static void InvalidatorRegistrarWithMemory::RegisterProfilePrefs( PrefRegistrySimple* registry) { + registry->RegisterDictionaryPref(kTopicsToHandlerDeprecated); registry->RegisterDictionaryPref(kTopicsToHandler); } InvalidatorRegistrarWithMemory::InvalidatorRegistrarWithMemory( - PrefService* local_state) - : InvalidatorRegistrar(), local_state_(local_state) { - const base::Value* pref_data = local_state_->Get(kTopicsToHandler); + PrefService* local_state, + const std::string& sender_id, + bool migrate_old_prefs) + : InvalidatorRegistrar(), local_state_(local_state), sender_id_(sender_id) { + if (migrate_old_prefs) { + MigratePrefs(local_state_, sender_id_); + } + const base::Value* pref_data = + local_state_->Get(kTopicsToHandler)->FindDictKey(sender_id_); + if (!pref_data) { + DictionaryPrefUpdate update(local_state_, kTopicsToHandler); + update->SetKey(sender_id_, base::DictionaryValue()); + return; + } for (const auto& it : pref_data->DictItems()) { Topic topic = it.first; std::string handler_name; @@ -54,19 +82,20 @@ TopicSet to_unregister; DictionaryPrefUpdate update(local_state_, kTopicsToHandler); + base::Value* pref_data = update->FindDictKey(sender_id_); std::set_difference(old_topics.begin(), old_topics.end(), topics.begin(), topics.end(), std::inserter(to_unregister, to_unregister.begin())); if (!to_unregister.empty()) { for (const auto& topic : to_unregister) { - update->RemoveKey(topic); + pref_data->RemoveKey(topic); handler_name_to_topics_map_[handler->GetOwnerName()].erase(topic); } } for (const auto& topic : topics) { handler_name_to_topics_map_[handler->GetOwnerName()].insert(topic); - update->SetKey(topic, base::Value(handler->GetOwnerName())); + pref_data->SetKey(topic, base::Value(handler->GetOwnerName())); } return success; }
diff --git a/components/invalidation/impl/invalidator_registrar_with_memory.h b/components/invalidation/impl/invalidator_registrar_with_memory.h index c3eb971..85aae59b 100644 --- a/components/invalidation/impl/invalidator_registrar_with_memory.h +++ b/components/invalidation/impl/invalidator_registrar_with_memory.h
@@ -31,7 +31,9 @@ class INVALIDATION_EXPORT InvalidatorRegistrarWithMemory : public InvalidatorRegistrar { public: - InvalidatorRegistrarWithMemory(PrefService* local_state); + InvalidatorRegistrarWithMemory(PrefService* local_state, + const std::string& sender_id, + bool migrate_old_prefs); // It is an error to have registered handlers on destruction. ~InvalidatorRegistrarWithMemory(); @@ -65,6 +67,7 @@ handler_name_to_handler_; HandlerNameTopicsMap handler_name_to_topics_map_; PrefService* local_state_; + const std::string sender_id_; DISALLOW_COPY_AND_ASSIGN(InvalidatorRegistrarWithMemory); };
diff --git a/components/invalidation/impl/per_user_topic_registration_manager.cc b/components/invalidation/impl/per_user_topic_registration_manager.cc index 2b6f5af..83f1edf 100644 --- a/components/invalidation/impl/per_user_topic_registration_manager.cc +++ b/components/invalidation/impl/per_user_topic_registration_manager.cc
@@ -17,7 +17,9 @@ #include "base/feature_list.h" #include "base/rand_util.h" #include "base/stl_util.h" +#include "base/strings/strcat.h" #include "base/strings/stringprintf.h" +#include "base/values.h" #include "components/gcm_driver/instance_id/instance_id_driver.h" #include "components/invalidation/impl/invalidation_switches.h" #include "components/invalidation/public/identity_provider.h" @@ -30,12 +32,18 @@ namespace { -const char kTypeRegisteredForInvalidation[] = +const char kTypeRegisteredForInvalidationsDeprecated[] = "invalidation.registered_for_invalidation"; -const char kActiveRegistrationToken[] = +const char kTypeRegisteredForInvalidations[] = + "invalidation.per_sender_registered_for_invalidation"; + +const char kActiveRegistrationTokenDeprecated[] = "invalidation.active_registration_token"; +const char kActiveRegistrationTokens[] = + "invalidation.per_sender_active_registration_tokens"; + const char kInvalidationRegistrationScope[] = "https://firebaseperusertopics-pa.googleapis.com"; @@ -74,13 +82,61 @@ false, }; +class PerProjectDictionaryPrefUpdate { + public: + explicit PerProjectDictionaryPrefUpdate(PrefService* prefs, + const std::string& project_id) + : update_(prefs, kTypeRegisteredForInvalidations) { + per_sender_pref_ = update_->FindDictKey(project_id); + if (!per_sender_pref_) { + update_->SetDictionary(project_id, + std::make_unique<base::DictionaryValue>()); + per_sender_pref_ = update_->FindDictKey(project_id); + } + DCHECK(per_sender_pref_); + } + + base::Value& operator*() { return *per_sender_pref_; } + + base::Value* operator->() { return per_sender_pref_; } + + private: + DictionaryPrefUpdate update_; + base::Value* per_sender_pref_; +}; + +// Added in M76. +void MigratePrefs(PrefService* prefs, const std::string& project_id) { + if (!prefs->HasPrefPath(kActiveRegistrationTokenDeprecated)) { + return; + } + { + DictionaryPrefUpdate token_update(prefs, kActiveRegistrationTokens); + token_update->SetString( + project_id, prefs->GetString(kActiveRegistrationTokenDeprecated)); + } + + auto* old_registrations = + prefs->GetDictionary(kTypeRegisteredForInvalidationsDeprecated); + { + PerProjectDictionaryPrefUpdate update(prefs, project_id); + *update = old_registrations->Clone(); + } + prefs->ClearPref(kActiveRegistrationTokenDeprecated); + prefs->ClearPref(kTypeRegisteredForInvalidationsDeprecated); +} + } // namespace // static void PerUserTopicRegistrationManager::RegisterProfilePrefs( PrefRegistrySimple* registry) { - registry->RegisterDictionaryPref(kTypeRegisteredForInvalidation); - registry->RegisterStringPref(kActiveRegistrationToken, std::string()); + registry->RegisterDictionaryPref(kTypeRegisteredForInvalidationsDeprecated); + registry->RegisterStringPref(kActiveRegistrationTokenDeprecated, + std::string()); + + registry->RegisterDictionaryPref(kTypeRegisteredForInvalidations); + registry->RegisterDictionaryPref(kActiveRegistrationTokens); } struct PerUserTopicRegistrationManager::RegistrationEntry { @@ -134,28 +190,37 @@ PrefService* local_state, network::mojom::URLLoaderFactory* url_loader_factory, const ParseJSONCallback& parse_json, - const std::string& project_id) + const std::string& project_id, + bool migrate_prefs) : local_state_(local_state), identity_provider_(identity_provider), request_access_token_backoff_(&kBackoffPolicy), parse_json_(parse_json), url_loader_factory_(url_loader_factory), - project_id_(project_id) {} + project_id_(project_id), + migrate_prefs_(migrate_prefs) {} PerUserTopicRegistrationManager::~PerUserTopicRegistrationManager() {} void PerUserTopicRegistrationManager::Init() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const base::Value* pref_data = - local_state_->Get(kTypeRegisteredForInvalidation); + if (migrate_prefs_) { + MigratePrefs(local_state_, project_id_); + } + PerProjectDictionaryPrefUpdate update(local_state_, project_id_); + if (update->DictEmpty()) { + return; + } + std::vector<std::string> keys_to_remove; // Load registered ids from prefs. - for (const auto& it : pref_data->DictItems()) { + for (const auto& it : update->DictItems()) { Topic topic = it.first; std::string private_topic_name; if (it.second.GetAsString(&private_topic_name) && !private_topic_name.empty()) { topic_to_private_topic_[topic] = private_topic_name; + private_topic_to_topic_[private_topic_name] = topic; continue; } // Remove saved pref. @@ -163,10 +228,8 @@ } // Delete prefs, which weren't decoded successfully. - DictionaryPrefUpdate update(local_state_, kTypeRegisteredForInvalidation); - base::DictionaryValue* pref_update = update.Get(); for (const std::string& key : keys_to_remove) { - pref_update->RemoveKey(key); + update->RemoveKey(key); } } @@ -204,10 +267,11 @@ &PerUserTopicRegistrationManager::RegistrationFinishedForTopic, base::Unretained(this)), PerUserTopicRegistrationRequest::UNSUBSCRIBE); + private_topic_to_topic_.erase(it->second); it = topic_to_private_topic_.erase(it); // The descision to unregister from the invalidations for the |topic| was // made, the preferences should be cleaned up immediatelly. - DictionaryPrefUpdate update(local_state_, kTypeRegisteredForInvalidation); + PerProjectDictionaryPrefUpdate update(local_state_, project_id_); update->RemoveKey(topic); } else { ++it; @@ -255,9 +319,10 @@ it->second->request_backoff_.InformOfRequest(true); registration_statuses_.erase(it); if (type == PerUserTopicRegistrationRequest::SUBSCRIBE) { - DictionaryPrefUpdate update(local_state_, kTypeRegisteredForInvalidation); + PerProjectDictionaryPrefUpdate update(local_state_, project_id_); update->SetKey(topic, base::Value(private_topic_name)); topic_to_private_topic_[topic] = private_topic_name; + private_topic_to_topic_[private_topic_name] = topic; local_state_->CommitPendingWrite(); } bool all_subscription_completed = true; @@ -393,20 +458,24 @@ void PerUserTopicRegistrationManager::DropAllSavedRegistrationsOnTokenChange( const std::string& instance_id_token) { - std::string current_token = local_state_->GetString(kActiveRegistrationToken); - if (current_token.empty()) { - local_state_->SetString(kActiveRegistrationToken, instance_id_token); - return; + { + DictionaryPrefUpdate token_update(local_state_, kActiveRegistrationTokens); + std::string current_token; + token_update->GetString(project_id_, ¤t_token); + if (current_token.empty()) { + token_update->SetString(project_id_, instance_id_token); + return; + } + if (current_token == instance_id_token) { + return; + } + token_update->SetString(project_id_, instance_id_token); } - if (current_token == instance_id_token) { - return; - } - local_state_->SetString(kActiveRegistrationToken, instance_id_token); - DictionaryPrefUpdate update(local_state_, kTypeRegisteredForInvalidation); - for (const auto& topic : topic_to_private_topic_) { - update->RemoveKey(topic.first); - } + + PerProjectDictionaryPrefUpdate update(local_state_, project_id_); + *update = base::Value(base::Value::Type::DICTIONARY); topic_to_private_topic_.clear(); + private_topic_to_topic_.clear(); // TODO(melandory): Figure out if the unsubscribe request should be // sent with the old token. } @@ -438,4 +507,14 @@ return status; } +base::Optional<Topic> +PerUserTopicRegistrationManager::LookupRegisteredPublicTopicByPrivateTopic( + const std::string& private_topic) const { + auto it = private_topic_to_topic_.find(private_topic); + if (it == private_topic_to_topic_.end()) { + return base::nullopt; + } + return it->second; +} + } // namespace syncer
diff --git a/components/invalidation/impl/per_user_topic_registration_manager.h b/components/invalidation/impl/per_user_topic_registration_manager.h index 7bff4f69..564e75ea 100644 --- a/components/invalidation/impl/per_user_topic_registration_manager.h +++ b/components/invalidation/impl/per_user_topic_registration_manager.h
@@ -55,7 +55,8 @@ PrefService* local_state, network::mojom::URLLoaderFactory* url_loader_factory, const ParseJSONCallback& parse_json, - const std::string& project_id); + const std::string& project_id, + bool migrate_prefs); virtual ~PerUserTopicRegistrationManager(); @@ -78,6 +79,9 @@ return registration_statuses_.empty(); } + virtual base::Optional<Topic> LookupRegisteredPublicTopicByPrivateTopic( + const std::string& private_topic) const; + private: struct RegistrationEntry; @@ -113,6 +117,7 @@ // For registered ids it maps the id value to the topic value. std::map<Topic, std::string> topic_to_private_topic_; + std::map<std::string, Topic> private_topic_to_topic_; // Token derrived from GCM IID. std::string token_; @@ -131,6 +136,7 @@ network::mojom::URLLoaderFactory* url_loader_factory_; const std::string project_id_; + const bool migrate_prefs_; base::ObserverList<Observer>::Unchecked observers_; SubscriptionChannelState last_issued_state_ =
diff --git a/components/invalidation/impl/per_user_topic_registration_manager_unittest.cc b/components/invalidation/impl/per_user_topic_registration_manager_unittest.cc index 2d13321..64dfd0c 100644 --- a/components/invalidation/impl/per_user_topic_registration_manager_unittest.cc +++ b/components/invalidation/impl/per_user_topic_registration_manager_unittest.cc
@@ -37,10 +37,10 @@ const char kProjectId[] = "8181035976"; const char kTypeRegisteredForInvalidation[] = - "invalidation.registered_for_invalidation"; + "invalidation.per_sender_registered_for_invalidation"; -const char kActiveRegistrationToken[] = - "invalidation.active_registration_token"; +const char kActiveRegistrationTokens[] = + "invalidation.per_sender_active_registration_tokens"; const char kFakeInstanceIdToken[] = "fake_instance_id_token"; @@ -124,10 +124,12 @@ identity_provider_->SetActiveAccountId(account.account_id); } - std::unique_ptr<PerUserTopicRegistrationManager> BuildRegistrationManager() { + std::unique_ptr<PerUserTopicRegistrationManager> BuildRegistrationManager( + bool migrate_prefs = true) { auto reg_manager = std::make_unique<PerUserTopicRegistrationManager>( identity_provider_.get(), &pref_service_, url_loader_factory(), - base::BindRepeating(&syncer::JsonUnsafeParser::Parse), kProjectId); + base::BindRepeating(&syncer::JsonUnsafeParser::Parse), kProjectId, + migrate_prefs); reg_manager->Init(); reg_manager->AddObserver(&state_observer_); return reg_manager; @@ -139,6 +141,12 @@ TestingPrefServiceSimple* pref_service() { return &pref_service_; } + const base::Value* GetRegisteredTopics() { + return pref_service() + ->GetDictionary(kTypeRegisteredForInvalidation) + ->FindDictKey(kProjectId); + } + SubscriptionChannelState observed_state() { return state_observer_.observed_state(); } @@ -220,8 +228,7 @@ per_user_topic_registration_manager->HaveAllRequestsFinishedForTest()); for (const auto& id : ids) { - const base::DictionaryValue* topics = - pref_service()->GetDictionary(kTypeRegisteredForInvalidation); + const base::Value* topics = GetRegisteredTopics(); const base::Value* private_topic_value = topics->FindKeyOfType(id, base::Value::Type::STRING); ASSERT_NE(private_topic_value, nullptr); @@ -293,16 +300,14 @@ // ids were disabled, check that they're not in the prefs. for (const auto& id : disabled_ids) { - const base::DictionaryValue* topics = - pref_service()->GetDictionary(kTypeRegisteredForInvalidation); + const base::Value* topics = GetRegisteredTopics(); const base::Value* private_topic_value = topics->FindKey(id); ASSERT_EQ(private_topic_value, nullptr); } // Check that enable ids are still in the prefs. for (const auto& id : enabled_ids) { - const base::DictionaryValue* topics = - pref_service()->GetDictionary(kTypeRegisteredForInvalidation); + const base::Value* topics = GetRegisteredTopics(); const base::Value* private_topic_value = topics->FindKeyOfType(id, base::Value::Type::STRING); ASSERT_NE(private_topic_value, nullptr); @@ -326,8 +331,7 @@ EXPECT_EQ(ids, per_user_topic_registration_manager->GetRegisteredIds()); for (const auto& id : ids) { - const base::DictionaryValue* topics = - pref_service()->GetDictionary(kTypeRegisteredForInvalidation); + const base::Value* topics = GetRegisteredTopics(); const base::Value* private_topic_value = topics->FindKeyOfType(id, base::Value::Type::STRING); ASSERT_NE(private_topic_value, nullptr); @@ -337,7 +341,9 @@ } EXPECT_EQ(kFakeInstanceIdToken, - pref_service()->GetString(kActiveRegistrationToken)); + *pref_service() + ->GetDictionary(kActiveRegistrationTokens) + ->FindStringKey(kProjectId)); std::string token = "new-fake-token"; AddCorrectSubscriptionResponce("new-token-topic", token); @@ -345,12 +351,13 @@ per_user_topic_registration_manager->UpdateRegisteredTopics(ids, token); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(token, pref_service()->GetString(kActiveRegistrationToken)); + EXPECT_EQ(token, *pref_service() + ->GetDictionary(kActiveRegistrationTokens) + ->FindStringKey(kProjectId)); EXPECT_EQ(ids, per_user_topic_registration_manager->GetRegisteredIds()); for (const auto& id : ids) { - const base::DictionaryValue* topics = - pref_service()->GetDictionary(kTypeRegisteredForInvalidation); + const base::Value* topics = GetRegisteredTopics(); const base::Value* private_topic_value = topics->FindKeyOfType(id, base::Value::Type::STRING); ASSERT_NE(private_topic_value, nullptr); @@ -385,16 +392,14 @@ // Ids should still be removed from prefs. for (const auto& id : disabled_ids) { - const base::DictionaryValue* topics = - pref_service()->GetDictionary(kTypeRegisteredForInvalidation); + const base::Value* topics = GetRegisteredTopics(); const base::Value* private_topic_value = topics->FindKey(id); ASSERT_EQ(private_topic_value, nullptr); } // Check that enable ids are still in the prefs. for (const auto& id : enabled_ids) { - const base::DictionaryValue* topics = - pref_service()->GetDictionary(kTypeRegisteredForInvalidation); + const base::Value* topics = GetRegisteredTopics(); const base::Value* private_topic_value = topics->FindKeyOfType(id, base::Value::Type::STRING); ASSERT_NE(private_topic_value, nullptr);
diff --git a/components/invalidation/impl/per_user_topic_registration_request.cc b/components/invalidation/impl/per_user_topic_registration_request.cc index 41554fe..336ab437 100644 --- a/components/invalidation/impl/per_user_topic_registration_request.cc +++ b/components/invalidation/impl/per_user_topic_registration_request.cc
@@ -20,12 +20,16 @@ namespace { +const char kPublicTopicNameKey[] = "publicTopicName"; const char kPrivateTopicNameKey[] = "privateTopicName"; -base::Value* GetPrivateTopicName(base::Value* value) { +base::Value* GetTopicName(base::Value* value) { if (!value || !value->is_dict()) { return nullptr; } + if (value->FindBoolKey("isPublic").value_or(false)) { + return value->FindKeyOfType(kPublicTopicNameKey, base::Value::Type::STRING); + } return value->FindKeyOfType(kPrivateTopicNameKey, base::Value::Type::STRING); } @@ -77,6 +81,13 @@ } } +bool IsPublicTopic(const base::StringPiece topic) { + // Team Drive topics are public. + // TODO(crbug.com/912281): Replace with plumbing this through from the + // InvalidationHandler. + return topic.starts_with("team-drive-"); +} + } // namespace namespace syncer { @@ -179,8 +190,7 @@ void PerUserTopicRegistrationRequest::OnJsonParseSuccess( std::unique_ptr<base::Value> value) { - const base::Value* private_topic_name_value = - GetPrivateTopicName(value.get()); + const base::Value* private_topic_name_value = GetTopicName(value.get()); RecordRequestStatus(SubscriptionStatus::kSuccess, type_, topic_); if (private_topic_name_value) { std::move(request_completed_callback_) @@ -212,9 +222,14 @@ scope_.c_str(), project_id_.c_str(), token_.c_str()); break; case UNSUBSCRIBE: + std::string public_param; + if (IsPublicTopic(topic_)) { + public_param = "subscription.is_public=true&"; + } url = base::StringPrintf( - "%s/v1/perusertopics/%s/rel/topics/%s?subscriber_token=%s", - scope_.c_str(), project_id_.c_str(), topic_.c_str(), token_.c_str()); + "%s/v1/perusertopics/%s/rel/topics/%s?%ssubscriber_token=%s", + scope_.c_str(), project_id_.c_str(), topic_.c_str(), + public_param.c_str(), token_.c_str()); break; } GURL full_url(url); @@ -290,6 +305,9 @@ base::DictionaryValue request; request.SetString("public_topic_name", topic_); + if (IsPublicTopic(topic_)) { + request.SetBoolean("is_public", true); + } std::string request_json; bool success = base::JSONWriter::Write(request, &request_json);
diff --git a/components/invalidation/impl/profile_invalidation_provider.cc b/components/invalidation/impl/profile_invalidation_provider.cc index ba1ec9c..f5c1681a 100644 --- a/components/invalidation/impl/profile_invalidation_provider.cc +++ b/components/invalidation/impl/profile_invalidation_provider.cc
@@ -14,9 +14,13 @@ ProfileInvalidationProvider::ProfileInvalidationProvider( std::unique_ptr<InvalidationService> invalidation_service, - std::unique_ptr<IdentityProvider> identity_provider) + std::unique_ptr<IdentityProvider> identity_provider, + CustomSenderInvalidationServiceFactory + custom_sender_invalidation_service_factory) : identity_provider_(std::move(identity_provider)), - invalidation_service_(std::move(invalidation_service)) {} + invalidation_service_(std::move(invalidation_service)), + custom_sender_invalidation_service_factory_( + std::move(custom_sender_invalidation_service_factory)) {} ProfileInvalidationProvider::~ProfileInvalidationProvider() { } @@ -29,15 +33,32 @@ return identity_provider_.get(); } +InvalidationService* +ProfileInvalidationProvider::GetInvalidationServiceForCustomSender( + const std::string& sender_id) { + DCHECK(custom_sender_invalidation_service_factory_); + + std::unique_ptr<InvalidationService>& invalidation_service = + custom_sender_invalidation_services_[sender_id]; + if (!invalidation_service) { + invalidation_service = + custom_sender_invalidation_service_factory_.Run(sender_id); + } + return invalidation_service.get(); +} + void ProfileInvalidationProvider::Shutdown() { invalidation_service_.reset(); + custom_sender_invalidation_services_.clear(); + custom_sender_invalidation_service_factory_.Reset(); } // static void ProfileInvalidationProvider::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref(prefs::kFCMInvalidationClientIDCache, + registry->RegisterStringPref(prefs::kFCMInvalidationClientIDCacheDeprecated, /*default_value=*/std::string()); + registry->RegisterDictionaryPref(prefs::kInvalidationClientIDCache); } } // namespace invalidation
diff --git a/components/invalidation/impl/profile_invalidation_provider.h b/components/invalidation/impl/profile_invalidation_provider.h index a7ef8e6..81b2e18 100644 --- a/components/invalidation/impl/profile_invalidation_provider.h +++ b/components/invalidation/impl/profile_invalidation_provider.h
@@ -6,6 +6,8 @@ #define COMPONENTS_INVALIDATION_IMPL_PROFILE_INVALIDATION_PROVIDER_H_ #include <memory> +#include <string> +#include <unordered_map> #include "base/compiler_specific.h" #include "base/macros.h" @@ -23,13 +25,26 @@ // A KeyedService that owns an InvalidationService. class ProfileInvalidationProvider : public KeyedService { public: - explicit ProfileInvalidationProvider( + using CustomSenderInvalidationServiceFactory = + base::RepeatingCallback<std::unique_ptr<InvalidationService>( + const std::string&)>; + ProfileInvalidationProvider( std::unique_ptr<InvalidationService> invalidation_service, - std::unique_ptr<IdentityProvider> identity_provider); + std::unique_ptr<IdentityProvider> identity_provider, + CustomSenderInvalidationServiceFactory + custom_sender_invalidation_service_factory = {}); ~ProfileInvalidationProvider() override; + // Returns the common Profile-wide InvalidationService; this should be used + // when using the deprecated invalidation provider or the FCM invalidation + // provider for Chrome Sync. InvalidationService* GetInvalidationService(); + // Returns the InvalidationService specific to |sender_id|. This should be + // used with the FCM invalidation provider for senders other than Chrome Sync. + InvalidationService* GetInvalidationServiceForCustomSender( + const std::string& sender_id); + IdentityProvider* GetIdentityProvider(); // KeyedService: @@ -47,6 +62,11 @@ std::unique_ptr<IdentityProvider> identity_provider_; std::unique_ptr<InvalidationService> invalidation_service_; + CustomSenderInvalidationServiceFactory + custom_sender_invalidation_service_factory_; + std::unordered_map<std::string, std::unique_ptr<InvalidationService>> + custom_sender_invalidation_services_; + DISALLOW_COPY_AND_ASSIGN(ProfileInvalidationProvider); };
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 8ee2f123..b6c37c6 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -187,6 +187,17 @@ # values will be masked with '********' in the chrome://policy UI and policy # exports. 'sensitiveValue' can be applied to all schema types. # +# For some policies which have complicated schema we add either +# 'description_schema' which describes some but not necessarily all properties +# of the policy or 'url_schema' which contains the link to the expanded +# documentation. +# Note that 'description_schema' is used for documentation purposes only, but +# not for schema validation. It can be used in cases where validation is not +# desired, e.g. if the schema does not describe all properties (see +# ArcPolicy). +# +# TODO(crbug.com/960274): Add translations of the schemas. +# # IDs: # Since a Protocol Buffer definition is generated from this file, unique and # persistent IDs for all fields (but not for groups!) are needed. These are @@ -3719,6 +3730,7 @@ }, }, }, + 'url_schema': 'https://www.chromium.org/administrators/policy-list-3/extension-settings-full', 'supported_on': ['chrome.*:62-', 'chrome_os:62-'], 'features': { 'dynamic_refresh': True, @@ -3774,8 +3786,6 @@ This policy maps an extension ID or an update URL to its configuration. With an extension ID, configuration will be applied to the specified extension only. A default configuration can be set for the special ID <ph name="DEFAULT_SCOPE">"*"</ph>, which will apply to all extensions that don't have a custom configuration set in this policy. With an update URL, configuration will be applied to all extensions with the exact update URL stated in manifest of this extension, as described at <ph name="LINK_TO_EXTENSION_DOC1">https://developer.chrome.com/extensions/autoupdate</ph>. For Windows instances that are not joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain, forced installation is limited to apps and extensions listed in the Chrome Web Store. - - For a full description of possible settings and structure of this policy please visit https://www.chromium.org/administrators/policy-list-3/extension-settings-full ''', }, { @@ -6229,6 +6239,7 @@ 'name': 'OpenNetworkConfiguration', 'type': 'string', 'schema': { 'type': 'string' }, + 'url_schema': 'https://chromium.googlesource.com/chromium/src/+/master/components/onc/docs/onc_spec.md', 'supported_on': ['chrome_os:16-'], 'features': { 'dynamic_refresh': True, @@ -6238,13 +6249,14 @@ 'id': 107, 'caption': '''User-level network configuration''', 'tags': ['full-admin-access'], - 'desc': '''Allows pushing network configuration to be applied per-user to a <ph name="PRODUCT_OS_NAME">$2<ex>Chromium OS</ex></ph> device. The network configuration is a JSON-formatted string as defined by the Open Network Configuration format described at <ph name="ONC_SPEC_URL">https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/open-network-configuration</ph>''', + 'desc': '''Allows pushing network configuration to be applied per-user to a <ph name="PRODUCT_OS_NAME">$2<ex>Chromium OS</ex></ph> device. The network configuration is a JSON-formatted string as defined by the Open Network Configuration format.''', 'arc_support': 'Android apps can use the network configurations and CA certificates set via this policy, but do not have access to some configuration options.', }, { 'name': 'DeviceOpenNetworkConfiguration', 'type': 'string', 'schema': { 'type': 'string' }, + 'url_schema': 'https://chromium.googlesource.com/chromium/src/+/master/components/onc/docs/onc_spec.md', 'supported_on': ['chrome_os:16-'], 'device_only': True, 'features': { @@ -6254,7 +6266,7 @@ 'id': 108, 'caption': '''Device-level network configuration''', 'tags': ['full-admin-access'], - 'desc': '''Allows pushing network configuration to be applied for all users of a <ph name="PRODUCT_OS_NAME">$2<ex>Chromium OS</ex></ph> device. The network configuration is a JSON-formatted string as defined by the Open Network Configuration format described at <ph name="ONC_SPEC_URL">https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/open-network-configuration</ph>''', + 'desc': '''Allows pushing network configuration to be applied for all users of a <ph name="PRODUCT_OS_NAME">$2<ex>Chromium OS</ex></ph> device. The network configuration is a JSON-formatted string as defined by the Open Network Configuration format.''', 'arc_support': 'Android apps can use the network configurations and CA certificates set via this policy, but do not have access to some configuration options.', }, { @@ -6582,26 +6594,6 @@ If this policy is not set or matching printer is not found within the timeout, the printer defaults to built-in PDF printer or no printer selected, when PDF printer is not available. - The value is parsed as JSON object, conforming to the following schema: - { - "type": "object", - "properties": { - "kind": { - "description": "Whether to limit the search of the matching printer to a specific set of printers.", - "type": "string", - "enum": [ "local", "cloud" ] - }, - "idPattern": { - "description": "Regular expression to match printer id.", - "type": "string" - }, - "namePattern": { - "description": "Regular expression to match printer display name.", - "type": "string" - } - } - } - Printers connected to <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph> are considered <ph name="PRINTER_TYPE_CLOUD">"cloud"</ph>, the rest of the printers are classified as <ph name="PRINTER_TYPE_LOCAL">"local"</ph>. Omitting a field means all values match, for example, not specifying connectivity will cause Print Preview to initiate the discovery of all kinds of printers, local and cloud. Regular expression patterns must follow the JavaScript RegExp syntax and matches are case sensistive.''', @@ -9986,8 +9978,14 @@ 'schema': { 'type': 'object', 'properties': { - 'url': { "type": "string" }, - 'hash': { "type": "string" } + 'url': { + 'description': 'The URL from which the avatar image can be downloaded.', + 'type': 'string' + }, + 'hash': { + 'description': 'The SHA-256 hash of the avatar image.', + 'type': 'string' + } }, }, 'supported_on': ['chrome_os:34-'], @@ -10004,21 +10002,6 @@ The avatar image is downloaded and cached. It will be re-downloaded whenever the URL or the hash changes. - The policy should be specified as a string that expresses the URL and hash in JSON format, conforming to the following schema: - { - "type": "object", - "properties": { - "url": { - "description": "The URL from which the avatar image can be downloaded.", - "type": "string" - }, - "hash": { - "description": "The SHA-256 hash of the avatar image.", - "type": "string" - } - } - } - If this policy is set, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will download and use the avatar image. If you set this policy, users cannot change or override it. @@ -10031,8 +10014,14 @@ 'schema': { 'type': 'object', 'properties': { - 'url': { "type": "string" }, - 'hash': { "type": "string" } + 'url': { + 'description': 'The URL from which the wallpaper image can be downloaded.', + 'type': 'string' + }, + 'hash': { + 'description': 'The SHA-256 hash of the wallpaper image.', + 'type': 'string' + } }, }, 'supported_on': ['chrome_os:35-'], @@ -10049,21 +10038,6 @@ The wallpaper image is downloaded and cached. It will be re-downloaded whenever the URL or the hash changes. - The policy should be specified as a string that expresses the URL and hash in JSON format, conforming to the following schema: - { - "type": "object", - "properties": { - "url": { - "description": "The URL from which the wallpaper image can be downloaded.", - "type": "string" - }, - "hash": { - "description": "The SHA-256 hash of the wallpaper image.", - "type": "string" - } - } - } - If this policy is set, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will download and use the wallpaper image. If you set this policy, users cannot change or override it. @@ -10853,21 +10827,7 @@ 'name': 'ArcPolicy', 'type': 'string', 'schema': { 'type': 'string' }, - 'supported_on': ['chrome_os:50-'], - 'features': { - 'dynamic_refresh': True, - 'per_profile': False, - }, - 'example_value': '{"applications":[{"packageName":"com.google.android.gm","installType":"FORCE_INSTALLED"},{"packageName":"com.google.android.apps.docs","installType":"PRELOAD"}]}', - 'id': 318, - 'caption': '''Configure ARC''', - 'tags': [], - 'desc': - '''Specifies a set of policies that will be handed over to the ARC runtime. The value must be valid JSON. - - This policy can be used to configure which Android apps are automatically installed on the device: - - { + 'description_schema': { "type": "object", "properties": { "applications": { @@ -10907,7 +10867,20 @@ } } } - } + }, + 'supported_on': ['chrome_os:50-'], + 'features': { + 'dynamic_refresh': True, + 'per_profile': False, + }, + 'example_value': '{"applications":[{"packageName":"com.google.android.gm","installType":"FORCE_INSTALLED","defaultPermissionPolicy":"PROMPT","managedConfiguration":{}},{"packageName":"com.google.android.apps.docs","installType":"PRELOAD","defaultPermissionPolicy":"PROMPT","managedConfiguration":{}}]}', + 'id': 318, + 'caption': '''Configure ARC''', + 'tags': [], + 'desc': + '''Specifies a set of policies that will be handed over to the ARC runtime. The value must be valid JSON. + + This policy can be used to configure which Android apps are automatically installed on the device. To pin apps to the launcher, see PinnedLauncherApps.''' }, @@ -12133,8 +12106,14 @@ 'schema': { 'type': 'object', 'properties': { - 'url': { "type": "string" }, - 'hash': { "type": "string" } + 'url': { + 'description': 'The URL from which the wallpaper image can be downloaded.', + 'type': 'string' + }, + 'hash': { + 'description': 'The SHA-256 hash of the wallpaper image.', + 'type': 'string' + } }, }, 'supported_on': ['chrome_os:61-'], @@ -12142,19 +12121,13 @@ 'features': { 'dynamic_refresh': True, }, - 'example_value': { "url": "https://example.com/device_wallpaper.jpg", "hash": "examplewallpaperexamplewallpaperexamplewallpaperexamplewallpaper" }, + 'example_value': { "url": "https://example.com/device_wallpaper.jpg", "hash": "1337c0ded00d84b1dbadf00dd15ea5eb000deaddeaddeaddeaddeaddeaddead0" }, 'max_size': 16777216, 'id': 357, 'caption': '''Device wallpaper image''', 'tags': [], 'desc': '''Configure device-level wallpaper image that is shown on the login screen if no user has yet signed in to the device. The policy is set by specifying the URL from which the Chrome OS device can download the wallpaper image and a cryptographic hash used to verify the integrity of the download. The image must be in JPEG format, its file size must not exceed 16MB. The URL must be accessible without any authentication. The wallpaper image is downloaded and cached. It will be re-downloaded whenever the URL or the hash changes. - The policy should be speicified as a string that expresses the URL and hash in JSON format, e.g., - { - "url": "https://example.com/device_wallpaper.jpg", - "hash": "examplewallpaperhash" - } - If the device wallpaper policy is set, the Chrome OS device will download and use the wallpaper image on the login screen if no user has yet signed in to the device. Once the user logs in, the user's wallpaper policy kicks in. If the device wallpaper policy is left not set, it's the user's wallpaper policy to decide what to show if the user's wallpaper policy is set.''', @@ -16115,6 +16088,14 @@ 'desc': '''Caption text of the field in the generated documentation that describes how a policy affects Android applications on Chrome OS''', 'text': '''Note for <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> devices supporting Android apps:''' }, + 'doc_schema': { + 'desc': '''Caption text of the 'schema' in the summary chart of a policy in the generated documentation''', + 'text': '''Schema:''' + }, + 'doc_url_schema': { + 'desc': '''Caption text of the field with the link to expanded schema description in the summary chart of a policy in the generated documentation''', + 'text': '''Expanded schema description:''' + }, 'doc_example_value': { 'desc': '''Caption text of the field 'example value' in the summary chart of a policy in the generated documentation''', 'text': '''Example value:''' @@ -16205,6 +16186,10 @@ 'desc': '''Caption text of the field 'maximum' in the summary chart of a policy in the generated documentation. Present only if policy has a maximum range restriction.''', 'text': '''Maximum:''' }, + 'doc_schema_description_link': { + 'desc': '''Text pointing the user to the expanded documentation page for this policy, containing the information about schema and formatting.''', + 'text': '''See <ph name="REFERENCE_URL">$6<ex>https://www.chromium.org/administrators/policy-list-3#WallpaperImage</ex></ph> for more information about schema and formatting.''' + }, 'deprecated_policy_group_caption': { 'desc': '''Localized name for the deprecated policies folder, for Microsoft's Group Policy Editor.''', 'text': '''Deprecated policies''',
diff --git a/components/policy/tools/syntax_check_policy_template_json.py b/components/policy/tools/syntax_check_policy_template_json.py index d5f463d..6be4b4f 100755 --- a/components/policy/tools/syntax_check_policy_template_json.py +++ b/components/policy/tools/syntax_check_policy_template_json.py
@@ -332,7 +332,8 @@ if key not in ('name', 'type', 'caption', 'desc', 'device_only', 'supported_on', 'label', 'policies', 'items', 'example_value', 'features', 'deprecated', 'future', 'id', - 'schema', 'validation_schema', 'max_size', 'tags', + 'schema', 'validation_schema', 'description_schema', + 'url_schema', 'max_size', 'tags', 'default_for_enterprise_users', 'default_for_managed_devices_doc_only', 'arc_support', 'supported_chrome_os_management'): @@ -533,8 +534,13 @@ self._Error(('Example for policy %s does not comply to the policy\'s ' 'schema or does not use all properties at least once.') % policy.get('name')) - if policy.has_key('validation_schema'): - validation_schema = policy['validation_schema'] + if policy.has_key('validation_schema') and policy.has_key( + 'description_schema'): + self._Error(('validation_schema and description_schema both defined ' + 'for policy %s.') % policy.get('name')) + secondary_schema = policy.get('validation_schema', + policy.get('description_schema')) + if secondary_schema: real_example = {} if policy_type == 'string': real_example = json.loads(example) @@ -543,7 +549,7 @@ else: self._Error('Unsupported type for legacy embedded json policy.') if not self.schema_validator.ValidateValue( - validation_schema, real_example, enforce_use_entire_schema=True): + secondary_schema, real_example, enforce_use_entire_schema=True): self._Error(('Example for policy %s does not comply to the ' + 'policy\'s validation_schema') % policy.get('name'))
diff --git a/components/policy/tools/template_writers/writers/adm_writer.py b/components/policy/tools/template_writers/writers/adm_writer.py index 56f185e..2f7a90dd 100755 --- a/components/policy/tools/template_writers/writers/adm_writer.py +++ b/components/policy/tools/template_writers/writers/adm_writer.py
@@ -180,7 +180,7 @@ ''' policy_desc = policy.get('desc') reference_url = POLICY_LIST_URL + '#' + policy['name'] - reference_link_text = self._GetLocalizedMessage('reference_link') + reference_link_text = self.GetLocalizedMessage('reference_link') reference_link_text = reference_link_text.replace('$6', reference_url) if policy_desc is not None: @@ -191,10 +191,6 @@ else: return reference_link_text - def _GetLocalizedMessage(self, msg_id): - '''Returns the localized message of the given message ID.''' - return self.messages['doc_' + msg_id]['text'] - def WriteComment(self, comment): self.lines.AddLine('; ' + comment)
diff --git a/components/policy/tools/template_writers/writers/adml_writer.py b/components/policy/tools/template_writers/writers/adml_writer.py index 21f7ed616..4415ad1 100755 --- a/components/policy/tools/template_writers/writers/adml_writer.py +++ b/components/policy/tools/template_writers/writers/adml_writer.py
@@ -80,6 +80,9 @@ policy_desc = policy.get('desc') example_value_text = self._GetExampleValueText(policy) + if policy_desc is not None and self.HasExpandedPolicyDescription(policy): + policy_desc += '\n' + self.GetExpandedPolicyDescription(policy) + '\n' + if policy_desc is not None and example_value_text is not None: policy_explain = policy_desc + '\n\n' + example_value_text elif policy_desc is not None: @@ -182,12 +185,12 @@ # Strings are simple - just return them as-is, on the same line. if isinstance(example_value, str): - return self._GetLocalizedMessage('example_value') + ' ' + example_value + return self.GetLocalizedMessage('example_value') + ' ' + example_value # Dicts are pretty simple - json.dumps them onto multiple lines. if isinstance(example_value, dict): value_as_text = json.dumps(example_value, indent=2) - return self._GetLocalizedMessage('example_value') + '\n\n' + value_as_text + return self.GetLocalizedMessage('example_value') + '\n\n' + value_as_text # Lists are the more complicated - the example value we show the user # depends on if they need to enter the list into a textbox (using JSON @@ -216,20 +219,16 @@ raise Exception( 'Unexpected policy type with list example value: %s' % policy_type) - return self._GetLocalizedMessage('example_value') + '\n\n' + value_as_text + return self.GetLocalizedMessage('example_value') + '\n\n' + value_as_text # Other types - mostly booleans - we don't show example values. return None def _GetLegacySingleLineLabel(self, policy_label): '''Generates a label for a legacy single-line textbox.''' - return (self._GetLocalizedMessage('legacy_single_line_label').replace( + return (self.GetLocalizedMessage('legacy_single_line_label').replace( '$6', policy_label)) - def _GetLocalizedMessage(self, msg_id): - '''Returns the localized message of the given message ID.''' - return self.messages['doc_' + msg_id]['text'] - def BeginTemplate(self): dom_impl = minidom.getDOMImplementation('') self._doc = dom_impl.createDocument(None, 'policyDefinitionResources', None)
diff --git a/components/policy/tools/template_writers/writers/adml_writer_unittest.py b/components/policy/tools/template_writers/writers/adml_writer_unittest.py index 7f6dfd0e..0d94fb1 100755 --- a/components/policy/tools/template_writers/writers/adml_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/adml_writer_unittest.py
@@ -59,6 +59,9 @@ 'doc_legacy_single_line_label': { 'text': '$6 (deprecated)', }, + 'doc_schema_description_link': { + 'text': '''See $6''' + }, } self.writer.Init() @@ -417,7 +420,9 @@ expected_output = ( '<string id="DictionaryPolicyStub">Dictionary policy caption</string>\n' '<string id="DictionaryPolicyStub_Explain">' - 'This is a test description.</string>') + 'This is a test description.\n' + 'See https://www.chromium.org/administrators/policy-list-3#' + 'DictionaryPolicyStub\n</string>') self.AssertXMLEquals(output, expected_output) # Assert generated presentation elements. output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
diff --git a/components/policy/tools/template_writers/writers/chromeos_adml_writer_unittest.py b/components/policy/tools/template_writers/writers/chromeos_adml_writer_unittest.py index 07c85a7..a6cc580 100755 --- a/components/policy/tools/template_writers/writers/chromeos_adml_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/chromeos_adml_writer_unittest.py
@@ -86,7 +86,9 @@ expected_output = ( '<string id="DictionaryPolicyStub">Dictionary policy caption</string>\n' '<string id="DictionaryPolicyStub_Explain">' - 'This is a test description.</string>\n' + 'This is a test description.\n' + 'See https://www.chromium.org/administrators/policy-list-3#' + 'DictionaryPolicyStub\n</string>\n' '<string id="DictionaryPolicyStub_Legacy">' 'Dictionary policy label (deprecated)</string>') self.AssertXMLEquals(output, expected_output)
diff --git a/components/policy/tools/template_writers/writers/doc_writer.py b/components/policy/tools/template_writers/writers/doc_writer.py index 7bc41a5..2d09058f 100755 --- a/components/policy/tools/template_writers/writers/doc_writer.py +++ b/components/policy/tools/template_writers/writers/doc_writer.py
@@ -33,17 +33,6 @@ files. ''' - def _GetLocalizedMessage(self, msg_id): - '''Returns a localized message for this writer. - - Args: - msg_id: The identifier of the message. - - Returns: - The localized message. - ''' - return self.messages['doc_' + msg_id]['text'] - def _MapListToString(self, item_map, items): '''Creates a comma-separated list. @@ -67,7 +56,7 @@ text: The string to be added. ''' # A simple regexp to search for URLs. It is enough for now. - url_matcher = re.compile('(http://[^\\s]*[^\\s\\.])') + url_matcher = re.compile('(https?://[^\\s]*[^\\s\\.\\)\\"])') # Iterate through all the URLs and replace them with links. while True: @@ -143,6 +132,18 @@ self.AddElement(ul, 'li', {}, '%s = %s' % (value_string, item['caption'])) + def _AddSchema(self, parent, schema): + '''Adds a schema to a DOM node. + + Args: + parent: The DOM node for which the schema will be added. + schema: The schema of a policy. + ''' + dd = self._AddPolicyAttribute(parent, 'schema', None, + ['.monospace', '.pre-wrap']) + schema_json = json.dumps(schema, indent=2, sort_keys=True) + self.AddText(dd, schema_json) + def _AddFeatures(self, parent, policy): '''Adds a string containing the list of supported features of a policy to a DOM node. The text will look like as: @@ -159,9 +160,9 @@ for key in keys: key_name = self._FEATURE_MAP[key] if policy['features'][key]: - value_name = self._GetLocalizedMessage('supported') + value_name = self.GetLocalizedMessage('supported') else: - value_name = self._GetLocalizedMessage('not_supported') + value_name = self.GetLocalizedMessage('not_supported') features.append('%s: %s' % (key_name, value_name)) self.AddText(parent, ', '.join(features)) @@ -194,8 +195,8 @@ is_win: True for Windows, False for Chromium/Google Chrome OS. ''' example_value = policy['example_value'] - os_header = self._GetLocalizedMessage('win_example_value') if is_win else \ - self._GetLocalizedMessage('chrome_os_example_value') + os_header = self.GetLocalizedMessage('win_example_value') if is_win else \ + self.GetLocalizedMessage('chrome_os_example_value') self.AddElement(parent, 'dt', {}, os_header) element = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre-wrap']) element_text = [] @@ -327,8 +328,8 @@ policy: A policy of type 'dict', for which the Windows example value is generated. ''' - os_header = self._GetLocalizedMessage('win_example_value') if is_win else \ - self._GetLocalizedMessage('chrome_os_example_value') + os_header = self.GetLocalizedMessage('win_example_value') if is_win else \ + self.GetLocalizedMessage('chrome_os_example_value') self.AddElement(parent, 'dt', {}, os_header) element = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre-wrap']) key_name = self._GetRegistryKeyName(policy, is_win) @@ -479,7 +480,7 @@ # Avoid modifying the default value of definition_style. if definition_style == None: definition_style = [] - term = self._GetLocalizedMessage(term_id) + term = self.GetLocalizedMessage(term_id) self._AddStyledElement(dl, 'dt', ['dt'], {}, term) return self._AddStyledElement(dl, 'dd', definition_style, {}, definition) @@ -500,10 +501,10 @@ text.append(self._PRODUCT_MAP[product]) text.append('(%s)' % self._MapListToString(self._PLATFORM_MAP, platforms)) if supported_on['since_version']: - since_version = self._GetLocalizedMessage('since_version') + since_version = self.GetLocalizedMessage('since_version') text.append(since_version.replace('$6', supported_on['since_version'])) if supported_on['until_version']: - until_version = self._GetLocalizedMessage('until_version') + until_version = self.GetLocalizedMessage('until_version') text.append(until_version.replace('$6', supported_on['until_version'])) # Add the list element: self.AddElement(ul, 'li', {}, ' '.join(text)) @@ -518,10 +519,10 @@ ''' ul = self._AddStyledElement(parent, 'ul', ['ul']) if 'minimum' in schema: - text_min = self._GetLocalizedMessage('range_minimum') + text_min = self.GetLocalizedMessage('range_minimum') self.AddElement(ul, 'li', {}, text_min + str(schema['minimum'])) if 'maximum' in schema: - text_max = self._GetLocalizedMessage('range_maximum') + text_max = self.GetLocalizedMessage('range_maximum') self.AddElement(ul, 'li', {}, text_max + str(schema['maximum'])) def _AddPolicyDetails(self, parent, policy): @@ -558,7 +559,7 @@ data_type.append('[%s]' % ', '.join(qualified_types)) if is_complex_policy: data_type.append( - '(%s)' % self._GetLocalizedMessage('complex_policies_on_windows')) + '(%s)' % self.GetLocalizedMessage('complex_policies_on_windows')) self._AddPolicyAttribute(dl, 'data_type', ' '.join(data_type)) if self.IsPolicySupportedOnPlatform(policy, 'win'): key_name = self._GetRegistryKeyName(policy, True) @@ -594,6 +595,15 @@ if 'arc_support' in policy: dd = self._AddPolicyAttribute(dl, 'arc_support') self._AddParagraphs(dd, policy['arc_support']) + if policy['type'] in ('dict', 'external') and 'schema' in policy: + self._AddSchema(dl, policy['schema']) + if 'validation_schema' in policy: + self._AddSchema(dl, policy['validation_schema']) + if 'description_schema' in policy: + self._AddSchema(dl, policy['description_schema']) + if 'url_schema' in policy: + dd = self._AddPolicyAttribute(dl, 'url_schema') + self._AddTextWithLinks(dd, policy['url_schema']) if (self.IsPolicySupportedOnPlatform(policy, 'win') or self.IsPolicySupportedOnPlatform(policy, 'linux') or self.IsPolicySupportedOnPlatform(policy, 'android') or @@ -615,7 +625,7 @@ return problem_href = policy['problem_href'] div = self._AddStyledElement(parent, 'div', ['div.note']) - note = self._GetLocalizedMessage('note').replace('$6', problem_href) + note = self.GetLocalizedMessage('note').replace('$6', problem_href) self._AddParagraphs(div, note) def _AddPolicyRow(self, parent, policy): @@ -666,7 +676,7 @@ policy_name_text = policy['name'] if 'deprecated' in policy and policy['deprecated'] == True: policy_name_text += " (" - policy_name_text += self._GetLocalizedMessage('deprecated') + ")" + policy_name_text += self.GetLocalizedMessage('deprecated') + ")" self.AddText(h2, policy_name_text) self.AddElement(parent2, 'span', {}, policy['caption']) self._AddPolicyNote(parent2, policy) @@ -677,7 +687,7 @@ self._AddStyledElement(parent2, 'div', ['div.group_desc'], {}, policy['desc']) self.AddElement(parent2, 'a', {'href': '#top'}, - self._GetLocalizedMessage('back_to_top')) + self.GetLocalizedMessage('back_to_top')) def SchemaHasRangeRestriction(self, schema): if 'maximum' in schema: @@ -713,7 +723,7 @@ summary_div = self.AddElement(self._main_div, 'div') self.AddElement(summary_div, 'a', {'name': 'top'}) self.AddElement(summary_div, 'br') - self._AddParagraphs(summary_div, self._GetLocalizedMessage('intro')) + self._AddParagraphs(summary_div, self.GetLocalizedMessage('intro')) self.AddElement(summary_div, 'br') self.AddElement(summary_div, 'br') self.AddElement(summary_div, 'br') @@ -723,10 +733,9 @@ thead = self.AddElement(summary_table, 'thead') tr = self._AddStyledElement(thead, 'tr', ['tr']) self._AddStyledElement(tr, 'td', ['td', 'td.left', 'thead td'], {}, - self._GetLocalizedMessage('name_column_title')) - self._AddStyledElement( - tr, 'td', ['td', 'td.right', 'thead td'], {}, - self._GetLocalizedMessage('description_column_title')) + self.GetLocalizedMessage('name_column_title')) + self._AddStyledElement(tr, 'td', ['td', 'td.right', 'thead td'], {}, + self.GetLocalizedMessage('description_column_title')) self._summary_tbody = self.AddElement(summary_table, 'tbody') # Add a <div> for the detailed policy listing.
diff --git a/components/policy/tools/template_writers/writers/doc_writer_unittest.py b/components/policy/tools/template_writers/writers/doc_writer_unittest.py index 47bdaf42..0af1a1c 100755 --- a/components/policy/tools/template_writers/writers/doc_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/doc_writer_unittest.py
@@ -63,6 +63,12 @@ 'doc_description': { 'text': '_test_description' }, + 'doc_schema': { + 'text': '_test_schema' + }, + 'doc_url_schema': { + 'text': '_test_url_schema' + }, 'doc_arc_support': { 'text': '_test_arc_support' }, @@ -195,7 +201,7 @@ # Test if localized messages are retrieved correctly. self.writer.messages = {'doc_hello_world': {'text': 'hello, vilag!'}} self.assertEquals( - self.writer._GetLocalizedMessage('hello_world'), 'hello, vilag!') + self.writer.GetLocalizedMessage('hello_world'), 'hello, vilag!') def testMapListToString(self): # Test function DocWriter.MapListToString() @@ -302,6 +308,41 @@ </p><ul><li>"one" = Disable foo</li><li>"two" = Solve your problem</li><li>"three" = Enable bar</li></ul></root>''' ) + def testAddSchema(self): + # Test if the schema of a policy is handled correctly. + policy = { + 'type': 'dict', + 'schema': { + 'properties': { + 'foo': { + 'type': 'integer' + } + }, + 'type': 'object' + } + } + self.writer._AddSchema(self.doc_root, policy['schema']) + self.assertEquals( + self.doc_root.toxml(), '<root>' + '<dt style="style_dt;">_test_schema</dt>' + '<dd style="style_.monospace;style_.pre-wrap;">{\n' + ' "properties": {\n' + ' "foo": {\n' + ' "type": "integer"\n' + ' }\n' + ' }, \n' + ' "type": "object"\n' + '}</dd></root>') + + def testAddUrlSchema(self): + # Test if the expanded schema description of a policy is handled correctly. + policy = {'url_schema': 'https://example.com/details'} + self.writer._AddTextWithLinks(self.doc_root, policy['url_schema']) + self.assertEquals( + self.doc_root.toxml(), + '<root><a href="https://example.com/details">https://example.com/details</a></root>' + ) + def testAddFeatures(self): # Test if the list of features of a policy is handled correctly. policy = { @@ -632,6 +673,16 @@ 'TestPolicyCaption', 'desc': 'TestPolicyDesc', + 'schema': { + 'properties': { + 'foo': { + 'type': 'integer' + } + }, + 'type': 'object' + }, + 'url_schema': + 'https://example.com/details', 'supported_on': [{ 'product': 'chrome', 'platforms': ['win', 'mac', 'linux', 'chrome_os'], @@ -665,6 +716,17 @@ '<dt style="style_dt;">_test_supported_features</dt>' '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>' '<dt style="style_dt;">_test_description</dt><dd><p>TestPolicyDesc</p></dd>' + '<dt style="style_dt;">_test_schema</dt>' + '<dd style="style_.monospace;style_.pre-wrap;">{\n' + ' "properties": {\n' + ' "foo": {\n' + ' "type": "integer"\n' + ' }\n' + ' }, \n' + ' "type": "object"\n' + '}</dd>' + '<dt style="style_dt;">_test_url_schema</dt>' + '<dd><a href="https://example.com/details">https://example.com/details</a></dd>' '<dt style="style_dt;">_test_example_value</dt>' '<dd>' '<dl style="style_dd dl;">' @@ -710,6 +772,17 @@ 'TestPolicyCaption', 'desc': 'TestPolicyDesc', + 'description_schema': { + 'properties': { + 'url': { + 'type': 'string' + }, + 'hash': { + 'type': 'string' + }, + }, + 'type': 'object' + }, 'supported_on': [{ 'product': 'chrome', 'platforms': ['win', 'mac', 'linux'], @@ -743,6 +816,18 @@ '<dt style="style_dt;">_test_supported_features</dt>' '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>' '<dt style="style_dt;">_test_description</dt><dd><p>TestPolicyDesc</p></dd>' + '<dt style="style_dt;">_test_schema</dt>' + '<dd style="style_.monospace;style_.pre-wrap;">{\n' + ' "properties": {\n' + ' "hash": {\n' + ' "type": "string"\n' + ' }, \n' + ' "url": {\n' + ' "type": "string"\n' + ' }\n' + ' }, \n' + ' "type": "object"\n' + '}</dd>' '<dt style="style_dt;">_test_example_value</dt>' '<dd>' '<dl style="style_dd dl;">'
diff --git a/components/policy/tools/template_writers/writers/json_writer.py b/components/policy/tools/template_writers/writers/json_writer.py index ff1c9d9..5943621 100755 --- a/components/policy/tools/template_writers/writers/json_writer.py +++ b/components/policy/tools/template_writers/writers/json_writer.py
@@ -57,7 +57,10 @@ line = ' // %s' % policy['caption'] self._out.append(line) self._out.append(HEADER_DELIMETER) - description = self._text_wrapper.wrap(policy['desc']) + description = policy['desc'] + if self.HasExpandedPolicyDescription(policy): + description += ' ' + self.GetExpandedPolicyDescription(policy) + '\n' + description = self._text_wrapper.wrap(description) self._out += description line = ' //"%s": %s' % (policy['name'], example_value_str) self._out.append('')
diff --git a/components/policy/tools/template_writers/writers/json_writer_unittest.py b/components/policy/tools/template_writers/writers/json_writer_unittest.py index ac84a67..8f9e36fa 100755 --- a/components/policy/tools/template_writers/writers/json_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/json_writer_unittest.py
@@ -34,6 +34,13 @@ //------------------------------------------------------------------------- """ +MESSAGES = ''' + { + 'doc_schema_description_link': { + 'text': 'See $6' + }, + }''' + class JsonWriterUnittest(writer_unittest_common.WriterUnittestCommon): '''Unit tests for JsonWriter.''' @@ -326,12 +333,14 @@ }, ], "placeholders": [], - "messages": {}, - }''' + "messages": %s, + }''' % MESSAGES output = self.GetOutput(policy_json, {'_chromium': '1'}, 'json') expected_output = ( TEMPLATE_HEADER + ' // Example Dictionary Policy\n' + HEADER_DELIMETER - + ' // Example Dictionary Policy\n\n' + + ' // Example Dictionary Policy See ' + 'https://www.chromium.org/administrators\n' + ' // /policy-list-3#DictionaryPolicy\n\n' ' //"DictionaryPolicy": {"bool": true, "dict": {"a": 1, ' '"b": 2}, "int": 10, "list": [1, 2, 3], "string": "abc"}\n\n' '}') @@ -356,12 +365,14 @@ }, ], "placeholders": [], - "messages": {}, - }''' % str(example) + "messages": %s, + }''' % (str(example), MESSAGES) output = self.GetOutput(policy_json, {'_chromium': '1'}, 'json') expected_output = ( TEMPLATE_HEADER + ' // Example External Policy\n' + HEADER_DELIMETER + - ' // Example External Policy\n\n' + ' // Example External Policy See ' + 'https://www.chromium.org/administrators/policy-\n' + ' // list-3#ExternalPolicy\n\n' ' //"ExternalPolicy": {"hash": "deadbeef", "url": "https://example.com/avatar.jpg"}\n\n' '}') self.CompareOutputs(output, expected_output)
diff --git a/components/policy/tools/template_writers/writers/plist_strings_writer.py b/components/policy/tools/template_writers/writers/plist_strings_writer.py index 137b83e..cb4d8482 100755 --- a/components/policy/tools/template_writers/writers/plist_strings_writer.py +++ b/components/policy/tools/template_writers/writers/plist_strings_writer.py
@@ -57,6 +57,8 @@ for item in policy['items']: item_descs.append(str(item['value']) + ' - ' + item['caption']) desc = '\n'.join(item_descs) + '\n' + desc + if self.HasExpandedPolicyDescription(policy): + desc += '\n' + self.GetExpandedPolicyDescription(policy) self._AddToStringTable(policy['name'], policy['label'], desc)
diff --git a/components/policy/tools/template_writers/writers/template_writer.py b/components/policy/tools/template_writers/writers/template_writer.py index 3a99248..4c5a0f7 100755 --- a/components/policy/tools/template_writers/writers/template_writer.py +++ b/components/policy/tools/template_writers/writers/template_writer.py
@@ -359,3 +359,36 @@ str_key = policy['name'] # Groups come before regular policies. return (not is_group, str_key) + + def GetLocalizedMessage(self, msg_id): + '''Returns a localized message for this writer. + + Args: + msg_id: The identifier of the message. + + Returns: + The localized message. + ''' + return self.messages['doc_' + msg_id]['text'] + + def HasExpandedPolicyDescription(self, policy): + '''Returns whether the policy has expanded documentation containing the link + to the documentation with schema and formatting. + ''' + return (policy['type'] in ('dict', 'external') or 'url_schema' in policy or + 'validation_schema' in policy or 'description_schema' in policy) + + def GetExpandedPolicyDescription(self, policy): + '''Returns the expanded description of the policy containing the link to the + documentation with schema and formatting. + ''' + schema_description_link_text = self.GetLocalizedMessage( + 'schema_description_link') + url = None + if 'url_schema' in policy: + url = policy['url_schema'] + if (policy['type'] in ('dict', 'external') or + 'validation_schema' in policy or 'description_schema' in policy): + url = 'https://www.chromium.org/administrators/policy-list-3#' + policy[ + 'name'] + return schema_description_link_text.replace('$6', url) if url else ''
diff --git a/components/policy/tools/template_writers/writers/template_writer_unittest.py b/components/policy/tools/template_writers/writers/template_writer_unittest.py index b319474..8e06df3 100755 --- a/components/policy/tools/template_writers/writers/template_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/template_writer_unittest.py
@@ -196,6 +196,40 @@ self.assertTrue(self._IsPolicySupported('*', 11, policy)) self.assertFalse(self._IsPolicySupported('*', 10, policy)) + def testHasExpandedPolicyDescriptionForUrlSchema(self): + policy = {'url_schema': 'https://example.com/details', 'type': 'list'} + tw = template_writer.TemplateWriter(None, None) + self.assertTrue(tw.HasExpandedPolicyDescription(policy)) + + def testHasExpandedPolicyDescriptionForJSONPolicies(self): + policy = {'name': 'PolicyName', 'type': 'dict'} + tw = template_writer.TemplateWriter(None, None) + self.assertTrue(tw.HasExpandedPolicyDescription(policy)) + + def testGetExpandedPolicyDescriptionForUrlSchema(self): + policy = {'type': 'integer', 'url_schema': 'https://example.com/details'} + tw = template_writer.TemplateWriter(None, None) + tw.messages = { + 'doc_schema_description_link': { + 'text': '''See $6''' + }, + } + expanded_description = tw.GetExpandedPolicyDescription(policy) + self.assertEqual(expanded_description, 'See https://example.com/details') + + def testGetExpandedPolicyDescriptionForJSONPolicies(self): + policy = {'name': 'PolicyName', 'type': 'dict'} + tw = template_writer.TemplateWriter(None, None) + tw.messages = { + 'doc_schema_description_link': { + 'text': '''See $6''' + }, + } + expanded_description = tw.GetExpandedPolicyDescription(policy) + self.assertEqual( + expanded_description, + 'See https://www.chromium.org/administrators/policy-list-3#PolicyName') + if __name__ == '__main__': unittest.main()
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ConsistencyCookieManager.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ConsistencyCookieManager.java index 7cb114b9..99eaac54 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ConsistencyCookieManager.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ConsistencyCookieManager.java
@@ -15,7 +15,8 @@ * Created by native code to get status of {@link AccountManagerFacade#isUpdatePending()} and * notifications when it changes. */ -public class ConsistencyCookieManager implements ObservableValue.Observer { +public class ConsistencyCookieManager + implements ObservableValue.Observer, AccountTrackerService.OnSystemAccountsSeededListener { private final long mNativeConsistencyCookieManager; private final AccountTrackerService mAccountTrackerService; private final AccountManagerFacade mAccountManagerFacade; @@ -38,7 +39,7 @@ // have already invalidate account seed status, so mIsUpdatePending will stay false until // accounts are seeded to the native AccountTrackerService. // TODO(https://crbug.com/831257): Simplify this after seeding is reimplemented. - mAccountTrackerService.addSystemAccountsSeededListener(this::onValueChanged); + mAccountTrackerService.addSystemAccountsSeededListener(this); mAccountManagerFacade.isUpdatePending().addObserver(this); mSigninActivityMonitor.hasOngoingActivity().addObserver(this); @@ -46,6 +47,11 @@ } @Override + public void onSystemAccountsSeedingComplete() { + onValueChanged(); + } + + @Override public void onValueChanged() { boolean state = calculateIsUpdatePending(); @@ -71,6 +77,8 @@ @MainThread private void destroy() { ThreadUtils.assertOnUiThread(); + mAccountTrackerService.removeSystemAccountsSeededListener(this); + mSigninActivityMonitor.hasOngoingActivity().removeObserver(this); mAccountManagerFacade.isUpdatePending().removeObserver(this); }
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc index a90f08f7..42ee6c93 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
@@ -114,14 +114,13 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); size_t request_id = result.request_id; DCHECK_LT(request_id, check_results_.size()); - DCHECK_LT(request_id, check_start_times_.size()); auto& stored_result = check_results_.at(request_id); CHECK(!stored_result.finished); stored_result = result; UMA_HISTOGRAM_TIMES("SubresourceFilter.SafeBrowsing.TotalCheckTime", - base::TimeTicks::Now() - check_start_times_[request_id]); + base::TimeTicks::Now() - result.start_time); if (deferring_ && HasFinishedAllSafeBrowsingChecks()) { NotifyResult(); @@ -151,14 +150,14 @@ void SubresourceFilterSafeBrowsingActivationThrottle::CheckCurrentUrl() { DCHECK(database_client_); - check_start_times_.push_back(base::TimeTicks::Now()); check_results_.emplace_back(); size_t id = check_results_.size() - 1; io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&SubresourceFilterSafeBrowsingClient::CheckUrlOnIO, base::Unretained(database_client_.get()), - navigation_handle()->GetURL(), id)); + navigation_handle()->GetURL(), id, + base::TimeTicks::Now())); } void SubresourceFilterSafeBrowsingActivationThrottle::NotifyResult() {
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h index fd2e4e2..472b8d4 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h
@@ -105,7 +105,6 @@ ActivationList matched_list) const; std::vector<SubresourceFilterSafeBrowsingClient::CheckResult> check_results_; - std::vector<base::TimeTicks> check_start_times_; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc index 119cc4d..7875dd5b 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -63,7 +63,7 @@ const char kSafeBrowsingNavigationDelay[] = "SubresourceFilter.PageLoad.SafeBrowsingDelay"; const char kSafeBrowsingCheckTime[] = - "SubresourceFilter.SafeBrowsing.CheckTime"; + "SubresourceFilter.SafeBrowsing.TotalCheckTime"; const char kActivationListHistogram[] = "SubresourceFilter.PageLoad.ActivationList";
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc index 5c6d895..cbe4a14 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc
@@ -24,7 +24,8 @@ value->SetInteger("request_id", request_id); value->SetInteger("threat_type", threat_type); value->SetValue("threat_metadata", threat_metadata.ToTracedValue().get()); - value->SetInteger("check_time (us)", check_time.InMicroseconds()); + value->SetInteger("duration (us)", + (base::TimeTicks::Now() - start_time).InMicroseconds()); value->SetBoolean("finished", finished); return value; } @@ -43,13 +44,15 @@ SubresourceFilterSafeBrowsingClient::~SubresourceFilterSafeBrowsingClient() {} -void SubresourceFilterSafeBrowsingClient::CheckUrlOnIO(const GURL& url, - size_t request_id) { +void SubresourceFilterSafeBrowsingClient::CheckUrlOnIO( + const GURL& url, + size_t request_id, + base::TimeTicks start_time) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(!url.is_empty()); auto request = std::make_unique<SubresourceFilterSafeBrowsingClientRequest>( - request_id, database_manager_, io_task_runner_, this); + request_id, start_time, database_manager_, io_task_runner_, this); auto* raw_request = request.get(); DCHECK(requests_.find(raw_request) == requests_.end()); requests_[raw_request] = std::move(request);
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h index 2817038..b64280d80 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h
@@ -50,7 +50,7 @@ // without performance implications. Refactor this class if that ever // changes. safe_browsing::ThreatMetadata threat_metadata; - base::TimeDelta check_time; + base::TimeTicks start_time; bool finished = false; std::unique_ptr<base::trace_event::TracedValue> ToTracedValue() const; @@ -65,7 +65,9 @@ ~SubresourceFilterSafeBrowsingClient(); - void CheckUrlOnIO(const GURL& url, size_t request_id); + void CheckUrlOnIO(const GURL& url, + size_t request_id, + base::TimeTicks start_time); void OnCheckBrowseUrlResult( SubresourceFilterSafeBrowsingClientRequest* request,
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.cc index 60c6771853..80357f0 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.cc
@@ -10,7 +10,6 @@ #include "base/bind_helpers.h" #include "base/location.h" #include "base/logging.h" -#include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h" #include "content/public/browser/browser_thread.h" @@ -24,11 +23,13 @@ SubresourceFilterSafeBrowsingClientRequest:: SubresourceFilterSafeBrowsingClientRequest( size_t request_id, + base::TimeTicks start_time, scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, SubresourceFilterSafeBrowsingClient* client) : request_id_(request_id), + start_time_(start_time), database_manager_(std::move(database_manager)), client_(client) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -45,8 +46,6 @@ void SubresourceFilterSafeBrowsingClientRequest::Start(const GURL& url) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - start_time_ = base::TimeTicks::Now(); - // Just return SAFE if the database is not supported. bool synchronous_finish = !database_manager_->IsSupported() || @@ -90,15 +89,13 @@ result.request_id = request_id_; result.threat_type = threat_type; result.threat_metadata = metadata; - result.check_time = base::TimeTicks::Now() - start_time_; + result.start_time = start_time_; // This memeber is separate from |request_completed_|, in that it just // indicates that this request is done processing (due to completion or // timeout). result.finished = true; - UMA_HISTOGRAM_TIMES("SubresourceFilter.SafeBrowsing.CheckTime", - result.check_time); // Will delete |this|. client_->OnCheckBrowseUrlResult(this, result); }
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.h b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.h index 9f9f13d9..219cd5f 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.h +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.h
@@ -35,6 +35,7 @@ public: SubresourceFilterSafeBrowsingClientRequest( size_t request_id, + base::TimeTicks start_time_, scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, @@ -73,14 +74,15 @@ // SubresourceFilterSafeBrowsingClient). const size_t request_id_; + // The time when the request started, measured on the UI thread. + const base::TimeTicks start_time_; + scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager_; SubresourceFilterSafeBrowsingClient* client_ = nullptr; // Timer to abort the safe browsing check if it takes too long. base::OneShotTimer timer_; - base::TimeTicks start_time_; - bool request_completed_ = false; DISALLOW_COPY_AND_ASSIGN(SubresourceFilterSafeBrowsingClientRequest);
diff --git a/components/sync/base/data_type_histogram.cc b/components/sync/base/data_type_histogram.cc index 55743d7c..0d75794 100644 --- a/components/sync/base/data_type_histogram.cc +++ b/components/sync/base/data_type_histogram.cc
@@ -26,7 +26,3 @@ kModelTypeCountHistogramPrefix + type_string; base::UmaHistogramCounts1M(full_histogram_name, count); } - -void SyncWalletDataRecordClearedEntitiesCount(size_t count) { - UMA_HISTOGRAM_COUNTS_100("Sync.Wallet.EntitiesClearedWhenDisabled", count); -}
diff --git a/components/sync/base/data_type_histogram.h b/components/sync/base/data_type_histogram.h index 6f645944..51cd1d2 100644 --- a/components/sync/base/data_type_histogram.h +++ b/components/sync/base/data_type_histogram.h
@@ -21,9 +21,6 @@ void SyncRecordModelTypeCountHistogram(syncer::ModelType model_type, size_t count); -// Records that |count| entities have been cleared when disabling sync. -void SyncWalletDataRecordClearedEntitiesCount(size_t count); - // Helper macro for datatype specific histograms. For each datatype, invokes // a pre-defined PER_DATA_TYPE_MACRO(type_str), where |type_str| is the string // version of the datatype.
diff --git a/components/sync/driver/about_sync_util.cc b/components/sync/driver/about_sync_util.cc index 6c55c6e..90e407c 100644 --- a/components/sync/driver/about_sync_util.cc +++ b/components/sync/driver/about_sync_util.cc
@@ -316,6 +316,7 @@ section_summary->AddBoolStat("Sync Feature Enabled"); Stat<bool>* setup_in_progress = section_summary->AddBoolStat("Setup In Progress"); + Stat<std::string>* auth_error = section_summary->AddStringStat("Auth Error"); Section* section_version = section_list.AddSection("Version Info"); Stat<std::string>* client_version = @@ -330,7 +331,6 @@ section_identity->AddStringStat("Invalidator Client ID"); Stat<std::string>* username = section_identity->AddStringStat("Username"); Stat<bool>* user_is_primary = section_identity->AddBoolStat("Is Primary"); - Stat<std::string>* auth_error = section_identity->AddStringStat("Auth Error"); Section* section_credentials = section_list.AddSection("Credentials"); Stat<std::string>* request_token_time = @@ -451,6 +451,10 @@ disable_reasons->Set(GetDisableReasonsString(service->GetDisableReasons())); feature_enabled->Set(service->IsSyncFeatureEnabled()); setup_in_progress->Set(service->IsSetupInProgress()); + std::string auth_error_str = service->GetAuthError().ToString(); + auth_error->Set(base::StringPrintf( + "%s since %s", (auth_error_str.empty() ? "OK" : auth_error_str).c_str(), + GetTimeStr(service->GetAuthErrorTime(), "browser startup").c_str())); SyncStatus full_status; bool is_status_valid = @@ -471,10 +475,6 @@ invalidator_id->Set(full_status.invalidator_client_id); username->Set(service->GetAuthenticatedAccountInfo().email); user_is_primary->Set(service->IsAuthenticatedAccountPrimary()); - std::string auth_error_str = service->GetAuthError().ToString(); - auth_error->Set(base::StringPrintf( - "%s since %s", (auth_error_str.empty() ? "OK" : auth_error_str).c_str(), - GetTimeStr(service->GetAuthErrorTime(), "browser startup").c_str())); // Credentials. request_token_time->Set(GetTimeStr(token_status.token_request_time, "n/a"));
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc index 93c9bfe4..1440bf5 100644 --- a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc +++ b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
@@ -58,7 +58,7 @@ sync_entity->mutable_specifics()->CopyFrom( commit_request->entity->specifics); } else { - PopulateCommitProto(*commit_request, sync_entity); + PopulateCommitProto(type_, *commit_request, sync_entity); AdjustCommitProto(sync_entity); } @@ -126,7 +126,7 @@ response_list.push_back(response_data); status->increment_num_successful_commits(); - if (commit_request.entity->specifics.has_bookmark()) { + if (type_ == BOOKMARKS) { status->increment_num_successful_bookmark_commits(); } @@ -178,12 +178,14 @@ // static void NonBlockingTypeCommitContribution::PopulateCommitProto( + ModelType type, const CommitRequestData& commit_entity, sync_pb::SyncEntity* commit_proto) { const EntityData& entity_data = *commit_entity.entity; commit_proto->set_id_string(entity_data.id); - // Populate client_defined_unique_tag only for non-bookmark data types. - if (!entity_data.specifics.has_bookmark()) { + // Populate client_defined_unique_tag only for non-bookmark and non-Nigori + // data types. + if (type != BOOKMARKS && type != NIGORI) { commit_proto->set_client_defined_unique_tag(entity_data.client_tag_hash); } commit_proto->set_version(commit_entity.base_version); @@ -193,7 +195,7 @@ if (!entity_data.is_deleted()) { // Handle bookmarks separately. - if (entity_data.specifics.has_bookmark()) { + if (type == BOOKMARKS) { // position_in_parent field is set only for legacy reasons. See comments // in sync.proto for more information. commit_proto->set_position_in_parent(
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.h b/components/sync/engine_impl/non_blocking_type_commit_contribution.h index 7e9ec461..c6bdb0c 100644 --- a/components/sync/engine_impl/non_blocking_type_commit_contribution.h +++ b/components/sync/engine_impl/non_blocking_type_commit_contribution.h
@@ -49,7 +49,8 @@ // Public for testing. // Copies data to be committed from CommitRequestData into SyncEntity proto. - static void PopulateCommitProto(const CommitRequestData& commit_entity, + static void PopulateCommitProto(ModelType type, + const CommitRequestData& commit_entity, sync_pb::SyncEntity* commit_proto); private:
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc b/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc index 285a3799..f0552ea1 100644 --- a/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc +++ b/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc
@@ -71,7 +71,8 @@ request_data.entity = std::move(data); SyncEntity entity; - NonBlockingTypeCommitContribution::PopulateCommitProto(request_data, &entity); + NonBlockingTypeCommitContribution::PopulateCommitProto(PREFERENCES, + request_data, &entity); // Exhaustively verify the populated SyncEntity. EXPECT_TRUE(entity.id_string().empty()); @@ -119,7 +120,8 @@ request_data.entity = std::move(data); SyncEntity entity; - NonBlockingTypeCommitContribution::PopulateCommitProto(request_data, &entity); + NonBlockingTypeCommitContribution::PopulateCommitProto(BOOKMARKS, + request_data, &entity); // Exhaustively verify the populated SyncEntity. EXPECT_FALSE(entity.id_string().empty());
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor.cc b/components/sync/model_impl/client_tag_based_model_type_processor.cc index 92192c66..1c09d5b 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor.cc +++ b/components/sync/model_impl/client_tag_based_model_type_processor.cc
@@ -293,8 +293,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Ignore all errors after the first. - if (model_error_) + if (model_error_) { return; + } model_error_ = error; @@ -307,14 +308,14 @@ DisconnectSync(); } - if (start_callback_) { - // Tell sync about the error instead of connecting. - ConnectIfReady(); - } else if (activation_request_.error_handler) { - // Connecting was already initiated; just tell sync about the error instead - // of going through ConnectIfReady(). + // Shouldn't connect anymore. + start_callback_.Reset(); + if (activation_request_.error_handler) { + // Tell sync about the error. activation_request_.error_handler.Run(error); } + // If the error handler isn't ready yet, we defer reporting the error until it + // becomes available which happens in ConnectIfReady() upon OnSyncStarting(). } base::Optional<ModelError> ClientTagBasedModelTypeProcessor::GetError() const {
diff --git a/components/thread_pool_util/BUILD.gn b/components/thread_pool_util/BUILD.gn deleted file mode 100644 index aa15acb..0000000 --- a/components/thread_pool_util/BUILD.gn +++ /dev/null
@@ -1,27 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -static_library("thread_pool_util") { - sources = [ - "variations_util.cc", - "variations_util.h", - ] - - deps = [ - "//base", - ] -} - -source_set("unit_tests") { - testonly = true - sources = [ - "variations_util_unittest.cc", - ] - deps = [ - ":thread_pool_util", - "//base", - "//components/variations:test_support", - "//testing/gtest", - ] -}
diff --git a/components/thread_pool_util/DEPS b/components/thread_pool_util/DEPS deleted file mode 100644 index be216e98a..0000000 --- a/components/thread_pool_util/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - "+components/variations/variations_params_manager.h", -]
diff --git a/components/thread_pool_util/OWNERS b/components/thread_pool_util/OWNERS deleted file mode 100644 index a003810..0000000 --- a/components/thread_pool_util/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://base/task/thread_pool/OWNERS
diff --git a/components/thread_pool_util/variations_util.cc b/components/thread_pool_util/variations_util.cc deleted file mode 100644 index f690e57e..0000000 --- a/components/thread_pool_util/variations_util.cc +++ /dev/null
@@ -1,125 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/thread_pool_util/variations_util.h" - -#include <map> -#include <string> - -#include "base/logging.h" -#include "base/metrics/field_trial_params.h" -#include "base/strings/strcat.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/task/thread_pool/initialization_util.h" -#include "base/time/time.h" - -namespace thread_pool_util { - -namespace { - -// Builds a ThreadGroupParams from the pool descriptor in -// |variation_params[pool_name]|. Returns an invalid -// ThreadGroupParams on failure. -// -// The pool descriptor is a semi-colon separated value string with the following -// items: -// 0. Minimum Thread Count (int) -// 1. Maximum Thread Count (int) -// 2. Thread Count Multiplier (double) -// 3. Thread Count Offset (int) -// 4. Detach Time in Milliseconds (int) -// Additional values may appear as necessary and will be ignored. -std::unique_ptr<base::ThreadGroupParams> GetThreadGroupParams( - base::StringPiece pool_name, - const std::map<std::string, std::string>& variation_params) { - auto pool_descriptor_it = variation_params.find(pool_name.as_string()); - if (pool_descriptor_it == variation_params.end()) - return nullptr; - const auto& pool_descriptor = pool_descriptor_it->second; - - const std::vector<base::StringPiece> tokens = SplitStringPiece( - pool_descriptor, ";", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - // Normally, we wouldn't initialize the values below because we don't read - // from them before we write to them. However, some compilers (like MSVC) - // complain about uninitialized variables due to the as_string() call below. - int min = 0; - int max = 0; - double cores_multiplier = 0.0; - int offset = 0; - int detach_milliseconds = 0; - // Checking for a size greater than the expected amount allows us to be - // forward compatible if we add more variation values. - if (tokens.size() < 5 || !base::StringToInt(tokens[0], &min) || - !base::StringToInt(tokens[1], &max) || - !base::StringToDouble(tokens[2].as_string(), &cores_multiplier) || - !base::StringToInt(tokens[3], &offset) || - !base::StringToInt(tokens[4], &detach_milliseconds)) { - DLOG(ERROR) << "Invalid Worker Pool Descriptor Format: " << pool_descriptor; - return nullptr; - } - - auto params = std::make_unique<base::ThreadGroupParams>( - base::RecommendedMaxNumberOfThreadsInThreadGroup( - min, max, cores_multiplier, offset), - base::TimeDelta::FromMilliseconds(detach_milliseconds)); - - if (params->max_tasks() <= 0) { - DLOG(ERROR) << "Invalid max tasks in the Worker Pool Descriptor: " - << params->max_tasks(); - return nullptr; - } - - if (params->suggested_reclaim_time() < base::TimeDelta()) { - DLOG(ERROR) - << "Invalid suggested reclaim time in the Worker Pool Descriptor:" - << params->suggested_reclaim_time(); - return nullptr; - } - - return params; -} - -} // namespace - -const base::Feature kBrowserThreadPoolInitParams = { - "BrowserThreadPoolInitParams", base::FEATURE_DISABLED_BY_DEFAULT}; - -const base::Feature kRendererThreadPoolInitParams = { - "RendererThreadPoolInitParams", base::FEATURE_DISABLED_BY_DEFAULT}; - -std::unique_ptr<base::ThreadPool::InitParams> GetThreadPoolInitParams( - const base::Feature& feature) { - std::map<std::string, std::string> variation_params; - if (!base::GetFieldTrialParamsByFeature(feature, &variation_params)) - return nullptr; - - const auto background_worker_pool_params = - GetThreadGroupParams("Background", variation_params); - const auto foreground_worker_pool_params = - GetThreadGroupParams("Foreground", variation_params); - - if (!background_worker_pool_params || !foreground_worker_pool_params) - return nullptr; - - return std::make_unique<base::ThreadPool::InitParams>( - *background_worker_pool_params, *foreground_worker_pool_params); -} - -std::unique_ptr<base::ThreadPool::InitParams> -GetThreadPoolInitParamsForBrowser() { - // Variations params for the browser processes are associated with the feature - // |kBrowserThreadPoolInitParams|. - return GetThreadPoolInitParams(kBrowserThreadPoolInitParams); -} - -std::unique_ptr<base::ThreadPool::InitParams> -GetThreadPoolInitParamsForRenderer() { - // Variations params for the renderer processes are associated with the - // feature |kRendererThreadPoolInitParams|. - return GetThreadPoolInitParams(kRendererThreadPoolInitParams); -} - -} // namespace thread_pool_util
diff --git a/components/thread_pool_util/variations_util.h b/components/thread_pool_util/variations_util.h deleted file mode 100644 index 9be9f66..0000000 --- a/components/thread_pool_util/variations_util.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_THREAD_POOL_UTIL_VARIATIONS_UTIL_H_ -#define COMPONENTS_THREAD_POOL_UTIL_VARIATIONS_UTIL_H_ - -#include <memory> - -#include "base/feature_list.h" -#include "base/strings/string_piece.h" -#include "base/task/thread_pool/thread_pool.h" - -namespace thread_pool_util { - -extern const base::Feature kBrowserThreadPoolInitParams; -extern const base::Feature kRendererThreadPoolInitParams; - -// Builds a ThreadPool::InitParams from variations params that are prefixed -// for |feature|. Returns nullptr on failure. -// -// TODO(fdoray): Move this to the anonymous namespace in the .cc file. -// https://crbug.com/810049 -std::unique_ptr<base::ThreadPool::InitParams> GetThreadPoolInitParams( - const base::Feature& feature); - -// Builds a ThreadPool::InitParams to use in the browser process from -// variation params in the BrowserThreadPool field trial. -std::unique_ptr<base::ThreadPool::InitParams> -GetThreadPoolInitParamsForBrowser(); - -// Builds a ThreadPool::InitParams to use in renderer processes from -// variation params in the RendererThreadPool field trial. -std::unique_ptr<base::ThreadPool::InitParams> -GetThreadPoolInitParamsForRenderer(); - -} // namespace thread_pool_util - -#endif // COMPONENTS_THREAD_POOL_UTIL_VARIATIONS_UTIL_H_
diff --git a/components/thread_pool_util/variations_util_unittest.cc b/components/thread_pool_util/variations_util_unittest.cc deleted file mode 100644 index fc23d859..0000000 --- a/components/thread_pool_util/variations_util_unittest.cc +++ /dev/null
@@ -1,117 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/thread_pool_util/variations_util.h" - -#include <map> -#include <string> - -#include "base/macros.h" -#include "base/metrics/field_trial.h" -#include "base/task/thread_pool/thread_group_params.h" -#include "base/task/thread_pool/worker_thread_params.h" -#include "components/variations/variations_params_manager.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace thread_pool_util { - -namespace { - -class ThreadPoolUtilVariationsUtilTest : public testing::Test { - protected: - ThreadPoolUtilVariationsUtilTest() = default; - - void SetVariationParams( - const std::map<std::string, std::string>& variation_params) { - std::set<std::string> features; - features.insert(kRendererThreadPoolInitParams.name); - variation_params_manager_.SetVariationParamsWithFeatureAssociations( - "DummyTrial", variation_params, features); - } - - private: - variations::testing::VariationParamsManager variation_params_manager_; - - DISALLOW_COPY_AND_ASSIGN(ThreadPoolUtilVariationsUtilTest); -}; - -} // namespace - -TEST_F(ThreadPoolUtilVariationsUtilTest, OrderingParams5) { - std::map<std::string, std::string> variation_params; - variation_params["Background"] = "1;1;1;0;42"; - variation_params["Foreground"] = "4;4;1;0;62"; - SetVariationParams(variation_params); - - auto init_params = GetThreadPoolInitParams(kRendererThreadPoolInitParams); - ASSERT_TRUE(init_params); - - EXPECT_EQ(1, init_params->background_thread_group_params.max_tasks()); - EXPECT_EQ( - base::TimeDelta::FromMilliseconds(42), - init_params->background_thread_group_params.suggested_reclaim_time()); - EXPECT_EQ( - base::WorkerThreadBackwardCompatibility::DISABLED, - init_params->background_thread_group_params.backward_compatibility()); - - EXPECT_EQ(4, init_params->foreground_thread_group_params.max_tasks()); - EXPECT_EQ( - base::TimeDelta::FromMilliseconds(62), - init_params->foreground_thread_group_params.suggested_reclaim_time()); - EXPECT_EQ( - base::WorkerThreadBackwardCompatibility::DISABLED, - init_params->foreground_thread_group_params.backward_compatibility()); -} - -TEST_F(ThreadPoolUtilVariationsUtilTest, NoData) { - EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams)); -} - -TEST_F(ThreadPoolUtilVariationsUtilTest, IncompleteParameters) { - std::map<std::string, std::string> variation_params; - variation_params["Background"] = "1;1;1;0"; - variation_params["Foreground"] = "4;4;1;0"; - SetVariationParams(variation_params); - EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams)); -} - -TEST_F(ThreadPoolUtilVariationsUtilTest, InvalidParametersFormat) { - std::map<std::string, std::string> variation_params; - variation_params["Background"] = "a;b;c;d;e"; - variation_params["Foreground"] = "a;b;c;d;e"; - SetVariationParams(variation_params); - EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams)); -} - -TEST_F(ThreadPoolUtilVariationsUtilTest, ZeroMaxThreads) { - // The Background thread group has a maximum number of threads equal to zero, - // which is invalid. - std::map<std::string, std::string> variation_params; - variation_params["Background"] = "0;0;0;0;0"; - variation_params["Foreground"] = "4;4;1;0;62"; - SetVariationParams(variation_params); - EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams)); -} - -TEST_F(ThreadPoolUtilVariationsUtilTest, NegativeMaxThreads) { - // The Background thread group has a negative maximum number of threads, which - // is invalid. - std::map<std::string, std::string> variation_params; - variation_params["Background"] = "-5;-5;0;0;0"; - variation_params["Foreground"] = "4;4;1;0;62"; - SetVariationParams(variation_params); - EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams)); -} - -TEST_F(ThreadPoolUtilVariationsUtilTest, NegativeSuggestedReclaimTime) { - // The Background thread group has a negative suggested reclaim time, which is - // invalid. - std::map<std::string, std::string> variation_params; - variation_params["Background"] = "1;1;1;0;-5"; - variation_params["Foreground"] = "4;4;1;0;62"; - SetVariationParams(variation_params); - EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams)); -} - -} // namespace thread_pool_util
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 3c6769fb..c9d44d7 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -1622,12 +1622,8 @@ bg_paint_filter ? bg_paint_filter->cached_sk_filter_ : nullptr; if (sk_bg_filter) { - SkMatrix content_to_dest = SkMatrix::MakeRectToRect( - gfx::RectFToSkRect(quad->tex_coord_rect), - gfx::RectToSkRect(quad->rect), SkMatrix::kFill_ScaleToFit); - content_to_dest.preConcat(local_matrix); rpdq_params.backdrop_filter = - sk_bg_filter->makeWithLocalMatrix(content_to_dest); + sk_bg_filter->makeWithLocalMatrix(local_matrix); } } @@ -1637,16 +1633,10 @@ const base::Optional<gfx::RRectF> backdrop_filter_bounds = BackdropFilterBoundsForPass(quad->render_pass_id); if (backdrop_filter_bounds) { - // Map this into the same coordinate system as the quad. - // (See gl_renderer::GetBackdropBoundingBoxForRenderPassQuad) rpdq_params.backdrop_filter_bounds = *backdrop_filter_bounds; // Scale by the filter's scale, but don't apply filter origin rpdq_params.backdrop_filter_bounds->Scale(quad->filters_scale.x(), quad->filters_scale.y()); - // Offset by the render pass' output rect. - rpdq_params.backdrop_filter_bounds->Offset( - gfx::Point() - - current_frame()->current_render_pass->output_rect.origin()); // If there are also regular image filters, they apply to the area of // the backdrop_filter_bounds too, so expand the backdrop bounds and join
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 47207ee..d355cc6 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -230,7 +230,7 @@ public_deps = [ ":accessibility_buildflags", - "//base/util/type-safety", + "//base/util/type_safety", "//ipc", "//media/mojo/interfaces:remoting", "//third_party/blink/public/mojom:embedded_frame_sink_mojo_bindings", @@ -1330,6 +1330,8 @@ "notification_service_impl.h", "notifications/blink_notification_service_impl.cc", "notifications/blink_notification_service_impl.h", + "notifications/devtools_event_logging.cc", + "notifications/devtools_event_logging.h", "notifications/notification_database.cc", "notifications/notification_database.h", "notifications/notification_database_conversions.cc",
diff --git a/content/browser/devtools/devtools_background_services.proto b/content/browser/devtools/devtools_background_services.proto index c51c161..8a80f14 100644 --- a/content/browser/devtools/devtools_background_services.proto +++ b/content/browser/devtools/devtools_background_services.proto
@@ -17,9 +17,10 @@ BACKGROUND_FETCH = 2; BACKGROUND_SYNC = 3; PUSH_MESSAGING = 4; + NOTIFICATIONS = 5; // Keep as last, must have the largest tag value. - COUNT = 5; + COUNT = 6; } // A proto for storing the background service event with common metadata for
diff --git a/content/browser/devtools/devtools_background_services_context_impl.cc b/content/browser/devtools/devtools_background_services_context_impl.cc index b8931c1..21ba92eb 100644 --- a/content/browser/devtools/devtools_background_services_context_impl.cc +++ b/content/browser/devtools/devtools_background_services_context_impl.cc
@@ -49,6 +49,8 @@ return devtools::proto::BACKGROUND_SYNC; case DevToolsBackgroundService::kPushMessaging: return devtools::proto::PUSH_MESSAGING; + case DevToolsBackgroundService::kNotifications: + return devtools::proto::NOTIFICATIONS; } }
diff --git a/content/browser/download/save_types.h b/content/browser/download/save_types.h index 77fdf8c..219aa86 100644 --- a/content/browser/download/save_types.h +++ b/content/browser/download/save_types.h
@@ -13,7 +13,7 @@ #include <vector> #include "base/files/file_path.h" -#include "base/util/type-safety/id_type.h" +#include "base/util/type_safety/id_type.h" #include "url/gurl.h" namespace content {
diff --git a/content/browser/isolation_context.h b/content/browser/isolation_context.h index 82f69d0..a607fdb 100644 --- a/content/browser/isolation_context.h +++ b/content/browser/isolation_context.h
@@ -6,7 +6,7 @@ #define CONTENT_BROWSER_ISOLATION_CONTEXT_H_ #include "base/optional.h" -#include "base/util/type-safety/id_type.h" +#include "base/util/type_safety/id_type.h" #include "content/common/content_export.h" #include "content/public/browser/browser_or_resource_context.h"
diff --git a/content/browser/notifications/devtools_event_logging.cc b/content/browser/notifications/devtools_event_logging.cc new file mode 100644 index 0000000..c91c2d8 --- /dev/null +++ b/content/browser/notifications/devtools_event_logging.cc
@@ -0,0 +1,141 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/notifications/devtools_event_logging.h" + +#include "base/callback.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/devtools_background_services_context.h" +#include "content/public/browser/notification_database_data.h" +#include "content/public/browser/storage_partition.h" +#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" +#include "url/gurl.h" + +namespace content { +namespace notifications { + +namespace { + +using EventMetadata = std::map<std::string, std::string>; +using DevToolsBaseCallback = + base::OnceCallback<void(const std::string& event_name, + const std::string& instance_id, + const EventMetadata& event_metadata)>; +using DevToolsCallback = + base::OnceCallback<void(const std::string& event_name, + const EventMetadata& event_metadata)>; + +DevToolsBackgroundServicesContext* GetDevToolsContext( + BrowserContext* browser_context, + const GURL& origin) { + auto* storage_partition = + BrowserContext::GetStoragePartitionForSite(browser_context, origin); + if (!storage_partition) + return nullptr; + + auto* devtools_context = + storage_partition->GetDevToolsBackgroundServicesContext(); + if (!devtools_context || !devtools_context->IsRecording( + DevToolsBackgroundService::kNotifications)) { + return nullptr; + } + + return devtools_context; +} + +DevToolsCallback GetDevToolsCallback(BrowserContext* browser_context, + const NotificationDatabaseData& data) { + if (data.service_worker_registration_id == + blink::mojom::kInvalidServiceWorkerRegistrationId) { + return DevToolsCallback(); + } + + auto* devtools_context = GetDevToolsContext(browser_context, data.origin); + if (!devtools_context) + return DevToolsCallback(); + + // Passing the |devtools_context| as base::Unretained is safe as the callback + // is executed synchronously. + auto base_callback = base::BindOnce( + &DevToolsBackgroundServicesContext::LogBackgroundServiceEvent, + base::Unretained(devtools_context), data.service_worker_registration_id, + url::Origin::Create(data.origin), + DevToolsBackgroundService::kNotifications); + + // TODO(knollr): Reorder parameters of LogBackgroundServiceEvent instead. + return base::BindOnce( + [](DevToolsBaseCallback callback, const std::string& notification_id, + const std::string& event_name, const EventMetadata& metadata) { + std::move(callback).Run(event_name, notification_id, metadata); + }, + std::move(base_callback), data.notification_data.tag); +} + +} // namespace + +bool ShouldLogNotificationEventToDevTools(BrowserContext* browser_context, + const GURL& origin) { + return GetDevToolsContext(browser_context, origin) != nullptr; +} + +void LogNotificationDisplayedEventToDevTools( + BrowserContext* browser_context, + const NotificationDatabaseData& data) { + DevToolsCallback callback = GetDevToolsCallback(browser_context, data); + if (!callback) + return; + + std::move(callback).Run(/* event_name= */ "Notification displayed", + /* event_metadata= */ {}); +} + +void LogNotificationClosedEventToDevTools( + BrowserContext* browser_context, + const NotificationDatabaseData& data) { + DevToolsCallback callback = GetDevToolsCallback(browser_context, data); + if (!callback) + return; + + std::move(callback).Run(/* event_name= */ "Notification closed", + /* event_metadata= */ {}); +} + +void LogNotificationScheduledEventToDevTools( + BrowserContext* browser_context, + const NotificationDatabaseData& data, + base::Time show_trigger_timestamp) { + DevToolsCallback callback = GetDevToolsCallback(browser_context, data); + if (!callback) + return; + + std::move(callback).Run( + /* event_name= */ "Notification scheduled", + /* event_metadata= */ { + {"Show Trigger Timestamp", + base::NumberToString(show_trigger_timestamp.ToJsTime())}}); +} + +void LogNotificationClickedEventToDevTools( + BrowserContext* browser_context, + const NotificationDatabaseData& data, + const base::Optional<int>& action_index, + const base::Optional<base::string16>& reply) { + DevToolsCallback callback = GetDevToolsCallback(browser_context, data); + if (!callback) + return; + + EventMetadata event_metadata; + if (action_index) + event_metadata["Action Index"] = base::NumberToString(*action_index); + if (reply) + event_metadata["Reply"] = base::UTF16ToUTF8(*reply); + + std::move(callback).Run(/* event_name= */ "Notification clicked", + event_metadata); +} + +} // namespace notifications +} // namespace content
diff --git a/content/browser/notifications/devtools_event_logging.h b/content/browser/notifications/devtools_event_logging.h new file mode 100644 index 0000000..c46a226 --- /dev/null +++ b/content/browser/notifications/devtools_event_logging.h
@@ -0,0 +1,47 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_NOTIFICATIONS_DEVTOOLS_EVENT_LOGGING_H_ +#define CONTENT_BROWSER_NOTIFICATIONS_DEVTOOLS_EVENT_LOGGING_H_ + +#include <string> + +#include "base/optional.h" +#include "base/strings/string16.h" +#include "base/time/time.h" + +class GURL; + +namespace content { + +class BrowserContext; +struct NotificationDatabaseData; + +namespace notifications { + +bool ShouldLogNotificationEventToDevTools(BrowserContext* browser_context, + const GURL& origin); + +void LogNotificationDisplayedEventToDevTools( + BrowserContext* browser_context, + const NotificationDatabaseData& data); + +void LogNotificationClosedEventToDevTools(BrowserContext* browser_context, + const NotificationDatabaseData& data); + +void LogNotificationScheduledEventToDevTools( + BrowserContext* browser_context, + const NotificationDatabaseData& data, + base::Time show_trigger_timestamp); + +void LogNotificationClickedEventToDevTools( + BrowserContext* browser_context, + const NotificationDatabaseData& data, + const base::Optional<int>& action_index, + const base::Optional<base::string16>& reply); + +} // namespace notifications +} // namespace content + +#endif // CONTENT_BROWSER_NOTIFICATIONS_DEVTOOLS_EVENT_LOGGING_H_
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc index 1993d8f4..ba2bb907 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.cc +++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -11,6 +11,7 @@ #include "base/optional.h" #include "base/task/post_task.h" #include "build/build_config.h" +#include "content/browser/notifications/devtools_event_logging.h" #include "content/browser/notifications/platform_notification_context_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_registration.h" @@ -34,6 +35,7 @@ NotificationDispatchCompleteCallback)>; using NotificationOperationCallbackWithContext = base::OnceCallback<void(const scoped_refptr<PlatformNotificationContext>&, + BrowserContext* browser_context, const ServiceWorkerRegistration*, const NotificationDatabaseData&, NotificationDispatchCompleteCallback)>; @@ -153,7 +155,7 @@ } // Finds the ServiceWorkerRegistration associated with the |origin| and -// |service_worker_registration_id|. Must be called on the IO thread. +// |service_worker_registration_id|. Must be called on the UI thread. void FindServiceWorkerRegistration( const GURL& origin, const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context, @@ -240,10 +242,18 @@ const base::Optional<int>& action_index, const base::Optional<base::string16>& reply, const scoped_refptr<PlatformNotificationContext>& notification_context, + BrowserContext* browser_context, const ServiceWorkerRegistration* service_worker_registration, const NotificationDatabaseData& notification_database_data, NotificationDispatchCompleteCallback dispatch_complete_callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(¬ifications::LogNotificationClickedEventToDevTools, + browser_context, notification_database_data, action_index, + reply)); + service_worker_registration->active_version()->RunAfterStartWorker( ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK, base::BindOnce( @@ -317,6 +327,7 @@ const std::string& notification_id, bool by_user, const scoped_refptr<PlatformNotificationContext>& notification_context, + BrowserContext* browser_context, const ServiceWorkerRegistration* service_worker_registration, const NotificationDatabaseData& notification_database_data, NotificationDispatchCompleteCallback dispatch_complete_callback) { @@ -366,7 +377,7 @@ notification_id, origin, interaction, service_worker_context, notification_context, base::BindOnce(std::move(notification_action_callback), - notification_context), + notification_context, browser_context), std::move(dispatch_complete_callback)); }
diff --git a/content/browser/notifications/platform_notification_context_impl.cc b/content/browser/notifications/platform_notification_context_impl.cc index 6e10dbb..9402a2b 100644 --- a/content/browser/notifications/platform_notification_context_impl.cc +++ b/content/browser/notifications/platform_notification_context_impl.cc
@@ -725,14 +725,13 @@ service_proxy_->CloseNotification(notification_id); // Schedule notification to be shown. - service_proxy_->ScheduleTrigger( - write_database_data.notification_data.show_trigger_timestamp.value()); + service_proxy_->ScheduleNotification(std::move(write_database_data)); // Respond with success as this notification got scheduled successfully. base::PostTaskWithTraits( FROM_HERE, {BrowserThread::UI}, base::BindOnce(std::move(callback), /* success= */ true, - write_database_data.notification_id)); + notification_id)); return; } @@ -767,15 +766,17 @@ if (close_notification) service_proxy_->CloseNotification(notification_id); - LazyInitialize( - base::BindOnce(&PlatformNotificationContextImpl::DoDeleteNotificationData, - this, notification_id, origin, std::move(callback))); + bool should_log_close = service_proxy_->ShouldLogClose(origin); + LazyInitialize(base::BindOnce( + &PlatformNotificationContextImpl::DoDeleteNotificationData, this, + notification_id, origin, std::move(callback), should_log_close)); } void PlatformNotificationContextImpl::DoDeleteNotificationData( const std::string& notification_id, const GURL& origin, DeleteResultCallback callback, + bool should_log_close, bool initialized) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (!initialized) { @@ -784,6 +785,15 @@ return; } + // Read additional data if we need to log the close event. + if (should_log_close) { + NotificationDatabaseData data; + if (database_->ReadNotificationData(notification_id, origin, &data) == + NotificationDatabase::STATUS_OK) { + service_proxy_->LogClose(std::move(data)); + } + } + NotificationDatabase::Status status = database_->DeleteNotificationData(notification_id, origin);
diff --git a/content/browser/notifications/platform_notification_context_impl.h b/content/browser/notifications/platform_notification_context_impl.h index 2544c6a6f..3373171 100644 --- a/content/browser/notifications/platform_notification_context_impl.h +++ b/content/browser/notifications/platform_notification_context_impl.h
@@ -207,6 +207,7 @@ void DoDeleteNotificationData(const std::string& notification_id, const GURL& origin, DeleteResultCallback callback, + bool should_log_close, bool initialized); // Actually reads all notification origins from the database. Must only be
diff --git a/content/browser/notifications/platform_notification_context_trigger_unittest.cc b/content/browser/notifications/platform_notification_context_trigger_unittest.cc index 4750c58c..de2d611 100644 --- a/content/browser/notifications/platform_notification_context_trigger_unittest.cc +++ b/content/browser/notifications/platform_notification_context_trigger_unittest.cc
@@ -62,6 +62,8 @@ } void SetUp() override { + // Advance time a little bit so TimeTicks::Now().is_null() becomes false. + thread_bundle_.FastForwardBy(base::TimeDelta::FromMilliseconds(1)); scoped_feature_list_.InitAndEnableFeature(features::kNotificationTriggers); platform_notification_context_ = base::MakeRefCounted<PlatformNotificationContextImpl>(
diff --git a/content/browser/notifications/platform_notification_service_proxy.cc b/content/browser/notifications/platform_notification_service_proxy.cc index 5ad2b972..41c4ac8 100644 --- a/content/browser/notifications/platform_notification_service_proxy.cc +++ b/content/browser/notifications/platform_notification_service_proxy.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/task/post_task.h" +#include "content/browser/notifications/devtools_event_logging.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/content_browser_client.h" @@ -21,6 +22,7 @@ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, BrowserContext* browser_context) : service_worker_context_(service_worker_context), + browser_context_(browser_context), notification_service_( GetContentClient()->browser()->GetPlatformNotificationService( browser_context)), @@ -49,6 +51,8 @@ data.notification_id, service_worker_scope, data.origin, data.notification_data, data.notification_resources.value_or(blink::NotificationResources())); + notifications::LogNotificationDisplayedEventToDevTools(browser_context_, + data); } std::move(callback).Run(/* success= */ true, data.notification_id); } @@ -126,6 +130,27 @@ notification_service_->ScheduleTrigger(timestamp); } +void PlatformNotificationServiceProxy::ScheduleNotification( + const NotificationDatabaseData& data) { + DCHECK(data.notification_data.show_trigger_timestamp.has_value()); + if (!notification_service_) + return; + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&PlatformNotificationServiceProxy::DoScheduleNotification, + AsWeakPtr(), data)); +} + +void PlatformNotificationServiceProxy::DoScheduleNotification( + const NotificationDatabaseData& data) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + base::Time show_trigger_timestamp = + data.notification_data.show_trigger_timestamp.value(); + notifications::LogNotificationScheduledEventToDevTools( + browser_context_, data, show_trigger_timestamp); + notification_service_->ScheduleTrigger(show_trigger_timestamp); +} + base::Time PlatformNotificationServiceProxy::GetNextTrigger() { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!notification_service_) @@ -141,4 +166,24 @@ notification_service_->RecordNotificationUkmEvent(data); } +bool PlatformNotificationServiceProxy::ShouldLogClose(const GURL& origin) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return notifications::ShouldLogNotificationEventToDevTools(browser_context_, + origin); +} + +void PlatformNotificationServiceProxy::LogClose( + const NotificationDatabaseData& data) { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI, base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&PlatformNotificationServiceProxy::DoLogClose, AsWeakPtr(), + data)); +} + +void PlatformNotificationServiceProxy::DoLogClose( + const NotificationDatabaseData& data) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + notifications::LogNotificationClosedEventToDevTools(browser_context_, data); +} + } // namespace content
diff --git a/content/browser/notifications/platform_notification_service_proxy.h b/content/browser/notifications/platform_notification_service_proxy.h index c24cf42..1d0693c 100644 --- a/content/browser/notifications/platform_notification_service_proxy.h +++ b/content/browser/notifications/platform_notification_service_proxy.h
@@ -58,6 +58,9 @@ // Schedules a notification trigger for |timestamp|. void ScheduleTrigger(base::Time timestamp); + // Schedules a notification with |data|. + void ScheduleNotification(const NotificationDatabaseData& data); + // Gets the next notification trigger or base::Time::Max if none set. Must be // called on the UI thread. base::Time GetNextTrigger(); @@ -65,6 +68,13 @@ // Records a given notification to UKM. Must be called on the UI thread. void RecordNotificationUkmEvent(const NotificationDatabaseData& data); + // Returns if we should log a notification close event by calling LogClose. + // Must be called on the UI thread. + bool ShouldLogClose(const GURL& origin); + + // Logs the event of closing a notification. + void LogClose(const NotificationDatabaseData& data); + private: // Actually calls |notification_service_| to display the notification after // verifying the |service_worker_scope|. Must be called on the UI thread. @@ -80,6 +90,14 @@ // called on the UI thread. void DoScheduleTrigger(base::Time timestamp); + // Actually calls |notification_service_| to schedule a notification. Must be + // called on the UI thread. + void DoScheduleNotification(const NotificationDatabaseData& data); + + // Actually logs the event of closing a notification. Must be called on the UI + // thread. + void DoLogClose(const NotificationDatabaseData& data); + // Verifies that the service worker exists and is valid for the given // notification origin. void VerifyServiceWorkerScope( @@ -89,6 +107,7 @@ scoped_refptr<ServiceWorkerRegistration> registration); scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; + BrowserContext* browser_context_; PlatformNotificationService* notification_service_; base::WeakPtrFactory<PlatformNotificationServiceProxy> weak_ptr_factory_ui_; base::WeakPtrFactory<PlatformNotificationServiceProxy> weak_ptr_factory_io_;
diff --git a/content/browser/startup_helper.cc b/content/browser/startup_helper.cc index 0f3b07b..7de51dcc 100644 --- a/content/browser/startup_helper.cc +++ b/content/browser/startup_helper.cc
@@ -11,42 +11,10 @@ #include "base/task/thread_pool/thread_pool.h" #include "build/build_config.h" #include "content/common/thread_pool_util.h" -#include "content/public/browser/content_browser_client.h" #include "content/public/common/content_switches.h" namespace content { -namespace { - -std::unique_ptr<base::ThreadPool::InitParams> GetDefaultThreadPoolInitParams() { -#if defined(OS_ANDROID) - // Mobile config, for iOS see ios/web/app/web_main_loop.cc. - return std::make_unique<base::ThreadPool::InitParams>( - base::ThreadGroupParams( - base::RecommendedMaxNumberOfThreadsInThreadGroup(4, 8, 0.2, 0), - base::TimeDelta::FromSeconds(30)), - base::ThreadGroupParams( - base::RecommendedMaxNumberOfThreadsInThreadGroup(6, 8, 0.6, 0), - base::TimeDelta::FromSeconds(30))); -#else - // Desktop config. - return std::make_unique<base::ThreadPool::InitParams>( - base::ThreadGroupParams( - base::RecommendedMaxNumberOfThreadsInThreadGroup(6, 8, 0.2, 0), - base::TimeDelta::FromSeconds(30)), - base::ThreadGroupParams( - base::RecommendedMaxNumberOfThreadsInThreadGroup(16, 32, 0.6, 0), - base::TimeDelta::FromSeconds(30)) -#if defined(OS_WIN) - , - base::ThreadPool::InitParams::CommonThreadPoolEnvironment::COM_MTA -#endif // defined(OS_WIN) - ); -#endif -} - -} // namespace - std::unique_ptr<base::FieldTrialList> SetUpFieldTrialsAndFeatureList() { auto field_trial_list = std::make_unique<base::FieldTrialList>(nullptr); const base::CommandLine* command_line = @@ -69,28 +37,34 @@ return field_trial_list; } +// TODO(scheduler-dev): Standardize thread pool logic and remove the need for +// specifying thread count manually. void StartBrowserThreadPool() { - auto thread_pool_init_params = - GetContentClient()->browser()->GetThreadPoolInitParams(); - if (!thread_pool_init_params) - thread_pool_init_params = GetDefaultThreadPoolInitParams(); - DCHECK(thread_pool_init_params); + base::ThreadPool::InitParams thread_pool_init_params = { +#if defined(OS_ANDROID) + // Mobile config, for iOS see ios/web/app/web_main_loop.cc. + base::RecommendedMaxNumberOfThreadsInThreadGroup(6, 8, 0.6, 0) +#else + // Desktop config. + base::RecommendedMaxNumberOfThreadsInThreadGroup(16, 32, 0.6, 0) +#endif + }; + +#if defined(OS_WIN) + thread_pool_init_params.common_thread_pool_environment = + base::ThreadPool::InitParams::CommonThreadPoolEnvironment::COM_MTA; +#endif // If a renderer lives in the browser process, adjust the number of // threads in the foreground pool. if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kSingleProcess)) { - const base::ThreadGroupParams& current_foreground_thread_group_params( - thread_pool_init_params->foreground_thread_group_params); - thread_pool_init_params->foreground_thread_group_params = - base::ThreadGroupParams( - std::max(GetMinForegroundThreadsInRendererThreadPool(), - current_foreground_thread_group_params.max_tasks()), - current_foreground_thread_group_params.suggested_reclaim_time(), - current_foreground_thread_group_params.backward_compatibility()); + thread_pool_init_params.max_num_foreground_threads = + std::max(GetMinForegroundThreadsInRendererThreadPool(), + thread_pool_init_params.max_num_foreground_threads); } - base::ThreadPool::GetInstance()->Start(*thread_pool_init_params.get()); + base::ThreadPool::GetInstance()->Start(thread_pool_init_params); } } // namespace content
diff --git a/content/browser/web_contents/web_contents_view_mac.h b/content/browser/web_contents/web_contents_view_mac.h index 4266d4c..f5d9025 100644 --- a/content/browser/web_contents/web_contents_view_mac.h +++ b/content/browser/web_contents/web_contents_view_mac.h
@@ -94,6 +94,7 @@ RenderWidgetHostImpl* source_rwh) override; void UpdateDragCursor(blink::WebDragOperation operation) override; void GotFocus(RenderWidgetHostImpl* render_widget_host) override; + void LostFocus(RenderWidgetHostImpl* render_widget_host) override; void TakeFocus(bool reverse) override; void ShowContextMenu(RenderFrameHost* render_frame_host, const ContextMenuParams& params) override;
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm index 57747d1..59198bf 100644 --- a/content/browser/web_contents/web_contents_view_mac.mm +++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -246,6 +246,10 @@ web_contents_->NotifyWebContentsFocused(render_widget_host); } +void WebContentsViewMac::LostFocus(RenderWidgetHostImpl* render_widget_host) { + web_contents_->NotifyWebContentsLostFocus(render_widget_host); +} + // This is called when the renderer asks us to take focus back (i.e., it has // iterated past the last focusable element on the page). void WebContentsViewMac::TakeFocus(bool reverse) {
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 74da3cc..da482a1a 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -732,11 +732,6 @@ return nullptr; } -std::unique_ptr<base::ThreadPool::InitParams> -ContentBrowserClient::GetThreadPoolInitParams() { - return nullptr; -} - std::vector<std::unique_ptr<URLLoaderThrottle>> ContentBrowserClient::CreateURLLoaderThrottles( const network::ResourceRequest& request,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 3545b14..5e79a99 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -1178,11 +1178,6 @@ // Returns the RapporService from the browser process. virtual ::rappor::RapporService* GetRapporService(); - // Provides parameters for initializing the global thread pool. Default - // params are used if this returns nullptr. - virtual std::unique_ptr<base::ThreadPool::InitParams> - GetThreadPoolInitParams(); - // Allows the embedder to register one or more URLLoaderThrottles for a // navigation request. // This is called both when the network service is enabled and disabled.
diff --git a/content/public/browser/devtools_background_services_context.h b/content/public/browser/devtools_background_services_context.h index b85e14a..bc479aa 100644 --- a/content/public/browser/devtools_background_services_context.h +++ b/content/public/browser/devtools_background_services_context.h
@@ -22,9 +22,10 @@ kBackgroundFetch = 2, kBackgroundSync = 3, kPushMessaging = 4, + kNotifications = 5, // Keep at the end. - kMaxValue = kPushMessaging, + kMaxValue = kNotifications, }; // This class is responsible for persisting the debugging events for the
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc index 09391a1..41d7d15 100644 --- a/content/public/renderer/content_renderer_client.cc +++ b/content/public/renderer/content_renderer_client.cc
@@ -236,11 +236,6 @@ return GURL(); } -std::unique_ptr<base::ThreadPool::InitParams> -ContentRendererClient::GetThreadPoolInitParams() { - return nullptr; -} - bool ContentRendererClient::IsIdleMediaSuspendEnabled() { return true; }
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 9e405a1f9..5bcf6f9 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -388,11 +388,6 @@ // An empty URL is returned if the URL is not overriden. virtual GURL OverrideFlashEmbedWithHTML(const GURL& url); - // Provides parameters for initializing the global thread pool. Default - // params are used if this returns nullptr. - virtual std::unique_ptr<base::ThreadPool::InitParams> - GetThreadPoolInitParams(); - // Whether the renderer allows idle media players to be automatically // suspended after a period of inactivity. virtual bool IsIdleMediaSuspendEnabled();
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc index 170b619..c645142d 100644 --- a/content/public/test/test_browser_thread_bundle.cc +++ b/content/public/test/test_browser_thread_bundle.cc
@@ -50,8 +50,7 @@ // The only way this check can fail after RunUntilIdle() is if a test is // running its own base::Thread's. Such tests should make sure to coalesce // independent threads before this point. - // TODO(crbug.com/938126): Enable this CHECK once flaky tests have been fixed. - // CHECK(MainThreadIsIdle()) << sequence_manager()->DescribeAllPendingTasks(); + CHECK(MainThreadIsIdle()) << sequence_manager()->DescribeAllPendingTasks(); BrowserTaskExecutor::ResetForTesting();
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc index 4ae9a95..38f08a8 100644 --- a/content/renderer/render_process_impl.cc +++ b/content/renderer/render_process_impl.cc
@@ -27,6 +27,7 @@ #include "base/memory/ptr_util.h" #include "base/system/sys_info.h" #include "base/task/thread_pool/initialization_util.h" +#include "base/task/thread_pool/thread_pool.h" #include "base/time/time.h" #include "content/common/thread_pool_util.h" #include "content/public/common/bindings_policy.h" @@ -62,18 +63,11 @@ } } -std::unique_ptr<base::ThreadPool::InitParams> GetDefaultThreadPoolInitParams() { - constexpr int kMaxNumThreadsInBackgroundPool = 2; +std::unique_ptr<base::ThreadPool::InitParams> GetThreadPoolInitParams() { constexpr int kMaxNumThreadsInForegroundPoolLowerBound = 3; - constexpr auto kSuggestedReclaimTime = base::TimeDelta::FromSeconds(30); - return std::make_unique<base::ThreadPool::InitParams>( - base::ThreadGroupParams(kMaxNumThreadsInBackgroundPool, - kSuggestedReclaimTime), - base::ThreadGroupParams( - std::max(kMaxNumThreadsInForegroundPoolLowerBound, - content::GetMinForegroundThreadsInRendererThreadPool()), - kSuggestedReclaimTime)); + std::max(kMaxNumThreadsInForegroundPoolLowerBound, + content::GetMinForegroundThreadsInRendererThreadPool())); } #if defined(DCHECK_IS_CONFIGURABLE) @@ -88,9 +82,8 @@ namespace content { -RenderProcessImpl::RenderProcessImpl( - std::unique_ptr<base::ThreadPool::InitParams> thread_pool_init_params) - : RenderProcess("Renderer", std::move(thread_pool_init_params)), +RenderProcessImpl::RenderProcessImpl() + : RenderProcess("Renderer", GetThreadPoolInitParams()), enabled_bindings_(0) { #if defined(DCHECK_IS_CONFIGURABLE) // Some official builds ship with DCHECKs compiled in. Failing DCHECKs then @@ -237,13 +230,7 @@ } std::unique_ptr<RenderProcess> RenderProcessImpl::Create() { - auto thread_pool_init_params = - content::GetContentClient()->renderer()->GetThreadPoolInitParams(); - if (!thread_pool_init_params) - thread_pool_init_params = GetDefaultThreadPoolInitParams(); - - return base::WrapUnique( - new RenderProcessImpl(std::move(thread_pool_init_params))); + return base::WrapUnique(new RenderProcessImpl()); } void RenderProcessImpl::AddBindings(int bindings) {
diff --git a/content/renderer/render_process_impl.h b/content/renderer/render_process_impl.h index f38863a47..b8f7295 100644 --- a/content/renderer/render_process_impl.h +++ b/content/renderer/render_process_impl.h
@@ -9,7 +9,6 @@ #include <vector> #include "base/macros.h" -#include "base/task/thread_pool/thread_pool.h" #include "content/renderer/render_process.h" namespace content { @@ -41,8 +40,7 @@ void ReleaseProcess() override; private: - RenderProcessImpl( - std::unique_ptr<base::ThreadPool::InitParams> thread_pool_init_params); + RenderProcessImpl(); // Bitwise-ORed set of extra bindings that have been enabled anywhere in this // process. See BindingsPolicy for details.
diff --git a/content/shell/browser/shell_views.cc b/content/shell/browser/shell_views.cc index b0314b8..eb4329b 100644 --- a/content/shell/browser/shell_views.cc +++ b/content/shell/browser/shell_views.cc
@@ -336,14 +336,7 @@ _setmode(_fileno(stderr), _O_BINARY); #endif #if defined(OS_CHROMEOS) - ui::ContextFactory* ui_context_factory = - aura::Env::GetInstance()->mode() == aura::Env::Mode::LOCAL - ? GetContextFactory() - : nullptr; - wm_test_helper_ = new wm::WMTestHelper( - default_window_size, - ServiceManagerConnection::GetForProcess()->GetConnector(), - ui_context_factory); + wm_test_helper_ = new wm::WMTestHelper(default_window_size); #else wm_state_ = new wm::WMState; views::InstallDesktopScreenIfNecessary();
diff --git a/docs/enterprise/policies.md b/docs/enterprise/policies.md new file mode 100644 index 0000000..cb06803d --- /dev/null +++ b/docs/enterprise/policies.md
@@ -0,0 +1,111 @@ +# Enterprise policies + +Under enterprise management organization admins can configure the way +ChromeOS device / browser operates using policies. + +On most operating systems policies are applied to specific users / all users +of the browser, but on ChromeOS there are also policies that control the device +itself. + +On all platforms cloud-based policies are fetched and applied when a managed +user signs in. + +[TOC] + +## Policy sources + +On different operating systems there can be different methods for enterprise +to propagate policies for all users (including non-managed ones): + +**Windows** Policies can be set up via Windows Registry ([GPO](https://en.wikipedia.org/wiki/Group_Policy)). + +**MacOS** Policies can be set via Mac preferences system. + +**Linux** Policies can be set via files in specific directories: + +Base directory is `/etc/chromium/policies` for Chromium builds, + `/etc/opt/chrome/policies/` for official Chrome builds. +Base directory contains two subdirectories: `managed/` for mandatory policies +and `recommended/` for recommended policies. All files inside these +directories are treated as JSON files containing +policies. + +On these systems it is also possible to set machine-wide cloud-based policies. + +** Chrome OS ** + +Chrome OS devices can be either cloud-managed or Active Directory managed +([AdManagement](https://support.google.com/chrome/a/answer/7497916?hl=en)). + +The cloud source is usually called DMServer (device management server). +Organization admins can configure both device and cloud policies using +https://admin.google.com. + +On an Active Directory managed device policies are set via GPO from the Active +Directory server. + +When Chrome OS is in development mode with writeable rootfs, it would also +apply use `Linux` policy mechanism, that can be handy for testing during +development. + +## Policy types (ChromeOS) + +There are two main types of policies on Chrome OS: User policies, that define +the browser behavior for a particular user, and Device policies, that control +the whole device. + +## Device policies + +Device policies are defined in the [chrome_device_policy proto file](https://cs.chromium.org/chromium/src/components/policy/proto/chrome_device_policy.proto). +They are also mentioned in the [policy templates file](https://cs.chromium.org/chromium/src/components/policy/resources/policy_templates.json) +with `'device_only': True` for documentation purposes. + +Device policies are applied to all users on the device (and even if no user +is signed in), even for guest sessions. Note that device policy can also limit +which users can sign in on the device. + +Implementation-wise, these policies can have complex structure, and are +usually accessed via +[DeviceSettingsProvider](https://cs.chromium.org/chromium/src/chrome/browser/chromeos/settings/device_settings_provider.h) +or it's wrapper [CrosSettings](https://cs.chromium.org/chromium/src/chrome/browser/chromeos/settings/cros_settings.h). + +## User policies + +User policies are defined in the [policy templates file](https://cs.chromium.org/chromium/src/components/policy/resources/policy_templates.json)ббб, +only entries without `'device_only': True` are user policies. + +User policies are bound to user accounts, so a personal account on +an enterprise-enrolled device would be affected only by device policy, while +an enterprise-owned account on personal device would only be affected by user +policy for that account. + +### ChromeOS +Chrome OS has some specific enterprise-only account types ([Kiosk, public +accounts](kiosk_public_session.md)) that are controlled via policies. Those +policies are usual user policies, though they have their own user ID namespace +when retrieved from DMServer. + +### Windows/MacOS/Linux +Chrome on these systems can be configured to receive machine-wide cloud-based +policy from DMServer. It is a user policy, but it would be applied to all +users. + +## Extension policies + +Organization admins can [configure particular extensions](http://dev.chromium.org/administrators/configuring-policy-for-extensions) +for the user. Such extensions have to define the schema of the configuration +in their manifest. + +When Chrome OS device is cloud-managed, there is a limit on policy size. +As such configuration can be relatively large, it is not provided as a part +of user policy. Instead, user policy would only include URL and hash signature +for external data, and browser would fetch that data, validate signature, +validate data against schema from extension manifest and provide the +extension with such configuration. + +The same approach is used for other large objects that can be set via +policies (e.g. background wallpapers or printer configuration). + +## Adding new policies + +See [adding new policies HowTo](http://dev.chromium.org/developers/how-tos/enterprise/adding-new-policies)
diff --git a/gpu/command_buffer/common/BUILD.gn b/gpu/command_buffer/common/BUILD.gn index 16b7de08..8988618 100644 --- a/gpu/command_buffer/common/BUILD.gn +++ b/gpu/command_buffer/common/BUILD.gn
@@ -106,7 +106,7 @@ configs += [ "//gpu:gpu_implementation" ] public_deps = [ - "//base/util/type-safety", + "//base/util/type_safety", "//mojo/public/cpp/system", "//ui/gfx:memory_buffer", "//ui/gfx/geometry",
diff --git a/gpu/command_buffer/common/command_buffer_id.h b/gpu/command_buffer/common/command_buffer_id.h index 26a2995..d3cacb2 100644 --- a/gpu/command_buffer/common/command_buffer_id.h +++ b/gpu/command_buffer/common/command_buffer_id.h
@@ -5,7 +5,7 @@ #ifndef GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_ID_H_ #define GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_ID_H_ -#include "base/util/type-safety/id_type.h" +#include "base/util/type_safety/id_type.h" namespace gpu {
diff --git a/gpu/command_buffer/common/discardable_handle.h b/gpu/command_buffer/common/discardable_handle.h index 33eda35..dbc1149 100644 --- a/gpu/command_buffer/common/discardable_handle.h +++ b/gpu/command_buffer/common/discardable_handle.h
@@ -6,7 +6,7 @@ #define GPU_COMMAND_BUFFER_COMMON_DISCARDABLE_HANDLE_H_ #include "base/memory/ref_counted.h" -#include "base/util/type-safety/id_type.h" +#include "base/util/type_safety/id_type.h" #include "gpu/gpu_export.h" namespace gpu {
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 1bf32ca..5a84425 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn
@@ -79,7 +79,7 @@ ] public_deps = [ - "//base/util/type-safety", + "//base/util/type_safety", "//gpu/command_buffer/common:common_sources", "//url:url", ] @@ -283,7 +283,7 @@ include_dirs = [ "//third_party/mesa_headers" ] public_deps = [ - "//base/util/type-safety", + "//base/util/type_safety", "//cc/paint", "//gpu/command_buffer/common", "//gpu/command_buffer/common:gles2_sources",
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index ed29f683..bc72d26 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -28,7 +28,6 @@ #include "base/containers/span.h" #include "base/debug/alias.h" #include "base/debug/dump_without_crashing.h" -#include "base/hash/hash.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/ranges.h" @@ -88,6 +87,7 @@ #include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "gpu/config/gpu_preferences.h" #include "third_party/angle/src/image_util/loadimage.h" +#include "third_party/smhasher/src/City.h" #include "ui/gfx/buffer_types.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/point.h" @@ -4449,10 +4449,7 @@ if (((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) && features().enable_shader_name_hashing) || force_shader_name_hashing_for_test) - resources.HashFunction = [](const char* data, size_t length) { - return static_cast<uint64_t>( - base::FastHash(base::as_bytes(base::make_span(data, length)))); - }; + resources.HashFunction = &CityHash64; else resources.HashFunction = nullptr;
diff --git a/gpu/command_buffer/service/sequence_id.h b/gpu/command_buffer/service/sequence_id.h index 7f8db99..e79ffc0 100644 --- a/gpu/command_buffer/service/sequence_id.h +++ b/gpu/command_buffer/service/sequence_id.h
@@ -5,7 +5,7 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_SEQUENCE_ID_H_ #define GPU_COMMAND_BUFFER_SERVICE_SEQUENCE_ID_H_ -#include "base/util/type-safety/id_type.h" +#include "base/util/type_safety/id_type.h" namespace gpu {
diff --git a/ios/chrome/app/DEPS b/ios/chrome/app/DEPS index b6395fae..90ebb2b4 100644 --- a/ios/chrome/app/DEPS +++ b/ios/chrome/app/DEPS
@@ -19,7 +19,6 @@ "+components/search_engines", "+components/suggestions", "+components/sync/driver", - "+components/thread_pool_util", "+components/ukm/ios", "+components/unified_consent", "+components/url_formatter",
diff --git a/ios/chrome/app/startup/BUILD.gn b/ios/chrome/app/startup/BUILD.gn index 1cc6af39..2add34f 100644 --- a/ios/chrome/app/startup/BUILD.gn +++ b/ios/chrome/app/startup/BUILD.gn
@@ -24,7 +24,6 @@ deps = [ "//base", "//components/crash/core/common", - "//components/thread_pool_util", "//ios/chrome/browser:chrome_paths", "//ios/web/public/app", "//skia",
diff --git a/ios/chrome/app/startup/ios_chrome_main.mm b/ios/chrome/app/startup/ios_chrome_main.mm index 4a1ce3b..382c2ee 100644 --- a/ios/chrome/app/startup/ios_chrome_main.mm +++ b/ios/chrome/app/startup/ios_chrome_main.mm
@@ -8,12 +8,10 @@ #include <vector> -#include "base/bind.h" #include "base/logging.h" #include "base/strings/string_piece.h" #include "base/strings/sys_string_conversions.h" #include "base/time/time.h" -#include "components/thread_pool_util/variations_util.h" #include "ios/web/public/app/web_main_runner.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -46,8 +44,6 @@ } main_params.argv = argv; - main_params.get_thread_pool_init_params_callback = - base::BindOnce(&thread_pool_util::GetThreadPoolInitParamsForBrowser); // Chrome registers an AtExitManager in main in order to initialize breakpad // early, so prevent a second registration by WebMainRunner. main_params.register_exit_manager = false;
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index dac510ce..bc6d99d 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -88,7 +88,6 @@ "+components/sync_preferences", "+components/sync_sessions", "+components/sync_user_events", - "+components/thread_pool_util", "+components/translate", "+components/ui_metrics", "+components/ukm",
diff --git a/ios/chrome/browser/find_in_page/find_in_page_controller.mm b/ios/chrome/browser/find_in_page/find_in_page_controller.mm index 68d1030..6d111a3 100644 --- a/ios/chrome/browser/find_in_page/find_in_page_controller.mm +++ b/ios/chrome/browser/find_in_page/find_in_page_controller.mm
@@ -223,6 +223,9 @@ // Keep track of whether a find is in progress so to avoid running // JavaScript during disable if unnecessary. _findStringStarted = YES; + // Save the query in the model before searching. TODO:(crbug.com/963908): + // Remove as part of refactoring. + [self.findInPageModel updateQuery:query matches:0]; _findInPageManager->Find(query, web::FindInPageOptions::FindInPageSearch); return; }
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc index 761dd90..90342e1 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -11,13 +11,11 @@ namespace flag_descriptions { -const char kEnableAutocompleteDataRetentionPolicyName[] = - "Enable automatic cleanup of expired Autocomplete entries."; -const char kEnableAutocompleteDataRetentionPolicyDescription[] = - "If enabled, will clean-up Autocomplete entries whose last use date is " - "older than the current retention policy. These entries will be " - "permanently deleted from the client on startup, and will be unlinked " - "from sync."; +const char kAppLauncherRefreshName[] = "Enable the new AppLauncher logic"; +const char kAppLauncherRefreshDescription[] = + "AppLauncher will always prompt if there is no direct link navigation, " + "also Apps will launch asynchronously and there will be no logic that" + "depends on the success or the failure of launching an app."; const char kAutofillCacheQueryResponsesName[] = "Cache Autofill Query Responses"; @@ -25,11 +23,6 @@ "When enabled, autofill will cache the responses it receives from the " "crowd-sourced field type prediction server."; -const char kAutofillEnableCompanyNameName[] = - "Enable Autofill Company Name field"; -const char kAutofillEnableCompanyNameDescription[] = - "When enabled, Company Name fields will be auto filled"; - const char kAutofillCreditCardUploadName[] = "Offers uploading Autofilled credit cards"; const char kAutofillCreditCardUploadDescription[] = @@ -42,10 +35,78 @@ "When enabled, shows the Google Pay logo animation when showing payments" "credit card suggestions in downstream keyboard accessory"; +const char kAutofillEnableCompanyNameName[] = + "Enable Autofill Company Name field"; +const char kAutofillEnableCompanyNameDescription[] = + "When enabled, Company Name fields will be auto filled"; + +const char kAutofillEnforceMinRequiredFieldsForHeuristicsName[] = + "Autofill Enforce Min Required Fields For Heuristics"; +const char kAutofillEnforceMinRequiredFieldsForHeuristicsDescription[] = + "When enabled, autofill will generally require a form to have at least 3 " + "fields before allowing heuristic field-type prediction to occur."; + +const char kAutofillEnforceMinRequiredFieldsForQueryName[] = + "Autofill Enforce Min Required Fields For Query"; +const char kAutofillEnforceMinRequiredFieldsForQueryDescription[] = + "When enabled, autofill will generally require a form to have at least 3 " + "fields before querying the autofill server for field-type predictions."; + +const char kAutofillEnforceMinRequiredFieldsForUploadName[] = + "Autofill Enforce Min Required Fields For Upload"; +const char kAutofillEnforceMinRequiredFieldsForUploadDescription[] = + "When enabled, autofill will generally require a form to have at least 3 " + "fillable fields before uploading field-type votes for that form."; + +const char kAutofillIOSDelayBetweenFieldsName[] = "Autofill delay"; +const char kAutofillIOSDelayBetweenFieldsDescription[] = + "Delay between the different fields of a form being autofilled. In " + "milliseconds."; + +const char kAutofillManualFallbackName[] = "Enable Autofill Manual Fallback"; +const char kAutofillManualFallbackDescription[] = + "When enabled, it shows the autofill UI with manual fallback when filling " + "forms."; + +const char kAutofillManualFallbackPhaseTwoName[] = "Enable Addresses and Cards"; +const char kAutofillManualFallbackPhaseTwoDescription[] = + "When enabled, it shows the credit cards and addresses buttons in manual " + "fallback."; + +const char kAutofillNoLocalSaveOnUnmaskSuccessName[] = + "Remove the option to save local copies of unmasked server cards"; +const char kAutofillNoLocalSaveOnUnmaskSuccessDescription[] = + "When enabled, the server card unmask prompt will not include the checkbox " + "to also save the card locally on the current device upon success."; + +const char kAutofillNoLocalSaveOnUploadSuccessName[] = + "Disable saving local copy of uploaded card when credit card upload " + "succeeds"; +const char kAutofillNoLocalSaveOnUploadSuccessDescription[] = + "When enabled, no local copy of server card will be saved when credit card " + "upload succeeds."; + const char kAutofillPruneSuggestionsName[] = "Autofill Prune Suggestions"; const char kAutofillPruneSuggestionsDescription[] = "Further limits the number of suggestions in the Autofill dropdown."; +const char kAutofillShowAllSuggestionsOnPrefilledFormsName[] = + "Enable showing all suggestions when focusing prefilled field"; +const char kAutofillShowAllSuggestionsOnPrefilledFormsDescription[] = + "When enabled: show all suggestions when the focused field value has not " + "been entered by the user. When disabled: use the field value as a filter."; + +const char kAutofillRestrictUnownedFieldsToFormlessCheckoutName[] = + "Restrict formless form extraction"; +const char kAutofillRestrictUnownedFieldsToFormlessCheckoutDescription[] = + "Restrict extraction of formless forms to checkout flows"; + +const char kAutofillRichMetadataQueriesName[] = + "Autofill - Rich metadata queries (Canary/Dev only)"; +const char kAutofillRichMetadataQueriesDescription[] = + "Transmit rich form/field metadata when querying the autofill server. " + "This feature only works on the Canary and Dev channels."; + const char kAutofillUseMobileLabelDisambiguationName[] = "Autofill Uses Mobile Label Disambiguation"; const char kAutofillUseMobileLabelDisambiguationDescription[] = @@ -59,12 +120,38 @@ "disabled, initial upload is delayed until deferred initialization. This " "does not affect recovery mode."; +const char kBrowserContainerKeepsContentViewName[] = + "Browser Container retains the content view"; +const char kBrowserContainerKeepsContentViewDescription[] = + "When enable, the browser container keeps the content view in the view " + "hierarchy, to avoid WKWebView from being unloaded from the process."; + +const char kBrowserTaskScheduler[] = "Task Scheduler"; +const char kBrowserTaskSchedulerDescription[] = + "Enables redirection of some task posting APIs to the task scheduler."; + +// TODO(crbug.com/893314) : Remove this flag. +const char kClosingLastIncognitoTabName[] = "Closing Last Incognito Tab"; +const char kClosingLastIncognitoTabDescription[] = + "Automatically switches to the regular tabs panel in the tab grid after " + "closing the last incognito tab"; + const char kCompactTranslateInfobarName[] = "Enable the compact translate infobar"; const char kCompactTranslateInfobarDescription[] = "When enabled, replaces the exisitng translate infobars with a new compact " "one."; +const char kContextualSearch[] = "Contextual Search"; +const char kContextualSearchDescription[] = + "Whether or not Contextual Search is enabled."; + +const char kCopiedContentBehaviorName[] = + "Enable differentiating between copied urls, text, and images"; +const char kCopiedContentBehaviorDescription[] = + "When enabled, places that handled copied urls (omnibox long-press, toolbar" + "menus) will differentiate between copied urls, text, and images."; + #if defined(DCHECK_IS_CONFIGURABLE) const char kDcheckIsFatalName[] = "DCHECKs are fatal"; const char kDcheckIsFatalDescription[] = @@ -72,6 +159,27 @@ "rather than crashing. If enabled, DCHECKs will crash the calling process."; #endif // defined(DCHECK_IS_CONFIGURABLE) +const char kDetectMainThreadFreezeName[] = "Detect freeze in the main thread."; +const char kDetectMainThreadFreezeDescription[] = + "A crash report will be uploaded if the main thread is frozen more than " + "the time specified by this flag."; + +const char kDisplaySearchEngineFaviconName[] = + "Display search engine favicons."; +const char kDisplaySearchEngineFaviconDescription[] = + "When enabled, Settings will display search engine favicons"; + +const char kDragAndDropName[] = "Drag and Drop"; +const char kDragAndDropDescription[] = "Enable support for drag and drop."; + +const char kEnableAutocompleteDataRetentionPolicyName[] = + "Enable automatic cleanup of expired Autocomplete entries."; +const char kEnableAutocompleteDataRetentionPolicyDescription[] = + "If enabled, will clean-up Autocomplete entries whose last use date is " + "older than the current retention policy. These entries will be " + "permanently deleted from the client on startup, and will be unlinked " + "from sync."; + const char kEnableAutofillCreditCardUploadUpdatePromptExplanationName[] = "Enable updated prompt explanation when offering credit card upload"; const char kEnableAutofillCreditCardUploadUpdatePromptExplanationDescription[] = @@ -98,66 +206,6 @@ "popping up the credit card offer-to-save prompt if it has repeatedly been" "ignored, declined, or failed."; -const char kEnableSyncUSSBookmarksName[] = "Enable USS for bookmarks sync"; -const char kEnableSyncUSSBookmarksDescription[] = - "Enables the new, experimental implementation of bookmark sync"; - -const char kEnableSyncUSSPasswordsName[] = "Enable USS for passwords sync"; -const char kEnableSyncUSSPasswordsDescription[] = - "Enables the new, experimental implementation of password sync"; - -const char kSyncSandboxName[] = "Use Chrome Sync sandbox"; -const char kSyncSandboxDescription[] = - "Connects to the testing server for Chrome Sync."; - -const char kSyncSupportSecondaryAccountName[] = - "Support secondary accounts for Sync standalone transport"; -const char kSyncSupportSecondaryAccountDescription[] = - "If enabled, allows Chrome Sync to start in standalone transport mode for " - "a signed-in account that has not been chosen as Chrome's primary account. " - "This only has an effect if sync-standalone-transport is also enabled."; - -const char kWalletServiceUseSandboxName[] = "Use Google Payments sandbox"; -const char kWalletServiceUseSandboxDescription[] = - "Uses the sandbox service for Google Payments API calls."; - -const char kAppLauncherRefreshName[] = "Enable the new AppLauncher logic"; -const char kAppLauncherRefreshDescription[] = - "AppLauncher will always prompt if there is no direct link navigation, " - "also Apps will launch asynchronously and there will be no logic that" - "depends on the success or the failure of launching an app."; - -const char kAutofillNoLocalSaveOnUnmaskSuccessName[] = - "Remove the option to save local copies of unmasked server cards"; -const char kAutofillNoLocalSaveOnUnmaskSuccessDescription[] = - "When enabled, the server card unmask prompt will not include the checkbox " - "to also save the card locally on the current device upon success."; - -const char kAutofillNoLocalSaveOnUploadSuccessName[] = - "Disable saving local copy of uploaded card when credit card upload " - "succeeds"; -const char kAutofillNoLocalSaveOnUploadSuccessDescription[] = - "When enabled, no local copy of server card will be saved when credit card " - "upload succeeds."; - -const char kAutofillEnforceMinRequiredFieldsForHeuristicsName[] = - "Autofill Enforce Min Required Fields For Heuristics"; -const char kAutofillEnforceMinRequiredFieldsForHeuristicsDescription[] = - "When enabled, autofill will generally require a form to have at least 3 " - "fields before allowing heuristic field-type prediction to occur."; - -const char kAutofillEnforceMinRequiredFieldsForQueryName[] = - "Autofill Enforce Min Required Fields For Query"; -const char kAutofillEnforceMinRequiredFieldsForQueryDescription[] = - "When enabled, autofill will generally require a form to have at least 3 " - "fields before querying the autofill server for field-type predictions."; - -const char kAutofillEnforceMinRequiredFieldsForUploadName[] = - "Autofill Enforce Min Required Fields For Upload"; -const char kAutofillEnforceMinRequiredFieldsForUploadDescription[] = - "When enabled, autofill will generally require a form to have at least 3 " - "fillable fields before uploading field-type votes for that form."; - const char kEnableAutofillImportDynamicFormsName[] = "Allow credit card import from dynamic forms after entry"; const char kEnableAutofillImportDynamicFormsDescription[] = @@ -171,90 +219,23 @@ "page after information has been entered into them, including " "accordion-style checkout flows."; -const char kAutofillIOSDelayBetweenFieldsName[] = "Autofill delay"; -const char kAutofillIOSDelayBetweenFieldsDescription[] = - "Delay between the different fields of a form being autofilled. In " - "milliseconds."; - -const char kAutofillManualFallbackName[] = "Enable Autofill Manual Fallback"; -const char kAutofillManualFallbackDescription[] = - "When enabled, it shows the autofill UI with manual fallback when filling " - "forms."; - -const char kAutofillManualFallbackPhaseTwoName[] = "Enable Addresses and Cards"; -const char kAutofillManualFallbackPhaseTwoDescription[] = - "When enabled, it shows the credit cards and addresses buttons in manual " - "fallback."; - -const char kAutofillShowAllSuggestionsOnPrefilledFormsName[] = - "Enable showing all suggestions when focusing prefilled field"; -const char kAutofillShowAllSuggestionsOnPrefilledFormsDescription[] = - "When enabled: show all suggestions when the focused field value has not " - "been entered by the user. When disabled: use the field value as a filter."; - -const char kAutofillRestrictUnownedFieldsToFormlessCheckoutName[] = - "Restrict formless form extraction"; -const char kAutofillRestrictUnownedFieldsToFormlessCheckoutDescription[] = - "Restrict extraction of formless forms to checkout flows"; - -const char kAutofillRichMetadataQueriesName[] = - "Autofill - Rich metadata queries (Canary/Dev only)"; -const char kAutofillRichMetadataQueriesDescription[] = - "Transmit rich form/field metadata when querying the autofill server. " - "This feature only works on the Canary and Dev channels."; - -const char kBrowserContainerKeepsContentViewName[] = - "Browser Container retains the content view"; -const char kBrowserContainerKeepsContentViewDescription[] = - "When enable, the browser container keeps the content view in the view " - "hierarchy, to avoid WKWebView from being unloaded from the process."; - -const char kBrowserTaskScheduler[] = "Task Scheduler"; -const char kBrowserTaskSchedulerDescription[] = - "Enables redirection of some task posting APIs to the task scheduler."; - -// TODO(crbug.com/893314) : Remove this flag. -const char kClosingLastIncognitoTabName[] = "Closing Last Incognito Tab"; -const char kClosingLastIncognitoTabDescription[] = - "Automatically switches to the regular tabs panel in the tab grid after " - "closing the last incognito tab"; - -const char kContextualSearch[] = "Contextual Search"; -const char kContextualSearchDescription[] = - "Whether or not Contextual Search is enabled."; - -const char kCopiedContentBehaviorName[] = - "Enable differentiating between copied urls, text, and images"; -const char kCopiedContentBehaviorDescription[] = - "When enabled, places that handled copied urls (omnibox long-press, toolbar" - "menus) will differentiate between copied urls, text, and images."; - -const char kDetectMainThreadFreezeName[] = "Detect freeze in the main thread."; -const char kDetectMainThreadFreezeDescription[] = - "A crash report will be uploaded if the main thread is frozen more than " - "the time specified by this flag."; - -const char kDisplaySearchEngineFaviconName[] = - "Display search engine favicons."; -const char kDisplaySearchEngineFaviconDescription[] = - "When enabled, Settings will display search engine favicons"; - -const char kDragAndDropName[] = "Drag and Drop"; -const char kDragAndDropDescription[] = "Enable support for drag and drop."; - -const char kNewClearBrowsingDataUIName[] = "Clear Browsing Data UI"; -const char kNewClearBrowsingDataUIDescription[] = - "Enable new Clear Browsing Data UI."; +const char kEnableClipboardProviderImageSuggestionsName[] = + "Enable copied image provider"; +const char kEnableClipboardProviderImageSuggestionsDescription[] = + "Enable suggesting a search for the image copied to the clipboard"; const char kEnableClipboardProviderTextSuggestionsName[] = "Enable copied text provider"; const char kEnableClipboardProviderTextSuggestionsDescription[] = "Enable suggesting a search for text copied to the clipboard"; -const char kEnableClipboardProviderImageSuggestionsName[] = - "Enable copied image provider"; -const char kEnableClipboardProviderImageSuggestionsDescription[] = - "Enable suggesting a search for the image copied to the clipboard"; +const char kEnableSyncUSSBookmarksName[] = "Enable USS for bookmarks sync"; +const char kEnableSyncUSSBookmarksDescription[] = + "Enables the new, experimental implementation of bookmark sync"; + +const char kEnableSyncUSSPasswordsName[] = "Enable USS for passwords sync"; +const char kEnableSyncUSSPasswordsDescription[] = + "Enables the new, experimental implementation of password sync"; const char kFCMInvalidationsName[] = "Enable invalidations delivery via new FCM based protocol"; @@ -267,6 +248,10 @@ "Filling of passwords when an account is explicitly selected by the user " "rather than autofilling credentials on page load on HTTP origins."; +const char kFindInPageiFrameName[] = "Find in Page in iFrames."; +const char kFindInPageiFrameDescription[] = + "When enabled, Find In Page will search in iFrames."; + const char kFullscreenViewportAdjustmentExperimentName[] = "Fullscreen Viewport Adjustment Mode"; const char kFullscreenViewportAdjustmentExperimentDescription[] = @@ -282,6 +267,10 @@ const char kIdentityDiscDescription[] = "Enables Identity Disc, profile avatar icon button in toolbar."; +const char kIgnoresViewportScaleLimitsName[] = "Ignore Viewport Scale Limits"; +const char kIgnoresViewportScaleLimitsDescription[] = + "When enabled the page can always be scaled, regardless of author intent."; + const char kInfobarUIRebootName[] = "Infobar UI Reboot"; const char kInfobarUIRebootDescription[] = "When enabled, Infobar will use the new UI."; @@ -306,6 +295,15 @@ const char kMarkHttpAsName[] = "Mark non-secure origins as non-secure"; const char kMarkHttpAsDescription[] = "Change the UI treatment for HTTP pages"; +const char kNewClearBrowsingDataUIName[] = "Clear Browsing Data UI"; +const char kNewClearBrowsingDataUIDescription[] = + "Enable new Clear Browsing Data UI."; + +const char kNewOmniboxPopupLayoutName[] = "New omnibox popup"; +const char kNewOmniboxPopupLayoutDescription[] = + "Switches the omnibox suggestions and omnibox itself to display the new " + "design with favicons, new suggestion layout, rich entity support."; + const char kNewPasswordFormParsingName[] = "New password form parsing"; const char kNewPasswordFormParsingDescription[] = "Replaces existing form parsing in password manager with a new version, " @@ -319,16 +317,6 @@ "version, currently under development. WARNING: when enabled, Password " "Manager might stop working"; -const char kNewOmniboxPopupLayoutName[] = "New omnibox popup"; -const char kNewOmniboxPopupLayoutDescription[] = - "Switches the omnibox suggestions and omnibox itself to display the new " - "design with favicons, new suggestion layout, rich entity support."; - -const char kOmniboxUseDefaultSearchEngineFaviconName[] = - "Default search engine favicon in the omnibox"; -const char kOmniboxUseDefaultSearchEngineFaviconDescription[] = - "Shows default search engine favicon in the omnibox"; - const char kNonModalDialogsName[] = "Use non-modal JavaScript dialogs"; const char kNonModalDialogsDescription[] = "Presents JavaScript dialogs non-modally so that the user can change tabs " @@ -346,11 +334,10 @@ "Instead of ZeroSuggest, show most visited sites and collection shortcuts " "in the omnibox popup."; -const char kOmniboxUIMaxAutocompleteMatchesName[] = - "Omnibox UI Max Autocomplete Matches"; -const char kOmniboxUIMaxAutocompleteMatchesDescription[] = - "Changes the maximum number of autocomplete matches displayed in the " - "Omnibox UI."; +const char kOmniboxTabSwitchSuggestionsName[] = + "Enable 'switch to this tab' option"; +const char kOmniboxTabSwitchSuggestionsDescription[] = + "Enable the 'switch to this tab' options in the omnibox suggestions."; const char kOmniboxUIElideSuggestionUrlAfterHostName[] = "Hide the path, query, and ref of omnibox suggestions"; @@ -358,6 +345,17 @@ "Elides the path, query, and ref of suggested URLs in the omnibox " "dropdown."; +const char kOmniboxUIMaxAutocompleteMatchesName[] = + "Omnibox UI Max Autocomplete Matches"; +const char kOmniboxUIMaxAutocompleteMatchesDescription[] = + "Changes the maximum number of autocomplete matches displayed in the " + "Omnibox UI."; + +const char kOmniboxUseDefaultSearchEngineFaviconName[] = + "Default search engine favicon in the omnibox"; +const char kOmniboxUseDefaultSearchEngineFaviconDescription[] = + "Shows default search engine favicon in the omnibox"; + const char kOnlyNewPasswordFormParsingName[] = "Use only new password form parsing"; const char kOnlyNewPasswordFormParsingDescription[] = @@ -372,10 +370,6 @@ "When enabled, the omnibox will include suggestions for web pages " "broadcast by devices near you."; -const char kIgnoresViewportScaleLimitsName[] = "Ignore Viewport Scale Limits"; -const char kIgnoresViewportScaleLimitsDescription[] = - "When enabled the page can always be scaled, regardless of author intent."; - const char kSearchIconToggleName[] = "Change the icon for the search button"; const char kSearchIconToggleDescription[] = "Different icons for the search button."; @@ -413,25 +407,44 @@ "Change the UI appearance of the settings to have something in phase with " "UI Refresh."; -const char kSlimNavigationManagerName[] = "Use Slim Navigation Manager"; -const char kSlimNavigationManagerDescription[] = - "When enabled, uses the experimental slim navigation manager that provides " - "better compatibility with HTML navigation spec."; - const char kShowAutofillTypePredictionsName[] = "Show Autofill predictions"; const char kShowAutofillTypePredictionsDescription[] = "Annotates web forms with Autofill field type predictions as placeholder " "text."; -const char kToolbarContainerName[] = "Use Toolbar Containers"; -const char kToolbarContainerDescription[] = - "When enabled, the toolbars and their fullscreen animations will be " - "managed by the toolbar container coordinator rather than BVC."; +const char kSlimNavigationManagerName[] = "Use Slim Navigation Manager"; +const char kSlimNavigationManagerDescription[] = + "When enabled, uses the experimental slim navigation manager that provides " + "better compatibility with HTML navigation spec."; const char kSnapshotDrawViewName[] = "Use DrawViewHierarchy for Snapshots"; const char kSnapshotDrawViewDescription[] = "When enabled, snapshots will be taken using |-drawViewHierarchy:|."; +const char kStorePendingItemInContextName[] = + "Store pending item in NavigationContext"; +const char kStorePendingItemInContextDescription[] = + "When enabled pending item will be stored in NavigationContext after " + "context is created. The item is still stored in NavigationManager if the " + "navigated was requested, but context does not yet exist or when " + "navigation was aborted."; + +const char kSyncSandboxName[] = "Use Chrome Sync sandbox"; +const char kSyncSandboxDescription[] = + "Connects to the testing server for Chrome Sync."; + +const char kSyncSupportSecondaryAccountName[] = + "Support secondary accounts for Sync standalone transport"; +const char kSyncSupportSecondaryAccountDescription[] = + "If enabled, allows Chrome Sync to start in standalone transport mode for " + "a signed-in account that has not been chosen as Chrome's primary account. " + "This only has an effect if sync-standalone-transport is also enabled."; + +const char kToolbarContainerName[] = "Use Toolbar Containers"; +const char kToolbarContainerDescription[] = + "When enabled, the toolbars and their fullscreen animations will be " + "managed by the toolbar container coordinator rather than BVC."; + const char kTranslateManualTriggerName[] = "Enable manual translate trigger"; const char kTranslateManualTriggerDescription[] = "Show a menu item in the popup menu that triggers page translation."; @@ -442,6 +455,10 @@ "features. This includes new confirmation screens and improved settings " "pages."; +const char kUseDdljsonApiName[] = "Use new ddljson API for Doodles"; +const char kUseDdljsonApiDescription[] = + "Enables the new ddljson API to fetch Doodles for the NTP."; + const char kUseMultiloginEndpointName[] = "Use Multilogin endpoint."; const char kUseMultiloginEndpointDescription[] = "Use Gaia OAuth multilogin for identity consistency."; @@ -451,22 +468,14 @@ const char kUseNSURLSessionForGaiaSigninRequestsDescription[] = "Use NSURLSession to make sign-in requests to Gaia"; -const char kUseDdljsonApiName[] = "Use new ddljson API for Doodles"; -const char kUseDdljsonApiDescription[] = - "Enables the new ddljson API to fetch Doodles for the NTP."; +const char kWalletServiceUseSandboxName[] = "Use Google Payments sandbox"; +const char kWalletServiceUseSandboxDescription[] = + "Uses the sandbox service for Google Payments API calls."; const char kWebClearBrowsingDataName[] = "Web-API for browsing data"; const char kWebClearBrowsingDataDescription[] = "When enabled the Clear Browsing Data feature is using the web API."; -const char kStorePendingItemInContextName[] = - "Store pending item in NavigationContext"; -const char kStorePendingItemInContextDescription[] = - "When enabled pending item will be stored in NavigationContext after " - "context is created. The item is still stored in NavigationManager if the " - "navigated was requested, but context does not yet exist or when " - "navigation was aborted."; - const char kWebPageTextAccessibilityName[] = "Enable text accessibility in web pages"; const char kWebPageTextAccessibilityDescription[] = @@ -477,10 +486,6 @@ const char kWKHTTPSystemCookieStoreDescription[] = "Use WKHTTPCookieStore backed store for main context URL requests."; -const char kFindInPageiFrameName[] = "Find in Page in iFrames."; -const char kFindInPageiFrameDescription[] = - "When enabled, Find In Page will search in iFrames."; - // Please insert your name/description above in alphabetical order. } // namespace flag_descriptions
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h index cb5ed9b..4a4cae7 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -5,21 +5,18 @@ #ifndef IOS_CHROME_BROWSER_IOS_CHROME_FLAG_DESCRIPTIONS_H_ #define IOS_CHROME_BROWSER_IOS_CHROME_FLAG_DESCRIPTIONS_H_ +// Please add names and descriptions in alphabetical order. + namespace flag_descriptions { -// Title and description for the flag to control the autocomplete retention -// policy. -extern const char kEnableAutocompleteDataRetentionPolicyName[]; -extern const char kEnableAutocompleteDataRetentionPolicyDescription[]; +// Title and description for the flag to control the new app launcher. +extern const char kAppLauncherRefreshName[]; +extern const char kAppLauncherRefreshDescription[]; // Title and description for the flag to control the autofill query cache. extern const char kAutofillCacheQueryResponsesName[]; extern const char kAutofillCacheQueryResponsesDescription[]; -// Title and description for the flag to control deprecating company name. -extern const char kAutofillEnableCompanyNameName[]; -extern const char kAutofillEnableCompanyNameDescription[]; - // Title and description for the flag to control upstreaming credit cards. extern const char kAutofillCreditCardUploadName[]; extern const char kAutofillCreditCardUploadDescription[]; @@ -29,11 +26,60 @@ extern const char kAutofillDownstreamUseGooglePayBrandingOniOSName[]; extern const char kAutofillDownstreamUseGooglePayBrandingOniOSDescription[]; +// Title and description for the flag to control deprecating company name. +extern const char kAutofillEnableCompanyNameName[]; +extern const char kAutofillEnableCompanyNameDescription[]; + +// Enforcing restrictions to enable/disable autofill small form support. +extern const char kAutofillEnforceMinRequiredFieldsForHeuristicsName[]; +extern const char kAutofillEnforceMinRequiredFieldsForHeuristicsDescription[]; +extern const char kAutofillEnforceMinRequiredFieldsForQueryName[]; +extern const char kAutofillEnforceMinRequiredFieldsForQueryDescription[]; +extern const char kAutofillEnforceMinRequiredFieldsForUploadName[]; +extern const char kAutofillEnforceMinRequiredFieldsForUploadDescription[]; + +// Title and description for the flag to control the autofill delay. +extern const char kAutofillIOSDelayBetweenFieldsName[]; +extern const char kAutofillIOSDelayBetweenFieldsDescription[]; + +// Title and description for the flag to control if manual fallback is enabled. +extern const char kAutofillManualFallbackName[]; +extern const char kAutofillManualFallbackDescription[]; + +// Title and description for the flag to control if manual fallback is enabled. +extern const char kAutofillManualFallbackPhaseTwoName[]; +extern const char kAutofillManualFallbackPhaseTwoDescription[]; + +// Title and description for the flag to control offering to save unmasked +// server cards locally as FULL_SERVER_CARDs upon success of credit card unmask. +extern const char kAutofillNoLocalSaveOnUnmaskSuccessName[]; +extern const char kAutofillNoLocalSaveOnUnmaskSuccessDescription[]; + +// Title and description for the flag to control saving FULL_SERVER_CARDS upon +// success of credit card upload. +extern const char kAutofillNoLocalSaveOnUploadSuccessName[]; +extern const char kAutofillNoLocalSaveOnUploadSuccessDescription[]; + // Title and description for the flag that controls whether the maximum number -// of Autofill suggestions shown to the user is further limited. +// of Autofill suggestions shown is pruned. extern const char kAutofillPruneSuggestionsName[]; extern const char kAutofillPruneSuggestionsDescription[]; +// Title and description for the flag to control if prefilled value filter +// profiles. +extern const char kAutofillShowAllSuggestionsOnPrefilledFormsName[]; +extern const char kAutofillShowAllSuggestionsOnPrefilledFormsDescription[]; + +// Title and description for the flag to restrict extraction of formless forms +// to checkout flows. +extern const char kAutofillRestrictUnownedFieldsToFormlessCheckoutName[]; +extern const char kAutofillRestrictUnownedFieldsToFormlessCheckoutDescription[]; + +// Title and description for the flag to enable rich autofill queries on +// Canary/Dev. +extern const char kAutofillRichMetadataQueriesName[]; +extern const char kAutofillRichMetadataQueriesDescription[]; + // Title and description for the flag that controls whether Autofill's // suggestions' labels are formatting with a mobile-friendly approach. extern const char kAutofillUseMobileLabelDisambiguationName[]; @@ -44,10 +90,34 @@ extern const char kBreakpadNoDelayInitialUploadName[]; extern const char kBreakpadNoDelayInitialUploadDescription[]; +// Title and description for the flag to make browser container keep the +// content view hierarchy directly. +extern const char kBrowserContainerKeepsContentViewName[]; +extern const char kBrowserContainerKeepsContentViewDescription[]; + +// Title and description for the flag to control redirection to the task +// scheduler. +extern const char kBrowserTaskScheduler[]; +extern const char kBrowserTaskSchedulerDescription[]; + +// Title and description for the flag to enable automatically switching to the +// regular tabs after closing the last incognito tab. +extern const char kClosingLastIncognitoTabName[]; +extern const char kClosingLastIncognitoTabDescription[]; + // Title and description for the flag to enable the compact translate infobar. extern const char kCompactTranslateInfobarName[]; extern const char kCompactTranslateInfobarDescription[]; +// Title and description for the flag to enable Contextual Search. +extern const char kContextualSearch[]; +extern const char kContextualSearchDescription[]; + +// Title and description for the flag to diffentiate between copied +// urls, strings, and images. +extern const char kCopiedContentBehaviorName[]; +extern const char kCopiedContentBehaviorDescription[]; + #if defined(DCHECK_IS_CONFIGURABLE) // Title and description for the flag to enable configurable DCHECKs. extern const char kDcheckIsFatalName[]; @@ -59,6 +129,20 @@ extern const char kDetectMainThreadFreezeName[]; extern const char kDetectMainThreadFreezeDescription[]; +// Title and description for the flag to enable displaying search engine +// favicons in Settings. +extern const char kDisplaySearchEngineFaviconName[]; +extern const char kDisplaySearchEngineFaviconDescription[]; + +// Title and description for the flag to enable drag and drop. +extern const char kDragAndDropName[]; +extern const char kDragAndDropDescription[]; + +// Title and description for the flag to control the autocomplete retention +// policy. +extern const char kEnableAutocompleteDataRetentionPolicyName[]; +extern const char kEnableAutocompleteDataRetentionPolicyDescription[]; + // Title and description for the flag to control the updated prompt explanation // when offering credit card upload. extern const char kEnableAutofillCreditCardUploadUpdatePromptExplanationName[]; @@ -82,49 +166,6 @@ extern const char kEnableAutofillSaveCreditCardUsesStrikeSystemV2Name[]; extern const char kEnableAutofillSaveCreditCardUsesStrikeSystemV2Description[]; -extern const char kEnableSyncUSSBookmarksName[]; -extern const char kEnableSyncUSSBookmarksDescription[]; - -extern const char kEnableSyncUSSPasswordsName[]; -extern const char kEnableSyncUSSPasswordsDescription[]; - -// Title and description for the flag to control if Chrome Sync should use the -// sandbox servers. -extern const char kSyncSandboxName[]; -extern const char kSyncSandboxDescription[]; - -// Title and description for the flag to control if Chrome Sync (in standalone -// transport mode) supports non-primary accounts. -extern const char kSyncSupportSecondaryAccountName[]; -extern const char kSyncSupportSecondaryAccountDescription[]; - -// Title and description for the flag to control if Google Payments API calls -// should use the sandbox servers. -extern const char kWalletServiceUseSandboxName[]; -extern const char kWalletServiceUseSandboxDescription[]; - -// Title and description for the flag to control the new app launcher. -extern const char kAppLauncherRefreshName[]; -extern const char kAppLauncherRefreshDescription[]; - -// Title and description for the flag to control offering to save unmasked -// server cards locally as FULL_SERVER_CARDs upon success of credit card unmask. -extern const char kAutofillNoLocalSaveOnUnmaskSuccessName[]; -extern const char kAutofillNoLocalSaveOnUnmaskSuccessDescription[]; - -// Title and description for the flag to control saving FULL_SERVER_CARDS upon -// success of credit card upload. -extern const char kAutofillNoLocalSaveOnUploadSuccessName[]; -extern const char kAutofillNoLocalSaveOnUploadSuccessDescription[]; - -// Enforcing restrictions to enable/disable autofill small form support. -extern const char kAutofillEnforceMinRequiredFieldsForHeuristicsName[]; -extern const char kAutofillEnforceMinRequiredFieldsForHeuristicsDescription[]; -extern const char kAutofillEnforceMinRequiredFieldsForQueryName[]; -extern const char kAutofillEnforceMinRequiredFieldsForQueryDescription[]; -extern const char kAutofillEnforceMinRequiredFieldsForUploadName[]; -extern const char kAutofillEnforceMinRequiredFieldsForUploadDescription[]; - // Title and description for the flag to control the credit card import from // dynamic forms. extern const char kEnableAutofillImportDynamicFormsName[]; @@ -135,79 +176,21 @@ extern const char kEnableAutofillImportNonFocusableCreditCardFormsName[]; extern const char kEnableAutofillImportNonFocusableCreditCardFormsDescription[]; -// Title and description for the flag to control the autofill delay. -extern const char kAutofillIOSDelayBetweenFieldsName[]; -extern const char kAutofillIOSDelayBetweenFieldsDescription[]; - -// Title and description for the flag to control if manual fallback is enabled. -extern const char kAutofillManualFallbackName[]; -extern const char kAutofillManualFallbackDescription[]; - -// Title and description for the flag to control if manual fallback is enabled. -extern const char kAutofillManualFallbackPhaseTwoName[]; -extern const char kAutofillManualFallbackPhaseTwoDescription[]; - -// Title and description for the flag to control if prefilled value filter -// profiles. -extern const char kAutofillShowAllSuggestionsOnPrefilledFormsName[]; -extern const char kAutofillShowAllSuggestionsOnPrefilledFormsDescription[]; - -// Title and description for the flag to restrict extraction of formless forms -// to checkout flows. -extern const char kAutofillRestrictUnownedFieldsToFormlessCheckoutName[]; -extern const char kAutofillRestrictUnownedFieldsToFormlessCheckoutDescription[]; - -// Title and description for the flag to enable rich autofill queries on -// Canary/Dev. -extern const char kAutofillRichMetadataQueriesName[]; -extern const char kAutofillRichMetadataQueriesDescription[]; - -// Title and description for the flag to make browser container keep the -// content view hierarchy directly. -extern const char kBrowserContainerKeepsContentViewName[]; -extern const char kBrowserContainerKeepsContentViewDescription[]; - -// Title and description for the flag to control redirection to the task -// scheduler. -extern const char kBrowserTaskScheduler[]; -extern const char kBrowserTaskSchedulerDescription[]; - -// Title and description for the flag to enable automatically switching to the -// regular tabs after closing the last incognito tab. -extern const char kClosingLastIncognitoTabName[]; -extern const char kClosingLastIncognitoTabDescription[]; - -// Title and description for the flag to enable Contextual Search. -extern const char kContextualSearch[]; -extern const char kContextualSearchDescription[]; - -// Title and description for the flag to diffentiate between copied -// urls, strings, and images. -extern const char kCopiedContentBehaviorName[]; -extern const char kCopiedContentBehaviorDescription[]; - -// Title and description for the flag to enable displaying search engine -// favicons in Settings. -extern const char kDisplaySearchEngineFaviconName[]; -extern const char kDisplaySearchEngineFaviconDescription[]; - -// Title and description for the flag to enable drag and drop. -extern const char kDragAndDropName[]; -extern const char kDragAndDropDescription[]; - -// Title and description for the flag to enable new Clear Browsing Data UI. -extern const char kNewClearBrowsingDataUIName[]; -extern const char kNewClearBrowsingDataUIDescription[]; +// Title and description for the flag to enable the clipboard provider to +// suggest searchihng for copied imagse +extern const char kEnableClipboardProviderImageSuggestionsName[]; +extern const char kEnableClipboardProviderImageSuggestionsDescription[]; // Title and description for the flag to enable the clipboard provider to // suggest copied text extern const char kEnableClipboardProviderTextSuggestionsName[]; extern const char kEnableClipboardProviderTextSuggestionsDescription[]; -// Title and description for the flag to enable the clipboard provider to -// suggest searchihng for copied imagse -extern const char kEnableClipboardProviderImageSuggestionsName[]; -extern const char kEnableClipboardProviderImageSuggestionsDescription[]; +extern const char kEnableSyncUSSBookmarksName[]; +extern const char kEnableSyncUSSBookmarksDescription[]; + +extern const char kEnableSyncUSSPasswordsName[]; +extern const char kEnableSyncUSSPasswordsDescription[]; // Title and description for the flag to enable invaliations delivery via FCM. extern const char kFCMInvalidationsName[]; @@ -218,6 +201,10 @@ extern const char kFillOnAccountSelectHttpName[]; extern const char kFillOnAccountSelectHttpDescription[]; +// Title and description for the flag to search in iFrames in Find In Page. +extern const char kFindInPageiFrameName[]; +extern const char kFindInPageiFrameDescription[]; + // Title and description for the command line switch used to determine the // active fullscreen viewport adjustment mode. extern const char kFullscreenViewportAdjustmentExperimentName[]; @@ -232,6 +219,10 @@ extern const char kIdentityDiscName[]; extern const char kIdentityDiscDescription[]; +// Title and description for the flag to ignore viewport scale limits. +extern const char kIgnoresViewportScaleLimitsName[]; +extern const char kIgnoresViewportScaleLimitsDescription[]; + // Title and description for the flag to enable the new UI Reboot on Infobars. extern const char kInfobarUIRebootName[]; extern const char kInfobarUIRebootDescription[]; @@ -254,6 +245,14 @@ extern const char kMarkHttpAsName[]; extern const char kMarkHttpAsDescription[]; +// Title and description for the flag to enable new Clear Browsing Data UI. +extern const char kNewClearBrowsingDataUIName[]; +extern const char kNewClearBrowsingDataUIDescription[]; + +// Title and description for the flag to display new omnibox popup. +extern const char kNewOmniboxPopupLayoutName[]; +extern const char kNewOmniboxPopupLayoutDescription[]; + // Title and description for the flag to enable new password form parsing. extern const char kNewPasswordFormParsingName[]; extern const char kNewPasswordFormParsingDescription[]; @@ -263,15 +262,6 @@ extern const char kNewPasswordFormParsingForSavingName[]; extern const char kNewPasswordFormParsingForSavingDescription[]; -// Title and description for the flag to display new omnibox popup. -extern const char kNewOmniboxPopupLayoutName[]; -extern const char kNewOmniboxPopupLayoutDescription[]; - -// Title and description for the flag to show default search engine favicon in -// the omnibox -extern const char kOmniboxUseDefaultSearchEngineFaviconName[]; -extern const char kOmniboxUseDefaultSearchEngineFaviconDescription[]; - // Title and description for the flag to enable non-modal JavaScript dialogs. extern const char kNonModalDialogsName[]; extern const char kNonModalDialogsDescription[]; @@ -286,16 +276,26 @@ extern const char kOmniboxPopupShortcutIconsInZeroStateName[]; extern const char kOmniboxPopupShortcutIconsInZeroStateDescription[]; -// Title and description for the flag to change the max number of autocomplete -// matches in the omnibox popup. -extern const char kOmniboxUIMaxAutocompleteMatchesName[]; -extern const char kOmniboxUIMaxAutocompleteMatchesDescription[]; +// Title and description for the flag to enable the "switch to this tab" option +// in the omnibox suggestion. It doesn't add new suggestions. +extern const char kOmniboxTabSwitchSuggestionsName[]; +extern const char kOmniboxTabSwitchSuggestionsDescription[]; // Title and description for the flag to enable elision of the URL path, query, // and ref in omnibox URL suggestions. extern const char kOmniboxUIElideSuggestionUrlAfterHostName[]; extern const char kOmniboxUIElideSuggestionUrlAfterHostDescription[]; +// Title and description for the flag to change the max number of autocomplete +// matches in the omnibox popup. +extern const char kOmniboxUIMaxAutocompleteMatchesName[]; +extern const char kOmniboxUIMaxAutocompleteMatchesDescription[]; + +// Title and description for the flag to show default search engine favicon in +// the omnibox +extern const char kOmniboxUseDefaultSearchEngineFaviconName[]; +extern const char kOmniboxUseDefaultSearchEngineFaviconDescription[]; + // Title and description for the flag to enable using only new password form // parsing. extern const char kOnlyNewPasswordFormParsingName[]; @@ -309,10 +309,6 @@ extern const char kPhysicalWeb[]; extern const char kPhysicalWebDescription[]; -// Title and description for the flag to ignore viewport scale limits. -extern const char kIgnoresViewportScaleLimitsName[]; -extern const char kIgnoresViewportScaleLimitsDescription[]; - // Title and description for the flag to toggle the flag of the search button. extern const char kSearchIconToggleName[]; extern const char kSearchIconToggleDescription[]; @@ -345,26 +341,41 @@ extern const char kSettingsRefreshName[]; extern const char kSettingsRefreshDescription[]; -// Title and description for the flag to enable WKBackForwardList based -// navigation manager. -extern const char kSlimNavigationManagerName[]; -extern const char kSlimNavigationManagerDescription[]; - // Title and description for the flag to enable annotating web forms with // Autofill field type predictions as placeholder. extern const char kShowAutofillTypePredictionsName[]; extern const char kShowAutofillTypePredictionsDescription[]; -// Title and description for the flag to enable the toolbar container -// implementation. -extern const char kToolbarContainerName[]; -extern const char kToolbarContainerDescription[]; +// Title and description for the flag to enable WKBackForwardList based +// navigation manager. +extern const char kSlimNavigationManagerName[]; +extern const char kSlimNavigationManagerDescription[]; // Title and description for the flag to use |-drawViewHierarchy:| for taking // snapshots. extern const char kSnapshotDrawViewName[]; extern const char kSnapshotDrawViewDescription[]; +// Title and description for the flag to store pending item in NavigationContext +// after context is created. +extern const char kStorePendingItemInContextName[]; +extern const char kStorePendingItemInContextDescription[]; + +// Title and description for the flag to control if Chrome Sync should use the +// sandbox servers. +extern const char kSyncSandboxName[]; +extern const char kSyncSandboxDescription[]; + +// Title and description for the flag to control if Chrome Sync (in standalone +// transport mode) supports non-primary accounts. +extern const char kSyncSupportSecondaryAccountName[]; +extern const char kSyncSupportSecondaryAccountDescription[]; + +// Title and description for the flag to enable the toolbar container +// implementation. +extern const char kToolbarContainerName[]; +extern const char kToolbarContainerDescription[]; + // Title and description for the flag to control manual translate trigger. extern const char kTranslateManualTriggerName[]; extern const char kTranslateManualTriggerDescription[]; @@ -373,6 +384,10 @@ extern const char kUnifiedConsentName[]; extern const char kUnifiedConsentDescription[]; +// Title and description for the flag to enable the ddljson Doodle API. +extern const char kUseDdljsonApiName[]; +extern const char kUseDdljsonApiDescription[]; + // Title and description for the flag to enable Gaia Auth Mutlilogin endpoint // for identity consistency. extern const char kUseMultiloginEndpointName[]; @@ -383,20 +398,16 @@ extern const char kUseNSURLSessionForGaiaSigninRequestsName[]; extern const char kUseNSURLSessionForGaiaSigninRequestsDescription[]; -// Title and description for the flag to enable the ddljson Doodle API. -extern const char kUseDdljsonApiName[]; -extern const char kUseDdljsonApiDescription[]; +// Title and description for the flag to control if Google Payments API calls +// should use the sandbox servers. +extern const char kWalletServiceUseSandboxName[]; +extern const char kWalletServiceUseSandboxDescription[]; // Title and description for the flag to use the Clear browsing data API from // web. extern const char kWebClearBrowsingDataName[]; extern const char kWebClearBrowsingDataDescription[]; -// Title and description for the flag to store pending item in NavigationContext -// after context is created. -extern const char kStorePendingItemInContextName[]; -extern const char kStorePendingItemInContextDescription[]; - // Title and description for the flag to enable text accessibility in webpages. extern const char kWebPageTextAccessibilityName[]; extern const char kWebPageTextAccessibilityDescription[]; @@ -406,11 +417,7 @@ extern const char kWKHTTPSystemCookieStoreName[]; extern const char kWKHTTPSystemCookieStoreDescription[]; -// Title and description for the flag to search in iFrames in Find In Page. -extern const char kFindInPageiFrameName[]; -extern const char kFindInPageiFrameDescription[]; - -// Please insert your name/description above in alphabetical order. +// Please add names and descriptions above in alphabetical order. } // namespace flag_descriptions
diff --git a/ios/chrome/browser/tabs/tab_model_observer.h b/ios/chrome/browser/tabs/tab_model_observer.h index 8e01fe14..9f5a0c8d 100644 --- a/ios/chrome/browser/tabs/tab_model_observer.h +++ b/ios/chrome/browser/tabs/tab_model_observer.h
@@ -21,9 +21,6 @@ atIndex:(NSUInteger)index inForeground:(BOOL)fg; -// The given tab will be removed. -- (void)tabModel:(TabModel*)model willRemoveTab:(Tab*)tab; - // A tab was removed at the given index. - (void)tabModel:(TabModel*)model didRemoveTab:(Tab*)tab
diff --git a/ios/chrome/browser/tabs/tab_model_observers_bridge.mm b/ios/chrome/browser/tabs/tab_model_observers_bridge.mm index 4b3381c..e6b8911 100644 --- a/ios/chrome/browser/tabs/tab_model_observers_bridge.mm +++ b/ios/chrome/browser/tabs/tab_model_observers_bridge.mm
@@ -98,12 +98,4 @@ atIndex:static_cast<NSUInteger>(atIndex)]; } -- (void)webStateList:(WebStateList*)webStateList - willDetachWebState:(web::WebState*)webState - atIndex:(int)atIndex { - DCHECK_GE(atIndex, 0); - [_tabModelObservers tabModel:_tabModel - willRemoveTab:LegacyTabHelper::GetTabForWebState(webState)]; -} - @end
diff --git a/ios/chrome/browser/ui/alert_view_controller/BUILD.gn b/ios/chrome/browser/ui/alert_view_controller/BUILD.gn index 6501e6c..257e5b7 100644 --- a/ios/chrome/browser/ui/alert_view_controller/BUILD.gn +++ b/ios/chrome/browser/ui/alert_view_controller/BUILD.gn
@@ -9,8 +9,6 @@ "alert_consumer.h", "alert_view_controller.h", "alert_view_controller.mm", - "non_modal_view_controller_presenter.h", - "non_modal_view_controller_presenter.mm", ] deps = [ "//base",
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 58b68c1..d5a0370 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -187,6 +187,7 @@ #import "ios/chrome/browser/web/web_navigation_util.h" #include "ios/chrome/browser/web_state_list/all_web_state_observation_forwarder.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" #import "ios/chrome/browser/web_state_list/web_usage_enabler/web_state_list_web_usage_enabler.h" #import "ios/chrome/browser/web_state_list/web_usage_enabler/web_state_list_web_usage_enabler_factory.h" #import "ios/chrome/browser/webui/net_export_tab_helper.h" @@ -392,6 +393,7 @@ TabModelObserver, TabStripPresentation, ToolbarHeightProviderForFullscreen, + WebStateListObserving, UIGestureRecognizerDelegate, URLLoadingObserver> { // The dependency factory passed on initialization. Used to vend objects used @@ -512,6 +514,9 @@ std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge; std::unique_ptr<UrlLoadingObserverBridge> _URLLoadingObserverBridge; + + // Bridges C++ WebStateListObserver methods to this BrowserViewController. + std::unique_ptr<WebStateListObserverBridge> _webStateListObserver; } // Activates/deactivates the object. This will enable/disable the ability for @@ -668,8 +673,8 @@ // Sets the correct frame and hierarchy for subviews and helper views. Only // insert views on |initialLayout|. - (void)setUpViewLayout:(BOOL)initialLayout; -// Makes |tab| the currently visible tab, displaying its view. -- (void)displayTab:(Tab*)tab; +// Makes |webState| the currently visible WebState, displaying its view. +- (void)displayWebState:(web::WebState*)webState; // Initializes the bookmark interaction controller if not already initialized. - (void)initializeBookmarkInteractionController; // Installs the BVC as overscroll actions controller of |nativeContent| if @@ -744,11 +749,12 @@ - (void)installDelegatesForTab:(Tab*)tab; // Remove delegates from the provided |tab|. - (void)uninstallDelegatesForTab:(Tab*)tab; -// Called when a tab is selected in the model. Make any required view changes. -// The notification will not be sent when the tab is already the selected tab. -// |notifyToolbar| indicates whether the toolbar is notified that the tab has -// changed. -- (void)tabSelected:(Tab*)tab notifyToolbar:(BOOL)notifyToolbar; +// Called when a |webState| is selected in the WebStateList. Make any required +// view changes. The notification will not be sent when the |webState| is +// already the selected WebState. |notifyToolbar| indicates whether the toolbar +// is notified that the webState has changed. +- (void)webStateSelected:(web::WebState*)webState + notifyToolbar:(BOOL)notifyToolbar; // Returns the native controller being used by |tab|'s web controller. - (id)nativeControllerForTab:(Tab*)tab; @@ -1231,7 +1237,7 @@ // Keyboard shouldn't overlay the ecoutez window, so dismiss find in page and // dismiss the keyboard. [self closeFindInPage]; - [[self viewForTab:self.tabModel.currentTab] endEditing:NO]; + [[self viewForWebState:self.currentWebState] endEditing:NO]; // Ensure that voice search objects are created. [self ensureVoiceSearchControllerCreated]; @@ -1277,7 +1283,7 @@ [self updateBroadcastState]; // Stop the NTP on web usage toggle. This happens when clearing browser - // data, and forces the NTP to be recreated in -displayTab below. + // data, and forces the NTP to be recreated in -displayWebState below. // TODO(crbug.com/906199): Move this to the NewTabPageTabHelper when // WebStateObserver has a webUsage callback. if (!active) { @@ -1294,9 +1300,8 @@ PagePlaceholderTabHelper::FromWebState(self.currentWebState) ->AddPlaceholderForNextNavigation(); } - Tab* currentTab = self.tabModel.currentTab; - if (currentTab) - [self displayTab:currentTab]; + if (self.currentWebState) + [self displayWebState:self.currentWebState]; } else { [_dialogPresenter cancelAllDialogs]; } @@ -1459,6 +1464,8 @@ // before self.tabModel is released. _sideSwipeController = nil; [self.tabModel removeObserver:self]; + self.tabModel.webStateList->RemoveObserver(_webStateListObserver.get()); + _webStateListObserver.reset(); _allWebStateObservationForwarder = nullptr; if (_voiceSearchController) _voiceSearchController->SetDispatcher(nil); @@ -1632,11 +1639,10 @@ // updating the view will be handled when it's displayed again. if (!self.webUsageEnabled || !self.contentArea) return; - // Update the displayed tab (if any; the switcher may not have created one - // yet) in case it changed while showing the switcher. - Tab* currentTab = self.tabModel.currentTab; - if (currentTab) - [self displayTab:currentTab]; + // Update the displayed WebState (if any; the switcher may not have created + // one yet) in case it changed while showing the switcher. + if (self.currentWebState) + [self displayWebState:self.currentWebState]; } - (void)viewWillDisappear:(BOOL)animated { @@ -1920,6 +1926,8 @@ std::make_unique<AllWebStateObservationForwarder>( self.tabModel.webStateList, _webStateObserverBridge.get()); + _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self); + self.tabModel.webStateList->AddObserver(_webStateListObserver.get()); _URLLoadingObserverBridge = std::make_unique<UrlLoadingObserverBridge>(self); UrlLoadingNotifier* urlLoadingNotifier = UrlLoadingNotifierFactory::GetForBrowserState(_browserState); @@ -2394,12 +2402,12 @@ } } -- (void)displayTab:(Tab*)tab { - DCHECK(tab); +- (void)displayWebState:(web::WebState*)webState { + DCHECK(webState); [self loadViewIfNeeded]; // Set this before triggering any of the possible page loads below. - tab.webState->SetKeepRenderProcessAlive(true); + webState->SetKeepRenderProcessAlive(true); if (!self.inNewTabAnimation) { // Hide findbar. |updateToolbar| will restore the findbar later. @@ -2407,25 +2415,25 @@ // Make new content visible, resizing it first as the orientation may // have changed from the last time it was displayed. - [self viewForTab:tab].frame = self.contentArea.bounds; + [self viewForWebState:webState].frame = self.contentArea.bounds; + [_toolbarUIUpdater updateState]; NewTabPageTabHelper* NTPHelper = - NewTabPageTabHelper::FromWebState(tab.webState); + NewTabPageTabHelper::FromWebState(webState); if (NTPHelper && NTPHelper->IsActive()) { UIViewController* viewController = - _ntpCoordinatorsForWebStates[tab.webState].viewController; - viewController.view.frame = [self ntpFrameForWebState:tab.webState]; + _ntpCoordinatorsForWebStates[webState].viewController; + viewController.view.frame = [self ntpFrameForWebState:webState]; // TODO(crbug.com/873729): For a newly created WebState, the session will // not be restored until LoadIfNecessary call. Remove when fixed. - tab.webState->GetNavigationManager()->LoadIfNecessary(); + webState->GetNavigationManager()->LoadIfNecessary(); // Always show the webState view under the NTP, to work around // crbug.com/848789 if (base::FeatureList::IsEnabled(kBrowserContainerKeepsContentView)) { if (self.browserContainerViewController.contentView != - tab.webState->GetView()) { - self.browserContainerViewController.contentView = - tab.webState->GetView(); + webState->GetView()) { + self.browserContainerViewController.contentView = webState->GetView(); } self.browserContainerViewController.contentView.frame = self.contentArea.bounds; @@ -2434,16 +2442,15 @@ } self.browserContainerViewController.contentViewController = viewController; - } else { - self.browserContainerViewController.contentView = [self viewForTab:tab]; + self.browserContainerViewController.contentView = + [self viewForWebState:webState]; } } [self updateToolbar]; // Notify the WebState that it was displayed. - DCHECK(tab.webState); - tab.webState->WasShown(); + webState->WasShown(); } - (void)initializeBookmarkInteractionController { @@ -2555,7 +2562,7 @@ } - (CGRect)visibleFrameForTab:(Tab*)tab { - UIView* tabView = [self viewForTab:tab]; + UIView* tabView = [self viewForWebState:tab.webState]; return UIEdgeInsetsInsetRect(tabView.bounds, [self viewportInsetsForView:tabView]); } @@ -2586,16 +2593,15 @@ } } -- (UIView*)viewForTab:(Tab*)tab { - DCHECK(tab); - if (!tab.webState) +- (UIView*)viewForWebState:(web::WebState*)webState { + if (!webState) return nil; - web::WebState* webState = tab.webState; NewTabPageTabHelper* NTPHelper = NewTabPageTabHelper::FromWebState(webState); if (NTPHelper && NTPHelper->IsActive()) { return _ntpCoordinatorsForWebStates[webState].viewController.view; } - DCHECK([self.tabModel indexOfTab:tab] != NSNotFound); + DCHECK(self.tabModel.webStateList->GetIndexOfWebState(webState) != + WebStateList::kInvalidIndex); // TODO(crbug.com/904588): Move |RecordPageLoadStart| to TabUsageRecorder. if (webState->IsEvicted() && [self.tabModel tabUsageRecorder]) { [self.tabModel tabUsageRecorder] -> RecordPageLoadStart(webState); @@ -2796,15 +2802,16 @@ SnapshotTabHelper::FromWebState(tab.webState)->SetDelegate(nil); } -- (void)tabSelected:(Tab*)tab notifyToolbar:(BOOL)notifyToolbar { - DCHECK(tab); +- (void)webStateSelected:(web::WebState*)webState + notifyToolbar:(BOOL)notifyToolbar { + DCHECK(webState); // Ignore changes while the tab stack view is visible (or while suspended). // The display will be refreshed when this view becomes active again. if (!self.visible || !self.webUsageEnabled) return; - [self displayTab:tab]; + [self displayWebState:webState]; if (_expectingForegroundTab && !self.inNewTabAnimation) { // Now that the new tab has been displayed, return to normal. Rather than @@ -4274,7 +4281,7 @@ // Dismiss the omnibox (if open). [self.dispatcher cancelOmniboxEdit]; // Dismiss the soft keyboard (if open). - [[self viewForTab:self.tabModel.currentTab] endEditing:NO]; + [[self viewForWebState:self.currentWebState] endEditing:NO]; // Dismiss Find in Page focus. [self updateFindBar:NO shouldFocus:NO]; @@ -4323,6 +4330,47 @@ navigationManager->ReloadWithUserAgentType(userAgentType); } +#pragma mark - WebStateListObserving methods + +// Observer method, active WebState changed. +- (void)webStateList:(WebStateList*)webStateList + didChangeActiveWebState:(web::WebState*)newWebState + oldWebState:(web::WebState*)oldWebState + atIndex:(int)atIndex + reason:(int)reason { + if (oldWebState) { + oldWebState->WasHidden(); + oldWebState->SetKeepRenderProcessAlive(false); + [self dismissPopups]; + } + // NOTE: webStateSelected expects to always be called with a + // non-null WebState. + if (!newWebState) + return; + + self.currentWebState->GetWebViewProxy().scrollViewProxy.clipsToBounds = NO; + + [_paymentRequestManager setActiveWebState:newWebState]; + + [self webStateSelected:newWebState notifyToolbar:YES]; +} + +- (void)webStateList:(WebStateList*)webStateList + willDetachWebState:(web::WebState*)webState + atIndex:(int)atIndex { + if (webState == self.currentWebState) { + self.browserContainerViewController.contentView = nil; + } + + [_paymentRequestManager stopTrackingWebState:webState]; + + [[UpgradeCenter sharedInstance] + tabWillClose:TabIdTabHelper::FromWebState(webState)->tab_id()]; + if (webStateList->count() == 1) { // About to remove the last tab. + [_paymentRequestManager setActiveWebState:nullptr]; + } +} + #pragma mark - TabModelObserver methods // Observer method, tab inserted. @@ -4338,29 +4386,6 @@ } } -// Observer method, active tab changed. -- (void)tabModel:(TabModel*)model - didChangeActiveTab:(Tab*)newTab - previousTab:(Tab*)previousTab - atIndex:(NSUInteger)index { - if (previousTab) { - previousTab.webState->WasHidden(); - previousTab.webState->SetKeepRenderProcessAlive(false); - [self dismissPopups]; - } - - // TODO(rohitrao): tabSelected expects to always be called with a non-nil tab. - // Currently this observer method is always called with a non-nil |newTab|, - // but that may change in the future. Remove this DCHECK when it does. - DCHECK(newTab); - - self.currentWebState->GetWebViewProxy().scrollViewProxy.clipsToBounds = NO; - - [_paymentRequestManager setActiveWebState:newTab.webState]; - - [self tabSelected:newTab notifyToolbar:YES]; -} - - (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab { DCHECK(tab && ([self.tabModel indexOfTab:tab] != NSNotFound)); if (tab == self.tabModel.currentTab) { @@ -4447,7 +4472,7 @@ // Add |newTab|'s view to the hierarchy if it's the current Tab. if (self.active && model.currentTab == newTab) - [self displayTab:newTab]; + [self displayWebState:newTab.webState]; if (newTab) [_paymentRequestManager setActiveWebState:newTab.webState]; @@ -4474,20 +4499,6 @@ [self hideFindBarWithAnimation:NO]; } -- (void)tabModel:(TabModel*)model willRemoveTab:(Tab*)tab { - if (tab == [model currentTab]) { - self.browserContainerViewController.contentView = nil; - } - - [_paymentRequestManager stopTrackingWebState:tab.webState]; - - [[UpgradeCenter sharedInstance] - tabWillClose:TabIdTabHelper::FromWebState(tab.webState)->tab_id()]; - if ([model count] == 1) { // About to remove the last tab. - [_paymentRequestManager setActiveWebState:nullptr]; - } -} - #pragma mark - TabModelObserver helpers (new tab animations) - (void)animateNewTab:(Tab*)tab @@ -4510,22 +4521,22 @@ toolbarSnapshot.frame = [self.contentArea convertRect:toolbarSnapshot.frame fromView:self.view]; [self.contentArea addSubview:toolbarSnapshot]; - newPage = [self viewForTab:tab]; + newPage = [self viewForWebState:tab.webState]; newPage.userInteractionEnabled = NO; newPage.frame = self.view.bounds; } else { - [self viewForTab:tab].frame = self.contentArea.bounds; + [self viewForWebState:tab.webState].frame = self.contentArea.bounds; // Setting the frame here doesn't trigger a layout pass. Trigger it manually // if needed. Not triggering it can create problem if the previous frame // wasn't the right one, for example in https://crbug.com/852106. - [[self viewForTab:tab] layoutIfNeeded]; - newPage = [self viewForTab:tab]; + [[self viewForWebState:tab.webState] layoutIfNeeded]; + newPage = [self viewForWebState:tab.webState]; newPage.userInteractionEnabled = NO; } // Cleanup steps needed for both UI Refresh and stack-view style animations. auto commonCompletion = ^{ - [self viewForTab:tab].frame = self.contentArea.bounds; + [self viewForWebState:tab.webState].frame = self.contentArea.bounds; newPage.userInteractionEnabled = YES; self.inNewTabAnimation = NO; // Use the model's currentTab here because it is possible that it can @@ -4534,8 +4545,8 @@ // tab's view hasn't been displayed yet because it was in a new tab // animation. Tab* currentTab = self.tabModel.currentTab; - if (currentTab) { - [self tabSelected:currentTab notifyToolbar:NO]; + if (currentTab.webState) { + [self webStateSelected:currentTab.webState notifyToolbar:NO]; } if (completion) completion(); @@ -4607,7 +4618,7 @@ } - (void)sideSwipeRedisplayTab:(Tab*)tab { - [self displayTab:tab]; + [self displayWebState:tab.webState]; } - (BOOL)preventSideSwipe { @@ -4894,7 +4905,7 @@ _ntpCoordinatorsForWebStates.erase(webState); } if (self.active && self.currentWebState == webState) { - [self displayTab:self.tabModel.currentTab]; + [self displayWebState:webState]; } }
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm index d6a2c06..11d3fb8 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
@@ -92,8 +92,8 @@ TabModelObserver> - (void)pageLoadStarted:(NSNotification*)notification; - (void)pageLoadComplete:(NSNotification*)notification; -- (void)tabSelected:(Tab*)tab notifyToolbar:(BOOL)notifyToolbar; -- (void)tabDeselected:(NSNotification*)notification; +- (void)webStateSelected:(web::WebState*)webState + notifyToolbar:(BOOL)notifyToolbar; - (void)tabCountChanged:(NSNotification*)notification; @end @@ -225,9 +225,11 @@ web::WebState::CreateParams params(chrome_browser_state_.get()); std::unique_ptr<web::WebState> webState = web::WebState::Create(params); - webStateImpl_.reset(static_cast<web::WebStateImpl*>(webState.release())); - AttachTabHelpers(webStateImpl_.get(), NO); - [currentTab setWebState:webStateImpl_.get()]; + webStateImpl_ = static_cast<web::WebStateImpl*>(webState.get()); + AttachTabHelpers(webStateImpl_, NO); + [currentTab setWebState:webStateImpl_]; + tabModel_.webStateList->InsertWebState(0, std::move(webState), 0, + WebStateOpener()); // Load TemplateURLService. TemplateURLService* template_url_service = @@ -280,7 +282,7 @@ web::TestWebThreadBundle thread_bundle_; IOSChromeScopedTestingLocalState local_state_; std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; - std::unique_ptr<WebStateImpl> webStateImpl_; + WebStateImpl* webStateImpl_; Tab* tab_; TabModel* tabModel_; BrowserViewControllerHelper* bvcHelper_; @@ -291,19 +293,19 @@ UIWindow* window_; }; -TEST_F(BrowserViewControllerTest, TestTabSelected) { - [bvc_ tabSelected:tab_ notifyToolbar:YES]; +TEST_F(BrowserViewControllerTest, TestWebStateSelected) { + [bvc_ webStateSelected:tab_.webState notifyToolbar:YES]; EXPECT_EQ([tab_.webState->GetView() superview], [bvc_ contentArea]); EXPECT_TRUE(webStateImpl_->IsVisible()); } -TEST_F(BrowserViewControllerTest, TestTabSelectedIsNewTab) { +TEST_F(BrowserViewControllerTest, TestWebStateSelectedIsNewWebState) { id block = [^{ return GURL(kChromeUINewTabURL); } copy]; id tabMock = (id)tab_; [tabMock onSelector:@selector(url) callBlockExpectation:block]; - [bvc_ tabSelected:tab_ notifyToolbar:YES]; + [bvc_ webStateSelected:tab_.webState notifyToolbar:YES]; EXPECT_EQ([tab_.webState->GetView() superview], [bvc_ contentArea]); EXPECT_TRUE(webStateImpl_->IsVisible()); }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 61f23d8..f75be6b29 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -69,17 +69,6 @@ @implementation ContentSuggestionsCoordinator @synthesize browserState = _browserState; -@synthesize suggestionsViewController = _suggestionsViewController; -@synthesize visible = _visible; -@synthesize contentSuggestionsMediator = _contentSuggestionsMediator; -@synthesize headerCollectionInteractionHandler = - _headerCollectionInteractionHandler; -@synthesize headerController = _headerController; -@synthesize webStateList = _webStateList; -@synthesize toolbarDelegate = _toolbarDelegate; -@synthesize dispatcher = _dispatcher; -@synthesize metricsRecorder = _metricsRecorder; -@synthesize NTPMediator = _NTPMediator; - (void)start { if (self.visible || !self.browserState) { @@ -116,7 +105,7 @@ } UrlLoadingService* urlLoadingService = - UrlLoadingServiceFactory::GetForBrowserState(_browserState); + UrlLoadingServiceFactory::GetForBrowserState(self.browserState); self.NTPMediator = [[NTPHomeMediator alloc] initWithWebStateList:self.webStateList
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm index 557fe6d..8b13394 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -21,6 +21,8 @@ #import "ios/chrome/browser/ui/browser_view/browser_view_controller.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" #import "ios/chrome/browser/url_loading/app_url_loading_service.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/web/public/web_state/web_state.h" @@ -83,7 +85,7 @@ @end -@interface BrowserViewWrangler ()<TabModelObserver> { +@interface BrowserViewWrangler () <WebStateListObserving, TabModelObserver> { ios::ChromeBrowserState* _browserState; __weak id<TabModelObserver> _tabModelObserver; __weak id<ApplicationCommands> _applicationCommandEndpoint; @@ -93,6 +95,7 @@ std::unique_ptr<Browser> _mainBrowser; std::unique_ptr<Browser> _otrBrowser; + std::unique_ptr<WebStateListObserverBridge> _webStateListObserver; } @property(nonatomic, strong, readwrite) WrangledBrowser* mainInterface; @@ -148,6 +151,7 @@ _applicationCommandEndpoint = applicationCommandEndpoint; _appURLLoadingService = appURLLoadingService; _storageSwitcher = storageSwitcher; + _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self); } return self; } @@ -245,6 +249,7 @@ [tabModel removeObserver:_tabModelObserver]; } [tabModel removeObserver:self]; + tabModel.webStateList->RemoveObserver(_webStateListObserver.get()); } _mainBrowser = std::move(mainBrowser); @@ -259,6 +264,7 @@ [tabModel removeObserver:_tabModelObserver]; } [tabModel removeObserver:self]; + tabModel.webStateList->RemoveObserver(_webStateListObserver.get()); } _otrBrowser = std::move(otrBrowser); @@ -275,15 +281,18 @@ [self.deviceSharingManager updateBrowserState:NULL]; } -#pragma mark - TabModelObserver +#pragma mark - WebStateListObserving -- (void)tabModel:(TabModel*)model - didChangeActiveTab:(Tab*)newTab - previousTab:(Tab*)previousTab - atIndex:(NSUInteger)index { +- (void)webStateList:(WebStateList*)webStateList + didChangeActiveWebState:(web::WebState*)newWebState + oldWebState:(web::WebState*)oldWebState + atIndex:(int)atIndex + reason:(int)reason { [self updateDeviceSharingManager]; } +#pragma mark - TabModelObserver + - (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab { [self updateDeviceSharingManager]; } @@ -410,6 +419,7 @@ if (_tabModelObserver) { [tabModel addObserver:_tabModelObserver]; [tabModel addObserver:self]; + tabModel.webStateList->AddObserver(_webStateListObserver.get()); } breakpad::MonitorTabStateForWebStateList(tabModel.webStateList); }
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn index df7b5f7d..c1ae2d2 100644 --- a/ios/chrome/browser/ui/omnibox/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -18,6 +18,45 @@ ] } +source_set("omnibox_protocols") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "favicon_retriever.h", + "image_retriever.h", + ] +} + +source_set("omnibox_ui") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "omnibox_icon.h", + "omnibox_icon_view.h", + "omnibox_icon_view.mm", + ] + deps = [ + ":omnibox_protocols", + "//url", + ] +} + +source_set("omnibox_ui_internal") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "omnibox_icon_formatter.h", + "omnibox_icon_formatter.mm", + ] + + deps = [ + ":omnibox_protocols", + ":omnibox_ui", + ":omnibox_util", + "//components/omnibox/browser", + "//ios/chrome/browser/ui:feature_flags", + "//ios/chrome/browser/ui/colors", + "//url", + ] +} + source_set("omnibox_popup_shared") { configs += [ "//build/config/compiler:enable_arc" ] sources = [
diff --git a/ios/chrome/browser/ui/omnibox/popup/favicon_retriever.h b/ios/chrome/browser/ui/omnibox/favicon_retriever.h similarity index 77% rename from ios/chrome/browser/ui/omnibox/popup/favicon_retriever.h rename to ios/chrome/browser/ui/omnibox/favicon_retriever.h index 9fb1906..d4a9f82 100644 --- a/ios/chrome/browser/ui/omnibox/popup/favicon_retriever.h +++ b/ios/chrome/browser/ui/omnibox/favicon_retriever.h
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_FAVICON_RETRIEVER_H_ -#define IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_FAVICON_RETRIEVER_H_ +#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_FAVICON_RETRIEVER_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_FAVICON_RETRIEVER_H_ + +class GURL; // A favicon retriever. // This protocol is intended to be used in Showcase, abstracting out the actual @@ -16,4 +18,4 @@ - (void)fetchFavicon:(GURL)pageURL completion:(void (^)(UIImage*))completion; @end -#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_FAVICON_RETRIEVER_H_ +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_FAVICON_RETRIEVER_H_
diff --git a/ios/chrome/browser/ui/omnibox/image_retriever.h b/ios/chrome/browser/ui/omnibox/image_retriever.h new file mode 100644 index 0000000..5deadda --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/image_retriever.h
@@ -0,0 +1,14 @@ +// 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_UI_OMNIBOX_IMAGE_RETRIEVER_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_IMAGE_RETRIEVER_H_ + +class GURL; + +@protocol ImageRetriever <NSObject> +- (void)fetchImage:(GURL)imageURL completion:(void (^)(UIImage*))completion; +@end + +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_IMAGE_RETRIEVER_H_
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_icon.h b/ios/chrome/browser/ui/omnibox/omnibox_icon.h new file mode 100644 index 0000000..dba322a --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_icon.h
@@ -0,0 +1,34 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_H_ + +class GURL; + +typedef NS_ENUM(NSInteger, OmniboxIconType) { + OmniboxIconTypeSuggestionIcon, + OmniboxIconTypeImage, + OmniboxIconTypeFavicon +}; + +// This protocol represents all the parts necessary to display a composited +// omnibox icon. Most icons have a background and a main image. If the main +// image is an icon (not an image from the web), it will be tinted some color. +// |OmniboxIconView| is the preferred way to consume this protocol and display +// the icons. +@protocol OmniboxIcon <NSObject> + +@property(nonatomic, assign, readonly) OmniboxIconType iconType; +@property(nonatomic, assign, readonly) GURL imageURL; +@property(nonatomic, strong, readonly) UIImage* iconImage; +@property(nonatomic, strong, readonly) UIColor* iconImageTintColor; +@property(nonatomic, strong, readonly) UIImage* backgroundImage; +@property(nonatomic, strong, readonly) UIColor* backgroundImageTintColor; +@property(nonatomic, strong, readonly) UIImage* overlayImage; +@property(nonatomic, strong, readonly) UIColor* overlayImageTintColor; + +@end + +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_H_
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_icon_formatter.h b/ios/chrome/browser/ui/omnibox/omnibox_icon_formatter.h new file mode 100644 index 0000000..3cea6eb --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_icon_formatter.h
@@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_FORMATTER_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_FORMATTER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/omnibox/omnibox_icon.h" + +struct AutocompleteMatch; + +@interface OmniboxIconFormatter : NSObject <OmniboxIcon> + +- (instancetype)initWithMatch:(const AutocompleteMatch&)match + NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_FORMATTER_H_
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_icon_formatter.mm b/ios/chrome/browser/ui/omnibox/omnibox_icon_formatter.mm new file mode 100644 index 0000000..1fc253f --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_icon_formatter.mm
@@ -0,0 +1,215 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/omnibox/omnibox_icon_formatter.h" + +#import "components/omnibox/browser/autocomplete_match.h" +#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" +#import "ios/chrome/browser/ui/omnibox/omnibox_util.h" +#import "ios/chrome/browser/ui/ui_feature_flags.h" +#import "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +OmniboxSuggestionIconType IconTypeFromMatchAndAnswerType( + AutocompleteMatchType::Type type, + base::Optional<int> answerType) { + // Some suggestions have custom icons. Others fallback to the icon from the + // overall match type. + if (answerType) { + switch (answerType.value()) { + case SuggestionAnswer::ANSWER_TYPE_DICTIONARY: + return DICTIONARY; + case SuggestionAnswer::ANSWER_TYPE_FINANCE: + return CURRENCY; + case SuggestionAnswer::ANSWER_TYPE_TRANSLATION: + return TRANSLATION; + case SuggestionAnswer::ANSWER_TYPE_WHEN_IS: + return WHEN_IS; + case SuggestionAnswer::ANSWER_TYPE_CURRENCY: + return CONVERSION; + case SuggestionAnswer::ANSWER_TYPE_SUNRISE: + return SUNRISE; + case SuggestionAnswer::ANSWER_TYPE_KNOWLEDGE_GRAPH: + case SuggestionAnswer::ANSWER_TYPE_LOCAL: + case SuggestionAnswer::ANSWER_TYPE_SPORTS: + case SuggestionAnswer::ANSWER_TYPE_LOCAL_TIME: + case SuggestionAnswer::ANSWER_TYPE_PLAY_INSTALL: + case SuggestionAnswer::ANSWER_TYPE_WEATHER: + break; + case SuggestionAnswer::ANSWER_TYPE_INVALID: + case SuggestionAnswer::ANSWER_TYPE_TOTAL_COUNT: + NOTREACHED(); + break; + } + } + switch (type) { + case AutocompleteMatchType::BOOKMARK_TITLE: + case AutocompleteMatchType::CLIPBOARD_URL: + case AutocompleteMatchType::NAVSUGGEST: + case AutocompleteMatchType::NAVSUGGEST_PERSONALIZED: + case AutocompleteMatchType::PHYSICAL_WEB_DEPRECATED: + case AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW_DEPRECATED: + case AutocompleteMatchType::URL_WHAT_YOU_TYPED: + case AutocompleteMatchType::DOCUMENT_SUGGESTION: + case AutocompleteMatchType::PEDAL: + case AutocompleteMatchType::HISTORY_BODY: + case AutocompleteMatchType::HISTORY_KEYWORD: + case AutocompleteMatchType::HISTORY_TITLE: + case AutocompleteMatchType::HISTORY_URL: + case AutocompleteMatchType::TAB_SEARCH_DEPRECATED: + return DEFAULT_FAVICON; + case AutocompleteMatchType::CONTACT_DEPRECATED: + case AutocompleteMatchType::SEARCH_HISTORY: + case AutocompleteMatchType::SEARCH_OTHER_ENGINE: + case AutocompleteMatchType::SEARCH_SUGGEST: + case AutocompleteMatchType::SEARCH_SUGGEST_ENTITY: + case AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED: + case AutocompleteMatchType::SEARCH_SUGGEST_PROFILE: + case AutocompleteMatchType::SEARCH_SUGGEST_TAIL: + case AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED: + case AutocompleteMatchType::VOICE_SUGGEST: + case AutocompleteMatchType::CLIPBOARD_TEXT: + case AutocompleteMatchType::CLIPBOARD_IMAGE: + return SEARCH; + case AutocompleteMatchType::CALCULATOR: + return CALCULATOR; + case AutocompleteMatchType::EXTENSION_APP_DEPRECATED: + case AutocompleteMatchType::NUM_TYPES: + NOTREACHED(); + return DEFAULT_FAVICON; + } +} + +} // namespace + +@interface OmniboxIconFormatter () + +@property(nonatomic, assign) BOOL isAnswer; +@property(nonatomic, assign) OmniboxIconType iconType; +@property(nonatomic, assign) OmniboxSuggestionIconType suggestionIconType; +@property(nonatomic, assign) GURL imageURL; + +@end + +@implementation OmniboxIconFormatter + +- (instancetype)initWithMatch:(const AutocompleteMatch&)match { + self = [super init]; + if (self) { + _isAnswer = match.answer.has_value(); + if (_isAnswer && match.answer->second_line().image_url().is_valid()) { + _iconType = OmniboxIconTypeImage; + _imageURL = match.answer->second_line().image_url(); + } else if (!match.image_url.empty()) { + _iconType = OmniboxIconTypeImage; + _imageURL = GURL(match.image_url); + } else if (!AutocompleteMatch::IsSearchType(match.type) && + !match.destination_url.is_empty()) { + _iconType = OmniboxIconTypeFavicon; + _imageURL = match.destination_url; + } else { + _iconType = OmniboxIconTypeSuggestionIcon; + _imageURL = GURL(); + } + + auto answerType = _isAnswer ? base::make_optional<int>(match.answer->type()) + : base::nullopt; + _suggestionIconType = + IconTypeFromMatchAndAnswerType(match.type, answerType); + } + return self; +} + +- (UIImage*)iconImage { + NSString* imageName = + GetOmniboxNewSuggestionIconTypeAssetName(self.suggestionIconType); + return [[UIImage imageNamed:imageName] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; +} + +- (BOOL)hasCustomAnswerIcon { + switch (self.suggestionIconType) { + case BOOKMARK: + case DEFAULT_FAVICON: + case HISTORY: + case SEARCH: + return NO; + case CALCULATOR: + case CONVERSION: + case DICTIONARY: + case CURRENCY: + case SUNRISE: + case LOCAL_TIME: + case WHEN_IS: + case TRANSLATION: + return YES; + case OMNIBOX_SUGGESTION_ICON_TYPE_COUNT: + NOTREACHED(); + return NO; + } +} + +- (UIColor*)iconImageTintColor { + switch (self.iconType) { + case OmniboxIconTypeImage: + case OmniboxIconTypeSuggestionIcon: + if ([self hasCustomAnswerIcon]) { + return UIColor.whiteColor; + } + return [UIColor.blackColor colorWithAlphaComponent:0.5]; + case OmniboxIconTypeFavicon: + return [UIColor.blackColor colorWithAlphaComponent:0.5]; + } +} + +- (UIImage*)backgroundImage { + switch (self.iconType) { + case OmniboxIconTypeImage: + return nil; + case OmniboxIconTypeSuggestionIcon: + return [[UIImage imageNamed:@"background_solid"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + case OmniboxIconTypeFavicon: + return [[UIImage imageNamed:@"background_stroke"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } +} + +- (UIColor*)backgroundImageTintColor { + switch (self.iconType) { + case OmniboxIconTypeImage: + return nil; + case OmniboxIconTypeSuggestionIcon: + if ([self hasCustomAnswerIcon]) { + return [MDCPalette.cr_bluePalette tint500]; + } + return [UIColor.blackColor colorWithAlphaComponent:0.1]; + case OmniboxIconTypeFavicon: + return [UIColor.blackColor colorWithAlphaComponent:0.2]; + } +} + +- (UIImage*)overlayImage { + switch (self.iconType) { + case OmniboxIconTypeImage: + return self.isAnswer ? nil + : [[UIImage imageNamed:@"background_stroke"] + imageWithRenderingMode: + UIImageRenderingModeAlwaysTemplate]; + case OmniboxIconTypeSuggestionIcon: + case OmniboxIconTypeFavicon: + return nil; + } +} + +- (UIColor*)overlayImageTintColor { + return [UIColor.blackColor colorWithAlphaComponent:0.1]; +} + +@end
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_icon_view.h b/ios/chrome/browser/ui/omnibox/omnibox_icon_view.h new file mode 100644 index 0000000..140db34 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_icon_view.h
@@ -0,0 +1,29 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_VIEW_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_VIEW_H_ + +#import <UIKit/UIKit.h> + +@protocol OmniboxIcon; +@protocol FaviconRetriever; +@protocol ImageRetriever; + +// This class is used to display |OmniboxIcon|s. It handles the multiple image +// views neceesary to get the correct compositing behavior. +@interface OmniboxIconView : UIView + +// Used to fetch favicons. +@property(nonatomic, weak) id<FaviconRetriever> faviconRetriever; + +@property(nonatomic, weak) id<ImageRetriever> imageRetriever; + +- (void)prepareForReuse; + +- (void)setOmniboxIcon:(id<OmniboxIcon>)omniboxIcon; + +@end + +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_VIEW_H_
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_icon_view.mm b/ios/chrome/browser/ui/omnibox/omnibox_icon_view.mm new file mode 100644 index 0000000..f808f3c0 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_icon_view.mm
@@ -0,0 +1,150 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/omnibox/omnibox_icon_view.h" + +#import "ios/chrome/browser/ui/omnibox/favicon_retriever.h" +#import "ios/chrome/browser/ui/omnibox/image_retriever.h" +#import "ios/chrome/browser/ui/omnibox/omnibox_icon.h" +#import "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface OmniboxIconView () + +@property(nonatomic, strong) UIImageView* backgroundImageView; +@property(nonatomic, strong) UIImageView* mainImageView; +@property(nonatomic, strong) UIImageView* overlayImageView; + +@end + +@implementation OmniboxIconView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _backgroundImageView = [[UIImageView alloc] initWithImage:nil]; + _backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO; + + _mainImageView = [[UIImageView alloc] initWithImage:nil]; + _mainImageView.translatesAutoresizingMaskIntoConstraints = NO; + + _overlayImageView = [[UIImageView alloc] initWithImage:nil]; + _overlayImageView.translatesAutoresizingMaskIntoConstraints = NO; + + UIImageView* mask = [[UIImageView alloc] + initWithImage:[UIImage imageNamed:@"background_solid"]]; + self.maskView = mask; + } + return self; +} + +- (void)prepareForReuse { + self.backgroundImageView.image = nil; + self.mainImageView.image = nil; + [self.overlayImageView removeFromSuperview]; + self.mainImageView.contentMode = UIViewContentModeCenter; +} + +// Override layoutSubviews to set the frame of the the mask +// correctly. It should be the same size as the view itself. +- (void)layoutSubviews { + [super layoutSubviews]; + self.maskView.frame = self.bounds; +} + +- (void)setupLayout { + [self addSubview:self.backgroundImageView]; + [self addSubview:self.mainImageView]; + + self.mainImageView.contentMode = UIViewContentModeCenter; + + [NSLayoutConstraint activateConstraints:@[ + [self.mainImageView.leadingAnchor + constraintEqualToAnchor:self.leadingAnchor], + [self.mainImageView.trailingAnchor + constraintEqualToAnchor:self.trailingAnchor], + [self.mainImageView.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.mainImageView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], + + [self.backgroundImageView.leadingAnchor + constraintEqualToAnchor:self.leadingAnchor], + [self.backgroundImageView.trailingAnchor + constraintEqualToAnchor:self.trailingAnchor], + [self.backgroundImageView.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.backgroundImageView.bottomAnchor + constraintEqualToAnchor:self.bottomAnchor], + ]]; +} + +- (void)addOverlayImageView { + [self addSubview:self.overlayImageView]; + [NSLayoutConstraint activateConstraints:@[ + [self.overlayImageView.leadingAnchor + constraintEqualToAnchor:self.leadingAnchor], + [self.overlayImageView.trailingAnchor + constraintEqualToAnchor:self.trailingAnchor], + [self.overlayImageView.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.overlayImageView.bottomAnchor + constraintEqualToAnchor:self.bottomAnchor], + ]]; +} + +- (void)setOmniboxIcon:(id<OmniboxIcon>)omniboxIcon { + // Setup the view layout the first time the cell is setup. + if (self.subviews.count == 0) { + [self setupLayout]; + } + + switch (omniboxIcon.iconType) { + case OmniboxIconTypeImage: { + self.mainImageView.contentMode = UIViewContentModeScaleAspectFill; + __weak OmniboxIconView* weakSelf = self; + GURL imageURL = omniboxIcon.imageURL; + [self.imageRetriever fetchImage:imageURL + completion:^(UIImage* image) { + // Make sure cell is still displaying the same + // suggestion. + if (omniboxIcon.imageURL != imageURL) { + return; + } + [weakSelf addOverlayImageView]; + weakSelf.overlayImageView.image = + omniboxIcon.overlayImage; + weakSelf.overlayImageView.tintColor = + omniboxIcon.overlayImageTintColor; + weakSelf.mainImageView.image = image; + }]; + break; + } + case OmniboxIconTypeFavicon: { + // Set fallback icon + self.mainImageView.image = omniboxIcon.iconImage; + + // Load favicon. + GURL pageURL = omniboxIcon.imageURL; + __weak OmniboxIconView* weakSelf = self; + [self.faviconRetriever fetchFavicon:pageURL + completion:^(UIImage* image) { + if (pageURL == omniboxIcon.imageURL) { + weakSelf.mainImageView.image = image; + } + }]; + break; + } + case OmniboxIconTypeSuggestionIcon: + self.mainImageView.image = omniboxIcon.iconImage; + break; + } + self.mainImageView.tintColor = omniboxIcon.iconImageTintColor; + + self.backgroundImageView.image = omniboxIcon.backgroundImage; + self.backgroundImageView.tintColor = omniboxIcon.backgroundImageTintColor; + + [self layoutIfNeeded]; +} + +@end
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn index 34e4bf6..004f0bc 100644 --- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -29,6 +29,7 @@ "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/ntp:util", + "//ios/chrome/browser/ui/omnibox:omnibox_protocols", "//ios/chrome/browser/ui/omnibox:omnibox_util", "//ios/chrome/browser/ui/omnibox/popup/shortcuts", "//ios/chrome/browser/ui/toolbar/buttons", @@ -48,8 +49,6 @@ sources = [ "autocomplete_result_consumer.h", "autocomplete_suggestion.h", - "favicon_retriever.h", - "image_retriever.h", "omnibox_popup_base_view_controller+internal.h", "omnibox_popup_base_view_controller.h", "omnibox_popup_base_view_controller.mm", @@ -76,6 +75,8 @@ "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/elements", "//ios/chrome/browser/ui/omnibox:omnibox_popup_shared", + "//ios/chrome/browser/ui/omnibox:omnibox_protocols", + "//ios/chrome/browser/ui/omnibox:omnibox_ui", "//ios/chrome/browser/ui/toolbar/buttons", "//ios/chrome/browser/ui/toolbar/public", "//ios/chrome/browser/ui/util", @@ -92,19 +93,16 @@ "autocomplete_match_formatter.mm", ] deps = [ + ":popup_ui", "//base", "//components/omnibox/browser", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/ui:feature_flags", + "//ios/chrome/browser/ui/omnibox:omnibox_ui_internal", "//ios/chrome/browser/ui/omnibox:omnibox_util", "//ios/chrome/browser/ui/util", "//ios/third_party/material_components_ios", ] - - # Temporary until ios_internal CL is submitted - public_deps = [ - ":popup_ui", - ] configs += [ "//build/config/compiler:enable_arc" ] }
diff --git a/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm b/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm index e9c2b51..edb3c61 100644 --- a/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm +++ b/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm
@@ -10,6 +10,7 @@ #include "base/strings/utf_string_conversions.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/suggestion_answer.h" +#import "ios/chrome/browser/ui/omnibox/omnibox_icon_formatter.h" #import "ios/chrome/browser/ui/omnibox/omnibox_util.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/ui_util.h" @@ -144,6 +145,10 @@ return detailAttributedText; } +- (id<OmniboxIcon>)icon { + return [[OmniboxIconFormatter alloc] initWithMatch:_match]; +} + - (NSInteger)numberOfLines { // Answers specify their own limit on the number of lines to show but are // additionally capped here at 3 to guard against unreasonable values. @@ -189,6 +194,7 @@ color:suggestionTextColor dimColor:dimColor]; } + return attributedText; }
diff --git a/ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h b/ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h index 58bd208..c9dabb23 100644 --- a/ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h +++ b/ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h
@@ -8,6 +8,7 @@ #import <UIKit/UIKit.h> class GURL; +@protocol OmniboxIcon; // Represents an autocomplete suggestion in UI. @protocol AutocompleteSuggestion <NSObject> @@ -42,6 +43,8 @@ // Page URL to be used to retrieve the favicon. - (GURL)faviconPageURL; +- (id<OmniboxIcon>)icon; + @end #endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_AUTOCOMPLETE_SUGGESTION_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/image_retriever.h b/ios/chrome/browser/ui/omnibox/popup/image_retriever.h deleted file mode 100644 index 0918c2f..0000000 --- a/ios/chrome/browser/ui/omnibox/popup/image_retriever.h +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_IMAGE_RETRIEVER_H_ -#define IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_IMAGE_RETRIEVER_H_ - -@protocol ImageRetriever <NSObject> -- (void)fetchImage:(GURL)imageURL completion:(void (^)(UIImage*))completion; -@end - -#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_IMAGE_RETRIEVER_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h index 411f1141..e0771a8 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h
@@ -9,7 +9,6 @@ #import "ios/chrome/browser/ui/commands/omnibox_suggestion_commands.h" #import "ios/chrome/browser/ui/omnibox/popup/autocomplete_result_consumer.h" -#import "ios/chrome/browser/ui/omnibox/popup/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h" #include "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h index 280d7bc..9095dad 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h
@@ -7,7 +7,6 @@ #import "ios/chrome/browser/ui/commands/omnibox_suggestion_commands.h" #import "ios/chrome/browser/ui/omnibox/popup/autocomplete_result_consumer.h" -#import "ios/chrome/browser/ui/omnibox/popup/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h" @interface OmniboxPopupLegacyViewController : OmniboxPopupBaseViewController
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.mm index 94df374..4de334f 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.mm
@@ -9,8 +9,8 @@ #include "base/ios/ios_util.h" #include "base/metrics/histogram_macros.h" +#import "ios/chrome/browser/ui/omnibox/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/omnibox_constants.h" -#import "ios/chrome/browser/ui/omnibox/popup/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_truncating_label.h" #import "ios/chrome/browser/ui/omnibox/popup/self_sizing_table_view.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h index 4968d21..aa3ddb2 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h
@@ -8,9 +8,9 @@ #import <UIKit/UIKit.h> #include "components/omnibox/browser/autocomplete_result.h" +#import "ios/chrome/browser/ui/omnibox/favicon_retriever.h" +#import "ios/chrome/browser/ui/omnibox/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/autocomplete_result_consumer.h" -#import "ios/chrome/browser/ui/omnibox/popup/favicon_retriever.h" -#import "ios/chrome/browser/ui/omnibox/popup/image_retriever.h" #include "ui/base/window_open_disposition.h" @protocol BrowserCommands;
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.h index 95e1c5d89..74d9cd4 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.h
@@ -10,6 +10,7 @@ @protocol AutocompleteSuggestion; @protocol FaviconRetriever; @protocol ImageRetriever; +@class OmniboxIconView; @class OmniboxPopupRowCell; namespace { @@ -54,7 +55,7 @@ @property(nonatomic, assign) BOOL showsSeparator; // Image view for the leading image. -@property(nonatomic, strong, readonly) UIImageView* leadingImageView; +@property(nonatomic, strong, readonly) OmniboxIconView* leadingIconView; @end
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm index c30c6f6..56af0f9 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm
@@ -9,9 +9,8 @@ #include "components/omnibox/common/omnibox_features.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/elements/extended_touch_target_button.h" +#import "ios/chrome/browser/ui/omnibox/omnibox_icon_view.h" #import "ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h" -#import "ios/chrome/browser/ui/omnibox/popup/favicon_retriever.h" -#import "ios/chrome/browser/ui/omnibox/popup/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_truncating_label.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" #import "ios/chrome/browser/ui/util/named_guide.h" @@ -85,9 +84,8 @@ _detailAnswerLabel.translatesAutoresizingMaskIntoConstraints = NO; _detailAnswerLabel.lineBreakMode = NSLineBreakByTruncatingTail; - _leadingImageView = [[UIImageView alloc] initWithImage:nil]; - _leadingImageView.translatesAutoresizingMaskIntoConstraints = NO; - _leadingImageView.contentMode = UIViewContentModeCenter; + _leadingIconView = [[OmniboxIconView alloc] init]; + _leadingIconView.translatesAutoresizingMaskIntoConstraints = NO; _trailingButton = [ExtendedTouchTargetButton buttonWithType:UIButtonTypeCustom]; @@ -99,7 +97,6 @@ _separator = [[UIView alloc] initWithFrame:CGRectZero]; _separator.translatesAutoresizingMaskIntoConstraints = NO; - _separator.backgroundColor = [MDCPalette.cr_greyPalette tint200]; _separator.hidden = YES; _incognito = NO; @@ -117,12 +114,39 @@ } } +#pragma mark - Property setter/getters + +- (void)setImageRetriever:(id<ImageRetriever>)imageRetriever { + _imageRetriever = imageRetriever; + self.leadingIconView.imageRetriever = imageRetriever; +} + +- (void)setFaviconRetriever:(id<FaviconRetriever>)faviconRetriever { + _faviconRetriever = faviconRetriever; + self.leadingIconView.faviconRetriever = faviconRetriever; +} + +- (void)setOmniboxSemanticContentAttribute: + (UISemanticContentAttribute)omniboxSemanticContentAttribute { + _omniboxSemanticContentAttribute = omniboxSemanticContentAttribute; + self.contentView.semanticContentAttribute = omniboxSemanticContentAttribute; + self.textStackView.semanticContentAttribute = omniboxSemanticContentAttribute; +} + +- (BOOL)showsSeparator { + return self.separator.hidden; +} + +- (void)setShowsSeparator:(BOOL)showsSeparator { + self.separator.hidden = !showsSeparator; +} + #pragma mark - Layout // Setup the layout of the cell initially. This only adds the elements that are // always in the cell. - (void)setupLayout { - [self.contentView addSubview:self.leadingImageView]; + [self.contentView addSubview:self.leadingIconView]; [self.contentView addSubview:self.textStackView]; [self.contentView addSubview:self.separator]; @@ -131,15 +155,15 @@ [self.contentView.heightAnchor constraintGreaterThanOrEqualToConstant:kOmniboxPopupCellMinimumHeight], - // Position leadingImageView at the leading edge of the view. + // Position leadingIconView at the leading edge of the view. // Leave the horizontal position unconstrained as that will be added via a // layout guide once the cell has been added to the view hierarchy. - [self.leadingImageView.heightAnchor - constraintEqualToAnchor:self.leadingImageView.widthAnchor], - [self.leadingImageView.centerYAnchor + [self.leadingIconView.heightAnchor + constraintEqualToAnchor:self.leadingIconView.widthAnchor], + [self.leadingIconView.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor], - // Position textStackView "after" leadingImageView. The horizontal position + // Position textStackView "after" leadingIconView. The horizontal position // is actually left off because it will be added via a // layout guide once the cell has been added to the view hierarchy. // Top space should be at least the given top margin, but can be more if @@ -223,9 +247,9 @@ stackViewToCellTrailing.priority = highest; [NSLayoutConstraint activateConstraints:@[ - [self.leadingImageView.centerXAnchor + [self.leadingIconView.centerXAnchor constraintEqualToAnchor:imageLayoutGuide.centerXAnchor], - [self.leadingImageView.widthAnchor + [self.leadingIconView.widthAnchor constraintEqualToAnchor:imageLayoutGuide.widthAnchor], [self.textStackView.leadingAnchor constraintEqualToAnchor:textLayoutGuide.leadingAnchor], @@ -235,21 +259,6 @@ ]]; } -- (void)setOmniboxSemanticContentAttribute: - (UISemanticContentAttribute)omniboxSemanticContentAttribute { - _omniboxSemanticContentAttribute = omniboxSemanticContentAttribute; - self.contentView.semanticContentAttribute = omniboxSemanticContentAttribute; - self.textStackView.semanticContentAttribute = omniboxSemanticContentAttribute; -} - -- (BOOL)showsSeparator { - return self.separator.hidden; -} - -- (void)setShowsSeparator:(BOOL)showsSeparator { - self.separator.hidden = !showsSeparator; -} - - (void)prepareForReuse { [super prepareForReuse]; @@ -263,7 +272,7 @@ self.detailTruncatingLabel.attributedText = nil; self.detailAnswerLabel.attributedText = nil; - self.leadingImageView.image = nil; + [self.leadingIconView prepareForReuse]; // Remove optional views. [self.trailingButton setImage:nil forState:UIControlStateNormal]; @@ -289,9 +298,9 @@ self.suggestion = suggestion; self.incognito = incognito; - self.separator.backgroundColor = self.incognito - ? [MDCPalette.cr_greyPalette tint700] - : [MDCPalette.cr_greyPalette tint200]; + self.separator.backgroundColor = + self.incognito ? [MDCPalette.cr_greyPalette tint700] + : [UIColor.blackColor colorWithAlphaComponent:0.12]; self.textTruncatingLabel.attributedText = self.suggestion.text; @@ -307,63 +316,13 @@ } } - [self setupLeadingImageView]; + [self.leadingIconView setOmniboxIcon:self.suggestion.icon]; if (self.suggestion.isAppendable || self.suggestion.isTabMatch) { [self setupTrailingButton]; } } -// Populate the leading image view with the correct image and color. -- (void)setupLeadingImageView { - if (self.suggestion.hasImage) { - [self setupLeadingImageViewForAnswerImage]; - } else { - [self setupLeadingImageViewForIconAndFavicon]; - } -} - -// Populate the leading image view in the case where the image should be an -// image from answers-in-suggest or rich entity. -- (void)setupLeadingImageViewForAnswerImage { - self.leadingImageView.contentMode = UIViewContentModeScaleAspectFill; - __weak OmniboxPopupRowCell* weakSelf = self; - GURL imageURL = self.suggestion.imageURL; - [self.imageRetriever fetchImage:imageURL - completion:^(UIImage* image) { - // Make sure cell is still displaying the same - // suggestion. - if (weakSelf.suggestion.imageURL != imageURL) { - return; - } - weakSelf.leadingImageView.image = image; - }]; - self.leadingImageView.backgroundColor = nil; -} - -// Populate the leading image view in the case where the image should be a -// standard suggestion icon or a favicon. -- (void)setupLeadingImageViewForIconAndFavicon { - self.leadingImageView.contentMode = UIViewContentModeCenter; - self.leadingImageView.image = self.suggestion.suggestionTypeIcon; - - // Attempt to load favicon. - GURL pageURL = self.suggestion.faviconPageURL; - __weak OmniboxPopupRowCell* weakSelf = self; - [self.faviconRetriever fetchFavicon:pageURL - completion:^(UIImage* image) { - if (pageURL == weakSelf.suggestion.faviconPageURL) - weakSelf.leadingImageView.image = image; - }]; - - self.leadingImageView.backgroundColor = - self.incognito ? [UIColor colorWithWhite:1 alpha:0.05] - : [UIColor colorWithWhite:0 alpha:0.03]; - self.leadingImageView.tintColor = self.incognito - ? [UIColor colorWithWhite:1 alpha:0.4] - : [UIColor colorWithWhite:0 alpha:0.33]; -} - // Setup the trailing button. This includes both setting up the button's layout // and popuplating it with the correct image and color. - (void)setupTrailingButton {
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm index 3e4dd1c..e175d5e 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
@@ -100,13 +100,13 @@ OmniboxPopupRowCell* cell = [self.tableView dequeueReusableCellWithIdentifier:OmniboxPopupRowCellReuseIdentifier forIndexPath:indexPath]; + cell.faviconRetriever = self.faviconRetriever; + cell.imageRetriever = self.imageRetriever; [cell setupWithAutocompleteSuggestion:self.currentResult[indexPath.row] incognito:self.incognito]; cell.showsSeparator = (NSUInteger)indexPath.row < self.currentResult.count - 1; cell.delegate = self; - cell.faviconRetriever = self.faviconRetriever; - cell.imageRetriever = self.imageRetriever; return cell; }
diff --git a/ios/chrome/browser/ui/presenters/BUILD.gn b/ios/chrome/browser/ui/presenters/BUILD.gn index 76d19b09..585e8e5 100644 --- a/ios/chrome/browser/ui/presenters/BUILD.gn +++ b/ios/chrome/browser/ui/presenters/BUILD.gn
@@ -7,6 +7,8 @@ sources = [ "contained_presenter.h", "contained_presenter_delegate.h", + "non_modal_view_controller_presenter.h", + "non_modal_view_controller_presenter.mm", "vertical_animation_container.h", "vertical_animation_container.mm", ]
diff --git a/ios/chrome/browser/ui/alert_view_controller/non_modal_view_controller_presenter.h b/ios/chrome/browser/ui/presenters/non_modal_view_controller_presenter.h similarity index 68% rename from ios/chrome/browser/ui/alert_view_controller/non_modal_view_controller_presenter.h rename to ios/chrome/browser/ui/presenters/non_modal_view_controller_presenter.h index 32d4053..4c00e1f 100644 --- a/ios/chrome/browser/ui/alert_view_controller/non_modal_view_controller_presenter.h +++ b/ios/chrome/browser/ui/presenters/non_modal_view_controller_presenter.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_ALERT_VIEW_CONTROLLER_NON_MODAL_VIEW_CONTROLLER_PRESENTER_H_ -#define IOS_CHROME_BROWSER_UI_ALERT_VIEW_CONTROLLER_NON_MODAL_VIEW_CONTROLLER_PRESENTER_H_ +#ifndef IOS_CHROME_BROWSER_UI_PRESENTERS_NON_MODAL_VIEW_CONTROLLER_PRESENTER_H_ +#define IOS_CHROME_BROWSER_UI_PRESENTERS_NON_MODAL_VIEW_CONTROLLER_PRESENTER_H_ #import <Foundation/Foundation.h> @@ -16,4 +16,4 @@ @interface NonModalViewControllerPresenter : NSObject <ContainedPresenter> @end -#endif // IOS_CHROME_BROWSER_UI_ALERT_VIEW_CONTROLLER_NON_MODAL_VIEW_CONTROLLER_PRESENTER_H_ +#endif // IOS_CHROME_BROWSER_UI_PRESENTERS_NON_MODAL_VIEW_CONTROLLER_PRESENTER_H_
diff --git a/ios/chrome/browser/ui/alert_view_controller/non_modal_view_controller_presenter.mm b/ios/chrome/browser/ui/presenters/non_modal_view_controller_presenter.mm similarity index 97% rename from ios/chrome/browser/ui/alert_view_controller/non_modal_view_controller_presenter.mm rename to ios/chrome/browser/ui/presenters/non_modal_view_controller_presenter.mm index 1ff2ad3..38422a9 100644 --- a/ios/chrome/browser/ui/alert_view_controller/non_modal_view_controller_presenter.mm +++ b/ios/chrome/browser/ui/presenters/non_modal_view_controller_presenter.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/alert_view_controller/non_modal_view_controller_presenter.h" +#import "ios/chrome/browser/ui/presenters/non_modal_view_controller_presenter.h" #include "base/logging.h" #import "ios/chrome/browser/ui/presenters/contained_presenter_delegate.h"
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn index b86c79f..1fe6f1de 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
@@ -29,6 +29,7 @@ "//components/browsing_data/core", "//components/feature_engagement/public", "//components/history/core/browser", + "//components/prefs/ios", "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/browser",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_collection_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_collection_view_controller.mm index 22e7f2b7b..4a60454 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_collection_view_controller.mm
@@ -210,8 +210,7 @@ case ItemTypeTimeRange: { UIViewController* controller = [[TimeRangeSelectorTableViewController alloc] - initWithPrefs:_browserState->GetPrefs() - delegate:self.dataManager]; + initWithPrefs:_browserState->GetPrefs()]; [self.navigationController pushViewController:controller animated:YES]; break; }
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.h b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.h index 96ae66e..119e795e 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.h +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.h
@@ -5,15 +5,18 @@ #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CLEAR_BROWSING_DATA_CLEAR_BROWSING_DATA_MANAGER_H_ #define IOS_CHROME_BROWSER_UI_SETTINGS_CLEAR_BROWSING_DATA_CLEAR_BROWSING_DATA_MANAGER_H_ -#import <Foundation/Foundation.h> +#include "components/browsing_data/core/counters/browsing_data_counter.h" +#import "ios/chrome/browser/ui/list_model/list_model.h" -#import "ios/chrome/browser/browsing_data/browsing_data_remover_observer_bridge.h" -#import "ios/chrome/browser/ui/settings/clear_browsing_data/browsing_data_counter_wrapper_producer.h" -#import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_consumer.h" -#import "ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.h" +namespace ios { +class ChromeBrowserState; +} +class BrowsingDataRemover; +enum class BrowsingDataRemoveMask; -@class ListModel; @class ActionSheetCoordinator; +@class BrowsingDataCounterWrapperProducer; +@protocol ClearBrowsingDataConsumer; @protocol CollectionViewFooterLinkDelegate; // Clear Browswing Data Section Identifiers. @@ -70,9 +73,7 @@ // Manager that serves as the bulk of the logic for // ClearBrowsingDataConsumer. -@interface ClearBrowsingDataManager - : NSObject <BrowsingDataRemoverObserving, - TimeRangeSelectorTableViewControllerDelegate> +@interface ClearBrowsingDataManager : NSObject // The manager's consumer. @property(nonatomic, weak) id<ClearBrowsingDataConsumer> consumer;
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm index 6fe461c..4e55db2 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
@@ -14,6 +14,7 @@ #include "components/feature_engagement/public/tracker.h" #include "components/google/core/common/google_util.h" #include "components/history/core/browser/web_history_service.h" +#include "components/prefs/ios/pref_observer_bridge.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" #include "components/sync/driver/sync_service.h" @@ -24,6 +25,7 @@ #include "ios/chrome/browser/browsing_data/browsing_data_remove_mask.h" #include "ios/chrome/browser/browsing_data/browsing_data_remover.h" #include "ios/chrome/browser/browsing_data/browsing_data_remover_factory.h" +#import "ios/chrome/browser/browsing_data/browsing_data_remover_observer_bridge.h" #include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/feature_engagement/tracker_factory.h" #include "ios/chrome/browser/history/web_history_service_factory.h" @@ -40,7 +42,10 @@ #import "ios/chrome/browser/ui/settings/cells/clear_browsing_data_item.h" #import "ios/chrome/browser/ui/settings/cells/legacy/legacy_settings_detail_item.h" #import "ios/chrome/browser/ui/settings/cells/table_view_clear_browsing_data_item.h" +#import "ios/chrome/browser/ui/settings/clear_browsing_data/browsing_data_counter_wrapper_producer.h" +#import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_consumer.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_ui_constants.h" +#import "ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_detail_icon_item.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h" @@ -93,9 +98,14 @@ @"clear_browsing_data_autofill", }; -@interface ClearBrowsingDataManager () { +@interface ClearBrowsingDataManager () <BrowsingDataRemoverObserving, + PrefObserverDelegate> { // Access to the kDeleteTimePeriod preference. IntegerPrefMember _timeRangePref; + // Pref observer to track changes to prefs. + std::unique_ptr<PrefObserverBridge> _prefObserverBridge; + // Registrar for pref changes notifications. + PrefChangeRegistrar _prefChangeRegistrar; // Observer for browsing data removal events and associated ScopedObserver // used to track registration with BrowsingDataRemover. They both may be @@ -175,6 +185,11 @@ ScopedObserver<BrowsingDataRemover, BrowsingDataRemoverObserver>>( observer_.get()); scoped_observer_->Add(remover); + + _prefChangeRegistrar.Init(_browserState->GetPrefs()); + _prefObserverBridge.reset(new PrefObserverBridge(self)); + _prefObserverBridge->ObserveChangesForPreference( + browsing_data::prefs::kDeleteTimePeriod, &_prefChangeRegistrar); } } return self; @@ -815,11 +830,10 @@ [self.consumer updateCellsForItem:footerItem]; } -#pragma mark TimeRangeSelectorTableViewControllerDelegate +#pragma mark - PrefObserverDelegate -- (void)timeRangeSelectorViewController: - (TimeRangeSelectorTableViewController*)tableViewController - didSelectTimePeriod:(browsing_data::TimePeriod)timePeriod { +- (void)onPreferenceChanged:(const std::string&)preferenceName { + DCHECK(preferenceName == browsing_data::prefs::kDeleteTimePeriod); NSString* detailText = [TimeRangeSelectorTableViewController timePeriodLabelForPrefs:self.browserState->GetPrefs()]; if (self.listType == ClearBrowsingDataListType::kListTypeCollectionView) {
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager_unittest.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager_unittest.mm index 42c14b5..15f45df 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager_unittest.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager_unittest.mm
@@ -20,6 +20,7 @@ #include "ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.h" #include "ios/chrome/browser/sync/profile_sync_service_factory.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data/fake_browsing_data_counter_wrapper_producer.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_icon_item.h" #import "ios/chrome/browser/ui/table_view/table_view_model.h" #include "ios/web/public/test/test_web_thread_bundle.h" #include "services/identity/public/cpp/identity_test_environment.h" @@ -64,13 +65,16 @@ manager_ = [[ClearBrowsingDataManager alloc] initWithBrowserState:browser_state_.get() listType:ClearBrowsingDataListType:: - kListTypeCollectionView + kListTypeTableView browsingDataRemover:remover_.get() browsingDataCounterWrapperProducer: [[FakeBrowsingDataCounterWrapperProducer alloc] init]]; test_sync_service_ = static_cast<syncer::TestSyncService*>( ProfileSyncServiceFactory::GetForBrowserState(browser_state_.get())); + + time_range_pref_.Init(browsing_data::prefs::kDeleteTimePeriod, + browser_state_->GetPrefs()); } identity::IdentityTestEnvironment* identity_test_env() { @@ -86,23 +90,24 @@ ClearBrowsingDataManager* manager_; syncer::TestSyncService* test_sync_service_; web::TestWebThreadBundle thread_bundle_; + IntegerPrefMember time_range_pref_; }; // Tests model is set up with all appropriate items and sections. TEST_F(ClearBrowsingDataManagerTest, TestModel) { [manager_ loadModel:model_]; - int section_offset = 0; + EXPECT_EQ(3, [model_ numberOfSections]); if (IsNewClearBrowsingDataUIEnabled()) { - EXPECT_EQ(4, [model_ numberOfSections]); + // Time Range selector. EXPECT_EQ(1, [model_ numberOfItemsInSection:0]); - section_offset = 1; + EXPECT_EQ(5, [model_ numberOfItemsInSection:1]); } else { - EXPECT_EQ(3, [model_ numberOfSections]); + EXPECT_EQ(5, [model_ numberOfItemsInSection:0]); + // CBD button. + EXPECT_EQ(1, [model_ numberOfItemsInSection:1]); } - EXPECT_EQ(5, [model_ numberOfItemsInSection:0 + section_offset]); - EXPECT_EQ(1, [model_ numberOfItemsInSection:1 + section_offset]); - EXPECT_EQ(1, [model_ numberOfItemsInSection:2 + section_offset]); + EXPECT_EQ(1, [model_ numberOfItemsInSection:2]); } // Tests model is set up with correct number of items and sections if signed in @@ -116,19 +121,18 @@ [manager_ loadModel:model_]; - int section_offset = 0; + EXPECT_EQ(4, [model_ numberOfSections]); if (IsNewClearBrowsingDataUIEnabled()) { - EXPECT_EQ(5, [model_ numberOfSections]); + // Time Range selector. EXPECT_EQ(1, [model_ numberOfItemsInSection:0]); - section_offset = 1; + EXPECT_EQ(5, [model_ numberOfItemsInSection:1]); } else { - EXPECT_EQ(4, [model_ numberOfSections]); + EXPECT_EQ(5, [model_ numberOfItemsInSection:0]); + // CBD button. + EXPECT_EQ(1, [model_ numberOfItemsInSection:1]); } - - EXPECT_EQ(5, [model_ numberOfItemsInSection:0 + section_offset]); - EXPECT_EQ(1, [model_ numberOfItemsInSection:1 + section_offset]); - EXPECT_EQ(1, [model_ numberOfItemsInSection:2 + section_offset]); - EXPECT_EQ(1, [model_ numberOfItemsInSection:3 + section_offset]); + EXPECT_EQ(1, [model_ numberOfItemsInSection:2]); + EXPECT_EQ(1, [model_ numberOfItemsInSection:3]); } TEST_F(ClearBrowsingDataManagerTest, TestCacheCounterFormattingForAllTime) { @@ -198,4 +202,25 @@ } } +TEST_F(ClearBrowsingDataManagerTest, TestOnPreferenceChanged) { + // Only works with new UI + if (!IsNewClearBrowsingDataUIEnabled()) { + return; + } + ASSERT_EQ("en", GetApplicationContext()->GetApplicationLocale()); + [manager_ loadModel:model_]; + NSArray* timeRangeItems = + [model_ itemsInSectionWithIdentifier:SectionIdentifierTimeRange]; + ASSERT_EQ(1UL, timeRangeItems.count); + TableViewDetailIconItem* timeRangeItem = timeRangeItems.firstObject; + ASSERT_TRUE([timeRangeItem isKindOfClass:[TableViewDetailIconItem class]]); + + // Changes of Time Range should trigger updates on Time Range item's + // detailText. + time_range_pref_.SetValue(2); + EXPECT_NSEQ(@"Past Week", timeRangeItem.detailText); + time_range_pref_.SetValue(3); + EXPECT_NSEQ(@"Last 4 Weeks", timeRangeItem.detailText); +} + } // namespace
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm index 5995f293..ec383d5 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm
@@ -18,9 +18,11 @@ #import "ios/chrome/browser/ui/elements/chrome_activity_overlay_coordinator.h" #include "ios/chrome/browser/ui/settings/cells/clear_browsing_data_constants.h" #import "ios/chrome/browser/ui/settings/cells/table_view_clear_browsing_data_item.h" +#import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_consumer.h" #include "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_local_commands.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_ui_constants.h" +#import "ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h" @@ -270,6 +272,20 @@ #pragma mark - UITableViewDelegate +- (CGFloat)tableView:(UITableView*)tableView + heightForHeaderInSection:(NSInteger)section { + NSInteger sectionIdentifier = + [self.tableViewModel sectionIdentifierForSection:section]; + switch (sectionIdentifier) { + case SectionIdentifierGoogleAccount: + case SectionIdentifierClearSyncAndSavedSiteData: + case SectionIdentifierSavedSiteData: + return 5; + default: + return [super tableView:tableView heightForHeaderInSection:section]; + } +} + - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { if (!IsNewClearBrowsingDataUIEnabled()) { @@ -281,8 +297,7 @@ case ItemTypeTimeRange: { UIViewController* controller = [[TimeRangeSelectorTableViewController alloc] - initWithPrefs:self.browserState->GetPrefs() - delegate:self.dataManager]; + initWithPrefs:self.browserState->GetPrefs()]; [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; [self.navigationController pushViewController:controller animated:YES]; break;
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.h b/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.h index e4a5eafe..84ecf95 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.h +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.h
@@ -5,28 +5,15 @@ #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CLEAR_BROWSING_DATA_TIME_RANGE_SELECTOR_TABLE_VIEW_CONTROLLER_H_ #define IOS_CHROME_BROWSER_UI_SETTINGS_CLEAR_BROWSING_DATA_TIME_RANGE_SELECTOR_TABLE_VIEW_CONTROLLER_H_ -#include "components/browsing_data/core/browsing_data_utils.h" #import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" class PrefService; -@class TimeRangeSelectorTableViewController; - -@protocol TimeRangeSelectorTableViewControllerDelegate <NSObject> - -// Informs the delegate that |timePeriod| was selected. -- (void)timeRangeSelectorViewController: - (TimeRangeSelectorTableViewController*)tableViewController - didSelectTimePeriod:(browsing_data::TimePeriod)timePeriod; - -@end // Table view for time range selection. @interface TimeRangeSelectorTableViewController : SettingsRootTableViewController -- (instancetype)initWithPrefs:(PrefService*)prefs - delegate:(id<TimeRangeSelectorTableViewControllerDelegate>) - delegate NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithPrefs:(PrefService*)prefs NS_DESIGNATED_INITIALIZER; - (instancetype)initWithTableViewStyle:(UITableViewStyle)style appBarStyle:
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.mm index 932a52df..ab34f16 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.mm
@@ -6,12 +6,12 @@ #import "base/mac/foundation_util.h" #include "base/stl_util.h" +#include "components/browsing_data/core/browsing_data_utils.h" #include "components/browsing_data/core/pref_names.h" #include "components/prefs/pref_member.h" #include "components/prefs/pref_service.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" -#include "ios/chrome/browser/ui/ui_feature_flags.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -52,23 +52,17 @@ IntegerPrefMember _timeRangePref; } -@property(nonatomic, weak) id<TimeRangeSelectorTableViewControllerDelegate> - delegate; - @end @implementation TimeRangeSelectorTableViewController #pragma mark Initialization -- (instancetype)initWithPrefs:(PrefService*)prefs - delegate:(id<TimeRangeSelectorTableViewControllerDelegate>) - delegate { +- (instancetype)initWithPrefs:(PrefService*)prefs { UITableViewStyle style = UITableViewStylePlain; self = [super initWithTableViewStyle:style appBarStyle:ChromeTableViewControllerStyleNoAppBar]; if (self) { - _delegate = delegate; self.title = l10n_util::GetNSString( IDS_IOS_CLEAR_BROWSING_DATA_TIME_RANGE_SELECTOR_TITLE); _timeRangePref.Init(browsing_data::prefs::kDeleteTimePeriod, prefs); @@ -156,10 +150,6 @@ DCHECK_LE(timePeriod, static_cast<int>(browsing_data::TimePeriod::TIME_PERIOD_LAST)); [self updatePrefValue:timePeriod]; - [self.delegate - timeRangeSelectorViewController:self - didSelectTimePeriod:static_cast<browsing_data::TimePeriod>( - timePeriod)]; [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; }
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller_unittest.mm index ab08f7c..b35cb68b 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller_unittest.mm
@@ -39,17 +39,13 @@ void SetUp() override { ChromeTableViewControllerTest::SetUp(); pref_service_ = CreateLocalState(); - delegate_ = [OCMockObject - mockForProtocol:@protocol( - TimeRangeSelectorTableViewControllerDelegate)]; CreateController(); } ChromeTableViewController* InstantiateController() override { time_range_selector_controller_ = [[TimeRangeSelectorTableViewController alloc] - initWithPrefs:pref_service_.get() - delegate:delegate_]; + initWithPrefs:pref_service_.get()]; return time_range_selector_controller_; } @@ -72,7 +68,6 @@ base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<PrefService> pref_service_; - id delegate_; TimeRangeSelectorTableViewController* time_range_selector_controller_; }; @@ -118,23 +113,4 @@ } } -TEST_F(TimeRangeSelectorTableViewControllerTest, TestUpdatePrefValue) { - CheckController(); - UITableView* tableView = time_range_selector_controller_.tableView; - for (NSInteger checkedItem = 0; checkedItem < kNumberOfItems; ++checkedItem) { - NSIndexPath* indexPath = [NSIndexPath indexPathForRow:checkedItem - inSection:0]; - [[delegate_ expect] - timeRangeSelectorViewController:time_range_selector_controller_ - didSelectTimePeriod:static_cast<browsing_data::TimePeriod>( - checkedItem)]; - [time_range_selector_controller_ tableView:tableView - didSelectRowAtIndexPath:indexPath]; - EXPECT_EQ( - pref_service_->GetInteger(browsing_data::prefs::kDeleteTimePeriod), - checkedItem); - EXPECT_OCMOCK_VERIFY(delegate_); - } -} - } // namespace
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm index 8a7964c..1d9b40e 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -45,6 +45,7 @@ #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/web/public/web_state/web_state.h" #include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h" @@ -154,12 +155,13 @@ @end -@interface TabStripController ()<DropAndNavigateDelegate, - TabModelObserver, - TabStripViewLayoutDelegate, - TabViewDelegate, - UIGestureRecognizerDelegate, - UIScrollViewDelegate> { +@interface TabStripController () <DropAndNavigateDelegate, + TabModelObserver, + TabStripViewLayoutDelegate, + TabViewDelegate, + WebStateListObserving, + UIGestureRecognizerDelegate, + UIScrollViewDelegate> { TabModel* _tabModel; UIView* _view; TabStripView* _tabStripView; @@ -232,6 +234,9 @@ // drags. std::unique_ptr<ScopedFullscreenDisabler> _fullscreenDisabler; + // Bridges C++ WebStateListObserver methods to this TabStripController. + std::unique_ptr<WebStateListObserverBridge> _webStateListObserver; + API_AVAILABLE(ios(11.0)) DropAndNavigateInteraction* _buttonNewTabInteraction; } @@ -388,6 +393,8 @@ _tabModel = tabModel; [_tabModel addObserver:self]; + _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self); + _tabModel.webStateList->AddObserver(_webStateListObserver.get()); _style = style; _dispatcher = dispatcher; @@ -486,6 +493,7 @@ [_tabStripView setDelegate:nil]; [_tabStripView setLayoutDelegate:nil]; [_tabModel removeObserver:self]; + _tabModel.webStateList->RemoveObserver(_webStateListObserver.get()); } - (void)hideTabStrip:(BOOL)hidden { @@ -939,6 +947,32 @@ } #pragma mark - +#pragma mark WebStateObserving methods + +// Observer method, active WebState changed. +- (void)webStateList:(WebStateList*)webStateList + didChangeActiveWebState:(web::WebState*)newWebState + oldWebState:(web::WebState*)oldWebState + atIndex:(int)atIndex + reason:(int)reason { + if (!newWebState) + return; + + for (TabView* view in _tabArray) { + [view setSelected:NO]; + } + + NSUInteger index = [self indexForModelIndex:atIndex]; + TabView* activeView = [_tabArray objectAtIndex:index]; + [activeView setSelected:YES]; + + // No need to animate this change, as selecting a new tab simply changes the + // z-ordering of the TabViews. If a new tab was selected as a result of a tab + // closure, then the animated layout has already been scheduled. + [_tabStripView setNeedsLayout]; +} + +#pragma mark - #pragma mark TabModelObserver methods // Observer method. @@ -1012,25 +1046,6 @@ } // Observer method. -- (void)tabModel:(TabModel*)model - didChangeActiveTab:(Tab*)newTab - previousTab:(Tab*)previousTab - atIndex:(NSUInteger)modelIndex { - for (TabView* view in _tabArray) { - [view setSelected:NO]; - } - - NSUInteger index = [self indexForModelIndex:modelIndex]; - TabView* activeView = [_tabArray objectAtIndex:index]; - [activeView setSelected:YES]; - - // No need to animate this change, as selecting a new tab simply changes the - // z-ordering of the TabViews. If a new tab was selected as a result of a tab - // closure, then the animated layout has already been scheduled. - [_tabStripView setNeedsLayout]; -} - -// Observer method. - (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab { NSUInteger modelIndex = [_tabModel indexOfTab:tab]; if (modelIndex == NSNotFound) {
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller_unittest.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller_unittest.mm index 8c6c329..e09e5bf 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller_unittest.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller_unittest.mm
@@ -85,7 +85,6 @@ - (void)browserStateDestroyed { _webStateList->CloseAllWebStates(WebStateList::CLOSE_NO_FLAGS); - _webStateList.reset(); _browserState = nullptr; } @@ -195,9 +194,9 @@ web::TestWebThreadBundle thread_bundle_; std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; + TabStripControllerTestTabModel* tab_model_; TabStripController* controller_; UIWindow* window_; - TabStripControllerTestTabModel* tab_model_; TabStripControllerTestTab* tab1_; TabStripControllerTestTab* tab2_; };
diff --git a/ios/showcase/alert/BUILD.gn b/ios/showcase/alert/BUILD.gn index f4bc5a6..acf0809 100644 --- a/ios/showcase/alert/BUILD.gn +++ b/ios/showcase/alert/BUILD.gn
@@ -10,6 +10,7 @@ deps = [ "//ios/chrome/browser/ui/alert_view_controller", "//ios/chrome/browser/ui/elements", + "//ios/chrome/browser/ui/presenters", "//ios/showcase/common", ] libs = [ "UIKit.framework" ]
diff --git a/ios/showcase/alert/sc_alert_coordinator.mm b/ios/showcase/alert/sc_alert_coordinator.mm index 95fcfa00..6cd36bc 100644 --- a/ios/showcase/alert/sc_alert_coordinator.mm +++ b/ios/showcase/alert/sc_alert_coordinator.mm
@@ -6,8 +6,8 @@ #import "ios/chrome/browser/ui/alert_view_controller/alert_action.h" #import "ios/chrome/browser/ui/alert_view_controller/alert_view_controller.h" -#import "ios/chrome/browser/ui/alert_view_controller/non_modal_view_controller_presenter.h" #import "ios/chrome/browser/ui/elements/text_field_configuration.h" +#import "ios/chrome/browser/ui/presenters/non_modal_view_controller_presenter.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm index fb912bb..97377ff9 100644 --- a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm +++ b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
@@ -292,6 +292,10 @@ return self.imageURL.is_valid(); } +- (id<OmniboxIcon>)icon { + return nil; +} + + (instancetype)simpleSuggestion { FakeAutocompleteSuggestion* suggestion = [[FakeAutocompleteSuggestion alloc] init];
diff --git a/ios/web/app/web_main_loop.h b/ios/web/app/web_main_loop.h index 9099da6..0a8efa1d 100644 --- a/ios/web/app/web_main_loop.h +++ b/ios/web/app/web_main_loop.h
@@ -10,7 +10,6 @@ #include "base/callback_helpers.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "ios/web/public/app/thread_pool_init_params_callback.h" namespace base { class PowerMonitor; @@ -35,10 +34,8 @@ void EarlyInitialization(); void MainMessageLoopStart(); - // Creates and starts running the tasks needed to complete startup. The - // |init_params_callback| may be null or supply InitParams to be used to start - // the global ThreadPool instead of using the defaults. - void CreateStartupTasks(ThreadPoolInitParamsCallback init_params_callback); + // Creates and starts running the tasks needed to complete startup. + void CreateStartupTasks(); // Performs the shutdown sequence, starting with PostMainMessageLoopRun // through stopping threads to PostDestroyThreads. @@ -52,10 +49,8 @@ // Called just before creating the threads int PreCreateThreads(); - // Creates all secondary threads. The |init_params_callback| may be null or - // supply InitParams to be used to start the global ThreadPool instead of - // using the defaults. - int CreateThreads(ThreadPoolInitParamsCallback init_params_callback); + // Creates all secondary threads. + int CreateThreads(); // Called right after the web threads have been started. int WebThreadsStarted();
diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm index 99cddba..7853dae 100644 --- a/ios/web/app/web_main_loop.mm +++ b/ios/web/app/web_main_loop.mm
@@ -90,14 +90,13 @@ } } -void WebMainLoop::CreateStartupTasks( - ThreadPoolInitParamsCallback init_params_callback) { +void WebMainLoop::CreateStartupTasks() { int result = 0; result = PreCreateThreads(); if (result > 0) return; - result = CreateThreads(std::move(init_params_callback)); + result = CreateThreads(); if (result > 0) return; @@ -118,13 +117,8 @@ return result_code_; } -int WebMainLoop::CreateThreads( - ThreadPoolInitParamsCallback init_params_callback) { - std::unique_ptr<base::ThreadPool::InitParams> init_params; - if (!init_params_callback.is_null()) { - init_params = std::move(init_params_callback).Run(); - } - ios_global_state::StartThreadPool(init_params.get()); +int WebMainLoop::CreateThreads() { + ios_global_state::StartThreadPool(); base::Thread::Options io_message_loop_options; io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO;
diff --git a/ios/web/app/web_main_runner.mm b/ios/web/app/web_main_runner.mm index 0a0efa7f..9810315 100644 --- a/ios/web/app/web_main_runner.mm +++ b/ios/web/app/web_main_runner.mm
@@ -73,8 +73,7 @@ main_loop_->Init(); main_loop_->EarlyInitialization(); main_loop_->MainMessageLoopStart(); - main_loop_->CreateStartupTasks( - std::move(params.get_thread_pool_init_params_callback)); + main_loop_->CreateStartupTasks(); int result_code = main_loop_->GetResultCode(); if (result_code > 0) return result_code;
diff --git a/ios/web/public/app/BUILD.gn b/ios/web/public/app/BUILD.gn index ea886b3..136588c 100644 --- a/ios/web/public/app/BUILD.gn +++ b/ios/web/public/app/BUILD.gn
@@ -4,7 +4,6 @@ source_set("app") { sources = [ - "thread_pool_init_params_callback.h", "web_main.h", "web_main_delegate.h", "web_main_parts.h",
diff --git a/ios/web/public/app/thread_pool_init_params_callback.h b/ios/web/public/app/thread_pool_init_params_callback.h deleted file mode 100644 index 5657bc2a..0000000 --- a/ios/web/public/app/thread_pool_init_params_callback.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_WEB_PUBLIC_APP_THREAD_POOL_INIT_PARAMS_CALLBACK_H_ -#define IOS_WEB_PUBLIC_APP_THREAD_POOL_INIT_PARAMS_CALLBACK_H_ - -#include "base/callback_forward.h" -#include "base/task/thread_pool/thread_pool.h" - -namespace web { - -// Callback which returns a pointer to InitParams for base::ThreadPool. -typedef base::OnceCallback<std::unique_ptr<base::ThreadPool::InitParams>()> - ThreadPoolInitParamsCallback; - -} // namespace web - -#endif // IOS_WEB_PUBLIC_APP_THREAD_POOL_INIT_PARAMS_CALLBACK_H_
diff --git a/ios/web/public/app/web_main.h b/ios/web/public/app/web_main.h index 4d1acb00..1df146b 100644 --- a/ios/web/public/app/web_main.h +++ b/ios/web/public/app/web_main.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/macros.h" -#include "ios/web/public/app/thread_pool_init_params_callback.h" #include "ios/web/public/app/web_main_delegate.h" namespace web { @@ -27,7 +26,6 @@ WebMainDelegate* delegate; bool register_exit_manager; - ThreadPoolInitParamsCallback get_thread_pool_init_params_callback; int argc; const char** argv;
diff --git a/ios/web/public/global_state/ios_global_state.h b/ios/web/public/global_state/ios_global_state.h index d7b1f45..1dd07c2 100644 --- a/ios/web/public/global_state/ios_global_state.h +++ b/ios/web/public/global_state/ios_global_state.h
@@ -54,11 +54,10 @@ // It is safe to call this method multiple time. void DestroyNetworkChangeNotifier(); -// Starts a global base::ThreadPool. This method must be called to start -// the Task Scheduler that is created in |Create|. If |init_params| is null, -// default InitParams will be used. It is safe to call this method more than -// once, the thread pool will only be started once. -void StartThreadPool(base::ThreadPool::InitParams* init_params); +// Starts a global base::ThreadPool. This method must be called to start the +// Thread Pool that is created in |Create|. It is safe to call this method more +// than once, the thread pool will only be started once. +void StartThreadPool(); // Destroys the AtExitManager if one was created in |Create|. It is safe to call // this method even if |install_at_exit_manager| was false in the CreateParams
diff --git a/ios/web/public/global_state/ios_global_state.mm b/ios/web/public/global_state/ios_global_state.mm index 862ac71..4ef1de6 100644 --- a/ios/web/public/global_state/ios_global_state.mm +++ b/ios/web/public/global_state/ios_global_state.mm
@@ -22,32 +22,6 @@ base::MessageLoopForUI* g_message_loop = nullptr; net::NetworkChangeNotifier* g_network_change_notifer = nullptr; -base::ThreadPool::InitParams GetDefaultThreadPoolInitParams() { - constexpr int kMinBackgroundThreads = 4; - constexpr int kMaxBackgroundThreads = 16; - constexpr double kCoreMultiplierBackgroundThreads = 0.2; - constexpr int kOffsetBackgroundThreads = 0; - constexpr int kReclaimTimeBackground = 30; - - constexpr int kMinForegroundThreads = 6; - constexpr int kMaxForegroundThreads = 16; - constexpr double kCoreMultiplierForegroundThreads = 0.6; - constexpr int kOffsetForegroundThreads = 0; - constexpr int kReclaimTimeForeground = 30; - - return base::ThreadPool::InitParams( - base::ThreadGroupParams( - base::RecommendedMaxNumberOfThreadsInThreadGroup( - kMinBackgroundThreads, kMaxBackgroundThreads, - kCoreMultiplierBackgroundThreads, kOffsetBackgroundThreads), - base::TimeDelta::FromSeconds(kReclaimTimeBackground)), - base::ThreadGroupParams( - base::RecommendedMaxNumberOfThreadsInThreadGroup( - kMinForegroundThreads, kMaxForegroundThreads, - kCoreMultiplierForegroundThreads, kOffsetForegroundThreads), - base::TimeDelta::FromSeconds(kReclaimTimeForeground))); -} - } // namespace namespace ios_global_state { @@ -93,11 +67,17 @@ g_network_change_notifer = nullptr; } -void StartThreadPool(base::ThreadPool::InitParams* params) { +void StartThreadPool() { static dispatch_once_t once_token; dispatch_once(&once_token, ^{ - auto init_params = params ? *params : GetDefaultThreadPoolInitParams(); - base::ThreadPool::GetInstance()->Start(init_params); + constexpr int kMinForegroundThreads = 6; + constexpr int kMaxForegroundThreads = 16; + constexpr double kCoreMultiplierForegroundThreads = 0.6; + constexpr int kOffsetForegroundThreads = 0; + base::ThreadPool::GetInstance()->Start( + {base::RecommendedMaxNumberOfThreadsInThreadGroup( + kMinForegroundThreads, kMaxForegroundThreads, + kCoreMultiplierForegroundThreads, kOffsetForegroundThreads)}); }); }
diff --git a/ios/web/web_state/BUILD.gn b/ios/web/web_state/BUILD.gn index 7f5bf8d..e8bdc5b 100644 --- a/ios/web/web_state/BUILD.gn +++ b/ios/web/web_state/BUILD.gn
@@ -171,3 +171,18 @@ configs += [ "//build/config/compiler:enable_arc" ] } + +source_set("user_interaction") { + sources = [ + "user_interaction_event.h", + "user_interaction_state.h", + "user_interaction_state.mm", + ] + + deps = [ + "//base", + "//url", + ] + + configs += [ "//build/config/compiler:enable_arc" ] +}
diff --git a/ios/web/web_state/ui/BUILD.gn b/ios/web/web_state/ui/BUILD.gn index 40adc19..d0bdab1 100644 --- a/ios/web/web_state/ui/BUILD.gn +++ b/ios/web/web_state/ui/BUILD.gn
@@ -29,6 +29,7 @@ "//ios/web/web_state:error_translation_util", "//ios/web/web_state:page_viewport_state", "//ios/web/web_state:session_certificate_policy_cache", + "//ios/web/web_state:user_interaction", "//ios/web/web_state:web_frame", "//ios/web/web_state:web_state_impl_header", "//ios/web/web_state:web_view_internal_creation_util",
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h index 5f449cb..f9d221b 100644 --- a/ios/web/web_state/ui/crw_web_controller.h +++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -222,9 +222,6 @@ @property(nonatomic, readonly) web::WebState* webState; @property(nonatomic, readonly) web::WebStateImpl* webStateImpl; -// Returns whether the user is interacting with the page. -@property(nonatomic, readonly) BOOL userIsInteracting; - // Injects a CRWWebViewContentView for testing. Takes ownership of // |webViewContentView|. - (void)injectWebViewContentView:(CRWWebViewContentView*)webViewContentView;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 5d7f13fa..e1f7b9a 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -107,6 +107,7 @@ #include "ios/web/web_state/ui/web_kit_constants.h" #import "ios/web/web_state/ui/wk_security_origin_util.h" #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" +#import "ios/web/web_state/user_interaction_state.h" #import "ios/web/web_state/web_frame_impl.h" #import "ios/web/web_state/web_frames_manager_impl.h" #import "ios/web/web_state/web_state_impl.h" @@ -141,17 +142,6 @@ namespace { -// Struct to capture data about a user interaction. Records the time of the -// interaction and the main document URL at that time. -struct UserInteractionEvent { - UserInteractionEvent(GURL url) - : main_document_url(url), time(CFAbsoluteTimeGetCurrent()) {} - // Main document URL at the time the interaction occurred. - GURL main_document_url; - // Time that the interaction occurred, measured in seconds since Jan 1 2001. - CFAbsoluteTime time; -}; - // Keys for JavaScript command handlers context. NSString* const kUserIsInteractingKey = @"userIsInteracting"; NSString* const kOriginURLKey = @"originURL"; @@ -165,10 +155,6 @@ // Message command sent when a frame is unloading. NSString* const kFrameBecameUnavailableMessageName = @"FrameBecameUnavailable"; -// The duration of the period following a screen touch during which the user is -// still considered to be interacting with the page. -const NSTimeInterval kMaximumDelayForUserInteractionInSeconds = 2; - // Values for the histogram that counts slow/fast back/forward navigations. enum class BackForwardNavigationType { // Fast back navigation through WKWebView back-forward list. @@ -249,9 +235,6 @@ BOOL _currentURLLoadWasTrigerred; BOOL _isHalted; // YES if halted. Halting happens prior to destruction. BOOL _isBeingDestroyed; // YES if in the process of closing. - // YES if the user has interacted with the content area since the last URL - // change. - BOOL _interactionRegisteredSinceLastURLChange; // The actual URL of the document object (i.e., the last committed URL). // TODO(crbug.com/549616): Remove this in favor of just updating the // navigation manager and treating that as authoritative. @@ -269,15 +252,6 @@ BOOL _webUsageEnabled; // The controller that tracks long press and check context menu trigger. CRWContextMenuController* _contextMenuController; - // Whether a click is in progress. - BOOL _clickInProgress; - // Data on the recorded last user interaction. - std::unique_ptr<UserInteractionEvent> _lastUserInteraction; - // YES if there has been user interaction with views owned by this controller. - BOOL _userInteractedWithWebController; - // The time of the last page transfer start, measured in seconds since Jan 1 - // 2001. - CFAbsoluteTime _lastTransferTimeInSeconds; // Default URL (about:blank). GURL _defaultURL; // Whether the web page is currently performing window.history.pushState or @@ -327,6 +301,9 @@ // cert status from |didReceiveAuthenticationChallenge:| to // |didFailProvisionalNavigation:| delegate method. std::unique_ptr<CertVerificationErrorsCacheType> _certVerificationErrors; + + // State of user interaction with web content. + web::UserInteractionState _userInteractionState; } // The WKNavigationDelegate handler class. @@ -365,9 +342,6 @@ // Returns the referrer for the current page. @property(nonatomic, readonly) web::Referrer currentReferrer; -// Returns YES if the user interacted with the page recently. -@property(nonatomic, readonly) BOOL userClickedRecently; - // User agent type of the transient item if any, the pending item if a // navigation is in progress or the last committed item otherwise. // Returns MOBILE, the default type, if navigation manager is nullptr or empty. @@ -376,10 +350,6 @@ // Facade for Mojo API. @property(nonatomic, readonly) web::MojoFacade* mojoFacade; -// YES if a user interaction has been registered at any time since the page has -// loaded. -@property(nonatomic, readwrite) BOOL userInteractionRegistered; - @property(nonatomic, readonly) web::WebState* webState; // WebStateImpl instance associated with this CRWWebController, web controller // does not own this pointer. @@ -860,21 +830,6 @@ web::ReferrerPolicyAlways); } -- (BOOL)userClickedRecently { - // Scrolling generates a pair of touch on/off event which causes - // _lastUserInteraction to register that there was user interaction. - // Checks for scrolling first to override time-based click heuristics. - BOOL scrolling = [[self webScrollView] isDragging] || - [[self webScrollView] isDecelerating]; - if (scrolling) - return NO; - if (!_lastUserInteraction) - return NO; - return _clickInProgress || - ((CFAbsoluteTimeGetCurrent() - _lastUserInteraction->time) < - kMaximumDelayForUserInteractionInSeconds); -} - - (web::UserAgentType)userAgentType { web::NavigationItem* item = self.currentNavItem; return item ? item->GetUserAgentType() : web::UserAgentType::MOBILE; @@ -890,12 +845,6 @@ return _mojoFacade.get(); } -- (void)setUserInteractionRegistered:(BOOL)flag { - _userInteractionRegistered = flag; - if (flag) - _interactionRegisteredSinceLastURLChange = YES; -} - - (WebState*)webState { return _webStateImpl; } @@ -1087,7 +1036,7 @@ // TODO(crbug.com/546337): Move to after the load commits, in the subclass // implementation. This will be inaccurate if the reload fails or is // cancelled. - _lastUserInteraction = nullptr; + _userInteractionState.SetLastUserInteraction(nullptr); base::RecordAction(base::UserMetricsAction("Reload")); GURL URL = self.currentNavItem->GetURL(); if ([self shouldLoadURLInNativeView:URL]) { @@ -1377,7 +1326,7 @@ // - the user has interacted with the page. web::NavigationItem* item = self.currentNavItem; if (item && item->GetURL() == [self currentURL] && - self.userInteractionRegistered) { + _userInteractionState.UserInteractionRegisteredSincePageLoaded()) { item->SetPageDisplayState(self.pageDisplayState); } } @@ -1548,10 +1497,9 @@ #pragma mark - CRWTouchTrackingDelegate (Public) - (void)touched:(BOOL)touched { - _clickInProgress = touched; + _userInteractionState.SetTapInProgress(touched); if (touched) { - self.userInteractionRegistered = YES; - _userInteractedWithWebController = YES; + _userInteractionState.SetUserInteractionRegisteredSincePageLoaded(true); if (_isBeingDestroyed) return; const NavigationManagerImpl* navigationManager = self.navigationManagerImpl; @@ -1559,8 +1507,8 @@ navigationManager->GetLastCommittedItem() ? navigationManager->GetLastCommittedItem()->GetURL() : [self currentURL]; - _lastUserInteraction = - std::make_unique<UserInteractionEvent>(mainDocumentURL); + _userInteractionState.SetLastUserInteraction( + std::make_unique<web::UserInteractionEvent>(mainDocumentURL)); } } @@ -1593,7 +1541,7 @@ context:(web::NavigationContextImpl*)context { if (newURL != _documentURL && newURL.is_valid()) { _documentURL = newURL; - _interactionRegisteredSinceLastURLChange = NO; + _userInteractionState.SetUserInteractionRegisteredSinceLastUrlChange(false); } if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && context && !context->IsLoadingHtmlString() && !context->IsLoadingErrorPage() && @@ -1687,7 +1635,8 @@ // the page has no navigation items, as occurs when an App Store link is // opened from another application. BOOL rendererInitiatedWithoutInteraction = - self.hasOpener && !_userInteractedWithWebController; + self.hasOpener && + !_userInteractionState.UserInteractionRegisteredSinceWebViewCreated(); BOOL noNavigationItems = !(self.navigationManagerImpl->GetItemCount()); return rendererInitiatedWithoutInteraction || noNavigationItems; } @@ -1709,7 +1658,7 @@ // or may not be the result of user actions. For now, guess based on // whether there's been an interaction since the last URL change. // TODO(crbug.com/549301): See if this heuristic can be improved. - return _interactionRegisteredSinceLastURLChange + return _userInteractionState.UserInteractionRegisteredSinceLastUrlChange() ? ui::PAGE_TRANSITION_LINK : ui::PAGE_TRANSITION_CLIENT_REDIRECT; } @@ -1775,7 +1724,7 @@ placeholderNavigation:(BOOL)placeholderNavigation { // Transfer time is registered so that further transitions within the time // envelope are not also registered as links. - _lastTransferTimeInSeconds = CFAbsoluteTimeGetCurrent(); + _userInteractionState.ResetLastTransferTime(); // Add or update pending item before any WebStateObserver callbacks. // See https://crbug.com/842151 for a scenario where this is important. @@ -2810,21 +2759,12 @@ if (!message->GetDictionary("crwCommand", &command)) { return NO; } - return [self respondToMessage:command - userIsInteracting:[self userIsInteracting] - originURL:net::GURLWithNSURL(self.webView.URL) - isMainFrame:scriptMessage.frameInfo.mainFrame - senderFrame:senderFrame]; -} - -- (BOOL)userIsInteracting { - // If page transfer started after last click, user is deemed to be no longer - // interacting. - if (!_lastUserInteraction || - _lastTransferTimeInSeconds > _lastUserInteraction->time) { - return NO; - } - return [self userClickedRecently]; + return [self + respondToMessage:command + userIsInteracting:_userInteractionState.IsUserInteracting(self.webView) + originURL:net::GURLWithNSURL(self.webView.URL) + isMainFrame:scriptMessage.frameInfo.mainFrame + senderFrame:senderFrame]; } #pragma mark - Web frames management @@ -3092,9 +3032,10 @@ // If not, categorize it is a client redirect as it occurred without user // input and should not be added to the history stack. // TODO(crbug.com/549301): Improve transition detection. - ui::PageTransition transition = self.userInteractionRegistered - ? ui::PAGE_TRANSITION_LINK - : ui::PAGE_TRANSITION_CLIENT_REDIRECT; + ui::PageTransition transition = + _userInteractionState.UserInteractionRegisteredSincePageLoaded() + ? ui::PAGE_TRANSITION_LINK + : ui::PAGE_TRANSITION_CLIENT_REDIRECT; [self pushStateWithPageURL:pushURL stateObject:stateObject transition:transition @@ -3218,7 +3159,7 @@ transition); context->SetHasCommitted(true); self.webStateImpl->OnNavigationFinished(context.get()); - self.userInteractionRegistered = NO; + _userInteractionState.SetUserInteractionRegisteredSincePageLoaded(false); } // Assigns the given URL and state object to the current NavigationItem. @@ -4025,7 +3966,7 @@ #pragma mark - WKUIDelegate Helpers - (BOOL)isUserInitiatedAction:(WKNavigationAction*)action { - return [self userIsInteracting]; + return _userInteractionState.IsUserInteracting(self.webView); } // Helper to respond to |webView:runJavaScript...| delegate methods. @@ -4245,9 +4186,9 @@ if (allowLoad) { BOOL userInteractedWithRequestMainFrame = - [self userClickedRecently] && + _userInteractionState.HasUserTappedRecently(self.webView) && net::GURLWithNSURL(action.request.mainDocumentURL) == - _lastUserInteraction->main_document_url; + _userInteractionState.LastUserInteraction()->main_document_url; web::WebStatePolicyDecider::RequestInfo requestInfo( transition, isMainFrameNavigationAction, userInteractedWithRequestMainFrame); @@ -5140,8 +5081,8 @@ // Resets any state that is associated with a specific document object (e.g., // page interaction tracking). - (void)resetDocumentSpecificState { - _lastUserInteraction = nullptr; - _clickInProgress = NO; + _userInteractionState.SetLastUserInteraction(nullptr); + _userInteractionState.SetTapInProgress(false); } // Called when a page (native or web) has actually started loading (i.e., for @@ -5152,7 +5093,7 @@ self.navigationState = web::WKNavigationState::STARTED; _displayStateOnStartLoading = self.pageDisplayState; - self.userInteractionRegistered = NO; + _userInteractionState.SetUserInteractionRegisteredSincePageLoaded(false); _pageHasZoomed = NO; } @@ -5265,6 +5206,24 @@ [self handleCancelledError:error forNavigation:navigation provisionalLoad:provisionalLoad]; + // TODO(crbug.com/957032): This might get fixed at some point. Check if + // there is a iOS version for which we don't need it any more. + if (@available(iOS 12.2, *)) { + if (![self.webView.backForwardList.currentItem.URL + isEqual:self.webView.URL] && + self.isCurrentNavigationItemPOST) { + UMA_HISTOGRAM_BOOLEAN("WebController.BackForwardListOutOfSync", true); + // Sometimes on error the backForward list is out of sync with the + // webView, go back or forward to fix it. See crbug.com/951880. + if ([self.webView.backForwardList.backItem.URL + isEqual:self.webView.URL]) { + [self.webView goBack]; + } else if ([self.webView.backForwardList.forwardItem.URL + isEqual:self.webView.URL]) { + [self.webView goForward]; + } + } + } // NSURLErrorCancelled errors that aren't handled by aborting the load will // automatically be retried by the web view, so early return in this case. return; @@ -5602,7 +5561,7 @@ item->ResetHttpRequestHeaders(); } - _lastTransferTimeInSeconds = CFAbsoluteTimeGetCurrent(); + _userInteractionState.ResetLastTransferTime(); } // Returns YES if the current live view is a web view with an image MIME type.
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 7003bee..27ad1b6 100644 --- a/ios/web/web_state/ui/crw_web_controller_unittest.mm +++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -1127,7 +1127,6 @@ // Tests that window.open executed w/o user gesture does not open a new window, // but blocks popup instead. TEST_P(WindowOpenByDomTest, BlockPopup) { - ASSERT_FALSE([web_controller() userIsInteracting]); EXPECT_NSEQ([NSNull null], OpenWindowByDom()); EXPECT_TRUE(delegate_.child_windows().empty());
diff --git a/ios/web/web_state/user_interaction_event.h b/ios/web/web_state/user_interaction_event.h new file mode 100644 index 0000000..4b928b5a --- /dev/null +++ b/ios/web/web_state/user_interaction_event.h
@@ -0,0 +1,27 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_WEB_STATE_USER_INTERACTION_EVENT_H_ +#define IOS_WEB_WEB_STATE_USER_INTERACTION_EVENT_H_ + +#import <CoreFoundation/CFDate.h> + +#include "url/gurl.h" + +namespace web { + +// Struct to capture data about a user interaction. Records the time of the +// interaction and the main document URL at that time. +struct UserInteractionEvent { + explicit UserInteractionEvent(const GURL& url) + : main_document_url(url), time(CFAbsoluteTimeGetCurrent()) {} + // Main document URL at the time the interaction occurred. + GURL main_document_url; + // Time that the interaction occurred, measured in seconds since Jan 1 2001. + CFAbsoluteTime time; +}; + +} // namespace web + +#endif // IOS_WEB_WEB_STATE_USER_INTERACTION_EVENT_H_
diff --git a/ios/web/web_state/user_interaction_state.h b/ios/web/web_state/user_interaction_state.h new file mode 100644 index 0000000..e2581df8 --- /dev/null +++ b/ios/web/web_state/user_interaction_state.h
@@ -0,0 +1,75 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_WEB_STATE_USER_INTERACTION_STATE_H_ +#define IOS_WEB_WEB_STATE_USER_INTERACTION_STATE_H_ + +#import <WebKit/WebKit.h> +#include <memory> + +#import "ios/web/web_state/user_interaction_event.h" + +namespace web { + +// Records user's interaction state with web content. +class UserInteractionState { + public: + UserInteractionState(); + ~UserInteractionState(); + + // Returns |user_interaction_registered_since_page_loaded_|. + bool UserInteractionRegisteredSincePageLoaded() const; + // Sets |user_interaction_registered_since_page_loaded_|. If true, also sets + // |user_interaction_registered_since_last_url_change_| and + // |user_interaction_registered_since_web_view_created_| to true; + void SetUserInteractionRegisteredSincePageLoaded( + bool user_interaction_registered_since_page_loaded); + + // Returns |user_interaction_registered_since_last_url_change_|. + bool UserInteractionRegisteredSinceLastUrlChange() const; + // Sets |user_interaction_registered_since_last_url_change_|. If true, also + // sets |user_interaction_registered_since_web_view_created_| to true. + void SetUserInteractionRegisteredSinceLastUrlChange( + bool interaction_registered_since_last_url_change); + + // Returns |user_interaction_registered_since_web_view_created_|. + bool UserInteractionRegisteredSinceWebViewCreated() const; + + // Sets |tap_in_progress_|. + void SetTapInProgress(bool tap_in_progress); + + // Resets |last_transfer_time_in_seconds_| to current time. + void ResetLastTransferTime(); + + // Returns the raw pointer managed by |last_user_interaction_|. + web::UserInteractionEvent* LastUserInteraction() const; + // Sets |last_user_interaction_|. + void SetLastUserInteraction( + std::unique_ptr<web::UserInteractionEvent> last_user_interaction); + + // Returns true if the user interacted with the page recently. + bool HasUserTappedRecently(WKWebView* web_view) const; + // Returns whether the user is interacting with the page. + bool IsUserInteracting(WKWebView* web_view) const; + + private: + // Whether a user interaction has been registered since the page has loaded. + bool user_interaction_registered_since_page_loaded_; + // Whether a user interaction has been registered since the last URL change. + bool user_interaction_registered_since_last_url_change_; + // Whether a user interaction has been registered since the web view is + // created. + bool user_interaction_registered_since_web_view_created_; + // Whether a tap is in progress. + bool tap_in_progress_; + // The time of the last page transfer start, measured in seconds since Jan 1 + // 2001. + CFAbsoluteTime last_transfer_time_in_seconds_; + // Data on the recorded last user interaction. + std::unique_ptr<web::UserInteractionEvent> last_user_interaction_; +}; + +} // namespace web + +#endif // IOS_WEB_WEB_STATE_USER_INTERACTION_STATE_H_
diff --git a/ios/web/web_state/user_interaction_state.mm b/ios/web/web_state/user_interaction_state.mm new file mode 100644 index 0000000..f5a617e --- /dev/null +++ b/ios/web/web_state/user_interaction_state.mm
@@ -0,0 +1,100 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/web_state/user_interaction_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// The duration of the period following a screen touch during which the user is +// still considered to be interacting with the page. +const NSTimeInterval kMaximumDelayForUserInteractionInSeconds = 2; +} + +namespace web { + +UserInteractionState::UserInteractionState() + : user_interaction_registered_since_page_loaded_(false), + user_interaction_registered_since_last_url_change_(false), + user_interaction_registered_since_web_view_created_(false), + tap_in_progress_(false), + last_user_interaction_(nullptr) {} + +UserInteractionState::~UserInteractionState() {} + +bool UserInteractionState::UserInteractionRegisteredSincePageLoaded() const { + return user_interaction_registered_since_page_loaded_; +} + +void UserInteractionState::SetUserInteractionRegisteredSincePageLoaded( + bool user_interaction_registered_since_page_loaded) { + user_interaction_registered_since_page_loaded_ = + user_interaction_registered_since_page_loaded; + if (user_interaction_registered_since_page_loaded) { + user_interaction_registered_since_last_url_change_ = true; + user_interaction_registered_since_web_view_created_ = true; + } +} + +bool UserInteractionState::UserInteractionRegisteredSinceLastUrlChange() const { + return user_interaction_registered_since_last_url_change_; +} + +void UserInteractionState::SetUserInteractionRegisteredSinceLastUrlChange( + bool user_interaction_registered_since_last_url_change) { + user_interaction_registered_since_last_url_change_ = + user_interaction_registered_since_last_url_change; + if (user_interaction_registered_since_last_url_change) { + user_interaction_registered_since_web_view_created_ = true; + } +} + +bool UserInteractionState::UserInteractionRegisteredSinceWebViewCreated() + const { + return user_interaction_registered_since_web_view_created_; +} + +void UserInteractionState::SetTapInProgress(bool tap_in_progress) { + tap_in_progress_ = tap_in_progress; +} + +void UserInteractionState::ResetLastTransferTime() { + last_transfer_time_in_seconds_ = CFAbsoluteTimeGetCurrent(); +} + +web::UserInteractionEvent* UserInteractionState::LastUserInteraction() const { + return last_user_interaction_.get(); +} + +void UserInteractionState::SetLastUserInteraction( + std::unique_ptr<web::UserInteractionEvent> last_user_interaction) { + last_user_interaction_ = std::move(last_user_interaction); +} + +bool UserInteractionState::HasUserTappedRecently(WKWebView* web_view) const { + // Scrolling generates a pair of touch on/off event which causes + // last_user_interaction_ to register that there was user interaction. Checks + // for scrolling first to override time-based tap heuristics. + if (web_view.scrollView.dragging || web_view.scrollView.decelerating) + return NO; + if (!last_user_interaction_) + return NO; + return tap_in_progress_ || + ((CFAbsoluteTimeGetCurrent() - last_user_interaction_->time) < + kMaximumDelayForUserInteractionInSeconds); +} + +bool UserInteractionState::IsUserInteracting(WKWebView* web_view) const { + // If page transfer started after last tap, user is deemed to be no longer + // interacting. + if (!last_user_interaction_ || + last_transfer_time_in_seconds_ > last_user_interaction_->time) { + return NO; + } + return HasUserTappedRecently(web_view); +} + +} // namespace web
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn index 92265228..69c18f0 100644 --- a/ipc/BUILD.gn +++ b/ipc/BUILD.gn
@@ -88,7 +88,7 @@ ":mojom", ":native_handle_type_converters", ":param_traits", - "//base/util/type-safety", + "//base/util/type_safety", "//mojo/public/cpp/base", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system",
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h index 4e28d4b0..53baea4 100644 --- a/ipc/ipc_message_utils.h +++ b/ipc/ipc_message_utils.h
@@ -35,7 +35,7 @@ #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "base/util/type-safety/id_type.h" +#include "base/util/type_safety/id_type.h" #include "build/build_config.h" #include "ipc/ipc_message_start.h" #include "ipc/ipc_param_traits.h"
diff --git a/media/capture/video/chromeos/camera_device_delegate.cc b/media/capture/video/chromeos/camera_device_delegate.cc index 43db043..d982804 100644 --- a/media/capture/video/chromeos/camera_device_delegate.cc +++ b/media/capture/video/chromeos/camera_device_delegate.cc
@@ -4,6 +4,7 @@ #include "media/capture/video/chromeos/camera_device_delegate.h" +#include <algorithm> #include <memory> #include <string> #include <utility> @@ -31,12 +32,10 @@ // The result of max_width and max_height could be zero if the stream // is not in the pre-defined configuration. -void GetMaxStreamResolution( - const cros::mojom::CameraMetadataPtr& static_metadata, - cros::mojom::Camera3StreamType stream_type, - cros::mojom::HalPixelFormat stream_format, - int32_t* max_width, - int32_t* max_height) { +void GetStreamResolutions(const cros::mojom::CameraMetadataPtr& static_metadata, + cros::mojom::Camera3StreamType stream_type, + cros::mojom::HalPixelFormat stream_format, + std::vector<gfx::Size>* resolutions) { const cros::mojom::CameraMetadataEntryPtr* stream_configurations = GetMetadataEntry(static_metadata, cros::mojom::CameraMetadataTag:: @@ -51,8 +50,6 @@ const size_t kStreamConfigurationSize = 4; int32_t* iter = reinterpret_cast<int32_t*>((*stream_configurations)->data.data()); - *max_width = 0; - *max_height = 0; for (size_t i = 0; i < (*stream_configurations)->count; i += kStreamConfigurationSize) { auto format = @@ -67,13 +64,13 @@ continue; } - // TODO(wtlee): Once we have resolution settings mechanism, we could set - // stream resolution based on user's settings. - if (width > *max_width && height > *max_height) { - *max_width = width; - *max_height = height; - } + resolutions->emplace_back(width, height); } + + std::sort(resolutions->begin(), resolutions->end(), + [](const gfx::Size& a, const gfx::Size& b) -> bool { + return a.width() * a.height() < b.width() * b.height(); + }); } // VideoCaptureDevice::TakePhotoCallback is given by the application and is used @@ -251,18 +248,26 @@ return; } - int32_t max_blob_width = 0, max_blob_height = 0; - GetMaxStreamResolution(static_metadata_, - cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT, - cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB, - &max_blob_width, &max_blob_height); - photo_state->width->current = max_blob_width; - photo_state->width->min = max_blob_width; - photo_state->width->max = max_blob_width; + std::vector<gfx::Size> blob_resolutions; + GetStreamResolutions( + static_metadata_, cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT, + cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB, &blob_resolutions); + if (blob_resolutions.empty()) { + std::move(callback).Run(std::move(photo_state)); + return; + } + + // Sets the correct range of min/max resolution in order to bypass checks that + // the resolution caller request should fall within the range when taking + // photos. And since we are not actually use the mechanism to get other + // resolutions, we set the step to 0.0 here. + photo_state->width->current = current_blob_resolution_.width(); + photo_state->width->min = blob_resolutions.front().width(); + photo_state->width->max = blob_resolutions.back().width(); photo_state->width->step = 0.0; - photo_state->height->current = max_blob_height; - photo_state->height->min = max_blob_height; - photo_state->height->max = max_blob_height; + photo_state->height->current = current_blob_resolution_.height(); + photo_state->height->min = blob_resolutions.front().height(); + photo_state->height->max = blob_resolutions.back().height(); photo_state->height->step = 0.0; std::move(callback).Run(std::move(photo_state)); } @@ -284,9 +289,25 @@ return; } - if (!request_manager_->HasStreamsConfiguredForTakePhoto()) { - request_manager_->StopPreview( - base::BindOnce(&CameraDeviceDelegate::OnFlushed, GetWeakPtr())); + bool is_resolution_specified = settings->has_width && settings->has_height; + bool should_reconfigure_streams = + is_resolution_specified && (current_blob_resolution_.IsEmpty() || + current_blob_resolution_.width() != + static_cast<int32_t>(settings->width) || + current_blob_resolution_.height() != + static_cast<int32_t>(settings->height)); + if (!request_manager_->HasStreamsConfiguredForTakePhoto() || + should_reconfigure_streams) { + if (is_resolution_specified) { + gfx::Size new_blob_resolution(static_cast<int32_t>(settings->width), + static_cast<int32_t>(settings->height)); + request_manager_->StopPreview( + base::BindOnce(&CameraDeviceDelegate::OnFlushed, GetWeakPtr(), + std::move(new_blob_resolution))); + } else { + request_manager_->StopPreview(base::BindOnce( + &CameraDeviceDelegate::OnFlushed, GetWeakPtr(), base::nullopt)); + } set_photo_option_callback_ = std::move(callback); } else { set_photo_option_callback_.Reset(); @@ -352,7 +373,9 @@ } } -void CameraDeviceDelegate::OnFlushed(int32_t result) { +void CameraDeviceDelegate::OnFlushed( + base::Optional<gfx::Size> new_blob_resolution, + int32_t result) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); if (result) { device_context_->SetErrorState( @@ -362,7 +385,7 @@ return; } device_context_->SetState(CameraDeviceContext::State::kInitialized); - ConfigureStreams(true); + ConfigureStreams(true, std::move(new_blob_resolution)); } void CameraDeviceDelegate::OnClosed(int32_t result) { @@ -376,6 +399,7 @@ } ResetMojoInterface(); device_context_ = nullptr; + current_blob_resolution_.SetSize(0, 0); std::move(device_close_callback_).Run(); } @@ -499,10 +523,12 @@ return; } device_context_->SetState(CameraDeviceContext::State::kInitialized); - ConfigureStreams(false); + ConfigureStreams(false, base::nullopt); } -void CameraDeviceDelegate::ConfigureStreams(bool require_photo) { +void CameraDeviceDelegate::ConfigureStreams( + bool require_photo, + base::Optional<gfx::Size> new_blob_resolution) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kInitialized); @@ -529,22 +555,35 @@ // Set up context for still capture stream. We set still capture stream to the // JPEG stream configuration with maximum supported resolution. - // TODO(jcliang): Once we support SetPhotoOptions() the still capture stream - // should be configured dynamically per the photo options. + int32_t blob_width = 0; + int32_t blob_height = 0; if (require_photo) { - int32_t max_blob_width = 0, max_blob_height = 0; - GetMaxStreamResolution( + std::vector<gfx::Size> blob_resolutions; + GetStreamResolutions( static_metadata_, cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT, - cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB, &max_blob_width, - &max_blob_height); + cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB, &blob_resolutions); + if (blob_resolutions.empty()) { + LOG(ERROR) << "Failed to configure streans: No BLOB resolution found."; + return; + } + if (new_blob_resolution.has_value() && + std::find(blob_resolutions.begin(), blob_resolutions.end(), + *new_blob_resolution) != blob_resolutions.end()) { + blob_width = new_blob_resolution->width(); + blob_height = new_blob_resolution->height(); + } else { + // Use the largest resolution as default. + blob_width = blob_resolutions.back().width(); + blob_height = blob_resolutions.back().height(); + } cros::mojom::Camera3StreamPtr still_capture_stream = cros::mojom::Camera3Stream::New(); still_capture_stream->id = static_cast<uint64_t>(StreamType::kJpegOutput); still_capture_stream->stream_type = cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT; - still_capture_stream->width = max_blob_width; - still_capture_stream->height = max_blob_height; + still_capture_stream->width = blob_width; + still_capture_stream->height = blob_height; still_capture_stream->format = cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB; still_capture_stream->data_space = 0; @@ -589,10 +628,12 @@ CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE; device_ops_->ConfigureStreams( std::move(stream_config), - base::BindOnce(&CameraDeviceDelegate::OnConfiguredStreams, GetWeakPtr())); + base::BindOnce(&CameraDeviceDelegate::OnConfiguredStreams, GetWeakPtr(), + gfx::Size(blob_width, blob_height))); } void CameraDeviceDelegate::OnConfiguredStreams( + gfx::Size blob_resolution, int32_t result, cros::mojom::Camera3StreamConfigurationPtr updated_config) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); @@ -623,6 +664,9 @@ return; } + current_blob_resolution_.SetSize(blob_resolution.width(), + blob_resolution.height()); + request_manager_->SetUpStreamsAndBuffers( chrome_capture_params_.requested_format, static_metadata_, std::move(updated_config->streams)); @@ -690,14 +734,16 @@ return false; } - GetMaxStreamResolution( + std::vector<gfx::Size> yuv_resolutions; + GetStreamResolutions( static_metadata_, cros::mojom::Camera3StreamType::CAMERA3_STREAM_INPUT, - cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888, max_width, - max_height); - if (max_width == 0 || max_height == 0) { + cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888, + &yuv_resolutions); + if (yuv_resolutions.empty()) { return false; } - + *max_width = yuv_resolutions.back().width(); + *max_height = yuv_resolutions.back().height(); return true; }
diff --git a/media/capture/video/chromeos/camera_device_delegate.h b/media/capture/video/chromeos/camera_device_delegate.h index fb3a2ae4..b1d4c41 100644 --- a/media/capture/video/chromeos/camera_device_delegate.h +++ b/media/capture/video/chromeos/camera_device_delegate.h
@@ -9,11 +9,13 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/single_thread_task_runner.h" #include "media/capture/video/chromeos/mojo/camera3.mojom.h" #include "media/capture/video/chromeos/mojo/camera_common.mojom.h" #include "media/capture/video/video_capture_device.h" #include "media/capture/video_capture_types.h" +#include "ui/gfx/geometry/size.h" namespace media { @@ -104,7 +106,7 @@ void OnMojoConnectionError(); // Reconfigure streams for picture taking. - void OnFlushed(int32_t result); + void OnFlushed(base::Optional<gfx::Size> new_blob_resolution, int32_t result); // Callback method for the Close Mojo IPC call. This method resets the Mojo // connection and closes the camera device. @@ -131,8 +133,10 @@ // indicates. If there's no error OnConfiguredStreams notifies // |client_| the capture has started by calling OnStarted, and proceeds to // ConstructDefaultRequestSettings. - void ConfigureStreams(bool require_photo); + void ConfigureStreams(bool require_photo, + base::Optional<gfx::Size> new_blob_resolution); void OnConfiguredStreams( + gfx::Size blob_resolution, int32_t result, cros::mojom::Camera3StreamConfigurationPtr updated_config); @@ -171,6 +175,9 @@ int32_t camera_id_; + // Current configured resolution of BLOB stream. + gfx::Size current_blob_resolution_; + const scoped_refptr<CameraHalDelegate> camera_hal_delegate_; VideoCaptureParams chrome_capture_params_;
diff --git a/media/capture/video/chromeos/camera_device_delegate_unittest.cc b/media/capture/video/chromeos/camera_device_delegate_unittest.cc index 2a753df..d27ec7c 100644 --- a/media/capture/video/chromeos/camera_device_delegate_unittest.cc +++ b/media/capture/video/chromeos/camera_device_delegate_unittest.cc
@@ -387,9 +387,9 @@ EXPECT_EQ(CameraDeviceContext::State::kStopped, GetState()); } - unittest_internal::MockVideoCaptureClient* ResetDeviceContext() { + unittest_internal::NiceMockVideoCaptureClient* ResetDeviceContext() { auto mock_client = - std::make_unique<unittest_internal::MockVideoCaptureClient>(); + std::make_unique<unittest_internal::NiceMockVideoCaptureClient>(); auto* client_ptr = mock_client.get(); device_context_ = std::make_unique<CameraDeviceContext>(std::move(mock_client));
diff --git a/media/capture/video/chromeos/mock_video_capture_client.h b/media/capture/video/chromeos/mock_video_capture_client.h index bb03e54..e23c17c 100644 --- a/media/capture/video/chromeos/mock_video_capture_client.h +++ b/media/capture/video/chromeos/mock_video_capture_client.h
@@ -76,6 +76,8 @@ base::OnceClosure quit_cb_; }; +using NiceMockVideoCaptureClient = ::testing::NiceMock<MockVideoCaptureClient>; + } // namespace unittest_internal } // namespace media
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc index 54cd768..387ad551 100644 --- a/media/capture/video/fake_video_capture_device_unittest.cc +++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -147,7 +147,7 @@ void SetUp() override { EXPECT_CALL(*client_, OnError(_, _, _)).Times(0); } std::unique_ptr<MockVideoCaptureDeviceClient> CreateClient() { - auto result = std::make_unique<MockVideoCaptureDeviceClient>(); + auto result = std::make_unique<NiceMockVideoCaptureDeviceClient>(); ON_CALL(*result, ReserveOutputBuffer(_, _, _, _)) .WillByDefault( Invoke([](const gfx::Size& dimensions, VideoPixelFormat format, int,
diff --git a/media/capture/video/file_video_capture_device_unittest.cc b/media/capture/video/file_video_capture_device_unittest.cc index 28ab439..c32d147 100644 --- a/media/capture/video/file_video_capture_device_unittest.cc +++ b/media/capture/video/file_video_capture_device_unittest.cc
@@ -50,7 +50,8 @@ class FileVideoCaptureDeviceTest : public ::testing::Test { protected: - FileVideoCaptureDeviceTest() : client_(new MockVideoCaptureDeviceClient()) {} + FileVideoCaptureDeviceTest() + : client_(new NiceMockVideoCaptureDeviceClient()) {} void SetUp() override { EXPECT_CALL(*client_, OnError(_, _, _)).Times(0); @@ -62,7 +63,7 @@ void TearDown() override { device_->StopAndDeAllocate(); } - std::unique_ptr<MockVideoCaptureDeviceClient> client_; + std::unique_ptr<NiceMockVideoCaptureDeviceClient> client_; MockImageCaptureClient image_capture_client_; std::unique_ptr<VideoCaptureDevice> device_; VideoCaptureFormat last_format_;
diff --git a/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc b/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc index c2992ff..7224c51 100644 --- a/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc +++ b/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc
@@ -123,7 +123,7 @@ arbitrary_params.requested_format.frame_size = gfx::Size(1280, 720); arbitrary_params.requested_format.frame_rate = 30.0f; arbitrary_params.requested_format.pixel_format = PIXEL_FORMAT_I420; - auto client = std::make_unique<MockVideoCaptureDeviceClient>(); + auto client = std::make_unique<NiceMockVideoCaptureDeviceClient>(); MockVideoCaptureDeviceClient* client_ptr = client.get(); base::RunLoop wait_loop;
diff --git a/media/capture/video/mock_video_capture_device_client.h b/media/capture/video/mock_video_capture_device_client.h index 6b53add..383df0ef 100644 --- a/media/capture/video/mock_video_capture_device_client.h +++ b/media/capture/video/mock_video_capture_device_client.h
@@ -69,6 +69,9 @@ const media::VideoFrameMetadata& additional_metadata)); }; +using NiceMockVideoCaptureDeviceClient = + ::testing::NiceMock<MockVideoCaptureDeviceClient>; + } // namespace media #endif // MEDIA_CAPTURE_VIDEO_MOCK_VIDEO_CAPTURE_DEVICE_CLIENT_H_
diff --git a/media/capture/video/video_capture_device_client_unittest.cc b/media/capture/video/video_capture_device_client_unittest.cc index 15a39c93..a8f3368 100644 --- a/media/capture/video/video_capture_device_client_unittest.cc +++ b/media/capture/video/video_capture_device_client_unittest.cc
@@ -27,9 +27,10 @@ using ::testing::_; using ::testing::AtLeast; -using ::testing::Mock; using ::testing::InSequence; using ::testing::Invoke; +using ::testing::Mock; +using ::testing::NiceMock; using ::testing::SaveArg; namespace media { @@ -55,7 +56,7 @@ scoped_refptr<VideoCaptureBufferPoolImpl> buffer_pool( new VideoCaptureBufferPoolImpl( std::make_unique<VideoCaptureBufferTrackerFactoryImpl>(), 2)); - auto controller = std::make_unique<MockVideoFrameReceiver>(); + auto controller = std::make_unique<NiceMock<MockVideoFrameReceiver>>(); receiver_ = controller.get(); gpu_memory_buffer_manager_ = std::make_unique<unittest_internal::MockGpuMemoryBufferManager>(); @@ -72,7 +73,7 @@ ~VideoCaptureDeviceClientTest() override = default; protected: - MockVideoFrameReceiver* receiver_; + NiceMock<MockVideoFrameReceiver>* receiver_; std::unique_ptr<unittest_internal::MockGpuMemoryBufferManager> gpu_memory_buffer_manager_; std::unique_ptr<VideoCaptureDeviceClient> device_client_;
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc index 6408259..aa579872 100644 --- a/media/capture/video/video_capture_device_unittest.cc +++ b/media/capture/video/video_capture_device_unittest.cc
@@ -299,7 +299,7 @@ #endif std::unique_ptr<MockVideoCaptureDeviceClient> CreateDeviceClient() { - auto result = std::make_unique<MockVideoCaptureDeviceClient>(); + auto result = std::make_unique<NiceMockVideoCaptureDeviceClient>(); ON_CALL(*result, OnError(_, _, _)).WillByDefault(Invoke(DumpError)); EXPECT_CALL(*result, ReserveOutputBuffer(_, _, _, _)).Times(0); EXPECT_CALL(*result, DoOnIncomingCapturedBuffer(_, _, _, _)).Times(0);
diff --git a/media/filters/vp9_parser.h b/media/filters/vp9_parser.h index 95e98f9..e4e3be0 100644 --- a/media/filters/vp9_parser.h +++ b/media/filters/vp9_parser.h
@@ -260,6 +260,10 @@ Vp9FrameContext initial_frame_context; // Current frame entropy context after header parsing. Vp9FrameContext frame_context; + + // Segmentation and loop filter params from uncompressed header + Vp9SegmentationParams segmentation; + Vp9LoopFilterParams loop_filter; }; // A parser for VP9 bitstream.
diff --git a/media/filters/vp9_uncompressed_header_parser.cc b/media/filters/vp9_uncompressed_header_parser.cc index d69fa929..6c99ef5b 100644 --- a/media/filters/vp9_uncompressed_header_parser.cc +++ b/media/filters/vp9_uncompressed_header_parser.cc
@@ -1083,10 +1083,13 @@ } ReadLoopFilterParams(); + // Update loop_filter in current_frame_hdr + fhdr->loop_filter = context_->loop_filter_; ReadQuantizationParams(&fhdr->quant_params); if (!ReadSegmentationParams()) return false; - + // Update segmentation in current_frame_hdr + fhdr->segmentation = context_->segmentation_; if (!ReadTileInfo(fhdr)) return false;
diff --git a/mojo/public/cpp/bindings/associated_interface_ptr.h b/mojo/public/cpp/bindings/associated_interface_ptr.h index 596856c..ab77a77f 100644 --- a/mojo/public/cpp/bindings/associated_interface_ptr.h +++ b/mojo/public/cpp/bindings/associated_interface_ptr.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <cstddef> #include <string> #include <utility> @@ -36,7 +37,7 @@ // Constructs an unbound AssociatedInterfacePtr. AssociatedInterfacePtr() {} - AssociatedInterfacePtr(decltype(nullptr)) {} + AssociatedInterfacePtr(std::nullptr_t) {} AssociatedInterfacePtr(AssociatedInterfacePtr&& other) { internal_state_.Swap(&other.internal_state_); @@ -52,7 +53,7 @@ // Assigning nullptr to this class causes it to closes the associated // interface (if any) and returns the pointer to the unbound state. - AssociatedInterfacePtr& operator=(decltype(nullptr)) { + AssociatedInterfacePtr& operator=(std::nullptr_t) { reset(); return *this; }
diff --git a/mojo/public/cpp/bindings/associated_interface_request.h b/mojo/public/cpp/bindings/associated_interface_request.h index 0926f3d..10c0dc5 100644 --- a/mojo/public/cpp/bindings/associated_interface_request.h +++ b/mojo/public/cpp/bindings/associated_interface_request.h
@@ -5,6 +5,7 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ #define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ +#include <cstddef> #include <string> #include <utility> @@ -21,7 +22,7 @@ // Constructs an empty AssociatedInterfaceRequest, representing that the // client is not requesting an implementation of Interface. AssociatedInterfaceRequest() {} - AssociatedInterfaceRequest(decltype(nullptr)) {} + AssociatedInterfaceRequest(std::nullptr_t) {} explicit AssociatedInterfaceRequest(ScopedInterfaceEndpointHandle handle) : handle_(std::move(handle)) {} @@ -41,7 +42,7 @@ // Assigning to nullptr resets the AssociatedInterfaceRequest to an empty // state, closing the interface endpoint handle currently bound to it (if // any). - AssociatedInterfaceRequest& operator=(decltype(nullptr)) { + AssociatedInterfaceRequest& operator=(std::nullptr_t) { handle_.reset(); return *this; }
diff --git a/mojo/public/cpp/bindings/interface_ptr.h b/mojo/public/cpp/bindings/interface_ptr.h index f0610da3..3708859 100644 --- a/mojo/public/cpp/bindings/interface_ptr.h +++ b/mojo/public/cpp/bindings/interface_ptr.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <cstddef> #include <string> #include <utility> @@ -45,7 +46,7 @@ // Constructs an unbound InterfacePtr. InterfacePtr() {} - InterfacePtr(decltype(nullptr)) {} + InterfacePtr(std::nullptr_t) {} // Takes over the binding of another InterfacePtr. InterfacePtr(InterfacePtr&& other) noexcept { @@ -64,7 +65,7 @@ // Assigning nullptr to this class causes it to close the currently bound // message pipe (if any) and returns the pointer to the unbound state. - InterfacePtr& operator=(decltype(nullptr)) { + InterfacePtr& operator=(std::nullptr_t) { reset(); return *this; }
diff --git a/mojo/public/cpp/bindings/interface_request.h b/mojo/public/cpp/bindings/interface_request.h index 9ace44c..03372bc 100644 --- a/mojo/public/cpp/bindings/interface_request.h +++ b/mojo/public/cpp/bindings/interface_request.h
@@ -5,6 +5,7 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ #define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ +#include <cstddef> #include <string> #include <utility> @@ -30,7 +31,7 @@ // Constructs an empty InterfaceRequest, representing that the client is not // requesting an implementation of Interface. InterfaceRequest() {} - InterfaceRequest(decltype(nullptr)) {} + InterfaceRequest(std::nullptr_t) {} explicit InterfaceRequest(ScopedMessagePipeHandle handle) : handle_(std::move(handle)) {} @@ -46,7 +47,7 @@ // Assigning to nullptr resets the InterfaceRequest to an empty state, // closing the message pipe currently bound to it (if any). - InterfaceRequest& operator=(decltype(nullptr)) { + InterfaceRequest& operator=(std::nullptr_t) { handle_.reset(); return *this; }
diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h index 5c88f5a..4dcddd15 100644 --- a/mojo/public/cpp/bindings/struct_ptr.h +++ b/mojo/public/cpp/bindings/struct_ptr.h
@@ -5,6 +5,7 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ #define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ +#include <cstddef> #include <functional> #include <memory> #include <new> @@ -35,11 +36,11 @@ using Struct = S; StructPtr() = default; - StructPtr(decltype(nullptr)) {} + StructPtr(std::nullptr_t) {} ~StructPtr() = default; - StructPtr& operator=(decltype(nullptr)) { + StructPtr& operator=(std::nullptr_t) { reset(); return *this; } @@ -130,11 +131,11 @@ using Struct = S; InlinedStructPtr() : state_(NIL) {} - InlinedStructPtr(decltype(nullptr)) : state_(NIL) {} + InlinedStructPtr(std::nullptr_t) : state_(NIL) {} ~InlinedStructPtr() {} - InlinedStructPtr& operator=(decltype(nullptr)) { + InlinedStructPtr& operator=(std::nullptr_t) { reset(); return *this; }
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index a8182b7..5644ab5 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc
@@ -227,14 +227,8 @@ // Initialize ThreadPool. ThreadPool::StartWithDefaultParams() doesn't // work on NACL. base::ThreadPool::Create("RemotingChromeApp"); - // TODO(etiennep): Change this to 2 in future CL. - constexpr int kBackgroundMaxThreads = 3; constexpr int kForegroundMaxThreads = 3; - constexpr base::TimeDelta kSuggestedReclaimTime = - base::TimeDelta::FromSeconds(30); - base::ThreadPool::GetInstance()->Start( - {{kBackgroundMaxThreads, kSuggestedReclaimTime}, - {kForegroundMaxThreads, kSuggestedReclaimTime}}); + base::ThreadPool::GetInstance()->Start({kForegroundMaxThreads}); return true; } @@ -250,8 +244,7 @@ base::DictionaryValue* message_dict = nullptr; std::string method; base::DictionaryValue* data = nullptr; - if (!json.get() || - !json->GetAsDictionary(&message_dict) || + if (!json.get() || !json->GetAsDictionary(&message_dict) || !message_dict->GetString("method", &method) || !message_dict->GetDictionary("data", &data)) { LOG(ERROR) << "Received invalid message:" << message.AsString(); @@ -633,8 +626,8 @@ experiments, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); } - VLOG(0) << "Connecting to " << host_jid - << ". Local jid: " << local_jid << "."; + VLOG(0) << "Connecting to " << host_jid << ". Local jid: " << local_jid + << "."; std::string key_filter; if (!data.GetString("keyFilter", &key_filter)) { @@ -770,7 +763,7 @@ } void ChromotingInstance::HandleInjectKeyEvent( - const base::DictionaryValue& data) { + const base::DictionaryValue& data) { int usb_keycode = 0; bool is_pressed = false; if (!data.GetInteger("usbKeycode", &usb_keycode) || @@ -838,10 +831,8 @@ int y_dpi = kDefaultDPI; if (!data.GetInteger("width", &width) || !data.GetInteger("height", &height) || - !data.GetInteger("x_dpi", &x_dpi) || - !data.GetInteger("y_dpi", &y_dpi) || - width <= 0 || height <= 0 || - x_dpi <= 0 || y_dpi <= 0) { + !data.GetInteger("x_dpi", &x_dpi) || !data.GetInteger("y_dpi", &y_dpi) || + width <= 0 || height <= 0 || x_dpi <= 0 || y_dpi <= 0) { LOG(ERROR) << "Invalid notifyClientResolution."; return; } @@ -963,8 +954,9 @@ void ChromotingInstance::HandleAllowMouseLockMessage() { // Create the mouse lock handler and route cursor shape messages through it. mouse_locker_.reset(new PepperMouseLocker( - this, base::Bind(&PepperInputHandler::set_send_mouse_move_deltas, - base::Unretained(&input_handler_)), + this, + base::Bind(&PepperInputHandler::set_send_mouse_move_deltas, + base::Unretained(&input_handler_)), &cursor_setter_)); empty_cursor_filter_.set_cursor_stub(mouse_locker_.get()); } @@ -1120,7 +1112,9 @@ } // static -bool ChromotingInstance::LogToUI(int severity, const char* file, int line, +bool ChromotingInstance::LogToUI(int severity, + const char* file, + int line, size_t message_start, const std::string& str) { PP_LogLevel log_level = PP_LOGLEVEL_ERROR;
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index 7cd8f393..457221c 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -106,7 +106,7 @@ return result; } -std::string IdentityManager::GetPrimaryAccountId() const { +CoreAccountId IdentityManager::GetPrimaryAccountId() const { return GetPrimaryAccountInfo().account_id; } @@ -124,7 +124,8 @@ accounts.reserve(account_ids_with_tokens.size()); for (const std::string& account_id : account_ids_with_tokens) { - accounts.push_back(GetAccountInfoForAccountWithRefreshToken(account_id)); + accounts.push_back( + GetAccountInfoForAccountWithRefreshToken(CoreAccountId(account_id))); } return accounts; @@ -139,7 +140,8 @@ accounts.reserve(account_ids_with_tokens.size()); for (const std::string& account_id : account_ids_with_tokens) { - accounts.push_back(GetAccountInfoForAccountWithRefreshToken(account_id)); + accounts.push_back( + GetAccountInfoForAccountWithRefreshToken(CoreAccountId(account_id))); } return accounts; @@ -156,17 +158,17 @@ } bool IdentityManager::HasAccountWithRefreshToken( - const std::string& account_id) const { + const CoreAccountId& account_id) const { return token_service_->RefreshTokenIsAvailable(account_id); } bool IdentityManager::HasAccountWithRefreshTokenInPersistentErrorState( - const std::string& account_id) const { + const CoreAccountId& account_id) const { return GetErrorStateOfRefreshTokenForAccount(account_id).IsPersistentError(); } GoogleServiceAuthError IdentityManager::GetErrorStateOfRefreshTokenForAccount( - const std::string& account_id) const { + const CoreAccountId& account_id) const { return token_service_->GetAuthError(account_id); } @@ -194,7 +196,7 @@ base::Optional<AccountInfo> IdentityManager::FindAccountInfoForAccountWithRefreshTokenByAccountId( - const std::string& account_id) const { + const CoreAccountId& account_id) const { AccountInfo account_info = account_tracker_service_->GetAccountInfo(account_id); @@ -239,7 +241,7 @@ std::unique_ptr<AccessTokenFetcher> IdentityManager::CreateAccessTokenFetcherForAccount( - const std::string& account_id, + const CoreAccountId& account_id, const std::string& oauth_consumer_name, const identity::ScopeSet& scopes, AccessTokenFetcher::TokenCallback callback, @@ -251,7 +253,7 @@ std::unique_ptr<AccessTokenFetcher> IdentityManager::CreateAccessTokenFetcherForAccount( - const std::string& account_id, + const CoreAccountId& account_id, const std::string& oauth_consumer_name, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const identity::ScopeSet& scopes, @@ -264,7 +266,7 @@ std::unique_ptr<AccessTokenFetcher> IdentityManager::CreateAccessTokenFetcherForClient( - const std::string& account_id, + const CoreAccountId& account_id, const std::string& client_id, const std::string& client_secret, const std::string& oauth_consumer_name, @@ -277,7 +279,7 @@ } void IdentityManager::RemoveAccessTokenFromCache( - const std::string& account_id, + const CoreAccountId& account_id, const identity::ScopeSet& scopes, const std::string& access_token) { token_service_->InvalidateAccessToken(account_id, scopes, access_token); @@ -285,7 +287,7 @@ std::unique_ptr<signin::UbertokenFetcher> IdentityManager::CreateUbertokenFetcherForAccount( - const std::string& account_id, + const CoreAccountId& account_id, signin::UbertokenFetcher::CompletionCallback callback, gaia::GaiaSource source, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, @@ -313,10 +315,13 @@ AccountTrackerService::RegisterPrefs(registry); } -std::string IdentityManager::PickAccountIdForAccount( +CoreAccountId IdentityManager::PickAccountIdForAccount( const std::string& gaia, const std::string& email) const { - return account_tracker_service_->PickAccountIdForAccount(gaia, email); + // TODO(triploblastic@): Remove explicit conversion once signin_manager + // has been fixed to use CoreAccountId. + return CoreAccountId( + account_tracker_service_->PickAccountIdForAccount(gaia, email)); } IdentityManager::AccountIdMigrationState @@ -370,12 +375,12 @@ gaia_cookie_manager_service_->ForceOnCookieChangeProcessing(); } -std::string IdentityManager::LegacySeedAccountInfo(const AccountInfo& info) { +CoreAccountId IdentityManager::LegacySeedAccountInfo(const AccountInfo& info) { return account_tracker_service_->SeedAccountInfo(info); } void IdentityManager::LegacyAddAccountFromSystem( - const std::string& account_id) { + const CoreAccountId& account_id) { token_service_->GetDelegate()->AddAccountFromSystem(account_id); } #endif @@ -402,7 +407,7 @@ } void IdentityManager::ForceRefreshOfExtendedAccountInfo( - const std::string& account_id) { + const CoreAccountId& account_id) { DCHECK(HasAccountWithRefreshToken(account_id)); account_fetcher_service_->ForceRefreshOfAccountInfo(account_id); } @@ -445,7 +450,7 @@ } AccountInfo IdentityManager::GetAccountInfoForAccountWithRefreshToken( - const std::string& account_id) const { + const CoreAccountId& account_id) const { // TODO(https://crbug.com/919793): This invariant is not currently possible to // enforce on Android due to the underlying relationship between // O2TS::GetAccounts(), O2TS::RefreshTokenIsAvailable(), and @@ -466,8 +471,9 @@ // always set. // TODO(860492): Remove this special case once supervised user support is // removed. - DCHECK(!account_info.IsEmpty() || account_id == kSupervisedUserPseudoEmail); - if (account_id == kSupervisedUserPseudoEmail && account_info.IsEmpty()) { + DCHECK(!account_info.IsEmpty() || + account_id.id == kSupervisedUserPseudoEmail); + if (account_id.id == kSupervisedUserPseudoEmail && account_info.IsEmpty()) { account_info.account_id = account_id; account_info.email = kSupervisedUserPseudoEmail; account_info.gaia = kSupervisedUserPseudoGaiaID; @@ -504,7 +510,7 @@ void IdentityManager::OnRefreshTokenAvailable(const std::string& account_id) { CoreAccountInfo account_info = - GetAccountInfoForAccountWithRefreshToken(account_id); + GetAccountInfoForAccountWithRefreshToken(CoreAccountId(account_id)); for (auto& observer : observer_list_) { observer.OnRefreshTokenUpdatedForAccount(account_info); @@ -531,7 +537,7 @@ const std::string& account_id, const GoogleServiceAuthError& auth_error) { CoreAccountInfo account_info = - GetAccountInfoForAccountWithRefreshToken(account_id); + GetAccountInfoForAccountWithRefreshToken(CoreAccountId(account_id)); for (auto& observer : observer_list_) observer.OnErrorStateOfRefreshTokenUpdatedForAccount(account_info,
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index b6f9c8d1..7359413 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -209,7 +209,7 @@ // Provides access to the account ID of the user's primary account. Simple // convenience wrapper over GetPrimaryAccountInfo().account_id. - std::string GetPrimaryAccountId() const; + CoreAccountId GetPrimaryAccountId() const; // Returns whether the user's primary account is available. bool HasPrimaryAccount() const; @@ -233,14 +233,14 @@ AccountsInCookieJarInfo GetAccountsInCookieJar() const; // Returns true if a refresh token exists for |account_id|. - bool HasAccountWithRefreshToken(const std::string& account_id) const; + bool HasAccountWithRefreshToken(const CoreAccountId& account_id) const; // Returns true if (a) a refresh token exists for |account_id|, and (b) the // refresh token is in a persistent error state (defined as // GoogleServiceAuthError::IsPersistentError() returning true for the error // returned by GetErrorStateOfRefreshTokenForAccount(account_id)). bool HasAccountWithRefreshTokenInPersistentErrorState( - const std::string& account_id) const; + const CoreAccountId& account_id) const; // Returns the error state of the refresh token associated with |account_id|. // In particular: Returns GoogleServiceAuthError::AuthErrorNone() if either @@ -248,7 +248,7 @@ // not in a persistent error state. Otherwise, returns the last persistent // error that was detected when using the refresh token. GoogleServiceAuthError GetErrorStateOfRefreshTokenForAccount( - const std::string& account_id) const; + const CoreAccountId& account_id) const; // Returns true if (a) the primary account exists, and (b) a refresh token // exists for the primary account. @@ -269,7 +269,7 @@ // without allocating memory for the vector. base::Optional<AccountInfo> FindAccountInfoForAccountWithRefreshTokenByAccountId( - const std::string& account_id) const; + const CoreAccountId& account_id) const; // Looks up and returns information for account with given |email_address|. If // the account cannot be found, return an empty optional. This is equivalent @@ -288,7 +288,7 @@ // Creates an AccessTokenFetcher given the passed-in information. std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForAccount( - const std::string& account_id, + const CoreAccountId& account_id, const std::string& oauth_consumer_name, const identity::ScopeSet& scopes, AccessTokenFetcher::TokenCallback callback, @@ -297,7 +297,7 @@ // Creates an AccessTokenFetcher given the passed-in information, allowing // to specify a custom |url_loader_factory| as well. std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForAccount( - const std::string& account_id, + const CoreAccountId& account_id, const std::string& oauth_consumer_name, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const identity::ScopeSet& scopes, @@ -308,7 +308,7 @@ // specify custom |client_id| and |client_secret| to identify the OAuth client // app. std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForClient( - const std::string& account_id, + const CoreAccountId& account_id, const std::string& client_id, const std::string& client_secret, const std::string& oauth_consumer_name, @@ -320,14 +320,14 @@ // given information, removes that entry; in this case, the next access token // request for |account_id| and |scopes| will fetch a new token from the // network. Otherwise, is a no-op. - void RemoveAccessTokenFromCache(const std::string& account_id, + void RemoveAccessTokenFromCache(const CoreAccountId& account_id, const identity::ScopeSet& scopes, const std::string& access_token); // Creates an UbertokenFetcher given the passed-in information, allowing // to specify a custom |url_loader_factory| as well. std::unique_ptr<signin::UbertokenFetcher> CreateUbertokenFetcherForAccount( - const std::string& account_id, + const CoreAccountId& account_id, signin::UbertokenFetcher::CompletionCallback callback, gaia::GaiaSource source, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, @@ -347,8 +347,8 @@ // migration state. // TODO(https://crbug.com/883272): Remove once all platform have migrated to // the new account_id based on gaia (currently, only Chrome OS remains). - std::string PickAccountIdForAccount(const std::string& gaia, - const std::string& email) const; + CoreAccountId PickAccountIdForAccount(const std::string& gaia, + const std::string& email) const; // Returns the currently saved state for the migration of accounts IDs. AccountIdMigrationState GetAccountIdMigrationState() const; @@ -406,14 +406,14 @@ // NOTE: In normal usage, this method SHOULD NOT be called for getting the // account id. It's only for replacement of production code. // TODO(https://crbug.com/926940): Eliminate the need to expose this. - std::string LegacySeedAccountInfo(const AccountInfo& info); + CoreAccountId LegacySeedAccountInfo(const AccountInfo& info); // Adds a given account to the token service from a system account. This // API calls OAuth2TokenServiceDelegate::AddAccountFromSystem and it // triggers platform specific implementation for IOS. // NOTE: In normal usage, this method SHOULD NOT be called. // TODO(https://crbug.com/930094): Eliminate the need to expose this. - void LegacyAddAccountFromSystem(const std::string& account_id); + void LegacyAddAccountFromSystem(const CoreAccountId& account_id); #endif #if defined(OS_ANDROID) || defined(OS_IOS) @@ -444,7 +444,7 @@ // account and has as its semantics that it fetches the account info for the // account, triggering an OnExtendedAccountInfoUpdated() callback if the info // was successfully fetched. - void ForceRefreshOfExtendedAccountInfo(const std::string& refresh_token); + void ForceRefreshOfExtendedAccountInfo(const CoreAccountId& account_id); #endif // Methods to register or remove observers. @@ -576,7 +576,7 @@ // Populates and returns an AccountInfo object corresponding to |account_id|, // which must be an account with a refresh token. AccountInfo GetAccountInfoForAccountWithRefreshToken( - const std::string& account_id) const; + const CoreAccountId& account_id) const; // Fires the IdentityManager::Observer::OnPrimaryAccountSet() notification // to observers.
diff --git a/services/network/public/cpp/cors/preflight_result.cc b/services/network/public/cpp/cors/preflight_result.cc index ac651bd..c3233987 100644 --- a/services/network/public/cpp/cors/preflight_result.cc +++ b/services/network/public/cpp/cors/preflight_result.cc
@@ -28,12 +28,7 @@ // Maximum cache expiry time. Even if a CORS-preflight response contains // Access-Control-Max-Age header that specifies a longer expiry time, this // maximum time is applied. -// -// Note: Should be short enough to minimize the risk of using a poisoned cache -// after switching to a secure network. -// TODO(toyoshim): Consider to invalidate all entries when network configuration -// is changed. See also discussion at https://crbug.com/131368. -constexpr base::TimeDelta kMaxTimeout = base::TimeDelta::FromSeconds(600); +constexpr base::TimeDelta kMaxTimeout = base::TimeDelta::FromHours(2); // Holds TickClock instance to overwrite TimeTicks::Now() for testing. const base::TickClock* tick_clock_for_testing = nullptr;
diff --git a/third_party/blink/renderer/DEPS b/third_party/blink/renderer/DEPS index f7983fe..eb3e573 100644 --- a/third_party/blink/renderer/DEPS +++ b/third_party/blink/renderer/DEPS
@@ -10,7 +10,6 @@ "+base/feature_list.h", "+base/format_macros.h", "+base/gtest_prod_util.h", - "+base/hash/hash.h", "+base/location.h", "+base/logging.h", "+base/macros.h",
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index bd52ca6..3ae968a 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -13,6 +13,7 @@ "+base/strings/stringprintf.h", "+base/synchronization/waitable_event.h", "+base/task/sequence_manager/task_time_observer.h", + "+base/time", "+base/unguessable_token.h", "+build/mac", "+build/win", @@ -87,6 +88,7 @@ # Additional allowed includes for tests. ".*_test(_.*)?\.(cc|h)" : [ "+base/message_loop/message_loop.h", + "+base/test/test_mock_time_task_runner.h", # Test harness may use cc directly instead of going through WebViewImpl etc. "+cc", "+components/ukm/test_ukm_recorder.h",
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget.cc b/third_party/blink/renderer/core/display_lock/display_lock_budget.cc index 3b8680bb..9cdd3da 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_budget.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_budget.cc
@@ -3,12 +3,14 @@ // found in the LICENSE file. #include "third_party/blink/renderer/core/display_lock/display_lock_budget.h" + +#include "base/time/default_tick_clock.h" #include "third_party/blink/renderer/core/display_lock/display_lock_context.h" namespace blink { DisplayLockBudget::DisplayLockBudget(DisplayLockContext* context) - : context_(context) {} + : clock_(base::DefaultTickClock::GetInstance()), context_(context) {} bool DisplayLockBudget::MarkAncestorsDirtyForPhaseIfNeeded(Phase phase) { switch (phase) {
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget.h b/third_party/blink/renderer/core/display_lock/display_lock_budget.h index 4199cb9..f715ab2 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_budget.h +++ b/third_party/blink/renderer/core/display_lock/display_lock_budget.h
@@ -8,6 +8,10 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/heap/member.h" +namespace base { +class TickClock; +} + namespace blink { class DisplayLockContext; @@ -39,6 +43,10 @@ // true indicating that another frame is needed. virtual bool NeedsLifecycleUpdates() const = 0; + // The caller is the owner of the |clock|. The |clock| must outlive the + // DisplayLockBudget. + void SetTickClockForTesting(const base::TickClock* clock) { clock_ = clock; } + protected: // Marks the ancestor chain dirty for the given phase if it's needed. Returns // true if the ancestors were marked dirty and false otherwise. @@ -47,6 +55,8 @@ // Returns true if there is likely to be work for the given phase. bool IsElementDirtyForPhase(Phase) const; + const base::TickClock* clock_; + private: // This is a backpointer to the context, which should always outlive this // budget, so it's untraced.
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc index c3567b4..3f57aa0 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "third_party/blink/renderer/core/display_lock/display_lock_budget.h" + +#include "base/test/test_mock_time_task_runner.h" #include "third_party/blink/renderer/bindings/core/v8/script_function.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/core/display_lock/display_lock_context.h" @@ -12,7 +14,6 @@ #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" -#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" namespace blink { @@ -22,6 +23,7 @@ RenderingTest::SetUp(); features_backup_.emplace(); RuntimeEnabledFeatures::SetDisplayLockingEnabled(true); + test_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); } void TearDown() override { @@ -46,6 +48,9 @@ context->update_budget_ = std::move(budget); } + protected: + scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; + private: base::Optional<RuntimeEnabledFeatures::Backup> features_backup_; }; @@ -295,8 +300,7 @@ ASSERT_TRUE(element->GetDisplayLockContext()); YieldingDisplayLockBudget budget(element->GetDisplayLockContext()); - - WTF::ScopedMockClock clock; + budget.SetTickClockForTesting(test_task_runner_->GetMockTickClock()); // When acquiring, we need to update the layout with the locked size, so we // need an update. @@ -314,13 +318,16 @@ EXPECT_TRUE(budget.NeedsLifecycleUpdates()); // Advancing the clock a bit will make us still want to the phases. - clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(budget) / 2)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMillisecondsD(GetBudgetMs(budget) / 2)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); // However, once we're out of budget, we will only do the next phase. - clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(budget))); + test_task_runner_->FastForwardBy( + TimeDelta::FromMillisecondsD(GetBudgetMs(budget))); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); @@ -340,7 +347,8 @@ // Now that we're out of budget, phases performed previously should remain // true. - clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(budget) * 2)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMillisecondsD(GetBudgetMs(budget) * 2)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); @@ -354,7 +362,8 @@ EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); - clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(budget) * 2)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMillisecondsD(GetBudgetMs(budget) * 2)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); @@ -368,7 +377,7 @@ EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); - clock.Advance(TimeDelta::FromMillisecondsD(10000)); + test_task_runner_->FastForwardBy(TimeDelta::FromMillisecondsD(10000)); } } @@ -400,6 +409,7 @@ new YieldingDisplayLockBudget(element->GetDisplayLockContext())); ; auto* budget = budget_owned.get(); + budget->SetTickClockForTesting(test_task_runner_->GetMockTickClock()); { auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame()); ScriptState::Scope scope(script_state); @@ -407,8 +417,6 @@ ResetBudget(std::move(budget_owned), element->GetDisplayLockContext()); } - WTF::ScopedMockClock clock; - // When acquiring, we need to update the layout with the locked size, so we // need an update. EXPECT_TRUE(budget->NeedsLifecycleUpdates()); @@ -429,7 +437,8 @@ EXPECT_TRUE(parent->NeedsStyleRecalc() || parent->ChildNeedsStyleRecalc()); EXPECT_TRUE(element->NeedsStyleRecalc() || element->ChildNeedsStyleRecalc()); - clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(*budget) * 2)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMillisecondsD(GetBudgetMs(*budget) * 2)); EXPECT_TRUE(budget->ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); EXPECT_FALSE(budget->ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
diff --git a/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.cc b/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.cc index b8425be..7ffac6e6 100644 --- a/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.cc +++ b/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.h" +#include "base/time/tick_clock.h" #include "third_party/blink/renderer/platform/wtf/time.h" #include <algorithm> @@ -24,7 +25,7 @@ return true; // Otherwise, we can still do work while we're not past the deadline. - return CurrentTimeTicks() < deadline_; + return clock_->NowTicks() < deadline_; } void YieldingDisplayLockBudget::DidPerformPhase(Phase phase) { @@ -42,7 +43,7 @@ void YieldingDisplayLockBudget::WillStartLifecycleUpdate() { ++lifecycle_count_; deadline_ = - CurrentTimeTicks() + TimeDelta::FromMillisecondsD(GetCurrentBudgetMs()); + clock_->NowTicks() + TimeDelta::FromMillisecondsD(GetCurrentBudgetMs()); // Figure out the next phase we would run. If we had completed a phase before, // then we should try to complete the next one, otherwise we'll start with the
diff --git a/third_party/blink/renderer/core/dom/idle_deadline.cc b/third_party/blink/renderer/core/dom/idle_deadline.cc index f59ec80..9a97ccb 100644 --- a/third_party/blink/renderer/core/dom/idle_deadline.cc +++ b/third_party/blink/renderer/core/dom/idle_deadline.cc
@@ -4,18 +4,20 @@ #include "third_party/blink/renderer/core/dom/idle_deadline.h" +#include "base/time/default_tick_clock.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/core/timing/performance.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" -#include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { IdleDeadline::IdleDeadline(TimeTicks deadline, CallbackType callback_type) - : deadline_(deadline), callback_type_(callback_type) {} + : deadline_(deadline), + callback_type_(callback_type), + clock_(base::DefaultTickClock::GetInstance()) {} double IdleDeadline::timeRemaining() const { - TimeDelta time_remaining = deadline_ - CurrentTimeTicks(); + TimeDelta time_remaining = deadline_ - clock_->NowTicks(); if (time_remaining < TimeDelta() || ThreadScheduler::Current()->ShouldYieldForHighPriorityWork()) { return 0;
diff --git a/third_party/blink/renderer/core/dom/idle_deadline.h b/third_party/blink/renderer/core/dom/idle_deadline.h index 2f4f0f1..23593a6 100644 --- a/third_party/blink/renderer/core/dom/idle_deadline.h +++ b/third_party/blink/renderer/core/dom/idle_deadline.h
@@ -10,6 +10,10 @@ #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/time.h" +namespace base { +class TickClock; +} + namespace blink { class CORE_EXPORT IdleDeadline : public ScriptWrappable { @@ -32,9 +36,14 @@ return callback_type_ == CallbackType::kCalledByTimeout; } + // The caller is the owner of the |clock|. The |clock| must outlive the + // IdleDeadline. + void SetTickClockForTesting(const base::TickClock* clock) { clock_ = clock; } + private: TimeTicks deadline_; CallbackType callback_type_; + const base::TickClock* clock_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/third_party/blink/renderer/core/dom/idle_deadline_test.cc index 7de829d..60ca7c7 100644 --- a/third_party/blink/renderer/core/dom/idle_deadline_test.cc +++ b/third_party/blink/renderer/core/dom/idle_deadline_test.cc
@@ -5,12 +5,11 @@ #include "third_party/blink/renderer/core/dom/idle_deadline.h" #include "base/single_thread_task_runner.h" +#include "base/test/test_mock_time_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h" -#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" -#include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { namespace { @@ -74,16 +73,20 @@ class IdleDeadlineTest : public testing::Test { public: - void SetUp() override { clock_.Advance(TimeDelta::FromSeconds(1)); } + void SetUp() override { + test_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + } - private: - WTF::ScopedMockClock clock_; + protected: + scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; }; TEST_F(IdleDeadlineTest, DeadlineInFuture) { auto* deadline = MakeGarbageCollected<IdleDeadline>( TimeTicks() + TimeDelta::FromSecondsD(1.25), IdleDeadline::CallbackType::kCalledWhenIdle); + deadline->SetTickClockForTesting(test_task_runner_->GetMockTickClock()); + test_task_runner_->FastForwardBy(TimeDelta::FromSeconds(1)); // Note: the deadline is computed with reduced resolution. EXPECT_FLOAT_EQ(250.0, deadline->timeRemaining()); } @@ -92,6 +95,8 @@ auto* deadline = MakeGarbageCollected<IdleDeadline>( TimeTicks() + TimeDelta::FromSecondsD(0.75), IdleDeadline::CallbackType::kCalledWhenIdle); + deadline->SetTickClockForTesting(test_task_runner_->GetMockTickClock()); + test_task_runner_->FastForwardBy(TimeDelta::FromSeconds(1)); EXPECT_FLOAT_EQ(0, deadline->timeRemaining()); } @@ -102,6 +107,8 @@ auto* deadline = MakeGarbageCollected<IdleDeadline>( TimeTicks() + TimeDelta::FromSecondsD(1.25), IdleDeadline::CallbackType::kCalledWhenIdle); + deadline->SetTickClockForTesting(test_task_runner_->GetMockTickClock()); + test_task_runner_->FastForwardBy(TimeDelta::FromSeconds(1)); EXPECT_FLOAT_EQ(0, deadline->timeRemaining()); }
diff --git a/third_party/blink/renderer/core/dom/user_gesture_indicator.cc b/third_party/blink/renderer/core/dom/user_gesture_indicator.cc index 43b3f08..477a3bbdb 100644 --- a/third_party/blink/renderer/core/dom/user_gesture_indicator.cc +++ b/third_party/blink/renderer/core/dom/user_gesture_indicator.cc
@@ -4,12 +4,12 @@ #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" +#include "base/time/default_clock.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/platform/histogram.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" -#include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { @@ -21,7 +21,8 @@ UserGestureToken::UserGestureToken(Status status) : consumable_gestures_(0), - timestamp_(WTF::CurrentTime()), + clock_(base::DefaultClock::GetInstance()), + timestamp_(clock_->Now().ToDoubleT()), timeout_policy_(kDefault), was_forwarded_cross_process_(false) { if (status == kNewGesture || !UserGestureIndicator::CurrentTokenThreadSafe()) @@ -52,7 +53,7 @@ } void UserGestureToken::ResetTimestamp() { - timestamp_ = WTF::CurrentTime(); + timestamp_ = clock_->Now().ToDoubleT(); } bool UserGestureToken::HasTimedOut() const { @@ -61,7 +62,7 @@ double timeout = timeout_policy_ == kOutOfProcess ? kUserGestureOutOfProcessTimeout : kUserGestureTimeout; - return WTF::CurrentTime() - timestamp_ > timeout; + return clock_->Now().ToDoubleT() - timestamp_ > timeout; } bool UserGestureToken::WasForwardedCrossProcess() const {
diff --git a/third_party/blink/renderer/core/dom/user_gesture_indicator.h b/third_party/blink/renderer/core/dom/user_gesture_indicator.h index 12736ad6..b64df7c10 100644 --- a/third_party/blink/renderer/core/dom/user_gesture_indicator.h +++ b/third_party/blink/renderer/core/dom/user_gesture_indicator.h
@@ -10,6 +10,10 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/wtf/ref_counted.h" +namespace base { +class Clock; +} + namespace blink { // A UserGestureToken represents the current state of a user gesture. It can be @@ -32,6 +36,9 @@ // need to investigate the usecase closely. bool HasGestures() const; + void SetClockForTesting(const base::Clock* clock) { clock_ = clock; } + void ResetTimestampForTesting() { ResetTimestamp(); } + private: UserGestureToken(Status); @@ -44,6 +51,7 @@ void SetWasForwardedCrossProcess(); size_t consumable_gestures_; + const base::Clock* clock_; double timestamp_; TimeoutPolicy timeout_policy_; bool was_forwarded_cross_process_;
diff --git a/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc b/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc index f2aa169..f58b598 100644 --- a/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc +++ b/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc
@@ -4,10 +4,9 @@ #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" +#include "base/test/test_mock_time_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" -#include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { @@ -112,17 +111,20 @@ } TEST(UserGestureIndicatorTest, Timeouts) { - WTF::ScopedMockClock clock; - + auto test_task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); { // Token times out after 1 second. std::unique_ptr<UserGestureIndicator> user_gesture_scope = LocalFrame::NotifyUserActivation(nullptr); scoped_refptr<UserGestureToken> token = user_gesture_scope->CurrentToken(); + token->SetClockForTesting(test_task_runner->GetMockClock()); + // Timestamp is initialized to Now() in constructor using the default clock, + // reset it so it gets the Now() of the mock clock. + token->ResetTimestampForTesting(); EXPECT_TRUE(token->HasGestures()); - clock.Advance(TimeDelta::FromSecondsD(0.75)); + test_task_runner->FastForwardBy(TimeDelta::FromSecondsD(0.75)); EXPECT_TRUE(token->HasGestures()); - clock.Advance(TimeDelta::FromSecondsD(0.75)); + test_task_runner->FastForwardBy(TimeDelta::FromSecondsD(0.75)); EXPECT_FALSE(token->HasGestures()); } @@ -134,16 +136,20 @@ std::unique_ptr<UserGestureIndicator> user_gesture_scope = LocalFrame::NotifyUserActivation(nullptr); token = user_gesture_scope->CurrentToken(); + token->SetClockForTesting(test_task_runner->GetMockClock()); + // Timestamp is initialized to Now() in constructor using the default + // clock, reset it so it gets the Now() of the mock clock. + token->ResetTimestampForTesting(); EXPECT_TRUE(token->HasGestures()); - clock.Advance(TimeDelta::FromSecondsD(0.75)); + test_task_runner->FastForwardBy(TimeDelta::FromSecondsD(0.75)); EXPECT_TRUE(token->HasGestures()); } { UserGestureIndicator user_gesture_scope(token.get()); - clock.Advance(TimeDelta::FromSecondsD(0.75)); + test_task_runner->FastForwardBy(TimeDelta::FromSecondsD(0.75)); EXPECT_TRUE(token->HasGestures()); - clock.Advance(TimeDelta::FromSecondsD(0.75)); + test_task_runner->FastForwardBy(TimeDelta::FromSecondsD(0.75)); EXPECT_FALSE(token->HasGestures()); } }
diff --git a/third_party/blink/renderer/core/exported/web_layer_test.cc b/third_party/blink/renderer/core/exported/web_layer_test.cc index 47cf3fc..0cb27052 100644 --- a/third_party/blink/renderer/core/exported/web_layer_test.cc +++ b/third_party/blink/renderer/core/exported/web_layer_test.cc
@@ -553,6 +553,70 @@ EXPECT_FALSE(transform_node->transform_changed); } +// This test ensures that the correct transform nodes are created and bits set +// so that the browser controls movement adjustments needed by bottom-fixed +// elements will work. +TEST_P(WebLayerListSimTest, AffectedByOuterViewportBoundsDelta) { + // TODO(bokan): This test will have to be reevaluated for CAP. It looks like + // the fixed layer isn't composited in CAP. + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + return; + + InitializeWithHTML(R"HTML( + <!DOCTYPE html> + <style> + body { height: 2000px; } + #fixed { + width: 100px; + height: 100px; + position: fixed; + left: 0; + background-color: red; + } + </style> + <div id='fixed'></div> + )HTML"); + + auto* fixed_element = GetElementById("fixed"); + auto* fixed_element_layer = ContentLayerAt(ContentLayerCount() - 2); + DCHECK_EQ(fixed_element_layer->element_id(), + CompositorElementIdFromUniqueObjectId( + fixed_element->GetLayoutObject()->UniqueId(), + CompositorElementIdNamespace::kPrimary)); + + // Fix the DIV to the bottom of the viewport. Since the viewport height will + // expand/contract, the fixed element will need to be moved as the bounds + // delta changes. + { + fixed_element->setAttribute(html_names::kStyleAttr, "bottom: 0"); + Compositor().BeginFrame(); + + auto transform_tree_index = fixed_element_layer->transform_tree_index(); + auto* transform_node = + GetPropertyTrees()->transform_tree.Node(transform_tree_index); + + DCHECK(transform_node); + EXPECT_FALSE(transform_node->moved_by_outer_viewport_bounds_delta_x); + EXPECT_TRUE(transform_node->moved_by_outer_viewport_bounds_delta_y); + } + + // Fix it to the top now. Since the top edge doesn't change (relative to the + // renderer origin), we no longer need to move it as the bounds delta + // changes. + { + fixed_element->setAttribute(html_names::kStyleAttr, "top: 0"); + Compositor().BeginFrame(); + + auto transform_tree_index = fixed_element_layer->transform_tree_index(); + auto* transform_node = + GetPropertyTrees()->transform_tree.Node(transform_tree_index); + + DCHECK(transform_node); + EXPECT_FALSE(transform_node->moved_by_outer_viewport_bounds_delta_x); + EXPECT_FALSE(transform_node->moved_by_outer_viewport_bounds_delta_y); + } +} + // When a property tree change occurs that affects layer transform-origin, the // transform can be directly updated without explicitly marking the layer as // damaged. The ensure damage occurs, the transform node should have
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc index 684940f2..9843f8c6 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc
@@ -6,6 +6,7 @@ #include "base/format_macros.h" #include "base/rand_util.h" +#include "base/time/default_tick_clock.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" @@ -15,15 +16,18 @@ LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::ScopedUkmHierarchicalTimer( scoped_refptr<LocalFrameUkmAggregator> aggregator, - size_t metric_index) + size_t metric_index, + const base::TickClock* clock) : aggregator_(aggregator), metric_index_(metric_index), - start_time_(CurrentTimeTicks()) {} + clock_(clock), + start_time_(clock_->NowTicks()) {} LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::ScopedUkmHierarchicalTimer( ScopedUkmHierarchicalTimer&& other) : aggregator_(other.aggregator_), metric_index_(other.metric_index_), + clock_(other.clock_), start_time_(other.start_time_) { other.aggregator_ = nullptr; } @@ -31,7 +35,7 @@ LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer:: ~ScopedUkmHierarchicalTimer() { if (aggregator_ && base::TimeTicks::IsHighResolution()) { - aggregator_->RecordSample(metric_index_, start_time_, CurrentTimeTicks()); + aggregator_->RecordSample(metric_index_, start_time_, clock_->NowTicks()); } } @@ -39,6 +43,7 @@ ukm::UkmRecorder* recorder) : source_id_(source_id), recorder_(recorder), + clock_(base::DefaultTickClock::GetInstance()), event_name_("Blink.UpdateTime") { // Record average and worst case for the primary metric. primary_metric_.reset(); @@ -111,7 +116,7 @@ LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer LocalFrameUkmAggregator::GetScopedTimer(size_t metric_index) { - return ScopedUkmHierarchicalTimer(this, metric_index); + return ScopedUkmHierarchicalTimer(this, metric_index, clock_); } void LocalFrameUkmAggregator::BeginMainFrame() { @@ -119,6 +124,11 @@ in_main_frame_update_ = true; } +void LocalFrameUkmAggregator::SetTickClockForTesting( + const base::TickClock* clock) { + clock_ = clock; +} + void LocalFrameUkmAggregator::RecordSample(size_t metric_index, TimeTicks start, TimeTicks end) {
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h index 936e589..445dd96 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
@@ -11,6 +11,10 @@ #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/time.h" +namespace base { +class TickClock; +} + namespace ukm { class UkmRecorder; } @@ -194,10 +198,12 @@ friend class LocalFrameUkmAggregator; ScopedUkmHierarchicalTimer(scoped_refptr<LocalFrameUkmAggregator>, - size_t metric_index); + size_t metric_index, + const base::TickClock* clock); scoped_refptr<LocalFrameUkmAggregator> aggregator_; const size_t metric_index_; + const base::TickClock* clock_; const TimeTicks start_time_; DISALLOW_COPY_AND_ASSIGN(ScopedUkmHierarchicalTimer); @@ -226,6 +232,10 @@ bool InMainFrame() { return in_main_frame_update_; } + // The caller is the owner of the |clock|. The |clock| must outlive the + // LocalFrameUkmAggregator. + void SetTickClockForTesting(const base::TickClock* clock); + private: struct AbsoluteMetricRecord { std::unique_ptr<CustomCountHistogram> uma_counter; @@ -261,6 +271,7 @@ // UKM system data const int64_t source_id_; ukm::UkmRecorder* const recorder_; + const base::TickClock* clock_; // Event and metric data const String event_name_;
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc index d5727a4..1693053 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc
@@ -4,9 +4,9 @@ #include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h" +#include "base/test/test_mock_time_task_runner.h" #include "components/ukm/test_ukm_recorder.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" namespace blink { @@ -16,14 +16,14 @@ ~LocalFrameUkmAggregatorTest() override = default; void SetUp() override { - clock_.emplace(); + test_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); aggregator_ = base::MakeRefCounted<LocalFrameUkmAggregator>( ukm::UkmRecorder::GetNewSourceID(), &recorder_); + aggregator_->SetTickClockForTesting(test_task_runner_->GetMockTickClock()); } void TearDown() override { aggregator_.reset(); - clock_.reset(); } LocalFrameUkmAggregator& aggregator() { @@ -35,8 +35,6 @@ void ResetAggregator() { aggregator_.reset(); } - WTF::ScopedMockClock& clock() { return *clock_; } - std::string GetPrimaryMetricName() { return std::string( LocalFrameUkmAggregator::primary_metric_name().Utf8().data()); @@ -58,9 +56,10 @@ aggregator().FramesToNextEventForTest(delta); } - base::TimeTicks Now() { - return base::TimeTicks() + base::TimeDelta::FromSecondsD(clock_->Now()); - } + base::TimeTicks Now() { return test_task_runner_->NowTicks(); } + + protected: + scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; void VerifyEntries(unsigned expected_num_entries, unsigned expected_primary_metric, @@ -93,7 +92,6 @@ } private: - base::Optional<WTF::ScopedMockClock> clock_; scoped_refptr<LocalFrameUkmAggregator> aggregator_; ukm::TestUkmRecorder recorder_; }; @@ -106,7 +104,7 @@ return; // There is no BeginMainFrame, so no metrics get recorded. - clock().Advance(TimeDelta::FromSeconds(10)); + test_task_runner_->FastForwardBy(TimeDelta::FromSeconds(10)); ResetAggregator(); EXPECT_EQ(recorder().sources_count(), 0u); @@ -129,7 +127,8 @@ for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { auto timer = aggregator().GetScopedTimer(i % LocalFrameUkmAggregator::kCount); - clock().Advance(TimeDelta::FromMilliseconds(millisecond_for_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_for_step)); } aggregator().RecordEndOfFrameMetrics(start_time, Now()); @@ -171,9 +170,11 @@ aggregator().BeginMainFrame(); for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { auto timer = aggregator().GetScopedTimer(i); - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); } - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); aggregator().RecordEndOfFrameMetrics(start_time, Now()); // We should have a sample after the very first step, regardless of the @@ -188,9 +189,11 @@ aggregator().BeginMainFrame(); for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { auto timer = aggregator().GetScopedTimer(i); - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); } - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); aggregator().RecordEndOfFrameMetrics(start_time, Now()); VerifyEntries(1u, millisecond_per_frame, millisecond_per_step, @@ -203,9 +206,11 @@ aggregator().BeginMainFrame(); for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { auto timer = aggregator().GetScopedTimer(i); - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); } - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); aggregator().RecordEndOfFrameMetrics(start_time, Now()); VerifyEntries(2u, millisecond_per_frame, millisecond_per_step, @@ -216,9 +221,11 @@ aggregator().BeginMainFrame(); for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { auto timer = aggregator().GetScopedTimer(i); - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); } - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); aggregator().RecordEndOfFrameMetrics(start_time, Now()); // Should be no more samples. @@ -230,9 +237,11 @@ aggregator().BeginMainFrame(); for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { auto timer = aggregator().GetScopedTimer(i); - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); } - clock().Advance(TimeDelta::FromMilliseconds(millisecond_per_step)); + test_task_runner_->FastForwardBy( + TimeDelta::FromMilliseconds(millisecond_per_step)); aggregator().RecordEndOfFrameMetrics(start_time, Now()); // We should have 3 more events, once for the prior interval and 2 for the
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index d16b91a..94060a2fbf 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -346,13 +346,23 @@ GetDocument().DecrementLoadEventDelayCount(); } + bool keep_plugin = context.performing_reattach && !dispose_view_; + // Only try to persist a plugin we actually own. WebPluginContainerImpl* plugin = OwnedPlugin(); - if (plugin && context.performing_reattach && !dispose_view_) { + if (plugin && keep_plugin) { SetPersistedPlugin(ToWebPluginContainerImpl(ReleaseEmbeddedContentView())); } else { + // A persisted plugin isn't processed and hooked up immediately + // (synchronously) when attaching the layout object, so it's possible that + // it's still around. That's fine if we're allowed to keep it. Otherwise, + // get rid of it now. + if (persisted_plugin_ && !keep_plugin) + SetPersistedPlugin(nullptr); + // Clear the plugin; will trigger disposal of it with Oilpan. - SetEmbeddedContentView(nullptr); + if (!persisted_plugin_) + SetEmbeddedContentView(nullptr); } // We should attempt to use the same view afterwards, so that we don't lose
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc index 5b31e5b..651ce56 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h" #include "base/bind.h" +#include "base/test/test_mock_time_task_runner.h" #include "build/build_config.h" #include "third_party/blink/public/platform/web_url_loader_mock_factory.h" #include "third_party/blink/public/web/web_performance.h" @@ -23,7 +24,6 @@ #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" -#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkSurface.h" @@ -38,6 +38,7 @@ ImagePaintTimingDetectorTest() : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()), ScopedFirstContentfulPaintPlusPlusForTest(true), + test_task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>()), base_url_("http://www.test.com/") {} ~ImagePaintTimingDetectorTest() override { @@ -131,8 +132,16 @@ return GetPaintTimingDetector().largest_image_paint_time_; } + static constexpr TimeDelta kQuantumOfTime = + base::TimeDelta::FromMilliseconds(10); + + void SimulatePassOfTime() { + test_task_runner_->FastForwardBy(kQuantumOfTime); + } + void UpdateAllLifecyclePhasesAndInvokeCallbackIfAny() { UpdateAllLifecyclePhasesForTest(); + SimulatePassOfTime(); if (!callback_queue_.empty()) InvokeCallback(); } @@ -140,7 +149,8 @@ void InvokeCallback() { DCHECK_GT(callback_queue_.size(), 0UL); std::move(callback_queue_.front()) - .Run(WebWidgetClient::SwapResult::kDidSwap, CurrentTimeTicks()); + .Run(WebWidgetClient::SwapResult::kDidSwap, + test_task_runner_->NowTicks()); callback_queue_.pop(); } @@ -177,6 +187,8 @@ void SimulateScroll() { GetPaintTimingDetector().NotifyScroll(kUserScroll); } + scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; + private: void FakeNotifySwapTime(WebWidgetClient::ReportTimeCallback callback) { callback_queue_.push(std::move(callback)); @@ -197,6 +209,8 @@ std::string base_url_; }; +constexpr TimeDelta ImagePaintTimingDetectorTest::kQuantumOfTime; + TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_NoImage) { SetBodyInnerHTML(R"HTML( <div></div> @@ -452,7 +466,6 @@ TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_ReattachedNodeUseFirstPaint) { - WTF::ScopedMockClock clock; SetBodyInnerHTML(R"HTML( <div id="parent"> </div> @@ -461,26 +474,32 @@ image->setAttribute("id", "target"); GetDocument().getElementById("parent")->AppendChild(image); SetImageAndPaint("target", 5, 5); - clock.Advance(TimeDelta::FromSecondsD(1)); + test_task_runner_->FastForwardBy(TimeDelta::FromSecondsD(1)); UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); ImageRecord* record; record = FindLargestPaintCandidate(); EXPECT_TRUE(record); - EXPECT_EQ(record->paint_time, base::TimeTicks() + TimeDelta::FromSecondsD(1)); + // UpdateAllLifecyclePhasesAndInvokeCallbackIfAny() moves time forward + // kQuantumOfTime so we should take that into account. + EXPECT_EQ(record->paint_time, + base::TimeTicks() + TimeDelta::FromSecondsD(1) + kQuantumOfTime); GetDocument().getElementById("parent")->RemoveChild(image); - clock.Advance(TimeDelta::FromSecondsD(1)); + test_task_runner_->FastForwardBy(TimeDelta::FromSecondsD(1)); UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); record = FindLargestPaintCandidate(); EXPECT_FALSE(record); GetDocument().getElementById("parent")->AppendChild(image); SetImageAndPaint("target", 5, 5); - clock.Advance(TimeDelta::FromSecondsD(1)); + test_task_runner_->FastForwardBy(TimeDelta::FromSecondsD(1)); UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); record = FindLargestPaintCandidate(); EXPECT_TRUE(record); - EXPECT_EQ(record->paint_time, base::TimeTicks() + TimeDelta::FromSecondsD(1)); + // UpdateAllLifecyclePhasesAndInvokeCallbackIfAny() moves time forward + // kQuantumOfTime so we should take that into account. + EXPECT_EQ(record->paint_time, + base::TimeTicks() + TimeDelta::FromSecondsD(1) + kQuantumOfTime); } // This is to prove that a swap time is assigned only to nodes of the frame who @@ -496,8 +515,10 @@ SetImageAndPaint("larger", 9, 9); UpdateAllLifecyclePhasesForTest(); + SimulatePassOfTime(); SetImageAndPaint("smaller", 5, 5); UpdateAllLifecyclePhasesForTest(); + SimulatePassOfTime(); InvokeCallback(); // record1 is the larger. ImageRecord* record1 = FindLargestPaintCandidate(); @@ -505,6 +526,7 @@ GetDocument().getElementById("parent")->RemoveChild( GetDocument().getElementById("larger")); UpdateAllLifecyclePhasesForTest(); + SimulatePassOfTime(); InvokeCallback(); // record2 is the smaller. ImageRecord* record2 = FindLargestPaintCandidate(); @@ -513,7 +535,7 @@ TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_UpdateResultWhenLargestChanged) { - TimeTicks time1 = CurrentTimeTicks(); + TimeTicks time1 = test_task_runner_->NowTicks(); SetBodyInnerHTML(R"HTML( <div id="parent"> <img id="target1"></img> @@ -522,14 +544,14 @@ )HTML"); SetImageAndPaint("target1", 5, 5); UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); - TimeTicks time2 = CurrentTimeTicks(); + TimeTicks time2 = test_task_runner_->NowTicks(); TimeTicks result1 = LargestPaintStoredResult(); EXPECT_GE(result1, time1); EXPECT_GE(time2, result1); SetImageAndPaint("target2", 10, 10); UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); - TimeTicks time3 = CurrentTimeTicks(); + TimeTicks time3 = test_task_runner_->NowTicks(); TimeTicks result2 = LargestPaintStoredResult(); EXPECT_GE(result2, time2); EXPECT_GE(time3, result2); @@ -545,9 +567,11 @@ )HTML"); SetImageAndPaint("1", 5, 5); UpdateAllLifecyclePhasesForTest(); + SimulatePassOfTime(); SetImageAndPaint("2", 9, 9); UpdateAllLifecyclePhasesForTest(); + SimulatePassOfTime(); // This callback only assigns a time to the 5x5 image. InvokeCallback();
diff --git a/third_party/blink/renderer/core/workers/shared_worker_client.cc b/third_party/blink/renderer/core/workers/shared_worker_client.cc index 984bbf3..75655884 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_client.cc +++ b/third_party/blink/renderer/core/workers/shared_worker_client.cc
@@ -42,8 +42,12 @@ } void SharedWorkerClient::OnScriptLoadFailed() { - worker_->DispatchEvent(*Event::CreateCancelable(event_type_names::kError)); worker_->SetIsBeingConnected(false); + worker_->DispatchEvent(*Event::CreateCancelable(event_type_names::kError)); + // |this| can be destroyed at this point, for example, when a frame hosting + // this shared worker is detached in the error handler, and closes mojo's + // strong bindings bound with |this| in + // SharedWorkerClientHolder::ContextDestroyed(). } void SharedWorkerClient::OnFeatureUsed(mojom::WebFeature feature) {
diff --git a/third_party/blink/renderer/modules/push_messaging/push_message_data_test.cc b/third_party/blink/renderer/modules/push_messaging/push_message_data_test.cc index 0ad947d..c6eaf5e 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_message_data_test.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_message_data_test.cc
@@ -19,7 +19,7 @@ PushMessageData* data = PushMessageData::Create(s); ASSERT_NE(data, nullptr); - EXPECT_STREQ(kPushMessageData, data->text().Utf8().data()); + EXPECT_EQ(kPushMessageData, data->text()); } TEST(PushMessageDataTest, ValidEmptyPayload) {
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc index 6b002ca..7b1653e7 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
@@ -216,13 +216,12 @@ Document& document = GetDocument(); document.SetURL(page_url); // Make sure that firstPartyForCookies() is set to the given value. - EXPECT_STREQ("http://example.com/", - document.SiteForCookies().GetString().Utf8().data()); + EXPECT_EQ("http://example.com/", document.SiteForCookies().GetString()); EXPECT_TRUE(Channel()->Connect(KURL("ws://localhost/"), "x")); EXPECT_EQ(1U, protocols.size()); - EXPECT_STREQ("x", protocols[0].Utf8().data()); + EXPECT_EQ("x", protocols[0]); checkpoint.Call(1); HandleClient()->DidConnect(Handle(), String("a"), String("b"));
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index a5397e5..aa6110b 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -708,6 +708,7 @@ "fonts/shaping/harfbuzz_shaper.h", "fonts/shaping/run_segmenter.cc", "fonts/shaping/run_segmenter.h", + "fonts/shaping/shape_cache.cc", "fonts/shaping/shape_cache.h", "fonts/shaping/shape_result.cc", "fonts/shaping/shape_result.h", @@ -1477,6 +1478,11 @@ "//ui/gfx/geometry", ] + # This is faster on armv7, untested on other CPUs (e.g. mips, power, etc). + # TODO(cavalcantii): add next xxhash. + defines = [ "USE_FUNCTION_CITYHASH" ] + deps += [ "//third_party/smhasher:cityhash" ] + if (is_mac) { sources -= [ "fonts/skia/font_cache_skia.cc",
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_cache.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_cache.cc new file mode 100644 index 0000000..3c486fe --- /dev/null +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_cache.cc
@@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012, 2017 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "third_party/blink/renderer/platform/fonts/shaping/shape_cache.h" +#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h" +#if defined(USE_FUNCTION_CITYHASH) +#include "third_party/smhasher/src/City.h" +#endif + +namespace blink { + +void ShapeCache::SmallStringKey::HashString() { +// TODO(cavalcanti): next add xxhash. +#if defined(USE_FUNCTION_CITYHASH) + hash_ = static_cast<unsigned>( + CityHash64((const char*)characters_, length_ * sizeof(UChar))); +#endif +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h b/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h index 7d5819d..44e55bc 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_cache.h
@@ -27,8 +27,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_CACHE_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_CACHE_H_ -#include "base/containers/span.h" -#include "base/hash/hash.h" #include "base/memory/weak_ptr.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h" #include "third_party/blink/renderer/platform/text/text_run.h" @@ -52,6 +50,8 @@ class SmallStringKey { DISALLOW_NEW(); + void HashString(); + public: static unsigned Capacity() { return kCapacity; } @@ -72,8 +72,7 @@ characters_[i] = characters[i]; } - hash_ = static_cast<unsigned>(base::FastHash( - base::as_bytes(base::make_span(characters_, length_)))); + HashString(); } SmallStringKey(base::span<const UChar> characters, TextDirection direction) @@ -81,8 +80,7 @@ direction_(static_cast<unsigned>(direction)) { DCHECK(characters.size() <= kCapacity); memcpy(characters_, characters.data(), characters.size_bytes()); - hash_ = static_cast<unsigned>(base::FastHash( - base::as_bytes(base::make_span(characters_, length_)))); + HashString(); } const UChar* Characters() const { return characters_; }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index 99dfa46..df9a79f7 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -399,7 +399,7 @@ return false; return node.CcNodeId(g_s_property_tree_sequence_number) == -1 && !node.IsRoot() && node.IsIdentityOr2DTranslation() && - !node.ScrollNode() && + !node.ScrollNode() && !node.IsAffectedByOuterViewportBoundsDelta() && !node.HasDirectCompositingReasonsOtherThan3dTransform() && node.FlattensInheritedTransformSameAsParent() && node.BackfaceVisibilitySameAsParent();
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc index b25a88e..31ffabe 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -422,8 +422,10 @@ transform_node.FlattensInheritedTransform(); compositor_node.sorting_context_id = transform_node.RenderingContextId(); - if (transform_node.IsAffectedByOuterViewportBoundsDelta()) + if (transform_node.IsAffectedByOuterViewportBoundsDelta()) { + compositor_node.moved_by_outer_viewport_bounds_delta_y = true; GetTransformTree().AddNodeAffectedByOuterViewportBoundsDelta(id); + } compositor_node.in_subtree_of_page_scale_layer = transform_node.IsInSubtreeOfPageScale();
diff --git a/third_party/blink/renderer/platform/histogram.h b/third_party/blink/renderer/platform/histogram.h index 0f0a6cc7..76f00cf 100644 --- a/third_party/blink/renderer/platform/histogram.h +++ b/third_party/blink/renderer/platform/histogram.h
@@ -8,6 +8,7 @@ #include <stdint.h> #include "base/metrics/histogram_base.h" #include "base/metrics/histogram_macros.h" +#include "base/time/default_tick_clock.h" #include "base/time/tick_clock.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" @@ -70,37 +71,42 @@ int32_t bucket_count); }; -class PLATFORM_EXPORT ScopedUsHistogramTimer { - USING_FAST_MALLOC(ScopedUsHistogramTimer); +template <typename Derived> +class ScopedUsHistogramTimerBase { + USING_FAST_MALLOC(ScopedUsHistogramTimerBase); public: - explicit ScopedUsHistogramTimer(CustomCountHistogram& counter) - : start_time_(CurrentTimeTicks()), counter_(counter) {} + explicit ScopedUsHistogramTimerBase(CustomCountHistogram& counter) + : ScopedUsHistogramTimerBase(counter, + base::DefaultTickClock::GetInstance()) {} - ~ScopedUsHistogramTimer() { - counter_.CountMicroseconds(CurrentTimeTicks() - start_time_); + ScopedUsHistogramTimerBase(CustomCountHistogram& counter, + const base::TickClock* clock) + : clock_(*clock), start_time_(clock_.NowTicks()), counter_(counter) {} + + ~ScopedUsHistogramTimerBase() { + if (Derived::ShouldRecord()) + counter_.CountMicroseconds(clock_.NowTicks() - start_time_); } private: + const base::TickClock& clock_; TimeTicks start_time_; CustomCountHistogram& counter_; }; -class PLATFORM_EXPORT ScopedHighResUsHistogramTimer { - USING_FAST_MALLOC(ScopedUsHistogramTimer); - +class ScopedUsHistogramTimer + : public ScopedUsHistogramTimerBase<ScopedUsHistogramTimer> { public: - explicit ScopedHighResUsHistogramTimer(CustomCountHistogram& counter) - : start_time_(CurrentTimeTicks()), counter_(counter) {} + using ScopedUsHistogramTimerBase::ScopedUsHistogramTimerBase; + static bool ShouldRecord() { return true; } +}; - ~ScopedHighResUsHistogramTimer() { - if (TimeTicks::IsHighResolution()) - counter_.CountMicroseconds(CurrentTimeTicks() - start_time_); - } - - private: - TimeTicks start_time_; - CustomCountHistogram& counter_; +class ScopedHighResUsHistogramTimer + : public ScopedUsHistogramTimerBase<ScopedHighResUsHistogramTimer> { + public: + using ScopedUsHistogramTimerBase::ScopedUsHistogramTimerBase; + static bool ShouldRecord() { return TimeTicks::IsHighResolution(); } }; #define SCOPED_BLINK_UMA_HISTOGRAM_TIMER_IMPL(name, allow_cross_thread) \
diff --git a/third_party/blink/renderer/platform/histogram_test.cc b/third_party/blink/renderer/platform/histogram_test.cc index 7892e35..1a67831 100644 --- a/third_party/blink/renderer/platform/histogram_test.cc +++ b/third_party/blink/renderer/platform/histogram_test.cc
@@ -5,9 +5,8 @@ #include "third_party/blink/renderer/platform/histogram.h" #include "base/metrics/histogram_samples.h" +#include "base/test/test_mock_time_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" -#include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { @@ -22,25 +21,35 @@ base::HistogramBase* Histogram() { return histogram_; } }; -TEST(ScopedUsHistogramTimerTest, Basic) { +class ScopedUsHistogramTimerTest : public testing::Test { + public: + void SetUp() override { + test_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + } + + protected: + scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; +}; + +TEST_F(ScopedUsHistogramTimerTest, Basic) { TestCustomCountHistogram scoped_us_counter("ScopedUsHistogramTimerTest.Basic", 0, 10000000, 50); { - WTF::ScopedMockClock clock; - ScopedUsHistogramTimer timer(scoped_us_counter); - clock.Advance(TimeDelta::FromMilliseconds(500)); + ScopedUsHistogramTimer timer(scoped_us_counter, + test_task_runner_->GetMockTickClock()); + test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(500)); } // 500ms == 500000us EXPECT_EQ(500000, scoped_us_counter.Histogram()->SnapshotSamples()->sum()); } -TEST(ScopedHighResUsHistogramTimerTest, Basic) { +TEST_F(ScopedUsHistogramTimerTest, BasicHighRes) { TestCustomCountHistogram scoped_us_counter( "ScopedHighResUsHistogramTimerTest.Basic", 0, 10000000, 50); { - WTF::ScopedMockClock clock; - ScopedHighResUsHistogramTimer timer(scoped_us_counter); - clock.Advance(TimeDelta::FromMilliseconds(500)); + ScopedHighResUsHistogramTimer timer(scoped_us_counter, + test_task_runner_->GetMockTickClock()); + test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(500)); } int64_t expected = TimeTicks::IsHighResolution() ? 500000 : 0; EXPECT_EQ(expected, scoped_us_counter.Histogram()->SnapshotSamples()->sum());
diff --git a/third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h b/third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h index 11de276..34bad3f 100644 --- a/third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h +++ b/third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <cstddef> #include <string> #include <utility> @@ -69,7 +70,7 @@ // Assigning nullptr to this class causes it to close the currently bound // message pipe (if any) and returns the pointer to the unbound state. - RevocableInterfacePtr& operator=(decltype(nullptr)) { + RevocableInterfacePtr& operator=(std::nullptr_t) { reset(); return *this; }
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index 16571be9b..a94a1e1 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -198,6 +198,12 @@ # For MessageLoop::TaskObserver. 'base::PendingTask', + # Time + 'base::Clock', + 'base::DefaultClock', + 'base::DefaultTickClock', + 'base::TickClock', + # cc painting types. 'cc::PaintCanvas', 'cc::PaintFlags',
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_github.py b/third_party/blink/tools/blinkpy/w3c/wpt_github.py index 22c50c3f..dd71479f 100644 --- a/third_party/blink/tools/blinkpy/w3c/wpt_github.py +++ b/third_party/blink/tools/blinkpy/w3c/wpt_github.py
@@ -210,10 +210,14 @@ @memoized def all_pull_requests(self): - """Fetches all (open and closed) PRs with the export label. + """Fetches the most recent (open and closed) PRs with the export label. The maximum number of PRs is pr_history_window. Search endpoint is used - instead of listing PRs, because we need to filter by labels. + instead of listing PRs, because we need to filter by labels. Note that + there are already more than MAX_PR_HISTORY_WINDOW export PRs, so we + can't really find *all* of them; we fetch the most recently updated ones + because we only check whether recent commits have been exported. + API doc: https://developer.github.com/v3/search/#search-issues Returns: @@ -222,6 +226,7 @@ path = ( '/search/issues' '?q=repo:{}/{}%20type:pr%20label:{}' + '&sort=updated' '&page=1' '&per_page={}' ).format(
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG index 3ab0caca..e47f84146 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -89,6 +89,7 @@ crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-list-item-002.html [ Pass ] crbug.com/933054 external/wpt/css/css-position/position-absolute-container-dynamic-002.html [ Pass ] crbug.com/952644 external/wpt/css/css-position/position-absolute-crash-chrome-006.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/position-absolute-dynamic-overflow-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-position/position-absolute-in-inline-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-position/position-absolute-in-inline-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-position/static-position/htb-ltr-rtl.tentative.html [ Pass ] @@ -112,6 +113,7 @@ crbug.com/591099 external/wpt/css/css-text/hyphens/hyphens-out-of-flow-002.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/hyphens/hyphens-shaping-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/hyphens/shy-styling-001.html [ Failure ] +crbug.com/591099 external/wpt/css/css-text/line-break/line-break-shaping-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-009.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-011.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-015.html [ Pass ] @@ -275,7 +277,7 @@ crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-margin-box-border-radius-004.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-margin-box-border-radius-008.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-padding-box-border-radius-002.html [ Pass ] -crbug.com/591099 external/wpt/event-timing/programmatic-click-not-observed.html [ Failure ] +crbug.com/591099 external/wpt/event-timing/programmatic-click-not-observed.html [ Failure Pass ] crbug.com/591099 external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ] crbug.com/591099 external/wpt/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-abort/javascript-url-abort-return-value-string.tentative.html [ Pass ] crbug.com/591099 external/wpt/html/user-activation/activation-transfer-without-click.tentative.html [ Pass ] @@ -295,7 +297,7 @@ crbug.com/591099 fast/backgrounds/quirks-mode-line-box-backgrounds.html [ Failure ] crbug.com/591099 fast/block/float/4145535Crash.html [ Pass ] crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ] -crbug.com/591099 fast/canvas/OffscreenCanvas-copyImage.html [ Pass ] +crbug.com/591099 fast/canvas/OffscreenCanvas-copyImage.html [ Failure Pass ] crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Pass ] crbug.com/591099 fast/css-intrinsic-dimensions/height-tables.html [ Failure Pass ] crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Pass ] @@ -307,12 +309,12 @@ crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ] crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-list-translate.html [ Failure ] crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ] -crbug.com/591099 fast/forms/autofocus-in-sandbox-with-allow-scripts.html [ Pass Timeout ] +crbug.com/591099 fast/forms/autofocus-in-sandbox-with-allow-scripts.html [ Timeout ] crbug.com/889721 fast/inline/outline-continuations.html [ Failure ] crbug.com/591099 fast/multicol/border-radius-clipped-layer.html [ Pass ] crbug.com/591099 fast/overflow/overflow-height-float-not-removed-crash3.html [ Failure ] crbug.com/591099 fast/peerconnection/RTCPeerConnection-many.html [ Pass ] -crbug.com/591099 fast/replaced/replaced-breaking.html [ Failure Pass ] +crbug.com/591099 fast/replaced/replaced-breaking.html [ Failure ] crbug.com/899902 fast/text/ellipsis-with-self-painting-layer.html [ Pass ] crbug.com/591099 fast/text/emoji-vertical-origin-visual.html [ Failure ] crbug.com/591099 fast/text/font-format-support-color-cff2-vertical.html [ Failure ] @@ -330,6 +332,7 @@ crbug.com/591099 http/tests/media/video-load-metadata-decode-error.html [ Pass ] crbug.com/591099 http/tests/security/inactive-document-with-empty-security-origin.html [ Pass ] crbug.com/591099 images/feature-policy-oversized-images-resize.html [ Pass ] +crbug.com/591099 media/video-object-fit-change.html [ Failure Pass ] crbug.com/591099 paint/invalidation/flexbox/scrollbars-changed.html [ Failure ] crbug.com/591099 paint/invalidation/media-audio-no-spurious-repaints.html [ Failure ] crbug.com/835484 paint/invalidation/outline/inline-focus.html [ Failure ] @@ -348,7 +351,7 @@ crbug.com/591099 virtual/exotic-color-space/ [ Skip ] crbug.com/591099 virtual/fractional_scrolling_threaded/fast/scrolling/unscrollable-layer-subpixel-size-with-negative-overflow.html [ Failure Pass ] crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Pass ] -crbug.com/591099 virtual/gpu/fast/canvas/OffscreenCanvas-copyImage.html [ Pass ] +crbug.com/591099 virtual/gpu/fast/canvas/OffscreenCanvas-copyImage.html [ Failure Pass ] crbug.com/591099 virtual/gpu/fast/canvas/OffscreenCanvas-filter.html [ Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-blend-image.html [ Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-color-over-pattern.html [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 0878786..fda8200 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5595,3 +5595,4 @@ # Sheriff 2019-05-16 crbug.com/963734 [ Mac ] mojo/bind-intercepted-interface-in-worker.html [ Failure ] crbug.com/963734 [ Mac ] shapedetection/detection-on-worker.html [ Timeout ] +crbug.com/963764 [ Mac ] media/video-aspect-ratio.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-basis-computed.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-basis-computed.html new file mode 100644 index 0000000..79781dd2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-basis-computed.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Flexible Box Layout: getComputedValue().flexBasis</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#propdef-flex-basis"> +<meta name="assert" content="flex-basis computed value is as specified, with length made absolute."> +<meta name="assert" content="flex-basis computed value is non-negative."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +<style> + #target { + font-size: 40px; + } +</style> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("flex-basis", "1px"); +test_computed_value("flex-basis", "calc(10px + 0.5em)", "30px"); +test_computed_value("flex-basis", "calc(10px - 0.5em)", "0px"); +test_computed_value("flex-basis", "400%"); +test_computed_value("flex-basis", "auto"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-direction-computed.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-direction-computed.html new file mode 100644 index 0000000..13b2f7e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-direction-computed.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Flexible Box Layout: getComputedValue().flexDirection</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#propdef-flex-direction"> +<meta name="assert" content="flex-direction computed value is as specified."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("flex-direction", "row"); +test_computed_value("flex-direction", "row-reverse"); +test_computed_value("flex-direction", "column"); +test_computed_value("flex-direction", "column-reverse"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-flow-computed.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-flow-computed.html new file mode 100644 index 0000000..cb4acbba --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-flow-computed.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Animations: getComputedValue().flexFlow</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#propdef-flex-flow"> +<meta name="assert" content="flex-flow computed value is as specified."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("flex-flow", "column wrap-reverse"); +test_computed_value("flex-flow", "row-reverse wrap"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-grow-computed.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-grow-computed.html new file mode 100644 index 0000000..fa67446 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-grow-computed.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Flexible Box Layout: getComputedValue().flexGrow</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#propdef-flex-grow"> +<meta name="assert" content="flex-grow computed value is as specified."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("flex-grow", "1"); +test_computed_value("flex-grow", "2.34e+06"); +test_computed_value("flex-grow", "6.78e+08"); +test_computed_value("flex-grow", "0"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-shrink-computed.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-shrink-computed.html new file mode 100644 index 0000000..299d6228 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-shrink-computed.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Flexible Box Layout: getComputedValue().flexShrink</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#propdef-flex-shrink"> +<meta name="assert" content="flex-shrink computed value is as specified."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("flex-shrink", "1"); +test_computed_value("flex-shrink", "2.34e+06"); +test_computed_value("flex-shrink", "6.78e+08"); +test_computed_value("flex-shrink", "0"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-wrap-computed.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-wrap-computed.html new file mode 100644 index 0000000..46df87f3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-wrap-computed.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Flexible Box Layout: getComputedValue().flexWrap</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#propdef-flex-wrap"> +<meta name="assert" content="flex-wrap computed value is as specified."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("flex-wrap", "nowrap"); +test_computed_value("flex-wrap", "wrap"); +test_computed_value("flex-wrap", "wrap-reverse"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/workers/SharedWorker-detach-frame-in-error-event.html b/third_party/blink/web_tests/external/wpt/workers/SharedWorker-detach-frame-in-error-event.html new file mode 100644 index 0000000..7363265fb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/SharedWorker-detach-frame-in-error-event.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Test frame detach in shared worker's error handler</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<iframe id="frame"></iframe> +</body> +<script> +promise_test(t => { + const frame = document.getElementById('frame'); + + const promise = new Promise(resolve => { + window.detachFrame = () => { + frame.remove(); + resolve(); + }; + }); + + // Start a new worker with an invalid script in the frame, and detach the + // frame in the worker's error handler. This shouldn't crash. + const s = frame.contentWindow.document.createElement('script'); + s.innerHTML = "const worker = new SharedWorker('error');" + + "worker.onerror = () => { window.parent.detachFrame(); };"; + frame.contentWindow.document.body.appendChild(s); + + return promise; +}); +</script>
diff --git a/third_party/blink/web_tests/plugins/remove-reattached-plugin-crash.html b/third_party/blink/web_tests/plugins/remove-reattached-plugin-crash.html new file mode 100644 index 0000000..eea07c4 --- /dev/null +++ b/third_party/blink/web_tests/plugins/remove-reattached-plugin-crash.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<object id="plugin" type="application/x-blink-test-plugin"></object> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script> + test(()=> { + document.body.offsetTop; + plugin.style.display = "block"; + document.body.offsetTop; + plugin.parentNode.removeChild(plugin); + }, "no crash or DCHECK failure"); +</script>
diff --git a/third_party/sqlite/BUILD.gn b/third_party/sqlite/BUILD.gn index 096c158..c18755f 100644 --- a/third_party/sqlite/BUILD.gn +++ b/third_party/sqlite/BUILD.gn
@@ -166,6 +166,13 @@ # Uses isnan() in the C99 standard library. "SQLITE_HAVE_ISNAN", + + # Forces SQLite to only store temporary data in memory. + # + # This is the only supported setting on Android. Using it everywhere removes + # a source of cross-platform variation, and saves us from having to reason + # about SQLite storing data in the operating system's temporary directory. + "SQLITE_TEMP_STORE=3", ] # On OSX, SQLite has extra logic for detecting the use of network @@ -348,7 +355,6 @@ defines += [ "SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576", "SQLITE_DEFAULT_AUTOVACUUM=1", - "SQLITE_TEMP_STORE=3", ] }
diff --git a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml index 09825ed..981e90ae 100644 --- a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml +++ b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
@@ -38,7 +38,7 @@ reset. </description> - <interface name="zcr_remote_shell_v1" version="20"> + <interface name="zcr_remote_shell_v1" version="21"> <description summary="remote_shell"> The global interface that allows clients to turn a wl_surface into a "real window" which is remotely managed but can be stacked, activated @@ -694,6 +694,7 @@ summary="the window bounds is moved due to other WM operations"/> <entry name="resize" value="6" summary="the window bounds is reiszed due to other WM operations"/> + <entry name="move_pip" value="7" summary="the window bounds is resized for PIP"/> </enum> <event name="bounds_changed" since="10">
diff --git a/tools/ipc_fuzzer/fuzzer/BUILD.gn b/tools/ipc_fuzzer/fuzzer/BUILD.gn index cb39a9a3..d00e411 100644 --- a/tools/ipc_fuzzer/fuzzer/BUILD.gn +++ b/tools/ipc_fuzzer/fuzzer/BUILD.gn
@@ -19,7 +19,7 @@ "rand_util.h", ] deps = [ - "//base/util/type-safety", + "//base/util/type_safety", "//tools/ipc_fuzzer/message_lib:ipc_message_lib", ] public_deps = [
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc index 2ccefca2..9fc7ad8 100644 --- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc +++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -15,7 +15,7 @@ #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/unguessable_token.h" -#include "base/util/type-safety/id_type.h" +#include "base/util/type_safety/id_type.h" #include "base/values.h" #include "build/build_config.h" #include "ipc/ipc_message.h"
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 87694869..df25617 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -12389,6 +12389,7 @@ <int value="2" label="Background Fetch"/> <int value="3" label="Background Sync"/> <int value="4" label="Push Messaging"/> + <int value="5" label="Notifications"/> </enum> <enum name="DevToolsPanel">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index d427f8c3..9014e8c 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -10157,6 +10157,9 @@ <histogram base="true" name="Autofill.WalletAddresses2" units="addresses" expires_after="2019-06-01"> + <obsolete> + Deprecated as of 05/2019. + </obsolete> <!-- Name completed by histogram_suffixes name="AutofillWalletCardsDiff" --> <owner>sebsg@chromium.org</owner> @@ -10242,6 +10245,9 @@ <histogram base="true" name="Autofill.WalletCards2" units="credit cards" expires_after="2019-06-01"> + <obsolete> + Deprecated as of 05/2019. + </obsolete> <!-- Name completed by histogram_suffixes name="AutofillWalletCardsDiff" --> <owner>sebsg@chromium.org</owner> @@ -124585,6 +124591,9 @@ </histogram> <histogram name="SubresourceFilter.SafeBrowsing.CheckTime" units="ms"> + <obsolete> + Deprecated in May 2019 in favor of the TotalCheckTime variant. + </obsolete> <owner>csharrison@chromium.org</owner> <summary> The time an individual Safe Browsing URL check took before finishing. Logged @@ -124594,6 +124603,7 @@ <histogram name="SubresourceFilter.SafeBrowsing.TotalCheckTime" units="ms"> <owner>csharrison@chromium.org</owner> + <owner>ericrobinson@chromium.org</owner> <summary> The time an individual Safe Browsing URL check took before finishing, including posting tasks to and from the IO thread. Measured on the UI @@ -127489,6 +127499,9 @@ <histogram name="Sync.Wallet.EntitiesClearedWhenDisabled" units="entities" expires_after="M74"> + <obsolete> + Deprecated as of 05/2019. + </obsolete> <owner>jkrcal@chromium.org</owner> <owner>feuunk@chromium.org</owner> <summary> @@ -138406,6 +138419,15 @@ </summary> </histogram> +<histogram name="WebController.BackForwardListOutOfSync" enum="BooleanHit"> + <owner>gambard@chromium.org</owner> + <summary> + [iOS] Counts the number of time the backForwardList of the WebView gets out + of sync with the URL exposed by the WebView. This should not happen and is + probably an issue in WebKit. This is only recorded when there is an error. + </summary> +</histogram> + <histogram name="WebController.CertVerificationErrorsCacheHit" enum="BooleanCacheHit" expires_after="M77"> <owner>eugenebut@chromium.org</owner>
diff --git a/tools/v8_context_snapshot/BUILD.gn b/tools/v8_context_snapshot/BUILD.gn index 771fc0df..2d7b357 100644 --- a/tools/v8_context_snapshot/BUILD.gn +++ b/tools/v8_context_snapshot/BUILD.gn
@@ -11,7 +11,7 @@ import("//build/config/c++/c++.gni") import("//build/config/compiler/compiler.gni") -import("//v8/snapshot_toolchain.gni") +import("//v8/gni/snapshot_toolchain.gni") if (is_android) { import("//build/config/android/rules.gni")
diff --git a/ui/aura/event_injector.cc b/ui/aura/event_injector.cc index 4fdfc171..6598c5f8 100644 --- a/ui/aura/event_injector.cc +++ b/ui/aura/event_injector.cc
@@ -6,12 +6,6 @@ #include <utility> -#include "base/bind.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" -#include "ui/aura/env.h" -#include "ui/aura/mus/window_tree_client.h" -#include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/events/event.h" @@ -19,89 +13,25 @@ namespace aura { -namespace { +EventInjector::EventInjector() = default; -void RunCallback(base::OnceClosure callback, bool processed) { - if (!callback) - return; - - std::move(callback).Run(); -} - -// Updates the location of |event| to be relative to the display |host| is -// on. It is assumed at the time this is called the location of the event is -// relative to |host|. -void ConvertHostLocationToDisplayLocation(WindowTreeHost* host, - ui::LocatedEvent* event) { - WindowTreeHostMus* host_mus = WindowTreeHostMus::ForWindow(host->window()); - DCHECK(host_mus); - // WindowTreeHostMus's bounds are in screen coordinates, convert to display - // relative. - gfx::PointF location = - gfx::PointF(host_mus->bounds_in_dip().origin() - - host_mus->GetDisplay().bounds().origin().OffsetFromOrigin()); - // And then add the event location. - location += event->root_location_f().OffsetFromOrigin(); - event->set_root_location_f(location); - event->set_location_f(location); -} - -} // namespace - -EventInjector::EventInjector() {} - -EventInjector::~EventInjector() { - // |event_injector_| should not be waiting for responses. Otherwise, the - // pending callback would not happen because the mojo channel is closed. - DCHECK(!has_pending_callback_ || !event_injector_.IsExpectingResponse()); -} +EventInjector::~EventInjector() = default; ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host, - ui::Event* event, - base::OnceClosure callback) { + ui::Event* event) { DCHECK(host); - Env* env = host->window()->env(); - DCHECK(env); DCHECK(event); - if (env->mode() == Env::Mode::LOCAL) { - if (event->IsLocatedEvent()) { - ui::LocatedEvent* located_event = event->AsLocatedEvent(); - // Transforming the coordinate to the root will apply the screen scale - // factor to the event's location and also the screen rotation degree. - located_event->UpdateForRootTransform( - host->GetRootTransform(), - host->GetRootTransformForLocalEventCoordinates()); - } - - ui::EventDispatchDetails details = - host->event_sink()->OnEventFromSource(event); - RunCallback(std::move(callback), /*processed=*/true); - return details; - } - - has_pending_callback_ |= !callback.is_null(); - if (event->IsLocatedEvent()) { - // The window-service expects events coming in to have a location matching - // the root location. - event->AsLocatedEvent()->set_root_location_f( - event->AsLocatedEvent()->location_f()); - - // Convert the location to be display relative. This is *not* needed in the - // classic case as the WindowTreeHost and the display are the same. - ConvertHostLocationToDisplayLocation(host, event->AsLocatedEvent()); + ui::LocatedEvent* located_event = event->AsLocatedEvent(); + // Transforming the coordinate to the root will apply the screen scale + // factor to the event's location and also the screen rotation degree. + located_event->UpdateForRootTransform( + host->GetRootTransform(), + host->GetRootTransformForLocalEventCoordinates()); } - if (!event_injector_) { - env->window_tree_client_->connector()->BindInterface( - ws::mojom::kServiceName, &event_injector_); - } - - event_injector_->InjectEvent( - host->GetDisplayId(), ui::Event::Clone(*event), - base::BindOnce(&RunCallback, std::move(callback))); - return ui::EventDispatchDetails(); + return host->event_sink()->OnEventFromSource(event); } } // namespace aura
diff --git a/ui/aura/event_injector.h b/ui/aura/event_injector.h index 725bfcf..98f2929 100644 --- a/ui/aura/event_injector.h +++ b/ui/aura/event_injector.h
@@ -5,8 +5,7 @@ #ifndef UI_AURA_EVENT_INJECTOR_H_ #define UI_AURA_EVENT_INJECTOR_H_ -#include "base/callback.h" -#include "services/ws/public/mojom/event_injector.mojom.h" +#include "base/macros.h" #include "ui/aura/aura_export.h" namespace ui { @@ -18,28 +17,17 @@ class WindowTreeHost; -// Used to inject events into the system. In LOCAL mode, it directly injects -// events into the WindowTreeHost, but in MUS mode, it injects events into the -// window-service (over the mojom API). +// Used to inject events as if they came from the OS. class AURA_EXPORT EventInjector { public: EventInjector(); ~EventInjector(); - // Inject |event| to |host|. |callback| is optional that gets invoked after - // the event is processed by |host|. In LOCAL mode, |callback| is invoked - // synchronously. In MUS mode, it is invoked after a response is received - // from the window service (via mojo). If |event| is a LocatedEvent, then - // coordinates are relative to host and in DIPs. - ui::EventDispatchDetails Inject( - WindowTreeHost* host, - ui::Event* event, - base::OnceClosure callback = base::OnceClosure()); + // Inject |event| to |host|. If |event| is a LocatedEvent, then coordinates + // are relative to host and in DIPs. + ui::EventDispatchDetails Inject(WindowTreeHost* host, ui::Event* event); private: - ws::mojom::EventInjectorPtr event_injector_; - bool has_pending_callback_ = false; - DISALLOW_COPY_AND_ASSIGN(EventInjector); };
diff --git a/ui/aura/test/ui_controls_factory_ozone.cc b/ui/aura/test/ui_controls_factory_ozone.cc index c729b40a..130aaf07 100644 --- a/ui/aura/test/ui_controls_factory_ozone.cc +++ b/ui/aura/test/ui_controls_factory_ozone.cc
@@ -6,22 +6,15 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" -#include "base/optional.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" -#include "services/ws/public/mojom/event_injector.mojom.h" #include "ui/aura/env.h" -#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/test/aura_test_utils.h" #include "ui/aura/test/env_test_helper.h" -#include "ui/aura/test/mus/window_tree_client_test_api.h" #include "ui/aura/test/ui_controls_factory_aura.h" #include "ui/aura/window_tree_host.h" #include "ui/base/test/ui_controls_aura.h" #include "ui/display/display.h" -#include "ui/display/display_observer.h" #include "ui/display/screen.h" #include "ui/events/event_utils.h" #include "ui/events/test/events_test_utils.h" @@ -31,16 +24,11 @@ namespace test { namespace { -class UIControlsOzone : public ui_controls::UIControlsAura, - display::DisplayObserver { +class UIControlsOzone : public ui_controls::UIControlsAura { public: UIControlsOzone(WindowTreeHost* host) : host_(host) { - MaybeInitializeEventInjector(); - display::Screen::GetScreen()->AddObserver(this); } - ~UIControlsOzone() override { - display::Screen::GetScreen()->RemoveObserver(this); - } + ~UIControlsOzone() override = default; private: // ui_controls::UIControlsAura: @@ -134,9 +122,6 @@ int64_t display_id = display::kInvalidDisplayId; if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; - last_mouse_location_ = host_location; - last_mouse_display_id_ = display_id; - ui::EventType event_type; if (button_down_mask_) @@ -159,17 +144,10 @@ int button_state, base::OnceClosure closure, int accelerator_state) override { - gfx::PointF host_location; + gfx::PointF host_location(host_->window()->env()->last_mouse_location()); int64_t display_id = display::kInvalidDisplayId; - if (last_mouse_location_.has_value()) { - host_location = last_mouse_location_.value(); - display_id = last_mouse_display_id_; - } else { - host_location = - gfx::PointF(host_->window()->env()->last_mouse_location()); - if (!ScreenDIPToHostPixels(&host_location, &display_id)) - return false; - } + if (!ScreenDIPToHostPixels(&host_location, &display_id)) + return false; int changed_button_flag = 0; @@ -253,40 +231,9 @@ } #endif - // display::DisplayObserver: - void OnDisplayRemoved(const display::Display& old_display) override { - if (last_mouse_display_id_ == old_display.id()) { - last_mouse_display_id_ = display::kInvalidDisplayId; - last_mouse_location_.reset(); - } - } - void SendEventToSink(ui::Event* event, int64_t display_id, base::OnceClosure closure) { - if (event_injector_) { - auto event_to_inject = ui::Event::Clone(*event); - - if (event_to_inject->IsLocatedEvent()) { - // EventInjector expects coordinates relative to host and in DIPs. - display::Display display; - CHECK(display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id, - &display)); - - ui::LocatedEvent* located_event = event_to_inject->AsLocatedEvent(); - gfx::PointF location_in_host_dip = gfx::ScalePoint( - located_event->location_f(), 1 / display.device_scale_factor(), - 1 / display.device_scale_factor()); - located_event->set_location_f(location_in_host_dip); - located_event->set_root_location_f(location_in_host_dip); - } - - event_injector_->InjectEvent( - display_id, std::move(event_to_inject), - base::BindOnce(&OnWindowServiceProcessedEvent, std::move(closure))); - return; - } - // Post the task before processing the event. This is necessary in case // processing the event results in a nested message loop. if (closure) { @@ -373,18 +320,6 @@ SendEventToSink(&touch_event, display_id, std::move(closure)); } - // Initializes EventInjector when Mus. Otherwise do nothing. - void MaybeInitializeEventInjector() { - if (host_->window()->env()->mode() != Env::Mode::MUS) - return; - - DCHECK(aura::test::EnvTestHelper().GetWindowTreeClient()); - aura::test::EnvTestHelper() - .GetWindowTreeClient() - ->connector() - ->BindInterface(ws::mojom::kServiceName, &event_injector_); - } - bool ScreenDIPToHostPixels(gfx::PointF* location, int64_t* display_id) { // The location needs to be in display's coordinate. display::Display display = @@ -401,17 +336,6 @@ } WindowTreeHost* host_; - ws::mojom::EventInjectorPtr event_injector_; - - // The mouse location for the last SendMouseEventsNotifyWhenDone call. This is - // used rather than Env::last_mouse_location() as Env::last_mouse_location() - // is updated asynchronously with mus. - base::Optional<gfx::PointF> last_mouse_location_; - - // The display ID where the last SendMouseEventsNotifyWhenDone occurred. This - // is used along with |last_mouse_location_| to send the mouse event to the - // event injector. Not used when Mus is not enabled. - int64_t last_mouse_display_id_ = display::kInvalidDisplayId; // Mask of the mouse buttons currently down. This is static as it needs to // track the state globally for all displays. A UIControlsOzone instance is @@ -430,20 +354,5 @@ return new UIControlsOzone(host); } -void OnWindowServiceProcessedEvent(base::OnceClosure closure, bool result) { - DCHECK(result); - if (closure) { - // There can be several mojo calls are queued in the window tree client, - // which may change the order of the operations unexpectedly. Do not call - // WaitForAllChangesToComplete() here, since some in-flight changes might - // not be resolved by just waiting (like window-dragging will not finish - // until it's cancelled or the mouse or touch is released). - // See also: https://crbug.com/916177 - WindowTreeClientTestApi(EnvTestHelper().GetWindowTreeClient()) - .FlushForTesting(); - std::move(closure).Run(); - } -} - } // namespace test } // namespace aura
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index 9f82bd5..ee6dc4b 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -144,7 +144,6 @@ div[section-start='removable'].tree-item { left: 0; max-width: 100%; - position: absolute; } #directory-tree .tree-row > .button {
diff --git a/ui/file_manager/file_manager/foreground/js/quick_view_controller.js b/ui/file_manager/file_manager/foreground/js/quick_view_controller.js index cebf88d..301a9887 100644 --- a/ui/file_manager/file_manager/foreground/js/quick_view_controller.js +++ b/ui/file_manager/file_manager/foreground/js/quick_view_controller.js
@@ -4,115 +4,418 @@ /** * Controller for QuickView. - * This should be initialized with |init_| method. - * - * @param {!MetadataModel} metadataModel File system metadata. - * @param {!FileSelectionHandler} selectionHandler - * @param {!ListContainer} listContainer - * @param {!cr.ui.MenuButton} selectionMenuButton - * @param {!QuickViewModel} quickViewModel - * @param {!TaskController} taskController - * @param {!cr.ui.ListSelectionModel} fileListSelectionModel - * @param {!QuickViewUma} quickViewUma - * @param {!MetadataBoxController} metadataBoxController - * @param {DialogType} dialogType - * @param {!VolumeManager} volumeManager - * - * @constructor */ -function QuickViewController( - metadataModel, selectionHandler, listContainer, selectionMenuButton, - quickViewModel, taskController, fileListSelectionModel, quickViewUma, - metadataBoxController, dialogType, volumeManager) { +class QuickViewController { /** - * @type {FilesQuickView} - * @private - */ - this.quickView_ = null; - - /** - * @type {!FileSelectionHandler} - * @private - */ - this.selectionHandler_ = selectionHandler; - - /** - * @type {!ListContainer} - * @private - */ - this.listContainer_ = listContainer; - - /** - * @type{!QuickViewModel} - * @private - */ - this.quickViewModel_ = quickViewModel; - - /** - * @type {!QuickViewUma} - * @private - */ - this.quickViewUma_ = quickViewUma; - - /** - * @type {!MetadataModel} - * @private - */ - this.metadataModel_ = metadataModel; - - /** - * @type {!TaskController} - * @private - */ - this.taskController_ = taskController; - - /** - * @type {!cr.ui.ListSelectionModel} - * @private - */ - this.fileListSelectionModel_ = fileListSelectionModel; - - /** - * @type {!MetadataBoxController} - * @private - */ - this.metadataBoxController_ = metadataBoxController; - - /** - * @type {DialogType} - * @private - */ - this.dialogType_ = dialogType; - - /** - * @type {!VolumeManager} - * @private - */ - this.volumeManager_ = volumeManager; - - /** - * Current selection of selectionHandler. + * This should be initialized with |init_| method. * - * @type {!Array<!FileEntry>} + * @param {!MetadataModel} metadataModel File system metadata. + * @param {!FileSelectionHandler} selectionHandler + * @param {!ListContainer} listContainer + * @param {!cr.ui.MenuButton} selectionMenuButton + * @param {!QuickViewModel} quickViewModel + * @param {!TaskController} taskController + * @param {!cr.ui.ListSelectionModel} fileListSelectionModel + * @param {!QuickViewUma} quickViewUma + * @param {!MetadataBoxController} metadataBoxController + * @param {DialogType} dialogType + * @param {!VolumeManager} volumeManager + */ + constructor( + metadataModel, selectionHandler, listContainer, selectionMenuButton, + quickViewModel, taskController, fileListSelectionModel, quickViewUma, + metadataBoxController, dialogType, volumeManager) { + /** @private {?FilesQuickView} */ + this.quickView_ = null; + + /** @private @const {!FileSelectionHandler} */ + this.selectionHandler_ = selectionHandler; + + /** @private @const {!ListContainer} */ + this.listContainer_ = listContainer; + + /** @private @const{!QuickViewModel} */ + this.quickViewModel_ = quickViewModel; + + /** @private @const {!QuickViewUma} */ + this.quickViewUma_ = quickViewUma; + + /** @private @const {!MetadataModel} */ + this.metadataModel_ = metadataModel; + + /** @private @const {!TaskController} */ + this.taskController_ = taskController; + + /** @private @const {!cr.ui.ListSelectionModel} */ + this.fileListSelectionModel_ = fileListSelectionModel; + + /** @private @const {!MetadataBoxController} */ + this.metadataBoxController_ = metadataBoxController; + + /** @private @const {DialogType} */ + this.dialogType_ = dialogType; + + /** @private @const {!VolumeManager} */ + this.volumeManager_ = volumeManager; + + /** + * Current selection of selectionHandler. + * @private {!Array<!FileEntry>} + */ + this.entries_ = []; + + this.selectionHandler_.addEventListener( + FileSelectionHandler.EventType.CHANGE, + this.onFileSelectionChanged_.bind(this)); + this.listContainer_.element.addEventListener( + 'keydown', this.onKeyDownToOpen_.bind(this)); + this.listContainer_.element.addEventListener('command', event => { + if (event.command.id === 'get-info') { + this.display_(QuickViewUma.WayToOpen.CONTEXT_MENU); + } + }); + selectionMenuButton.addEventListener('command', event => { + if (event.command.id === 'get-info') { + this.display_(QuickViewUma.WayToOpen.SELECTION_MENU); + } + }); + } + + /** + * Initialize the controller with quick view which will be lazily loaded. + * @param {!FilesQuickView} quickView * @private */ - this.entries_ = []; + init_(quickView) { + this.quickView_ = quickView; + this.metadataBoxController_.init(quickView); + document.body.addEventListener( + 'keydown', this.onQuickViewKeyDown_.bind(this)); + quickView.addEventListener('close', () => { + this.listContainer_.focus(); + }); + quickView.onOpenInNewButtonTap = this.onOpenInNewButtonTap_.bind(this); - this.selectionHandler_.addEventListener( - FileSelectionHandler.EventType.CHANGE, - this.onFileSelectionChanged_.bind(this)); - this.listContainer_.element.addEventListener( - 'keydown', this.onKeyDownToOpen_.bind(this)); - this.listContainer_.element.addEventListener('command', event => { - if (event.command.id === 'get-info') { - this.display_(QuickViewUma.WayToOpen.CONTEXT_MENU); + const toolTip = this.quickView_.$$('files-tooltip'); + const elems = + this.quickView_.$$('#toolbar').querySelectorAll('[has-tooltip]'); + toolTip.addTargets(elems); + } + + /** + * Create quick view element. + * @return Promise<!FilesQuickView> + * @private + */ + createQuickView_() { + return new Promise((resolve, reject) => { + Polymer.Base.importHref(constants.FILES_QUICK_VIEW_HTML, () => { + const quickView = document.querySelector('#quick-view'); + resolve(quickView); + }, reject); + }); + } + + /** + * Handles open-in-new button tap. + * + * @param {!Event} event A button click event. + * @private + */ + onOpenInNewButtonTap_(event) { + this.taskController_.executeDefaultTask(); + this.quickView_.close(); + } + + /** + * Handles key event on listContainer if it's relevant to quick view. + * + * @param {!Event} event A keyboard event. + * @private + */ + onKeyDownToOpen_(event) { + if (event.key === ' ') { + event.preventDefault(); + if (this.entries_.length != 1) { + return; + } + event.stopImmediatePropagation(); + this.display_(QuickViewUma.WayToOpen.SPACE_KEY); } - }); - selectionMenuButton.addEventListener('command', event => { - if (event.command.id === 'get-info') { - this.display_(QuickViewUma.WayToOpen.SELECTION_MENU); + } + + /** + * Handles key event on quick view. + * + * @param {!Event} event A keyboard event. + * @private + */ + onQuickViewKeyDown_(event) { + if (this.quickView_.isOpened()) { + let index; + switch (event.key) { + case ' ': + case 'Escape': + event.preventDefault(); + // Prevent the open dialog from closing. + event.stopImmediatePropagation(); + this.quickView_.close(); + break; + case 'ArrowRight': + case 'ArrowDown': + index = this.fileListSelectionModel_.selectedIndex + 1; + if (index >= this.fileListSelectionModel_.length) { + index = 0; + } + this.fileListSelectionModel_.selectedIndex = index; + break; + case 'ArrowLeft': + case 'ArrowUp': + index = this.fileListSelectionModel_.selectedIndex - 1; + if (index < 0) { + index = this.fileListSelectionModel_.length - 1; + } + this.fileListSelectionModel_.selectedIndex = index; + break; + } } - }); + } + + /** + * Display quick view. + * + * @param {QuickViewUma.WayToOpen=} opt_wayToOpen in which way opening of + * quick view was triggered. Can be omitted if quick view is already open. + * @private + */ + display_(opt_wayToOpen) { + this.updateQuickView_().then(() => { + if (!this.quickView_.isOpened()) { + this.quickView_.open(); + this.quickViewUma_.onOpened(this.entries_[0], assert(opt_wayToOpen)); + } + }); + } + + /** + * Update quick view on file selection change. + * + * @param {!Event} event an Event whose target is FileSelectionHandler. + * @private + */ + onFileSelectionChanged_(event) { + this.entries_ = event.target.selection.entries; + if (this.quickView_ && this.quickView_.isOpened()) { + assert(this.entries_.length > 0); + const entry = this.entries_[0]; + if (util.isSameEntry(entry, this.quickViewModel_.getSelectedEntry())) { + return; + } + this.quickViewModel_.setSelectedEntry(entry); + this.display_(); + } + } + + /** + * @param {!FileEntry} entry + * @return {!Promise<!Array<!chrome.fileManagerPrivate.FileTask>>} + * @private + */ + getAvailableTasks_(entry) { + return this.taskController_.getFileTasks().then(tasks => { + return tasks.getTaskItems(); + }); + } + + /** + * Update quick view using current entries. + * + * @return {!Promise} Promise fulfilled after quick view is updated. + * @private + */ + updateQuickView_() { + if (!this.quickView_) { + return this.createQuickView_() + .then(this.init_.bind(this)) + .then(this.updateQuickView_.bind(this)) + .catch(console.error); + } + assert(this.entries_.length > 0); + // TODO(oka): Support multi-selection. + this.quickViewModel_.setSelectedEntry(this.entries_[0]); + + const entry = + (/** @type {!FileEntry} */ (this.quickViewModel_.getSelectedEntry())); + assert(entry); + this.quickViewUma_.onEntryChanged(entry); + return Promise + .all([ + this.metadataModel_.get([entry], ['thumbnailUrl', 'mediaMimeType']), + this.getAvailableTasks_(entry) + ]) + .then(values => { + const items = (/**@type{Array<MetadataItem>}*/ (values[0])); + const tasks = + (/**@type{!Array<!chrome.fileManagerPrivate.FileTask>}*/ ( + values[1])); + return this.onMetadataLoaded_(entry, items, tasks); + }) + .catch(console.error); + } + + /** + * Update quick view using file entry and loaded metadata and tasks. + * + * @param {!FileEntry} entry + * @param {Array<MetadataItem>} items + * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks + * @private + */ + onMetadataLoaded_(entry, items, tasks) { + return this.getQuickViewParameters_(entry, items, tasks).then(params => { + this.quickView_.type = params.type || ''; + this.quickView_.subtype = params.subtype || ''; + this.quickView_.filePath = params.filePath || ''; + this.quickView_.hasTask = params.hasTask || false; + this.quickView_.contentUrl = params.contentUrl || ''; + this.quickView_.videoPoster = params.videoPoster || ''; + this.quickView_.audioArtwork = params.audioArtwork || ''; + this.quickView_.autoplay = params.autoplay || false; + this.quickView_.browsable = params.browsable || false; + }); + } + + /** + * @param {!FileEntry} entry + * @param {Array<MetadataItem>} items + * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks + * @return !Promise<!QuickViewParams> + * + * @private + */ + getQuickViewParameters_(entry, items, tasks) { + const item = items[0]; + const typeInfo = FileType.getType(entry, item.mediaMimeType); + const type = typeInfo.type; + + /** @type {!QuickViewParams} */ + const params = { + type: type, + subtype: typeInfo.subtype, + filePath: entry.name, + hasTask: tasks.length > 0, + }; + + const volumeInfo = this.volumeManager_.getVolumeInfo(entry); + const localFile = volumeInfo && + QuickViewController.LOCAL_VOLUME_TYPES_.indexOf( + volumeInfo.volumeType) >= 0; + + if (!localFile) { + // For Drive files, display a thumbnail if there is one. + if (item.thumbnailUrl) { + return this.loadThumbnailFromDrive_(item.thumbnailUrl).then(result => { + if (result.status === 'success') { + if (params.type == 'video') { + params.videoPoster = result.data; + } else if (params.type == 'image') { + params.contentUrl = result.data; + } else { + // TODO(sashab): Rather than re-use 'image', create a new type + // here, e.g. 'thumbnail'. + params.type = 'image'; + params.contentUrl = result.data; + } + } + return params; + }); + } + + // We ask user to open it with external app. + return Promise.resolve(params); + } + + if (type === '.folder') { + return Promise.resolve(params); + } + return new Promise((resolve, reject) => { + entry.file(resolve, reject); + }) + .then(file => { + switch (type) { + case 'image': + if (QuickViewController.UNSUPPORTED_IMAGE_SUBTYPES_.indexOf( + typeInfo.subtype) !== -1) { + params.contentUrl = ''; + } else { + params.contentUrl = URL.createObjectURL(file); + } + return params; + case 'video': + params.contentUrl = URL.createObjectURL(file); + params.autoplay = true; + if (item.thumbnailUrl) { + params.videoPoster = item.thumbnailUrl; + } + return params; + case 'audio': + params.contentUrl = URL.createObjectURL(file); + params.autoplay = true; + return this.metadataModel_.get([entry], ['contentThumbnailUrl']) + .then(items => { + const item = items[0]; + if (item.contentThumbnailUrl) { + params.audioArtwork = item.contentThumbnailUrl; + } + return params; + }); + case 'document': + if (typeInfo.subtype === 'HTML') { + params.contentUrl = URL.createObjectURL(file); + return params; + } else { + break; + } + case 'text': + if (typeInfo.subtype === 'TXT') { + params.contentUrl = URL.createObjectURL(file); + params.browsable = true; + return params; + } else { + break; + } + } + const browsable = tasks.some(task => { + return ['view-in-browser', 'view-pdf'].includes( + task.taskId.split('|')[2]); + }); + params.browsable = browsable; + params.contentUrl = browsable ? URL.createObjectURL(file) : ''; + if (params.subtype == 'PDF') { + params.contentUrl += '#view=FitH'; + } + return params; + }) + .catch(e => { + console.error(e); + return params; + }); + } + + /** + * Loads a thumbnail from Drive. + * + * @param {string} url Thumbnail url + * @return Promise<{{status: string, data:string, width:number, + * height:number}}> + * @private + */ + loadThumbnailFromDrive_(url) { + return new Promise(resolve => { + ImageLoaderClient.getInstance().load( + LoadImageRequest.createForUrl(url), resolve); + }); + } } /** @@ -127,9 +430,7 @@ * with Quick View unless thumbnails are provided (which is the case with * Drive). * - * @type {!Array<!VolumeManagerCommon.VolumeType>} - * @const - * @private + * @private @const {!Array<!VolumeManagerCommon.VolumeType>} */ QuickViewController.LOCAL_VOLUME_TYPES_ = [ VolumeManagerCommon.VolumeType.ARCHIVE, @@ -143,219 +444,13 @@ /** * List of unsupported image subtypes - * @type {!Array<string>} - * @const - * @private + * @private @const {!Array<string>} */ QuickViewController.UNSUPPORTED_IMAGE_SUBTYPES_ = [ 'TIFF', ]; /** - * Initialize the controller with quick view which will be lazily loaded. - * @param {!FilesQuickView} quickView - * @private - */ -QuickViewController.prototype.init_ = function(quickView) { - this.quickView_ = quickView; - this.metadataBoxController_.init(quickView); - document.body.addEventListener( - 'keydown', this.onQuickViewKeyDown_.bind(this)); - quickView.addEventListener('close', () => { - this.listContainer_.focus(); - }); - quickView.onOpenInNewButtonTap = this.onOpenInNewButtonTap_.bind(this); - - const toolTip = this.quickView_.$$('files-tooltip'); - const elems = - this.quickView_.$$('#toolbar').querySelectorAll('[has-tooltip]'); - toolTip.addTargets(elems); -}; - -/** - * Craete quick view element. - * @return Promise<!FilesQuickView> - * @private - */ -QuickViewController.prototype.createQuickView_ = () => { - return new Promise((resolve, reject) => { - Polymer.Base.importHref(constants.FILES_QUICK_VIEW_HTML, () => { - const quickView = document.querySelector('#quick-view'); - resolve(quickView); - }, reject); - }); -}; - -/** - * Handles open-in-new button tap. - * - * @param {!Event} event A button click event. - * @private - */ -QuickViewController.prototype.onOpenInNewButtonTap_ = function(event) { - this.taskController_.executeDefaultTask(); - this.quickView_.close(); -}; - -/** - * Handles key event on listContainer if it's relevant to quick view. - * - * @param {!Event} event A keyboard event. - * @private - */ -QuickViewController.prototype.onKeyDownToOpen_ = function(event) { - if (event.key === ' ') { - event.preventDefault(); - if (this.entries_.length != 1) { - return; - } - event.stopImmediatePropagation(); - this.display_(QuickViewUma.WayToOpen.SPACE_KEY); - } -}; - -/** - * Handles key event on quick view. - * - * @param {!Event} event A keyboard event. - * @private - */ -QuickViewController.prototype.onQuickViewKeyDown_ = function(event) { - if (this.quickView_.isOpened()) { - let index; - switch (event.key) { - case ' ': - case 'Escape': - event.preventDefault(); - // Prevent the open dialog from closing. - event.stopImmediatePropagation(); - this.quickView_.close(); - break; - case 'ArrowRight': - case 'ArrowDown': - index = this.fileListSelectionModel_.selectedIndex + 1; - if (index >= this.fileListSelectionModel_.length) { - index = 0; - } - this.fileListSelectionModel_.selectedIndex = index; - break; - case 'ArrowLeft': - case 'ArrowUp': - index = this.fileListSelectionModel_.selectedIndex - 1; - if (index < 0) { - index = this.fileListSelectionModel_.length - 1; - } - this.fileListSelectionModel_.selectedIndex = index; - break; - } - } -}; - -/** - * Display quick view. - * - * @param {QuickViewUma.WayToOpen=} opt_wayToOpen in which way opening of - * quick view was triggered. Can be omitted if quick view is already open. - * @private - */ -QuickViewController.prototype.display_ = function(opt_wayToOpen) { - this.updateQuickView_().then(() => { - if (!this.quickView_.isOpened()) { - this.quickView_.open(); - this.quickViewUma_.onOpened(this.entries_[0], assert(opt_wayToOpen)); - } - }); -}; - -/** - * Update quick view on file selection change. - * - * @param {!Event} event an Event whose target is FileSelectionHandler. - * @private - */ -QuickViewController.prototype.onFileSelectionChanged_ = function(event) { - this.entries_ = event.target.selection.entries; - if (this.quickView_ && this.quickView_.isOpened()) { - assert(this.entries_.length > 0); - const entry = this.entries_[0]; - if (util.isSameEntry(entry, this.quickViewModel_.getSelectedEntry())) { - return; - } - this.quickViewModel_.setSelectedEntry(entry); - this.display_(); - } -}; - -/** - * @param {!FileEntry} entry - * @return {!Promise<!Array<!chrome.fileManagerPrivate.FileTask>>} - * @private - */ -QuickViewController.prototype.getAvailableTasks_ = function(entry) { - return this.taskController_.getFileTasks().then(tasks => { - return tasks.getTaskItems(); - }); -}; - -/** - * Update quick view using current entries. - * - * @return {!Promise} Promise fulfilled after quick view is updated. - * @private - */ -QuickViewController.prototype.updateQuickView_ = function() { - if (!this.quickView_) { - return this.createQuickView_() - .then(this.init_.bind(this)) - .then(this.updateQuickView_.bind(this)) - .catch(console.error); - } - assert(this.entries_.length > 0); - // TODO(oka): Support multi-selection. - this.quickViewModel_.setSelectedEntry(this.entries_[0]); - - const entry = - (/** @type {!FileEntry} */ (this.quickViewModel_.getSelectedEntry())); - assert(entry); - this.quickViewUma_.onEntryChanged(entry); - return Promise - .all([ - this.metadataModel_.get([entry], ['thumbnailUrl', 'mediaMimeType']), - this.getAvailableTasks_(entry) - ]) - .then(values => { - const items = (/**@type{Array<MetadataItem>}*/ (values[0])); - const tasks = (/**@type{!Array<!chrome.fileManagerPrivate.FileTask>}*/ ( - values[1])); - return this.onMetadataLoaded_(entry, items, tasks); - }) - .catch(console.error); -}; - -/** - * Update quick view using file entry and loaded metadata and tasks. - * - * @param {!FileEntry} entry - * @param {Array<MetadataItem>} items - * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks - * @private - */ -QuickViewController.prototype.onMetadataLoaded_ = function( - entry, items, tasks) { - return this.getQuickViewParameters_(entry, items, tasks).then(params => { - this.quickView_.type = params.type || ''; - this.quickView_.subtype = params.subtype || ''; - this.quickView_.filePath = params.filePath || ''; - this.quickView_.hasTask = params.hasTask || false; - this.quickView_.contentUrl = params.contentUrl || ''; - this.quickView_.videoPoster = params.videoPoster || ''; - this.quickView_.audioArtwork = params.audioArtwork || ''; - this.quickView_.autoplay = params.autoplay || false; - this.quickView_.browsable = params.browsable || false; - }); -}; - -/** * @typedef {{ * type: string, * subtype: string, @@ -368,135 +463,3 @@ * }} */ let QuickViewParams; - -/** - * @param {!FileEntry} entry - * @param {Array<MetadataItem>} items - * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks - * @return !Promise<!QuickViewParams> - * - * @private - */ -QuickViewController.prototype.getQuickViewParameters_ = function( - entry, items, tasks) { - const item = items[0]; - const typeInfo = FileType.getType(entry, item.mediaMimeType); - const type = typeInfo.type; - - /** @type {!QuickViewParams} */ - const params = { - type: type, - subtype: typeInfo.subtype, - filePath: entry.name, - hasTask: tasks.length > 0, - }; - - const volumeInfo = this.volumeManager_.getVolumeInfo(entry); - const localFile = volumeInfo && - QuickViewController.LOCAL_VOLUME_TYPES_.indexOf(volumeInfo.volumeType) >= - 0; - - if (!localFile) { - // For Drive files, display a thumbnail if there is one. - if (item.thumbnailUrl) { - return this.loadThumbnailFromDrive_(item.thumbnailUrl).then(result => { - if (result.status === 'success') { - if (params.type == 'video') { - params.videoPoster = result.data; - } else if (params.type == 'image') { - params.contentUrl = result.data; - } else { - // TODO(sashab): Rather than re-use 'image', create a new type - // here, e.g. 'thumbnail'. - params.type = 'image'; - params.contentUrl = result.data; - } - } - return params; - }); - } - - // We ask user to open it with external app. - return Promise.resolve(params); - } - - if (type === '.folder') { - return Promise.resolve(params); - } - return new Promise((resolve, reject) => { - entry.file(resolve, reject); - }) - .then(file => { - switch (type) { - case 'image': - if (QuickViewController.UNSUPPORTED_IMAGE_SUBTYPES_.indexOf( - typeInfo.subtype) !== -1) { - params.contentUrl = ''; - } else { - params.contentUrl = URL.createObjectURL(file); - } - return params; - case 'video': - params.contentUrl = URL.createObjectURL(file); - params.autoplay = true; - if (item.thumbnailUrl) { - params.videoPoster = item.thumbnailUrl; - } - return params; - case 'audio': - params.contentUrl = URL.createObjectURL(file); - params.autoplay = true; - return this.metadataModel_.get([entry], ['contentThumbnailUrl']) - .then(items => { - const item = items[0]; - if (item.contentThumbnailUrl) { - params.audioArtwork = item.contentThumbnailUrl; - } - return params; - }); - case 'document': - if (typeInfo.subtype === 'HTML') { - params.contentUrl = URL.createObjectURL(file); - return params; - } else { - break; - } - case 'text': - if (typeInfo.subtype === 'TXT') { - params.contentUrl = URL.createObjectURL(file); - params.browsable = true; - return params; - } else { - break; - } - } - const browsable = tasks.some(task => { - return ['view-in-browser', 'view-pdf'].includes( - task.taskId.split('|')[2]); - }); - params.browsable = browsable; - params.contentUrl = browsable ? URL.createObjectURL(file) : ''; - if (params.subtype == 'PDF') { - params.contentUrl += '#view=FitH'; - } - return params; - }) - .catch(e => { - console.error(e); - return params; - }); -}; - -/** - * Loads a thumbnail from Drive. - * - * @param {string} url Thumbnail url - * @return Promise<{{status: string, data:string, width:number, height:number}}> - * @private - */ -QuickViewController.prototype.loadThumbnailFromDrive_ = url => { - return new Promise(resolve => { - ImageLoaderClient.getInstance().load( - LoadImageRequest.createForUrl(url), resolve); - }); -};
diff --git a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js index 3e8049f..1c230ba5 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js +++ b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js
@@ -4,289 +4,303 @@ /** * Item element of the progress center. - * @param {Document} document Document which the new item belongs to. - * @constructor - * @extends {HTMLDivElement} + * @extends HTMLDivElement */ -function ProgressCenterItemElement(document) { - const label = document.createElement('label'); - label.className = 'label'; +class ProgressCenterItemElement { + /** + * @param {Document} document Document which the new item belongs to. + */ + constructor(document) { + /** @private {?ProgressItemState} */ + this.state_ = null; - const progressBarIndicator = document.createElement('div'); - progressBarIndicator.className = 'progress-track'; + /** @private {?function()} */ + this.cancelTransition_ = null; - const progressBar = document.createElement('div'); - progressBar.className = 'progress-bar'; - progressBar.appendChild(progressBarIndicator); + /** @private {?Element} */ + this.track_ = null; - const progressFrame = document.createElement('div'); - progressFrame.className = 'progress-frame'; - progressFrame.appendChild(label); - progressFrame.appendChild(progressBar); + const label = document.createElement('label'); + label.className = 'label'; - const cancelButton = document.createElement('button'); - cancelButton.className = 'cancel'; - cancelButton.setAttribute('tabindex', '-1'); + const progressBarIndicator = document.createElement('div'); + progressBarIndicator.className = 'progress-track'; - // Dismiss button is shown for error item. - const dismissButton = document.createElement('button'); - dismissButton.classList.add('dismiss'); - dismissButton.setAttribute('tabindex', '-1'); + const progressBar = document.createElement('div'); + progressBar.className = 'progress-bar'; + progressBar.appendChild(progressBarIndicator); - const buttonFrame = document.createElement('div'); - buttonFrame.className = 'button-frame'; - buttonFrame.appendChild(cancelButton); - buttonFrame.appendChild(dismissButton); + const progressFrame = document.createElement('div'); + progressFrame.className = 'progress-frame'; + progressFrame.appendChild(label); + progressFrame.appendChild(progressBar); - const itemElement = document.createElement('li'); - itemElement.appendChild(progressFrame); - itemElement.appendChild(buttonFrame); + const cancelButton = document.createElement('button'); + cancelButton.className = 'cancel'; + cancelButton.setAttribute('tabindex', '-1'); - return ProgressCenterItemElement.decorate(itemElement); + // Dismiss button is shown for error item. + const dismissButton = document.createElement('button'); + dismissButton.classList.add('dismiss'); + dismissButton.setAttribute('tabindex', '-1'); + + const buttonFrame = document.createElement('div'); + buttonFrame.className = 'button-frame'; + buttonFrame.appendChild(cancelButton); + buttonFrame.appendChild(dismissButton); + + const itemElement = document.createElement('li'); + itemElement.appendChild(progressFrame); + itemElement.appendChild(buttonFrame); + + return ProgressCenterItemElement.decorate(itemElement); + } + + /** + * Ensures the animation triggers. + * + * @param {function(?)} callback Function to set the transition end + * properties. + * @return {function()} Function to cancel the request. + * @private + */ + static safelySetAnimation_(callback) { + let requestId = window.requestAnimationFrame(() => { + // The transition start properties currently set are rendered at this + // frame. And the transition end properties set by the callback is + // rendered at the next frame. + requestId = window.requestAnimationFrame(callback); + }); + return () => { + window.cancelAnimationFrame(requestId); + }; + } + + /** + * Decorates the given element as a progress item. + * @param {!Element} element Item to be decorated. + * @return {!ProgressCenterItemElement} Decorated item. + */ + static decorate(element) { + element.__proto__ = ProgressCenterItemElement.prototype; + element = /** @type {!ProgressCenterItemElement} */ (element); + element.state_ = ProgressItemState.PROGRESSING; + element.track_ = element.querySelector('.progress-track'); + element.track_.addEventListener( + 'transitionend', element.onTransitionEnd_.bind(element)); + element.cancelTransition_ = null; + return element; + } + + get quiet() { + return this.classList.contains('quiet'); + } + + /** + * Updates the element view according to the item. + * @param {ProgressCenterItem} item Item to be referred for the update. + * @param {boolean} animated Whether the progress width is applied as animated + * or not. + */ + update(item, animated) { + // Set element attributes. + this.state_ = item.state; + this.setAttribute('data-progress-id', item.id); + this.classList.toggle('error', item.state === ProgressItemState.ERROR); + this.classList.toggle('cancelable', item.cancelable); + this.classList.toggle('single', item.single); + this.classList.toggle('quiet', item.quiet); + + // Set label. + if (this.state_ === ProgressItemState.PROGRESSING || + this.state_ === ProgressItemState.ERROR) { + this.querySelector('label').textContent = item.message; + } else if (this.state_ === ProgressItemState.CANCELED) { + this.querySelector('label').textContent = ''; + } + + // Cancel the previous property set. + if (this.cancelTransition_) { + this.cancelTransition_(); + this.cancelTransition_ = null; + } + + // Set track width. + const setWidth = ((nextWidthFrame) => { + const currentWidthRate = + parseInt(this.track_.style.width, 10); + // Prevent assigning the same width to avoid stopping the + // animation. animated == false may be intended to cancel + // the animation, so in that case, the assignment should + // be done. + if (currentWidthRate === nextWidthFrame && animated) { + return; + } + this.track_.hidden = false; + this.track_.style.width = nextWidthFrame + '%'; + this.track_.classList.toggle('animated', animated); + }).bind(null, item.progressRateInPercent); + + if (animated) { + this.cancelTransition_ = + ProgressCenterItemElement.safelySetAnimation_(setWidth); + } else { + // For animated === false, we should call setWidth immediately to cancel + // the animation, otherwise the animation may complete before canceling + // it. + setWidth(); + } + } + + /** + * Resets the item. + */ + reset() { + this.track_.hidden = true; + this.track_.width = ''; + this.state_ = ProgressItemState.PROGRESSING; + } + + /** + * Handles transition end events. + * @param {Event} event Transition end event. + * @private + */ + onTransitionEnd_(event) { + if (event.propertyName !== 'width') { + return; + } + this.track_.classList.remove('animated'); + this.dispatchEvent(new Event( + ProgressCenterItemElement.PROGRESS_ANIMATION_END_EVENT, + {bubbles: true})); + } } -/** - * Ensures the animation triggers. - * - * @param {function(?)} callback Function to set the transition end properties. - * @return {function()} Function to cancel the request. - * @private - */ -ProgressCenterItemElement.safelySetAnimation_ = callback => { - let requestId = window.requestAnimationFrame(() => { - // The transition start properties currently set are rendered at this frame. - // And the transition end properties set by the callback is rendered at the - // next frame. - requestId = window.requestAnimationFrame(callback); - }); - return () => { - window.cancelAnimationFrame(requestId); - }; -}; +ProgressCenterItemElement.prototype.__proto__ = HTMLDivElement.prototype; /** * Event triggered when the item should be dismissed. - * @type {string} - * @const + * @const {string} */ ProgressCenterItemElement.PROGRESS_ANIMATION_END_EVENT = 'progressAnimationEnd'; /** - * Decorates the given element as a progress item. - * @param {Element} element Item to be decorated. - * @return {ProgressCenterItemElement} Decorated item. - */ -ProgressCenterItemElement.decorate = element => { - element.__proto__ = ProgressCenterItemElement.prototype; - element = /** @type {ProgressCenterItemElement} */ (element); - element.state_ = ProgressItemState.PROGRESSING; - element.track_ = element.querySelector('.progress-track'); - element.track_.addEventListener( - 'transitionend', element.onTransitionEnd_.bind(element)); - element.cancelTransition_ = null; - return element; -}; - -ProgressCenterItemElement.prototype = { - __proto__: HTMLDivElement.prototype, - get quiet() { - return this.classList.contains('quiet'); - } -}; - -/** - * Updates the element view according to the item. - * @param {ProgressCenterItem} item Item to be referred for the update. - * @param {boolean} animated Whether the progress width is applied as animated - * or not. - */ -ProgressCenterItemElement.prototype.update = function(item, animated) { - // Set element attributes. - this.state_ = item.state; - this.setAttribute('data-progress-id', item.id); - this.classList.toggle('error', item.state === ProgressItemState.ERROR); - this.classList.toggle('cancelable', item.cancelable); - this.classList.toggle('single', item.single); - this.classList.toggle('quiet', item.quiet); - - // Set label. - if (this.state_ === ProgressItemState.PROGRESSING || - this.state_ === ProgressItemState.ERROR) { - this.querySelector('label').textContent = item.message; - } else if (this.state_ === ProgressItemState.CANCELED) { - this.querySelector('label').textContent = ''; - } - - // Cancel the previous property set. - if (this.cancelTransition_) { - this.cancelTransition_(); - this.cancelTransition_ = null; - } - - // Set track width. - const setWidth = ((nextWidthFrame) => { - const currentWidthRate = - parseInt(this.track_.style.width, 10); - // Prevent assigning the same width to avoid stopping the - // animation. animated == false may be intended to cancel - // the animation, so in that case, the assignment should be - // done. - if (currentWidthRate === nextWidthFrame && animated) { - return; - } - this.track_.hidden = false; - this.track_.style.width = nextWidthFrame + '%'; - this.track_.classList.toggle('animated', animated); - }).bind(null, item.progressRateInPercent); - - if (animated) { - this.cancelTransition_ = - ProgressCenterItemElement.safelySetAnimation_(setWidth); - } else { - // For animated === false, we should call setWidth immediately to cancel the - // animation, otherwise the animation may complete before canceling it. - setWidth(); - } -}; - -/** - * Resets the item. - */ -ProgressCenterItemElement.prototype.reset = function() { - this.track_.hidden = true; - this.track_.width = ''; - this.state_ = ProgressItemState.PROGRESSING; -}; - -/** - * Handles transition end events. - * @param {Event} event Transition end event. - * @private - */ -ProgressCenterItemElement.prototype.onTransitionEnd_ = function(event) { - if (event.propertyName !== 'width') { - return; - } - this.track_.classList.remove('animated'); - this.dispatchEvent(new Event( - ProgressCenterItemElement.PROGRESS_ANIMATION_END_EVENT, {bubbles: true})); -}; - -/** * Progress center panel. * - * @param {!Element} element DOM Element of the process center panel. - * @constructor - * @struct */ -function ProgressCenterPanel(element) { +class ProgressCenterPanel { /** - * Root element of the progress center. - * @type {!Element} + * @param {!Element} element DOM Element of the process center panel. + */ + constructor(element) { + /** + * Root element of the progress center. + * @type {!Element} + * @private + */ + this.element_ = element; + + /** + * Open view containing multiple progress items. + * @type {!HTMLDivElement} + * @private + */ + this.openView_ = assertInstanceof( + queryRequiredElement('#progress-center-open-view', this.element_), + HTMLDivElement); + + /** + * Close view that is a summarized progress item. + * @type {ProgressCenterItemElement} + * @private + */ + this.closeView_ = ProgressCenterItemElement.decorate( + assert(this.element_.querySelector('#progress-center-close-view'))); + + /** + * Toggle animation rule of the progress center. + * @type {CSSKeyframesRule} + * @private + */ + this.toggleAnimation_ = + ProgressCenterPanel.getToggleAnimation_(element.ownerDocument); + + /** + * Item group for normal priority items. + * @type {ProgressCenterItemGroup} + * @private + */ + this.normalItemGroup_ = new ProgressCenterItemGroup('normal', false); + + /** + * Item group for low priority items. + * @type {ProgressCenterItemGroup} + * @private + */ + this.quietItemGroup_ = new ProgressCenterItemGroup('quiet', true); + + /** + * Queries to obtains items for each group. + * @type {Object<string>} + * @private + */ + this.itemQuery_ = + Object.preventExtensions({normal: 'li:not(.quiet)', quiet: 'li.quiet'}); + + /** + * Timeout IDs of the inactive state of each group. + * @type {Object<?number>} + * @private + */ + this.timeoutId_ = Object.preventExtensions({normal: null, quiet: null}); + + /** + * Callback to be called with the ID of the progress item when the cancel + * button is clicked. + * @type {?function(string)} + */ + this.cancelCallback = null; + + /** + * Callback to be called with the ID of the error item when user pressed + * dismiss button of it. + * @type {?function(string)} + */ + this.dismissErrorItemCallback = null; + + // Register event handlers. + element.addEventListener('click', this.onClick_.bind(this)); + element.addEventListener( + 'animationend', this.onToggleAnimationEnd_.bind(this)); + element.addEventListener( + ProgressCenterItemElement.PROGRESS_ANIMATION_END_EVENT, + this.onItemAnimationEnd_.bind(this)); + } + + /** + * Obtains the toggle animation keyframes rule from the document. + * @param {Document} document Document containing the rule. + * @return {CSSKeyframesRule} Animation rule. * @private */ - this.element_ = element; - - /** - * Open view containing multiple progress items. - * @type {!HTMLDivElement} - * @private - */ - this.openView_ = assertInstanceof( - queryRequiredElement('#progress-center-open-view', this.element_), - HTMLDivElement); - - /** - * Close view that is a summarized progress item. - * @type {ProgressCenterItemElement} - * @private - */ - this.closeView_ = ProgressCenterItemElement.decorate( - this.element_.querySelector('#progress-center-close-view')); - - /** - * Toggle animation rule of the progress center. - * @type {CSSKeyframesRule} - * @private - */ - this.toggleAnimation_ = - ProgressCenterPanel.getToggleAnimation_(element.ownerDocument); - - /** - * Item group for normal priority items. - * @type {ProgressCenterItemGroup} - * @private - */ - this.normalItemGroup_ = new ProgressCenterItemGroup('normal', false); - - /** - * Item group for low priority items. - * @type {ProgressCenterItemGroup} - * @private - */ - this.quietItemGroup_ = new ProgressCenterItemGroup('quiet', true); - - /** - * Queries to obtains items for each group. - * @type {Object<string>} - * @private - */ - this.itemQuery_ = - Object.preventExtensions({normal: 'li:not(.quiet)', quiet: 'li.quiet'}); - - /** - * Timeout IDs of the inactive state of each group. - * @type {Object<?number>} - * @private - */ - this.timeoutId_ = Object.preventExtensions({normal: null, quiet: null}); - - /** - * Callback to be called with the ID of the progress item when the cancel - * button is clicked. - * @type {?function(string)} - */ - this.cancelCallback = null; - - /** - * Callback to be called with the ID of the error item when user pressed - * dismiss button of it. - * @type {?function(string)} - */ - this.dismissErrorItemCallback = null; - - // Register event handlers. - element.addEventListener('click', this.onClick_.bind(this)); - element.addEventListener( - 'animationend', this.onToggleAnimationEnd_.bind(this)); - element.addEventListener( - ProgressCenterItemElement.PROGRESS_ANIMATION_END_EVENT, - this.onItemAnimationEnd_.bind(this)); -} - -/** - * Obtains the toggle animation keyframes rule from the document. - * @param {Document} document Document containing the rule. - * @return {CSSKeyframesRule} Animation rule. - * @private - */ -ProgressCenterPanel.getToggleAnimation_ = document => { - for (let i = 0; i < document.styleSheets.length; i++) { - const styleSheet = document.styleSheets[i]; - for (let j = 0; j < styleSheet.cssRules.length; j++) { - // HACK: closure does not define experimental CSSRules. - const keyFramesRule = CSSRule.KEYFRAMES_RULE || 7; - const rule = styleSheet.cssRules[j]; - if (rule.type === keyFramesRule && - rule.name === 'progress-center-toggle') { - return rule; + static getToggleAnimation_(document) { + for (let i = 0; i < document.styleSheets.length; i++) { + const styleSheet = document.styleSheets[i]; + for (let j = 0; j < styleSheet.cssRules.length; j++) { + // HACK: closure does not define experimental CSSRules. + const keyFramesRule = CSSRule.KEYFRAMES_RULE || 7; + const rule = styleSheet.cssRules[j]; + if (rule.type === keyFramesRule && + rule.name === 'progress-center-toggle') { + return rule; + } } } - } - throw new Error('The progress-center-toggle rules is not found.'); -}; -ProgressCenterPanel.prototype = /** @struct */ { + throw new Error('The progress-center-toggle rules is not found.'); + } + /** * Root element of the progress center. * @type {HTMLElement} @@ -294,207 +308,208 @@ get element() { return this.element_; } -}; -/** - * Updates an item to the progress center panel. - * @param {!ProgressCenterItem} item Item including new contents. - */ -ProgressCenterPanel.prototype.updateItem = function(item) { - const targetGroup = this.getGroupForItem_(item); + /** + * Updates an item to the progress center panel. + * @param {!ProgressCenterItem} item Item including new contents. + */ + updateItem(item) { + const targetGroup = this.getGroupForItem_(item); - // Update the item. - targetGroup.update(item); + // Update the item. + targetGroup.update(item); - // Update an open view item. - const newItem = targetGroup.getItem(item.id); - let itemElement = this.getItemElement_(item.id); - if (newItem) { - if (!itemElement) { - itemElement = new ProgressCenterItemElement(this.element_.ownerDocument); - // Find quiet node and insert the item before the quiet node. - this.openView_.insertBefore( - itemElement, this.openView_.querySelector('.quiet')); - } - itemElement.update(newItem, targetGroup.isAnimated(item.id)); - } else { - if (itemElement) { - itemElement.parentNode.removeChild(itemElement); - } - } - - // Update the close view. - this.updateCloseView_(); -}; - -/** - * Handles the item animation end. - * @param {Event} event Item animation end event. - * @private - */ -ProgressCenterPanel.prototype.onItemAnimationEnd_ = function(event) { - const targetGroup = event.target.classList.contains('quiet') ? - this.quietItemGroup_ : - this.normalItemGroup_; - if (event.target === this.closeView_) { - targetGroup.completeSummarizedItemAnimation(); - } else { - const itemId = event.target.getAttribute('data-progress-id'); - targetGroup.completeItemAnimation(itemId); - const newItem = targetGroup.getItem(itemId); - const itemElement = this.getItemElement_(itemId); - if (!newItem && itemElement) { - itemElement.parentNode.removeChild(itemElement); - } - } - this.updateCloseView_(); -}; - -/** - * Requests all item groups to dismiss an error item. - * @param {string} id Item id. - */ -ProgressCenterPanel.prototype.dismissErrorItem = function(id) { - this.normalItemGroup_.dismissErrorItem(id); - this.quietItemGroup_.dismissErrorItem(id); - - const element = this.getItemElement_(id); - if (element) { - this.openView_.removeChild(element); - } - this.updateCloseView_(); -}; - -/** - * Updates the close view. - * @private - */ -ProgressCenterPanel.prototype.updateCloseView_ = function() { - // Try to use the normal summarized item. - const normalSummarizedItem = - this.normalItemGroup_.getSummarizedItem(this.quietItemGroup_.numErrors); - if (normalSummarizedItem) { - // If the quiet animation is overridden by normal summarized item, discard - // the quiet animation. - if (this.quietItemGroup_.isSummarizedAnimated()) { - this.quietItemGroup_.completeSummarizedItemAnimation(); + // Update an open view item. + const newItem = targetGroup.getItem(item.id); + let itemElement = this.getItemElement_(item.id); + if (newItem) { + if (!itemElement) { + itemElement = + new ProgressCenterItemElement(this.element_.ownerDocument); + // Find quiet node and insert the item before the quiet node. + this.openView_.insertBefore( + itemElement, this.openView_.querySelector('.quiet')); + } + itemElement.update(newItem, targetGroup.isAnimated(item.id)); + } else { + if (itemElement) { + itemElement.parentNode.removeChild(itemElement); + } } - // Update the view state. - this.closeView_.update( - normalSummarizedItem, this.normalItemGroup_.isSummarizedAnimated()); - this.element_.hidden = false; - return; + // Update the close view. + this.updateCloseView_(); } - // Try to use the quiet summarized item. - const quietSummarizedItem = - this.quietItemGroup_.getSummarizedItem(this.normalItemGroup_.numErrors); - if (quietSummarizedItem) { - this.closeView_.update( - quietSummarizedItem, this.quietItemGroup_.isSummarizedAnimated()); - this.element_.hidden = false; - return; + /** + * Handles the item animation end. + * @param {Event} event Item animation end event. + * @private + */ + onItemAnimationEnd_(event) { + const targetGroup = event.target.classList.contains('quiet') ? + this.quietItemGroup_ : + this.normalItemGroup_; + if (event.target === this.closeView_) { + targetGroup.completeSummarizedItemAnimation(); + } else { + const itemId = event.target.getAttribute('data-progress-id'); + targetGroup.completeItemAnimation(itemId); + const newItem = targetGroup.getItem(itemId); + const itemElement = this.getItemElement_(itemId); + if (!newItem && itemElement) { + itemElement.parentNode.removeChild(itemElement); + } + } + this.updateCloseView_(); } - // Try to use the error summarized item. - const errorSummarizedItem = ProgressCenterItemGroup.getSummarizedErrorItem( - this.normalItemGroup_, this.quietItemGroup_); - if (errorSummarizedItem) { - this.closeView_.update(errorSummarizedItem, false); - this.element_.hidden = false; - return; + /** + * Requests all item groups to dismiss an error item. + * @param {string} id Item id. + */ + dismissErrorItem(id) { + this.normalItemGroup_.dismissErrorItem(id); + this.quietItemGroup_.dismissErrorItem(id); + + const element = this.getItemElement_(id); + if (element) { + this.openView_.removeChild(element); + } + this.updateCloseView_(); } - // Hide the progress center because there is no items to show. - this.closeView_.reset(); - this.element_.hidden = true; - this.element_.classList.remove('opened'); -}; + /** + * Updates the close view. + * @private + */ + updateCloseView_() { + // Try to use the normal summarized item. + const normalSummarizedItem = + this.normalItemGroup_.getSummarizedItem(this.quietItemGroup_.numErrors); + if (normalSummarizedItem) { + // If the quiet animation is overridden by normal summarized item, discard + // the quiet animation. + if (this.quietItemGroup_.isSummarizedAnimated()) { + this.quietItemGroup_.completeSummarizedItemAnimation(); + } -/** - * Gets an item element having the specified ID. - * @param {string} id progress item ID. - * @return {ProgressCenterItemElement} Item element having the ID. - * @private - */ -ProgressCenterPanel.prototype.getItemElement_ = function(id) { - const query = 'li[data-progress-id="' + id + '"]'; - return /** @type {ProgressCenterItemElement} */ ( - this.openView_.querySelector(query)); -}; - -/** - * Obtains the group for the item. - * @param {ProgressCenterItem} item Progress item. - * @return {ProgressCenterItemGroup} Item group that should contain the item. - * @private - */ -ProgressCenterPanel.prototype.getGroupForItem_ = function(item) { - return item.quiet ? this.quietItemGroup_ : this.normalItemGroup_; -}; - -/** - * Handles the animation end event of the progress center. - * @param {Event} event Animation end event. - * @private - */ -ProgressCenterPanel.prototype.onToggleAnimationEnd_ = function(event) { - // Transition end of the root element's height. - if (event.target === this.element_ && - event.animationName === 'progress-center-toggle') { - this.element_.classList.remove('animated'); - return; - } -}; - -/** - * Handles the click event. - * @param {Event} event Click event. - * @private - */ -ProgressCenterPanel.prototype.onClick_ = function(event) { - // Toggle button. - if (event.target.classList.contains('open') || - event.target.classList.contains('close')) { - // If the progress center has already animated, just return. - if (this.element_.classList.contains('animated')) { + // Update the view state. + this.closeView_.update( + normalSummarizedItem, this.normalItemGroup_.isSummarizedAnimated()); + this.element_.hidden = false; return; } - // Obtains current and target height. - let currentHeight; - let targetHeight; - if (this.element_.classList.contains('opened')) { - currentHeight = this.openView_.getBoundingClientRect().height; - targetHeight = this.closeView_.getBoundingClientRect().height; - } else { - currentHeight = this.closeView_.getBoundingClientRect().height; - targetHeight = this.openView_.getBoundingClientRect().height; + // Try to use the quiet summarized item. + const quietSummarizedItem = + this.quietItemGroup_.getSummarizedItem(this.normalItemGroup_.numErrors); + if (quietSummarizedItem) { + this.closeView_.update( + quietSummarizedItem, this.quietItemGroup_.isSummarizedAnimated()); + this.element_.hidden = false; + return; } - // Set styles for animation. - this.toggleAnimation_.cssRules[0].style.height = currentHeight + 'px'; - this.toggleAnimation_.cssRules[1].style.height = targetHeight + 'px'; - this.element_.classList.add('animated'); - this.element_.classList.toggle('opened'); - return; + // Try to use the error summarized item. + const errorSummarizedItem = ProgressCenterItemGroup.getSummarizedErrorItem( + this.normalItemGroup_, this.quietItemGroup_); + if (errorSummarizedItem) { + this.closeView_.update(errorSummarizedItem, false); + this.element_.hidden = false; + return; + } + + // Hide the progress center because there is no items to show. + this.closeView_.reset(); + this.element_.hidden = true; + this.element_.classList.remove('opened'); } - if (event.target.classList.contains('dismiss')) { - // To dismiss the error item in all windows, we send this to progress center - // in background page. - const itemElement = event.target.parentNode.parentNode; - const id = itemElement.getAttribute('data-progress-id'); - this.dismissErrorItemCallback(id); + /** + * Gets an item element having the specified ID. + * @param {string} id progress item ID. + * @return {ProgressCenterItemElement} Item element having the ID. + * @private + */ + getItemElement_(id) { + const query = 'li[data-progress-id="' + id + '"]'; + return /** @type {ProgressCenterItemElement} */ ( + this.openView_.querySelector(query)); } - // Cancel button. - if (event.target.classList.contains('cancel')) { - const itemElement = event.target.parentNode.parentNode; - if (this.cancelCallback) { + /** + * Obtains the group for the item. + * @param {ProgressCenterItem} item Progress item. + * @return {ProgressCenterItemGroup} Item group that should contain the item. + * @private + */ + getGroupForItem_(item) { + return item.quiet ? this.quietItemGroup_ : this.normalItemGroup_; + } + + /** + * Handles the animation end event of the progress center. + * @param {Event} event Animation end event. + * @private + */ + onToggleAnimationEnd_(event) { + // Transition end of the root element's height. + if (event.target === this.element_ && + event.animationName === 'progress-center-toggle') { + this.element_.classList.remove('animated'); + return; + } + } + + /** + * Handles the click event. + * @param {Event} event Click event. + * @private + */ + onClick_(event) { + // Toggle button. + if (event.target.classList.contains('open') || + event.target.classList.contains('close')) { + // If the progress center has already animated, just return. + if (this.element_.classList.contains('animated')) { + return; + } + + // Obtains current and target height. + let currentHeight; + let targetHeight; + if (this.element_.classList.contains('opened')) { + currentHeight = this.openView_.getBoundingClientRect().height; + targetHeight = this.closeView_.getBoundingClientRect().height; + } else { + currentHeight = this.closeView_.getBoundingClientRect().height; + targetHeight = this.openView_.getBoundingClientRect().height; + } + + // Set styles for animation. + this.toggleAnimation_.cssRules[0].style.height = currentHeight + 'px'; + this.toggleAnimation_.cssRules[1].style.height = targetHeight + 'px'; + this.element_.classList.add('animated'); + this.element_.classList.toggle('opened'); + return; + } + + if (event.target.classList.contains('dismiss')) { + // To dismiss the error item in all windows, we send this to progress + // center in background page. + const itemElement = event.target.parentNode.parentNode; const id = itemElement.getAttribute('data-progress-id'); - this.cancelCallback(id); + this.dismissErrorItemCallback(id); + } + + // Cancel button. + if (event.target.classList.contains('cancel')) { + const itemElement = event.target.parentNode.parentNode; + if (this.cancelCallback) { + const id = itemElement.getAttribute('data-progress-id'); + this.cancelCallback(id); + } } } -}; +}
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager.cc index 91d1d0e1..3818efd 100644 --- a/ui/ozone/platform/wayland/host/wayland_buffer_manager.cc +++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager.cc
@@ -80,7 +80,7 @@ return false; } - // Once the BufferRelease is called. The buffer will be released. + // Once the BufferRelease is called, the buffer will be released. DCHECK(buffer->released); buffer->released = false; @@ -100,7 +100,7 @@ // before, and Wayland won't release the front buffer until next buffer is // attached. Thus, notify about successful submission immediately. if (!prev_submitted_buffer_) - OnRelease(); + CompleteSubmission(); return true; } @@ -130,7 +130,7 @@ // comes for that buffer. Thus, if there is a submitted buffer, notify // the client about successful swap. if (buffer && !buffer->released && submitted_buffer_) - OnRelease(); + CompleteSubmission(); if (prev_submitted_buffer_ == buffer) prev_submitted_buffer_ = nullptr; @@ -276,23 +276,55 @@ self->OnFrameCallback(callback); } - // wl_buffer_listener - static void BufferRelease(void* data, struct wl_buffer* wl_buffer) { - Surface* self = static_cast<Surface*>(data); - DCHECK(self); + void OnRelease(struct wl_buffer* wl_buffer) { + DCHECK(wl_buffer); - DCHECK(self->prev_submitted_buffer_->wl_buffer.get() == wl_buffer); - self->prev_submitted_buffer_->released = true; + WaylandBuffer* buffer = nullptr; + // The Wayland compositor may release the buffer immediately after it has + // been submitted. Thus, check that wl_buffer belongs to either the + // submitted buffer or the previously submitted buffer. + if (submitted_buffer_ && submitted_buffer_->wl_buffer.get() == wl_buffer) { + buffer = submitted_buffer_; + DCHECK(buffer->wl_buffer.get() == wl_buffer); + } else { + buffer = prev_submitted_buffer_; + DCHECK(buffer && buffer->wl_buffer.get() == wl_buffer); + } + + DCHECK(!buffer->released); + buffer->released = true; + + // It may happen that the client has attached only one buffer and then + // destroyed the window. That means that we manually called OnRelease on + // that very first buffer attach as long as the surface has not had any + // buffers attached before. However, the |submitted_buffer_| can be null in + // the OnRelease and hit the DCHECK when the client does not continue + // attaching new buffers (only one has been attached) and destroyes the + // surface. In this case, the Wayland compositor releases the buffer and the + // DCHECK is hit, because we have already run the OnRelease call manually. + // Please note that the |prev_submitted_buffer_| is the buffer we have + // released manually, and when the Wayland compositor sends OnRelease, the + // validation of the wl_buffers succeeds because of that previous manual + // OnRelease call. + if (!submitted_buffer_) + return; // Although, the Wayland compositor has just released the previously // attached buffer, which became a back buffer, we have to notify the client // that next buffer has been attach and become the front one. Thus, mark the // back buffer as released to ensure the DCHECK is not hit, and notify about // successful submission of the front buffer. - self->OnRelease(); + CompleteSubmission(); } - void OnRelease() { + // wl_buffer_listener + static void BufferRelease(void* data, struct wl_buffer* wl_buffer) { + Surface* self = static_cast<Surface*>(data); + DCHECK(self); + self->OnRelease(wl_buffer); + } + + void CompleteSubmission() { DCHECK(submitted_buffer_); auto id = submitted_buffer_->buffer_id; prev_submitted_buffer_ = submitted_buffer_;
diff --git a/ui/views/test/widget_test_aura.cc b/ui/views/test/widget_test_aura.cc index ea2ad38..970fe6a 100644 --- a/ui/views/test/widget_test_aura.cc +++ b/ui/views/test/widget_test_aura.cc
@@ -6,7 +6,6 @@ #include "build/build_config.h" #include "ui/aura/client/focus_client.h" -#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/test/aura_test_helper.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h"
diff --git a/ui/views/touchui/touch_selection_controller_impl.cc b/ui/views/touchui/touch_selection_controller_impl.cc index f3ef0038..43d84d10 100644 --- a/ui/views/touchui/touch_selection_controller_impl.cc +++ b/ui/views/touchui/touch_selection_controller_impl.cc
@@ -11,7 +11,6 @@ #include "base/time/time.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/env.h" -#include "ui/aura/mus/window_port_mus.h" #include "ui/aura/window.h" #include "ui/aura/window_targeter.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/ui/views_content_client/views_content_client_main_parts_chromeos.cc b/ui/views_content_client/views_content_client_main_parts_chromeos.cc index df9492a..876c1ad 100644 --- a/ui/views_content_client/views_content_client_main_parts_chromeos.cc +++ b/ui/views_content_client/views_content_client_main_parts_chromeos.cc
@@ -4,7 +4,6 @@ #include "base/macros.h" #include "content/public/browser/context_factory.h" -#include "content/public/common/service_manager_connection.h" #include "content/shell/browser/shell_browser_context.h" #include "ui/aura/test/test_screen.h" #include "ui/aura/window.h" @@ -50,10 +49,7 @@ test_screen_.reset(aura::TestScreen::Create(host_size)); display::Screen::SetScreenInstance(test_screen_.get()); // Set up basic pieces of views::corewm. - wm_test_helper_ = std::make_unique<wm::WMTestHelper>( - host_size, - content::ServiceManagerConnection::GetForProcess()->GetConnector(), - content::GetContextFactory()); + wm_test_helper_ = std::make_unique<wm::WMTestHelper>(host_size); // Ensure the X window gets mapped. wm_test_helper_->host()->Show();
diff --git a/ui/wm/core/ime_util_chromeos.cc b/ui/wm/core/ime_util_chromeos.cc index 3df58d11..03e98076 100644 --- a/ui/wm/core/ime_util_chromeos.cc +++ b/ui/wm/core/ime_util_chromeos.cc
@@ -5,7 +5,6 @@ #include "ui/wm/core/ime_util_chromeos.h" #include "ui/aura/client/aura_constants.h" -#include "ui/aura/mus/window_mus.h" #include "ui/base/ui_base_switches.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -80,16 +79,6 @@ void EnsureWindowNotInRect(aura::Window* window, const gfx::Rect& rect_in_screen) { - // If |window| is embedded, the move should happen at the embedding side. - if (auto* window_mus = aura::WindowMus::Get(window->GetRootWindow())) { - if (window_mus->window_mus_type() == aura::WindowMusType::EMBED) { - window->GetRootWindow()->SetProperty( - aura::client::kEmbeddedWindowEnsureNotInRect, - new gfx::Rect(rect_in_screen)); - return; - } - } - gfx::Rect original_window_bounds = window->GetBoundsInScreen(); if (window->GetProperty(wm::kVirtualKeyboardRestoreBoundsKey)) { original_window_bounds =
diff --git a/ui/wm/core/ime_util_chromeos_unittest.cc b/ui/wm/core/ime_util_chromeos_unittest.cc index 7fa6fde..5a5c7f9 100644 --- a/ui/wm/core/ime_util_chromeos_unittest.cc +++ b/ui/wm/core/ime_util_chromeos_unittest.cc
@@ -7,10 +7,7 @@ #include "base/command_line.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/client/aura_constants.h" -#include "ui/aura/mus/embed_root.h" -#include "ui/aura/mus/embed_root_delegate.h" #include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/mus/window_tree_client_test_api.h" #include "ui/aura/test/test_screen.h" #include "ui/aura/test/test_windows.h" #include "ui/base/ui_base_switches.h" @@ -171,57 +168,4 @@ EXPECT_EQ(original_bounds, top_level->bounds()); } -class TestEmbedRootDelegate : public aura::EmbedRootDelegate { - public: - TestEmbedRootDelegate() = default; - ~TestEmbedRootDelegate() override = default; - - // EmbedRootDelegate: - void OnEmbedTokenAvailable(const base::UnguessableToken& token) override {} - void OnEmbed(aura::Window* window) override {} - void OnUnembed() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(TestEmbedRootDelegate); -}; - -class ImeUtilChromeosEmbeddedTest : public ImeUtilChromeosTest { - public: - ImeUtilChromeosEmbeddedTest() = default; - ~ImeUtilChromeosEmbeddedTest() override = default; - - // ImeUtilChromeosTest: - void SetUp() override { - EnableMusWithTestWindowTree(); - ImeUtilChromeosTest::SetUp(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(ImeUtilChromeosEmbeddedTest); -}; - -// Tests that EnsureWindowNotInRect on an embedded window sets the -// kEmbeddedWindowEnsureNotInRect property on the embedded root window and -// RestoreWindowBoundsOnClientFocusLost resets the property. -TEST_F(ImeUtilChromeosEmbeddedTest, EnsureWindowNotInRect) { - // Simulates embedding and create an embedded root. - TestEmbedRootDelegate embed_root_delegate; - std::unique_ptr<aura::EmbedRoot> embed_root = - window_tree_client_impl()->CreateEmbedRoot(&embed_root_delegate); - aura::WindowTreeClientTestApi(window_tree_client_impl()) - .CallOnEmbedFromToken(embed_root.get()); - ASSERT_TRUE(embed_root->window()); - - // EnsureWindowNotInRect on embedded window sets the property. - gfx::Rect occluded_rect(50, 50, 200, 200); - EnsureWindowNotInRect(embed_root->window(), occluded_rect); - EXPECT_EQ(occluded_rect, *embed_root->window()->GetProperty( - aura::client::kEmbeddedWindowEnsureNotInRect)); - - // RestoreWindowBoundsOnClientFocusLost clears the property. - RestoreWindowBoundsOnClientFocusLost(embed_root->window()); - EXPECT_EQ(nullptr, embed_root->window()->GetProperty( - aura::client::kEmbeddedWindowEnsureNotInRect)); -} - } // namespace wm
diff --git a/ui/wm/test/wm_test_helper.cc b/ui/wm/test/wm_test_helper.cc index b62bdb6..003170b6 100644 --- a/ui/wm/test/wm_test_helper.cc +++ b/ui/wm/test/wm_test_helper.cc
@@ -4,27 +4,13 @@ #include "ui/wm/test/wm_test_helper.h" -#include <map> #include <memory> #include <utility> -#include <vector> -#include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/cpp/input_devices/input_device_client.h" -#include "services/ws/public/cpp/property_type_converters.h" -#include "services/ws/public/mojom/constants.mojom.h" -#include "services/ws/public/mojom/window_manager.mojom.h" #include "ui/aura/client/default_capture_client.h" -#include "ui/aura/env.h" -#include "ui/aura/mus/property_converter.h" -#include "ui/aura/mus/window_tree_client.h" -#include "ui/aura/mus/window_tree_host_mus.h" -#include "ui/aura/mus/window_tree_host_mus_init_params.h" -#include "ui/aura/test/mus/window_tree_client_test_api.h" #include "ui/aura/test/test_focus_client.h" #include "ui/aura/test/test_screen.h" #include "ui/aura/window.h" -#include "ui/base/ui_base_features.h" #include "ui/platform_window/platform_window_init_properties.h" #include "ui/wm/core/compound_event_filter.h" #include "ui/wm/core/default_activation_client.h" @@ -32,15 +18,17 @@ namespace wm { -WMTestHelper::WMTestHelper(const gfx::Size& default_window_size, - service_manager::Connector* connector, - ui::ContextFactory* context_factory) { - if (context_factory) - aura::Env::GetInstance()->set_context_factory(context_factory); - if (aura::Env::GetInstance()->mode() == aura::Env::Mode::LOCAL) - InitLocalHost(default_window_size); - else - InitMusHost(connector, default_window_size); +WMTestHelper::WMTestHelper(const gfx::Size& default_window_size) { + wm_state_ = std::make_unique<WMState>(); + + // Install a screen, like TestWindowService's AuraTestHelper for InitMusHost. + test_screen_ = base::WrapUnique(aura::TestScreen::Create(gfx::Size())); + display::Screen::SetScreenInstance(test_screen_.get()); + + host_ = aura::WindowTreeHost::Create( + ui::PlatformWindowInitProperties{gfx::Rect(default_window_size)}); + host_->InitHost(); + aura::client::SetWindowParentingClient(host_->window(), this); focus_client_.reset(new aura::test::TestFocusClient); @@ -56,13 +44,6 @@ } WMTestHelper::~WMTestHelper() { - if (test_ws_) { - // Wait for test_ws to shutdown so that its AuraTestHelper is destroyed - // and there is no lingering WindowTreeHost. - base::RunLoop run_loop; - test_ws_->Shutdown(run_loop.QuitClosure()); - run_loop.Run(); - } host_->window()->RemovePreTargetHandler(root_window_event_filter_.get()); if (display::Screen::GetScreen() == test_screen_.get()) @@ -74,85 +55,4 @@ return host_->window(); } -void WMTestHelper::InitLocalHost(const gfx::Size& default_window_size) { - wm_state_ = std::make_unique<WMState>(); - - // Install a screen, like TestWindowService's AuraTestHelper for InitMusHost. - test_screen_ = base::WrapUnique(aura::TestScreen::Create(gfx::Size())); - display::Screen::SetScreenInstance(test_screen_.get()); - - host_ = aura::WindowTreeHost::Create( - ui::PlatformWindowInitProperties{gfx::Rect(default_window_size)}); - host_->InitHost(); -} - -void WMTestHelper::InitMusHost(service_manager::Connector* connector, - const gfx::Size& default_window_size) { - DCHECK(!aura::Env::GetInstance()->HasWindowTreeClient()); - - const bool running_in_ws_process = features::IsSingleProcessMash(); - - if (!running_in_ws_process) { - wm_state_ = std::make_unique<WMState>(); - - input_device_client_ = std::make_unique<ws::InputDeviceClient>(); - ws::mojom::InputDeviceServerPtr input_device_server; - connector->BindInterface(ws::mojom::kServiceName, &input_device_server); - input_device_client_->Connect(std::move(input_device_server)); - } - - property_converter_ = std::make_unique<aura::PropertyConverter>(); - - const bool create_discardable_memory = false; - window_tree_client_ = aura::WindowTreeClient::CreateForWindowTreeFactory( - connector, this, create_discardable_memory); - aura::Env::GetInstance()->SetWindowTreeClient(window_tree_client_.get()); - if (running_in_ws_process) { - // Spin message loop to wait for displays when WindowService runs in the - // same process to avoid deadlock. - display_wait_loop_ = std::make_unique<base::RunLoop>( - base::RunLoop::Type::kNestableTasksAllowed); - display_wait_loop_->Run(); - display_wait_loop_.reset(); - - // Bind to test_ws so that it could be shutdown at the right time. - connector->BindInterface(test_ws::mojom::kServiceName, &test_ws_); - } else { - window_tree_client_->WaitForDisplays(); - } - - std::map<std::string, std::vector<uint8_t>> properties; - properties[ws::mojom::WindowManager::kBounds_InitProperty] = - mojo::ConvertTo<std::vector<uint8_t>>(gfx::Rect(default_window_size)); - - auto host_mus = std::make_unique<aura::WindowTreeHostMus>( - aura::CreateInitParamsForTopLevel(window_tree_client_.get(), properties)); - host_mus->InitHost(); - - host_ = std::move(host_mus); -} - -void WMTestHelper::OnEmbed( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {} - -void WMTestHelper::OnUnembed(aura::Window* root) {} - -void WMTestHelper::OnEmbedRootDestroyed( - aura::WindowTreeHostMus* window_tree_host) {} - -void WMTestHelper::OnLostConnection(aura::WindowTreeClient* client) {} - -aura::PropertyConverter* WMTestHelper::GetPropertyConverter() { - return property_converter_.get(); -} - -void WMTestHelper::OnDisplaysChanged( - std::vector<ws::mojom::WsDisplayPtr> ws_displays, - int64_t primary_display_id, - int64_t internal_display_id, - int64_t display_id_for_new_windows) { - if (display_wait_loop_) - display_wait_loop_->Quit(); -} - } // namespace wm
diff --git a/ui/wm/test/wm_test_helper.h b/ui/wm/test/wm_test_helper.h index 3ce5ac0..71f642bf 100644 --- a/ui/wm/test/wm_test_helper.h +++ b/ui/wm/test/wm_test_helper.h
@@ -10,16 +10,12 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/run_loop.h" -#include "services/ws/test_ws/test_ws.mojom.h" #include "ui/aura/client/window_parenting_client.h" -#include "ui/aura/mus/window_tree_client_delegate.h" #include "ui/aura/window_tree_host.h" namespace aura { -class PropertyConverter; class TestScreen; class Window; -class WindowTreeClient; class WindowTreeHost; namespace client { class DefaultCaptureClient; @@ -32,18 +28,6 @@ class Size; } -namespace service_manager { -class Connector; -} - -namespace ui { -class ContextFactory; -} - -namespace ws { -class InputDeviceClient; -} // namespace ws - namespace wm { class CompoundEventFilter; @@ -52,12 +36,9 @@ // Creates a minimal environment for running the shell. We can't pull in all of // ash here, but we can create and attach several of the same things we'd find // in ash. -class WMTestHelper : public aura::client::WindowParentingClient, - public aura::WindowTreeClientDelegate { +class WMTestHelper : public aura::client::WindowParentingClient { public: - WMTestHelper(const gfx::Size& default_window_size, - service_manager::Connector* coonnector, - ui::ContextFactory* context_factory); + explicit WMTestHelper(const gfx::Size& default_window_size); ~WMTestHelper() override; aura::WindowTreeHost* host() { return host_.get(); } @@ -67,40 +48,13 @@ const gfx::Rect& bounds) override; private: - // Used when aura is running in Mode::LOCAL. - void InitLocalHost(const gfx::Size& default_window_size); - - // Used when aura is running in Mode::MUS. - void InitMusHost(service_manager::Connector* connector, - const gfx::Size& default_window_size); - - // aura::WindowTreeClientDelegate: - void OnEmbed( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) override; - void OnUnembed(aura::Window* root) override; - void OnEmbedRootDestroyed(aura::WindowTreeHostMus* window_tree_host) override; - void OnLostConnection(aura::WindowTreeClient* client) override; - aura::PropertyConverter* GetPropertyConverter() override; - void OnDisplaysChanged(std::vector<ws::mojom::WsDisplayPtr> ws_displays, - int64_t primary_display_id, - int64_t internal_display_id, - int64_t display_id_for_new_windows) override; - std::unique_ptr<WMState> wm_state_; std::unique_ptr<aura::TestScreen> test_screen_; - std::unique_ptr<ws::InputDeviceClient> input_device_client_; - std::unique_ptr<aura::PropertyConverter> property_converter_; - std::unique_ptr<aura::WindowTreeClient> window_tree_client_; std::unique_ptr<aura::WindowTreeHost> host_; std::unique_ptr<wm::CompoundEventFilter> root_window_event_filter_; std::unique_ptr<aura::client::DefaultCaptureClient> capture_client_; std::unique_ptr<aura::client::FocusClient> focus_client_; - // Loop to wait for |host_| gets embedded under mus. - std::unique_ptr<base::RunLoop> display_wait_loop_; - - test_ws::mojom::TestWsPtr test_ws_; - DISALLOW_COPY_AND_ASSIGN(WMTestHelper); };