diff --git a/DEPS b/DEPS index c8aac75..1697d07 100644 --- a/DEPS +++ b/DEPS
@@ -144,11 +144,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': '5207f35f33b1ccc173cff02bd0a38223554ba6f2', + 'skia_revision': '84bcd0c3ae08f2add3a3999cff784fe907b03c45', # 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': '12c0646785a3207f5cdd747038a9cf9910e2bab5', + 'v8_revision': '109b30b38f8365b80ff4b7c563d19264789d6865', # 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. @@ -156,7 +156,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'cd369bb8a2518eaca7fbdb0936095d3b5d44b4ee', + 'angle_revision': 'dd3de6f095c1a0e8b7c4fff579541287ab2f4fe6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -207,7 +207,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': '249e608964291a3db12869d6158b6df5679c7a22', + 'catapult_revision': '282f4dfee653d0ecb74a111a57b501617f6eb99f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -279,11 +279,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '4e3b218e9695b1f7011ff80319e75e14a35cf466', + 'dawn_revision': '68d97adf88de11cd9c5b9e2f9a77d50ab985ede4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': 'ad0248681e65620726a9cd2fc22df10da8f85346', + 'quiche_revision': '0b5bfaebe8ba794946fe335423c4013f2743ddee', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -298,7 +298,7 @@ # revisions. # GN CIPD package version. - 'gn_version': 'git_revision:972ed755f8e6d31cae9ba15fcd08136ae1a7886f', + 'gn_version': 'git_revision:152c5144ceed9592c20f0c8fd55769646077569b', # Also, if you change these, update buildtools/DEPS too. Also update the # libc++ svn_revision in //buildtools/deps_revisions.gni. @@ -1374,7 +1374,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'abaae129d9a0c6e1e092067e0b105475df43352e', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '61689ab0630a4489549a67024d6bd4fb2c153295', + Var('webrtc_git') + '/src.git' + '@' + 'cfefa0aef329aac0206c5e56efd90b3b0bdb88b6', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1415,7 +1415,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0ecadc16190aacfd177863dc7c64c9d39e2a7502', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@59b2d77a1e398b1154bbcb0e022683d57ca6f5a2', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index cd47d1b..466cf5f 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -994,7 +994,7 @@ if (content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) { // Manages its own lifetime. new android_webview::AwProxyingURLLoaderFactory( - 0 /* process_id */, std::move(request), nullptr, nullptr, + 0 /* process_id */, std::move(request), nullptr, true /* intercept_only */); } else { base::PostTaskWithTraits( @@ -1003,7 +1003,7 @@ [](network::mojom::URLLoaderFactoryRequest request) { // Manages its own lifetime. new android_webview::AwProxyingURLLoaderFactory( - 0 /* process_id */, std::move(request), nullptr, nullptr, + 0 /* process_id */, std::move(request), nullptr, true /* intercept_only */); }, std::move(request))); @@ -1069,8 +1069,7 @@ FROM_HERE, {content::BrowserThread::IO}, base::BindOnce(&AwProxyingURLLoaderFactory::CreateProxy, process_id, std::move(proxied_receiver), - std::move(target_factory_info), - nullptr /* AwInterceptedRequestHandler */)); + std::move(target_factory_info))); return true; } @@ -1088,8 +1087,7 @@ FROM_HERE, {content::BrowserThread::IO}, base::BindOnce(&AwProxyingURLLoaderFactory::CreateProxy, render_process_id, std::move(factory_receiver), - std::move(pending_proxy), - nullptr /* AwInterceptedRequestHandler */)); + std::move(pending_proxy))); } uint32_t AwContentBrowserClient::GetWebSocketOptions(
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc index e78f414..0efa517 100644 --- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc +++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
@@ -711,13 +711,10 @@ int process_id, network::mojom::URLLoaderFactoryRequest loader_request, network::mojom::URLLoaderFactoryPtrInfo target_factory_info, - std::unique_ptr<AwInterceptedRequestHandler> request_handler, bool intercept_only) : process_id_(process_id), - request_handler_(std::move(request_handler)), intercept_only_(intercept_only), weak_factory_(this) { - // actual creation of the factory DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(!(intercept_only_ && target_factory_info)); if (target_factory_info) { @@ -738,14 +735,12 @@ void AwProxyingURLLoaderFactory::CreateProxy( int process_id, network::mojom::URLLoaderFactoryRequest loader_request, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info, - std::unique_ptr<AwInterceptedRequestHandler> request_handler) { + network::mojom::URLLoaderFactoryPtrInfo target_factory_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // will manage its own lifetime new AwProxyingURLLoaderFactory(process_id, std::move(loader_request), - std::move(target_factory_info), - std::move(request_handler), false); + std::move(target_factory_info), false); } void AwProxyingURLLoaderFactory::CreateLoaderAndStart(
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h index 0a4cb7887..4a367eb 100644 --- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h +++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
@@ -22,11 +22,32 @@ namespace android_webview { -class AwInterceptedRequestHandler {}; - -// URL Loader Factory for android webview, for supporting request/response -// interception, processing and callback invocation. Currently contains basic -// pass-through implementation. +// URL Loader Factory for Android WebView. This is the entry point for handling +// Android WebView callbacks (i.e. error, interception and other callbacks) and +// loading of android specific schemes and overridden responses. +// +// This class contains centralized logic for: +// - request interception and blocking, +// - setting load flags and headers, +// - loading requests depending on the scheme (e.g. different delegates are +// used for loading android assets/resources as compared to overridden +// responses). +// - handling errors (e.g. no input stream, redirect or safebrowsing related +// errors). +// +// In particular handles the following Android WebView callbacks: +// - shouldInterceptRequest +// - onReceivedError +// - onReceivedHttpError +// - onReceivedLoginRequest +// +// Threading: +// Currently the factory and the associated loader assume they live on the IO +// thread. This is also required by the shouldInterceptRequest callback (which +// should be called on a non-UI thread). The other callbacks (i.e. +// onReceivedError, onReceivedHttpError and onReceivedLoginRequest) are posted +// on the UI thread. +// class AwProxyingURLLoaderFactory : public network::mojom::URLLoaderFactory { public: // Create a factory that will create specialized URLLoaders for Android @@ -38,7 +59,6 @@ int process_id, network::mojom::URLLoaderFactoryRequest loader_request, network::mojom::URLLoaderFactoryPtrInfo target_factory_info, - std::unique_ptr<AwInterceptedRequestHandler> request_handler, bool intercept_only); ~AwProxyingURLLoaderFactory() override; @@ -47,8 +67,7 @@ static void CreateProxy( int process_id, network::mojom::URLLoaderFactoryRequest loader, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info, - std::unique_ptr<AwInterceptedRequestHandler> request_handler); + network::mojom::URLLoaderFactoryPtrInfo target_factory_info); void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, int32_t routing_id, @@ -69,10 +88,6 @@ mojo::BindingSet<network::mojom::URLLoaderFactory> proxy_bindings_; network::mojom::URLLoaderFactoryPtr target_factory_; - // TODO(timvolodine): consider functionality to have multiple interception - // handlers operating in sequence. - std::unique_ptr<AwInterceptedRequestHandler> request_handler_; - // When true the loader resulting from this factory will only execute // intercept callback (shouldInterceptRequest). If that returns without // a response, the loader will abort loading.
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc index e0929a1..1dbb1ab 100644 --- a/android_webview/lib/aw_main_delegate.cc +++ b/android_webview/lib/aw_main_delegate.cc
@@ -53,7 +53,6 @@ #include "gpu/ipc/gl_in_process_context.h" #include "media/base/media_switches.h" #include "media/media_buildflags.h" -#include "services/network/public/cpp/features.h" #include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_switches.h" #include "ui/events/gesture_detection/gesture_configuration.h" @@ -201,10 +200,6 @@ features.DisableIfNotSet(features::kAndroidSurfaceControl); - // Network service for WebView is still being evaluated. Once enabled - // by default the following line can be deleted. - features.DisableIfNotSet(network::features::kNetworkService); - // TODO(https://crbug.com/963653): SmsReceiver is not yet supported on // WebView. features.DisableIfNotSet(features::kSmsReceiver);
diff --git a/ash/app_list/views/app_list_folder_view.cc b/ash/app_list/views/app_list_folder_view.cc index d9f433c..4fdea27 100644 --- a/ash/app_list/views/app_list_folder_view.cc +++ b/ash/app_list/views/app_list_folder_view.cc
@@ -64,20 +64,14 @@ // folder's background when opening the folder. Transit the other way when // closing the folder. class BackgroundAnimation : public AppListFolderView::Animation, - public views::AnimationDelegateViews { + public ui::ImplicitAnimationObserver { public: BackgroundAnimation(bool show, AppListFolderView* folder_view, views::View* background_view) - : AnimationDelegateViews(background_view), - show_(show), - animation_(this), + : show_(show), folder_view_(folder_view), - background_view_(background_view) { - animation_.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN); - animation_.SetSlideDuration( - AppListConfig::instance().folder_transition_in_duration_ms()); - } + background_view_(background_view) {} ~BackgroundAnimation() override = default; @@ -88,14 +82,14 @@ const int icon_radius = AppListConfig::instance().folder_icon_radius(); const int folder_radius = AppListConfig::instance().folder_background_radius(); - from_radius_ = show_ ? icon_radius : folder_radius; - to_radius_ = show_ ? folder_radius : icon_radius; - from_rect_ = show_ ? folder_view_->folder_item_icon_bounds() - : background_view_->bounds(); - from_rect_ -= background_view_->bounds().OffsetFromOrigin(); - to_rect_ = show_ ? background_view_->bounds() - : folder_view_->folder_item_icon_bounds(); - to_rect_ -= background_view_->bounds().OffsetFromOrigin(); + const int from_radius = show_ ? icon_radius : folder_radius; + const int to_radius = show_ ? folder_radius : icon_radius; + gfx::Rect from_rect = show_ ? folder_view_->folder_item_icon_bounds() + : background_view_->bounds(); + from_rect -= background_view_->bounds().OffsetFromOrigin(); + gfx::Rect to_rect = show_ ? background_view_->bounds() + : folder_view_->folder_item_icon_bounds(); + to_rect -= background_view_->bounds().OffsetFromOrigin(); const SkColor background_color = AppListConfig::instance().folder_background_color(); const SkColor from_color = @@ -106,55 +100,36 @@ : AppListConfig::instance().folder_bubble_color(); background_view_->layer()->SetColor(from_color); - background_view_->layer()->SetClipRect(from_rect_); + background_view_->layer()->SetClipRect(from_rect); background_view_->layer()->SetRoundedCornerRadius( - gfx::RoundedCornersF(from_radius_)); + gfx::RoundedCornersF(from_radius)); - // We use the layer animation for the color, while gfx::Animation to update - // the corner radius and the clip rect. They can be slightly inconsistent - // since these animations run independently. ui::ScopedLayerAnimationSettings settings( background_view_->layer()->GetAnimator()); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( AppListConfig::instance().folder_transition_in_duration_ms())); settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN); + settings.AddObserver(this); background_view_->layer()->SetColor(to_color); - - animation_.Show(); - } - - bool IsAnimationRunning() override { return animation_.is_animating(); } - - // gfx::AnimationDelegate - void AnimationProgressed(const gfx::Animation* animation) override { - const double progress = animation->GetCurrentValue(); - const int current_radius = - gfx::Tween::IntValueBetween(progress, from_radius_, to_radius_); + background_view_->layer()->SetClipRect(to_rect); background_view_->layer()->SetRoundedCornerRadius( - gfx::RoundedCornersF(current_radius)); - const gfx::Rect current_bounds = - gfx::Tween::RectValueBetween(progress, from_rect_, to_rect_); - background_view_->layer()->SetClipRect(current_bounds); + gfx::RoundedCornersF(to_radius)); + is_animating_ = true; } - void AnimationEnded(const gfx::Animation* animation) override { + + bool IsAnimationRunning() override { return is_animating_; } + + // ui::ImplicitAnimationObserver: + void OnImplicitAnimationsCompleted() override { + is_animating_ = false; folder_view_->RecordAnimationSmoothness(); } - void AnimationCanceled(const gfx::Animation* animation) override { - AnimationEnded(animation); - } // True if opening the folder. const bool show_; - // The source and target state of the background's corner radius. - int from_radius_ = 0; - int to_radius_ = 0; + bool is_animating_ = false; - // The source and target state of the bounds of the background. - gfx::Rect from_rect_; - gfx::Rect to_rect_; - - gfx::SlideAnimation animation_; AppListFolderView* const folder_view_; // Not owned. views::View* const background_view_; // Not owned.
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc index 07399b9..c4ffef24 100644 --- a/ash/app_list/views/app_list_item_view.cc +++ b/ash/app_list/views/app_list_item_view.cc
@@ -159,6 +159,22 @@ return old_layer; } + // Update the rounded corner and insets with animation. |show| is true when + // the target rounded corner radius and insets are for showing the indicator + // circle. + void AnimateRoundedCornerAndInsets(bool show) { + ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator()); + settings.SetTweenType(gfx::Tween::EASE_IN); + settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( + kDraggedViewHoverAnimationDurationForFolder)); + + SetRoundedCornerAndInsets( + show ? AppListConfig::instance().folder_unclipped_icon_dimension() / 2 + : AppListConfig::instance().folder_icon_dimension() / 2, + show ? gfx::Insets() + : gfx::Insets(AppListConfig::instance().folder_icon_insets())); + } + // Sets the rounded corner and the clip insets. void SetRoundedCornerAndInsets(int corner_radius, const gfx::Insets& insets) { EnsureLayer(); @@ -761,11 +777,19 @@ } void AppListItemView::OnDraggedViewEnter() { + if (is_folder_) { + icon_->AnimateRoundedCornerAndInsets(true); + return; + } CreateDraggedViewHoverAnimation(); dragged_view_hover_animation_->Show(); } void AppListItemView::OnDraggedViewExit() { + if (is_folder_) { + icon_->AnimateRoundedCornerAndInsets(false); + return; + } CreateDraggedViewHoverAnimation(); dragged_view_hover_animation_->Hide(); } @@ -786,18 +810,7 @@ } void AppListItemView::AnimationProgressed(const gfx::Animation* animation) { - if (is_folder_) { - // Animate the folder icon via changing mask layer's corner radius and - // insets. - const double progress = animation->GetCurrentValue(); - const int corner_radius = gfx::Tween::IntValueBetween( - progress, AppListConfig::instance().folder_icon_dimension() / 2, - AppListConfig::instance().folder_unclipped_icon_dimension() / 2); - const int insets = gfx::Tween::IntValueBetween( - progress, AppListConfig::instance().folder_icon_insets(), 0); - icon_->SetRoundedCornerAndInsets(corner_radius, gfx::Insets(insets)); - return; - } + DCHECK(!is_folder_); preview_circle_radius_ = gfx::Tween::IntValueBetween( animation->GetCurrentValue(), 0, @@ -926,14 +939,15 @@ } void AppListItemView::CreateDraggedViewHoverAnimation() { + DCHECK(!is_folder_); + if (dragged_view_hover_animation_) return; dragged_view_hover_animation_ = std::make_unique<gfx::SlideAnimation>(this); dragged_view_hover_animation_->SetTweenType(gfx::Tween::EASE_IN); dragged_view_hover_animation_->SetSlideDuration( - is_folder_ ? kDraggedViewHoverAnimationDurationForFolder - : kDraggedViewHoverAnimationDuration); + kDraggedViewHoverAnimationDuration); } void AppListItemView::AdaptBoundsForSelectionHighlight(gfx::Rect* bounds) {
diff --git a/ash/public/cpp/wallpaper_controller_client.h b/ash/public/cpp/wallpaper_controller_client.h index 5f41ae9..2889165 100644 --- a/ash/public/cpp/wallpaper_controller_client.h +++ b/ash/public/cpp/wallpaper_controller_client.h
@@ -14,12 +14,6 @@ public: // Opens the wallpaper picker window. virtual void OpenWallpaperPicker() = 0; - - // Notifies the client that the animation of the first wallpaper since the - // controller initialization has completed. - // TODO(crbug.com/875128): Remove this after web-ui login code is completely - // removed. - virtual void OnFirstWallpaperAnimationFinished() = 0; }; } // namespace ash
diff --git a/ash/shelf/shelf_context_menu_model_unittest.cc b/ash/shelf/shelf_context_menu_model_unittest.cc index 69504da..4b1671d 100644 --- a/ash/shelf/shelf_context_menu_model_unittest.cc +++ b/ash/shelf/shelf_context_menu_model_unittest.cc
@@ -50,7 +50,6 @@ // WallpaperControllerClient: void OpenWallpaperPicker() override { open_count_++; } - void OnFirstWallpaperAnimationFinished() override {} private: size_t open_count_ = 0;
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc index df68ae5f..3edaa22e 100644 --- a/ash/wallpaper/wallpaper_controller_impl.cc +++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -615,12 +615,6 @@ return true; } -void WallpaperControllerImpl::OnWallpaperAnimationFinished() { - // TODO(crbug.com/875128): Remove this after web-ui login code is removed. - if (wallpaper_controller_client_ && is_first_wallpaper_) - wallpaper_controller_client_->OnFirstWallpaperAnimationFinished(); -} - bool WallpaperControllerImpl::CanOpenWallpaperPicker() { return ShouldShowWallpaperSetting() && !IsActiveUserWallpaperControlledByPolicy();
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h index b5e0cdcf..6c869fa 100644 --- a/ash/wallpaper/wallpaper_controller_impl.h +++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -133,9 +133,6 @@ // wallpapers at login screen). bool ShouldShowInitialAnimation(); - // Notifies the controller that the wallpaper animation has finished. - void OnWallpaperAnimationFinished(); - // Returns true if the active user is allowed to open the wallpaper picker. bool CanOpenWallpaperPicker();
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index 2890304..15894459 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -231,15 +231,12 @@ virtual ~TestWallpaperControllerClient() = default; size_t open_count() const { return open_count_; } - size_t animation_count() const { return animation_count_; } // WallpaperControllerClient: void OpenWallpaperPicker() override { open_count_++; } - void OnFirstWallpaperAnimationFinished() override { animation_count_++; } private: size_t open_count_ = 0; - size_t animation_count_ = 0; DISALLOW_COPY_AND_ASSIGN(TestWallpaperControllerClient); }; @@ -552,13 +549,6 @@ EXPECT_TRUE(controller_->CanOpenWallpaperPicker()); controller_->OpenWallpaperPickerIfAllowed(); EXPECT_EQ(1u, client.open_count()); - - EXPECT_EQ(0u, client.animation_count()); - controller_->ShowWallpaperImage(CreateImage(640, 480, SK_ColorBLUE), - CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH), - /*preview_mode=*/false, - /*always_on_top=*/false); - EXPECT_EQ(1u, client.animation_count()); } TEST_F(WallpaperControllerTest, BasicReparenting) {
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc index f930f96..8d117d8 100644 --- a/ash/wallpaper/wallpaper_view.cc +++ b/ash/wallpaper/wallpaper_view.cc
@@ -232,7 +232,7 @@ ::wm::SetWindowVisibilityAnimationType(wallpaper_window, animation_type); // Enable wallpaper transition for the following cases: - // 1. Initial(OOBE) wallpaper animation. + // 1. Initial wallpaper animation after device boot. // 2. Wallpaper fades in from a non empty background. // 3. From an empty background, chrome transit to a logged in user session. // 4. From an empty background, guest user logged in.
diff --git a/ash/wallpaper/wallpaper_widget_controller.cc b/ash/wallpaper/wallpaper_widget_controller.cc index f6b2395..f9b13ad 100644 --- a/ash/wallpaper/wallpaper_widget_controller.cc +++ b/ash/wallpaper/wallpaper_widget_controller.cc
@@ -8,8 +8,6 @@ #include "ash/ash_export.h" #include "ash/root_window_controller.h" -#include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" #include "base/scoped_observer.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h" @@ -262,7 +260,6 @@ // Notify observers that animation finished. RunAnimationEndCallbacks(); - Shell::Get()->wallpaper_controller()->OnWallpaperAnimationFinished(); } void WallpaperWidgetController::RunAnimationEndCallbacks() {
diff --git a/base/scoped_observer.h b/base/scoped_observer.h index ecad6c0..f5ddc73 100644 --- a/base/scoped_observer.h +++ b/base/scoped_observer.h
@@ -52,6 +52,8 @@ bool IsObservingSources() const { return !sources_.empty(); } + size_t GetSourcesCount() const { return sources_.size(); } + private: Observer* observer_;
diff --git a/build/config/ios/ios_sdk_overrides.gni b/build/config/ios/ios_sdk_overrides.gni index 5699ebe..d139a97 100644 --- a/build/config/ios/ios_sdk_overrides.gni +++ b/build/config/ios/ios_sdk_overrides.gni
@@ -7,11 +7,11 @@ declare_args() { # Version of iOS that we're targeting. - ios_deployment_target = "11.0" + ios_deployment_target = "12.0" } # Always assert that ios_deployment_target is used on non-iOS platforms to # prevent unused args warnings. if (!is_ios) { - assert(ios_deployment_target == "11.0" || true) + assert(ios_deployment_target == "12.0" || true) }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index a6da973..bdc6462 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8907154544763250576 \ No newline at end of file +8907128039086305440 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 21f99f0..77d0db30 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8907153950120029888 \ No newline at end of file +8907132289784850704 \ No newline at end of file
diff --git a/buildtools/DEPS b/buildtools/DEPS index 46c3966..602bc00 100644 --- a/buildtools/DEPS +++ b/buildtools/DEPS
@@ -14,7 +14,7 @@ # # GN CIPD package version. - 'gn_version': 'git_revision:972ed755f8e6d31cae9ba15fcd08136ae1a7886f', + 'gn_version': 'git_revision:152c5144ceed9592c20f0c8fd55769646077569b', # When changing these, also update the svn revisions in deps_revisions.gni 'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917',
diff --git a/cc/animation/keyframed_animation_curve.h b/cc/animation/keyframed_animation_curve.h index 27e87ba3..c843fc7f 100644 --- a/cc/animation/keyframed_animation_curve.h +++ b/cc/animation/keyframed_animation_curve.h
@@ -164,12 +164,15 @@ // BackgrounColorAnimationCurve implementation SkColor GetValue(base::TimeDelta t) const override; + using Keyframes = std::vector<std::unique_ptr<ColorKeyframe>>; + const Keyframes& keyframes_for_testing() const { return keyframes_; } + private: KeyframedColorAnimationCurve(); // Always sorted in order of increasing time. No two keyframes have the // same time. - std::vector<std::unique_ptr<ColorKeyframe>> keyframes_; + Keyframes keyframes_; std::unique_ptr<TimingFunction> timing_function_; double scaled_duration_; };
diff --git a/chrome/VERSION b/chrome/VERSION index d9d8172..a8f6692 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=77 MINOR=0 -BUILD=3862 +BUILD=3863 PATCH=0
diff --git a/chrome/android/features/vr/java/AndroidManifest.xml b/chrome/android/features/vr/java/AndroidManifest.xml index 4a2c233..388353f7 100644 --- a/chrome/android/features/vr/java/AndroidManifest.xml +++ b/chrome/android/features/vr/java/AndroidManifest.xml
@@ -8,9 +8,17 @@ featureSplit="vr"> <dist:module - dist:onDemand="true" - dist:title="@string/vr_module_title"> - <dist:fusing dist:include="false" /> + dist:instant="false" + dist:title="@string/vr_module_title"> + <dist:fusing dist:include="false" /> + <dist:delivery> + <dist:install-time> + <dist:conditions> + <dist:device-feature dist:name="android.hardware.vr.high_performance" /> + </dist:conditions> + </dist:install-time> + <dist:on-demand /> + </dist:delivery> </dist:module> <application>
diff --git a/chrome/android/features/vr/java/AndroidManifest_chrome_modern.xml b/chrome/android/features/vr/java/AndroidManifest_chrome_modern.xml new file mode 100644 index 0000000..4a2c233 --- /dev/null +++ b/chrome/android/features/vr/java/AndroidManifest_chrome_modern.xml
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:dist="http://schemas.android.com/apk/distribution" + featureSplit="vr"> + + <dist:module + dist:onDemand="true" + dist:title="@string/vr_module_title"> + <dist:fusing dist:include="false" /> + </dist:module> + + <application> + </application> +</manifest>
diff --git a/chrome/android/features/vr/vr_module.gni b/chrome/android/features/vr/vr_module.gni index 429f1d7..7dd4443 100644 --- a/chrome/android/features/vr/vr_module.gni +++ b/chrome/android/features/vr/vr_module.gni
@@ -21,3 +21,7 @@ loadable_module = "libvr_ui_dummy_lib.so" } } + +vr_chrome_modern_module_desc = vr_module_desc +vr_chrome_modern_module_desc.android_manifest = + "//chrome/android/features/vr/java/AndroidManifest_chrome_modern.xml"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java index a7cb1f6..d3dcbc4f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java
@@ -109,6 +109,9 @@ public static @Type int fromMimeType(String mimeType) { if (TextUtils.isEmpty(mimeType)) return Type.OTHER; + Integer type = filterForSpecialMimeTypes(mimeType); + if (type != null) return type; + String[] pieces = mimeType.toLowerCase(Locale.getDefault()).split("/"); if (pieces.length != 2) return Type.OTHER; @@ -124,4 +127,9 @@ return Type.OTHER; } } + + private static Integer filterForSpecialMimeTypes(String mimeType) { + if (mimeType.equals("application/ogg")) return Type.AUDIO; + return null; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java index cfd66cc..0fb7e6a5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java
@@ -31,6 +31,8 @@ ChromeNotificationBuilder setSmallIcon(Icon icon); + ChromeNotificationBuilder setColor(int argb); + ChromeNotificationBuilder setTicker(CharSequence text); ChromeNotificationBuilder setLocalOnly(boolean localOnly);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java index 39e6295..4c9ec2f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java
@@ -89,6 +89,14 @@ } @Override + public ChromeNotificationBuilder setColor(int argb) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mBuilder.setColor(argb); + } + return this; + } + + @Override public ChromeNotificationBuilder setTicker(CharSequence text) { mBuilder.setTicker(text); return this;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java index b3e3659..501c519 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java
@@ -86,6 +86,12 @@ } @Override + public ChromeNotificationBuilder setColor(int argb) { + mBuilder.setColor(argb); + return this; + } + + @Override public ChromeNotificationBuilder setTicker(CharSequence text) { mBuilder.setTicker(text); return this;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java index c66bcd6..0a2ad62 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
@@ -114,8 +114,8 @@ models.add(model); mPendingImageRequests.put(url, models); - mImageFetcher.fetchImage(url, "EntitySuggestionProcessor", mEntityImageSizePx, - mEntityImageSizePx, (Bitmap bitmap) -> { + mImageFetcher.fetchImage(url, ImageFetcher.ENTITY_SUGGESTIONS_UMA_CLIENT_NAME, + mEntityImageSizePx, mEntityImageSizePx, (Bitmap bitmap) -> { ThreadUtils.assertOnUiThread(); final List<PropertyModel> pendingModels = mPendingImageRequests.remove(url);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java index 51decac..b11df5f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java
@@ -14,6 +14,7 @@ import android.support.v4.app.NotificationCompat; import android.text.TextUtils; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.metrics.CachedMetrics; @@ -81,6 +82,8 @@ .setContentIntent(contentIntent) .setContentTitle(phoneNumber) .setContentText(text) + .setColor(ApiCompatibilityUtils.getColor( + context.getResources(), R.color.default_icon_color_blue)) .setGroup(NotificationConstants.GROUP_CLICK_TO_CALL) .setPriorityBeforeO(NotificationCompat.PRIORITY_HIGH) .setVibrate(new long[0])
diff --git a/chrome/android/modules/chrome_feature_modules.gni b/chrome/android/modules/chrome_feature_modules.gni index 765f7a6..4f72ca8 100644 --- a/chrome/android/modules/chrome_feature_modules.gni +++ b/chrome/android/modules/chrome_feature_modules.gni
@@ -49,7 +49,7 @@ # Modules shipped in Chrome Modern (Android L+). chrome_modern_module_descs = [] if (enable_vr) { - chrome_modern_module_descs += [ vr_module_desc ] + chrome_modern_module_descs += [ vr_chrome_modern_module_desc ] } if (dfmify_dev_ui) { chrome_modern_module_descs += [ dev_ui_module_desc ] @@ -57,6 +57,10 @@ # Modules shipped in Monochrome (Android N+). monochrome_module_descs = chrome_modern_module_descs +if (enable_vr) { + monochrome_module_descs -= [ vr_chrome_modern_module_desc ] + monochrome_module_descs += [ vr_module_desc ] +} if (enable_arcore) { monochrome_module_descs += [ ar_module_desc ] }
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index 6d25c29..0c2cb55 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -1169,9 +1169,6 @@ <message name="IDS_WELCOME_HEADER" desc="A message which will appear as the header on the Welcome UI if the user has never run Chromium before."> Welcome to Chromium </message> - <message name="IDS_WELCOME_HEADER_AFTER_FIRST_RUN" desc="A message which will appear as the header on the Welcome UI if the user has run Chromium before."> - Take Chromium everywhere - </message> </if> <!-- Native notifications for Windows 10 -->
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index e09cf16..1dfdd3c 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -9330,22 +9330,6 @@ </message> </if> - <!-- Welcome page (chrome://welcome) strings --> - <if expr="not chromeos"> - <message name="IDS_WELCOME_SUBHEADER" desc="A message which will appear underneath the header on the Welcome UI."> - The web browser by Google, for you - </message> - <message name="IDS_WELCOME_DESCRIPTION" desc="A message on the welcome page explaining the purpose of signing in."> - Sign in to Chrome with your Google Account to get your bookmarks, history, passwords, and other settings on all your devices. - </message> - <message name="IDS_WELCOME_ACCEPT_BUTTON" desc="A button on the welcome page which accepts the offer to sign in to Chrome."> - Sign in - </message> - <message name="IDS_WELCOME_DECLINE_BUTTON" desc="A button on the welcome page which declines the offer to sign in to Chrome."> - No thanks - </message> - </if> - <!-- Windows 10 toast strings --> <if expr="is_win"> <message name="IDS_WIN10_TOAST_BROWSE_FAST" desc="Toast message variant: browse fast.">
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index 5c58d56..fb159f1 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -1188,9 +1188,6 @@ <message name="IDS_WELCOME_HEADER" desc="A message which will appear as the header on the Welcome UI if the user has never run Chrome before."> Welcome to Chrome </message> - <message name="IDS_WELCOME_HEADER_AFTER_FIRST_RUN" desc="A message which will appear as the header on the Welcome UI if the user has run Chrome before."> - Take Chrome everywhere - </message> </if> <!-- Native notifications for Windows 10 -->
diff --git a/chrome/app/onboarding_welcome_strings.grdp b/chrome/app/onboarding_welcome_strings.grdp index cbabb3c..ca34a69 100644 --- a/chrome/app/onboarding_welcome_strings.grdp +++ b/chrome/app/onboarding_welcome_strings.grdp
@@ -1,9 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> <!-- Shared strings --> - <message name="IDS_ONBOARDING_WELCOME_GET_STARTED" desc="Label for a confirmation button to finish adding a bookmark and get the user started with using the browser."> - Get started - </message> <message name="IDS_ONBOARDING_WELCOME_NEXT" desc="Label for a button to confirm and continue from the current onboarding step."> Next </message> @@ -90,9 +87,6 @@ <message name="IDS_ONBOARDING_WELCOME_NUX_SET_AS_DEFAULT_SUB_HEADER" desc="Sub-header for the page that prompts user to set Chrome as their default browser."> Get Google Search and Google smarts everytime you browse </message> - <message name="IDS_ONBOARDING_WELCOME_NUX_SET_AS_DEFAULT_SKIP" desc="The label for a button to skip setting Chrome as their default browser."> - Skip - </message> <message name="IDS_ONBOARDING_WELCOME_NUX_SET_AS_DEFAULT_SET_AS_DEFAULT" desc="The label for a button to confirm setting Chrome as their default browser."> Set as default </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0389149f..11ee113a 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3530,11 +3530,6 @@ flag_descriptions::kEnableAssistantAppSupportDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::assistant::features::kAssistantAppSupport)}, - {"enable-assistant-key-remapping", - flag_descriptions::kEnableAssistantKeyRemappingName, - flag_descriptions::kEnableAssistantKeyRemappingDescription, kOsCrOS, - FEATURE_VALUE_TYPE(chromeos::assistant::features::kAssistantKeyRemapping)}, - {"enable-assistant-media-session-integration", flag_descriptions::kEnableAssistantMediaSessionIntegrationName, flag_descriptions::kEnableAssistantMediaSessionIntegrationDescription,
diff --git a/chrome/browser/android/feed/feed_offline_bridge.cc b/chrome/browser/android/feed/feed_offline_bridge.cc index 664fd053..dae5d0fe 100644 --- a/chrome/browser/android/feed/feed_offline_bridge.cc +++ b/chrome/browser/android/feed/feed_offline_bridge.cc
@@ -134,7 +134,7 @@ if (!j_snippet.is_null()) { metadata.snippet = base::android::ConvertJavaStringToUTF8(env, j_snippet); } - known_content_metadata_buffer_.push_back(std::move(metadata)); + known_content_metadata_buffer_.emplace_back(std::move(metadata)); } void FeedOfflineBridge::OnGetKnownContentDone(
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn index 177b1ea..3deba2912 100644 --- a/chrome/browser/android/vr/BUILD.gn +++ b/chrome/browser/android/vr/BUILD.gn
@@ -85,6 +85,7 @@ "arcore_device/arcore_impl.h", "arcore_device/arcore_java_utils.cc", "arcore_device/arcore_java_utils.h", + "arcore_device/arcore_sdk.h", "arcore_device/arcore_session_utils.h", "arcore_device/arcore_shim.cc", "arcore_device/arcore_shim.h",
diff --git a/chrome/browser/android/vr/arcore_device/arcore_impl.cc b/chrome/browser/android/vr/arcore_device/arcore_impl.cc index 1054860..aba8193 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_impl.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_impl.cc
@@ -73,6 +73,11 @@ return false; } + // Set incognito mode for ARCore session - this is done unconditionally as we + // always want to limit the amount of logging done by ARCore. + ArSession_enableIncognitoMode_private(session.get()); + DVLOG(1) << __func__ << ": ARCore incognito mode enabled"; + internal::ScopedArCoreObject<ArConfig*> arcore_config; ArConfig_create( session.get(), @@ -247,7 +252,7 @@ fn(ar_plane); } -} +} // namespace device std::vector<mojom::XRPlaneDataPtr> ArCoreImpl::GetUpdatedPlanesData() { EnsureArCorePlanesList();
diff --git a/chrome/browser/android/vr/arcore_device/arcore_impl.h b/chrome/browser/android/vr/arcore_device/arcore_impl.h index 013418d..4863016 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_impl.h +++ b/chrome/browser/android/vr/arcore_device/arcore_impl.h
@@ -9,8 +9,8 @@ #include "base/optional.h" #include "base/scoped_generic.h" #include "chrome/browser/android/vr/arcore_device/arcore.h" +#include "chrome/browser/android/vr/arcore_device/arcore_sdk.h" #include "device/vr/public/mojom/vr_service.mojom.h" -#include "third_party/arcore-android-sdk/src/libraries/include/arcore_c_api.h" namespace device {
diff --git a/chrome/browser/android/vr/arcore_device/arcore_sdk.h b/chrome/browser/android/vr/arcore_device/arcore_sdk.h new file mode 100644 index 0000000..428c4c76 --- /dev/null +++ b/chrome/browser/android/vr/arcore_device/arcore_sdk.h
@@ -0,0 +1,17 @@ +// 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_VR_ARCORE_DEVICE_ARCORE_SDK_H_ +#define CHROME_BROWSER_ANDROID_VR_ARCORE_DEVICE_ARCORE_SDK_H_ + +#include "third_party/arcore-android-sdk/src/libraries/include/arcore_c_api.h" + +/// Sets ARCore to comply with incognito mode in Google Chrome and Chromium. +/// When called before calling Resume(), it will minimize the amount of logging +/// done by ARCore for this ArSession. +/// +/// @param[in] session - the ARCore session. +void ArSession_enableIncognitoMode_private(ArSession* session); + +#endif // CHROME_BROWSER_ANDROID_VR_ARCORE_DEVICE_ARCORE_SDK_H_
diff --git a/chrome/browser/android/vr/arcore_device/arcore_shim.cc b/chrome/browser/android/vr/arcore_device/arcore_shim.cc index f6b01197..4ee8a62f2 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_shim.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_shim.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/arcore-android-sdk/src/libraries/include/arcore_c_api.h" +#include "chrome/browser/android/vr/arcore_device/arcore_sdk.h" #include <dlfcn.h> @@ -12,52 +12,53 @@ namespace { // Run CALL macro for every function defined in the API. -#define FOR_EACH_API_FN \ - CALL(ArCamera_getDisplayOrientedPose) \ - CALL(ArCamera_getProjectionMatrix) \ - CALL(ArCamera_getTrackingState) \ - CALL(ArCamera_getViewMatrix) \ - CALL(ArConfig_create) \ - CALL(ArConfig_destroy) \ - CALL(ArFrame_acquireCamera) \ - CALL(ArFrame_create) \ - CALL(ArFrame_destroy) \ - CALL(ArFrame_getUpdatedTrackables) \ - CALL(ArFrame_hitTestRay) \ - CALL(ArFrame_transformCoordinates2d) \ - CALL(ArHitResult_acquireTrackable) \ - CALL(ArHitResult_create) \ - CALL(ArHitResult_destroy) \ - CALL(ArHitResult_getHitPose) \ - CALL(ArHitResultList_create) \ - CALL(ArHitResultList_destroy) \ - CALL(ArHitResultList_getItem) \ - CALL(ArHitResultList_getSize) \ - CALL(ArPlane_acquireSubsumedBy) \ - CALL(ArPlane_getCenterPose) \ - CALL(ArPlane_getPolygon) \ - CALL(ArPlane_getPolygonSize) \ - CALL(ArPlane_getType) \ - CALL(ArPlane_isPoseInPolygon) \ - CALL(ArPose_create) \ - CALL(ArPose_destroy) \ - CALL(ArPose_getMatrix) \ - CALL(ArPose_getPoseRaw) \ - CALL(ArSession_configure) \ - CALL(ArSession_create) \ - CALL(ArSession_destroy) \ - CALL(ArSession_getAllTrackables) \ - CALL(ArSession_pause) \ - CALL(ArSession_resume) \ - CALL(ArSession_setCameraTextureName) \ - CALL(ArSession_setDisplayGeometry) \ - CALL(ArSession_update) \ - CALL(ArTrackable_getTrackingState) \ - CALL(ArTrackable_getType) \ - CALL(ArTrackable_release) \ - CALL(ArTrackableList_acquireItem) \ - CALL(ArTrackableList_create) \ - CALL(ArTrackableList_destroy) \ +#define FOR_EACH_API_FN \ + CALL(ArCamera_getDisplayOrientedPose) \ + CALL(ArCamera_getProjectionMatrix) \ + CALL(ArCamera_getTrackingState) \ + CALL(ArCamera_getViewMatrix) \ + CALL(ArConfig_create) \ + CALL(ArConfig_destroy) \ + CALL(ArFrame_acquireCamera) \ + CALL(ArFrame_create) \ + CALL(ArFrame_destroy) \ + CALL(ArFrame_getUpdatedTrackables) \ + CALL(ArFrame_hitTestRay) \ + CALL(ArFrame_transformCoordinates2d) \ + CALL(ArHitResult_acquireTrackable) \ + CALL(ArHitResult_create) \ + CALL(ArHitResult_destroy) \ + CALL(ArHitResult_getHitPose) \ + CALL(ArHitResultList_create) \ + CALL(ArHitResultList_destroy) \ + CALL(ArHitResultList_getItem) \ + CALL(ArHitResultList_getSize) \ + CALL(ArPlane_acquireSubsumedBy) \ + CALL(ArPlane_getCenterPose) \ + CALL(ArPlane_getPolygon) \ + CALL(ArPlane_getPolygonSize) \ + CALL(ArPlane_getType) \ + CALL(ArPlane_isPoseInPolygon) \ + CALL(ArPose_create) \ + CALL(ArPose_destroy) \ + CALL(ArPose_getMatrix) \ + CALL(ArPose_getPoseRaw) \ + CALL(ArSession_configure) \ + CALL(ArSession_create) \ + CALL(ArSession_destroy) \ + CALL(ArSession_enableIncognitoMode_private) \ + CALL(ArSession_getAllTrackables) \ + CALL(ArSession_pause) \ + CALL(ArSession_resume) \ + CALL(ArSession_setCameraTextureName) \ + CALL(ArSession_setDisplayGeometry) \ + CALL(ArSession_update) \ + CALL(ArTrackable_getTrackingState) \ + CALL(ArTrackable_getType) \ + CALL(ArTrackable_release) \ + CALL(ArTrackableList_acquireItem) \ + CALL(ArTrackableList_create) \ + CALL(ArTrackableList_destroy) \ CALL(ArTrackableList_getSize) #define CALL(fn) decltype(&fn) impl_##fn = nullptr; @@ -352,6 +353,10 @@ arcore_api->impl_ArSession_destroy(session); } +void ArSession_enableIncognitoMode_private(ArSession* session) { + arcore_api->impl_ArSession_enableIncognitoMode_private(session); +} + void ArSession_getAllTrackables(const ArSession* session, ArTrackableType filter_type, ArTrackableList* out_trackable_list) {
diff --git a/chrome/browser/android/vr/arcore_device/type_converters.h b/chrome/browser/android/vr/arcore_device/type_converters.h index 111f104..c8cf665 100644 --- a/chrome/browser/android/vr/arcore_device/type_converters.h +++ b/chrome/browser/android/vr/arcore_device/type_converters.h
@@ -5,8 +5,8 @@ #ifndef CHROME_BROWSER_ANDROID_VR_ARCORE_DEVICE_TYPE_CONVERTERS_H_ #define CHROME_BROWSER_ANDROID_VR_ARCORE_DEVICE_TYPE_CONVERTERS_H_ +#include "chrome/browser/android/vr/arcore_device/arcore_sdk.h" #include "device/vr/public/mojom/vr_service.mojom.h" -#include "third_party/arcore-android-sdk/src/libraries/include/arcore_c_api.h" namespace mojo {
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc index a2ec7d61..33b016e 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -58,6 +58,10 @@ #include "chrome/browser/upgrade_detector/upgrade_detector.h" #endif +#if defined(OS_CHROMEOS) +#include "chromeos/constants/chromeos_features.h" +#endif + namespace { #if !defined(OS_ANDROID) @@ -69,18 +73,22 @@ chrome::kLanguageOptionsSubPage, chrome::kPasswordManagerSubPage, chrome::kPaymentsSubPage, chrome::kResetProfileSettingsSubPage, chrome::kSearchEnginesSubPage, chrome::kSyncSetupSubPage, -#if defined(OS_CHROMEOS) - chrome::kAccessibilitySubPage, chrome::kBluetoothSubPage, - chrome::kDateTimeSubPage, chrome::kDisplaySubPage, - chrome::kInternetSubPage, chrome::kPowerSubPage, - chrome::kStylusSubPage, -#else +#if !defined(OS_CHROMEOS) chrome::kCreateProfileSubPage, chrome::kImportDataSubPage, chrome::kManageProfileSubPage, chrome::kPeopleSubPage, #endif }; #endif // !defined(OS_ANDROID) +#if defined(OS_CHROMEOS) +const char* const kChromeOSSettingsSubPages[] = { + chrome::kAccessibilitySubPage, chrome::kBluetoothSubPage, + chrome::kDateTimeSubPage, chrome::kDisplaySubPage, + chrome::kInternetSubPage, chrome::kPowerSubPage, + chrome::kStylusSubPage, +}; +#endif // defined(OS_CHROMEOS) + } // namespace ChromeAutocompleteProviderClient::ChromeAutocompleteProviderClient( @@ -227,6 +235,18 @@ } #endif +#if defined(OS_CHROMEOS) + // TODO(crbug/950007): Delete this after the settings split is complete since + // the OS setting routes should not show up as an autocomplete suggestion in + // browser. + if (!base::FeatureList::IsEnabled(chromeos::features::kSplitSettings)) { + for (size_t i = 0; i < base::size(kChromeOSSettingsSubPages); i++) { + builtins.push_back(settings + + base::ASCIIToUTF16(kChromeOSSettingsSubPages[i])); + } + } +#endif + return builtins; }
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client_unittest.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client_unittest.cc index 00eb2a5..fd037b2 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client_unittest.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/prefs/pref_service.h" @@ -16,6 +17,10 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +#if defined(OS_CHROMEOS) +#include "chromeos/constants/chromeos_features.h" +#endif + namespace { class TestSchemeClassifier : public AutocompleteSchemeClassifier { @@ -146,3 +151,24 @@ GURL(test_case.url2), &input)); } } + +// TODO(crbug/950007): Remove this test when the split settings work is complete +#if defined(OS_CHROMEOS) +TEST_F(ChromeAutocompleteProviderClientTest, OSSettingsDoNotShowUp) { + size_t builtin_urls_with_os_settings; + size_t builtin_urls_without_os_settings; + + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(chromeos::features::kSplitSettings); + builtin_urls_with_os_settings = client_->GetBuiltinURLs().size(); + } + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(chromeos::features::kSplitSettings); + builtin_urls_without_os_settings = client_->GetBuiltinURLs().size(); + } + + EXPECT_GT(builtin_urls_with_os_settings, builtin_urls_without_os_settings); +} +#endif
diff --git a/chrome/browser/background_sync/background_sync_controller_impl.cc b/chrome/browser/background_sync/background_sync_controller_impl.cc index 290296c..1bf97cd 100644 --- a/chrome/browser/background_sync/background_sync_controller_impl.cc +++ b/chrome/browser/background_sync/background_sync_controller_impl.cc
@@ -191,10 +191,13 @@ #endif } -int BackgroundSyncControllerImpl::GetSiteEngagementPenalty( - const GURL& url) const { +int BackgroundSyncControllerImpl::GetSiteEngagementPenalty(const GURL& url) { blink::mojom::EngagementLevel engagement_level = site_engagement_service_->GetEngagementLevel(url); + if (engagement_level == blink::mojom::EngagementLevel::NONE) { + suspended_periodic_sync_origins_.insert( + url::Origin::Create(url.GetOrigin())); + } switch (engagement_level) { case blink::mojom::EngagementLevel::NONE: @@ -283,3 +286,11 @@ BackgroundSyncControllerImpl::BackgroundSyncEventKeepAliveImpl:: ~BackgroundSyncEventKeepAliveImpl() = default; #endif + +void BackgroundSyncControllerImpl::NoteSuspendedPeriodicSyncOrigins( + std::set<url::Origin> suspended_origins) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + for (auto& origin : suspended_origins) + suspended_periodic_sync_origins_.insert(std::move(origin)); +}
diff --git a/chrome/browser/background_sync/background_sync_controller_impl.h b/chrome/browser/background_sync/background_sync_controller_impl.h index 52a3a2a..7871ffd 100644 --- a/chrome/browser/background_sync/background_sync_controller_impl.h +++ b/chrome/browser/background_sync/background_sync_controller_impl.h
@@ -9,6 +9,8 @@ #include <stdint.h> +#include <set> + #include "base/macros.h" #include "base/time/time.h" #include "build/build_config.h" @@ -19,6 +21,7 @@ #include "content/public/browser/background_sync_registration.h" #include "content/public/browser/browser_thread.h" #include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h" +#include "url/gurl.h" namespace content { struct BackgroundSyncParameters; @@ -92,6 +95,8 @@ content::BackgroundSyncParameters* parameters) override; std::unique_ptr<BackgroundSyncEventKeepAlive> CreateBackgroundSyncEventKeepAlive() override; + void NoteSuspendedPeriodicSyncOrigins( + std::set<url::Origin> suspended_origins) override; private: // Gets the site engagement penalty for |url|, which is inversely proportional @@ -99,7 +104,7 @@ // the less often periodic sync events will be fired. // Returns kEngagementLevelNonePenalty if the engagement level is // blink::mojom::EngagementLevel::NONE. - int GetSiteEngagementPenalty(const GURL& url) const; + int GetSiteEngagementPenalty(const GURL& url); // Once we've identified the minimum number of hours between each periodicsync // event for an origin, every delay calculated for the origin should be a @@ -114,6 +119,8 @@ BackgroundSyncMetrics background_sync_metrics_; + std::set<url::Origin> suspended_periodic_sync_origins_; + DISALLOW_COPY_AND_ASSIGN(BackgroundSyncControllerImpl); };
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 510dc12..c0cef30 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -67,11 +67,6 @@ </else> </if> </if> - <if expr="not is_android and not chromeos"> - <structure name="IDR_WELCOME_CSS" file="resources\welcome\welcome.css" type="chrome_html" preprocess="true"/> - <structure name="IDR_WELCOME_HTML" file="resources\welcome\welcome.html" type="chrome_html" preprocess="true"/> - <structure name="IDR_WELCOME_JS" file="resources\welcome\welcome.js" type="chrome_html" preprocess="true"/> - </if> <if expr="chromeos"> <structure name="IDR_FIRST_RUN_HTML" file="resources\chromeos\first_run\first_run.html" flattenhtml="true" type="chrome_html"/> <structure name="IDR_FIRST_RUN_JS" file="resources\chromeos\first_run\first_run.js" flattenhtml="true" type="chrome_html" />
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h index 82d48c6..1a0c83d 100644 --- a/chrome/browser/chrome_notification_types.h +++ b/chrome/browser/chrome_notification_types.h
@@ -278,11 +278,6 @@ // which was installed. NOTIFICATION_APP_INSTALLED_TO_NTP, -#if defined(OS_CHROMEOS) - // Sent when wallpaper show animation has finished. - NOTIFICATION_WALLPAPER_ANIMATION_FINISHED, -#endif - // Note:- // Currently only Content and Chrome define and use notifications. // Custom notifications not belonging to Content and Chrome should start
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc index d6781fc..9e97973e 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -353,20 +353,6 @@ device.type != chromeos::AudioDeviceType::AUDIO_TYPE_OTHER; } -bool ShouldInitializeWebUIHidden() { - // Always postpone WebUI initialization on first boot, otherwise we miss - // initial animation. - if (!StartupUtils::IsOobeCompleted()) - return false; - - // Tests and kiosk app autolaunch don't support hidden. - if (WizardController::IsZeroDelayEnabled()) - return false; - - // Default. - return true; -} - } // namespace // static @@ -400,8 +386,7 @@ // LoginDisplayHostWebUI, public LoginDisplayHostWebUI::LoginDisplayHostWebUI() - : initialize_webui_hidden_(ShouldInitializeWebUIHidden()), - oobe_startup_sound_played_(StartupUtils::IsOobeCompleted()), + : oobe_startup_sound_played_(StartupUtils::IsOobeCompleted()), weak_factory_(this) { SessionManagerClient::Get()->AddObserver(this); CrasAudioHandler::Get()->AddAudioObserver(this); @@ -410,26 +395,12 @@ ui::DeviceDataManager::GetInstance()->AddObserver(this); - bool zero_delay_enabled = WizardController::IsZeroDelayEnabled(); - waiting_for_wallpaper_load_ = !zero_delay_enabled; - - if (waiting_for_wallpaper_load_) { - registrar_.Add(this, chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED, - content::NotificationService::AllSources()); - } - // When we wait for WebUI to be initialized we wait for one of // these notifications. - if (waiting_for_wallpaper_load_ && initialize_webui_hidden_) { - registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, - content::NotificationService::AllSources()); - registrar_.Add(this, chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, - content::NotificationService::AllSources()); - } - VLOG(1) << "Login WebUI >> " - << "zero_delay: " << zero_delay_enabled - << " wait_for_wp_load_: " << waiting_for_wallpaper_load_ - << " init_webui_hidden_: " << initialize_webui_hidden_; + registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()); + registrar_.Add(this, chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, + content::NotificationService::AllSources()); audio::SoundsManager* manager = audio::SoundsManager::Get(); ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); @@ -520,9 +491,9 @@ } void LoginDisplayHostWebUI::SetStatusAreaVisible(bool visible) { - if (initialize_webui_hidden_) + if (!login_view_) status_area_saved_visibility_ = visible; - else if (login_view_) + else login_view_->SetStatusAreaVisible(visible); } @@ -555,10 +526,6 @@ first_screen_ = first_screen; is_showing_login_ = false; - if (waiting_for_wallpaper_load_ && !initialize_webui_hidden_) { - VLOG(1) << "Login WebUI >> wizard postponed"; - return; - } VLOG(1) << "Login WebUI >> wizard"; if (!login_window_) @@ -635,10 +602,6 @@ is_showing_login_ = true; finalize_animation_type_ = ANIMATION_WORKSPACE; - if (waiting_for_wallpaper_load_ && !initialize_webui_hidden_) { - VLOG(1) << "Login WebUI >> sign in postponed"; - return; - } VLOG(1) << "Login WebUI >> sign in"; // TODO(crbug.com/784495): Make sure this is ported to views. @@ -731,35 +694,11 @@ if (chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE == type || chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN == type) { VLOG(1) << "Login WebUI >> WEBUI_VISIBLE"; - if (waiting_for_wallpaper_load_ && initialize_webui_hidden_) { - // Reduce time till login UI is shown - show it as soon as possible. - waiting_for_wallpaper_load_ = false; - ShowWebUI(); - } + ShowWebUI(); registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, content::NotificationService::AllSources()); registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, content::NotificationService::AllSources()); - } else if (chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED == type) { - VLOG(1) << "Login WebUI >> wp animation done"; - is_wallpaper_loaded_ = true; - if (waiting_for_wallpaper_load_) { - // StartWizard / StartSignInScreen could be called multiple times through - // the lifetime of host. - // Make sure that subsequent calls are not postponed. - waiting_for_wallpaper_load_ = false; - if (initialize_webui_hidden_) { - // If we're in the process of switching locale, the wallpaper might - // have finished loading before the locale switch was completed. - // Only show the UI if it already exists. - if (login_window_ && login_view_) - ShowWebUI(); - } else { - StartPostponedWebUI(); - } - } - registrar_.Remove(this, chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED, - content::NotificationService::AllSources()); } } @@ -901,49 +840,14 @@ } void LoginDisplayHostWebUI::ShowWebUI() { - if (!login_window_ || !login_view_) { - NOTREACHED(); - return; - } + DCHECK(login_window_); + DCHECK(login_view_); + VLOG(1) << "Login WebUI >> Show already initialized UI"; login_window_->Show(); login_view_->GetWebContents()->Focus(); login_view_->SetStatusAreaVisible(status_area_saved_visibility_); login_view_->OnPostponedShow(); - - // We should reset this flag to allow changing of status area visibility. - initialize_webui_hidden_ = false; -} - -void LoginDisplayHostWebUI::StartPostponedWebUI() { - if (!is_wallpaper_loaded_) { - NOTREACHED(); - return; - } - VLOG(1) << "Login WebUI >> Init postponed WebUI"; - - // Wallpaper has finished loading before StartWizard/StartSignInScreen has - // been called. In general this should not happen. - // Let go through normal code path when one of those will be called. - if (restore_path_ == RESTORE_UNKNOWN) { - NOTREACHED(); - return; - } - - switch (restore_path_) { - case RESTORE_WIZARD: - StartWizard(first_screen_); - break; - case RESTORE_SIGN_IN: - StartSignInScreen(LoginScreenContext()); - break; - case RESTORE_ADD_USER_INTO_SESSION: - StartUserAdding(base::OnceClosure()); - break; - default: - NOTREACHED(); - break; - } } void LoginDisplayHostWebUI::InitLoginWindowAndView() { @@ -984,18 +888,11 @@ login_window_->AddObserver(this); login_window_->AddRemovalsObserver(this); login_window_->SetContentsView(login_view_); - - // If WebUI is initialized in hidden state, show it only if we're no - // longer waiting for wallpaper animation/user images loading. Otherwise, - // always show it. - if (!initialize_webui_hidden_ || !waiting_for_wallpaper_load_) { - VLOG(1) << "Login WebUI >> show login wnd on create"; - login_window_->Show(); - } else { - VLOG(1) << "Login WebUI >> login wnd is hidden on create"; - login_view_->set_is_hidden(true); - } login_window_->GetNativeView()->SetName("WebUILoginView"); + + // Delay showing the window until the login webui is ready. + VLOG(1) << "Login WebUI >> login window is hidden on create"; + login_view_->set_is_hidden(true); } void LoginDisplayHostWebUI::ResetLoginWindowAndView() {
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.h b/chrome/browser/chromeos/login/ui/login_display_host_webui.h index a1ac3310..c8a7cbd6 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_webui.h +++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.h
@@ -42,8 +42,13 @@ class LoginDisplayWebUI; class WebUILoginView; -// An implementation class for OOBE/login WebUI screen host. -// It encapsulates controllers, wallpaper integration and flow. +// An implementation class for OOBE and user adding screen host via WebUI. +// For OOBE, it provides wizard screens such as welcome, network, EULA, update, +// GAIA etc. For user adding, it is legacy support and provides the user +// selection screen (aka account picker). +// The WebUI (chrome://oobe) is loaded hidden on start and made visible when +// WebUI signals ready (via NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE) or there +// is a network error (via NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN). class LoginDisplayHostWebUI : public LoginDisplayHostCommon, public content::WebContentsObserver, public chromeos::SessionManagerClient::Observer, @@ -166,10 +171,6 @@ // Shows OOBE/sign in WebUI that was previously initialized in hidden state. void ShowWebUI(); - // Starts postponed WebUI (OOBE/sign in) if it was waiting for - // wallpaper animation end. - void StartPostponedWebUI(); - // Initializes |login_window_| and |login_view_| fields if needed. void InitLoginWindowAndView(); @@ -216,24 +217,10 @@ // True if the login display is the current screen. bool is_showing_login_ = false; - // True if NOTIFICATION_WALLPAPER_ANIMATION_FINISHED notification has been - // received. - bool is_wallpaper_loaded_ = false; - // Stores status area current visibility to be applied once login WebUI // is shown. bool status_area_saved_visibility_ = false; - // If true, WebUI is initialized in a hidden state and shown after the - // wallpaper animation is finished (when it is enabled) or the user pods have - // been loaded (otherwise). - // By default is true. Could be used to tune performance if needed. - bool initialize_webui_hidden_; - - // True if WebUI is initialized in hidden state and we're waiting for - // wallpaper load animation to finish. - bool waiting_for_wallpaper_load_; - // True if WebUI is initialized in hidden state, the OOBE is not completed // and we're waiting for OOBE configuration check to finish. bool waiting_for_configuration_ = false;
diff --git a/chrome/browser/download/offline_item_utils.cc b/chrome/browser/download/offline_item_utils.cc index 6200d1f..061d88d 100644 --- a/chrome/browser/download/offline_item_utils.cc +++ b/chrome/browser/download/offline_item_utils.cc
@@ -41,8 +41,18 @@ // The remaining time for a download item if it cannot be calculated. constexpr int64_t kUnknownRemainingTime = -1; +base::Optional<OfflineItemFilter> FilterForSpecialMimeTypes( + const std::string& mime_type) { + if (base::EqualsCaseInsensitiveASCII(mime_type, "application/ogg")) + return OfflineItemFilter::FILTER_AUDIO; + + return base::nullopt; +} + OfflineItemFilter MimeTypeToOfflineItemFilter(const std::string& mime_type) { - OfflineItemFilter filter = OfflineItemFilter::FILTER_OTHER; + auto filter = FilterForSpecialMimeTypes(mime_type); + if (filter.has_value()) + return filter.value(); if (base::StartsWith(mime_type, "audio/", base::CompareCase::SENSITIVE)) { filter = OfflineItemFilter::FILTER_AUDIO; @@ -59,7 +69,7 @@ filter = OfflineItemFilter::FILTER_OTHER; } - return filter; + return filter.value(); } bool IsInterruptedDownloadAutoResumable(download::DownloadItem* item) {
diff --git a/chrome/browser/extensions/chrome_extensions_interface_registration.cc b/chrome/browser/extensions/chrome_extensions_interface_registration.cc index 666e402a..1483684 100644 --- a/chrome/browser/extensions/chrome_extensions_interface_registration.cc +++ b/chrome/browser/extensions/chrome_extensions_interface_registration.cc
@@ -22,6 +22,7 @@ #include "services/service_manager/public/cpp/binder_registry.h" #if defined(OS_CHROMEOS) +#include "base/task/post_task.h" #include "chromeos/services/ime/public/mojom/constants.mojom.h" #include "chromeos/services/ime/public/mojom/input_engine.mojom.h" #include "chromeos/services/media_perception/public/mojom/media_perception.mojom.h"
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 454968f..1655b8ed 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3126,11 +3126,6 @@ const char kEnableAssistantAppSupportDescription[] = "Enable the Assistant App Support feature"; -const char kEnableAssistantKeyRemappingName[] = - "Enable Assistant Key Remapping"; -const char kEnableAssistantKeyRemappingDescription[] = - "Allow Assistant key remapping in the keyboard settings."; - const char kEnableAssistantLauncherIntegrationName[] = "Assistant & Launcher integration"; const char kEnableAssistantLauncherIntegrationDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 2fcd89d4..a57e9791 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1870,9 +1870,6 @@ extern const char kEnableAssistantAppSupportName[]; extern const char kEnableAssistantAppSupportDescription[]; -extern const char kEnableAssistantKeyRemappingName[]; -extern const char kEnableAssistantKeyRemappingDescription[]; - extern const char kEnableAssistantLauncherIntegrationName[]; extern const char kEnableAssistantLauncherIntegrationDescription[];
diff --git a/chrome/browser/google/google_brand_code_map_chromeos.cc b/chrome/browser/google/google_brand_code_map_chromeos.cc index a2187fa..3630cf6 100644 --- a/chrome/browser/google/google_brand_code_map_chromeos.cc +++ b/chrome/browser/google/google_brand_code_map_chromeos.cc
@@ -45,6 +45,7 @@ {"BAQN", {"YJJJ", "LDCA", "QSJF"}}, {"BCOL", {"YJDV", "GSIC", "BAUL"}}, {"BDIW", {"UDUG", "TRYQ", "PWFV"}}, + {"CQPQ", {"GATZ", "QAVU", "WRXC"}}, {"CYQR", {"XGJJ", "DRMC", "RUQD"}}, {"CYSQ", {"NHHD", "TAVM", "FHSA"}}, {"DEAA", {"HXUG", "BJUN", "IYTV"}}, @@ -107,6 +108,7 @@ {"VEUT", {"JDFA", "ALIR", "DDJM"}}, {"VHUH", {"JYDF", "SFJY", "JMBU"}}, {"WBZQ", {"LAYK", "LQDM", "QBFV"}}, + {"WJOZ", {"BASQ", "BRTL", "CQAV"}}, {"XVTK", {"TMUU", "BTWW", "THQH"}}, {"XVYQ", {"UAVB", "OEMI", "VQVK"}}, {"XWJE", {"KDZI", "IYPJ", "ERIM"}},
diff --git a/chrome/browser/media/router/discovery/BUILD.gn b/chrome/browser/media/router/discovery/BUILD.gn index ef7a335..2e3ece36 100644 --- a/chrome/browser/media/router/discovery/BUILD.gn +++ b/chrome/browser/media/router/discovery/BUILD.gn
@@ -1,7 +1,8 @@ # 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. -# + +assert(!is_android) static_library("discovery") { inputs = [ @@ -46,6 +47,16 @@ "dial/safe_dial_app_info_parser.h", "dial/safe_dial_device_description_parser.cc", "dial/safe_dial_device_description_parser.h", + "discovery_network_info.cc", + "discovery_network_info.h", + "discovery_network_list.h", + "discovery_network_list_wifi.h", + "discovery_network_monitor.cc", + "discovery_network_monitor.h", + "discovery_network_monitor_metric_observer.cc", + "discovery_network_monitor_metric_observer.h", + "discovery_network_monitor_metrics.cc", + "discovery_network_monitor_metrics.h", "mdns/cast_media_sink_service.cc", "mdns/cast_media_sink_service.h", "mdns/cast_media_sink_service_impl.cc", @@ -62,28 +73,20 @@ "media_sink_discovery_metrics.h", ] - if (!is_android) { - sources += [ - "discovery_network_info.cc", - "discovery_network_info.h", - "discovery_network_list.h", - "discovery_network_list_wifi.h", - "discovery_network_list_wifi_linux.cc", - "discovery_network_list_wifi_mac.mm", - "discovery_network_list_win.cc", - "discovery_network_monitor.cc", - "discovery_network_monitor.h", - "discovery_network_monitor_metric_observer.cc", - "discovery_network_monitor_metric_observer.h", - "discovery_network_monitor_metrics.cc", - "discovery_network_monitor_metrics.h", - ] - if (is_posix) { - sources += [ "discovery_network_list_posix.cc" ] - } + if (is_linux) { + sources += [ "discovery_network_list_wifi_linux.cc" ] + } + + if (is_posix) { + sources += [ "discovery_network_list_posix.cc" ] } if (is_mac) { + sources += [ "discovery_network_list_wifi_mac.mm" ] libs = [ "CoreWLAN.framework" ] } + + if (is_win) { + sources += [ "discovery_network_list_win.cc" ] + } }
diff --git a/chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.cc b/chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.cc index 717d5bd6..08ab3d3f 100644 --- a/chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.cc +++ b/chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.h" +#include "chrome/browser/media/router/discovery/mdns/dns_sd_delegate.h" + using local_discovery::ServiceDescription; namespace media_router {
diff --git a/chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.h b/chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.h index 43d814a3..a4cbefd 100644 --- a/chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.h +++ b/chrome/browser/media/router/discovery/mdns/dns_sd_device_lister.h
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "chrome/browser/local_discovery/service_discovery_device_lister.h" -#include "chrome/browser/media/router/discovery/mdns/dns_sd_delegate.h" namespace local_discovery { class ServiceDiscoveryClient; @@ -18,6 +17,8 @@ namespace media_router { +class DnsSdDelegate; + // Manages a watcher for a specific MDNS/DNS-SD service type and notifies // a delegate of changes to watched services. class DnsSdDeviceLister @@ -35,6 +36,7 @@ void Reset(); protected: + // local_discovery::ServiceDiscoveryDeviceLister::Delegate: void OnDeviceChanged( const std::string& service_type, bool added, @@ -52,7 +54,7 @@ // The client and service type used to create |device_lister_|. local_discovery::ServiceDiscoveryClient* const service_discovery_client_; - std::string service_type_; + const std::string service_type_; DISALLOW_COPY_AND_ASSIGN(DnsSdDeviceLister); };
diff --git a/chrome/browser/media/router/providers/cast/cast_media_route_provider.h b/chrome/browser/media/router/providers/cast/cast_media_route_provider.h index 502c5b5..14d594c 100644 --- a/chrome/browser/media/router/providers/cast/cast_media_route_provider.h +++ b/chrome/browser/media/router/providers/cast/cast_media_route_provider.h
@@ -5,6 +5,10 @@ #ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_MEDIA_ROUTE_PROVIDER_H_ #define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_MEDIA_ROUTE_PROVIDER_H_ +#include <memory> +#include <string> +#include <vector> + #include "base/containers/flat_map.h" #include "base/macros.h" #include "chrome/browser/media/router/providers/cast/cast_app_discovery_service.h" @@ -16,6 +20,10 @@ class CastMessageHandler; } +namespace service_manager { +class Connector; +} + namespace url { class Origin; } @@ -24,6 +32,7 @@ class CastActivityManager; class CastSessionTracker; +class DataDecoder; // MediaRouteProvider for Cast sinks. This class may be created on any sequence. // All other methods, however, must be called on the task runner provided
diff --git a/chrome/browser/media/router/providers/cast/dual_media_sink_service.h b/chrome/browser/media/router/providers/cast/dual_media_sink_service.h index b5ea6ca..8ac672c 100644 --- a/chrome/browser/media/router/providers/cast/dual_media_sink_service.h +++ b/chrome/browser/media/router/providers/cast/dual_media_sink_service.h
@@ -15,8 +15,6 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/sequence_checker.h" -#include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h" -#include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h" #include "chrome/browser/media/router/media_sinks_observer.h" #include "chrome/common/media_router/discovery/media_sink_internal.h" #include "chrome/common/media_router/media_source.h" @@ -28,6 +26,7 @@ class CastMediaSinkService; class DialMediaSinkService; class DialMediaSinkServiceImpl; +class MediaSinkServiceBase; // This class uses DialMediaSinkService and CastMediaSinkService to discover // sinks used by the Cast MediaRouteProvider. It also encapsulates the setup
diff --git a/chrome/browser/metrics/power_metrics_provider_mac.mm b/chrome/browser/metrics/power_metrics_provider_mac.mm index 63a77c4..40c7d2b 100644 --- a/chrome/browser/metrics/power_metrics_provider_mac.mm +++ b/chrome/browser/metrics/power_metrics_provider_mac.mm
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/power_monitor/power_monitor.h" #include "base/process/process.h" #include "base/sequenced_task_runner.h" #include "base/task/post_task.h" @@ -239,6 +240,7 @@ RecordSMC("DuringStartup"); } else { RecordSMC("All"); + RecordIsOnBattery(); if (@available(macOS 10.10.3, *)) { RecordThermal(); } @@ -264,6 +266,13 @@ } } + void RecordIsOnBattery() { + bool is_on_battery = false; + if (base::PowerMonitor::IsInitialized()) + is_on_battery = base::PowerMonitor::IsOnBatteryPower(); + UMA_HISTOGRAM_BOOLEAN("Power.Mac.IsOnBattery", is_on_battery); + } + void RecordThermal() API_AVAILABLE(macos(10.10.3)) { UMA_HISTOGRAM_ENUMERATION( "Power.Mac.ThermalState",
diff --git a/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc b/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc index bf5e83c0..d1d5f9d 100644 --- a/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc +++ b/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc
@@ -38,8 +38,8 @@ #include "components/offline_items_collection/core/offline_content_provider.h" #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/client_namespace_constants.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/downloads/download_ui_adapter.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_item_utils.h" #include "components/offline_pages/core/offline_page_model.h" @@ -111,7 +111,7 @@ bool DownloadUIAdapterDelegate::IsVisibleInUI(const ClientId& client_id) { const std::string& name_space = client_id.name_space; - return model_->GetPolicyController()->IsSupportedByDownload(name_space) && + return GetPolicy(name_space).is_supported_by_download && base::IsValidGUID(client_id.id); }
diff --git a/chrome/browser/offline_pages/android/downloads/offline_page_share_helper.cc b/chrome/browser/offline_pages/android/downloads/offline_page_share_helper.cc index 60a5882..561d6815 100644 --- a/chrome/browser/offline_pages/android/downloads/offline_page_share_helper.cc +++ b/chrome/browser/offline_pages/android/downloads/offline_page_share_helper.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/android/download/download_controller_base.h" #include "chrome/browser/android/download/download_utils.h" #include "chrome/browser/offline_pages/offline_page_mhtml_archiver.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/page_criteria.h" @@ -66,9 +67,8 @@ return; } const OfflinePageItem& page = pages[0]; - bool is_suggested = - model_->GetPolicyController()->IsSuggested(page.client_id.name_space); - bool in_private_dir = model_->IsArchiveInInternalDir(page.file_path); + const bool is_suggested = GetPolicy(page.client_id.name_space).is_suggested; + const bool in_private_dir = model_->IsArchiveInInternalDir(page.file_path); // Need to publish internal page to public directory to share the file with // content URI instead of the web page URL.
diff --git a/chrome/browser/offline_pages/android/offline_page_bridge.cc b/chrome/browser/offline_pages/android/offline_page_bridge.cc index 2ee0400..f5782564 100644 --- a/chrome/browser/offline_pages/android/offline_page_bridge.cc +++ b/chrome/browser/offline_pages/android/offline_page_bridge.cc
@@ -36,7 +36,6 @@ #include "components/offline_pages/core/archive_validator.h" #include "components/offline_pages/core/background/request_queue_results.h" #include "components/offline_pages/core/background/save_page_request.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_item.h" @@ -712,7 +711,7 @@ const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jstring>& j_name_space) { std::string name_space(ConvertJavaStringToUTF8(env, j_name_space)); - return (offline_page_model_->GetPolicyController()->IsTemporary(name_space)); + return GetPolicy(name_space).lifetime_type == LifetimeType::TEMPORARY; } ScopedJavaLocalRef<jobject> OfflinePageBridge::GetOfflinePage(
diff --git a/chrome/browser/offline_pages/background_loader_offliner.cc b/chrome/browser/offline_pages/background_loader_offliner.cc index b8844d08..d63fc8e 100644 --- a/chrome/browser/offline_pages/background_loader_offliner.cc +++ b/chrome/browser/offline_pages/background_loader_offliner.cc
@@ -28,6 +28,7 @@ #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/client_namespace_constants.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/renovations/page_renovation_loader.h" @@ -147,10 +148,8 @@ return false; } - ClientPolicyController* policy_controller = - offline_page_model_->GetPolicyController(); - if (policy_controller->RequiresSpecificUserSettings( - request.client_id().name_space) && + if (GetPolicy(request.client_id().name_space) + .requires_specific_user_settings && (AreThirdPartyCookiesBlocked(browser_context_) || IsNetworkPredictionDisabled(browser_context_))) { DVLOG(1) << "WARNING: Unable to load when 3rd party cookies blocked or " @@ -261,9 +260,8 @@ // If we want to proceed with the file download, fail with // DOWNLOAD_THROTTLED. If we don't want to proceed with the file download, // fail with LOADING_FAILED_DOWNLOAD. - if (offline_page_model_->GetPolicyController() - ->AllowsConversionToBackgroundFileDownload( - pending_request_.get()->client_id().name_space)) { + if (GetPolicy(pending_request_.get()->client_id().name_space) + .allows_conversion_to_background_file_download) { should_allow_downloads = true; final_status = Offliner::RequestStatus::DOWNLOAD_THROTTLED; }
diff --git a/chrome/browser/offline_pages/fresh_offline_content_observer.cc b/chrome/browser/offline_pages/fresh_offline_content_observer.cc index 39feb93..41e2b2c 100644 --- a/chrome/browser/offline_pages/fresh_offline_content_observer.cc +++ b/chrome/browser/offline_pages/fresh_offline_content_observer.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/offline_pages/fresh_offline_content_observer.h" #include "chrome/browser/offline_pages/prefetch/prefetched_pages_notifier.h" -#include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_item.h" @@ -36,8 +36,7 @@ void FreshOfflineContentObserver::OfflinePageAdded( OfflinePageModel* model, const OfflinePageItem& added_page) { - if (model->GetPolicyController()->IsSupportedByDownload( - added_page.client_id.name_space)) { + if (GetPolicy(added_page.client_id.name_space).is_supported_by_download) { OnFreshOfflineContentAvailableForNotification(); } }
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.cc b/chrome/browser/offline_pages/offline_page_tab_helper.cc index 9cd8e2a7..4bd40d8 100644 --- a/chrome/browser/offline_pages/offline_page_tab_helper.cc +++ b/chrome/browser/offline_pages/offline_page_tab_helper.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/profiles/profile.h" #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/model/offline_page_model_utils.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_item_utils.h" #include "components/offline_pages/core/offline_page_model.h" @@ -266,7 +267,7 @@ if (offline_page()) { // Report prefetch usage. - if (policy_controller_.IsSuggested(offline_page()->client_id.name_space)) + if (GetPolicy(offline_page()->client_id.name_space).is_suggested) metrics_collector->OnPrefetchedPageOpened(); // Note that navigation to offline page may happen even if network is // connected. For the purposes of collecting offline usage statistics,
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.h b/chrome/browser/offline_pages/offline_page_tab_helper.h index 2d40cd3..7f703d6 100644 --- a/chrome/browser/offline_pages/offline_page_tab_helper.h +++ b/chrome/browser/offline_pages/offline_page_tab_helper.h
@@ -211,11 +211,6 @@ // Service, outlives this object. PrefetchService* prefetch_service_ = nullptr; - // Table of OfflinePages policies. - // TODO(dimich): When we only have one shared version of PolicyController, - // replace this instance with access to a shared one. - ClientPolicyController policy_controller_; - // TODO(crbug.com/827215): We only really want interface messages for the main // frame but this is not easily done with the current helper classes. content::WebContentsFrameBindingSet<mojom::MhtmlPageNotifier>
diff --git a/chrome/browser/offline_pages/offline_page_utils.cc b/chrome/browser/offline_pages/offline_page_utils.cc index b8d02b5..c12fe77 100644 --- a/chrome/browser/offline_pages/offline_page_utils.cc +++ b/chrome/browser/offline_pages/offline_page_utils.cc
@@ -28,8 +28,8 @@ #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/client_namespace_constants.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_clock.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_item_utils.h" @@ -60,13 +60,7 @@ bool IsSupportedByDownload(content::BrowserContext* browser_context, const std::string& name_space) { - OfflinePageModel* offline_page_model = - OfflinePageModelFactory::GetForBrowserContext(browser_context); - DCHECK(offline_page_model); - ClientPolicyController* policy_controller = - offline_page_model->GetPolicyController(); - DCHECK(policy_controller); - return policy_controller->IsSupportedByDownload(name_space); + return GetPolicy(name_space).is_supported_by_download; } void CheckDuplicateOngoingDownloads(
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc index 750a80c..20ad898 100644 --- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
@@ -1128,6 +1128,10 @@ EXPECT_EQ(1u, entries.size()); test_ukm_recorder().ExpectEntryMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_TotalName, 1500); + test_ukm_recorder().ExpectEntryMetric( + entries.front(), + ukm::builders::AdFrameLoad::kCpuTime_PeakWindowedPercentName, + 100 * 1500 / 30000); EXPECT_FALSE(test_ukm_recorder().EntryHasMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_PreActivationName)); EXPECT_FALSE(test_ukm_recorder().EntryHasMetric( @@ -1182,6 +1186,10 @@ EXPECT_EQ(1u, entries.size()); test_ukm_recorder().ExpectEntryMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_TotalName, 1500); + test_ukm_recorder().ExpectEntryMetric( + entries.front(), + ukm::builders::AdFrameLoad::kCpuTime_PeakWindowedPercentName, + 100 * 1500 / 30000); EXPECT_FALSE(test_ukm_recorder().EntryHasMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_PreActivationName)); EXPECT_FALSE(test_ukm_recorder().EntryHasMetric( @@ -1240,6 +1248,10 @@ test_ukm_recorder().ExpectEntryMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_TotalName, 1500); test_ukm_recorder().ExpectEntryMetric( + entries.front(), + ukm::builders::AdFrameLoad::kCpuTime_PeakWindowedPercentName, + 100 * 1000 / 30000); + test_ukm_recorder().ExpectEntryMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_PreActivationName, 1000); test_ukm_recorder().ExpectEntryMetric( @@ -1293,6 +1305,9 @@ EXPECT_EQ(1u, entries.size()); test_ukm_recorder().ExpectEntryMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_TotalName, 0); + test_ukm_recorder().ExpectEntryMetric( + entries.front(), + ukm::builders::AdFrameLoad::kCpuTime_PeakWindowedPercentName, 0); EXPECT_FALSE(test_ukm_recorder().EntryHasMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_PreActivationName)); EXPECT_FALSE(test_ukm_recorder().EntryHasMetric( @@ -1330,6 +1345,10 @@ EXPECT_EQ(1u, entries.size()); test_ukm_recorder().ExpectEntryMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_TotalName, 500); + test_ukm_recorder().ExpectEntryMetric( + entries.front(), + ukm::builders::AdFrameLoad::kCpuTime_PeakWindowedPercentName, + 100 * 500 / 30000); } TEST_F(AdsPageLoadMetricsObserverTest, TestCpuTimingMetricsShortTimeframes) { @@ -1373,6 +1392,10 @@ EXPECT_EQ(1u, entries.size()); test_ukm_recorder().ExpectEntryMetric( entries.front(), ukm::builders::AdFrameLoad::kCpuTime_TotalName, 1500); + test_ukm_recorder().ExpectEntryMetric( + entries.front(), + ukm::builders::AdFrameLoad::kCpuTime_PeakWindowedPercentName, + 100 * 1500 / 30000); } TEST_F(AdsPageLoadMetricsObserverTest, AdFrameLoadTiming) {
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc index 8ef3b3d..8a62600 100644 --- a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc +++ b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc
@@ -248,6 +248,8 @@ pre_activation_foreground_duration().InMilliseconds()); } + builder.SetCpuTime_PeakWindowedPercent(peak_windowed_cpu_percent_); + builder .SetVisibility_FrameWidth( ukm::GetExponentialBucketMinForCounts1000(frame_size().width()))
diff --git a/chrome/browser/predictors/loading_predictor_unittest.cc b/chrome/browser/predictors/loading_predictor_unittest.cc index c168cd5..75cfada 100644 --- a/chrome/browser/predictors/loading_predictor_unittest.cc +++ b/chrome/browser/predictors/loading_predictor_unittest.cc
@@ -49,8 +49,10 @@ MOCK_METHOD1(StartPreresolveHost, void(const GURL& url)); MOCK_METHOD1(StartPreresolveHosts, void(const std::vector<std::string>& hostnames)); - MOCK_METHOD2(StartPreconnectUrl, - void(const GURL& url, bool allow_credentials)); + MOCK_METHOD3(StartPreconnectUrl, + void(const GURL& url, + bool allow_credentials, + net::NetworkIsolationKey network_isolation_key)); MOCK_METHOD1(Stop, void(const GURL& url)); void Start(const GURL& url, @@ -303,7 +305,8 @@ TEST_F(LoadingPredictorPreconnectTest, TestHandleOmniboxHint) { const GURL preconnect_suggestion = GURL("http://search.com/kittens"); EXPECT_CALL(*mock_preconnect_manager_, - StartPreconnectUrl(preconnect_suggestion, true)); + StartPreconnectUrl(preconnect_suggestion, true, + net::NetworkIsolationKey())); predictor_->PrepareForPageLoad(preconnect_suggestion, HintOrigin::OMNIBOX, true); // The second suggestion for the same host should be filtered out.
diff --git a/chrome/browser/predictors/loading_test_util.cc b/chrome/browser/predictors/loading_test_util.cc index 8cb9ace..ab0ec9af 100644 --- a/chrome/browser/predictors/loading_test_util.cc +++ b/chrome/browser/predictors/loading_test_util.cc
@@ -31,11 +31,12 @@ MockResourcePrefetchPredictor::~MockResourcePrefetchPredictor() = default; void InitializeRedirectStat(RedirectStat* redirect, - const std::string& url, + const GURL& url, int number_of_hits, int number_of_misses, int consecutive_misses) { - redirect->set_url(url); + redirect->set_url(url.host()); + redirect->set_url_scheme(url.scheme()); redirect->set_number_of_hits(number_of_hits); redirect->set_number_of_misses(number_of_misses); redirect->set_consecutive_misses(consecutive_misses); @@ -168,9 +169,9 @@ } std::ostream& operator<<(std::ostream& os, const RedirectStat& redirect) { - return os << "[" << redirect.url() << "," << redirect.number_of_hits() << "," - << redirect.number_of_misses() << "," - << redirect.consecutive_misses() << "]"; + return os << "[" << redirect.url() << "," << redirect.url_scheme() << "," + << redirect.number_of_hits() << "," << redirect.number_of_misses() + << "," << redirect.consecutive_misses() << "]"; } std::ostream& operator<<(std::ostream& os, const OriginData& data) { @@ -237,7 +238,7 @@ } bool operator==(const RedirectStat& lhs, const RedirectStat& rhs) { - return lhs.url() == rhs.url() && + return lhs.url() == rhs.url() && lhs.url_scheme() == rhs.url_scheme() && lhs.number_of_hits() == rhs.number_of_hits() && lhs.number_of_misses() == rhs.number_of_misses() && lhs.consecutive_misses() == rhs.consecutive_misses();
diff --git a/chrome/browser/predictors/loading_test_util.h b/chrome/browser/predictors/loading_test_util.h index fdfe434..8923b83 100644 --- a/chrome/browser/predictors/loading_test_util.h +++ b/chrome/browser/predictors/loading_test_util.h
@@ -36,7 +36,7 @@ }; void InitializeRedirectStat(RedirectStat* redirect, - const std::string& url, + const GURL& url, int number_of_hits, int number_of_misses, int consecutive_misses);
diff --git a/chrome/browser/predictors/preconnect_manager.cc b/chrome/browser/predictors/preconnect_manager.cc index b095937..cdee4d11 100644 --- a/chrome/browser/predictors/preconnect_manager.cc +++ b/chrome/browser/predictors/preconnect_manager.cc
@@ -46,10 +46,23 @@ PreresolveJob::PreresolveJob(const GURL& url, int num_sockets, bool allow_credentials, + net::NetworkIsolationKey network_isolation_key, PreresolveInfo* info) : url(url), num_sockets(num_sockets), allow_credentials(allow_credentials), + network_isolation_key(std::move(network_isolation_key)), + info(info) { + DCHECK_GE(num_sockets, 0); +} + +PreresolveJob::PreresolveJob(PreconnectRequest preconnect_request, + PreresolveInfo* info) + : url(std::move(preconnect_request.origin)), + num_sockets(preconnect_request.num_sockets), + allow_credentials(preconnect_request.allow_credentials), + network_isolation_key( + std::move(preconnect_request.network_isolation_key)), info(info) { DCHECK_GE(num_sockets, 0); } @@ -79,11 +92,11 @@ host, std::make_unique<PreresolveInfo>(url, requests.size())); PreresolveInfo* info = iterator_and_whether_inserted.first->second.get(); - for (const auto& request : requests) { - DCHECK(request.origin.GetOrigin() == request.origin); + for (auto request_it = requests.begin(); request_it != requests.end(); + ++request_it) { + DCHECK(request_it->origin.GetOrigin() == request_it->origin); PreresolveJobId job_id = preresolve_jobs_.Add( - std::make_unique<PreresolveJob>(request.origin, request.num_sockets, - request.allow_credentials, info)); + std::make_unique<PreresolveJob>(std::move(*request_it), info)); queued_jobs_.push_back(job_id); } @@ -95,7 +108,8 @@ if (!url.SchemeIsHTTPOrHTTPS()) return; PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>( - url.GetOrigin(), 0, kAllowCredentialsOnPreconnectByDefault, nullptr)); + url.GetOrigin(), 0, kAllowCredentialsOnPreconnectByDefault, + net::NetworkIsolationKey(), nullptr)); queued_jobs_.push_front(job_id); TryToLaunchPreresolveJobs(); @@ -109,20 +123,23 @@ PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>( GURL("http://" + *it), 0, kAllowCredentialsOnPreconnectByDefault, - nullptr)); + net::NetworkIsolationKey(), nullptr)); queued_jobs_.push_front(job_id); } TryToLaunchPreresolveJobs(); } -void PreconnectManager::StartPreconnectUrl(const GURL& url, - bool allow_credentials) { +void PreconnectManager::StartPreconnectUrl( + const GURL& url, + bool allow_credentials, + net::NetworkIsolationKey network_isolation_key) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!url.SchemeIsHTTPOrHTTPS()) return; PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>( - url.GetOrigin(), 1, allow_credentials, nullptr)); + url.GetOrigin(), 1, allow_credentials, std::move(network_isolation_key), + nullptr)); queued_jobs_.push_front(job_id); TryToLaunchPreresolveJobs(); @@ -138,9 +155,11 @@ it->second->was_canceled = true; } -void PreconnectManager::PreconnectUrl(const GURL& url, - int num_sockets, - bool allow_credentials) const { +void PreconnectManager::PreconnectUrl( + const GURL& url, + int num_sockets, + bool allow_credentials, + const net::NetworkIsolationKey& network_isolation_key) const { DCHECK(url.GetOrigin() == url); DCHECK(url.SchemeIsHTTPOrHTTPS()); if (observer_) @@ -159,9 +178,8 @@ net::LOAD_DO_NOT_SEND_AUTH_DATA; } - // TODO(mmenke): Use an appropriate NetworkIsolationKey(). network_context->PreconnectSockets(num_sockets, url, load_flags, privacy_mode, - net::NetworkIsolationKey()); + network_isolation_key); } std::unique_ptr<ResolveHostClientImpl> PreconnectManager::PreresolveUrl( @@ -275,8 +293,10 @@ DCHECK(job); bool need_preconnect = success && job->need_preconnect(); - if (need_preconnect) - PreconnectUrl(job->url, job->num_sockets, job->allow_credentials); + if (need_preconnect) { + PreconnectUrl(job->url, job->num_sockets, job->allow_credentials, + job->network_isolation_key); + } PreresolveInfo* info = job->info; if (info)
diff --git a/chrome/browser/predictors/preconnect_manager.h b/chrome/browser/predictors/preconnect_manager.h index e5962a0c..51a842d 100644 --- a/chrome/browser/predictors/preconnect_manager.h +++ b/chrome/browser/predictors/preconnect_manager.h
@@ -17,6 +17,7 @@ #include "chrome/browser/predictors/proxy_lookup_client_impl.h" #include "chrome/browser/predictors/resolve_host_client_impl.h" #include "chrome/browser/predictors/resource_prefetch_predictor.h" +#include "net/base/network_isolation_key.h" #include "url/gurl.h" class Profile; @@ -75,7 +76,9 @@ PreresolveJob(const GURL& url, int num_sockets, bool allow_credentials, + net::NetworkIsolationKey network_isolation_key, PreresolveInfo* info); + PreresolveJob(PreconnectRequest preconnect_request, PreresolveInfo* info); PreresolveJob(PreresolveJob&& other); ~PreresolveJob(); bool need_preconnect() const { @@ -85,8 +88,9 @@ GURL url; int num_sockets; bool allow_credentials; + net::NetworkIsolationKey network_isolation_key; // Raw pointer usage is fine here because even though PreresolveJob can - // outlive PreresolveInfo it's only accessed on PreconnectManager class + // outlive PreresolveInfo. It's only accessed on PreconnectManager class // context and PreresolveInfo lifetime is tied to PreconnectManager. // May be equal to nullptr in case of detached job. PreresolveInfo* info; @@ -145,7 +149,19 @@ // than trackable requests thus they are put in the front of the jobs queue. virtual void StartPreresolveHost(const GURL& url); virtual void StartPreresolveHosts(const std::vector<std::string>& hostnames); - virtual void StartPreconnectUrl(const GURL& url, bool allow_credentials); + // |network_isolation_key| specifies the key that network requests for the + // preconnected URL are expected to use. If a request is issued with a + // different key, it may not use the preconnected socket. + // + // TODO(https://crbug.com/966896): Update consumers and make + // |network_isolation_key| a mandatory argument. Note that this is a temporary + // style guide violation, but keeping this until all consumers correctly fill + // the argument reduces the chances of forgetting to update one. + virtual void StartPreconnectUrl( + const GURL& url, + bool allow_credentials, + net::NetworkIsolationKey network_isolation_key = + net::NetworkIsolationKey()); // No additional jobs keyed by the |url| will be queued after this. virtual void Stop(const GURL& url); @@ -166,9 +182,11 @@ using PreresolveJobId = PreresolveJobMap::KeyType; friend class PreconnectManagerTest; - void PreconnectUrl(const GURL& url, - int num_sockets, - bool allow_credentials) const; + void PreconnectUrl( + const GURL& url, + int num_sockets, + bool allow_credentials, + const net::NetworkIsolationKey& network_isolation_key) const; std::unique_ptr<ResolveHostClientImpl> PreresolveUrl( const GURL& url, ResolveHostCallback callback) const;
diff --git a/chrome/browser/predictors/preconnect_manager_unittest.cc b/chrome/browser/predictors/preconnect_manager_unittest.cc index 4bda676..c9161f8 100644 --- a/chrome/browser/predictors/preconnect_manager_unittest.cc +++ b/chrome/browser/predictors/preconnect_manager_unittest.cc
@@ -219,6 +219,27 @@ mock_network_context_->CompleteHostLookup(url_to_preconnect.host(), net::OK); } +TEST_F(PreconnectManagerTest, + TestStartOneUrlPreconnectWithNetworkIsolationKey) { + GURL main_frame_url("http://google.com"); + GURL url_to_preconnect("http://cdn.google.com"); + url::Origin requesting_origin = url::Origin::Create(GURL("http://foo.test")); + net::NetworkIsolationKey network_isolation_key(requesting_origin, + requesting_origin); + + EXPECT_CALL(*mock_network_context_, + ResolveHostProxy(url_to_preconnect.host())); + preconnect_manager_->Start( + main_frame_url, + {PreconnectRequest(url_to_preconnect, 1, network_isolation_key)}); + EXPECT_CALL(*mock_network_context_, + PreconnectSockets(1, url_to_preconnect, kNormalLoadFlags, + false /* privacy_mode_enabled */, + network_isolation_key)); + EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url)); + mock_network_context_->CompleteHostLookup(url_to_preconnect.host(), net::OK); +} + // Sends preconnect request for a webpage, and stops the request before // all pertaining preconnect requests finish. Next, preconnect request // for the same webpage is sent again. Verifies that all the preconnects @@ -599,7 +620,8 @@ bool allow_credentials = false; EXPECT_CALL(*mock_network_context_, ResolveHostProxy(origin.host())); - preconnect_manager_->StartPreconnectUrl(url, allow_credentials); + preconnect_manager_->StartPreconnectUrl(url, allow_credentials, + net::NetworkIsolationKey()); EXPECT_CALL( *mock_network_context_, @@ -609,7 +631,26 @@ // Non http url shouldn't be preconnected. GURL non_http_url("file:///tmp/index.html"); - preconnect_manager_->StartPreconnectUrl(non_http_url, allow_credentials); + preconnect_manager_->StartPreconnectUrl(non_http_url, allow_credentials, + net::NetworkIsolationKey()); +} + +TEST_F(PreconnectManagerTest, TestStartPreconnectUrlWithNetworkIsolationKey) { + GURL url("http://cdn.google.com/script.js"); + GURL origin("http://cdn.google.com"); + bool allow_credentials = false; + url::Origin requesting_origin = url::Origin::Create(GURL("http://foo.test")); + net::NetworkIsolationKey network_isolation_key(requesting_origin, + requesting_origin); + + EXPECT_CALL(*mock_network_context_, ResolveHostProxy(origin.host())); + preconnect_manager_->StartPreconnectUrl(url, allow_credentials, + network_isolation_key); + + EXPECT_CALL(*mock_network_context_, + PreconnectSockets(1, origin, kPrivateLoadFlags, + !allow_credentials, network_isolation_key)); + mock_network_context_->CompleteHostLookup(origin.host(), net::OK); } TEST_F(PreconnectManagerTest, TestDetachedRequestHasHigherPriority) {
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc index 808be8f1..ef3b4e7 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -59,8 +59,13 @@ } // namespace -PreconnectRequest::PreconnectRequest(const GURL& origin, int num_sockets) - : origin(origin), num_sockets(num_sockets) { +PreconnectRequest::PreconnectRequest( + const GURL& origin, + int num_sockets, + net::NetworkIsolationKey network_isolation_key) + : origin(origin), + num_sockets(num_sockets), + network_isolation_key(std::move(network_isolation_key)) { DCHECK_GE(num_sockets, 0); } @@ -188,9 +193,10 @@ return; } - const std::string& host = summary->main_frame_url.host(); - LearnRedirect(summary->initial_url.host(), host, host_redirect_data_.get()); - LearnOrigins(host, summary->main_frame_url.GetOrigin(), summary->origins); + LearnRedirect(summary->initial_url.host(), summary->main_frame_url, + host_redirect_data_.get()); + LearnOrigins(summary->main_frame_url.host(), + summary->main_frame_url.GetOrigin(), summary->origins); if (observer_) observer_->OnNavigationLearned(*summary); @@ -287,7 +293,7 @@ } void ResourcePrefetchPredictor::LearnRedirect(const std::string& key, - const std::string& final_redirect, + const GURL& final_redirect, RedirectDataMap* redirect_data) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // If the primary key is too long reject it. @@ -300,18 +306,36 @@ data.set_primary_key(key); data.set_last_visit_time(base::Time::Now().ToInternalValue()); RedirectStat* redirect_to_add = data.add_redirect_endpoints(); - redirect_to_add->set_url(final_redirect); + redirect_to_add->set_url(final_redirect.host()); redirect_to_add->set_number_of_hits(1); + redirect_to_add->set_url_scheme(final_redirect.scheme()); } else { data.set_last_visit_time(base::Time::Now().ToInternalValue()); bool need_to_add = true; for (RedirectStat& redirect : *(data.mutable_redirect_endpoints())) { - if (redirect.url() == final_redirect) { + const bool host_mismatch = redirect.url() != final_redirect.host(); + + // When the existing scheme in database is empty, then difference in + // schemes is not considered a scheme mismatch. This case is treated + // specially since scheme was added later to the database, and previous + // entries would have empty scheme. In such case, we do not consider this + // as a mismatch, and simply update the scheme in the database. + const bool url_scheme_mismatch = + !redirect.url_scheme().empty() && + redirect.url_scheme() != final_redirect.scheme(); + + if (!host_mismatch && !url_scheme_mismatch) { + // No mismatch. need_to_add = false; redirect.set_number_of_hits(redirect.number_of_hits() + 1); redirect.set_consecutive_misses(0); + + // If existing scheme in database is empty, then update it. + if (redirect.url_scheme().empty()) + redirect.set_url_scheme(final_redirect.scheme()); } else { + // A real mismatch. redirect.set_number_of_misses(redirect.number_of_misses() + 1); redirect.set_consecutive_misses(redirect.consecutive_misses() + 1); } @@ -319,8 +343,9 @@ if (need_to_add) { RedirectStat* redirect_to_add = data.add_redirect_endpoints(); - redirect_to_add->set_url(final_redirect); + redirect_to_add->set_url(final_redirect.host()); redirect_to_add->set_number_of_hits(1); + redirect_to_add->set_url_scheme(final_redirect.scheme()); } }
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.h b/chrome/browser/predictors/resource_prefetch_predictor.h index 0fb21eb..c43d5ed 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.h +++ b/chrome/browser/predictors/resource_prefetch_predictor.h
@@ -16,6 +16,7 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/scoped_observer.h" #include "base/task/cancelable_task_tracker.h" #include "base/time/time.h" @@ -28,6 +29,7 @@ #include "components/history/core/browser/history_types.h" #include "components/keyed_service/core/keyed_service.h" #include "content/public/common/resource_type.h" +#include "net/base/network_isolation_key.h" #include "url/gurl.h" class PredictorsHandler; @@ -54,12 +56,23 @@ // Stores all values needed to trigger a preconnect/preresolve job to a single // origin. struct PreconnectRequest { - PreconnectRequest(const GURL& origin, int num_sockets); + // |network_isolation_key| specifies the key that network requests for the + // preconnected URL are expected to use. If a request is issued with a + // different key, it may not use the preconnected socket. It has no effect + // when |num_sockets| == 0. + // + // TODO(https://crbug.com/966896): Update consumers and make + // |network_isolation_key| a mandatory argument. + PreconnectRequest(const GURL& origin, + int num_sockets, + net::NetworkIsolationKey network_isolation_key = + net::NetworkIsolationKey()); GURL origin; // A zero-value means that we need to preresolve a host only. int num_sockets = 0; bool allow_credentials = true; + net::NetworkIsolationKey network_isolation_key; }; // Stores a result of preconnect prediction. The |requests| vector is the main @@ -224,7 +237,7 @@ // Updates information about final redirect destination for the |key| in // |redirect_data| and correspondingly updates the predictor database. void LearnRedirect(const std::string& key, - const std::string& final_redirect, + const GURL& final_redirect, RedirectDataMap* redirect_data); void LearnOrigins(const std::string& host,
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.proto b/chrome/browser/predictors/resource_prefetch_predictor.proto index 1ceed7d..2181648 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.proto +++ b/chrome/browser/predictors/resource_prefetch_predictor.proto
@@ -14,12 +14,19 @@ option optimize_for = LITE_RUNTIME; // Represents a single redirect chain endpoint. +// When adding a field here, please also update the equality operator and the +// output operator in +// chrome/browser/predictors/loading_test_util.cc. message RedirectStat { // Represents the host for RedirectData in a host-based table. optional string url = 1; optional uint32 number_of_hits = 2; optional uint32 number_of_misses = 3; optional uint32 consecutive_misses = 4; + // |url_scheme| is typically either "http" or "https". This field was added + // in M-77 without wiping the database. As such, it may be empty in some + // cases even when originally |url| had a non-empty scheme. + optional string url_scheme = 5; } // Represents a mapping from URL or host to a list of redirect endpoints.
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc index cafa2003..f84761fb 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc
@@ -69,9 +69,11 @@ void TestOriginStatsAreEqual(const std::vector<OriginStat>& lhs, const std::vector<OriginStat>& rhs) const; - void AddKey(RedirectDataMap* m, const std::string& key) const; + void AddKey(RedirectDataMap* m, const GURL& url) const; void AddKey(OriginDataMap* m, const std::string& key) const; + std::string GetKeyForRedirectStat(const RedirectStat& stat) const; + RedirectDataMap test_host_redirect_data_; OriginDataMap test_origin_data_; }; @@ -140,7 +142,7 @@ RedirectDataMap expected_host_redirect_data; OriginDataMap expected_origin_data; - AddKey(&expected_host_redirect_data, "bbc.com"); + AddKey(&expected_host_redirect_data, GURL("http://bbc.com")); AddKey(&expected_origin_data, "abc.xyz"); TestRedirectDataAreEqual(expected_host_redirect_data, @@ -150,10 +152,10 @@ void ResourcePrefetchPredictorTablesTest::TestUpdateData() { RedirectData microsoft = CreateRedirectData("microsoft.com", 21); - InitializeRedirectStat(microsoft.add_redirect_endpoints(), "m.microsoft.com", - 5, 7, 1); - InitializeRedirectStat(microsoft.add_redirect_endpoints(), "microsoft.org", 7, - 2, 0); + InitializeRedirectStat(microsoft.add_redirect_endpoints(), + GURL("https://m.microsoft.com"), 5, 7, 1); + InitializeRedirectStat(microsoft.add_redirect_endpoints(), + GURL("https://microsoft.org"), 7, 2, 0); tables_->ExecuteDBTaskOnDBSequence( base::BindOnce(&LoadingPredictorKeyValueTable<RedirectData>::UpdateData, @@ -174,7 +176,7 @@ RedirectDataMap expected_host_redirect_data; OriginDataMap expected_origin_data; - AddKey(&expected_host_redirect_data, "bbc.com"); + AddKey(&expected_host_redirect_data, GURL("https://bbc.com")); expected_host_redirect_data.insert( std::make_pair("microsoft.com", microsoft)); @@ -225,16 +227,19 @@ std::map<std::string, RedirectStat> lhs_index; // Repeated redirects are not allowed. - for (const auto& r : lhs) - EXPECT_TRUE(lhs_index.insert(std::make_pair(r.url(), r)).second); + for (const auto& r : lhs) { + EXPECT_TRUE( + lhs_index.insert(std::make_pair(GetKeyForRedirectStat(r), r)).second) + << " r.url()=" << r.url(); + } for (const auto& r : rhs) { - auto lhs_it = lhs_index.find(r.url()); + auto lhs_it = lhs_index.find(GetKeyForRedirectStat(r)); if (lhs_it != lhs_index.end()) { EXPECT_EQ(r, lhs_it->second); lhs_index.erase(lhs_it); } else { - ADD_FAILURE() << r.url(); + ADD_FAILURE() << r.url() << " " << r.url_scheme(); } } @@ -282,8 +287,8 @@ } void ResourcePrefetchPredictorTablesTest::AddKey(RedirectDataMap* m, - const std::string& key) const { - auto it = test_host_redirect_data_.find(key); + const GURL& url) const { + auto it = test_host_redirect_data_.find(url.host()); EXPECT_TRUE(it != test_host_redirect_data_.end()); m->insert(*it); } @@ -295,6 +300,11 @@ m->insert(*it); } +std::string ResourcePrefetchPredictorTablesTest::GetKeyForRedirectStat( + const RedirectStat& stat) const { + return stat.url() + "," + stat.url_scheme(); +} + void ResourcePrefetchPredictorTablesTest::DeleteAllData() { tables_->ExecuteDBTaskOnDBSequence(base::BindOnce( &LoadingPredictorKeyValueTable<RedirectData>::DeleteAllData, @@ -318,14 +328,22 @@ void ResourcePrefetchPredictorTablesTest::InitializeSampleData() { { // Host redirect data. RedirectData bbc = CreateRedirectData("bbc.com", 9); - InitializeRedirectStat(bbc.add_redirect_endpoints(), "www.bbc.com", 8, 4, - 1); - InitializeRedirectStat(bbc.add_redirect_endpoints(), "m.bbc.com", 5, 8, 0); - InitializeRedirectStat(bbc.add_redirect_endpoints(), "bbc.co.uk", 1, 3, 0); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("https://www.bbc.com"), 8, 4, 1); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("https://m.bbc.com"), 5, 8, 0); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("https://bbc.co.uk"), 1, 3, 0); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("http://www.bbc.com"), 8, 4, 1); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("http://m.bbc.com"), 5, 8, 0); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("http://bbc.co.uk"), 1, 3, 0); RedirectData microsoft = CreateRedirectData("microsoft.com", 10); InitializeRedirectStat(microsoft.add_redirect_endpoints(), - "www.microsoft.com", 10, 0, 0); + GURL("https://www.microsoft.com"), 10, 0, 0); test_host_redirect_data_.clear(); test_host_redirect_data_.insert(std::make_pair(bbc.primary_key(), bbc));
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc index 9b318b3..a6e00f2 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
@@ -187,14 +187,18 @@ void ResourcePrefetchPredictorTest::InitializeSampleData() { { // Host redirect data. RedirectData bbc = CreateRedirectData("bbc.com", 9); - InitializeRedirectStat(bbc.add_redirect_endpoints(), "www.bbc.com", 8, 4, - 1); - InitializeRedirectStat(bbc.add_redirect_endpoints(), "m.bbc.com", 5, 8, 0); - InitializeRedirectStat(bbc.add_redirect_endpoints(), "bbc.co.uk", 1, 3, 0); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("https://www.bbc.com"), 8, 4, 1); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("https://m.bbc.com"), 5, 8, 0); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("http://bbc.co.uk"), 1, 3, 0); + InitializeRedirectStat(bbc.add_redirect_endpoints(), + GURL("https://bbc.co.uk"), 1, 3, 0); RedirectData microsoft = CreateRedirectData("microsoft.com", 10); InitializeRedirectStat(microsoft.add_redirect_endpoints(), - "www.microsoft.com", 10, 0, 0); + GURL("https://www.microsoft.com"), 10, 0, 0); test_host_redirect_data_.clear(); test_host_redirect_data_.insert(std::make_pair(bbc.primary_key(), bbc)); @@ -295,7 +299,7 @@ RedirectData host_redirect_data = CreateRedirectData("www.google.com"); InitializeRedirectStat(host_redirect_data.add_redirect_endpoints(), - "www.google.com", 1, 0, 0); + GURL("http://www.google.com"), 1, 0, 0); EXPECT_EQ(mock_tables_->host_redirect_table_.data_, RedirectDataMap( {{host_redirect_data.primary_key(), host_redirect_data}})); @@ -339,7 +343,7 @@ RedirectData host_redirect_data = CreateRedirectData("www.google.com"); InitializeRedirectStat(host_redirect_data.add_redirect_endpoints(), - "www.google.com", 1, 0, 0); + GURL("http://www.google.com"), 1, 0, 0); EXPECT_EQ(mock_tables_->host_redirect_table_.data_, RedirectDataMap( {{host_redirect_data.primary_key(), host_redirect_data}})); @@ -381,7 +385,7 @@ RedirectData host_redirect_data = CreateRedirectData("www.nike.com"); InitializeRedirectStat(host_redirect_data.add_redirect_endpoints(), - "www.nike.com", 1, 0, 0); + GURL("http://www.nike.com"), 1, 0, 0); EXPECT_EQ(mock_tables_->host_redirect_table_.data_, RedirectDataMap( {{host_redirect_data.primary_key(), host_redirect_data}})); @@ -451,7 +455,7 @@ RedirectData host_redirect_data = CreateRedirectData("fb.com"); InitializeRedirectStat(host_redirect_data.add_redirect_endpoints(), - "facebook.com", 1, 0, 0); + GURL("https://facebook.com"), 1, 0, 0); EXPECT_EQ(mock_tables_->host_redirect_table_.data_, RedirectDataMap( {{host_redirect_data.primary_key(), host_redirect_data}})); @@ -480,7 +484,7 @@ RedirectData host_redirect_data = CreateRedirectData("fb.com"); InitializeRedirectStat(host_redirect_data.add_redirect_endpoints(), - "facebook.com", 1, 0, 0); + GURL("https://facebook.com"), 1, 0, 0); RedirectDataMap expected_host_redirect_data = test_host_redirect_data_; expected_host_redirect_data.erase("bbc.com"); expected_host_redirect_data[host_redirect_data.primary_key()] = @@ -489,6 +493,85 @@ expected_host_redirect_data); } +// Tests that redirect is recorded correctly for URL already present in +// the database cache. Test with both https and http schemes for the same +// host. +TEST_F(ResourcePrefetchPredictorTest, RedirectUrlInDB_MultipleSchemes) { + mock_tables_->host_redirect_table_.data_ = test_host_redirect_data_; + + ResetPredictor(); + InitializePredictor(); + + { + std::vector<content::mojom::ResourceLoadInfoPtr> resources_https; + resources_https.push_back(CreateResourceLoadInfoWithRedirects( + {"https://fb.com/google", "https://facebook.com/google"})); + auto page_summary_https = + CreatePageRequestSummary("https://facebook.com/google", + "https://fb.com/google", resources_https); + + StrictMock<MockResourcePrefetchPredictorObserver> mock_observer(predictor_); + EXPECT_CALL(mock_observer, OnNavigationLearned(page_summary_https)); + + predictor_->RecordPageRequestSummary( + std::make_unique<PageRequestSummary>(page_summary_https)); + profile_->BlockUntilHistoryProcessesPendingRequests(); + + RedirectData host_redirect_data_https = CreateRedirectData("fb.com"); + InitializeRedirectStat(host_redirect_data_https.add_redirect_endpoints(), + GURL("https://facebook.com"), 1, 0, 0); + RedirectDataMap expected_host_redirect_data_https = + test_host_redirect_data_; + expected_host_redirect_data_https.erase("bbc.com"); + expected_host_redirect_data_https[host_redirect_data_https.primary_key()] = + host_redirect_data_https; + EXPECT_EQ(mock_tables_->host_redirect_table_.data_, + expected_host_redirect_data_https); + EXPECT_EQ(1, mock_tables_->host_redirect_table_ + .data_[host_redirect_data_https.primary_key()] + .redirect_endpoints() + .size()); + EXPECT_EQ("https", mock_tables_->host_redirect_table_ + .data_[host_redirect_data_https.primary_key()] + .redirect_endpoints(0) + .url_scheme()); + } + { + std::vector<content::mojom::ResourceLoadInfoPtr> resources_http; + resources_http.push_back(CreateResourceLoadInfoWithRedirects( + {"http://fb.com/google", "http://facebook.com/google"})); + auto page_summary_http = CreatePageRequestSummary( + "http://facebook.com/google", "http://fb.com/google", resources_http); + + StrictMock<MockResourcePrefetchPredictorObserver> mock_observer(predictor_); + EXPECT_CALL(mock_observer, OnNavigationLearned(page_summary_http)); + + predictor_->RecordPageRequestSummary( + std::make_unique<PageRequestSummary>(page_summary_http)); + profile_->BlockUntilHistoryProcessesPendingRequests(); + + RedirectData host_redirect_data_http = CreateRedirectData("fb.com"); + InitializeRedirectStat(host_redirect_data_http.add_redirect_endpoints(), + GURL("http://facebook.com"), 1, 0, 0); + RedirectDataMap expected_host_redirect_data_http = test_host_redirect_data_; + expected_host_redirect_data_http.erase("bbc.com"); + expected_host_redirect_data_http[host_redirect_data_http.primary_key()] = + host_redirect_data_http; + EXPECT_EQ(2, mock_tables_->host_redirect_table_ + .data_[host_redirect_data_http.primary_key()] + .redirect_endpoints() + .size()); + EXPECT_EQ("facebook.com", mock_tables_->host_redirect_table_ + .data_[host_redirect_data_http.primary_key()] + .redirect_endpoints(1) + .url()); + EXPECT_EQ("http", mock_tables_->host_redirect_table_ + .data_[host_redirect_data_http.primary_key()] + .redirect_endpoints(1) + .url_scheme()); + } +} + TEST_F(ResourcePrefetchPredictorTest, DeleteUrls) { ResetPredictor(false); InitializePredictor(); @@ -555,8 +638,8 @@ // The data to be requested for the confident endpoint. RedirectData nyt = CreateRedirectData("nyt.com", 1); - InitializeRedirectStat(nyt.add_redirect_endpoints(), "mobile.nytimes.com", 10, - 0, 0); + InitializeRedirectStat(nyt.add_redirect_endpoints(), + GURL("https://mobile.nytimes.com"), 10, 0, 0); redirect_data.UpdateData(nyt.primary_key(), nyt); EXPECT_TRUE(predictor_->GetRedirectEndpoint("nyt.com", redirect_data, &redirect_endpoint)); @@ -564,20 +647,20 @@ // The data to check negative result due not enough confidence. RedirectData facebook = CreateRedirectData("fb.com", 3); - InitializeRedirectStat(facebook.add_redirect_endpoints(), "facebook.com", 5, - 5, 0); + InitializeRedirectStat(facebook.add_redirect_endpoints(), + GURL("https://facebook.com"), 5, 5, 0); redirect_data.UpdateData(facebook.primary_key(), facebook); EXPECT_FALSE(predictor_->GetRedirectEndpoint("fb.com", redirect_data, &redirect_endpoint)); // The data to check negative result due ambiguity. RedirectData google = CreateRedirectData("google.com", 4); - InitializeRedirectStat(google.add_redirect_endpoints(), "google.com", 10, 0, - 0); - InitializeRedirectStat(google.add_redirect_endpoints(), "google.fr", 10, 1, - 0); - InitializeRedirectStat(google.add_redirect_endpoints(), "google.ws", 20, 20, - 0); + InitializeRedirectStat(google.add_redirect_endpoints(), + GURL("https://google.com"), 10, 0, 0); + InitializeRedirectStat(google.add_redirect_endpoints(), + GURL("https://google.fr"), 10, 1, 0); + InitializeRedirectStat(google.add_redirect_endpoints(), + GURL("https://google.ws"), 20, 20, 0); redirect_data.UpdateData(google.primary_key(), google); EXPECT_FALSE(predictor_->GetRedirectEndpoint("google.com", redirect_data, &redirect_endpoint)); @@ -617,8 +700,8 @@ // Add a redirect. RedirectData redirect = CreateRedirectData("google.com", 3); - InitializeRedirectStat(redirect.add_redirect_endpoints(), "www.google.com", - 10, 0, 0); + InitializeRedirectStat(redirect.add_redirect_endpoints(), + GURL("https://www.google.com"), 10, 0, 0); predictor_->host_redirect_data_->UpdateData(redirect.primary_key(), redirect); // Prediction failed: no data associated with the redirect endpoint.
diff --git a/chrome/browser/previews/previews_prober.cc b/chrome/browser/previews/previews_prober.cc index 93af097b..8662587 100644 --- a/chrome/browser/previews/previews_prober.cc +++ b/chrome/browser/previews/previews_prober.cc
@@ -26,7 +26,6 @@ #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/http/http_status_code.h" -#include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" @@ -221,6 +220,7 @@ const net::HttpRequestHeaders headers, const RetryPolicy& retry_policy, const TimeoutPolicy& timeout_policy, + const net::NetworkTrafficAnnotationTag& traffic_annotation, const size_t max_cache_entries, base::TimeDelta revalidate_cache_after) : PreviewsProber(delegate, @@ -232,6 +232,7 @@ headers, retry_policy, timeout_policy, + traffic_annotation, max_cache_entries, revalidate_cache_after, base::DefaultTickClock::GetInstance(), @@ -247,6 +248,7 @@ const net::HttpRequestHeaders headers, const RetryPolicy& retry_policy, const TimeoutPolicy& timeout_policy, + const net::NetworkTrafficAnnotationTag& traffic_annotation, const size_t max_cache_entries, base::TimeDelta revalidate_cache_after, const base::TickClock* tick_clock, @@ -261,6 +263,7 @@ timeout_policy_(timeout_policy), max_cache_entries_(max_cache_entries), revalidate_cache_after_(revalidate_cache_after), + traffic_annotation_(traffic_annotation), successive_retry_count_(0), successive_timeout_count_(0), cached_probe_results_(std::make_unique<base::DictionaryValue>()), @@ -385,28 +388,6 @@ url = url.ReplaceComponents(replacements); } - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("previews_prober", R"( - semantics { - sender: "Previews Prober" - description: - "Requests a small resource to test network connectivity to a given " - "resource or domain which will either be a Google owned domain or" - "the website that the user is navigating to." - trigger: - "Requested when Lite mode and Previews are enabled on startup and " - "on every network change." - data: "None." - destination: WEBSITE - } - policy { - cookies_allowed: NO - setting: - "Users can control Lite mode on Android via the settings menu. " - "Lite mode is not available on iOS, and on desktop only for " - "developer testing." - policy_exception_justification: "Not implemented." - })"); auto request = std::make_unique<network::ResourceRequest>(); request->url = url; request->method = HttpMethodToString(http_method_); @@ -415,7 +396,7 @@ request->allow_credentials = false; url_loader_ = - network::SimpleURLLoader::Create(std::move(request), traffic_annotation); + network::SimpleURLLoader::Create(std::move(request), traffic_annotation_); url_loader_->SetAllowHttpErrorResults(true); url_loader_->DownloadToString(
diff --git a/chrome/browser/previews/previews_prober.h b/chrome/browser/previews/previews_prober.h index 543b995..c118278 100644 --- a/chrome/browser/previews/previews_prober.h +++ b/chrome/browser/previews/previews_prober.h
@@ -23,6 +23,7 @@ #include "build/build_config.h" #include "net/base/net_errors.h" #include "net/http/http_request_headers.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/cpp/resource_response.h" #include "url/gurl.h" @@ -140,6 +141,7 @@ const net::HttpRequestHeaders headers, const RetryPolicy& retry_policy, const TimeoutPolicy& timeout_policy, + const net::NetworkTrafficAnnotationTag& traffic_annotation, const size_t max_cache_entries, base::TimeDelta revalidate_cache_after); ~PreviewsProber() override; @@ -180,6 +182,7 @@ const net::HttpRequestHeaders headers, const RetryPolicy& retry_policy, const TimeoutPolicy& timeout_policy, + const net::NetworkTrafficAnnotationTag& traffic_annotation, const size_t max_cache_entries, base::TimeDelta revalidate_cache_after, const base::TickClock* tick_clock, @@ -234,6 +237,9 @@ // background. const base::TimeDelta revalidate_cache_after_; + // The traffic annotation to use for creating |url_loader_|. + const net::NetworkTrafficAnnotationTag traffic_annotation_; + // The number of retries that have been attempted. This count does not include // the original probe. size_t successive_retry_count_;
diff --git a/chrome/browser/previews/previews_prober_browsertest.cc b/chrome/browser/previews/previews_prober_browsertest.cc index 0db82db..acbe139a 100644 --- a/chrome/browser/previews/previews_prober_browsertest.cc +++ b/chrome/browser/previews/previews_prober_browsertest.cc
@@ -19,6 +19,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/public/mojom/network_service_test.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -133,7 +134,8 @@ browser()->profile()->GetPrefs(), PreviewsProber::ClientName::kLitepages, url, PreviewsProber::HttpMethod::kGet, headers, retry_policy, - timeout_policy, 1, base::TimeDelta::FromDays(1)); + timeout_policy, TRAFFIC_ANNOTATION_FOR_TESTS, 1, + base::TimeDelta::FromDays(1)); prober.SendNowIfInactive(false); WaitForCompletedProbe(&prober); @@ -155,7 +157,8 @@ browser()->profile()->GetPrefs(), PreviewsProber::ClientName::kLitepages, url, PreviewsProber::HttpMethod::kGet, headers, retry_policy, - timeout_policy, 1, base::TimeDelta::FromDays(1)); + timeout_policy, TRAFFIC_ANNOTATION_FOR_TESTS, 1, + base::TimeDelta::FromDays(1)); prober.SendNowIfInactive(false); WaitForCompletedProbe(&prober); @@ -180,7 +183,8 @@ browser()->profile()->GetPrefs(), PreviewsProber::ClientName::kLitepages, url, PreviewsProber::HttpMethod::kGet, headers, retry_policy, - timeout_policy, 1, base::TimeDelta::FromDays(1)); + timeout_policy, TRAFFIC_ANNOTATION_FOR_TESTS, 1, + base::TimeDelta::FromDays(1)); SimulateNetworkChange(network::mojom::ConnectionType::CONNECTION_4G); WaitForCompletedProbe(&prober);
diff --git a/chrome/browser/previews/previews_prober_unittest.cc b/chrome/browser/previews/previews_prober_unittest.cc index 4c6dcb4c..3b0653e 100644 --- a/chrome/browser/previews/previews_prober_unittest.cc +++ b/chrome/browser/previews/previews_prober_unittest.cc
@@ -16,6 +16,7 @@ #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/http/http_status_code.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/resource_response.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" @@ -63,6 +64,7 @@ const net::HttpRequestHeaders headers, const RetryPolicy& retry_policy, const TimeoutPolicy& timeout_policy, + const net::NetworkTrafficAnnotationTag& traffic_annotation, const size_t max_cache_entries, base::TimeDelta revalidate_cache_after, const base::TickClock* tick_clock, @@ -76,6 +78,7 @@ headers, retry_policy, timeout_policy, + traffic_annotation, max_cache_entries, revalidate_cache_after, tick_clock, @@ -125,8 +128,9 @@ delegate, test_shared_loader_factory_, &test_prefs_, PreviewsProber::ClientName::kLitepages, kTestUrl, PreviewsProber::HttpMethod::kGet, headers, retry_policy, - timeout_policy, 1, kCacheRevalidateAfter, - thread_bundle_.GetMockTickClock(), thread_bundle_.GetMockClock()); + timeout_policy, TRAFFIC_ANNOTATION_FOR_TESTS, 1, + kCacheRevalidateAfter, thread_bundle_.GetMockTickClock(), + thread_bundle_.GetMockClock()); prober->SetOnCompleteCallback(base::BindRepeating( &PreviewsProberTest::OnProbeComplete, base::Unretained(this))); return prober;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 99539e2b..55083525c 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1256,19 +1256,18 @@ menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); if (send_tab_to_self::GetValidDeviceCount(GetBrowser()->profile()) == 1) { #if defined(OS_MACOSX) - menu_model_.AddItem( - IDC_CONTENT_LINK_SEND_TAB_TO_SELF_SINGLE_TARGET, - l10n_util::GetStringFUTF16( - IDS_LINK_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, - base::UTF8ToUTF16(send_tab_to_self::GetSingleTargetDeviceName( - GetBrowser()->profile())))); + menu_model_.AddItem(IDC_CONTENT_LINK_SEND_TAB_TO_SELF_SINGLE_TARGET, + l10n_util::GetStringFUTF16( + IDS_LINK_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, + send_tab_to_self::GetSingleTargetDeviceName( + GetBrowser()->profile()))); #else menu_model_.AddItemWithIcon( IDC_CONTENT_LINK_SEND_TAB_TO_SELF_SINGLE_TARGET, l10n_util::GetStringFUTF16( IDS_LINK_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, - base::UTF8ToUTF16(send_tab_to_self::GetSingleTargetDeviceName( - GetBrowser()->profile()))), + send_tab_to_self::GetSingleTargetDeviceName( + GetBrowser()->profile())), *send_tab_to_self::GetImageSkia()); #endif send_tab_to_self::RecordSendTabToSelfClickResult( @@ -1491,19 +1490,18 @@ menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); if (send_tab_to_self::GetValidDeviceCount(GetBrowser()->profile()) == 1) { #if defined(OS_MACOSX) - menu_model_.AddItem( - IDC_SEND_TAB_TO_SELF_SINGLE_TARGET, - l10n_util::GetStringFUTF16( - IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, - base::UTF8ToUTF16(send_tab_to_self::GetSingleTargetDeviceName( - GetBrowser()->profile())))); + menu_model_.AddItem(IDC_SEND_TAB_TO_SELF_SINGLE_TARGET, + l10n_util::GetStringFUTF16( + IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, + send_tab_to_self::GetSingleTargetDeviceName( + GetBrowser()->profile()))); #else menu_model_.AddItemWithIcon( IDC_SEND_TAB_TO_SELF_SINGLE_TARGET, l10n_util::GetStringFUTF16( IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, - base::UTF8ToUTF16(send_tab_to_self::GetSingleTargetDeviceName( - GetBrowser()->profile()))), + send_tab_to_self::GetSingleTargetDeviceName( + GetBrowser()->profile())), *send_tab_to_self::GetImageSkia()); #endif send_tab_to_self::RecordSendTabToSelfClickResult(
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h index 49728eb..7e993b49 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.h +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -71,8 +71,6 @@ bool is_checked); // Range of command IDs to use for the items in the send tab to self submenu. - static const int kMinSendTabToSelfSubMenuCommandId = - send_tab_to_self::SendTabToSelfSubMenuModel::kMinCommandId; static const int kMaxSendTabToSelfSubMenuCommandId = send_tab_to_self::SendTabToSelfSubMenuModel::kMaxCommandId;
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc index 15cdd8e..ee593372 100644 --- a/chrome/browser/renderer_host/chrome_render_message_filter.cc +++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -32,6 +32,7 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/render_process_host.h" #include "extensions/buildflags/buildflags.h" +#include "net/base/network_isolation_key.h" #include "ppapi/buildflags/buildflags.h" #if BUILDFLAG(ENABLE_EXTENSIONS) @@ -130,12 +131,17 @@ return; } - if (preconnect_manager_initialized_) { - base::PostTaskWithTraits( - FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&predictors::PreconnectManager::StartPreconnectUrl, - preconnect_manager_, url, allow_credentials)); - } + if (!preconnect_manager_initialized_) + return; + + // TODO(mmenke): Use process and frame ids to populate NetworkIsolationKey. + // May also need to think about enabling cross-site preconnects, though that + // will result in at least some cross-site information leakage. + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&predictors::PreconnectManager::StartPreconnectUrl, + preconnect_manager_, url, allow_credentials, + net::NetworkIsolationKey())); } void ChromeRenderMessageFilter::OnAllowDatabase(
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/prefs.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/prefs.js index 73c7b66e..b6e14ac9 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/prefs.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/prefs.js
@@ -168,6 +168,15 @@ localStorage[pref] = cvox.ChromeVoxPrefs.DEFAULT_PREFS[pref]; } } + // Since language switching is currently an experimental feature, ensure that + // it is off if the feature flag is absent. + chrome.commandLinePrivate.hasSwitch( + 'enable-experimental-accessibility-chromevox-language-switching', + function(enabled) { + if (!enabled) { + localStorage['languageSwitching'] = false; + } + }); }; /**
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index 7ab4d242..24a75930 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -148,22 +148,6 @@ * @const */ const LOG_TYPE = { - // A static Doodle was shown, coming from cache. - NTP_STATIC_LOGO_SHOWN_FROM_CACHE: 30, - // A static Doodle was shown, coming from the network. - NTP_STATIC_LOGO_SHOWN_FRESH: 31, - // A call-to-action Doodle image was shown, coming from cache. - NTP_CTA_LOGO_SHOWN_FROM_CACHE: 32, - // A call-to-action Doodle image was shown, coming from the network. - NTP_CTA_LOGO_SHOWN_FRESH: 33, - - // A static Doodle was clicked. - NTP_STATIC_LOGO_CLICKED: 34, - // A call-to-action Doodle was clicked. - NTP_CTA_LOGO_CLICKED: 35, - // An animated Doodle was clicked. - NTP_ANIMATED_LOGO_CLICKED: 36, - // The One Google Bar was shown. NTP_ONE_GOOGLE_BAR_SHOWN: 37,
diff --git a/chrome/browser/resources/management/management_browser_proxy.js b/chrome/browser/resources/management/management_browser_proxy.js index 20c5400..0633bdc 100644 --- a/chrome/browser/resources/management/management_browser_proxy.js +++ b/chrome/browser/resources/management/management_browser_proxy.js
@@ -2,70 +2,69 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -cr.exportPath('management'); -/** - * @typedef {{ - * name: string, - * permissions: !Array<string> - * }} - */ -management.Extension; - -/** @enum {string} */ -management.ReportingType = { - SECURITY: 'security', - DEVICE: 'device', - USER: 'user', - USER_ACTIVITY: 'user-activity', - EXTENSIONS: 'extensions' -}; - -/** - * @typedef {{ - * messageId: string, - * reportingType: !management.ReportingType, - * }} - */ -management.BrowserReportingResponse; - -/** - * @typedef {{ - * browserManagementNotice: string, - * extensionReportingTitle: string, - * pageSubtitle: string, - * managed: boolean, - * overview: string, - * customerLogo: string, - * }} - */ -management.ManagedDataResponse; - -// <if expr="chromeos"> -/** - * @enum {string} Look at ToJSDeviceReportingType usage in - * management_ui_handler.cc for more details. - */ -management.DeviceReportingType = { - SUPERVISED_USER: 'supervised user', - DEVICE_ACTIVITY: 'device activity', - STATISTIC: 'device statistics', - DEVICE: 'device', - LOGS: 'logs', - PRINT: 'print', - CROSTINI: 'crostini' -}; - - -/** - * @typedef {{ - * messageId: string, - * reportingType: !management.DeviceReportingType, - * }} - */ -management.DeviceReportingResponse; -// </if> - cr.define('management', function() { + /** + * @typedef {{ + * name: string, + * permissions: !Array<string> + * }} + */ + let Extension; + + /** @enum {string} */ + const ReportingType = { + SECURITY: 'security', + DEVICE: 'device', + USER: 'user', + USER_ACTIVITY: 'user-activity', + EXTENSIONS: 'extensions' + }; + + /** + * @typedef {{ + * messageId: string, + * reportingType: !management.ReportingType, + * }} + */ + let BrowserReportingResponse; + + /** + * @typedef {{ + * browserManagementNotice: string, + * extensionReportingTitle: string, + * pageSubtitle: string, + * managed: boolean, + * overview: string, + * customerLogo: string, + * }} + */ + let ManagedDataResponse; + + // <if expr="chromeos"> + /** + * @enum {string} Look at ToJSDeviceReportingType usage in + * management_ui_handler.cc for more details. + */ + const DeviceReportingType = { + SUPERVISED_USER: 'supervised user', + DEVICE_ACTIVITY: 'device activity', + STATISTIC: 'device statistics', + DEVICE: 'device', + LOGS: 'logs', + PRINT: 'print', + CROSTINI: 'crostini' + }; + + + /** + * @typedef {{ + * messageId: string, + * reportingType: !management.DeviceReportingType, + * }} + */ + let DeviceReportingResponse; + // </if> + /** @interface */ class ManagementBrowserProxy { /** @return {!Promise<!Array<!management.Extension>>} */ @@ -128,7 +127,15 @@ cr.addSingletonGetter(ManagementBrowserProxyImpl); return { + BrowserReportingResponse: BrowserReportingResponse, + // <if expr="chromeos"> + DeviceReportingResponse: DeviceReportingResponse, + DeviceReportingType: DeviceReportingType, + // </if> + Extension: Extension, + ManagedDataResponse: ManagedDataResponse, + ManagementBrowserProxyImpl: ManagementBrowserProxyImpl, ManagementBrowserProxy: ManagementBrowserProxy, - ManagementBrowserProxyImpl: ManagementBrowserProxyImpl + ReportingType: ReportingType, }; });
diff --git a/chrome/browser/resources/management/management_ui.js b/chrome/browser/resources/management/management_ui.js index 3d5011b..a4984aa 100644 --- a/chrome/browser/resources/management/management_ui.js +++ b/chrome/browser/resources/management/management_ui.js
@@ -2,264 +2,270 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -cr.exportPath('management'); -/** - * @typedef {{ - * messageIds: !Array<string>, - * icon: string, - * }} - */ -management.BrowserReportingData; +cr.define('management', function() { + /** + * @typedef {{ + * messageIds: !Array<string>, + * icon: string, + * }} + */ + let BrowserReportingData; -Polymer({ - is: 'management-ui', + Polymer({ + is: 'management-ui', - behaviors: [ - I18nBehavior, - WebUIListenerBehavior, - ], + behaviors: [ + I18nBehavior, + WebUIListenerBehavior, + ], - properties: { - /** - * List of messages related to browser reporting. - * @private {?Array<!management.BrowserReportingData>} - */ - browserReportingInfo_: Array, + properties: { + /** + * List of messages related to browser reporting. + * @private {?Array<!management.BrowserReportingData>} + */ + browserReportingInfo_: Array, + + /** + * List of messages related to browser reporting. + * @private {?Array<!management.Extension>} + */ + extensions_: Array, + + // <if expr="chromeos"> + /** + * List of messages related to device reporting. + * @private {?Array<!management.DeviceReportingResponse>} + */ + deviceReportingInfo_: Array, + + /** + * Message stating if the Trust Roots are configured. + * @private + */ + localTrustRoots_: String, + + /** @private */ + customerLogo_: String, + + /** @private */ + managementOverview_: String, + + // </if> + + /** @private */ + subtitle_: String, + + // <if expr="not chromeos"> + /** @private */ + managementNoticeHtml_: String, + // </if> + + /** @private */ + managed_: Boolean, + + /** @private */ + extensionReportingSubtitle_: String, + }, + + /** @private {?management.ManagementBrowserProxy} */ + browserProxy_: null, + + /** @override */ + attached() { + document.documentElement.classList.remove('loading'); + this.browserProxy_ = management.ManagementBrowserProxyImpl.getInstance(); + this.updateManagedFields_(); + this.initBrowserReportingInfo_(); + + this.addWebUIListener( + 'browser-reporting-info-updated', + reportingInfo => this.onBrowserReportingInfoReceived_(reportingInfo)); + + this.addWebUIListener('managed_data_changed', () => { + this.updateManagedFields_(); + }); + + this.getExtensions_(); + // <if expr="chromeos"> + this.getDeviceReportingInfo_(); + this.getLocalTrustRootsInfo_(); + // </if> + }, + + /** @private */ + initBrowserReportingInfo_() { + this.browserProxy_.initBrowserReportingInfo().then( + reportingInfo => this.onBrowserReportingInfoReceived_(reportingInfo)); + }, /** - * List of messages related to browser reporting. - * @private {?Array<!management.Extension>} - */ - extensions_: Array, - - // <if expr="chromeos"> - /** - * List of messages related to device reporting. - * @private {?Array<!management.DeviceReportingResponse>} - */ - deviceReportingInfo_: Array, - - /** - * Message stating if the Trust Roots are configured. + * @param {!Array<!management.BrowserReportingResponse>} reportingInfo * @private */ - localTrustRoots_: String, + onBrowserReportingInfoReceived_(reportingInfo) { + const reportingInfoMap = reportingInfo.reduce((info, response) => { + info[response.reportingType] = info[response.reportingType] || { + icon: this.getIconForReportingType_(response.reportingType), + messageIds: [] + }; + info[response.reportingType].messageIds.push(response.messageId); + return info; + }, {}); - /** @private */ - customerLogo_: String, - - /** @private */ - managementOverview_: String, - - // </if> - - /** @private */ - subtitle_: String, - - // <if expr="not chromeos"> - /** @private */ - managementNoticeHtml_: String, - // </if> - - /** @private */ - managed_: Boolean, - - /** @private */ - extensionReportingSubtitle_: String, - }, - - /** @private {?management.ManagementBrowserProxy} */ - browserProxy_: null, - - /** @override */ - attached() { - document.documentElement.classList.remove('loading'); - this.browserProxy_ = management.ManagementBrowserProxyImpl.getInstance(); - this.updateManagedFields_(); - this.initBrowserReportingInfo_(); - - this.addWebUIListener( - 'browser-reporting-info-updated', - reportingInfo => this.onBrowserReportingInfoReceived_(reportingInfo)); - - this.addWebUIListener('managed_data_changed', () => { - this.updateManagedFields_(); - }); - - this.getExtensions_(); - // <if expr="chromeos"> - this.getDeviceReportingInfo_(); - this.getLocalTrustRootsInfo_(); - // </if> - }, - - /** @private */ - initBrowserReportingInfo_() { - this.browserProxy_.initBrowserReportingInfo().then( - reportingInfo => this.onBrowserReportingInfoReceived_(reportingInfo)); - }, - - /** - * @param {!Array<!management.BrowserReportingResponse>} reportingInfo - * @private - */ - onBrowserReportingInfoReceived_(reportingInfo) { - const reportingInfoMap = reportingInfo.reduce((info, response) => { - info[response.reportingType] = info[response.reportingType] || { - icon: this.getIconForReportingType_(response.reportingType), - messageIds: [] + const reportingTypeOrder = { + [management.ReportingType.SECURITY]: 1, + [management.ReportingType.EXTENSIONS]: 2, + [management.ReportingType.USER]: 3, + [management.ReportingType.USER_ACTIVITY]: 4, + [management.ReportingType.DEVICE]: 5, }; - info[response.reportingType].messageIds.push(response.messageId); - return info; - }, {}); - const reportingTypeOrder = { - [management.ReportingType.SECURITY]: 1, - [management.ReportingType.EXTENSIONS]: 2, - [management.ReportingType.USER]: 3, - [management.ReportingType.USER_ACTIVITY]: 4, - [management.ReportingType.DEVICE]: 5, - }; + this.browserReportingInfo_ = + Object.keys(reportingInfoMap) + .sort((a, b) => reportingTypeOrder[a] - reportingTypeOrder[b]) + .map(reportingType => reportingInfoMap[reportingType]); + }, - this.browserReportingInfo_ = - Object.keys(reportingInfoMap) - .sort((a, b) => reportingTypeOrder[a] - reportingTypeOrder[b]) - .map(reportingType => reportingInfoMap[reportingType]); - }, + /** @private */ + getExtensions_() { + this.browserProxy_.getExtensions().then(extensions => { + this.extensions_ = extensions; + }); + }, - /** @private */ - getExtensions_() { - this.browserProxy_.getExtensions().then(extensions => { - this.extensions_ = extensions; - }); - }, + // <if expr="chromeos"> + /** @private */ + getLocalTrustRootsInfo_() { + this.browserProxy_.getLocalTrustRootsInfo().then(trustRootsConfigured => { + this.localTrustRoots_ = trustRootsConfigured ? + loadTimeData.getString('managementTrustRootsConfigured') : + ''; + }); + }, - // <if expr="chromeos"> - /** @private */ - getLocalTrustRootsInfo_() { - this.browserProxy_.getLocalTrustRootsInfo().then(trustRootsConfigured => { - this.localTrustRoots_ = trustRootsConfigured ? - loadTimeData.getString('managementTrustRootsConfigured') : - ''; - }); - }, + /** @private */ + getDeviceReportingInfo_() { + this.browserProxy_.getDeviceReportingInfo().then(reportingInfo => { + this.deviceReportingInfo_ = reportingInfo; + }); + }, - /** @private */ - getDeviceReportingInfo_() { - this.browserProxy_.getDeviceReportingInfo().then(reportingInfo => { - this.deviceReportingInfo_ = reportingInfo; - }); - }, + /** + * @return {boolean} True of there are device reporting info to show. + * @private + */ + showDeviceReportingInfo_() { + return !!this.deviceReportingInfo_ && + this.deviceReportingInfo_.length > 0; + }, - /** - * @return {boolean} True of there are device reporting info to show. - * @private - */ - showDeviceReportingInfo_() { - return !!this.deviceReportingInfo_ && this.deviceReportingInfo_.length > 0; - }, + /** + * @param {management.DeviceReportingType} reportingType + * @return {string} The associated icon. + * @private + */ + getIconForDeviceReportingType_(reportingType) { + switch (reportingType) { + case management.DeviceReportingType.SUPERVISED_USER: + return 'management:supervised-user'; + case management.DeviceReportingType.DEVICE_ACTIVITY: + return 'management:timelapse'; + case management.DeviceReportingType.STATISTIC: + return 'management:bar-chart'; + case management.DeviceReportingType.DEVICE: + return 'cr:computer'; + case management.DeviceReportingType.LOGS: + return 'management:report'; + case management.DeviceReportingType.PRINT: + return 'cr:print'; + case management.DeviceReportingType.CROSTINI: + return 'management:linux'; + default: + return 'cr:computer'; + } + }, + // </if> - /** - * @param {management.DeviceReportingType} reportingType - * @return {string} The associated icon. - * @private - */ - getIconForDeviceReportingType_(reportingType) { - switch (reportingType) { - case management.DeviceReportingType.SUPERVISED_USER: - return 'management:supervised-user'; - case management.DeviceReportingType.DEVICE_ACTIVITY: - return 'management:timelapse'; - case management.DeviceReportingType.STATISTIC: - return 'management:bar-chart'; - case management.DeviceReportingType.DEVICE: - return 'cr:computer'; - case management.DeviceReportingType.LOGS: - return 'management:report'; - case management.DeviceReportingType.PRINT: - return 'cr:print'; - case management.DeviceReportingType.CROSTINI: - return 'management:linux'; - default: - return 'cr:computer'; - } - }, - // </if> + /** + * @return {boolean} True of there are browser reporting info to show. + * @private + */ + showBrowserReportingInfo_() { + return !!this.browserReportingInfo_ && + this.browserReportingInfo_.length > 0; + }, - /** - * @return {boolean} True of there are browser reporting info to show. - * @private - */ - showBrowserReportingInfo_() { - return !!this.browserReportingInfo_ && - this.browserReportingInfo_.length > 0; - }, + /** + * @return {boolean} True of there are extension reporting info to show. + * @private + */ + showExtensionReportingInfo_() { + return !!this.extensions_ && this.extensions_.length > 0; + }, - /** - * @return {boolean} True of there are extension reporting info to show. - * @private - */ - showExtensionReportingInfo_() { - return !!this.extensions_ && this.extensions_.length > 0; - }, + /** + * @param {management.ReportingType} reportingType + * @returns {string} The associated icon. + * @private + */ + getIconForReportingType_(reportingType) { + switch (reportingType) { + case management.ReportingType.SECURITY: + return 'cr:security'; + case management.ReportingType.DEVICE: + return 'cr:computer'; + case management.ReportingType.EXTENSIONS: + return 'cr:extension'; + case management.ReportingType.USER: + return 'management:account-circle'; + case management.ReportingType.USER_ACTIVITY: + return 'management:public'; + default: + return 'cr:security'; + } + }, - /** - * @param {management.ReportingType} reportingType - * @returns {string} The associated icon. - * @private - */ - getIconForReportingType_(reportingType) { - switch (reportingType) { - case management.ReportingType.SECURITY: - return 'cr:security'; - case management.ReportingType.DEVICE: - return 'cr:computer'; - case management.ReportingType.EXTENSIONS: - return 'cr:extension'; - case management.ReportingType.USER: - return 'management:account-circle'; - case management.ReportingType.USER_ACTIVITY: - return 'management:public'; - default: - return 'cr:security'; - } - }, + /** + * Handles the 'search-changed' event fired from the toolbar. + * Redirects to the settings page initialized the the current + * search query. + * @param {!CustomEvent<string>} e + * @private + */ + onSearchChanged_: function(e) { + const query = e.detail; + window.location.href = + `chrome://settings?search=${encodeURIComponent(query)}`; + }, - /** - * Handles the 'search-changed' event fired from the toolbar. - * Redirects to the settings page initialized the the current - * search query. - * @param {!CustomEvent<string>} e - * @private - */ - onSearchChanged_: function(e) { - const query = e.detail; - window.location.href = - `chrome://settings?search=${encodeURIComponent(query)}`; - }, + /** @private */ + onTapBack_() { + if (history.length > 1) { + history.back(); + } else { + window.location.href = 'chrome://settings/help'; + } + }, - /** @private */ - onTapBack_() { - if (history.length > 1) { - history.back(); - } else { - window.location.href = 'chrome://settings/help'; - } - }, + /** @private */ + updateManagedFields_() { + this.browserProxy_.getContextualManagedData().then(data => { + this.managed_ = data.managed; + this.extensionReportingSubtitle_ = data.extensionReportingTitle; + this.subtitle_ = data.pageSubtitle; + // <if expr="chromeos"> + this.customerLogo_ = data.customerLogo; + this.managementOverview_ = data.overview; + // </if> + // <if expr="not chromeos"> + this.managementNoticeHtml_ = data.browserManagementNotice; + // </if> + }); + }, + }); - /** @private */ - updateManagedFields_() { - this.browserProxy_.getContextualManagedData().then(data => { - this.managed_ = data.managed; - this.extensionReportingSubtitle_ = data.extensionReportingTitle; - this.subtitle_ = data.pageSubtitle; - // <if expr="chromeos"> - this.customerLogo_ = data.customerLogo; - this.managementOverview_ = data.overview; - // </if> - // <if expr="not chromeos"> - this.managementNoticeHtml_ = data.browserManagementNotice; - // </if> - }); - }, + return { + BrowserReportingData: BrowserReportingData, + }; });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html index 837247f..53688f8 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
@@ -88,7 +88,7 @@ <div class="illustration slide-in" aria-hidden="true"></div> <div class="button-bar"> <cr-button id="decline-button" on-click="onDeclineClick_"> - $i18n{setDefaultSkip} + $i18n{skip} </cr-button> <step-indicator model="[[indicatorModel]]"></step-indicator> <cr-button class="action-button" on-click="onSetDefaultClick_">
diff --git a/chrome/browser/resources/welcome/welcome.css b/chrome/browser/resources/welcome/welcome.css deleted file mode 100644 index 94d8481..0000000 --- a/chrome/browser/resources/welcome/welcome.css +++ /dev/null
@@ -1,46 +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. */ - -body { - align-items: center; - box-sizing: border-box; - color: var(--paper-grey-900); - display: flex; - flex-direction: column; - font-size: 100%; - justify-content: center; - margin: 0; - min-height: 100vh; - padding: 8px; -} - -@media (prefers-color-scheme: dark) { - body { - color: var(--cr-primary-text-color); - } -} - -.watermark { - -webkit-mask-image: url(chrome://resources/images/google_logo.svg); - -webkit-mask-repeat: no-repeat; - -webkit-mask-size: 100%; - animation: fadeIn 1s cubic-bezier(0, 0, .2, 1) both; - background: var(--paper-grey-400); - bottom: 24px; - height: 24px; - position: absolute; - width: 74px; -} - -@media (prefers-color-scheme: dark) { - .watermark { - background: var(--cr-secondary-text-color); - } -} - -@media(max-height: 608px) { - .watermark { - display: none; - } -}
diff --git a/chrome/browser/resources/welcome/welcome.html b/chrome/browser/resources/welcome/welcome.html deleted file mode 100644 index 8f0474a..0000000 --- a/chrome/browser/resources/welcome/welcome.html +++ /dev/null
@@ -1,244 +0,0 @@ -<!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> -<head> - <meta charset="utf-8"> - <title>$i18n{headerText}</title> - - <link rel="import" href="chrome://resources/html/polymer.html"> - - <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html"> - <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> - <link rel="import" href="chrome://resources/html/cr.html"> - <link rel="import" href="chrome://resources/html/util.html"> - - <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> - <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> - <link rel="stylesheet" href="chrome://welcome/welcome.css"> - - <style> - @media (prefers-color-scheme: dark) { - html { - background-color: var(--md-background-color); - } - } - </style> - - <dom-module id="welcome-app"> - <template> - <style> - @keyframes slideUpContent { - from { - transform: translateY(186px); - } - } - - @keyframes fadeIn { - from { - opacity: 0; - } - } - - @keyframes fadeOut { - to { - opacity: 0; - } - } - - - @keyframes fadeInAndSlideUp { - from { - opacity: 0; - transform: translateY(8px); - } - } - - @keyframes spin { - from { - transform: rotate(1440deg) scale(0.8); - } - } - - @keyframes fadeInAndSlideDownShadow { - from { - opacity: .6; - top: 0; - } - } - - @keyframes scaleUp { - 0% { - transform: scale(.8); - } - } - - @keyframes colorize { - from { - filter: grayscale(100%) brightness(128%) contrast(20%) brightness(161%); - opacity: .6; - } - } - - @keyframes bounce { - 0% { - transform: matrix3d(0.8, 0, 0, 0, 0, 0.8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 7.61% { - transform: matrix3d(0.907, 0, 0, 0, 0, 0.907, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 11.41% { - transform: matrix3d(0.948, 0, 0, 0, 0, 0.948, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 15.12% { - transform: matrix3d(0.976, 0, 0, 0, 0, 0.976, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 18.92% { - transform: matrix3d(0.996, 0, 0, 0, 0, 0.996, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 22.72% { - transform: matrix3d(1.008, 0, 0, 0, 0, 1.008, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 30.23% { - transform: matrix3d(1.014, 0, 0, 0, 0, 1.014, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 50.25% { - transform: matrix3d(1.003, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 70.27% { - transform: matrix3d(0.999, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - 100% { - transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - } - - .content { - height: 100%; - overflow-y: hidden; - } - - .slider { - align-items: center; - animation: slideUpContent 600ms 1.8s cubic-bezier(.4, .2, 0, 1) both; - display: flex; - flex: 1; - flex-direction: column; - justify-content: center; - max-width: 500px; - } - - .heading { - animation: fadeInAndSlideUp 600ms 1.9s cubic-bezier(.4, .2, 0, 1) both; - font-size: 2.125em; - margin-bottom: .25em; - margin-top: 1.5em; - text-align: center; - } - - .subheading { - animation: fadeInAndSlideUp 600ms 1.9s cubic-bezier(.4, .2, 0, 1) both; - color: rgb(95, 99, 104); - font-size: 1em; - font-weight: 500; - margin-top: .25em; - text-align: center; - } - - @media (prefers-color-scheme: dark) { - .subheading { - color: var(--cr-secondary-text-color); - } - } - - .logo { - animation: fadeIn 600ms both, bounce 1s 600ms linear both; - height: 96px; - position: relative; - width: 96px; - } - - .logo-icon { - animation: spin 2.4s cubic-bezier(.4, .2, 0, 1) both, - colorize 300ms 700ms linear both; - background-image: -webkit-image-set(url(chrome://welcome/logo.png) 1x, - url(chrome://welcome/logo2x.png) 2x); - background-size: 100%; - height: 96px; - width: 96px; - } - - .logo-shadow { - animation: fadeInAndSlideDownShadow 300ms 600ms both; - background: rgba(0, 0, 0, .2); - border-radius: 50%; - filter: blur(16px); - height: 96px; - position: absolute; - top: 16px; - width: 96px; - z-index: -1; - } - - .signin { - animation: fadeInAndSlideUp 600ms 2s cubic-bezier(.4, .2, 0, 1) both; - margin-top: 3em; - } - - .signin-description { - font-size: .875em; - line-height: 1.725em; - max-width: 344px; - } - - .signin-buttons { - align-items: center; - display: flex; - flex-direction: column; - margin: auto; - margin-top: 2em; - width: fit-content; - } - - cr-button { - font-size: .8125em; - /* Makes sure the two cr-button's are the same width since they're - placed vertically. Requires parent to be "width: fit-content;". */ - width: 100%; - } - - #cancel { - margin-bottom: 2px; /* Prevent focus ring from being chopped. */ - margin-top: 1.5em; - } - </style> - <div class="content"> - <div class="slider"> - <div class="logo"> - <div class="logo-icon" on-click="onLogoTap_"></div> - <div class="logo-shadow"></div> - </div> - <div class="heading">$i18n{headerText}</div> - <if expr="_google_chrome"> - <div class="subheading">$i18n{subheaderText}</div> - </if> - <div class="signin"> - <div class="signin-description">$i18n{descriptionText}</div> - <div class="signin-buttons"> - <cr-button class="action-button" on-click="onAccept_"> - $i18n{acceptText} - </cr-button> - <cr-button id="cancel" on-click="onDecline_"> - $i18n{declineText} - </cr-button> - </div> - </div> - </div> - </div> - </template> - <script src="welcome.js"></script> - </dom-module> -</head> -<body> - <welcome-app></welcome-app> - <div class="watermark"></div> -</body> -</html>
diff --git a/chrome/browser/resources/welcome/welcome.js b/chrome/browser/resources/welcome/welcome.js deleted file mode 100644 index 7343242c..0000000 --- a/chrome/browser/resources/welcome/welcome.js +++ /dev/null
@@ -1,30 +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. - -Polymer({ - is: 'welcome-app', - - /** @private */ - onAccept_: function() { - chrome.send('handleActivateSignIn'); - }, - - /** @private */ - onDecline_: function() { - chrome.send('handleUserDecline'); - }, - - /** @private */ - onLogoTap_: function() { - this.$$('.logo-icon') - .animate( - { - transform: ['none', 'rotate(-10turn)'], - }, - /** @type {!KeyframeEffectOptions} */ ({ - duration: 500, - easing: 'cubic-bezier(1, 0, 0, 1)', - })); - }, -});
diff --git a/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.cc b/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.cc index bda0b78..d1e3150 100644 --- a/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.cc +++ b/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.cc
@@ -64,8 +64,8 @@ void ShareToSingleTarget(content::WebContents* tab, const GURL& link_url) { Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext()); - DCHECK(GetValidDeviceCount(profile) == 1); - std::vector<TargetDeviceInfo> devices = + DCHECK_EQ(GetValidDeviceCount(profile), 1u); + const std::vector<TargetDeviceInfo>& devices = SendTabToSelfSyncServiceFactory::GetForProfile(profile) ->GetSendTabToSelfModel() ->GetTargetDeviceInfoSortedList(); @@ -94,24 +94,25 @@ device_count); } -int GetValidDeviceCount(Profile* profile) { +size_t GetValidDeviceCount(Profile* profile) { SendTabToSelfSyncService* service = SendTabToSelfSyncServiceFactory::GetForProfile(profile); DCHECK(service); SendTabToSelfModel* model = service->GetSendTabToSelfModel(); DCHECK(model); - std::vector<TargetDeviceInfo> devices = + const std::vector<TargetDeviceInfo>& devices = model->GetTargetDeviceInfoSortedList(); return devices.size(); } -std::string GetSingleTargetDeviceName(Profile* profile) { - DCHECK(GetValidDeviceCount(profile) == 1); - return SendTabToSelfSyncServiceFactory::GetForProfile(profile) - ->GetSendTabToSelfModel() - ->GetTargetDeviceInfoSortedList() - .begin() - ->device_name; +base::string16 GetSingleTargetDeviceName(Profile* profile) { + DCHECK_EQ(GetValidDeviceCount(profile), 1u); + return base::UTF8ToUTF16( + SendTabToSelfSyncServiceFactory::GetForProfile(profile) + ->GetSendTabToSelfModel() + ->GetTargetDeviceInfoSortedList() + .begin() + ->device_name); } } // namespace send_tab_to_self
diff --git a/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h b/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h index 15387963..5b8322a 100644 --- a/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h +++ b/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h
@@ -6,6 +6,8 @@ #define CHROME_BROWSER_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_DESKTOP_UTIL_H_ #include <string> + +#include "base/strings/string16.h" #include "url/gurl.h" class GURL; @@ -63,11 +65,11 @@ const int& device_count); // Gets the count of valid device number. -int GetValidDeviceCount(Profile* profile); +size_t GetValidDeviceCount(Profile* profile); // Gets the name of the single valid device. Will be called when // GetValidDeviceCount() == 1. -std::string GetSingleTargetDeviceName(Profile* profile); +base::string16 GetSingleTargetDeviceName(Profile* profile); } // namespace send_tab_to_self
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.cc b/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.cc index 4c85674..cc5d714 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.h" #include "base/strings/strcat.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/external_protocol/external_protocol_handler.h" #include "chrome/browser/sharing/click_to_call/click_to_call_constants.h" #include "chrome/browser/sharing/click_to_call/click_to_call_dialog.h" @@ -23,6 +24,7 @@ #include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" #include "ui/strings/grit/ui_strings.h" +#include "url/url_util.h" using SharingMessage = chrome_browser_sharing::SharingMessage; using App = ClickToCallSharingDialogController::App; @@ -137,9 +139,17 @@ send_failed_ = false; UpdateIcon(); + std::string phone_number_string(phone_url_.GetContent()); + url::RawCanonOutputT<base::char16> unescaped_phone_number; + url::DecodeURLEscapeSequences( + phone_number_string.data(), phone_number_string.size(), + url::DecodeURLMode::kUTF8OrIsomorphic, &unescaped_phone_number); + SharingMessage sharing_message; sharing_message.mutable_click_to_call_message()->set_phone_number( - phone_url_.GetContent()); + base::UTF16ToUTF8(base::string16(unescaped_phone_number.data(), + unescaped_phone_number.length()))); + sharing_service_->SendMessageToDevice( device.guid(), kSharingClickToCallMessageTTL, std::move(sharing_message), base::Bind(&ClickToCallSharingDialogController::OnMessageSentToDevice,
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller_unittest.cc b/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller_unittest.cc index 5d0c4c6..71994b7 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller_unittest.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller_unittest.cc
@@ -36,7 +36,8 @@ namespace { -const char kPhoneNumber[] = "987654321"; +const char kPhoneNumber[] = "073%2087%202525%2078"; +const char kExpectedPhoneNumber[] = "073 87 2525 78"; const char kReceiverGuid[] = "test_receiver_guid"; const char kReceiverName[] = "test_receiver_name"; @@ -112,7 +113,7 @@ sync_pb::SyncEnums::TYPE_PHONE, base::Time::Now(), 1); chrome_browser_sharing::SharingMessage sharing_message; sharing_message.mutable_click_to_call_message()->set_phone_number( - kPhoneNumber); + kExpectedPhoneNumber); EXPECT_CALL(*service(), SendMessageToDevice(Eq(kReceiverGuid), Eq(kSharingClickToCallMessageTTL), ProtoEquals(sharing_message), _));
diff --git a/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc b/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc index 5754f2f..cdae9e9 100644 --- a/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc
@@ -9,6 +9,7 @@ #include "components/sync/base/passphrase_enums.h" #include "components/sync/driver/profile_sync_service.h" #include "components/sync/driver/sync_driver_switches.h" +#include "components/sync/engine/sync_engine_switches.h" #include "components/sync/nigori/cryptographer.h" namespace { @@ -399,6 +400,59 @@ expected, {KeyDerivationParams::CreateForPbkdf2(), "hunter2"})); } +// TODO(https://crbug.com/952074): re-enable once flakiness is addressed. +#if defined(THREAD_SANITIZER) +#define MAYBE_PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode \ + DISABLED_PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode +#else +#define MAYBE_PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode \ + PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode +#endif + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode) { + base::test::ScopedFeatureList override_features; + // TODO(crbug.com/922900): Don't disable scrypt derivation and use it as key + // derivation method in ShouldLoadUSSCustomPassphraseInDirectoryMode, once + // USS implementation support it for new passphrases. + override_features.InitWithFeatures( + /*enabled_features=*/{switches::kSyncUSSBookmarks, + switches::kSyncUSSPasswords, + switches::kSyncUSSAutofillWalletMetadata, + switches::kSyncUSSNigori}, + /*disabled_features=*/{switches::kSyncUseScryptForNewCustomPassphrases}); + ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(WaitForNigori(PassphraseType::KEYSTORE_PASSPHRASE)); + GetSyncService()->GetUserSettings()->SetEncryptionPassphrase("hunter2"); + ASSERT_TRUE(WaitForNigori(PassphraseType::CUSTOM_PASSPHRASE)); +} + +// TODO(https://crbug.com/952074): re-enable once flakiness is addressed. +#if defined(THREAD_SANITIZER) +#define MAYBE_ShouldLoadUSSCustomPassphraseInDirectoryMode \ + DISABLED_ShouldLoadUSSCustomPassphraseInDirectoryMode +#else +#define MAYBE_ShouldLoadUSSCustomPassphraseInDirectoryMode \ + ShouldLoadUSSCustomPassphraseInDirectoryMode +#endif + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + ShouldLoadUSSCustomPassphraseInDirectoryMode) { + // We should be able to decrypt bookmarks with passphrase, which was set when + // kSyncUSSNigori was enabled, without providing it again once kSyncUSSNigori + // is disabled. + base::test::ScopedFeatureList override_features; + override_features.InitAndDisableFeature(switches::kSyncUSSNigori); + const KeyParams key_params = {KeyDerivationParams::CreateForPbkdf2(), + "hunter2"}; + InjectEncryptedServerBookmark( + "some bookmark", GURL("http://example.com/doesnt-matter"), key_params); + ASSERT_TRUE(SetupClients()); + + EXPECT_TRUE(WaitForPassphraseRequiredState(/*desired_state=*/false)); + EXPECT_TRUE(WaitForClientBookmarkWithTitle("some bookmark")); +} + INSTANTIATE_TEST_SUITE_P(USS, SingleClientCustomPassphraseDoNotUseScryptSyncTest, testing::Values(false, true));
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.cc b/chrome/browser/ui/app_list/app_list_client_impl.cc index e234b828..09aaa7cc 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.cc +++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -191,10 +191,7 @@ return; } - requested_model_updater->ActivateChromeItem(id, event_flags); - // Send a training signal to the search controller. - CHECK(current_model_updater_); const auto* item = current_model_updater_->FindItem(id); if (item) { app_list::AppLaunchData app_launch_data; @@ -205,6 +202,19 @@ } app_launch_event_logger_.OnGridClicked(id); + + requested_model_updater->ActivateChromeItem(id, event_flags); + + // Suspect that |id| may be destructed after calling ActivateChromeItem. Add + // the following two lines to help investigate the crash. + std::string copy = id; + base::debug::Alias(©); + + // Suspect that the model updater may change after calling ActivateChromeItem. + // Add checks to help invesigate the crash. + CHECK(current_model_updater_); + CHECK(requested_model_updater); + CHECK(current_model_updater_ == requested_model_updater); } void AppListClientImpl::GetContextMenuModel(
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc index a408dbd..88e6e9e 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -310,7 +310,7 @@ // Methods for item querying ChromeAppListItem* ChromeAppListModelUpdater::FindItem(const std::string& id) { - return items_.count(id) ? items_[id].get() : nullptr; + return items_.find(id) != items_.end() ? items_[id].get() : nullptr; } size_t ChromeAppListModelUpdater::ItemCount() {
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.cc b/chrome/browser/ui/ash/wallpaper_controller_client.cc index f81641e..1e37d89 100644 --- a/chrome/browser/ui/ash/wallpaper_controller_client.cc +++ b/chrome/browser/ui/ash/wallpaper_controller_client.cc
@@ -9,7 +9,6 @@ #include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/customization/customization_wallpaper_util.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/device_local_account.h" @@ -26,7 +25,6 @@ #include "components/session_manager/core/session_manager.h" #include "components/user_manager/known_user.h" #include "components/user_manager/user_manager.h" -#include "content/public/browser/notification_service.h" #include "content/public/common/service_manager_connection.h" #include "extensions/browser/extension_system.h" #include "extensions/common/constants.h" @@ -501,13 +499,6 @@ extensions::AppLaunchSource::kSourceChromeInternal)); } -void WallpaperControllerClient::OnFirstWallpaperAnimationFinished() { - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED, - content::NotificationService::AllSources(), - content::NotificationService::NoDetails()); -} - bool WallpaperControllerClient::ShouldShowUserNamesOnLogin() const { bool show_user_names = true; chromeos::CrosSettings::Get()->GetBoolean(
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.h b/chrome/browser/ui/ash/wallpaper_controller_client.h index 16299018..17cd1a8 100644 --- a/chrome/browser/ui/ash/wallpaper_controller_client.h +++ b/chrome/browser/ui/ash/wallpaper_controller_client.h
@@ -104,7 +104,6 @@ // ash::WallpaperControllerClient: void OpenWallpaperPicker() override; - void OnFirstWallpaperAnimationFinished() override; void DeviceWallpaperImageFilePathChanged();
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc index a690c98..6083b88 100644 --- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc +++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc
@@ -62,8 +62,8 @@ return l10n_util::GetStringUTF16(IDS_CONTEXT_MENU_SEND_TAB_TO_SELF); } -std::vector<TargetDeviceInfo> SendTabToSelfBubbleController::GetValidDevices() - const { +const std::vector<TargetDeviceInfo>& +SendTabToSelfBubbleController::GetValidDevices() const { return valid_devices_; } @@ -91,7 +91,7 @@ SendTabToSelfBubbleController::SendTabToSelfBubbleController( content::WebContents* web_contents) : web_contents_(web_contents) { - this->FetchDeviceInfo(); + FetchDeviceInfo(); } void SendTabToSelfBubbleController::FetchDeviceInfo() {
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h index 00ec118..5ae3ddb 100644 --- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h +++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h
@@ -40,7 +40,7 @@ // Returns the title of send tab to self bubble. base::string16 GetWindowTitle() const; // Returns the valid devices info map. - std::vector<TargetDeviceInfo> GetValidDevices() const; + const std::vector<TargetDeviceInfo>& GetValidDevices() const; // Returns current profile. Profile* GetProfile() const;
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_view.h b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_view.h index ac4d9dd..aa31214 100644 --- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_view.h +++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_view.h
@@ -11,6 +11,8 @@ // This object is responsible for its own lifetime. class SendTabToSelfBubbleView { public: + virtual ~SendTabToSelfBubbleView() = default; + // Called to close the bubble and prevent future callbacks into the // controller. virtual void Hide() = 0;
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.cc b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.cc index bca6921..e48a9da 100644 --- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.cc +++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.cc
@@ -41,7 +41,7 @@ // Returns true if the command id identifies a non-link contextual menu item. bool IsShareTabCommandId(int command_id) { - return (command_id >= kShareTabCommandId && command_id < kShareLinkCommandId); + return command_id >= kShareTabCommandId && command_id < kShareLinkCommandId; } // Returns true if the command id identifies a link contextual menu item. @@ -53,7 +53,8 @@ int CommandIdToVectorIndex(int command_id) { if (IsShareTabCommandId(command_id)) { return command_id - kShareTabCommandId; - } else if (IsShareLinkCommandId(command_id)) { + } + if (IsShareLinkCommandId(command_id)) { return command_id - kShareLinkCommandId; } return -1; @@ -87,6 +88,11 @@ SendTabToSelfSubMenuModel::SendTabToSelfSubMenuModel( content::WebContents* tab, + SendTabToSelfMenuType menu_type) + : SendTabToSelfSubMenuModel(tab, menu_type, GURL()) {} + +SendTabToSelfSubMenuModel::SendTabToSelfSubMenuModel( + content::WebContents* tab, SendTabToSelfMenuType menu_type, const GURL& link_url) : ui::SimpleMenuModel(this), @@ -155,14 +161,8 @@ const std::string& cache_guid, int index) { ValidDeviceItem item(device_name, cache_guid); - int command_id; - if (menu_type_ == kLink) { - // Generates command ids for sharing a link. - command_id = index + kShareLinkCommandId; - } else { - // Generates command ids for sharing a tab. - command_id = index + kShareTabCommandId; - } + int command_id = + (menu_type_ == kTab) ? kShareTabCommandId : kShareLinkCommandId + index; InsertItemAt(index, command_id, base::UTF8ToUTF16(device_name)); valid_device_items_.push_back(item); }
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h index 464a8df..0d5ddf170 100644 --- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h +++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h
@@ -33,8 +33,10 @@ struct ValidDeviceItem; SendTabToSelfSubMenuModel(content::WebContents* tab, + SendTabToSelfMenuType menu_type); + SendTabToSelfSubMenuModel(content::WebContents* tab, SendTabToSelfMenuType menu_type, - const GURL& link_url = GURL()); + const GURL& link_url); ~SendTabToSelfSubMenuModel() override; // Overridden from ui::SimpleMenuModel::Delegate:
diff --git a/chrome/browser/ui/tabs/pinned_tab_service.cc b/chrome/browser/ui/tabs/pinned_tab_service.cc index ac761ab0..29e862bb 100644 --- a/chrome/browser/ui/tabs/pinned_tab_service.cc +++ b/chrome/browser/ui/tabs/pinned_tab_service.cc
@@ -7,47 +7,16 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/tabs/pinned_tab_codec.h" #include "content/public/browser/notification_service.h" -namespace { - -// Returns true if |browser| is the only normal (tabbed) browser for |browser|'s -// profile (across all desktops). -bool IsOnlyNormalBrowser(Browser* browser) { - for (auto* b : *BrowserList::GetInstance()) { - if (b != browser && b->is_type_tabbed() && - b->profile() == browser->profile()) { - return false; - } - } - return true; -} - -// Returns true if there's at lease one tabbed browser associated with -// |profile|. -bool BrowserListHasNormalBrowser(Profile* profile) { - for (auto* b : *BrowserList::GetInstance()) { - if (b->is_type_tabbed() && b->profile() == profile) - return true; - } - return false; -} - -} // namespace - -PinnedTabService::PinnedTabService(Profile* profile) - : profile_(profile), - save_pinned_tabs_(true), - has_normal_browser_(false), - browser_list_observer_(this) { - registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED, - content::NotificationService::AllBrowserContextsAndSources()); +PinnedTabService::PinnedTabService(Profile* profile) : profile_(profile) { registrar_.Add(this, chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, content::NotificationService::AllSources()); - registrar_.Add(this, chrome::NOTIFICATION_TAB_ADDED, - content::NotificationService::AllSources()); + + for (Browser* browser : *BrowserList::GetInstance()) + OnBrowserAdded(browser); + browser_list_observer_.Add(BrowserList::GetInstance()); } @@ -56,14 +25,12 @@ void PinnedTabService::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - // Saving of tabs happens when saving is enabled, and when either the user - // exits the application or closes the last browser window. - // Saving is disabled when the user exits the application to prevent the - // pin state of all the open browsers being overwritten by the state of the - // last browser window to close. - // Saving is re-enabled when a browser window or tab is opened again. - // Note, cancelling a shutdown (via onbeforeunload) will not re-enable pinned - // tab saving immediately, to prevent the following situation: + // Saving of tabs happens when the user exits the application or closes the + // last browser window. After saving, |need_to_write_pinned_tabs_| is set to + // false to make sure subsequent window closures don't overwrite the pinned + // tab state. Saving is re-enabled when a browser window or tab is opened + // again. Note, cancelling a shutdown (via onbeforeunload) will not re-enable + // pinned tab saving immediately, to prevent the following situation: // * two windows are open, one with pinned tabs // * user exits // * pinned tabs are saved @@ -73,55 +40,52 @@ // * pinned tabs are saved, without the window with the pinned tabs, // over-writing the correct state. // Saving is re-enabled if a new tab or window is opened. - switch (type) { - case chrome::NOTIFICATION_BROWSER_OPENED: { - Browser* browser = content::Source<Browser>(source).ptr(); - if (!has_normal_browser_ && browser->is_type_tabbed() && - browser->profile() == profile_) { - has_normal_browser_ = true; - } - save_pinned_tabs_ = true; - break; - } + DCHECK_EQ(type, chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST); + if (observed_tab_strips_.IsObservingSources()) + WritePinnedTabsIfNecessary(); +} - case chrome::NOTIFICATION_TAB_ADDED: { - save_pinned_tabs_ = true; - break; - } +void PinnedTabService::OnBrowserAdded(Browser* browser) { + if (browser->profile() != profile_ || !browser->is_type_tabbed()) + return; - case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: { - if (has_normal_browser_ && save_pinned_tabs_) { - PinnedTabCodec::WritePinnedTabs(profile_); - save_pinned_tabs_ = false; - } - break; - } - - default: - NOTREACHED(); - } + need_to_write_pinned_tabs_ = true; + observed_tab_strips_.Add(browser->tab_strip_model()); } void PinnedTabService::OnBrowserClosing(Browser* browser) { - if (has_normal_browser_ && save_pinned_tabs_ && - browser->profile() == profile_ && IsOnlyNormalBrowser(browser)) { - has_normal_browser_ = false; - PinnedTabCodec::WritePinnedTabs(profile_); - } + if (browser->profile() != profile_ || !browser->is_type_tabbed()) + return; + + if (observed_tab_strips_.GetSourcesCount() == 1U) + WritePinnedTabsIfNecessary(); } void PinnedTabService::OnBrowserRemoved(Browser* browser) { - if (!browser->is_type_tabbed() || browser->profile() != profile_) + if (browser->profile() != profile_ || !browser->is_type_tabbed()) return; - if (save_pinned_tabs_ && has_normal_browser_ && - !BrowserListHasNormalBrowser(browser->profile())) { - // This happens when user closes each tabs manually via the close button on - // them. In this case OnBrowserClosing() above is not called. This causes - // pinned tabs to repopen on the next startup. So we should call - // WritePinnedTab() to clear the data. - // http://crbug.com/71939 - has_normal_browser_ = false; + observed_tab_strips_.Remove(browser->tab_strip_model()); + + // This happens when user closes each tabs manually via the close button on + // them. In this case OnBrowserClosing() above is not called. This causes + // pinned tabs to repopen on the next startup. So we should call + // WritePinnedTab() to clear the data. + // http://crbug.com/71939 + if (!observed_tab_strips_.IsObservingSources()) + WritePinnedTabsIfNecessary(); +} + +void PinnedTabService::OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) { + if (change.type() == TabStripModelChange::kInserted) + need_to_write_pinned_tabs_ = true; +} + +void PinnedTabService::WritePinnedTabsIfNecessary() { + if (need_to_write_pinned_tabs_) PinnedTabCodec::WritePinnedTabs(profile_); - } + need_to_write_pinned_tabs_ = false; }
diff --git a/chrome/browser/ui/tabs/pinned_tab_service.h b/chrome/browser/ui/tabs/pinned_tab_service.h index 23922c3..2d624c0 100644 --- a/chrome/browser/ui/tabs/pinned_tab_service.h +++ b/chrome/browser/ui/tabs/pinned_tab_service.h
@@ -10,6 +10,8 @@ #include "base/scoped_observer.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list_observer.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "components/keyed_service/core/keyed_service.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -21,6 +23,7 @@ // appropriate set of notifications to know it should update preferences. class PinnedTabService : public content::NotificationObserver, public BrowserListObserver, + public TabStripModelObserver, public KeyedService { public: explicit PinnedTabService(Profile* profile); @@ -33,21 +36,34 @@ const content::NotificationDetails& details) override; // BrowserListObserver: + void OnBrowserAdded(Browser* browser) override; void OnBrowserClosing(Browser* browser) override; void OnBrowserRemoved(Browser* browser) override; + // TabStripModelObserver: + void OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override; + + // Writes the pinned tabs for |profile_|, but only if a new tab or browser + // window has been added since the last time the method was called. + void WritePinnedTabsIfNecessary(); + Profile* profile_; // True if we should save the pinned tabs when a browser window closes or the - // user exits the application. - bool save_pinned_tabs_; - - // True if there is at least one normal browser for our profile. - bool has_normal_browser_; + // user exits the application. This is set to false after writing pinned tabs, + // and set back to true when new tabs or windows are added. + bool need_to_write_pinned_tabs_ = true; content::NotificationRegistrar registrar_; - ScopedObserver<BrowserList, BrowserListObserver> browser_list_observer_; + ScopedObserver<BrowserList, BrowserListObserver> browser_list_observer_{this}; + + // |this| observes all tabbed browsers that match |profile_|. + ScopedObserver<TabStripModel, TabStripModelObserver> observed_tab_strips_{ + this}; DISALLOW_COPY_AND_ASSIGN(PinnedTabService); };
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc index 717748c..a796b6e 100644 --- a/chrome/browser/ui/tabs/tab_menu_model.cc +++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -6,7 +6,6 @@ #include "base/command_line.h" #include "base/metrics/user_metrics.h" -#include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h" @@ -94,16 +93,15 @@ AddItem(TabStripModel::CommandSendTabToSelfSingleTarget, l10n_util::GetStringFUTF16( IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, - base::UTF8ToUTF16(send_tab_to_self::GetSingleTargetDeviceName( - tab_strip->profile())))); + send_tab_to_self::GetSingleTargetDeviceName( + tab_strip->profile()))); #else - AddItemWithIcon( - TabStripModel::CommandSendTabToSelfSingleTarget, - l10n_util::GetStringFUTF16( - IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, - base::UTF8ToUTF16(send_tab_to_self::GetSingleTargetDeviceName( - tab_strip->profile()))), - *send_tab_to_self::GetImageSkia()); + AddItemWithIcon(TabStripModel::CommandSendTabToSelfSingleTarget, + l10n_util::GetStringFUTF16( + IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, + (send_tab_to_self::GetSingleTargetDeviceName( + tab_strip->profile()))), + *send_tab_to_self::GetImageSkia()); #endif send_tab_to_self::RecordSendTabToSelfClickResult( send_tab_to_self::kTabMenu,
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index a7c88b8..f270fc7 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -66,6 +66,7 @@ #include "chrome/browser/ui/tabs/tab_menu_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_utils.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/accelerator_table.h" #include "chrome/browser/ui/views/accessibility/invert_bubble_view.h" @@ -1163,6 +1164,8 @@ } ToolbarActionsBar* BrowserView::GetToolbarActionsBar() { + CHECK(!base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)); + BrowserActionsContainer* container = toolbar_button_provider_->GetBrowserActionsContainer(); return container ? container->toolbar_actions_bar() : nullptr;
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 2abc7d0..1f30038 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -1041,10 +1041,7 @@ PageActionIconView* icon = this->omnibox_page_action_icon_container_view()->GetPageActionIconView( PageActionIconType::kSendTabToSelf); - if (icon) { - return icon->Update(); - } - return false; + return icon && icon->Update(); } void LocationBarView::SaveStateToContents(WebContents* contents) {
diff --git a/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view.cc b/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view.cc index ab3ecf2..df3e693 100644 --- a/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view.cc +++ b/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view.cc
@@ -6,6 +6,7 @@ #include "base/i18n/message_formatter.h" #include "base/i18n/unicodestring.h" +#include "base/stl_util.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/native_file_system/chrome_native_file_system_permission_context.h" #include "chrome/browser/ui/browser.h" @@ -248,6 +249,18 @@ ->toolbar_button_provider() ->GetOmniboxPageActionIconContainerView(); + // Writable directories are generally also readable, but we don't want to + // display the same directory twice. So filter out any writable directories + // from the readable directories list. + std::set<base::FilePath> writable_directories( + usage.writable_directories.begin(), usage.writable_directories.end()); + std::vector<base::FilePath> readable_directories; + for (base::FilePath& path : usage.readable_directories) { + if (!base::Contains(writable_directories, path)) + readable_directories.push_back(std::move(path)); + } + usage.readable_directories = readable_directories; + bubble_ = new NativeFileSystemUsageBubbleView( anchor_view, gfx::Point(), web_contents, origin, std::move(usage));
diff --git a/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view_browsertest.cc b/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view_browsertest.cc index f4ef40d..0fd7a8c 100644 --- a/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view_browsertest.cc
@@ -54,6 +54,16 @@ usage.readable_directories.emplace_back( FILE_PATH_LITERAL("/baz/My Project")); usage.readable_directories.emplace_back(FILE_PATH_LITERAL("/baz/Assets")); + } else if (name == "ReadableAndWritableFolders") { + usage.readable_directories.emplace_back( + FILE_PATH_LITERAL("/foo/bar/Images")); + usage.readable_directories.emplace_back( + FILE_PATH_LITERAL("/baz/My Project")); + usage.readable_directories.emplace_back(FILE_PATH_LITERAL("/baz/Assets")); + usage.writable_directories.emplace_back(FILE_PATH_LITERAL("/baz/Assets")); + usage.writable_directories.emplace_back( + FILE_PATH_LITERAL("/la/asdf/Processing")); + usage.writable_directories.emplace_back(FILE_PATH_LITERAL("/baz/Images")); } else if (name == "default") { usage.readable_directories.emplace_back( FILE_PATH_LITERAL("/home/me/Images")); @@ -119,3 +129,8 @@ InvokeUi_MultipleReadableFolders) { ShowAndVerifyUi(); } + +IN_PROC_BROWSER_TEST_F(NativeFileSystemUsageBubbleViewTest, + InvokeUi_ReadableAndWritableFolders) { + ShowAndVerifyUi(); +}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index d1031ab..dda1742c 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -12,7 +12,6 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/command_updater.h" @@ -1773,8 +1772,8 @@ index, IDC_SEND_TAB_TO_SELF_SINGLE_TARGET, l10n_util::GetStringFUTF16( IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET, - base::UTF8ToUTF16(send_tab_to_self::GetSingleTargetDeviceName( - location_bar_view_->profile())))); + send_tab_to_self::GetSingleTargetDeviceName( + location_bar_view_->profile()))); send_tab_to_self::RecordSendTabToSelfClickResult( send_tab_to_self::kOmniboxMenu, SendTabToSelfClickResult::kShowDeviceList);
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc index 5ba7e8791..b55cccd42 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "chrome/app/vector_icons/vector_icons.h"
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.h b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.h index d560bebc..01c15f79 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.h +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.h
@@ -24,8 +24,8 @@ int button_tag); ~SendTabToSelfBubbleDeviceButton() override; - const std::string device_name() const { return device_name_; } - const std::string device_guid() const { return device_guid_; } + const std::string& device_name() const { return device_name_; } + const std::string& device_guid() const { return device_guid_; } sync_pb::SyncEnums::DeviceType device_type() const { return device_type_; } private:
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc index b494f8c1..9d5dfc3 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc
@@ -25,6 +25,17 @@ namespace send_tab_to_self { +namespace { + +// The valid device button height. +constexpr int kDeviceButtonHeight = 56; +// Maximum number of buttons that are shown without scroll. If the device +// number is larger than kMaximumButtons, the bubble content will be +// scrollable. +constexpr int kMaximumButtons = 5; + +} // namespace + SendTabToSelfBubbleViewImpl::SendTabToSelfBubbleViewImpl( views::View* anchor_view, const gfx::Point& anchor_point, @@ -71,10 +82,7 @@ void SendTabToSelfBubbleViewImpl::ButtonPressed(views::Button* sender, const ui::Event& event) { - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&SendTabToSelfBubbleViewImpl::DevicePressed, - weak_factory_.GetWeakPtr(), sender->tag())); + DevicePressed(sender->tag()); } gfx::Size SendTabToSelfBubbleViewImpl::CalculatePreferredSize() const { @@ -129,7 +137,7 @@ } void SendTabToSelfBubbleViewImpl::PopulateScrollView( - const std::vector<TargetDeviceInfo> devices) { + const std::vector<TargetDeviceInfo>& devices) { device_buttons_.clear(); auto device_list_view = std::make_unique<views::View>(); device_list_view->SetLayoutManager(std::make_unique<views::BoxLayout>( @@ -152,8 +160,7 @@ if (!controller_) { return; } - SendTabToSelfBubbleDeviceButton* device_button = - device_buttons_.at(index).get(); + SendTabToSelfBubbleDeviceButton* device_button = device_buttons_[index].get(); controller_->OnDeviceSelected(device_button->device_name(), device_button->device_guid()); Hide();
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h index d1222f2..910064b 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h
@@ -5,7 +5,9 @@ #ifndef CHROME_BROWSER_UI_VIEWS_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_BUBBLE_VIEW_IMPL_H_ #define CHROME_BROWSER_UI_VIEWS_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_BUBBLE_VIEW_IMPL_H_ +#include <map> #include <memory> +#include <string> #include <vector> #include "base/memory/weak_ptr.h" @@ -21,7 +23,7 @@ namespace content { class WebContents; -} +} // namespace content namespace send_tab_to_self { @@ -35,13 +37,6 @@ public views::ButtonListener, public LocationBarBubbleDelegateView { public: - // The valid device button height. - static constexpr int kDeviceButtonHeight = 56; - // Maximum number of buttons that are shown without scroll. If the device - // number is larger than kMaximumButtons, the bubble content will be - // scrollable. - static constexpr int kMaximumButtons = 5; - // Bubble will be anchored to |anchor_view|. SendTabToSelfBubbleViewImpl(views::View* anchor_view, const gfx::Point& anchor_point, @@ -88,7 +83,7 @@ void CreateScrollView(); // Populates the scroll view containing valid devices. - void PopulateScrollView(const std::vector<TargetDeviceInfo> devices); + void PopulateScrollView(const std::vector<TargetDeviceInfo>& devices); // Handles the action when a target device has been pressed. void DevicePressed(size_t index);
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc index 7dc7653..de342d5a 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
@@ -11,7 +11,6 @@ #include "base/values.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" #include "chromeos/constants/chromeos_switches.h" -#include "chromeos/services/assistant/public/features.h" #include "content/public/browser/web_ui.h" #include "content/public/common/service_manager_connection.h" #include "services/service_manager/public/cpp/connector.h" @@ -150,9 +149,7 @@ keyboard_params.SetKey("hasInternalKeyboard", base::Value(keyboards_state.has_internal_keyboard)); - const bool show_assistant_key_settings = - chromeos::assistant::features::IsKeyRemappingEnabled() && - ui::DeviceKeyboardHasAssistantKey(); + const bool show_assistant_key_settings = ui::DeviceKeyboardHasAssistantKey(); keyboard_params.SetKey("hasAssistantKey", base::Value(show_assistant_key_settings));
diff --git a/chrome/browser/ui/webui/welcome/welcome_ui.cc b/chrome/browser/ui/webui/welcome/welcome_ui.cc index 6786e280..4ae52e2 100644 --- a/chrome/browser/ui/webui/welcome/welcome_ui.cc +++ b/chrome/browser/ui/webui/welcome/welcome_ui.cc
@@ -5,9 +5,7 @@ #include "chrome/browser/ui/webui/welcome/welcome_ui.h" #include "base/bind.h" -#include "base/metrics/histogram_macros.h" -#include "base/stl_util.h" -#include "build/build_config.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/signin/account_consistency_mode_manager.h" #include "chrome/browser/ui/webui/localized_string.h" #include "chrome/browser/ui/webui/welcome/nux/bookmark_handler.h" @@ -18,7 +16,6 @@ #include "chrome/browser/ui/webui/welcome/nux_helper.h" #include "chrome/browser/ui/webui/welcome/welcome_handler.h" #include "chrome/common/pref_names.h" -#include "chrome/grit/browser_resources.h" #include "chrome/grit/chrome_unscaled_resources.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" @@ -27,9 +24,7 @@ #include "components/prefs/pref_service.h" #include "components/signin/public/base/signin_pref_names.h" #include "components/strings/grit/components_strings.h" -#include "content/public/browser/web_contents.h" #include "net/base/url_util.h" -#include "ui/base/l10n/l10n_util.h" #if defined(OS_WIN) #include "base/win/windows_version.h" @@ -37,13 +32,6 @@ namespace { -const bool kIsBranded = -#if defined(GOOGLE_CHROME_BUILD) - true; -#else - false; -#endif - const char kPreviewBackgroundPath[] = "preview-background.jpg"; bool ShouldHandleRequestCallback(base::WeakPtr<WelcomeUI> weak_ptr, @@ -81,13 +69,11 @@ void AddOnboardingStrings(content::WebUIDataSource* html_source) { static constexpr LocalizedString kLocalizedStrings[] = { // Shared strings. - {"acceptText", IDS_WELCOME_ACCEPT_BUTTON}, {"bookmarkAdded", IDS_ONBOARDING_WELCOME_BOOKMARK_ADDED}, {"bookmarksAdded", IDS_ONBOARDING_WELCOME_BOOKMARKS_ADDED}, {"bookmarkRemoved", IDS_ONBOARDING_WELCOME_BOOKMARK_REMOVED}, {"bookmarksRemoved", IDS_ONBOARDING_WELCOME_BOOKMARKS_REMOVED}, {"defaultBrowserChanged", IDS_ONBOARDING_DEFAULT_BROWSER_CHANGED}, - {"getStarted", IDS_ONBOARDING_WELCOME_GET_STARTED}, {"headerText", IDS_WELCOME_HEADER}, {"next", IDS_ONBOARDING_WELCOME_NEXT}, {"noThanks", IDS_NO_THANKS}, @@ -115,7 +101,6 @@ {"setDefaultHeader", IDS_ONBOARDING_WELCOME_NUX_SET_AS_DEFAULT_HEADER}, {"setDefaultSubHeader", IDS_ONBOARDING_WELCOME_NUX_SET_AS_DEFAULT_SUB_HEADER}, - {"setDefaultSkip", IDS_ONBOARDING_WELCOME_NUX_SET_AS_DEFAULT_SKIP}, {"setDefaultConfirm", IDS_ONBOARDING_WELCOME_NUX_SET_AS_DEFAULT_SET_AS_DEFAULT}, @@ -148,111 +133,81 @@ content::WebUIDataSource* html_source = content::WebUIDataSource::Create(url.host()); - if (nux::IsNuxOnboardingEnabled(profile)) { - // Add Onboarding welcome strings. - AddOnboardingStrings(html_source); + // Add Onboarding welcome strings. + AddOnboardingStrings(html_source); - // Add all Onboarding resources. - for (size_t i = 0; i < kOnboardingWelcomeResourcesSize; ++i) { - html_source->AddResourcePath(kOnboardingWelcomeResources[i].name, - kOnboardingWelcomeResources[i].value); - } + // Add all Onboarding resources. + for (size_t i = 0; i < kOnboardingWelcomeResourcesSize; ++i) { + html_source->AddResourcePath(kOnboardingWelcomeResources[i].name, + kOnboardingWelcomeResources[i].value); + } #if defined(GOOGLE_CHROME_BUILD) - // Load unscaled images. - html_source->AddResourcePath("images/module_icons/google_dark.svg", - IDR_WELCOME_MODULE_ICONS_GOOGLE_DARK); - html_source->AddResourcePath("images/module_icons/google_light.svg", - IDR_WELCOME_MODULE_ICONS_GOOGLE_LIGHT); - html_source->AddResourcePath("images/module_icons/set_default_dark.svg", - IDR_WELCOME_MODULE_ICONS_SET_DEFAULT_DARK); - html_source->AddResourcePath("images/module_icons/set_default_light.svg", - IDR_WELCOME_MODULE_ICONS_SET_DEFAULT_LIGHT); - html_source->AddResourcePath("images/module_icons/wallpaper_dark.svg", - IDR_WELCOME_MODULE_ICONS_WALLPAPER_DARK); - html_source->AddResourcePath("images/module_icons/wallpaper_light.svg", - IDR_WELCOME_MODULE_ICONS_WALLPAPER_LIGHT); - html_source->AddResourcePath("images/ntp_thumbnails/art.jpg", - IDR_WELCOME_NTP_THUMBNAILS_ART); - html_source->AddResourcePath("images/ntp_thumbnails/cityscape.jpg", - IDR_WELCOME_NTP_THUMBNAILS_CITYSCAPE); - html_source->AddResourcePath("images/ntp_thumbnails/earth.jpg", - IDR_WELCOME_NTP_THUMBNAILS_EARTH); - html_source->AddResourcePath("images/ntp_thumbnails/geometric_shapes.jpg", - IDR_WELCOME_NTP_THUMBNAILS_GEOMETRIC_SHAPES); - html_source->AddResourcePath("images/ntp_thumbnails/landscape.jpg", - IDR_WELCOME_NTP_THUMBNAILS_LANDSCAPE); - html_source->AddResourcePath("images/set_default_dark.svg", - IDR_WELCOME_SET_DEFAULT_DARK); - html_source->AddResourcePath("images/set_default_light.svg", - IDR_WELCOME_SET_DEFAULT_LIGHT); + // Load unscaled images. + html_source->AddResourcePath("images/module_icons/google_dark.svg", + IDR_WELCOME_MODULE_ICONS_GOOGLE_DARK); + html_source->AddResourcePath("images/module_icons/google_light.svg", + IDR_WELCOME_MODULE_ICONS_GOOGLE_LIGHT); + html_source->AddResourcePath("images/module_icons/set_default_dark.svg", + IDR_WELCOME_MODULE_ICONS_SET_DEFAULT_DARK); + html_source->AddResourcePath("images/module_icons/set_default_light.svg", + IDR_WELCOME_MODULE_ICONS_SET_DEFAULT_LIGHT); + html_source->AddResourcePath("images/module_icons/wallpaper_dark.svg", + IDR_WELCOME_MODULE_ICONS_WALLPAPER_DARK); + html_source->AddResourcePath("images/module_icons/wallpaper_light.svg", + IDR_WELCOME_MODULE_ICONS_WALLPAPER_LIGHT); + html_source->AddResourcePath("images/ntp_thumbnails/art.jpg", + IDR_WELCOME_NTP_THUMBNAILS_ART); + html_source->AddResourcePath("images/ntp_thumbnails/cityscape.jpg", + IDR_WELCOME_NTP_THUMBNAILS_CITYSCAPE); + html_source->AddResourcePath("images/ntp_thumbnails/earth.jpg", + IDR_WELCOME_NTP_THUMBNAILS_EARTH); + html_source->AddResourcePath("images/ntp_thumbnails/geometric_shapes.jpg", + IDR_WELCOME_NTP_THUMBNAILS_GEOMETRIC_SHAPES); + html_source->AddResourcePath("images/ntp_thumbnails/landscape.jpg", + IDR_WELCOME_NTP_THUMBNAILS_LANDSCAPE); + html_source->AddResourcePath("images/set_default_dark.svg", + IDR_WELCOME_SET_DEFAULT_DARK); + html_source->AddResourcePath("images/set_default_light.svg", + IDR_WELCOME_SET_DEFAULT_LIGHT); #endif // defined(GOOGLE_CHROME_BUILD) - // chrome://welcome - html_source->SetDefaultResource( - IDR_WELCOME_ONBOARDING_WELCOME_WELCOME_HTML); + // chrome://welcome + html_source->SetDefaultResource(IDR_WELCOME_ONBOARDING_WELCOME_WELCOME_HTML); #if defined(OS_WIN) - html_source->AddBoolean( - "is_win10", base::win::GetVersion() >= base::win::Version::WIN10); + html_source->AddBoolean("is_win10", + base::win::GetVersion() >= base::win::Version::WIN10); #endif - // Add the shared bookmark handler for onboarding modules. - web_ui->AddMessageHandler( - std::make_unique<nux::BookmarkHandler>(profile->GetPrefs())); + // Add the shared bookmark handler for onboarding modules. + web_ui->AddMessageHandler( + std::make_unique<nux::BookmarkHandler>(profile->GetPrefs())); - // Add google apps bookmarking onboarding module. - web_ui->AddMessageHandler(std::make_unique<nux::GoogleAppsHandler>()); + // Add google apps bookmarking onboarding module. + web_ui->AddMessageHandler(std::make_unique<nux::GoogleAppsHandler>()); - // Add NTP custom background onboarding module. - web_ui->AddMessageHandler(std::make_unique<nux::NtpBackgroundHandler>()); + // Add NTP custom background onboarding module. + web_ui->AddMessageHandler(std::make_unique<nux::NtpBackgroundHandler>()); - // Add set-as-default onboarding module. - web_ui->AddMessageHandler(std::make_unique<nux::SetAsDefaultHandler>()); + // Add set-as-default onboarding module. + web_ui->AddMessageHandler(std::make_unique<nux::SetAsDefaultHandler>()); - html_source->AddString( - "newUserModules", - nux::GetNuxOnboardingModules(profile).FindKey("new-user")->GetString()); - html_source->AddString("returningUserModules", - nux::GetNuxOnboardingModules(profile) - .FindKey("returning-user") - ->GetString()); - html_source->AddBoolean("signinAllowed", profile->GetPrefs()->GetBoolean( - prefs::kSigninAllowed)); - html_source->SetRequestFilter( - base::BindRepeating(&ShouldHandleRequestCallback, - weak_ptr_factory_.GetWeakPtr()), - base::BindRepeating(&HandleRequestCallback, - weak_ptr_factory_.GetWeakPtr())); - html_source->SetJsonPath("strings.js"); - } else { - // Use default layout for non-DICE or unbranded build. - std::string value; - bool is_everywhere_variant = - (net::GetValueForKeyInQuery(url, "variant", &value) && - value == "everywhere"); - - if (kIsBranded) { - base::string16 subheader = - is_everywhere_variant - ? base::string16() - : l10n_util::GetStringUTF16(IDS_WELCOME_SUBHEADER); - html_source->AddString("subheaderText", subheader); - } - - int header_id = is_everywhere_variant ? IDS_WELCOME_HEADER_AFTER_FIRST_RUN - : IDS_WELCOME_HEADER; - html_source->AddString("headerText", l10n_util::GetStringUTF16(header_id)); - html_source->AddLocalizedString("acceptText", IDS_WELCOME_ACCEPT_BUTTON); - html_source->AddLocalizedString("descriptionText", IDS_WELCOME_DESCRIPTION); - html_source->AddLocalizedString("declineText", IDS_WELCOME_DECLINE_BUTTON); - html_source->AddResourcePath("welcome.js", IDR_WELCOME_JS); - html_source->AddResourcePath("welcome.css", IDR_WELCOME_CSS); - html_source->SetDefaultResource(IDR_WELCOME_HTML); - - html_source->AddResourcePath("logo.png", IDR_PRODUCT_LOGO_128); - html_source->AddResourcePath("logo2x.png", IDR_PRODUCT_LOGO_256); - } + html_source->AddString( + "newUserModules", + nux::GetNuxOnboardingModules(profile).FindKey("new-user")->GetString()); + html_source->AddString("returningUserModules", + nux::GetNuxOnboardingModules(profile) + .FindKey("returning-user") + ->GetString()); + html_source->AddBoolean( + "signinAllowed", profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed)); + html_source->SetRequestFilter( + base::BindRepeating(&ShouldHandleRequestCallback, + weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating(&HandleRequestCallback, + weak_ptr_factory_.GetWeakPtr())); + html_source->SetJsonPath("strings.js"); content::WebUIDataSource::Add(profile, html_source); }
diff --git a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java b/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java index d3925ba..fb760d8 100644 --- a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java +++ b/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
@@ -22,6 +22,7 @@ public static final String ANSWER_SUGGESTIONS_UMA_CLIENT_NAME = "AnswerSuggestions"; public static final String ASSISTANT_DETAILS_UMA_CLIENT_NAME = "AssistantDetails"; public static final String ASSISTANT_INFO_BOX_UMA_CLIENT_NAME = "AssistantInfoBox"; + public static final String ENTITY_SUGGESTIONS_UMA_CLIENT_NAME = "EntitySuggestions"; public static final String FEED_UMA_CLIENT_NAME = "Feed"; public static final String NTP_ANIMATED_LOGO_UMA_CLIENT_NAME = "NewTabPageAnimatedLogo";
diff --git a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java b/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java index aae248a..5f8e827 100644 --- a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java +++ b/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
@@ -39,7 +39,12 @@ @Override public void fetchImage( String url, String clientName, int width, int height, Callback<Bitmap> callback) { - mImageFetcherBridge.fetchImage(getConfig(), url, clientName, width, height, callback); + long startTimeMillis = System.currentTimeMillis(); + mImageFetcherBridge.fetchImage( + getConfig(), url, clientName, width, height, (Bitmap bitmapFromNative) -> { + callback.onResult(bitmapFromNative); + mImageFetcherBridge.reportTotalFetchTimeFromNative(clientName, startTimeMillis); + }); } @Override
diff --git a/chrome/renderer/extensions/extension_hooks_delegate.cc b/chrome/renderer/extensions/extension_hooks_delegate.cc index 6a536f2..b4e8bef 100644 --- a/chrome/renderer/extensions/extension_hooks_delegate.cc +++ b/chrome/renderer/extensions/extension_hooks_delegate.cc
@@ -17,6 +17,7 @@ #include "extensions/renderer/message_target.h" #include "extensions/renderer/messaging_util.h" #include "extensions/renderer/native_renderer_messaging_service.h" +#include "extensions/renderer/runtime_hooks_delegate.h" #include "extensions/renderer/script_context.h" #include "gin/converter.h" #include "gin/dictionary.h" @@ -238,17 +239,10 @@ RequestResult ExtensionHooksDelegate::HandleGetURL( ScriptContext* script_context, const std::vector<v8::Local<v8::Value>>& arguments) { - DCHECK_EQ(1u, arguments.size()); - DCHECK(arguments[0]->IsString()); - DCHECK(script_context->extension()); - - std::string path = gin::V8ToString(script_context->isolate(), arguments[0]); - - RequestResult result(RequestResult::HANDLED); - result.return_value = - gin::StringToV8(script_context->isolate(), - script_context->extension()->GetResourceURL(path).spec()); - return result; + // We call a static implementation here rather using an alias due to not being + // able to remove the extension.json GetURL entry, as it is used for generated + // documentation and api feature lists some other methods refer to. + return RuntimeHooksDelegate::GetURL(script_context, arguments); } APIBindingHooks::RequestResult ExtensionHooksDelegate::HandleGetViews(
diff --git a/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc b/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc index be0703f..1bc125b6 100644 --- a/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc +++ b/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc
@@ -237,4 +237,30 @@ context, 0, nullptr); } +// Ensure that HandleGetURL allows extension URLs and doesn't allow arbitrary +// non-extension URLs. Very similar to RuntimeHooksDeligateTest that tests a +// similar function. +TEST_F(ExtensionHooksDelegateTest, GetURL) { + v8::HandleScope handle_scope(isolate()); + v8::Local<v8::Context> context = MainContext(); + + auto get_url = [this, context](const char* args, const GURL& expected_url) { + SCOPED_TRACE(base::StringPrintf("Args: `%s`", args)); + constexpr char kGetUrlTemplate[] = + "(function() { return chrome.extension.getURL(%s); })"; + v8::Local<v8::Function> get_url = + FunctionFromString(context, base::StringPrintf(kGetUrlTemplate, args)); + v8::Local<v8::Value> url = RunFunction(get_url, context, 0, nullptr); + ASSERT_FALSE(url.IsEmpty()); + ASSERT_TRUE(url->IsString()); + EXPECT_EQ(expected_url.spec(), gin::V8ToString(isolate(), url)); + }; + + get_url("''", extension()->url()); + get_url("'foo'", extension()->GetResourceURL("foo")); + get_url("'/foo'", extension()->GetResourceURL("foo")); + get_url("'https://www.google.com'", + GURL(extension()->url().spec() + "https://www.google.com")); +} + } // namespace extensions
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index 55fdaaae2..5f608b4 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -114,7 +114,7 @@ !theme_info.custom_background_url.is_empty(); if (theme_info.logo_alternate && !has_background_image) { logo_color = GetContrastingColorForBackground(theme_info.background_color, - /*luminosity_change=*/0.4f); + /*luminosity_change=*/0.3f); } return logo_color;
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 22eb2bf7..2121673 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -13,6 +13,8 @@ "javatests/src/org/chromium/chrome/test/pagecontroller/controllers/first_run/SyncController.java", "javatests/src/org/chromium/chrome/test/pagecontroller/controllers/first_run/TOSController.java", "javatests/src/org/chromium/chrome/test/pagecontroller/controllers/notifications/DownloadNotificationController.java", + "javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ArticleActionsMenu.java", + "javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ArticleCardController.java", "javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ChromeMenu.java", "javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/IncognitoNewTabPageController.java", "javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/NewTabPageController.java", @@ -38,6 +40,7 @@ "//base:base_java_test_support", "//chrome/android:chrome_java", "//third_party/android_support_test_runner:runner_java", + "//third_party/guava:guava_android_java", "//third_party/junit", "//third_party/ub-uiautomator:ub_uiautomator_java", ]
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ArticleActionsMenu.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ArticleActionsMenu.java new file mode 100644 index 0000000..4147434 --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ArticleActionsMenu.java
@@ -0,0 +1,77 @@ +// 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.test.pagecontroller.controllers.ntp; + +import com.google.android.libraries.feed.sharedstream.contextmenumanager.R; + +import org.chromium.chrome.test.pagecontroller.controllers.PageController; +import org.chromium.chrome.test.pagecontroller.controllers.urlpage.UrlPage; +import org.chromium.chrome.test.pagecontroller.utils.IUi2Locator; +import org.chromium.chrome.test.pagecontroller.utils.Ui2Locators; + +/** + * Article Actions Menu (long-press on NTP article) Page Controller. + */ +public class ArticleActionsMenu extends PageController { + private static final IUi2Locator LOCATOR_MENU = Ui2Locators.withClassRegex(".*ListView"); + + private static final IUi2Locator LOCATOR_OPEN_NEW_TAB = Ui2Locators.withResEntriesByIndex( + 0, org.chromium.chrome.R.id.title, R.id.feed_simple_list_item); + private static final IUi2Locator LOCATOR_OPEN_INCOGNITO = Ui2Locators.withResEntriesByIndex( + 1, org.chromium.chrome.R.id.title, R.id.feed_simple_list_item); + private static final IUi2Locator LOCATOR_DOWNLOAD_LINK = Ui2Locators.withResEntriesByIndex( + 2, org.chromium.chrome.R.id.title, R.id.feed_simple_list_item); + private static final IUi2Locator LOCATOR_REMOVE = Ui2Locators.withResEntriesByIndex( + 3, org.chromium.chrome.R.id.title, R.id.feed_simple_list_item); + private static final IUi2Locator LOCATOR_LEARN_MORE = Ui2Locators.withResEntriesByIndex( + 4, org.chromium.chrome.R.id.title, R.id.feed_simple_list_item); + + static private ArticleActionsMenu sInstance = new ArticleActionsMenu(); + private ArticleActionsMenu() {} + static public ArticleActionsMenu getInstance() { + return sInstance; + } + + @Override + public boolean isCurrentPageThis() { + return mLocatorHelper.isOnScreen(LOCATOR_LEARN_MORE); + } + + public UrlPage clickOpenNewTab() { + mUtils.click(LOCATOR_OPEN_NEW_TAB); + UrlPage inst = UrlPage.getInstance(); + inst.verify(); + return inst; + } + + public UrlPage clickOpenIncognitoTab() { + mUtils.click(LOCATOR_OPEN_INCOGNITO); + UrlPage inst = UrlPage.getInstance(); + inst.verify(); + return inst; + } + + public void clickDownloadLink() { + mUtils.click(LOCATOR_DOWNLOAD_LINK); + } + + public NewTabPageController clickRemoveArticle() { + mUtils.click(LOCATOR_REMOVE); + NewTabPageController inst = NewTabPageController.getInstance(); + inst.verify(); + return inst; + } + + public void clickLearnMore() { + mUtils.click(LOCATOR_LEARN_MORE); + } + + public NewTabPageController dismiss() { + mUtils.clickOutsideOf(LOCATOR_MENU); + NewTabPageController inst = NewTabPageController.getInstance(); + inst.verify(); + return inst; + } +}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ArticleCardController.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ArticleCardController.java new file mode 100644 index 0000000..56534220 --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/ArticleCardController.java
@@ -0,0 +1,202 @@ +// 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.test.pagecontroller.controllers.ntp; + +import static org.chromium.chrome.test.pagecontroller.utils.Ui2Locators.withText; +import static org.chromium.chrome.test.pagecontroller.utils.Ui2Locators.withTextRegex; + +import android.support.test.uiautomator.UiObject2; + +import com.google.common.base.Joiner; + +import org.chromium.chrome.R; +import org.chromium.chrome.test.pagecontroller.controllers.ElementController; +import org.chromium.chrome.test.pagecontroller.utils.IUi2Locator; +import org.chromium.chrome.test.pagecontroller.utils.Ui2Locators; +import org.chromium.chrome.test.pagecontroller.utils.UiLocationException; +import org.chromium.chrome.test.pagecontroller.utils.UiLocatorHelper; + +import java.util.List; +import java.util.Objects; + +/** + * NTP Article Element Controller. + */ +public class ArticleCardController extends ElementController { + // Implementation type of the article card. + public enum ImplementationType { ZINE, FEED }; + + /** + * Represents a single article, can be used by the NewTabPageController + * to perform actions. + */ + static public class Info { + private final String mHeadline, mPublisher, mAge; + private final ImplementationType mImplType; + + public Info(String headline, String publisher, String age, + ImplementationType implementationType) { + mHeadline = headline; + mPublisher = publisher; + mAge = age; + mImplType = implementationType; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Info)) return false; + Info that = (Info) o; + return Objects.equals(mHeadline, that.mHeadline) + && Objects.equals(mPublisher, that.mPublisher) + && Objects.equals(mAge, that.mAge) && mImplType == that.mImplType; + } + + @Override + public int hashCode() { + return Objects.hash(mHeadline, mPublisher, mAge, mImplType); + } + + @Override + public String toString() { + return "ArticleCardController{" + + "mHeadline='" + mHeadline + '\'' + ", mPublisher='" + mPublisher + '\'' + + ", mAge='" + mAge + '\'' + ", mImplementation=" + mImplType + '}'; + } + + public String getHeadline() { + return mHeadline; + } + + public String getPublisher() { + return mPublisher; + } + + public String getAge() { + return mAge; + } + + public ImplementationType getImplementationType() { + return mImplType; + } + } + + private static abstract class ArticleImpl { + abstract public List<Info> parseScreenForArticles(UiLocatorHelper locatorHelper); + abstract public IUi2Locator getLocator(Info cardInfo); + protected List<Info> parseScreenForArticles(final UiLocatorHelper locatorHelper, + final ImplementationType implementationType, final IUi2Locator cardsLocator, + final IUi2Locator headlineLocator, final IUi2Locator publisherLocator, + final IUi2Locator ageLocator) { + return locatorHelper.getCustomElements( + cardsLocator, new UiLocatorHelper.CustomElementMaker<Info>() { + @Override + public Info makeElement(UiObject2 articleCard, boolean isLastAttempt) { + String headline = + locatorHelper.getOneTextImmediate(headlineLocator, articleCard); + String publisher = locatorHelper.getOneTextImmediate( + publisherLocator, articleCard); + String age = locatorHelper.getOneTextImmediate(ageLocator, articleCard); + if (headline != null && publisher != null && age != null) { + return new Info(headline, publisher, age, implementationType); + } else if (isLastAttempt) { + return null; + } else { + if (headline == null) + throw UiLocationException.newInstance( + "Headline not found", headlineLocator, articleCard); + else if (publisher == null) + throw UiLocationException.newInstance( + "Publisher not found", publisherLocator, articleCard); + else + throw UiLocationException.newInstance( + "Age not found", ageLocator, articleCard); + } + } + }); + } + } + + private static class FeedArticleImpl extends ArticleImpl { + private static final IUi2Locator LOCATOR_NON_EMPTY_STRING = withTextRegex(".+"); + private static final IUi2Locator LOCATOR_CARDS = Ui2Locators.withPath( + Ui2Locators.withResEntries(R.id.content), + Ui2Locators.withResEntries(com.google.android.libraries.feed.basicstream.R.id + .feed_stream_recycler_view), + Ui2Locators.withResEntries(com.google.android.libraries.feed.basicstream.internal + .viewholders.R.id.feed_content_card)); + private static final IUi2Locator LOCATOR_HEADLINE = + Ui2Locators.withPath(Ui2Locators.withChildIndex(0, 6), LOCATOR_NON_EMPTY_STRING); + private static final IUi2Locator LOCATOR_PUBLISHER = + Ui2Locators.withPath(Ui2Locators.withChildIndex(0, 5), + Ui2Locators.withChildIndex(1, 2), LOCATOR_NON_EMPTY_STRING); + private static final IUi2Locator LOCATOR_AGE = Ui2Locators.withPath( + Ui2Locators.withChildIndex(0, 5), Ui2Locators.withChildIndex(1), + Ui2Locators.withChildIndex(2), LOCATOR_NON_EMPTY_STRING); + @Override + public List<Info> parseScreenForArticles(UiLocatorHelper locatorHelper) { + return parseScreenForArticles(locatorHelper, ImplementationType.FEED, LOCATOR_CARDS, + LOCATOR_HEADLINE, LOCATOR_PUBLISHER, LOCATOR_AGE); + } + @Override + public IUi2Locator getLocator(Info cardInfo) { + return Ui2Locators.withPath(LOCATOR_HEADLINE, withText(cardInfo.getHeadline())); + } + } + + private static class ZineArticleImpl extends ArticleImpl { + private static final IUi2Locator LOCATOR_CARDS = + Ui2Locators.withPath(Ui2Locators.withResEntries(R.id.content), + Ui2Locators.withResEntries(R.id.card_contents)); + private static final IUi2Locator LOCATOR_HEADLINE = + Ui2Locators.withResEntries(R.id.article_headline); + private static final IUi2Locator LOCATOR_PUBLISHER = + Ui2Locators.withResEntries(R.id.article_publisher); + private static final IUi2Locator LOCATOR_AGE = Ui2Locators.withResEntries(R.id.article_age); + @Override + public List<Info> parseScreenForArticles(UiLocatorHelper locatorHelper) { + return parseScreenForArticles(locatorHelper, ImplementationType.ZINE, LOCATOR_CARDS, + LOCATOR_HEADLINE, LOCATOR_PUBLISHER, LOCATOR_AGE); + } + @Override + public IUi2Locator getLocator(Info cardInfo) { + return Ui2Locators.withPath(LOCATOR_HEADLINE, withText(cardInfo.getHeadline())); + } + } + + private static ArticleCardController sInstance = new ArticleCardController(); + private ArticleImpl mFeedImpl, mZineImpl; + private ArticleCardController() { + mFeedImpl = new FeedArticleImpl(); + mZineImpl = new ZineArticleImpl(); + } + + public static ArticleCardController getInstance() { + return sInstance; + } + + public IUi2Locator getLocator(Info cardInfo) { + return getCurrentImplementation(cardInfo.getImplementationType()).getLocator(cardInfo); + } + + public List<Info> parseScreenForArticles(final ImplementationType cardImplementationType) { + return getCurrentImplementation(cardImplementationType) + .parseScreenForArticles(mLocatorHelper); + } + + public String articlesToString(List<Info> cards) { + return Joiner.on("\n").join(cards); + } + + private ArticleImpl getCurrentImplementation(ImplementationType implementationType) { + switch (implementationType) { + case FEED: + return mFeedImpl; + case ZINE: + return mZineImpl; + } + throw new IllegalArgumentException("Unknown implementation type" + implementationType); + } +}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/NewTabPageController.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/NewTabPageController.java index 7375b3d..27120579 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/NewTabPageController.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/NewTabPageController.java
@@ -57,16 +57,26 @@ com.google.android.libraries.feed.basicstream.R.id.feed_stream_recycler_view, R.id.card_contents); + private ArticleCardController mAriticleCardController; private SuggestionTileController mSuggestionsTileController; private static final NewTabPageController sInstance = new NewTabPageController(); private NewTabPageController() { + mAriticleCardController = ArticleCardController.getInstance(); mSuggestionsTileController = SuggestionTileController.getInstance(); } public static NewTabPageController getInstance() { return sInstance; } + public ArticleCardController.ImplementationType getArticleImplementationType() { + if (mLocatorHelper.isOnScreen(LOCATOR_FEED_STREAM_RECYCLER_VIEW)) { + return ArticleCardController.ImplementationType.FEED; + } else { + return ArticleCardController.ImplementationType.ZINE; + } + } + /** * Hide articles if shown, and vice-versa. This will cause page to scroll to where the * show/hide articles button is visible. @@ -155,6 +165,10 @@ } } + public List<ArticleCardController.Info> getAllLoadedArticles() { + return getAllLoadedArticles(getArticleImplementationType()); + } + /** * Get all suggestion tiles. This will cause the page to scroll to the top. * @return List of suggestion infos, possibly empty. @@ -167,11 +181,52 @@ } /** + * Get all loaded articles. This will cause the page to scroll to top then down to the bottom. + * @param implementationType The article implementation type, FEED or ZINE. + * @return List of article card infos, this is a list to preserve the + * order of the articles as they appeared on the screen. + */ + public List<ArticleCardController.Info> getAllLoadedArticles( + ArticleCardController.ImplementationType implementationType) { + scrollToTop(); + List<ArticleCardController.Info> allArticles = + mAriticleCardController.parseScreenForArticles(implementationType); + do { + scrollTowardsBottom(SCROLL_SWIPE_FRACTION); + List<ArticleCardController.Info> currentArticles = + mAriticleCardController.parseScreenForArticles(implementationType); + for (ArticleCardController.Info article : currentArticles) { + if (!allArticles.contains(article)) { + allArticles.add(article); + } + } + } while (!hasScrolledToBottom()); + + return allArticles; + } + + /** + * Perform the default card action by tapping on it. This will cause the page to scroll to top + * then down to where the article is located (or hit bottom if it isn't found). + * @param article The article info. + * @return UrlPage Controller where the article will be loaded. + */ + public UrlPage clickArticle(ArticleCardController.Info article) { + scrollToTop(); + IUi2Locator locator = ArticleCardController.getInstance().getLocator(article); + mUtils.swipeUpVerticallyUntilFound(locator, LOCATOR_BOTTOM_OF_PAGE); + mUtils.click(locator); + UrlPage inst = UrlPage.getInstance(); + inst.verify(); + return inst; + } + + /** * The default action is the one that gets performed when the user taps on the tile icon * (opens site in a new page). If user long taps, then a menu is shown providing more choices * (not yet implemented). This will cause the page to scroll to the top. */ - public UrlPage performDefaultSuggestionTileAction(SuggestionTileController.Info tile) { + public UrlPage clickSuggestionTile(SuggestionTileController.Info tile) { scrollToTop(); IUi2Locator locator = mSuggestionsTileController.getLocator(tile); mUtils.swipeUpVerticallyUntilFound(locator, LOCATOR_BOTTOM_OF_PAGE); @@ -202,6 +257,16 @@ return inst; } + public ArticleActionsMenu openArticleContextMenu(ArticleCardController.Info card) { + scrollToTop(); + IUi2Locator locator = mAriticleCardController.getLocator(card); + mUtils.swipeUpVerticallyUntilFound(locator, LOCATOR_BOTTOM_OF_PAGE); + mUtils.longClick(locator); + ArticleActionsMenu inst = ArticleActionsMenu.getInstance(); + inst.verify(); + return inst; + } + public UrlPage omniboxSearch(String url) { mUtils.click(LOCATOR_SEARCH_BOX_TEXT); mUtils.setTextAndEnter(LOCATOR_URL_BAR, url);
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc index 3dcca5b..dcc4b2a 100644 --- a/chrome/test/chromedriver/window_commands.cc +++ b/chrome/test/chromedriver/window_commands.cc
@@ -1429,10 +1429,10 @@ } } - int init_x, init_y; - if (!input_state->GetInteger("x", &init_x) || - !input_state->GetInteger("y", &init_y)) - return Status(kUnknownError, "invalid input state"); + int init_x = 0; + int init_y = 0; + input_state->GetInteger("x", &init_x); + input_state->GetInteger("y", &init_y); if (pointer_type == "mouse" || pointer_type == "pen") { longest_mouse_list_size =
diff --git a/chromeos/services/assistant/public/features.cc b/chromeos/services/assistant/public/features.cc index c99d4bd..0ed4fdb71 100644 --- a/chromeos/services/assistant/public/features.cc +++ b/chromeos/services/assistant/public/features.cc
@@ -53,9 +53,6 @@ const base::Feature kEnablePowerManager{"ChromeOSAssistantEnablePowerManager", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kAssistantKeyRemapping{"AssistantKeyRemapping", - base::FEATURE_DISABLED_BY_DEFAULT}; - // Enables sending a screen context request ("What's on my screen?" and // metalayer selection) as a text query. This is as opposed to sending // the request as a contextual cards request. @@ -95,10 +92,6 @@ return base::FeatureList::IsEnabled(kInAssistantNotifications); } -bool IsKeyRemappingEnabled() { - return base::FeatureList::IsEnabled(kAssistantKeyRemapping); -} - bool IsMediaSessionIntegrationEnabled() { return base::FeatureList::IsEnabled(kEnableMediaSessionIntegration); }
diff --git a/chromeos/services/assistant/public/features.h b/chromeos/services/assistant/public/features.h index 5d9960b1..fb5376f 100644 --- a/chromeos/services/assistant/public/features.h +++ b/chromeos/services/assistant/public/features.h
@@ -76,10 +76,6 @@ COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) extern const base::Feature kTimerTicks; -// Enables Assistant key remapping on keyboards. -COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) -extern const base::Feature kAssistantKeyRemapping; - COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsAlarmTimerManagerEnabled(); COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsAppSupportEnabled();
diff --git a/chromeos/services/device_sync/BUILD.gn b/chromeos/services/device_sync/BUILD.gn index cf81320..fdc393d2 100644 --- a/chromeos/services/device_sync/BUILD.gn +++ b/chromeos/services/device_sync/BUILD.gn
@@ -44,6 +44,10 @@ "cryptauth_enrollment_manager_impl.h", "cryptauth_enrollment_result.cc", "cryptauth_enrollment_result.h", + "cryptauth_feature_status_getter.cc", + "cryptauth_feature_status_getter.h", + "cryptauth_feature_status_getter_impl.cc", + "cryptauth_feature_status_getter_impl.h", "cryptauth_feature_type.cc", "cryptauth_feature_type.h", "cryptauth_gcm_manager.cc", @@ -165,10 +169,14 @@ "fake_cryptauth_enrollment_manager.h", "fake_cryptauth_gcm_manager.cc", "fake_cryptauth_gcm_manager.h", + "fake_cryptauth_group_private_key_sharer.cc", + "fake_cryptauth_group_private_key_sharer.h", "fake_cryptauth_key_creator.cc", "fake_cryptauth_key_creator.h", "fake_cryptauth_key_proof_computer.cc", "fake_cryptauth_key_proof_computer.h", + "fake_cryptauth_metadata_syncer.cc", + "fake_cryptauth_metadata_syncer.h", "fake_cryptauth_scheduler.cc", "fake_cryptauth_scheduler.h", "fake_cryptauth_v2_enroller.cc", @@ -216,6 +224,7 @@ "cryptauth_ecies_encryptor_impl_unittest.cc", "cryptauth_enroller_impl_unittest.cc", "cryptauth_enrollment_manager_impl_unittest.cc", + "cryptauth_feature_status_getter_impl_unittest.cc", "cryptauth_gcm_manager_impl_unittest.cc", "cryptauth_group_private_key_sharer_impl_unittest.cc", "cryptauth_key_bundle_unittest.cc",
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_getter.cc b/chromeos/services/device_sync/cryptauth_feature_status_getter.cc new file mode 100644 index 0000000..93b8c53 --- /dev/null +++ b/chromeos/services/device_sync/cryptauth_feature_status_getter.cc
@@ -0,0 +1,39 @@ +// 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 "chromeos/services/device_sync/cryptauth_feature_status_getter.h" + +#include <utility> + +namespace chromeos { + +namespace device_sync { + +CryptAuthFeatureStatusGetter::CryptAuthFeatureStatusGetter() = default; + +CryptAuthFeatureStatusGetter::~CryptAuthFeatureStatusGetter() = default; + +void CryptAuthFeatureStatusGetter::GetFeatureStatuses( + const cryptauthv2::RequestContext& request_context, + const base::flat_set<std::string>& device_ids, + GetFeatureStatusesAttemptFinishedCallback callback) { + // Enforce that GetFeatureStatuses() can only be called once. + DCHECK(!was_get_feature_statuses_called_); + was_get_feature_statuses_called_ = true; + + callback_ = std::move(callback); + + OnAttemptStarted(request_context, device_ids); +} + +void CryptAuthFeatureStatusGetter::OnAttemptFinished( + const IdToFeatureStatusMap& id_to_feature_status_map, + const CryptAuthDeviceSyncResult::ResultCode& device_sync_result_code) { + DCHECK(callback_); + std::move(callback_).Run(id_to_feature_status_map, device_sync_result_code); +} + +} // namespace device_sync + +} // namespace chromeos
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_getter.h b/chromeos/services/device_sync/cryptauth_feature_status_getter.h new file mode 100644 index 0000000..8644a0a3 --- /dev/null +++ b/chromeos/services/device_sync/cryptauth_feature_status_getter.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 CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_FEATURE_STATUS_GETTER_H_ +#define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_FEATURE_STATUS_GETTER_H_ + +#include <map> +#include <string> + +#include "base/callback.h" +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" +#include "base/macros.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" +#include "chromeos/services/device_sync/cryptauth_device_sync_result.h" + +namespace cryptauthv2 { +class RequestContext; +} // namespace cryptauthv2 + +namespace chromeos { + +namespace device_sync { + +// Handles the BatchGetFeatureStatuses portion of the CryptAuth v2 DeviceSync +// protocol. Returns the feature statuses for each input device ID as a map from +// multidevice::SoftwareFeature to multidevice::SoftwareFeatureState. +// +// A CryptAuthFeatureStatusGetter object is designed to be used for only one +// GetFeatureStatuses() call. For a new attempt, a new object should be created. +class CryptAuthFeatureStatusGetter { + public: + using FeatureStatusMap = + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>; + using IdToFeatureStatusMap = base::flat_map<std::string, FeatureStatusMap>; + using GetFeatureStatusesAttemptFinishedCallback = + base::OnceCallback<void(const IdToFeatureStatusMap&, + const CryptAuthDeviceSyncResult::ResultCode&)>; + + virtual ~CryptAuthFeatureStatusGetter(); + + // Starts the BatchGetFeatureStatuses portion of the CryptAuth v2 DeviceSync + // flow, retrieving feature status for |device_ids|. + void GetFeatureStatuses(const cryptauthv2::RequestContext& request_context, + const base::flat_set<std::string>& device_ids, + GetFeatureStatusesAttemptFinishedCallback callback); + + protected: + CryptAuthFeatureStatusGetter(); + + // Implementations should retrieve feature statuses for devices with IDs + // |device_ids|, using CryptAuth's BatchGetFeatureStatuses API, and call + // OnAttemptFinished() with the results. + virtual void OnAttemptStarted( + const cryptauthv2::RequestContext& request_context, + const base::flat_set<std::string>& device_ids) = 0; + + void OnAttemptFinished( + const IdToFeatureStatusMap& id_to_feature_status_map, + const CryptAuthDeviceSyncResult::ResultCode& device_sync_result_code); + + private: + GetFeatureStatusesAttemptFinishedCallback callback_; + bool was_get_feature_statuses_called_ = false; + + DISALLOW_COPY_AND_ASSIGN(CryptAuthFeatureStatusGetter); +}; + +} // namespace device_sync + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_FEATURE_STATUS_GETTER_H_
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_getter_impl.cc b/chromeos/services/device_sync/cryptauth_feature_status_getter_impl.cc new file mode 100644 index 0000000..2952944 --- /dev/null +++ b/chromeos/services/device_sync/cryptauth_feature_status_getter_impl.cc
@@ -0,0 +1,267 @@ +// 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 "chromeos/services/device_sync/cryptauth_feature_status_getter_impl.h" + +#include <array> +#include <utility> + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/no_destructor.h" +#include "base/stl_util.h" +#include "chromeos/components/multidevice/logging/logging.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" +#include "chromeos/services/device_sync/cryptauth_better_together_feature_types.h" +#include "chromeos/services/device_sync/cryptauth_client.h" + +namespace chromeos { + +namespace device_sync { + +namespace { + +// Timeout value for asynchronous operation. +// TODO(https://crbug.com/933656): Tune this value. +constexpr base::TimeDelta kWaitingForBatchGetFeatureStatusesResponseTimeout = + base::TimeDelta::FromSeconds(10); + +constexpr std::array<multidevice::SoftwareFeature, 8> kAllSoftwareFeatures = { + multidevice::SoftwareFeature::kBetterTogetherHost, + multidevice::SoftwareFeature::kBetterTogetherClient, + multidevice::SoftwareFeature::kSmartLockHost, + multidevice::SoftwareFeature::kSmartLockClient, + multidevice::SoftwareFeature::kInstantTetheringHost, + multidevice::SoftwareFeature::kInstantTetheringClient, + multidevice::SoftwareFeature::kMessagesForWebHost, + multidevice::SoftwareFeature::kMessagesForWebClient}; + +CryptAuthDeviceSyncResult::ResultCode +BatchGetFeatureStatusesNetworkRequestErrorToResultCode( + NetworkRequestError error) { + switch (error) { + case NetworkRequestError::kOffline: + return CryptAuthDeviceSyncResult::ResultCode:: + kErrorBatchGetFeatureStatusesApiCallOffline; + case NetworkRequestError::kEndpointNotFound: + return CryptAuthDeviceSyncResult::ResultCode:: + kErrorBatchGetFeatureStatusesApiCallEndpointNotFound; + case NetworkRequestError::kAuthenticationError: + return CryptAuthDeviceSyncResult::ResultCode:: + kErrorBatchGetFeatureStatusesApiCallAuthenticationError; + case NetworkRequestError::kBadRequest: + return CryptAuthDeviceSyncResult::ResultCode:: + kErrorBatchGetFeatureStatusesApiCallBadRequest; + case NetworkRequestError::kResponseMalformed: + return CryptAuthDeviceSyncResult::ResultCode:: + kErrorBatchGetFeatureStatusesApiCallResponseMalformed; + case NetworkRequestError::kInternalServerError: + return CryptAuthDeviceSyncResult::ResultCode:: + kErrorBatchGetFeatureStatusesApiCallInternalServerError; + case NetworkRequestError::kUnknown: + return CryptAuthDeviceSyncResult::ResultCode:: + kErrorBatchGetFeatureStatusesApiCallUnknownError; + } +} + +CryptAuthFeatureStatusGetter::FeatureStatusMap +ConvertFeatureStatusesToSoftwareFeatureMap( + const ::google::protobuf::RepeatedPtrField< + cryptauthv2::DeviceFeatureStatus::FeatureStatus>& feature_statuses, + bool* did_non_fatal_error_occur) { + base::flat_set<multidevice::SoftwareFeature> marked_supported; + base::flat_set<multidevice::SoftwareFeature> marked_enabled; + for (const cryptauthv2::DeviceFeatureStatus::FeatureStatus& status : + feature_statuses) { + // TODO(https://crbug.com/936273): Add metrics to track unknown feature type + // occurrences. + if (!base::Contains(GetBetterTogetherFeatureTypes(), + status.feature_type())) { + PA_LOG(ERROR) << "Unknown feature type: " << status.feature_type(); + *did_non_fatal_error_occur = true; + continue; + } + + multidevice::SoftwareFeature feature = + BetterTogetherFeatureTypeStringToSoftwareFeature(status.feature_type()); + + if (base::Contains(GetSupportedBetterTogetherFeatureTypes(), + status.feature_type()) && + status.enabled()) { + marked_supported.insert(feature); + continue; + } + + if (base::Contains(GetEnabledBetterTogetherFeatureTypes(), + status.feature_type()) && + status.enabled()) { + marked_enabled.insert(feature); + continue; + } + } + + CryptAuthFeatureStatusGetter::FeatureStatusMap feature_states; + for (const multidevice::SoftwareFeature& feature : kAllSoftwareFeatures) { + bool is_marked_supported = base::Contains(marked_supported, feature); + bool is_marked_enabled = base::Contains(marked_enabled, feature); + if (is_marked_supported) { + feature_states[feature] = + is_marked_enabled ? multidevice::SoftwareFeatureState::kEnabled + : multidevice::SoftwareFeatureState::kSupported; + continue; + } + + // TODO(https://crbug.com/936273): Add metrics to track occurrences of + // unsupported features marked as enabled. + if (!is_marked_supported && is_marked_enabled) { + PA_LOG(ERROR) << "SoftwareFeature " << feature << " flagged as enabled " + << "but not supported. Marking unsupported."; + *did_non_fatal_error_occur = true; + } + + feature_states[feature] = multidevice::SoftwareFeatureState::kNotSupported; + } + + return feature_states; +} + +} // namespace + +// static +CryptAuthFeatureStatusGetterImpl::Factory* + CryptAuthFeatureStatusGetterImpl::Factory::test_factory_ = nullptr; + +// static +CryptAuthFeatureStatusGetterImpl::Factory* +CryptAuthFeatureStatusGetterImpl::Factory::Get() { + if (test_factory_) + return test_factory_; + + static base::NoDestructor<CryptAuthFeatureStatusGetterImpl::Factory> factory; + return factory.get(); +} + +// static +void CryptAuthFeatureStatusGetterImpl::Factory::SetFactoryForTesting( + Factory* test_factory) { + test_factory_ = test_factory; +} + +CryptAuthFeatureStatusGetterImpl::Factory::~Factory() = default; + +std::unique_ptr<CryptAuthFeatureStatusGetter> +CryptAuthFeatureStatusGetterImpl::Factory::BuildInstance( + CryptAuthClientFactory* client_factory, + std::unique_ptr<base::OneShotTimer> timer) { + return base::WrapUnique( + new CryptAuthFeatureStatusGetterImpl(client_factory, std::move(timer))); +} + +CryptAuthFeatureStatusGetterImpl::CryptAuthFeatureStatusGetterImpl( + CryptAuthClientFactory* client_factory, + std::unique_ptr<base::OneShotTimer> timer) + : client_factory_(client_factory), timer_(std::move(timer)) { + DCHECK(client_factory); +} + +CryptAuthFeatureStatusGetterImpl::~CryptAuthFeatureStatusGetterImpl() = default; + +void CryptAuthFeatureStatusGetterImpl::OnAttemptStarted( + const cryptauthv2::RequestContext& request_context, + const base::flat_set<std::string>& device_ids) { + cryptauthv2::BatchGetFeatureStatusesRequest request; + request.mutable_context()->CopyFrom(request_context); + *request.mutable_device_ids() = {device_ids.begin(), device_ids.end()}; + *request.mutable_feature_types() = {GetBetterTogetherFeatureTypes().begin(), + GetBetterTogetherFeatureTypes().end()}; + + // TODO(https://crbug.com/936273): Add metrics to track failure rates due to + // async timeouts. + timer_->Start( + FROM_HERE, kWaitingForBatchGetFeatureStatusesResponseTimeout, + base::BindOnce( + &CryptAuthFeatureStatusGetterImpl::OnBatchGetFeatureStatusesTimeout, + base::Unretained(this))); + + cryptauth_client_ = client_factory_->CreateInstance(); + cryptauth_client_->BatchGetFeatureStatuses( + request, + base::Bind( + &CryptAuthFeatureStatusGetterImpl::OnBatchGetFeatureStatusesSuccess, + base::Unretained(this), device_ids), + base::Bind( + &CryptAuthFeatureStatusGetterImpl::OnBatchGetFeatureStatusesFailure, + base::Unretained(this))); +} + +void CryptAuthFeatureStatusGetterImpl::OnBatchGetFeatureStatusesSuccess( + const base::flat_set<std::string>& input_device_ids, + const cryptauthv2::BatchGetFeatureStatusesResponse& feature_response) { + DCHECK(id_to_feature_status_map_.empty()); + + bool did_non_fatal_error_occur = false; + for (const cryptauthv2::DeviceFeatureStatus& device_feature_status : + feature_response.device_feature_statuses()) { + const std::string& id = device_feature_status.device_id(); + + // TODO(https://crbug.com/936273): Log metrics for unrequested devices + // in response. + bool was_id_requested = base::Contains(input_device_ids, id); + if (!was_id_requested) { + PA_LOG(ERROR) << "Unrequested device (ID: " << id + << ") in BatchGetFeatureStatuses response."; + did_non_fatal_error_occur = true; + continue; + } + + // TODO(https://crbug.com/936273): Log metrics for duplicate device IDs. + bool is_duplicate_id = base::Contains(id_to_feature_status_map_, id); + if (is_duplicate_id) { + PA_LOG(ERROR) << "Duplicate device IDs (" << id + << ") in BatchGetFeatureStatuses response."; + did_non_fatal_error_occur = true; + continue; + } + + id_to_feature_status_map_[device_feature_status.device_id()] = + ConvertFeatureStatusesToSoftwareFeatureMap( + device_feature_status.feature_statuses(), + &did_non_fatal_error_occur); + } + + // TODO(https://crbug.com/936273): Log metrics for missing devices. + if (input_device_ids.size() != id_to_feature_status_map_.size()) { + PA_LOG(ERROR) << "Devices missing in BatchGetFeatureStatuses response."; + did_non_fatal_error_occur = true; + } + + CryptAuthDeviceSyncResult::ResultCode result_code = + did_non_fatal_error_occur + ? CryptAuthDeviceSyncResult::ResultCode::kFinishedWithNonFatalErrors + : CryptAuthDeviceSyncResult::ResultCode::kSuccess; + FinishAttempt(result_code); +} + +void CryptAuthFeatureStatusGetterImpl::OnBatchGetFeatureStatusesFailure( + NetworkRequestError error) { + FinishAttempt(BatchGetFeatureStatusesNetworkRequestErrorToResultCode(error)); +} + +void CryptAuthFeatureStatusGetterImpl::OnBatchGetFeatureStatusesTimeout() { + FinishAttempt(CryptAuthDeviceSyncResult::ResultCode:: + kErrorTimeoutWaitingForBatchGetFeatureStatusesResponse); +} + +void CryptAuthFeatureStatusGetterImpl::FinishAttempt( + const CryptAuthDeviceSyncResult::ResultCode& result_code) { + cryptauth_client_.reset(); + timer_->Stop(); + + OnAttemptFinished(id_to_feature_status_map_, result_code); +} + +} // namespace device_sync + +} // namespace chromeos
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_getter_impl.h b/chromeos/services/device_sync/cryptauth_feature_status_getter_impl.h new file mode 100644 index 0000000..f0a7ad9 --- /dev/null +++ b/chromeos/services/device_sync/cryptauth_feature_status_getter_impl.h
@@ -0,0 +1,81 @@ +// 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 CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_FEATURE_STATUS_GETTER_IMPL_H_ +#define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_FEATURE_STATUS_GETTER_IMPL_H_ + +#include <memory> +#include <string> + +#include "base/containers/flat_set.h" +#include "base/macros.h" +#include "base/timer/timer.h" +#include "chromeos/services/device_sync/cryptauth_device_sync_result.h" +#include "chromeos/services/device_sync/cryptauth_feature_status_getter.h" +#include "chromeos/services/device_sync/network_request_error.h" +#include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h" + +namespace chromeos { + +namespace device_sync { + +class CryptAuthClient; +class CryptAuthClientFactory; + +// An implementation of CryptAuthFeatureStatusGetter, using instances of +// CryptAuthClient to make the BatchGetFeatureStatuses API calls to CryptAuth. +// Timeouts are handled internally, so GetFeatureStatuses() is always guaranteed +// to return. +class CryptAuthFeatureStatusGetterImpl : public CryptAuthFeatureStatusGetter { + public: + class Factory { + public: + static Factory* Get(); + static void SetFactoryForTesting(Factory* test_factory); + virtual ~Factory(); + virtual std::unique_ptr<CryptAuthFeatureStatusGetter> BuildInstance( + CryptAuthClientFactory* client_factory, + std::unique_ptr<base::OneShotTimer> timer = + std::make_unique<base::OneShotTimer>()); + + private: + static Factory* test_factory_; + }; + + ~CryptAuthFeatureStatusGetterImpl() override; + + private: + CryptAuthFeatureStatusGetterImpl(CryptAuthClientFactory* client_factory, + std::unique_ptr<base::OneShotTimer> timer); + + // CryptAuthFeatureStatusGetter: + void OnAttemptStarted(const cryptauthv2::RequestContext& request_context, + const base::flat_set<std::string>& device_ids) override; + + void OnBatchGetFeatureStatusesSuccess( + const base::flat_set<std::string>& input_device_ids, + const cryptauthv2::BatchGetFeatureStatusesResponse& feature_response); + void OnBatchGetFeatureStatusesFailure(NetworkRequestError error); + void OnBatchGetFeatureStatusesTimeout(); + + void FinishAttempt(const CryptAuthDeviceSyncResult::ResultCode& result_code); + + IdToFeatureStatusMap id_to_feature_status_map_; + + // The CryptAuthClient for the latest CryptAuth request. The client can only + // be used for one call; therefore, for each API call, a new client needs to + // be generated from |client_factory_|. + std::unique_ptr<CryptAuthClient> cryptauth_client_; + + CryptAuthClientFactory* client_factory_ = nullptr; + std::unique_ptr<base::OneShotTimer> timer_; + + DISALLOW_COPY_AND_ASSIGN(CryptAuthFeatureStatusGetterImpl); +}; + +} // namespace device_sync + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_FEATURE_STATUS_GETTER_IMPL_H_
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_getter_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_feature_status_getter_impl_unittest.cc new file mode 100644 index 0000000..e1062f9 --- /dev/null +++ b/chromeos/services/device_sync/cryptauth_feature_status_getter_impl_unittest.cc
@@ -0,0 +1,416 @@ +// 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 "chromeos/services/device_sync/cryptauth_feature_status_getter_impl.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/containers/flat_set.h" +#include "base/macros.h" +#include "base/no_destructor.h" +#include "base/optional.h" +#include "base/timer/mock_timer.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" +#include "chromeos/services/device_sync/cryptauth_better_together_feature_types.h" +#include "chromeos/services/device_sync/cryptauth_client.h" +#include "chromeos/services/device_sync/cryptauth_device.h" +#include "chromeos/services/device_sync/cryptauth_device_sync_result.h" +#include "chromeos/services/device_sync/cryptauth_key_bundle.h" +#include "chromeos/services/device_sync/cryptauth_v2_device_sync_test_devices.h" +#include "chromeos/services/device_sync/mock_cryptauth_client.h" +#include "chromeos/services/device_sync/network_request_error.h" +#include "chromeos/services/device_sync/proto/cryptauth_common.pb.h" +#include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h" +#include "chromeos/services/device_sync/proto/cryptauth_v2_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace device_sync { + +namespace { + +const char kAccessTokenUsed[] = "access token used by CryptAuthClient"; + +const cryptauthv2::ClientMetadata& GetClientMetadata() { + static const base::NoDestructor<cryptauthv2::ClientMetadata> client_metadata( + cryptauthv2::BuildClientMetadata(0 /* retry_count */, + cryptauthv2::ClientMetadata::PERIODIC)); + return *client_metadata; +} + +const cryptauthv2::RequestContext& GetRequestContext() { + static const base::NoDestructor<cryptauthv2::RequestContext> request_context( + [] { + return cryptauthv2::BuildRequestContext( + CryptAuthKeyBundle::KeyBundleNameEnumToString( + CryptAuthKeyBundle::Name::kDeviceSyncBetterTogether), + GetClientMetadata(), + cryptauthv2::GetClientAppMetadataForTest().instance_id(), + cryptauthv2::GetClientAppMetadataForTest().instance_id_token()); + }()); + + return *request_context; +} + +cryptauthv2::DeviceFeatureStatus ConvertDeviceToDeviceFeatureStatus( + const CryptAuthDevice& device, + const base::flat_set<std::string>& feature_types) { + cryptauthv2::DeviceFeatureStatus device_feature_status; + device_feature_status.set_device_id(device.instance_id()); + for (const std::string& feature_type : feature_types) { + bool is_supported_feature_type = + base::Contains(GetSupportedBetterTogetherFeatureTypes(), feature_type); + + const auto it = device.feature_states.find( + BetterTogetherFeatureTypeStringToSoftwareFeature(feature_type)); + bool is_supported = + it != device.feature_states.end() && + it->second != multidevice::SoftwareFeatureState::kNotSupported; + bool is_enabled = it != device.feature_states.end() && + it->second == multidevice::SoftwareFeatureState::kEnabled; + + cryptauthv2::DeviceFeatureStatus::FeatureStatus* feature_status = + device_feature_status.add_feature_statuses(); + feature_status->set_feature_type(feature_type); + if (is_supported_feature_type) { + feature_status->set_enabled(is_supported); + } else { + EXPECT_TRUE( + base::Contains(GetEnabledBetterTogetherFeatureTypes(), feature_type)); + feature_status->set_enabled(is_enabled); + } + } + + return device_feature_status; +} + +} // namespace + +class DeviceSyncCryptAuthFeatureStatusGetterImplTest + : public testing::Test, + public MockCryptAuthClientFactory::Observer { + protected: + DeviceSyncCryptAuthFeatureStatusGetterImplTest() + : client_factory_(std::make_unique<MockCryptAuthClientFactory>( + MockCryptAuthClientFactory::MockType::MAKE_NICE_MOCKS)) { + client_factory_->AddObserver(this); + } + + ~DeviceSyncCryptAuthFeatureStatusGetterImplTest() override { + client_factory_->RemoveObserver(this); + } + + // testing::Test: + void SetUp() override { + auto mock_timer = std::make_unique<base::MockOneShotTimer>(); + timer_ = mock_timer.get(); + + feature_status_getter_ = + CryptAuthFeatureStatusGetterImpl::Factory::Get()->BuildInstance( + client_factory_.get(), std::move(mock_timer)); + } + + // MockCryptAuthClientFactory::Observer: + void OnCryptAuthClientCreated(MockCryptAuthClient* client) override { + ON_CALL(*client, + BatchGetFeatureStatuses(testing::_, testing::_, testing::_)) + .WillByDefault( + Invoke(this, &DeviceSyncCryptAuthFeatureStatusGetterImplTest:: + OnBatchGetFeatureStatuses)); + + ON_CALL(*client, GetAccessTokenUsed()) + .WillByDefault(testing::Return(kAccessTokenUsed)); + } + + void GetFeatureStatuses(const base::flat_set<std::string>& device_ids) { + feature_status_getter_->GetFeatureStatuses( + GetRequestContext(), device_ids, + base::BindOnce(&DeviceSyncCryptAuthFeatureStatusGetterImplTest:: + OnGetFeatureStatusesComplete, + base::Unretained(this))); + } + + void VerifyBatchGetFeatureStatusesRequest( + const base::flat_set<std::string>& expected_device_ids) { + ASSERT_TRUE(batch_get_feature_statuses_request_); + EXPECT_TRUE(batch_get_feature_statuses_success_callback_); + EXPECT_TRUE(batch_get_feature_statuses_failure_callback_); + + EXPECT_EQ( + GetRequestContext().SerializeAsString(), + batch_get_feature_statuses_request_->context().SerializeAsString()); + EXPECT_EQ(expected_device_ids, + base::flat_set<std::string>( + batch_get_feature_statuses_request_->device_ids().begin(), + batch_get_feature_statuses_request_->device_ids().end())); + EXPECT_EQ(GetBetterTogetherFeatureTypes(), + base::flat_set<std::string>( + batch_get_feature_statuses_request_->feature_types().begin(), + batch_get_feature_statuses_request_->feature_types().end())); + } + + void SendCorrectBatchGetFeatureStatusesResponse( + const base::flat_set<std::string>& device_ids, + const base::flat_set<std::string>& feature_types) { + cryptauthv2::BatchGetFeatureStatusesResponse response; + for (const std::string& device_id : device_ids) { + base::Optional<CryptAuthDevice> device = GetTestDeviceWithId(device_id); + if (!device) + continue; + + response.add_device_feature_statuses()->CopyFrom( + ConvertDeviceToDeviceFeatureStatus(*device, feature_types)); + } + ASSERT_TRUE(batch_get_feature_statuses_success_callback_); + std::move(batch_get_feature_statuses_success_callback_).Run(response); + } + + void SendCustomBatchGetFeatureStatusesResponse( + const cryptauthv2::BatchGetFeatureStatusesResponse& response) { + ASSERT_TRUE(batch_get_feature_statuses_success_callback_); + std::move(batch_get_feature_statuses_success_callback_).Run(response); + } + + void FailBatchGetFeatureStatusesRequest( + const NetworkRequestError& network_request_error) { + ASSERT_TRUE(batch_get_feature_statuses_failure_callback_); + std::move(batch_get_feature_statuses_failure_callback_) + .Run(network_request_error); + } + + void VerifyGetFeatureStatuesResult( + const base::flat_set<std::string>& expected_device_ids, + const CryptAuthDeviceSyncResult::ResultCode& expected_result_code) { + ASSERT_TRUE(device_sync_result_code_); + EXPECT_EQ(expected_device_ids.size(), id_to_feature_status_map_.size()); + EXPECT_EQ(expected_result_code, device_sync_result_code_); + + for (const std::string& id : expected_device_ids) { + const auto it = id_to_feature_status_map_.find(id); + ASSERT_TRUE(it != id_to_feature_status_map_.end()); + EXPECT_EQ(GetTestDeviceWithId(id).feature_states, it->second); + } + } + + base::MockOneShotTimer* timer() { return timer_; } + + private: + void OnBatchGetFeatureStatuses( + const cryptauthv2::BatchGetFeatureStatusesRequest& request, + const CryptAuthClient::BatchGetFeatureStatusesCallback& callback, + const CryptAuthClient::ErrorCallback& error_callback) { + EXPECT_FALSE(batch_get_feature_statuses_request_); + EXPECT_FALSE(batch_get_feature_statuses_success_callback_); + EXPECT_FALSE(batch_get_feature_statuses_failure_callback_); + + batch_get_feature_statuses_request_ = request; + batch_get_feature_statuses_success_callback_ = callback; + batch_get_feature_statuses_failure_callback_ = error_callback; + } + + void OnGetFeatureStatusesComplete( + const CryptAuthFeatureStatusGetter::IdToFeatureStatusMap& + id_to_feature_status_map, + const CryptAuthDeviceSyncResult::ResultCode& device_sync_result_code) { + id_to_feature_status_map_ = id_to_feature_status_map; + device_sync_result_code_ = device_sync_result_code; + } + + base::Optional<cryptauthv2::BatchGetFeatureStatusesRequest> + batch_get_feature_statuses_request_; + CryptAuthClient::BatchGetFeatureStatusesCallback + batch_get_feature_statuses_success_callback_; + CryptAuthClient::ErrorCallback batch_get_feature_statuses_failure_callback_; + + CryptAuthFeatureStatusGetter::IdToFeatureStatusMap id_to_feature_status_map_; + base::Optional<CryptAuthDeviceSyncResult::ResultCode> + device_sync_result_code_; + + std::unique_ptr<MockCryptAuthClientFactory> client_factory_; + base::MockOneShotTimer* timer_; + + std::unique_ptr<CryptAuthFeatureStatusGetter> feature_status_getter_; + + DISALLOW_COPY_AND_ASSIGN(DeviceSyncCryptAuthFeatureStatusGetterImplTest); +}; + +TEST_F(DeviceSyncCryptAuthFeatureStatusGetterImplTest, Success) { + GetFeatureStatuses(GetAllTestDeviceIds()); + + VerifyBatchGetFeatureStatusesRequest(GetAllTestDeviceIds()); + + SendCorrectBatchGetFeatureStatusesResponse(GetAllTestDeviceIds(), + GetBetterTogetherFeatureTypes()); + + VerifyGetFeatureStatuesResult( + GetAllTestDeviceIds(), CryptAuthDeviceSyncResult::ResultCode::kSuccess); +} + +TEST_F(DeviceSyncCryptAuthFeatureStatusGetterImplTest, + FinishedWithNonFatalErrors_UnknownFeatureType) { + base::flat_set<std::string> device_ids = { + GetLocalDeviceMetadataPacketForTest().device_id()}; + GetFeatureStatuses(device_ids); + + VerifyBatchGetFeatureStatusesRequest(device_ids); + + // Include an unknown feature type string in the response. The unknown feature + // type should be ignored. + cryptauthv2::DeviceFeatureStatus status = ConvertDeviceToDeviceFeatureStatus( + GetLocalDeviceForTest(), GetBetterTogetherFeatureTypes()); + status.add_feature_statuses()->set_feature_type("Unknown_feature_type"); + + cryptauthv2::BatchGetFeatureStatusesResponse response; + response.add_device_feature_statuses()->CopyFrom(status); + SendCustomBatchGetFeatureStatusesResponse(response); + + VerifyGetFeatureStatuesResult( + device_ids, + CryptAuthDeviceSyncResult::ResultCode::kFinishedWithNonFatalErrors); +} + +TEST_F(DeviceSyncCryptAuthFeatureStatusGetterImplTest, + FinishedWithNonFatalErrors_UnsupportedFeatureMarkedEnabled) { + base::flat_set<std::string> device_ids = { + GetLocalDeviceMetadataPacketForTest().device_id()}; + GetFeatureStatuses(device_ids); + + VerifyBatchGetFeatureStatusesRequest(device_ids); + + cryptauthv2::DeviceFeatureStatus status = ConvertDeviceToDeviceFeatureStatus( + GetLocalDeviceForTest(), GetBetterTogetherFeatureTypes()); + + // The BetterTogether host feature is not supported for the local device. + EXPECT_EQ(multidevice::SoftwareFeatureState::kNotSupported, + GetLocalDeviceForTest() + .feature_states + .find(multidevice::SoftwareFeature::kBetterTogetherHost) + ->second); + + // Ensure that BetterTogether host is marked as not supported in the response. + auto beto_host_supported_it = + std::find_if(status.mutable_feature_statuses()->begin(), + status.mutable_feature_statuses()->end(), + [](const cryptauthv2::DeviceFeatureStatus::FeatureStatus& + feature_status) { + return feature_status.feature_type() == + kCryptAuthFeatureTypeBetterTogetherHostSupported; + }); + EXPECT_FALSE(beto_host_supported_it->enabled()); + + // Erroneously mark the BetterTogether host feature state as enabled in the + // response though it is not supported. + auto beto_host_enabled_it = + std::find_if(status.mutable_feature_statuses()->begin(), + status.mutable_feature_statuses()->end(), + [](const cryptauthv2::DeviceFeatureStatus::FeatureStatus& + feature_status) { + return feature_status.feature_type() == + kCryptAuthFeatureTypeBetterTogetherHostEnabled; + }); + beto_host_enabled_it->set_enabled(true); + + cryptauthv2::BatchGetFeatureStatusesResponse response; + response.add_device_feature_statuses()->CopyFrom(status); + SendCustomBatchGetFeatureStatusesResponse(response); + + // The final output BetterTogether host state should continue to be + // unsupported for the local device. + VerifyGetFeatureStatuesResult( + device_ids, + CryptAuthDeviceSyncResult::ResultCode::kFinishedWithNonFatalErrors); +} + +TEST_F(DeviceSyncCryptAuthFeatureStatusGetterImplTest, + FinishedWithNonFatalErrors_UnrequestedDevicesInResponse) { + base::flat_set<std::string> requested_device_ids = { + GetLocalDeviceMetadataPacketForTest().device_id()}; + GetFeatureStatuses(requested_device_ids); + + VerifyBatchGetFeatureStatusesRequest(requested_device_ids); + + // Include features statuses for unrequested devices. These extra devices + // should be ignored. + SendCorrectBatchGetFeatureStatusesResponse(GetAllTestDeviceIds(), + GetBetterTogetherFeatureTypes()); + + VerifyGetFeatureStatuesResult( + requested_device_ids, + CryptAuthDeviceSyncResult::ResultCode::kFinishedWithNonFatalErrors); +} + +TEST_F(DeviceSyncCryptAuthFeatureStatusGetterImplTest, + FinishedWithNonFatalErrors_DuplicateDeviceIdsInResponse) { + base::flat_set<std::string> requested_device_ids = { + GetLocalDeviceMetadataPacketForTest().device_id()}; + GetFeatureStatuses(requested_device_ids); + + VerifyBatchGetFeatureStatusesRequest(requested_device_ids); + + // Send duplicate local device entries in the response. These duplicate + // entries should be ignored. + cryptauthv2::DeviceFeatureStatus status = ConvertDeviceToDeviceFeatureStatus( + GetLocalDeviceForTest(), GetBetterTogetherFeatureTypes()); + cryptauthv2::BatchGetFeatureStatusesResponse response; + response.add_device_feature_statuses()->CopyFrom(status); + response.add_device_feature_statuses()->CopyFrom(status); + SendCustomBatchGetFeatureStatusesResponse(response); + + VerifyGetFeatureStatuesResult( + requested_device_ids, + CryptAuthDeviceSyncResult::ResultCode::kFinishedWithNonFatalErrors); +} + +TEST_F(DeviceSyncCryptAuthFeatureStatusGetterImplTest, + FinishedWithNonFatalErrors_DevicesMissingInResponse) { + GetFeatureStatuses(GetAllTestDeviceIds()); + + VerifyBatchGetFeatureStatusesRequest(GetAllTestDeviceIds()); + + // Send feature statuses for only one of the three requested devices. + base::flat_set<std::string> returned_device_ids = { + GetLocalDeviceMetadataPacketForTest().device_id()}; + SendCorrectBatchGetFeatureStatusesResponse(returned_device_ids, + GetBetterTogetherFeatureTypes()); + + VerifyGetFeatureStatuesResult( + returned_device_ids, + CryptAuthDeviceSyncResult::ResultCode::kFinishedWithNonFatalErrors); +} + +TEST_F(DeviceSyncCryptAuthFeatureStatusGetterImplTest, + Failure_Timeout_BatchGetFeatureStatusesResponse) { + GetFeatureStatuses(GetAllTestDeviceIds()); + + VerifyBatchGetFeatureStatusesRequest(GetAllTestDeviceIds()); + + timer()->Fire(); + + VerifyGetFeatureStatuesResult( + {} /* expected_device_ids */, + CryptAuthDeviceSyncResult::ResultCode:: + kErrorTimeoutWaitingForBatchGetFeatureStatusesResponse); +} + +TEST_F(DeviceSyncCryptAuthFeatureStatusGetterImplTest, + Failure_ApiCall_BatchGetFeatureStatuses) { + GetFeatureStatuses(GetAllTestDeviceIds()); + + VerifyBatchGetFeatureStatusesRequest(GetAllTestDeviceIds()); + + FailBatchGetFeatureStatusesRequest(NetworkRequestError::kBadRequest); + + VerifyGetFeatureStatuesResult( + {} /* expected_device_ids */, + CryptAuthDeviceSyncResult::ResultCode:: + kErrorBatchGetFeatureStatusesApiCallBadRequest); +} + +} // namespace device_sync + +} // namespace chromeos
diff --git a/chromeos/services/device_sync/fake_cryptauth_group_private_key_sharer.cc b/chromeos/services/device_sync/fake_cryptauth_group_private_key_sharer.cc new file mode 100644 index 0000000..c62a86d0 --- /dev/null +++ b/chromeos/services/device_sync/fake_cryptauth_group_private_key_sharer.cc
@@ -0,0 +1,57 @@ +// 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 "chromeos/services/device_sync/fake_cryptauth_group_private_key_sharer.h" + +#include "chromeos/services/device_sync/cryptauth_key.h" + +namespace chromeos { + +namespace device_sync { + +FakeCryptAuthGroupPrivateKeySharer::FakeCryptAuthGroupPrivateKeySharer() = + default; + +FakeCryptAuthGroupPrivateKeySharer::~FakeCryptAuthGroupPrivateKeySharer() = + default; + +void FakeCryptAuthGroupPrivateKeySharer::FinishAttempt( + const CryptAuthDeviceSyncResult::ResultCode& device_sync_result_code) { + DCHECK(request_context_); + DCHECK(group_key_); + DCHECK(id_to_encrypting_key_map_); + + OnAttemptFinished(device_sync_result_code); +} + +void FakeCryptAuthGroupPrivateKeySharer::OnAttemptStarted( + const cryptauthv2::RequestContext& request_context, + const CryptAuthKey& group_key, + const IdToEncryptingKeyMap& id_to_encrypting_key_map) { + request_context_ = request_context; + group_key_ = std::make_unique<CryptAuthKey>(group_key); + id_to_encrypting_key_map_ = id_to_encrypting_key_map; +} + +FakeCryptAuthGroupPrivateKeySharerFactory:: + FakeCryptAuthGroupPrivateKeySharerFactory() = default; + +FakeCryptAuthGroupPrivateKeySharerFactory:: + ~FakeCryptAuthGroupPrivateKeySharerFactory() = default; + +std::unique_ptr<CryptAuthGroupPrivateKeySharer> +FakeCryptAuthGroupPrivateKeySharerFactory::BuildInstance( + CryptAuthClientFactory* client_factory, + std::unique_ptr<base::OneShotTimer> timer) { + last_client_factory_ = client_factory; + + auto instance = std::make_unique<FakeCryptAuthGroupPrivateKeySharer>(); + instances_.push_back(instance.get()); + + return instance; +} + +} // namespace device_sync + +} // namespace chromeos
diff --git a/chromeos/services/device_sync/fake_cryptauth_group_private_key_sharer.h b/chromeos/services/device_sync/fake_cryptauth_group_private_key_sharer.h new file mode 100644 index 0000000..e5ddd8c --- /dev/null +++ b/chromeos/services/device_sync/fake_cryptauth_group_private_key_sharer.h
@@ -0,0 +1,97 @@ +// 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 CHROMEOS_SERVICES_DEVICE_SYNC_FAKE_CRYPTAUTH_GROUP_PRIVATE_KEY_SHARER_H_ +#define CHROMEOS_SERVICES_DEVICE_SYNC_FAKE_CRYPTAUTH_GROUP_PRIVATE_KEY_SHARER_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "base/optional.h" +#include "base/timer/timer.h" +#include "chromeos/services/device_sync/cryptauth_device_sync_result.h" +#include "chromeos/services/device_sync/cryptauth_group_private_key_sharer.h" +#include "chromeos/services/device_sync/cryptauth_group_private_key_sharer_impl.h" +#include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h" + +namespace chromeos { +namespace device_sync { + +class CryptAuthClientFactory; +class CryptAuthKey; + +class FakeCryptAuthGroupPrivateKeySharer + : public CryptAuthGroupPrivateKeySharer { + public: + FakeCryptAuthGroupPrivateKeySharer(); + ~FakeCryptAuthGroupPrivateKeySharer() override; + + // The RequestContext passed to ShareGroupPrivateKey(). Returns null if + // ShareGroupPrivateKey() has not been called yet. + const base::Optional<cryptauthv2::RequestContext>& request_context() const { + return request_context_; + } + + // The group key passed to ShareGroupPrivateKey(). Returns null if + // ShareGroupPrivateKey() has not been called yet. + const CryptAuthKey* group_key() const { return group_key_.get(); } + + // The device ID to encrypting key map passed to ShareGroupPrivateKey(). + // Returns null if ShareGroupPrivateKey() has not been called yet. + const base::Optional<IdToEncryptingKeyMap>& id_to_encrypting_key_map() const { + return id_to_encrypting_key_map_; + } + + void FinishAttempt( + const CryptAuthDeviceSyncResult::ResultCode& device_sync_result_code); + + private: + // CryptAuthGroupPrivateKeySharer: + void OnAttemptStarted( + const cryptauthv2::RequestContext& request_context, + const CryptAuthKey& group_key, + const IdToEncryptingKeyMap& id_to_encrypting_key_map) override; + + base::Optional<cryptauthv2::RequestContext> request_context_; + std::unique_ptr<CryptAuthKey> group_key_; + base::Optional<IdToEncryptingKeyMap> id_to_encrypting_key_map_; + + DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthGroupPrivateKeySharer); +}; + +class FakeCryptAuthGroupPrivateKeySharerFactory + : public CryptAuthGroupPrivateKeySharerImpl::Factory { + public: + FakeCryptAuthGroupPrivateKeySharerFactory(); + ~FakeCryptAuthGroupPrivateKeySharerFactory() override; + + // Returns a vector of all FakeCryptAuthGroupPrivateKeySharer instances + // created by BuildInstance(). + const std::vector<FakeCryptAuthGroupPrivateKeySharer*>& instances() const { + return instances_; + } + + // Returns the most recent CryptAuthClientFactory input into BuildInstance(). + const CryptAuthClientFactory* last_client_factory() const { + return last_client_factory_; + } + + private: + // CryptAuthGroupPrivateKeySharerImpl::Factory: + std::unique_ptr<CryptAuthGroupPrivateKeySharer> BuildInstance( + CryptAuthClientFactory* client_factory, + std::unique_ptr<base::OneShotTimer> timer = nullptr) override; + + std::vector<FakeCryptAuthGroupPrivateKeySharer*> instances_; + CryptAuthClientFactory* last_client_factory_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthGroupPrivateKeySharerFactory); +}; + +} // namespace device_sync + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_DEVICE_SYNC_FAKE_CRYPTAUTH_GROUP_PRIVATE_KEY_SHARER_H_
diff --git a/chromeos/services/device_sync/fake_cryptauth_metadata_syncer.cc b/chromeos/services/device_sync/fake_cryptauth_metadata_syncer.cc new file mode 100644 index 0000000..9d38f99 --- /dev/null +++ b/chromeos/services/device_sync/fake_cryptauth_metadata_syncer.cc
@@ -0,0 +1,58 @@ +// 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 "chromeos/services/device_sync/fake_cryptauth_metadata_syncer.h" + +namespace chromeos { + +namespace device_sync { + +FakeCryptAuthMetadataSyncer::FakeCryptAuthMetadataSyncer() = default; + +FakeCryptAuthMetadataSyncer::~FakeCryptAuthMetadataSyncer() = default; + +void FakeCryptAuthMetadataSyncer::FinishAttempt( + const IdToDeviceMetadataPacketMap& id_to_device_metadata_packet_map, + std::unique_ptr<CryptAuthKey> new_group_key, + const base::Optional<cryptauthv2::EncryptedGroupPrivateKey>& + encrypted_group_private_key, + const CryptAuthDeviceSyncResult& device_sync_result) { + DCHECK(request_context_); + DCHECK(local_device_metadata_); + DCHECK(initial_group_key_); + + OnAttemptFinished(id_to_device_metadata_packet_map, std::move(new_group_key), + encrypted_group_private_key, device_sync_result); +} + +void FakeCryptAuthMetadataSyncer::OnAttemptStarted( + const cryptauthv2::RequestContext& request_context, + const cryptauthv2::BetterTogetherDeviceMetadata& local_device_metadata, + const CryptAuthKey* initial_group_key) { + request_context_ = request_context; + local_device_metadata_ = local_device_metadata; + initial_group_key_ = initial_group_key; +} + +FakeCryptAuthMetadataSyncerFactory::FakeCryptAuthMetadataSyncerFactory() = + default; + +FakeCryptAuthMetadataSyncerFactory::~FakeCryptAuthMetadataSyncerFactory() = + default; + +std::unique_ptr<CryptAuthMetadataSyncer> +FakeCryptAuthMetadataSyncerFactory::BuildInstance( + CryptAuthClientFactory* client_factory, + std::unique_ptr<base::OneShotTimer> timer) { + last_client_factory_ = client_factory; + + auto instance = std::make_unique<FakeCryptAuthMetadataSyncer>(); + instances_.push_back(instance.get()); + + return instance; +} + +} // namespace device_sync + +} // namespace chromeos
diff --git a/chromeos/services/device_sync/fake_cryptauth_metadata_syncer.h b/chromeos/services/device_sync/fake_cryptauth_metadata_syncer.h new file mode 100644 index 0000000..af9f471d --- /dev/null +++ b/chromeos/services/device_sync/fake_cryptauth_metadata_syncer.h
@@ -0,0 +1,106 @@ +// 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 CHROMEOS_SERVICES_DEVICE_SYNC_FAKE_CRYPTAUTH_METADATA_SYNCER_H_ +#define CHROMEOS_SERVICES_DEVICE_SYNC_FAKE_CRYPTAUTH_METADATA_SYNCER_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "base/optional.h" +#include "base/timer/timer.h" +#include "chromeos/services/device_sync/cryptauth_metadata_syncer.h" +#include "chromeos/services/device_sync/cryptauth_metadata_syncer_impl.h" +#include "chromeos/services/device_sync/proto/cryptauth_better_together_device_metadata.pb.h" +#include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h" + +namespace chromeos { + +namespace device_sync { + +class CryptAuthClientFactory; +class CryptAuthDeviceSyncResult; +class CryptAuthKey; + +class FakeCryptAuthMetadataSyncer : public CryptAuthMetadataSyncer { + public: + FakeCryptAuthMetadataSyncer(); + ~FakeCryptAuthMetadataSyncer() override; + + // The RequestContext passed to SyncMetadata(). Returns null if + // SyncMetadata() has not been called yet. + const base::Optional<cryptauthv2::RequestContext>& request_context() const { + return request_context_; + } + + // The local device's BetterTogetherDeviceMetadata passed to SyncMetadata(). + // Returns null if SyncMetadata() has not been called yet. + const base::Optional<cryptauthv2::BetterTogetherDeviceMetadata>& + local_device_metadata() const { + return local_device_metadata_; + } + + // The initial group key passed to SyncMetadata(). Returns null if + // SyncMetadata() has not been called yet. + const base::Optional<const CryptAuthKey*>& initial_group_key() const { + return initial_group_key_; + } + + void FinishAttempt( + const IdToDeviceMetadataPacketMap& id_to_device_metadata_packet_map, + std::unique_ptr<CryptAuthKey> new_group_key, + const base::Optional<cryptauthv2::EncryptedGroupPrivateKey>& + encrypted_group_private_key, + const CryptAuthDeviceSyncResult& device_sync_result); + + private: + // CryptAuthMetadataSyncer: + void OnAttemptStarted( + const cryptauthv2::RequestContext& request_context, + const cryptauthv2::BetterTogetherDeviceMetadata& local_device_metadata, + const CryptAuthKey* initial_group_key) override; + + base::Optional<cryptauthv2::RequestContext> request_context_; + base::Optional<cryptauthv2::BetterTogetherDeviceMetadata> + local_device_metadata_; + base::Optional<const CryptAuthKey*> initial_group_key_; + + DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthMetadataSyncer); +}; + +class FakeCryptAuthMetadataSyncerFactory + : public CryptAuthMetadataSyncerImpl::Factory { + public: + FakeCryptAuthMetadataSyncerFactory(); + ~FakeCryptAuthMetadataSyncerFactory() override; + + // Returns a vector of all FakeCryptAuthMetadataSyncer instances created + // by BuildInstance(). + const std::vector<FakeCryptAuthMetadataSyncer*>& instances() const { + return instances_; + } + + // Returns the most recent CryptAuthClientFactory input into BuildInstance(). + const CryptAuthClientFactory* last_client_factory() const { + return last_client_factory_; + } + + private: + // CryptAuthMetadataSyncerImpl::Factory: + std::unique_ptr<CryptAuthMetadataSyncer> BuildInstance( + CryptAuthClientFactory* client_factory, + std::unique_ptr<base::OneShotTimer> timer = nullptr) override; + + std::vector<FakeCryptAuthMetadataSyncer*> instances_; + CryptAuthClientFactory* last_client_factory_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthMetadataSyncerFactory); +}; + +} // namespace device_sync + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_DEVICE_SYNC_FAKE_CRYPTAUTH_METADATA_SYNCER_H_
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm index 55d7f476..fadbcb4 100644 --- a/components/autofill/ios/browser/autofill_agent.mm +++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -45,13 +45,13 @@ #import "components/prefs/ios/pref_observer_bridge.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h" +#include "ios/web/common/url_scheme_util.h" #import "ios/web/public/deprecated/crw_js_injection_receiver.h" #include "ios/web/public/deprecated/url_verification_constants.h" #include "ios/web/public/js_messaging/web_frame.h" #include "ios/web/public/js_messaging/web_frame_util.h" #import "ios/web/public/js_messaging/web_frames_manager.h" #import "ios/web/public/navigation/navigation_context.h" -#include "ios/web/public/url_scheme_util.h" #import "ios/web/public/web_state/web_state.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" #include "ui/gfx/geometry/rect.h"
diff --git a/components/cronet/stale_host_resolver_unittest.cc b/components/cronet/stale_host_resolver_unittest.cc index 1232471..bbe32a619 100644 --- a/components/cronet/stale_host_resolver_unittest.cc +++ b/components/cronet/stale_host_resolver_unittest.cc
@@ -185,8 +185,10 @@ if (dns_client) { inner_resolver->GetManagerForTesting()->SetDnsClientForTesting( std::move(dns_client)); + inner_resolver->GetManagerForTesting()->SetInsecureDnsClientEnabled(true); } else { - inner_resolver->GetManagerForTesting()->SetDnsClientEnabled(false); + inner_resolver->GetManagerForTesting()->SetInsecureDnsClientEnabled( + false); } return inner_resolver; }
diff --git a/components/cronet/third_party/curl_headers/BUILD.gn b/components/cronet/third_party/curl_headers/BUILD.gn new file mode 100644 index 0000000..b97609d --- /dev/null +++ b/components/cronet/third_party/curl_headers/BUILD.gn
@@ -0,0 +1,24 @@ +# 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. + +config("curl_headers_include_config") { + include_dirs = [ "//components/cronet/third_party/curl_headers/include" ] +} + +source_set("curl_headers") { + configs += [ ":curl_headers_include_config" ] + public_configs = [ ":curl_headers_include_config" ] + + public = [ + "include/curl/curl.h", + "include/curl/curlver.h", + "include/curl/easy.h", + "include/curl/mprintf.h", + "include/curl/multi.h", + "include/curl/stdcheaders.h", + "include/curl/system.h", + "include/curl/typecheck-gcc.h", + "include/curl/urlapi.h", + ] +}
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index c27fa41..d3e297e 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -679,7 +679,8 @@ CHECK(net_log) << "All DNS-related experiments require NetLog."; std::unique_ptr<net::HostResolver> host_resolver; net::HostResolver::ManagerOptions host_resolver_manager_options; - host_resolver_manager_options.dns_client_enabled = async_dns_enable; + host_resolver_manager_options.insecure_dns_client_enabled = + async_dns_enable; host_resolver_manager_options.check_ipv6_on_wifi = !disable_ipv6_on_wifi; // TODO(crbug.com/934402): Consider using a shared HostResolverManager for // Cronet HostResolvers.
diff --git a/components/download/internal/common/download_stats.cc b/components/download/internal/common/download_stats.cc index 025a169..1a141f7 100644 --- a/components/download/internal/common/download_stats.cc +++ b/components/download/internal/common/download_stats.cc
@@ -650,8 +650,6 @@ bool unknown_size = total <= 0; int64_t received_kb = received / 1024; int64_t total_kb = total / 1024; - UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedReceivedSizeK", received_kb, - 1, kMaxKb, kBuckets); if (is_parallel_download_enabled) { UMA_HISTOGRAM_CUSTOM_COUNTS( "Download.InterruptedReceivedSizeK.ParallelDownload", received_kb, 1, @@ -668,31 +666,9 @@ } if (delta_bytes == 0) { RecordDownloadCountWithSource(INTERRUPTED_AT_END_COUNT, download_source); - UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.InterruptedAtEndReason", - reason, samples); - if (is_parallelizable) { RecordParallelizableDownloadCount(INTERRUPTED_AT_END_COUNT, is_parallel_download_enabled); - UMA_HISTOGRAM_CUSTOM_ENUMERATION( - "Download.InterruptedAtEndReason.ParallelDownload", reason, - samples); - } - } else if (delta_bytes > 0) { - UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedOverrunBytes", - delta_bytes, 1, kMaxKb, kBuckets); - if (is_parallel_download_enabled) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Download.InterruptedOverrunBytes.ParallelDownload", delta_bytes, 1, - kMaxKb, kBuckets); - } - } else { - UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedUnderrunBytes", - -delta_bytes, 1, kMaxKb, kBuckets); - if (is_parallel_download_enabled) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Download.InterruptedUnderrunBytes.ParallelDownload", -delta_bytes, - 1, kMaxKb, kBuckets); } } }
diff --git a/components/feed/content/feed_offline_host.cc b/components/feed/content/feed_offline_host.cc index fa84beb..54f818a9 100644 --- a/components/feed/content/feed_offline_host.cc +++ b/components/feed/content/feed_offline_host.cc
@@ -121,9 +121,8 @@ void RunSuggestionCallbackWithConversion( SuggestionsProvider::SuggestionCallback suggestions_callback, - std::vector<ContentMetadata> metadataVector) { - std::move(suggestions_callback) - .Run(ConvertMetadataToSuggestions(std::move(metadataVector))); + std::vector<offline_pages::PrefetchSuggestion> metadataVector) { + std::move(suggestions_callback).Run(metadataVector); } } // namespace @@ -136,6 +135,7 @@ prefetch_service_(prefetch_service), on_suggestion_consumed_(on_suggestion_consumed), on_suggestions_shown_(on_suggestions_shown) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(offline_page_model_); DCHECK(prefetch_service_); DCHECK(!on_suggestion_consumed_.is_null()); @@ -143,6 +143,7 @@ } FeedOfflineHost::~FeedOfflineHost() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Safe to call RemoveObserver() even if AddObserver() has not been called. offline_page_model_->RemoveObserver(this); } @@ -150,6 +151,7 @@ void FeedOfflineHost::Initialize( const base::RepeatingClosure& trigger_get_known_content, const NotifyStatusChangeCallback& notify_status_change) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(trigger_get_known_content_.is_null()); DCHECK(!trigger_get_known_content.is_null()); DCHECK(notify_status_change_.is_null()); @@ -168,10 +170,12 @@ } void FeedOfflineHost::SetSuggestionProvider() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); prefetch_service_->SetSuggestionProvider(this); } base::Optional<int64_t> FeedOfflineHost::GetOfflineId(const std::string& url) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto iter = url_hash_to_id_.find(base::Hash(url)); return iter == url_hash_to_id_.end() ? base::Optional<int64_t>() : base::Optional<int64_t>(iter->second); @@ -180,6 +184,7 @@ void FeedOfflineHost::GetOfflineStatus( std::vector<std::string> urls, base::OnceCallback<void(std::vector<std::string>)> callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); UMA_HISTOGRAM_EXACT_LINEAR("ContentSuggestions.Feed.Offline.GetStatusCount", urls.size(), 50); @@ -200,38 +205,42 @@ } void FeedOfflineHost::OnContentRemoved(std::vector<std::string> urls) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (const std::string& url : urls) { prefetch_service_->RemoveSuggestion(GURL(url)); } } void FeedOfflineHost::OnNewContentReceived() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); prefetch_service_->NewSuggestionsAvailable(); } void FeedOfflineHost::OnNoListeners() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); url_hash_to_id_.clear(); } void FeedOfflineHost::OnGetKnownContentDone( std::vector<ContentMetadata> suggestions) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // While |suggestions| are movable, there might be multiple callbacks in - // |pending_known_content_callbacks_|. All but one callback will need to - // receive a full copy of |suggestions|, and the last one will received a - // moved copy. - for (size_t i = 0; i < pending_known_content_callbacks_.size(); i++) { - bool can_move = (i + 1 == pending_known_content_callbacks_.size()); - std::move(pending_known_content_callbacks_[i]) - .Run(can_move ? std::move(suggestions) : suggestions); + // |pending_known_content_callbacks_|. To be safe, copy all the suggestions. + std::vector<offline_pages::PrefetchSuggestion> converted_suggestions = + ConvertMetadataToSuggestions(std::move(suggestions)); + for (auto& callback : pending_known_content_callbacks_) { + RunSuggestionCallbackWithConversion(std::move(callback), + converted_suggestions); } pending_known_content_callbacks_.clear(); } void FeedOfflineHost::GetCurrentArticleSuggestions( SuggestionsProvider::SuggestionCallback suggestions_callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!trigger_get_known_content_.is_null()); - pending_known_content_callbacks_.push_back(base::BindOnce( - &RunSuggestionCallbackWithConversion, std::move(suggestions_callback))); + pending_known_content_callbacks_.emplace_back( + std::move(suggestions_callback)); // Trigger after push_back() in case triggering results in a synchronous // response via OnGetKnownContentDone(). if (pending_known_content_callbacks_.size() <= 1) { @@ -240,19 +249,23 @@ } void FeedOfflineHost::ReportArticleListViewed() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); on_suggestion_consumed_.Run(); } void FeedOfflineHost::ReportArticleViewed(GURL article_url) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); on_suggestions_shown_.Run(); } void FeedOfflineHost::OfflinePageModelLoaded(OfflinePageModel* model) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Ignored. } void FeedOfflineHost::OfflinePageAdded(OfflinePageModel* model, const OfflinePageItem& added_page) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!notify_status_change_.is_null()); const std::string& url = added_page.GetOriginalUrl().spec(); CacheOfflinePageUrlAndId(url, added_page.offline_id); @@ -260,6 +273,7 @@ } void FeedOfflineHost::OfflinePageDeleted(const OfflinePageItem& deleted_page) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!notify_status_change_.is_null()); const std::string& url = deleted_page.url.spec(); EvictOfflinePageUrl(url);
diff --git a/components/feed/content/feed_offline_host.h b/components/feed/content/feed_offline_host.h index 66a9fdf..34b8567c 100644 --- a/components/feed/content/feed_offline_host.h +++ b/components/feed/content/feed_offline_host.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "base/sequenced_task_runner.h" #include "components/feed/core/content_metadata.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/prefetch/suggestions_provider.h" @@ -130,11 +131,14 @@ // Holds all consumers of GetKnownContent(). It is assumed that there's an // outstanding GetKnownContent() if and only if this vector is not empty. - std::vector<GetKnownContentCallback> pending_known_content_callbacks_; + std::vector<SuggestionsProvider::SuggestionCallback> + pending_known_content_callbacks_; // Calls all OfflineStatusListeners with the updated status. NotifyStatusChangeCallback notify_status_change_; + SEQUENCE_CHECKER(sequence_checker_); + base::WeakPtrFactory<FeedOfflineHost> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(FeedOfflineHost);
diff --git a/components/gcm_driver/web_push_metrics.cc b/components/gcm_driver/web_push_metrics.cc index 3e175d1..56d3b44e 100644 --- a/components/gcm_driver/web_push_metrics.cc +++ b/components/gcm_driver/web_push_metrics.cc
@@ -12,4 +12,9 @@ base::UmaHistogramEnumeration("GCM.SendWebPushMessageResult", result); } +void LogSendWebPushMessagePayloadSize(int size) { + // Note: The maximum size accepted by FCM is 4096. + base::UmaHistogramCounts10000("GCM.SendWebPushMessagePayloadSize", size); +} + } // namespace gcm
diff --git a/components/gcm_driver/web_push_metrics.h b/components/gcm_driver/web_push_metrics.h index bbdb5ff0e..52d0aa1b 100644 --- a/components/gcm_driver/web_push_metrics.h +++ b/components/gcm_driver/web_push_metrics.h
@@ -23,6 +23,10 @@ // is sent. void LogSendWebPushMessageResult(SendWebPushMessageResult result); +// Logs the size of message payload to UMA. This should be called right before a +// web push message is sent. +void LogSendWebPushMessagePayloadSize(int size); + } // namespace gcm #endif // COMPONENTS_GCM_DRIVER_WEB_PUSH_METRICS_H_
diff --git a/components/gcm_driver/web_push_sender.cc b/components/gcm_driver/web_push_sender.cc index 506ec5df..2976db5 100644 --- a/components/gcm_driver/web_push_sender.cc +++ b/components/gcm_driver/web_push_sender.cc
@@ -149,6 +149,7 @@ return; } + LogSendWebPushMessagePayloadSize(message.payload.size()); std::unique_ptr<network::SimpleURLLoader> url_loader = BuildURLLoader( fcm_token, message.time_to_live, *auth_header, message.payload); url_loader->DownloadToString(
diff --git a/components/image_fetcher/core/cached_image_fetcher_unittest.cc b/components/image_fetcher/core/cached_image_fetcher_unittest.cc index a6f6448..2323f8bd5 100644 --- a/components/image_fetcher/core/cached_image_fetcher_unittest.cc +++ b/components/image_fetcher/core/cached_image_fetcher_unittest.cc
@@ -53,10 +53,9 @@ constexpr char kImageDataOther[] = "other"; const char kImageFetcherEventHistogramName[] = "ImageFetcher.Events"; -const char kCacheLoadHistogramName[] = - "CachedImageFetcher.ImageLoadFromCacheTime"; +const char kCacheLoadHistogramName[] = "ImageFetcher.ImageLoadFromCacheTime"; const char kNetworkLoadHistogramName[] = - "CachedImageFetcher.ImageLoadFromNetworkTime"; + "ImageFetcher.ImageLoadFromNetworkTime"; } // namespace
diff --git a/components/image_fetcher/core/image_fetcher_metrics_reporter.cc b/components/image_fetcher/core/image_fetcher_metrics_reporter.cc index 9779f5b1..6147b4ea 100644 --- a/components/image_fetcher/core/image_fetcher_metrics_reporter.cc +++ b/components/image_fetcher/core/image_fetcher_metrics_reporter.cc
@@ -20,16 +20,18 @@ constexpr char kEventsHistogram[] = "ImageFetcher.Events"; constexpr char kImageLoadFromCacheHistogram[] = - "CachedImageFetcher.ImageLoadFromCacheTime"; + "ImageFetcher.ImageLoadFromCacheTime"; constexpr char kImageLoadFromCacheJavaHistogram[] = - "CachedImageFetcher.ImageLoadFromCacheTimeJava"; + "ImageFetcher.ImageLoadFromCacheTimeJava"; constexpr char kTotalFetchFromNativeTimeJavaHistogram[] = - "CachedImageFetcher.ImageLoadFromNativeTimeJava"; + "ImageFetcher.ImageLoadFromNativeTimeJava"; constexpr char kImageLoadFromNetworkHistogram[] = - "CachedImageFetcher.ImageLoadFromNetworkTime"; + "ImageFetcher.ImageLoadFromNetworkTime"; constexpr char kImageLoadFromNetworkAfterCacheHitHistogram[] = - "CachedImageFetcher.ImageLoadFromNetworkAfterCacheHit"; -constexpr char kLoadImageMetadata[] = "CachedImageFetcher.LoadImageMetadata"; + "ImageFetcher.ImageLoadFromNetworkAfterCacheHit"; +constexpr char kTimeSinceLastLRUEvictionHistogram[] = + "ImageFetcher.TimeSinceLastCacheLRUEviction"; +constexpr char kLoadImageMetadata[] = "ImageFetcher.LoadImageMetadata"; // Returns a raw pointer to a histogram which is owned base::HistogramBase* GetTimeHistogram(const std::string& histogram_name, @@ -115,8 +117,7 @@ void ImageFetcherMetricsReporter::ReportTimeSinceLastCacheLRUEviction( base::Time start_time) { base::TimeDelta time_delta = base::Time::Now() - start_time; - UMA_HISTOGRAM_TIMES("CachedImageFetcher.TimeSinceLastCacheLRUEviction", - time_delta); + UMA_HISTOGRAM_TIMES(kTimeSinceLastLRUEvictionHistogram, time_delta); } // static
diff --git a/components/image_fetcher/core/image_fetcher_metrics_reporter_unittest.cc b/components/image_fetcher/core/image_fetcher_metrics_reporter_unittest.cc index 5fe1acf..39d15e35 100644 --- a/components/image_fetcher/core/image_fetcher_metrics_reporter_unittest.cc +++ b/components/image_fetcher/core/image_fetcher_metrics_reporter_unittest.cc
@@ -17,18 +17,17 @@ const char kUmaClientNameOther[] = "bar"; const char kImageFetcherEventHistogramName[] = "ImageFetcher.Events"; -const char kCacheLoadHistogramName[] = - "CachedImageFetcher.ImageLoadFromCacheTime"; +const char kCacheLoadHistogramName[] = "ImageFetcher.ImageLoadFromCacheTime"; const char kCacheLoadHistogramNameJava[] = - "CachedImageFetcher.ImageLoadFromCacheTimeJava"; + "ImageFetcher.ImageLoadFromCacheTimeJava"; constexpr char kTotalFetchFromNativeHistogramNameJava[] = - "CachedImageFetcher.ImageLoadFromNativeTimeJava"; + "ImageFetcher.ImageLoadFromNativeTimeJava"; const char kNetworkLoadHistogramName[] = - "CachedImageFetcher.ImageLoadFromNetworkTime"; + "ImageFetcher.ImageLoadFromNetworkTime"; const char kNetworkLoadAfterCacheHitHistogram[] = - "CachedImageFetcher.ImageLoadFromNetworkAfterCacheHit"; + "ImageFetcher.ImageLoadFromNetworkAfterCacheHit"; const char kTimeSinceLastCacheLRUEviction[] = - "CachedImageFetcher.TimeSinceLastCacheLRUEviction"; + "ImageFetcher.TimeSinceLastCacheLRUEviction"; } // namespace
diff --git a/components/ntp_snippets/offline_pages/offline_pages_test_utils.cc b/components/ntp_snippets/offline_pages/offline_pages_test_utils.cc index a892490..e3f0a99b 100644 --- a/components/ntp_snippets/offline_pages/offline_pages_test_utils.cc +++ b/components/ntp_snippets/offline_pages/offline_pages_test_utils.cc
@@ -12,10 +12,8 @@ #include "base/guid.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "components/offline_pages/core/client_policy_controller.h" using offline_pages::ClientId; -using offline_pages::ClientPolicyController; using offline_pages::MultipleOfflinePageItemCallback; using offline_pages::OfflinePageItem; using offline_pages::PageCriteria; @@ -36,10 +34,9 @@ void FakeOfflinePageModel::GetPagesWithCriteria( const PageCriteria& criteria, MultipleOfflinePageItemCallback callback) { - ClientPolicyController controller; MultipleOfflinePageItemResult filtered_result; for (auto& item : items_) { - if (offline_pages::MeetsCriteria(controller, criteria, item)) + if (offline_pages::MeetsCriteria(criteria, item)) filtered_result.emplace_back(item); } std::move(callback).Run(filtered_result);
diff --git a/components/ntp_tiles/icon_cacher_impl.cc b/components/ntp_tiles/icon_cacher_impl.cc index 52a3b5f..49c5e9f87 100644 --- a/components/ntp_tiles/icon_cacher_impl.cc +++ b/components/ntp_tiles/icon_cacher_impl.cc
@@ -152,7 +152,6 @@ const image_fetcher::RequestMetadata& metadata) { if (fetched_image.IsEmpty()) { FinishRequestAndNotifyIconAvailable(site.url, /*newly_available=*/false); - UMA_HISTOGRAM_BOOLEAN("NewTabPage.TileFaviconFetchSuccess.Popular", false); return; } @@ -163,7 +162,6 @@ } SaveIconForSite(site, fetched_image); FinishRequestAndNotifyIconAvailable(site.url, /*newly_available=*/true); - UMA_HISTOGRAM_BOOLEAN("NewTabPage.TileFaviconFetchSuccess.Popular", true); } void IconCacherImpl::SaveAndNotifyDefaultIconForSite( @@ -276,9 +274,6 @@ void IconCacherImpl::OnMostLikelyFaviconDownloaded( const GURL& request_url, favicon_base::GoogleFaviconServerRequestStatus status) { - UMA_HISTOGRAM_ENUMERATION( - "NewTabPage.TileFaviconFetchStatus.Server", status, - favicon_base::GoogleFaviconServerRequestStatus::COUNT); FinishRequestAndNotifyIconAvailable( request_url, status == favicon_base::GoogleFaviconServerRequestStatus::SUCCESS);
diff --git a/components/ntp_tiles/icon_cacher_impl_unittest.cc b/components/ntp_tiles/icon_cacher_impl_unittest.cc index 26f184bf..94e1c2b 100644 --- a/components/ntp_tiles/icon_cacher_impl_unittest.cc +++ b/components/ntp_tiles/icon_cacher_impl_unittest.cc
@@ -195,9 +195,6 @@ WaitForMainThreadTasksToFinish(); EXPECT_FALSE(IconIsCachedFor(site_.url, favicon_base::IconType::kFavicon)); EXPECT_TRUE(IconIsCachedFor(site_.url, favicon_base::IconType::kTouchIcon)); - EXPECT_THAT(histogram_tester.GetAllSamples( - "NewTabPage.TileFaviconFetchSuccess.Popular"), - IsEmpty()); } TEST_F(IconCacherTestPopularSites, LargeNotCachedAndFetchSucceeded) { @@ -217,9 +214,6 @@ loop.Run(); EXPECT_FALSE(IconIsCachedFor(site_.url, favicon_base::IconType::kFavicon)); EXPECT_TRUE(IconIsCachedFor(site_.url, favicon_base::IconType::kTouchIcon)); - EXPECT_THAT(histogram_tester.GetAllSamples( - "NewTabPage.TileFaviconFetchSuccess.Popular"), - ElementsAre(Bucket(/*bucket=*/true, /*count=*/1))); } TEST_F(IconCacherTestPopularSites, SmallNotCachedAndFetchSucceeded) { @@ -257,9 +251,6 @@ WaitForMainThreadTasksToFinish(); EXPECT_FALSE(IconIsCachedFor(site_.url, favicon_base::IconType::kFavicon)); EXPECT_FALSE(IconIsCachedFor(site_.url, favicon_base::IconType::kTouchIcon)); - EXPECT_THAT(histogram_tester.GetAllSamples( - "NewTabPage.TileFaviconFetchSuccess.Popular"), - ElementsAre(Bucket(/*bucket=*/false, /*count=*/1))); } TEST_F(IconCacherTestPopularSites, HandlesEmptyCallbacksNicely) { @@ -274,9 +265,6 @@ EXPECT_FALSE(IconIsCachedFor(site_.url, favicon_base::IconType::kFavicon)); EXPECT_TRUE(IconIsCachedFor(site_.url, favicon_base::IconType::kTouchIcon)); // The histogram gets reported despite empty callbacks. - EXPECT_THAT(histogram_tester.GetAllSamples( - "NewTabPage.TileFaviconFetchSuccess.Popular"), - ElementsAre(Bucket(/*bucket=*/true, /*count=*/1))); } TEST_F(IconCacherTestPopularSites, ProvidesDefaultIconAndSucceedsWithFetching) { @@ -321,11 +309,6 @@ EXPECT_THAT( GetCachedIconFor(site_.url, favicon_base::IconType::kTouchIcon).Size(), Eq(gfx::Size(128, 128))); // Compares dimensions, not objects. - // The histogram gets reported only once (for the downloaded icon, not for the - // default one). - EXPECT_THAT(histogram_tester.GetAllSamples( - "NewTabPage.TileFaviconFetchSuccess.Popular"), - ElementsAre(Bucket(/*bucket=*/true, /*count=*/1))); } TEST_F(IconCacherTestPopularSites, LargeNotCachedAndFetchPerformedOnlyOnce) { @@ -379,9 +362,6 @@ EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kFavicon)); EXPECT_TRUE(IconIsCachedFor(page_url, favicon_base::IconType::kTouchIcon)); - EXPECT_THAT(histogram_tester.GetAllSamples( - "NewTabPage.TileFaviconFetchStatus.Server"), - IsEmpty()); } TEST_F(IconCacherTestMostLikely, NotCachedAndFetchSucceeded) { @@ -413,12 +393,6 @@ loop.Run(); EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kFavicon)); EXPECT_TRUE(IconIsCachedFor(page_url, favicon_base::IconType::kTouchIcon)); - EXPECT_THAT(histogram_tester.GetAllSamples( - "NewTabPage.TileFaviconFetchStatus.Server"), - ElementsAre(Bucket( - /*bucket=*/static_cast<int>( - favicon_base::GoogleFaviconServerRequestStatus::SUCCESS), - /*count=*/1))); } TEST_F(IconCacherTestMostLikely, NotCachedAndFetchFailed) { @@ -448,13 +422,6 @@ EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kFavicon)); EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kTouchIcon)); - EXPECT_THAT(histogram_tester.GetAllSamples( - "NewTabPage.TileFaviconFetchStatus.Server"), - ElementsAre(Bucket( - /*bucket=*/static_cast<int>( - favicon_base::GoogleFaviconServerRequestStatus:: - FAILURE_CONNECTION_ERROR), - /*count=*/1))); } TEST_F(IconCacherTestMostLikely, HandlesEmptyCallbacksNicely) {
diff --git a/components/offline_pages/core/BUILD.gn b/components/offline_pages/core/BUILD.gn index 23d262f..6340993e 100644 --- a/components/offline_pages/core/BUILD.gn +++ b/components/offline_pages/core/BUILD.gn
@@ -20,8 +20,6 @@ "client_id.h", "client_namespace_constants.cc", "client_namespace_constants.h", - "client_policy_controller.cc", - "client_policy_controller.h", "model/add_page_task.cc", "model/add_page_task.h", "model/cleanup_visuals_task.cc", @@ -157,7 +155,6 @@ "archive_validator_unittest.cc", "auto_fetch_unittest.cc", "background_snapshot_controller_unittest.cc", - "client_policy_controller_unittest.cc", "model/add_page_task_unittest.cc", "model/cleanup_visuals_task_unittest.cc", "model/clear_storage_task_unittest.cc", @@ -173,6 +170,7 @@ "model/update_publish_id_task_unittest.cc", "model/visuals_availability_task_unittest.cc", "offline_event_logger_unittest.cc", + "offline_page_client_policy_unittest.cc", "offline_page_feature_unittest.cc", "offline_page_item_utils_unittest.cc", "offline_page_metadata_store_unittest.cc",
diff --git a/components/offline_pages/core/background/pick_request_task.cc b/components/offline_pages/core/background/pick_request_task.cc index 893b545..348acae 100644 --- a/components/offline_pages/core/background/pick_request_task.cc +++ b/components/offline_pages/core/background/pick_request_task.cc
@@ -19,8 +19,8 @@ #include "components/offline_pages/core/background/request_notifier.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/save_page_request.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_clock.h" +#include "components/offline_pages/core/offline_page_client_policy.h" namespace { template <typename T> @@ -42,7 +42,6 @@ PickRequestTask::PickRequestTask( RequestQueueStore* store, OfflinerPolicy* policy, - ClientPolicyController* policy_controller, RequestPickedCallback picked_callback, RequestNotPickedCallback not_picked_callback, RequestCountCallback request_count_callback, @@ -51,7 +50,6 @@ base::circular_deque<int64_t>* prioritized_requests) : store_(store), policy_(policy), - policy_controller_(policy_controller), picked_callback_(std::move(picked_callback)), not_picked_callback_(std::move(not_picked_callback)), request_count_callback_(std::move(request_count_callback)), @@ -134,7 +132,7 @@ available_requests->push_back(*request); if (!RequestConditionsSatisfied(*request)) continue; - if (policy_controller_->GetPolicy(request->client_id().name_space) + if (GetPolicy(request->client_id().name_space) .defer_background_fetch_while_page_is_active) { if (!request->last_attempt_time().is_null() && OfflineTimeNow() - request->last_attempt_time() < kDeferInterval) {
diff --git a/components/offline_pages/core/background/pick_request_task.h b/components/offline_pages/core/background/pick_request_task.h index 88814f3..7332891 100644 --- a/components/offline_pages/core/background/pick_request_task.h +++ b/components/offline_pages/core/background/pick_request_task.h
@@ -18,7 +18,6 @@ namespace offline_pages { -class ClientPolicyController; class OfflinerPolicy; class PickRequestTask; class RequestQueueStore; @@ -49,7 +48,6 @@ PickRequestTask(RequestQueueStore* store, OfflinerPolicy* policy, - ClientPolicyController* policy_controller, RequestPickedCallback picked_callback, RequestNotPickedCallback not_picked_callback, RequestCountCallback request_count_callback, @@ -101,7 +99,6 @@ // Member variables, all pointers are not owned here. RequestQueueStore* store_; OfflinerPolicy* policy_; - ClientPolicyController* policy_controller_; RequestPickedCallback picked_callback_; RequestNotPickedCallback not_picked_callback_; RequestCountCallback request_count_callback_;
diff --git a/components/offline_pages/core/background/pick_request_task_unittest.cc b/components/offline_pages/core/background/pick_request_task_unittest.cc index 41ff45b..88b34e9 100644 --- a/components/offline_pages/core/background/pick_request_task_unittest.cc +++ b/components/offline_pages/core/background/pick_request_task_unittest.cc
@@ -20,7 +20,6 @@ #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/background/test_request_queue_store.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -123,7 +122,6 @@ std::unique_ptr<RequestNotifierStub> notifier_; std::unique_ptr<SavePageRequest> last_picked_; std::unique_ptr<OfflinerPolicy> policy_; - ClientPolicyController policy_controller_; RequestCoordinatorEventLogger event_logger_; std::set<int64_t> disabled_requests_; base::circular_deque<int64_t> prioritized_requests_; @@ -192,7 +190,7 @@ void PickRequestTaskTest::MakePickRequestTask() { DeviceConditions conditions; task_.reset(new PickRequestTask( - &store_, policy_.get(), &policy_controller_, + &store_, policy_.get(), base::BindOnce(&PickRequestTaskTest::RequestPicked, base::Unretained(this)), base::BindOnce(&PickRequestTaskTest::RequestNotPicked,
diff --git a/components/offline_pages/core/background/request_coordinator.cc b/components/offline_pages/core/background/request_coordinator.cc index 508e4690..df0a163b 100644 --- a/components/offline_pages/core/background/request_coordinator.cc +++ b/components/offline_pages/core/background/request_coordinator.cc
@@ -21,8 +21,8 @@ #include "components/offline_pages/core/background/offliner_client.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/save_page_request.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_clock.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_model.h" @@ -279,7 +279,6 @@ policy_(std::move(policy)), queue_(std::move(queue)), scheduler_(std::move(scheduler)), - policy_controller_(new ClientPolicyController()), network_quality_tracker_(network_quality_tracker), network_quality_at_request_start_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN), last_offlining_status_(Offliner::RequestStatus::UNKNOWN), @@ -801,7 +800,7 @@ // Ask request queue to make a new PickRequestTask object, then put it on // the task queue. queue_->PickNextRequest( - policy_.get(), policy_controller_.get(), + policy_.get(), base::BindOnce(&RequestCoordinator::RequestPicked, weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&RequestCoordinator::RequestNotPicked, @@ -921,7 +920,7 @@ RecordStartTimeUMA(request); } const OfflinePageClientPolicy& policy = - policy_controller_->GetPolicy(request.client_id().name_space); + GetPolicy(request.client_id().name_space); if (policy.defer_background_fetch_while_page_is_active && active_tab_info_->DoesActiveTabMatch(request.url())) { queue_->MarkAttemptDeferred( @@ -1181,10 +1180,6 @@ observer.OnNetworkProgress(request, received_bytes); } -ClientPolicyController* RequestCoordinator::GetPolicyController() { - return policy_controller_.get(); -} - void RequestCoordinator::RecordOfflinerResult(const SavePageRequest& request, Offliner::RequestStatus status) { event_logger_.RecordOfflinerResult(request.client_id().name_space, status,
diff --git a/components/offline_pages/core/background/request_coordinator.h b/components/offline_pages/core/background/request_coordinator.h index 92bffaf..bb919ed 100644 --- a/components/offline_pages/core/background/request_coordinator.h +++ b/components/offline_pages/core/background/request_coordinator.h
@@ -40,7 +40,6 @@ class OfflinerPolicy; class Offliner; class SavePageRequest; -class ClientPolicyController; // Coordinates queueing and processing save page later requests. class RequestCoordinator : public KeyedService, @@ -241,8 +240,6 @@ OfflinerPolicy* policy() { return policy_.get(); } - ClientPolicyController* GetPolicyController(); - // Return the state of the request coordinator. RequestCoordinatorState state() { return state_; } @@ -468,8 +465,6 @@ std::unique_ptr<RequestQueue> queue_; // Scheduler. Used to request a callback when network is available. Owned. std::unique_ptr<Scheduler> scheduler_; - // Controller of client policies. Owned. - std::unique_ptr<ClientPolicyController> policy_controller_; // Unowned pointer. Guaranteed to be non-null during the lifetime of |this|. // Must be accessed only on the UI thread. network::NetworkQualityTracker* network_quality_tracker_;
diff --git a/components/offline_pages/core/background/request_queue.cc b/components/offline_pages/core/background/request_queue.cc index 6c10b2c..1a413bf 100644 --- a/components/offline_pages/core/background/request_queue.cc +++ b/components/offline_pages/core/background/request_queue.cc
@@ -131,7 +131,6 @@ void RequestQueue::PickNextRequest( OfflinerPolicy* policy, - ClientPolicyController* policy_controller, PickRequestTask::RequestPickedCallback picked_callback, PickRequestTask::RequestNotPickedCallback not_picked_callback, PickRequestTask::RequestCountCallback request_count_callback, @@ -140,7 +139,7 @@ base::circular_deque<int64_t>* prioritized_requests) { // Using the PickerContext, create a picker task. std::unique_ptr<Task> task(new PickRequestTask( - store_.get(), policy, policy_controller, std::move(picked_callback), + store_.get(), policy, std::move(picked_callback), std::move(not_picked_callback), std::move(request_count_callback), std::move(conditions), disabled_requests, prioritized_requests));
diff --git a/components/offline_pages/core/background/request_queue.h b/components/offline_pages/core/background/request_queue.h index 31c4cf9..e55e1f6 100644 --- a/components/offline_pages/core/background/request_queue.h +++ b/components/offline_pages/core/background/request_queue.h
@@ -30,7 +30,6 @@ namespace offline_pages { class CleanupTaskFactory; -class ClientPolicyController; class RequestQueueStore; // Class responsible for managing save page requests. @@ -130,7 +129,6 @@ // callbacks. void PickNextRequest( OfflinerPolicy* policy, - ClientPolicyController* policy_controller, PickRequestTask::RequestPickedCallback picked_callback, PickRequestTask::RequestNotPickedCallback not_picked_callback, PickRequestTask::RequestCountCallback request_count_callback,
diff --git a/components/offline_pages/core/client_policy_controller.cc b/components/offline_pages/core/client_policy_controller.cc deleted file mode 100644 index e05a7f5..0000000 --- a/components/offline_pages/core/client_policy_controller.cc +++ /dev/null
@@ -1,172 +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/offline_pages/core/client_policy_controller.h" - -#include <utility> - -#include "base/time/time.h" -#include "components/offline_pages/core/client_namespace_constants.h" - -namespace offline_pages { - -OfflinePageClientPolicy* ClientPolicyController::AddTemporaryPolicy( - const std::string& name_space, - const base::TimeDelta& expiration_period) { - auto iter_and_was_inserted_pair = policies_.emplace( - name_space, OfflinePageClientPolicy(name_space, LifetimeType::TEMPORARY)); - DCHECK(iter_and_was_inserted_pair.second) << "Policy was not inserted"; - OfflinePageClientPolicy& policy = (*iter_and_was_inserted_pair.first).second; - policy.expiration_period = expiration_period; - return &policy; -} - -OfflinePageClientPolicy* ClientPolicyController::AddPersistentPolicy( - const std::string& name_space) { - auto iter_and_was_inserted_pair = policies_.emplace( - name_space, - OfflinePageClientPolicy(name_space, LifetimeType::PERSISTENT)); - DCHECK(iter_and_was_inserted_pair.second) << "Policy was not inserted"; - OfflinePageClientPolicy& policy = (*iter_and_was_inserted_pair.first).second; - return &policy; -} - -ClientPolicyController::ClientPolicyController() { - { - OfflinePageClientPolicy* policy = - AddTemporaryPolicy(kBookmarkNamespace, base::TimeDelta::FromDays(7)); - policy->pages_allowed_per_url = 1; - } - { - OfflinePageClientPolicy* policy = - AddTemporaryPolicy(kLastNNamespace, base::TimeDelta::FromDays(30)); - policy->is_restricted_to_tab_from_client_id = true; - } - { - OfflinePageClientPolicy* policy = AddPersistentPolicy(kAsyncNamespace); - policy->is_supported_by_download = true; - } - { - OfflinePageClientPolicy* policy = - AddTemporaryPolicy(kCCTNamespace, base::TimeDelta::FromDays(2)); - policy->pages_allowed_per_url = 1; - policy->requires_specific_user_settings = true; - } - { - OfflinePageClientPolicy* policy = AddPersistentPolicy(kDownloadNamespace); - policy->is_supported_by_download = true; - } - { - OfflinePageClientPolicy* policy = - AddPersistentPolicy(kNTPSuggestionsNamespace); - policy->is_supported_by_download = true; - } - { - OfflinePageClientPolicy* policy = AddTemporaryPolicy( - kSuggestedArticlesNamespace, base::TimeDelta::FromDays(30)); - policy->is_supported_by_download = 1; - policy->is_suggested = true; - } - { - OfflinePageClientPolicy* policy = - AddPersistentPolicy(kBrowserActionsNamespace); - policy->is_supported_by_download = true; - policy->allows_conversion_to_background_file_download = true; - } - { - OfflinePageClientPolicy* policy = AddTemporaryPolicy( - kLivePageSharingNamespace, base::TimeDelta::FromHours(1)); - policy->pages_allowed_per_url = 1; - policy->is_restricted_to_tab_from_client_id = true; - } - { - OfflinePageClientPolicy* policy = - AddTemporaryPolicy(kAutoAsyncNamespace, base::TimeDelta::FromDays(30)); - policy->pages_allowed_per_url = 1; - policy->defer_background_fetch_while_page_is_active = true; - } - - // Fallback policy. - { - OfflinePageClientPolicy* policy = - AddTemporaryPolicy(kDefaultNamespace, base::TimeDelta::FromDays(1)); - policy->page_limit = 10; - policy->pages_allowed_per_url = 1; - } - - for (const auto& policy_item : policies_) { - const std::string& name = policy_item.first; - switch (policy_item.second.lifetime_type) { - case LifetimeType::TEMPORARY: - temporary_namespaces_.push_back(name); - break; - case LifetimeType::PERSISTENT: - persistent_namespaces_.push_back(name); - break; - } - } -} - -ClientPolicyController::~ClientPolicyController() {} - -const OfflinePageClientPolicy& ClientPolicyController::GetPolicy( - const std::string& name_space) const { - const auto& iter = policies_.find(name_space); - if (iter != policies_.end()) - return iter->second; - // Fallback when the namespace isn't defined. - return policies_.at(kDefaultNamespace); -} - -std::vector<std::string> ClientPolicyController::GetAllNamespaces() const { - std::vector<std::string> result; - for (const auto& policy_item : policies_) - result.emplace_back(policy_item.first); - - return result; -} - -bool ClientPolicyController::IsTemporary(const std::string& name_space) const { - return GetPolicy(name_space).lifetime_type == LifetimeType::TEMPORARY; -} - -const std::vector<std::string>& ClientPolicyController::GetTemporaryNamespaces() - const { - return temporary_namespaces_; -} - -bool ClientPolicyController::IsSupportedByDownload( - const std::string& name_space) const { - return GetPolicy(name_space).is_supported_by_download; -} - -bool ClientPolicyController::IsPersistent(const std::string& name_space) const { - return GetPolicy(name_space).lifetime_type == LifetimeType::PERSISTENT; -} - -const std::vector<std::string>& -ClientPolicyController::GetPersistentNamespaces() const { - return persistent_namespaces_; -} - -bool ClientPolicyController::IsRestrictedToTabFromClientId( - const std::string& name_space) const { - return GetPolicy(name_space).is_restricted_to_tab_from_client_id; -} - -bool ClientPolicyController::RequiresSpecificUserSettings( - const std::string& name_space) const { - return GetPolicy(name_space).requires_specific_user_settings; -} - -bool ClientPolicyController::IsSuggested(const std::string& name_space) const { - return GetPolicy(name_space).is_suggested; -} - -bool ClientPolicyController::AllowsConversionToBackgroundFileDownload( - const std::string& name_space) const { - return GetPolicy(name_space).allows_conversion_to_background_file_download; -} - -} // namespace offline_pages
diff --git a/components/offline_pages/core/client_policy_controller.h b/components/offline_pages/core/client_policy_controller.h deleted file mode 100644 index 6d973e8e..0000000 --- a/components/offline_pages/core/client_policy_controller.h +++ /dev/null
@@ -1,83 +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_OFFLINE_PAGES_CORE_CLIENT_POLICY_CONTROLLER_H_ -#define COMPONENTS_OFFLINE_PAGES_CORE_CLIENT_POLICY_CONTROLLER_H_ - -#include <map> -#include <string> -#include <vector> - -#include "components/offline_pages/core/offline_page_client_policy.h" - -namespace offline_pages { - -// This is the class which is a singleton for offline page model -// to get client policies based on namespaces. -class ClientPolicyController { - public: - ClientPolicyController(); - ClientPolicyController(const ClientPolicyController&) = delete; - ~ClientPolicyController(); - - ClientPolicyController& operator=(const ClientPolicyController&) = delete; - - // Get the client policy for |name_space|. - const OfflinePageClientPolicy& GetPolicy(const std::string& name_space) const; - - // Returns a list of all known namespaces. - std::vector<std::string> GetAllNamespaces() const; - - // Returns whether pages for |name_space| are temporary. - bool IsTemporary(const std::string& name_space) const; - - // Returns a list of all temporary namespaces. - const std::vector<std::string>& GetTemporaryNamespaces() const; - - // Returns whether pages for |name_space| persistent. - bool IsPersistent(const std::string& name_space) const; - - // Returns a list of all persistent namespaces. - const std::vector<std::string>& GetPersistentNamespaces() const; - - // Returns whether pages for |name_space| are shown in Download UI. - bool IsSupportedByDownload(const std::string& name_space) const; - - // Returns whether pages for |name_space| should only be opened in a - // specifically assigned tab. - // Note: For this restriction to work offline pages saved to this namespace - // must have the respective tab id set to their ClientId::id field. - bool IsRestrictedToTabFromClientId(const std::string& name_space) const; - - // Returns whether pages for |name_space| can be saved only if specific user - // settings are properly set. See - // OfflinePageClientPolicy::requires_specific_user_settings for details). - bool RequiresSpecificUserSettings(const std::string& name_space) const; - - // Returns whether pages for |name_space| originate from suggested URLs and - // are downloaded on behalf of user. - bool IsSuggested(const std::string& name_space) const; - - // Returns whether we should allow background downloads of pages for - // |name_space| to be converted to regular file downloads. - bool AllowsConversionToBackgroundFileDownload( - const std::string& name_space) const; - - private: - OfflinePageClientPolicy* AddTemporaryPolicy( - const std::string& name_space, - const base::TimeDelta& expiration_period); - OfflinePageClientPolicy* AddPersistentPolicy(const std::string& name_space); - - // The map from name_space to a client policy. Will be generated - // as pre-defined values for now. - std::map<std::string, OfflinePageClientPolicy> policies_; - - std::vector<std::string> temporary_namespaces_; - std::vector<std::string> persistent_namespaces_; -}; - -} // namespace offline_pages - -#endif // COMPONENTS_OFFLINE_PAGES_CORE_CLIENT_POLICY_CONTROLLER_H_
diff --git a/components/offline_pages/core/client_policy_controller_unittest.cc b/components/offline_pages/core/client_policy_controller_unittest.cc index 9d354a2..d8b10aee 100644 --- a/components/offline_pages/core/client_policy_controller_unittest.cc +++ b/components/offline_pages/core/client_policy_controller_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include <algorithm> #include <memory> @@ -25,11 +25,10 @@ class ClientPolicyControllerTest : public testing::Test { public: - ClientPolicyController* controller() { return controller_.get(); } // testing::Test - void SetUp() override; - void TearDown() override; + void SetUp() override {} + void TearDown() override {} protected: void ExpectTemporary(std::string name_space); @@ -39,70 +38,47 @@ bool expectation); void ExpectRequiresSpecificUserSettings(std::string name_space, bool expectation); - - private: - std::unique_ptr<ClientPolicyController> controller_; }; -void ClientPolicyControllerTest::SetUp() { - controller_.reset(new ClientPolicyController()); -} - -void ClientPolicyControllerTest::TearDown() { - controller_.reset(); -} - void ClientPolicyControllerTest::ExpectTemporary(std::string name_space) { - EXPECT_TRUE( - base::Contains(controller()->GetTemporaryNamespaces(), name_space)) + EXPECT_TRUE(base::Contains(GetTemporaryPolicyNamespaces(), name_space)) << "Namespace " << name_space << " had incorrect lifetime type when getting temporary namespaces."; - EXPECT_TRUE(controller()->IsTemporary(name_space)) + EXPECT_EQ(GetPolicy(name_space).lifetime_type, LifetimeType::TEMPORARY) << "Namespace " << name_space << " had incorrect lifetime type setting when directly checking" " if it is temporary."; - EXPECT_FALSE( - base::Contains(controller()->GetPersistentNamespaces(), name_space)) + EXPECT_FALSE(base::Contains(GetPersistentPolicyNamespaces(), name_space)) << "Namespace " << name_space << " had incorrect lifetime type when getting persistent namespaces."; - EXPECT_FALSE(controller()->IsPersistent(name_space)) - << "Namespace " << name_space - << " had incorrect lifetime type setting when directly checking" - " if it is persistent."; } void ClientPolicyControllerTest::ExpectDownloadSupport(std::string name_space, bool expectation) { - EXPECT_EQ(expectation, controller()->IsSupportedByDownload(name_space)) + EXPECT_EQ(expectation, GetPolicy(name_space).is_supported_by_download) << "Namespace " << name_space << " had incorrect download support when directly checking if supported" " by download."; } void ClientPolicyControllerTest::ExpectPersistent(std::string name_space) { - EXPECT_FALSE( - base::Contains(controller()->GetTemporaryNamespaces(), name_space)) + EXPECT_FALSE(base::Contains(GetTemporaryPolicyNamespaces(), name_space)) << "Namespace " << name_space << " had incorrect lifetime type when getting temporary namespaces."; - EXPECT_FALSE(controller()->IsTemporary(name_space)) + EXPECT_EQ(GetPolicy(name_space).lifetime_type, LifetimeType::PERSISTENT) << "Namespace " << name_space << " had incorrect lifetime type setting when directly checking" " if it is temporary."; - EXPECT_TRUE( - base::Contains(controller()->GetPersistentNamespaces(), name_space)) + EXPECT_TRUE(base::Contains(GetPersistentPolicyNamespaces(), name_space)) << "Namespace " << name_space << " had incorrect lifetime type when getting persistent namespaces."; - EXPECT_TRUE(controller()->IsPersistent(name_space)) - << "Namespace " << name_space - << " had incorrect lifetime type setting when directly checking" - " if it is persistent."; } void ClientPolicyControllerTest::ExpectRestrictedToTabFromClientId( std::string name_space, bool expectation) { EXPECT_EQ(expectation, - controller()->IsRestrictedToTabFromClientId(name_space)) + GetPolicy(name_space).is_restricted_to_tab_from_client_id) << "Namespace " << name_space << " had incorrect restriction when directly checking if the namespace" " is restricted to the tab from the client id field"; @@ -111,20 +87,21 @@ void ClientPolicyControllerTest::ExpectRequiresSpecificUserSettings( std::string name_space, bool expectation) { - EXPECT_EQ(expectation, controller()->RequiresSpecificUserSettings(name_space)) + EXPECT_EQ(expectation, GetPolicy(name_space).requires_specific_user_settings) << "Namespace " << name_space << " had incorrect download support when directly checking if disabled" " when prefetch settings are disabled."; } TEST_F(ClientPolicyControllerTest, FallbackTest) { - OfflinePageClientPolicy policy = controller()->GetPolicy(kUndefinedNamespace); + const OfflinePageClientPolicy& policy = GetPolicy(kUndefinedNamespace); EXPECT_EQ(policy.name_space, kDefaultNamespace); EXPECT_TRUE(isTemporary(policy)); ExpectTemporary(kDefaultNamespace); - EXPECT_FALSE(base::Contains(controller()->GetTemporaryNamespaces(), - kUndefinedNamespace)); - EXPECT_TRUE(controller()->IsTemporary(kUndefinedNamespace)); + EXPECT_FALSE( + base::Contains(GetTemporaryPolicyNamespaces(), kUndefinedNamespace)); + EXPECT_EQ(GetPolicy(kUndefinedNamespace).lifetime_type, + LifetimeType::TEMPORARY); ExpectDownloadSupport(kUndefinedNamespace, false); ExpectDownloadSupport(kDefaultNamespace, false); ExpectRestrictedToTabFromClientId(kUndefinedNamespace, false); @@ -134,7 +111,7 @@ } TEST_F(ClientPolicyControllerTest, CheckBookmarkDefined) { - OfflinePageClientPolicy policy = controller()->GetPolicy(kBookmarkNamespace); + OfflinePageClientPolicy policy = GetPolicy(kBookmarkNamespace); EXPECT_EQ(policy.name_space, kBookmarkNamespace); EXPECT_TRUE(isTemporary(policy)); ExpectTemporary(kBookmarkNamespace); @@ -144,7 +121,7 @@ } TEST_F(ClientPolicyControllerTest, CheckLastNDefined) { - OfflinePageClientPolicy policy = controller()->GetPolicy(kLastNNamespace); + OfflinePageClientPolicy policy = GetPolicy(kLastNNamespace); EXPECT_EQ(policy.name_space, kLastNNamespace); EXPECT_TRUE(isTemporary(policy)); ExpectTemporary(kLastNNamespace); @@ -154,7 +131,7 @@ } TEST_F(ClientPolicyControllerTest, CheckAsyncDefined) { - OfflinePageClientPolicy policy = controller()->GetPolicy(kAsyncNamespace); + OfflinePageClientPolicy policy = GetPolicy(kAsyncNamespace); EXPECT_EQ(policy.name_space, kAsyncNamespace); EXPECT_FALSE(isTemporary(policy)); ExpectDownloadSupport(kAsyncNamespace, true); @@ -164,7 +141,7 @@ } TEST_F(ClientPolicyControllerTest, CheckCCTDefined) { - OfflinePageClientPolicy policy = controller()->GetPolicy(kCCTNamespace); + OfflinePageClientPolicy policy = GetPolicy(kCCTNamespace); EXPECT_EQ(policy.name_space, kCCTNamespace); EXPECT_TRUE(isTemporary(policy)); ExpectTemporary(kCCTNamespace); @@ -174,7 +151,7 @@ } TEST_F(ClientPolicyControllerTest, CheckDownloadDefined) { - OfflinePageClientPolicy policy = controller()->GetPolicy(kDownloadNamespace); + OfflinePageClientPolicy policy = GetPolicy(kDownloadNamespace); EXPECT_EQ(policy.name_space, kDownloadNamespace); EXPECT_FALSE(isTemporary(policy)); ExpectDownloadSupport(kDownloadNamespace, true); @@ -184,8 +161,7 @@ } TEST_F(ClientPolicyControllerTest, CheckNTPSuggestionsDefined) { - OfflinePageClientPolicy policy = - controller()->GetPolicy(kNTPSuggestionsNamespace); + OfflinePageClientPolicy policy = GetPolicy(kNTPSuggestionsNamespace); EXPECT_EQ(policy.name_space, kNTPSuggestionsNamespace); EXPECT_FALSE(isTemporary(policy)); ExpectDownloadSupport(kNTPSuggestionsNamespace, true); @@ -195,8 +171,7 @@ } TEST_F(ClientPolicyControllerTest, CheckSuggestedArticlesDefined) { - OfflinePageClientPolicy policy = - controller()->GetPolicy(kSuggestedArticlesNamespace); + OfflinePageClientPolicy policy = GetPolicy(kSuggestedArticlesNamespace); EXPECT_EQ(policy.name_space, kSuggestedArticlesNamespace); EXPECT_TRUE(isTemporary(policy)); ExpectTemporary(kSuggestedArticlesNamespace); @@ -206,8 +181,7 @@ } TEST_F(ClientPolicyControllerTest, CheckLivePageSharingDefined) { - OfflinePageClientPolicy policy = - controller()->GetPolicy(kLivePageSharingNamespace); + OfflinePageClientPolicy policy = GetPolicy(kLivePageSharingNamespace); EXPECT_EQ(policy.name_space, kLivePageSharingNamespace); EXPECT_TRUE(isTemporary(policy)); ExpectTemporary(kLivePageSharingNamespace); @@ -217,9 +191,9 @@ } TEST_F(ClientPolicyControllerTest, AllTemporaryNamespaces) { - std::vector<std::string> all_namespaces = controller()->GetAllNamespaces(); + std::vector<std::string> all_namespaces = GetAllPolicyNamespaces(); const std::vector<std::string>& cache_reset_namespaces_list = - controller()->GetTemporaryNamespaces(); + GetTemporaryPolicyNamespaces(); std::set<std::string> cache_reset_namespaces( cache_reset_namespaces_list.begin(), cache_reset_namespaces_list.end()); for (auto name_space : cache_reset_namespaces) {
diff --git a/components/offline_pages/core/downloads/download_ui_adapter.cc b/components/offline_pages/core/downloads/download_ui_adapter.cc index b4e23a8..4019831c 100644 --- a/components/offline_pages/core/downloads/download_ui_adapter.cc +++ b/components/offline_pages/core/downloads/download_ui_adapter.cc
@@ -18,8 +18,8 @@ #include "components/offline_pages/core/background/request_notifier.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/client_namespace_constants.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/downloads/offline_item_conversions.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/page_criteria.h" #include "components/offline_pages/core/visuals_decoder.h" @@ -35,20 +35,17 @@ namespace { bool RequestsMatchesGuid(const std::string& guid, - ClientPolicyController* policy_controller, const SavePageRequest& request) { return request.client_id().id == guid && - policy_controller->IsSupportedByDownload( - request.client_id().name_space); + GetPolicy(request.client_id().name_space).is_supported_by_download; } std::vector<int64_t> FilterRequestsByGuid( std::vector<std::unique_ptr<SavePageRequest>> requests, - const std::string& guid, - ClientPolicyController* policy_controller) { + const std::string& guid) { std::vector<int64_t> request_ids; for (const auto& request : requests) { - if (RequestsMatchesGuid(guid, policy_controller, *request)) + if (RequestsMatchesGuid(guid, *request)) request_ids.push_back(request->request_id()); } return request_ids; @@ -125,8 +122,8 @@ if (!delegate_->IsVisibleInUI(added_page.client_id)) return; - bool is_suggested = model->GetPolicyController()->IsSuggested( - added_page.client_id.name_space); + const bool is_suggested = + GetPolicy(added_page.client_id.name_space).is_suggested; OfflineItem offline_item( OfflineItemConversions::CreateOfflineItem(added_page, is_suggested)); @@ -357,10 +354,8 @@ if (!page) return; - bool is_suggested = - model_->GetPolicyController()->IsSuggested(page->client_id.name_space); - auto offline_item = - OfflineItemConversions::CreateOfflineItem(*page, is_suggested); + auto offline_item = OfflineItemConversions::CreateOfflineItem( + *page, GetPolicy(page->client_id.name_space).is_suggested); offline_items_collection::UpdateDelta update_delta; update_delta.visuals_changed = true; @@ -389,8 +384,8 @@ const std::vector<OfflinePageItem>& pages) { if (!pages.empty()) { const OfflinePageItem* page = &pages[0]; - bool is_suggested = - model_->GetPolicyController()->IsSuggested(page->client_id.name_space); + const bool is_suggested = + GetPolicy(page->client_id.name_space).is_suggested; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), OfflineItemConversions::CreateOfflineItem( @@ -430,8 +425,7 @@ if (pages.empty()) return; const OfflinePageItem* page = &pages[0]; - bool is_suggested = - model_->GetPolicyController()->IsSuggested(page->client_id.name_space); + const bool is_suggested = GetPolicy(page->client_id.name_space).is_suggested; OfflineItem item = OfflineItemConversions::CreateOfflineItem(*page, is_suggested); delegate_->OpenItem(item, page->offline_id, location); @@ -447,11 +441,7 @@ } void DownloadUIAdapter::CancelDownload(const ContentId& id) { - auto predicate = - base::BindRepeating(&RequestsMatchesGuid, id.id, - // Since RequestCoordinator is calling us back, - // binding its policy controller is safe. - request_coordinator_->GetPolicyController()); + auto predicate = base::BindRepeating(&RequestsMatchesGuid, id.id); request_coordinator_->RemoveRequestsIf(predicate, base::DoNothing()); } @@ -466,8 +456,8 @@ void DownloadUIAdapter::PauseDownloadContinuation( const std::string& guid, std::vector<std::unique_ptr<SavePageRequest>> requests) { - request_coordinator_->PauseRequests(FilterRequestsByGuid( - std::move(requests), guid, request_coordinator_->GetPolicyController())); + request_coordinator_->PauseRequests( + FilterRequestsByGuid(std::move(requests), guid)); } void DownloadUIAdapter::ResumeDownload(const ContentId& id, @@ -486,8 +476,8 @@ void DownloadUIAdapter::ResumeDownloadContinuation( const std::string& guid, std::vector<std::unique_ptr<SavePageRequest>> requests) { - request_coordinator_->ResumeRequests(FilterRequestsByGuid( - std::move(requests), guid, request_coordinator_->GetPolicyController())); + request_coordinator_->ResumeRequests( + FilterRequestsByGuid(std::move(requests), guid)); } void DownloadUIAdapter::OnOfflinePagesLoaded( @@ -497,10 +487,8 @@ for (const auto& page : pages) { if (delegate_->IsVisibleInUI(page.client_id)) { std::string guid = page.client_id.id; - bool is_suggested = - model_->GetPolicyController()->IsSuggested(page.client_id.name_space); - offline_items->push_back( - OfflineItemConversions::CreateOfflineItem(page, is_suggested)); + offline_items->push_back(OfflineItemConversions::CreateOfflineItem( + page, GetPolicy(page.client_id.name_space).is_suggested)); } } request_coordinator_->GetAllRequests(base::BindOnce(
diff --git a/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc b/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc index 2c7ee95..80d7cbf6 100644 --- a/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc +++ b/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc
@@ -30,8 +30,8 @@ #include "components/offline_pages/core/background/offliner_stub.h" #include "components/offline_pages/core/background/request_coordinator_stub_taco.h" #include "components/offline_pages/core/client_namespace_constants.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/downloads/offline_item_conversions.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/stub_offline_page_model.h" #include "components/offline_pages/core/visuals_decoder.h" #include "testing/gtest/include/gtest/gtest.h" @@ -116,9 +116,7 @@ class MockOfflinePageModel : public StubOfflinePageModel { public: explicit MockOfflinePageModel(base::TestMockTimeTaskRunner* task_runner) - : observer_(nullptr), - task_runner_(task_runner), - policy_controller_(new ClientPolicyController()) {} + : observer_(nullptr), task_runner_(task_runner) {} ~MockOfflinePageModel() override {} @@ -193,10 +191,9 @@ void GetPagesWithCriteria(const PageCriteria& criteria, MultipleOfflinePageItemCallback callback) override { - ClientPolicyController policy_controller; std::vector<OfflinePageItem> matches; for (const auto& page : pages) { - if (MeetsCriteria(policy_controller, criteria, page.second)) { + if (MeetsCriteria(criteria, page.second)) { matches.push_back(page.second); } } @@ -209,18 +206,12 @@ observer_->OfflinePageAdded(this, page); } - ClientPolicyController* GetPolicyController() override { - return policy_controller_.get(); - } - std::map<int64_t, OfflinePageItem> pages; std::unique_ptr<OfflinePageVisuals> visuals_by_offline_id_result; private: OfflinePageModel::Observer* observer_; base::TestMockTimeTaskRunner* task_runner_; - // Normally owned by OfflinePageModel. - std::unique_ptr<ClientPolicyController> policy_controller_; DISALLOW_COPY_AND_ASSIGN(MockOfflinePageModel); };
diff --git a/components/offline_pages/core/model/clear_storage_task.cc b/components/offline_pages/core/model/clear_storage_task.cc index 2316fb8..a4820d6 100644 --- a/components/offline_pages/core/model/clear_storage_task.cc +++ b/components/offline_pages/core/model/clear_storage_task.cc
@@ -17,7 +17,6 @@ #include "base/metrics/histogram_macros.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/delete_page_task.h" #include "components/offline_pages/core/model/get_pages_task.h" #include "components/offline_pages/core/offline_page_client_policy.h" @@ -42,18 +41,14 @@ class PageClearCriteria { public: - PageClearCriteria(const ClientPolicyController* policy_controller, - base::Time start_time, + PageClearCriteria(base::Time start_time, const ArchiveManager::StorageStats& stats) - : policy_controller_(policy_controller), - start_time_(start_time), - stats_(stats) {} + : start_time_(start_time), stats_(stats) {} // Returns whether a page should be deleted. bool should_delete_item(const OfflinePageItem& page) { const std::string& name_space = page.client_id.name_space; - const OfflinePageClientPolicy& policy = - policy_controller_->GetPolicy(name_space); + const OfflinePageClientPolicy& policy = GetPolicy(name_space); const size_t page_limit = policy.page_limit; const base::TimeDelta expiration_period = policy.expiration_period; @@ -96,7 +91,6 @@ } private: - const ClientPolicyController* policy_controller_; base::Time start_time_; const ArchiveManager::StorageStats& stats_; @@ -105,12 +99,11 @@ }; std::vector<OfflinePageItem> GetPagesToClear( - const ClientPolicyController* policy_controller, const base::Time& start_time, const ArchiveManager::StorageStats& stats, sql::Database* db) { std::map<std::string, size_t> namespace_page_count; - PageClearCriteria additional_criteria(policy_controller, start_time, stats); + PageClearCriteria additional_criteria(start_time, stats); PageCriteria criteria; criteria.lifetime_type = LifetimeType::TEMPORARY; @@ -120,7 +113,7 @@ base::BindRepeating(&PageClearCriteria::should_delete_item, base::Unretained(&additional_criteria)); GetPagesTask::ReadResult result = - GetPagesTask::ReadPagesWithCriteriaSync(policy_controller, criteria, db); + GetPagesTask::ReadPagesWithCriteriaSync(criteria, db); return std::move(result.pages); } @@ -131,12 +124,11 @@ } std::pair<size_t, DeletePageResult> ClearPagesSync( - ClientPolicyController* policy_controller, const base::Time& start_time, const ArchiveManager::StorageStats& stats, sql::Database* db) { std::vector<OfflinePageItem> pages_to_delete = - GetPagesToClear(policy_controller, start_time, stats, db); + GetPagesToClear(start_time, stats, db); size_t pages_cleared = 0; for (const OfflinePageItem& page : pages_to_delete) { @@ -163,17 +155,14 @@ ClearStorageTask::ClearStorageTask(OfflinePageMetadataStore* store, ArchiveManager* archive_manager, - ClientPolicyController* policy_controller, const base::Time& clearup_time, ClearStorageCallback callback) : store_(store), archive_manager_(archive_manager), - policy_controller_(policy_controller), callback_(std::move(callback)), clearup_time_(clearup_time) { DCHECK(store_); DCHECK(archive_manager_); - DCHECK(policy_controller_); DCHECK(!callback_.is_null()); } @@ -188,11 +177,10 @@ void ClearStorageTask::OnGetStorageStatsDone( const ArchiveManager::StorageStats& stats) { - store_->Execute( - base::BindOnce(&ClearPagesSync, policy_controller_, clearup_time_, stats), - base::BindOnce(&ClearStorageTask::OnClearPagesDone, - weak_ptr_factory_.GetWeakPtr()), - {0, DeletePageResult::STORE_FAILURE}); + store_->Execute(base::BindOnce(&ClearPagesSync, clearup_time_, stats), + base::BindOnce(&ClearStorageTask::OnClearPagesDone, + weak_ptr_factory_.GetWeakPtr()), + {0, DeletePageResult::STORE_FAILURE}); } void ClearStorageTask::OnClearPagesDone(
diff --git a/components/offline_pages/core/model/clear_storage_task.h b/components/offline_pages/core/model/clear_storage_task.h index 8e6aa2ba..f67f6f9 100644 --- a/components/offline_pages/core/model/clear_storage_task.h +++ b/components/offline_pages/core/model/clear_storage_task.h
@@ -19,7 +19,6 @@ namespace offline_pages { -class ClientPolicyController; class OfflinePageMetadataStore; // This task is responsible for clearing expired temporary pages from metadata @@ -47,7 +46,6 @@ ClearStorageTask(OfflinePageMetadataStore* store, ArchiveManager* archive_manager, - ClientPolicyController* policy_controller, const base::Time& clearup_time, ClearStorageCallback callback); ~ClearStorageTask() override; @@ -65,9 +63,6 @@ // The archive manager owning the archive directories to delete pages from. // Not owned. ArchiveManager* archive_manager_; - // The policy controller which is used to determine if a page needs to be - // cleared. Not owned. - ClientPolicyController* policy_controller_; ClearStorageCallback callback_; base::Time clearup_time_;
diff --git a/components/offline_pages/core/model/clear_storage_task_unittest.cc b/components/offline_pages/core/model/clear_storage_task_unittest.cc index 3392c91..7f48904 100644 --- a/components/offline_pages/core/model/clear_storage_task_unittest.cc +++ b/components/offline_pages/core/model/clear_storage_task_unittest.cc
@@ -18,6 +18,7 @@ #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/model_task_test_base.h" #include "components/offline_pages/core/model/offline_page_test_utils.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/test_scoped_offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -148,12 +149,13 @@ // during each test. // Make sure no persistent pages are marked as expired. - if (!policy_controller()->IsTemporary(setting.name_space)) + const OfflinePageClientPolicy& policy = GetPolicy(setting.name_space); + if (policy.lifetime_type == LifetimeType::PERSISTENT) ASSERT_FALSE(setting.expired_page_count); generator()->SetCreationTime(clock()->Now()); generator()->SetNamespace(setting.name_space); - if (policy_controller()->IsTemporary(setting.name_space)) { + if (policy.lifetime_type == LifetimeType::TEMPORARY) { generator()->SetArchiveDirectory(TemporaryDir()); } else { generator()->SetArchiveDirectory(PrivateDir()); @@ -164,9 +166,7 @@ AddPage(); } - generator()->SetLastAccessTime( - clock_.Now() - - policy_controller()->GetPolicy(setting.name_space).expiration_period); + generator()->SetLastAccessTime(clock_.Now() - policy.expiration_period); for (int i = 0; i < setting.expired_page_count; ++i) { AddPage(); } @@ -174,7 +174,7 @@ void ClearStorageTaskTest::RunClearStorageTask(const base::Time& start_time) { auto task = std::make_unique<ClearStorageTask>( - store(), archive_manager(), policy_controller(), start_time, + store(), archive_manager(), start_time, base::BindOnce(&ClearStorageTaskTest::OnClearStorageDone, base::AsWeakPtr(this))); @@ -263,12 +263,11 @@ // Check preconditions, especially that last_n expiration is longer than // bookmark's. - OfflinePageClientPolicy bookmark_policy = - policy_controller()->GetPolicy(kBookmarkNamespace); - OfflinePageClientPolicy last_n_policy = - policy_controller()->GetPolicy(kLastNNamespace); - OfflinePageClientPolicy download_policy = - policy_controller()->GetPolicy(kDownloadNamespace); + const OfflinePageClientPolicy& bookmark_policy = + GetPolicy(kBookmarkNamespace); + const OfflinePageClientPolicy& last_n_policy = GetPolicy(kLastNNamespace); + const OfflinePageClientPolicy& download_policy = + GetPolicy(kDownloadNamespace); ASSERT_EQ(LifetimeType::TEMPORARY, bookmark_policy.lifetime_type); ASSERT_EQ(LifetimeType::TEMPORARY, last_n_policy.lifetime_type); ASSERT_EQ(LifetimeType::PERSISTENT, download_policy.lifetime_type);
diff --git a/components/offline_pages/core/model/delete_page_task.cc b/components/offline_pages/core/model/delete_page_task.cc index d5d0120..26cfa9ee 100644 --- a/components/offline_pages/core/model/delete_page_task.cc +++ b/components/offline_pages/core/model/delete_page_task.cc
@@ -14,7 +14,6 @@ #include "base/metrics/histogram_functions.h" #include "base/time/time.h" #include "build/build_config.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/get_pages_task.h" #include "components/offline_pages/core/model/offline_page_model_utils.h" #include "components/offline_pages/core/offline_clock.h" @@ -100,7 +99,6 @@ } DeletePageTaskResult DeletePagesWithCriteria( - const ClientPolicyController* policy_controller, const PageCriteria& criteria, sql::Database* db) { // If you create a transaction but dont Commit() it is automatically @@ -110,7 +108,7 @@ return {DeletePageResult::STORE_FAILURE, {}}; GetPagesTask::ReadResult read_result = - GetPagesTask::ReadPagesWithCriteriaSync(policy_controller, criteria, db); + GetPagesTask::ReadPagesWithCriteriaSync(criteria, db); if (!read_result.success) return {DeletePageResult::STORE_FAILURE, {}}; @@ -125,7 +123,6 @@ // Deletes all but |limit| pages that match |criteria|, in the order specified // by |criteria|. DeletePageTaskResult DeletePagesForPageLimit( - const ClientPolicyController* policy_controller, const PageCriteria& criteria, size_t limit, sql::Database* db) { @@ -143,7 +140,7 @@ return {DeletePageResult::STORE_FAILURE, {}}; GetPagesTask::ReadResult read_result = - GetPagesTask::ReadPagesWithCriteriaSync(policy_controller, criteria, db); + GetPagesTask::ReadPagesWithCriteriaSync(criteria, db); if (!read_result.success) return {DeletePageResult::STORE_FAILURE, {}}; @@ -165,12 +162,10 @@ // static std::unique_ptr<DeletePageTask> DeletePageTask::CreateTaskWithCriteria( OfflinePageMetadataStore* store, - const ClientPolicyController& policy_controller, const PageCriteria& criteria, DeletePageTask::DeletePageTaskCallback callback) { return std::unique_ptr<DeletePageTask>(new DeletePageTask( - store, - base::BindOnce(&DeletePagesWithCriteria, &policy_controller, criteria), + store, base::BindOnce(&DeletePagesWithCriteria, criteria), std::move(callback))); } @@ -178,7 +173,6 @@ std::unique_ptr<DeletePageTask> DeletePageTask::CreateTaskMatchingUrlPredicateForCachedPages( OfflinePageMetadataStore* store, - const ClientPolicyController& policy_controller, DeletePageTask::DeletePageTaskCallback callback, const UrlPredicate& predicate) { PageCriteria criteria; @@ -188,29 +182,25 @@ return predicate.Run(item.url); }, predicate); - return CreateTaskWithCriteria(store, policy_controller, criteria, - std::move(callback)); + return CreateTaskWithCriteria(store, criteria, std::move(callback)); } // static std::unique_ptr<DeletePageTask> DeletePageTask::CreateTaskDeletingForPageLimit( OfflinePageMetadataStore* store, - const ClientPolicyController& policy_controller, DeletePageTask::DeletePageTaskCallback callback, const OfflinePageItem& page) { std::string name_space = page.client_id.name_space; - size_t limit = policy_controller.GetPolicy(name_space).pages_allowed_per_url; + size_t limit = GetPolicy(name_space).pages_allowed_per_url; PageCriteria criteria; criteria.url = page.url; criteria.client_namespaces = std::vector<std::string>{name_space}; // Sorting is important here. DeletePagesForPageLimit will delete the results // in order, leaving only the last |limit| pages. criteria.result_order = PageCriteria::kAscendingAccessTime; - return base::WrapUnique( - new DeletePageTask(store, - base::BindOnce(&DeletePagesForPageLimit, - &policy_controller, criteria, limit), - std::move(callback))); + return base::WrapUnique(new DeletePageTask( + store, base::BindOnce(&DeletePagesForPageLimit, criteria, limit), + std::move(callback))); } DeletePageTask::DeletePageTask(OfflinePageMetadataStore* store,
diff --git a/components/offline_pages/core/model/delete_page_task.h b/components/offline_pages/core/model/delete_page_task.h index b642f97..0ff39b4 100644 --- a/components/offline_pages/core/model/delete_page_task.h +++ b/components/offline_pages/core/model/delete_page_task.h
@@ -39,7 +39,6 @@ static std::unique_ptr<DeletePageTask> CreateTaskWithCriteria( OfflinePageMetadataStore* store, - const ClientPolicyController& policy_controller, const PageCriteria& criteria, DeletePageTask::DeletePageTaskCallback callback); @@ -47,7 +46,6 @@ static std::unique_ptr<DeletePageTask> CreateTaskMatchingUrlPredicateForCachedPages( OfflinePageMetadataStore* store, - const ClientPolicyController& policy_controller, DeletePageTask::DeletePageTaskCallback callback, const UrlPredicate& predicate); @@ -57,7 +55,6 @@ // Returns nullptr if there's no page limit per url of the page's namespace. static std::unique_ptr<DeletePageTask> CreateTaskDeletingForPageLimit( OfflinePageMetadataStore* store, - const ClientPolicyController& policy_controller, DeletePageTask::DeletePageTaskCallback callback, const OfflinePageItem& page);
diff --git a/components/offline_pages/core/model/delete_page_task_unittest.cc b/components/offline_pages/core/model/delete_page_task_unittest.cc index 98a94d8..0c812ca 100644 --- a/components/offline_pages/core/model/delete_page_task_unittest.cc +++ b/components/offline_pages/core/model/delete_page_task_unittest.cc
@@ -109,8 +109,8 @@ // Run DeletePageTask for to delete the page. PageCriteria criteria; criteria.offline_ids = std::vector<int64_t>{page1.offline_id}; - auto task = DeletePageTask::CreateTaskWithCriteria( - store(), *policy_controller(), criteria, delete_page_callback()); + auto task = DeletePageTask::CreateTaskWithCriteria(store(), criteria, + delete_page_callback()); RunTask(std::move(task)); EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_page_result()); @@ -152,7 +152,7 @@ }); auto task = DeletePageTask::CreateTaskMatchingUrlPredicateForCachedPages( - store(), *policy_controller(), delete_page_callback(), predicate); + store(), delete_page_callback(), predicate); RunTask(std::move(task)); EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_page_result()); @@ -201,7 +201,7 @@ base::BindRepeating([](const GURL& url) -> bool { return false; }); auto task = DeletePageTask::CreateTaskMatchingUrlPredicateForCachedPages( - store(), *policy_controller(), delete_page_callback(), predicate); + store(), delete_page_callback(), predicate); RunTask(std::move(task)); EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_page_result()); @@ -243,7 +243,7 @@ EXPECT_TRUE(base::PathExists(page3.file_path)); auto task = DeletePageTask::CreateTaskDeletingForPageLimit( - store(), *policy_controller(), delete_page_callback(), page); + store(), delete_page_callback(), page); RunTask(std::move(task)); EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_page_result()); @@ -281,7 +281,7 @@ EXPECT_TRUE(base::PathExists(page3.file_path)); auto task = DeletePageTask::CreateTaskDeletingForPageLimit( - store(), *policy_controller(), delete_page_callback(), page); + store(), delete_page_callback(), page); RunTask(std::move(task)); // Since there's no limit for page per url of Download Namespace, the result
diff --git a/components/offline_pages/core/model/get_pages_task.cc b/components/offline_pages/core/model/get_pages_task.cc index b076df73..6a1aa03 100644 --- a/components/offline_pages/core/model/get_pages_task.cc +++ b/components/offline_pages/core/model/get_pages_task.cc
@@ -12,7 +12,6 @@ #include "base/files/file_path.h" #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_item_utils.h" #include "components/offline_pages/core/offline_store_utils.h" @@ -86,11 +85,9 @@ GetPagesTask::ReadResult::~ReadResult() = default; GetPagesTask::GetPagesTask(OfflinePageMetadataStore* store, - const ClientPolicyController* policy_controller, const PageCriteria& criteria, MultipleOfflinePageItemCallback callback) : store_(store), - policy_controller_(policy_controller), criteria_(criteria), callback_(std::move(callback)) { DCHECK(store_); @@ -101,7 +98,7 @@ void GetPagesTask::Run() { store_->Execute(base::BindOnce(&GetPagesTask::ReadPagesWithCriteriaSync, - policy_controller_, std::move(criteria_)), + std::move(criteria_)), base::BindOnce(&GetPagesTask::CompleteWithResult, weak_ptr_factory_.GetWeakPtr()), ReadResult()); @@ -129,7 +126,6 @@ // the db is loaded to memory, and disk access will likely dwarf any // other query optimizations. ReadResult GetPagesTask::ReadPagesWithCriteriaSync( - const ClientPolicyController* policy_controller, const PageCriteria& criteria, sql::Database* db) { ReadResult result; @@ -186,7 +182,7 @@ // want to find, and then search that string for the row's namespace and // client_id respectively. std::vector<std::string> potential_namespaces = - PotentiallyMatchingNamespaces(*policy_controller, criteria); + PotentiallyMatchingNamespaces(criteria); if (!potential_namespaces.empty()) { statement.BindBool(param++, false); statement.BindString(param++, base::JoinString(potential_namespaces, "")); @@ -239,12 +235,11 @@ while (statement.Step()) { // Initially, read just the client ID to avoid creating the offline item // if it's filtered out. - if (!MeetsCriteria(*policy_controller, criteria, - OfflinePageClientId(statement))) { + if (!MeetsCriteria(criteria, OfflinePageClientId(statement))) { continue; } OfflinePageItem item = MakeOfflinePageItem(statement); - if (!MeetsCriteria(*policy_controller, criteria, item)) + if (!MeetsCriteria(criteria, item)) continue; result.pages.push_back(std::move(item));
diff --git a/components/offline_pages/core/model/get_pages_task.h b/components/offline_pages/core/model/get_pages_task.h index 47940151..4a49bb00 100644 --- a/components/offline_pages/core/model/get_pages_task.h +++ b/components/offline_pages/core/model/get_pages_task.h
@@ -17,7 +17,6 @@ #include "components/offline_pages/task/task.h" namespace offline_pages { -class ClientPolicyController; // Gets offline pages that match the criteria. class GetPagesTask : public Task { @@ -33,7 +32,6 @@ }; GetPagesTask(OfflinePageMetadataStore* store, - const ClientPolicyController* policy_controller, const PageCriteria& criteria, MultipleOfflinePageItemCallback callback); @@ -46,7 +44,6 @@ // from the database and should be called from within an // |SqlStoreBase::Execute()| call. static ReadResult ReadPagesWithCriteriaSync( - const ClientPolicyController* policy_controller, const PageCriteria& criteria, sql::Database* db); @@ -54,7 +51,6 @@ void CompleteWithResult(ReadResult result); OfflinePageMetadataStore* store_; - const ClientPolicyController* policy_controller_; PageCriteria criteria_; MultipleOfflinePageItemCallback callback_;
diff --git a/components/offline_pages/core/model/get_pages_task_unittest.cc b/components/offline_pages/core/model/get_pages_task_unittest.cc index 1c3d3a6..5ead6fe5 100644 --- a/components/offline_pages/core/model/get_pages_task_unittest.cc +++ b/components/offline_pages/core/model/get_pages_task_unittest.cc
@@ -41,7 +41,7 @@ std::unique_ptr<GetPagesTask> CreateTask(const PageCriteria& criteria) { return std::make_unique<GetPagesTask>( - store(), &policy_controller_, criteria, + store(), criteria, base::BindOnce(&GetPagesTaskTest::OnGetPagesDone, base::Unretained(this))); } @@ -57,7 +57,6 @@ } protected: - ClientPolicyController policy_controller_; std::set<OfflinePageItem> task_result_; std::vector<OfflinePageItem> ordered_task_result_; };
diff --git a/components/offline_pages/core/model/model_task_test_base.h b/components/offline_pages/core/model/model_task_test_base.h index 69600f5f..09d8851 100644 --- a/components/offline_pages/core/model/model_task_test_base.h +++ b/components/offline_pages/core/model/model_task_test_base.h
@@ -12,7 +12,6 @@ #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/archive_manager.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/offline_page_item_generator.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_metadata_store_test_util.h" @@ -51,7 +50,6 @@ OfflinePageMetadataStore* store() { return store_test_util_.store(); } OfflinePageItemGenerator* generator() { return &generator_; } ArchiveManager* archive_manager() { return archive_manager_.get(); } - ClientPolicyController* policy_controller() { return &policy_controller_; } private: OfflinePageMetadataStoreTestUtil store_test_util_; @@ -60,7 +58,6 @@ base::ScopedTempDir private_dir_; base::ScopedTempDir public_dir_; std::unique_ptr<ArchiveManager> archive_manager_; - ClientPolicyController policy_controller_; }; } // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.cc b/components/offline_pages/core/model/offline_page_model_taskified.cc index 539deee..e1ecaf0 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified.cc
@@ -31,6 +31,7 @@ #include "components/offline_pages/core/model/update_publish_id_task.h" #include "components/offline_pages/core/model/visuals_availability_task.h" #include "components/offline_pages/core/offline_clock.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_metadata_store.h" #include "components/offline_pages/core/offline_page_model.h" @@ -176,7 +177,6 @@ : store_(std::move(store)), archive_manager_(std::move(archive_manager)), archive_publisher_(std::move(archive_publisher)), - policy_controller_(new ClientPolicyController()), task_queue_(this), skip_clearing_original_url_for_testing_(false), skip_maintenance_tasks_for_testing_(false), @@ -262,7 +262,7 @@ const PageCriteria& criteria, DeletePageCallback callback) { task_queue_.AddTask(DeletePageTask::CreateTaskWithCriteria( - store_.get(), *policy_controller_.get(), criteria, + store_.get(), criteria, base::BindOnce(&OfflinePageModelTaskified::OnDeleteDone, weak_ptr_factory_.GetWeakPtr(), std::move(callback)))); } @@ -271,7 +271,7 @@ const UrlPredicate& predicate, DeletePageCallback callback) { auto task = DeletePageTask::CreateTaskMatchingUrlPredicateForCachedPages( - store_.get(), *policy_controller_.get(), + store_.get(), base::BindOnce(&OfflinePageModelTaskified::OnDeleteDone, weak_ptr_factory_.GetWeakPtr(), std::move(callback)), predicate); @@ -303,8 +303,8 @@ void OfflinePageModelTaskified::GetPagesWithCriteria( const PageCriteria& criteria, MultipleOfflinePageItemCallback callback) { - task_queue_.AddTask(std::make_unique<GetPagesTask>( - store_.get(), policy_controller_.get(), criteria, std::move(callback))); + task_queue_.AddTask(std::make_unique<GetPagesTask>(store_.get(), criteria, + std::move(callback))); } void OfflinePageModelTaskified::GetOfflineIdsForClientId( @@ -351,7 +351,7 @@ const base::FilePath& OfflinePageModelTaskified::GetInternalArchiveDirectory( const std::string& name_space) const { - if (policy_controller_->IsTemporary(name_space)) + if (GetPolicy(name_space).lifetime_type == LifetimeType::TEMPORARY) return archive_manager_->GetTemporaryArchivesDir(); return archive_manager_->GetPrivateArchivesDir(); } @@ -366,10 +366,6 @@ archive_manager_->GetPrivateArchivesDir().IsParent(file_path); } -ClientPolicyController* OfflinePageModelTaskified::GetPolicyController() { - return policy_controller_.get(); -} - OfflineEventLogger* OfflinePageModelTaskified::GetLogger() { return &offline_event_logger_; } @@ -435,7 +431,8 @@ offline_page.original_url_if_different = save_page_params.original_url; } - if (policy_controller_->IsPersistent(offline_page.client_id.name_space)) { + if (GetPolicy(offline_page.client_id.name_space).lifetime_type == + LifetimeType::PERSISTENT) { // If the user intentionally downloaded the page (aka it belongs to a // persistent namespace), move it to a public place. archive_publisher_->PublishArchive( @@ -541,8 +538,8 @@ successful_finish_time); // TODO(romax): Just keep the same with logic in OPMImpl (which was wrong). // This should be fixed once we have the new strategy for clearing pages. - if (policy_controller_->GetPolicy(page_attempted.client_id.name_space) - .pages_allowed_per_url != kUnlimitedPages) { + if (GetPolicy(page_attempted.client_id.name_space).pages_allowed_per_url != + kUnlimitedPages) { RemovePagesMatchingUrlAndNamespace(page_attempted); } offline_event_logger_.RecordPageSaved(page_attempted.client_id.name_space, @@ -642,20 +639,20 @@ // reporting storage usage UMA. if (first_run) { task_queue_.AddTask(std::make_unique<StartupMaintenanceTask>( - store_.get(), archive_manager_.get(), policy_controller_.get())); + store_.get(), archive_manager_.get())); task_queue_.AddTask(std::make_unique<CleanupVisualsTask>( store_.get(), OfflineTimeNow(), base::DoNothing())); } task_queue_.AddTask(std::make_unique<ClearStorageTask>( - store_.get(), archive_manager_.get(), policy_controller_.get(), now, + store_.get(), archive_manager_.get(), now, base::BindOnce(&OfflinePageModelTaskified::OnClearCachedPagesDone, weak_ptr_factory_.GetWeakPtr()))); // TODO(https://crbug.com/834902) This might need a better execution plan. task_queue_.AddTask(std::make_unique<PersistentPageConsistencyCheckTask>( - store_.get(), archive_manager_.get(), policy_controller_.get(), now, + store_.get(), archive_manager_.get(), now, base::BindOnce( &OfflinePageModelTaskified::OnPersistentPageConsistencyCheckDone, weak_ptr_factory_.GetWeakPtr()))); @@ -680,7 +677,7 @@ void OfflinePageModelTaskified::RemovePagesMatchingUrlAndNamespace( const OfflinePageItem& page) { auto task = DeletePageTask::CreateTaskDeletingForPageLimit( - store_.get(), *policy_controller_.get(), + store_.get(), base::BindOnce(&OfflinePageModelTaskified::OnDeleteDone, weak_ptr_factory_.GetWeakPtr(), base::DoNothing::Once<DeletePageResult>()),
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.h b/components/offline_pages/core/model/offline_page_model_taskified.h index 74ee8b4..ba8b37561 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.h +++ b/components/offline_pages/core/model/offline_page_model_taskified.h
@@ -39,7 +39,7 @@ struct OfflinePageItem; class ArchiveManager; -class ClientPolicyController; +class OfflinePageArchivePublisher; class OfflinePageArchiver; class OfflinePageMetadataStore; @@ -105,7 +105,6 @@ const base::FilePath& GetInternalArchiveDirectory( const std::string& name_space) const override; bool IsArchiveInInternalDir(const base::FilePath& file_path) const override; - ClientPolicyController* GetPolicyController() override; OfflineEventLogger* GetLogger() override; void PublishInternalArchive( const OfflinePageItem& offline_page, @@ -200,9 +199,6 @@ // Used for moving archives into public storage. std::unique_ptr<OfflinePageArchivePublisher> archive_publisher_; - // Controller of the client policies. - std::unique_ptr<ClientPolicyController> policy_controller_; - // The observers. base::ObserverList<Observer>::Unchecked observers_;
diff --git a/components/offline_pages/core/model/persistent_page_consistency_check_task.cc b/components/offline_pages/core/model/persistent_page_consistency_check_task.cc index c2b9d44..ed294f1 100644 --- a/components/offline_pages/core/model/persistent_page_consistency_check_task.cc +++ b/components/offline_pages/core/model/persistent_page_consistency_check_task.cc
@@ -14,7 +14,6 @@ #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "components/offline_pages/core/archive_manager.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/delete_page_task.h" #include "components/offline_pages/core/model/get_pages_task.h" #include "components/offline_pages/core/offline_page_client_policy.h" @@ -36,13 +35,10 @@ const base::TimeDelta kExpireThreshold = base::TimeDelta::FromDays(365); std::vector<OfflinePageItem> GetPersistentPages( - const ClientPolicyController* policy_controller, sql::Database* db) { PageCriteria criteria; criteria.lifetime_type = LifetimeType::PERSISTENT; - return std::move( - GetPagesTask::ReadPagesWithCriteriaSync(policy_controller, criteria, db) - .pages); + return std::move(GetPagesTask::ReadPagesWithCriteriaSync(criteria, db).pages); } bool SetItemsFileMissingTimeSync(const std::vector<int64_t>& item_ids, @@ -78,7 +74,6 @@ OfflinePageMetadataStore* store, const base::FilePath& private_dir, const base::FilePath& public_dir, - const ClientPolicyController* policy_controller, base::Time check_time, sql::Database* db) { std::vector<PublishedArchiveId> publish_ids_of_deleted_pages; @@ -88,8 +83,7 @@ return {SyncOperationResult::TRANSACTION_BEGIN_ERROR, publish_ids_of_deleted_pages}; - std::vector<OfflinePageItem> persistent_page_infos = - GetPersistentPages(policy_controller, db); + std::vector<OfflinePageItem> persistent_page_infos = GetPersistentPages(db); std::vector<int64_t> pages_found_missing; std::vector<int64_t> pages_reappeared; @@ -163,31 +157,28 @@ PersistentPageConsistencyCheckTask::PersistentPageConsistencyCheckTask( OfflinePageMetadataStore* store, ArchiveManager* archive_manager, - ClientPolicyController* policy_controller, base::Time check_time, PersistentPageConsistencyCheckCallback callback) : store_(store), archive_manager_(archive_manager), - policy_controller_(policy_controller), check_time_(check_time), callback_(std::move(callback)) { DCHECK(store_); DCHECK(archive_manager_); - DCHECK(policy_controller_); } PersistentPageConsistencyCheckTask::~PersistentPageConsistencyCheckTask() = default; void PersistentPageConsistencyCheckTask::Run() { - store_->Execute(base::BindOnce(&PersistentPageConsistencyCheckSync, store_, - archive_manager_->GetPrivateArchivesDir(), - archive_manager_->GetPublicArchivesDir(), - policy_controller_, check_time_), - base::BindOnce(&PersistentPageConsistencyCheckTask:: - OnPersistentPageConsistencyCheckDone, - weak_ptr_factory_.GetWeakPtr()), - CheckResult{SyncOperationResult::INVALID_DB_CONNECTION, {}}); + store_->Execute( + base::BindOnce(&PersistentPageConsistencyCheckSync, store_, + archive_manager_->GetPrivateArchivesDir(), + archive_manager_->GetPublicArchivesDir(), check_time_), + base::BindOnce(&PersistentPageConsistencyCheckTask:: + OnPersistentPageConsistencyCheckDone, + weak_ptr_factory_.GetWeakPtr()), + CheckResult{SyncOperationResult::INVALID_DB_CONNECTION, {}}); } void PersistentPageConsistencyCheckTask::OnPersistentPageConsistencyCheckDone(
diff --git a/components/offline_pages/core/model/persistent_page_consistency_check_task.h b/components/offline_pages/core/model/persistent_page_consistency_check_task.h index 9e3a006..051fca15 100644 --- a/components/offline_pages/core/model/persistent_page_consistency_check_task.h +++ b/components/offline_pages/core/model/persistent_page_consistency_check_task.h
@@ -16,7 +16,6 @@ namespace offline_pages { class ArchiveManager; -class ClientPolicyController; class OfflinePageMetadataStore; // This task is responsible for checking consistency of persistent pages, mark @@ -43,7 +42,6 @@ PersistentPageConsistencyCheckTask( OfflinePageMetadataStore* store, ArchiveManager* archive_manager, - ClientPolicyController* policy_controller, base::Time check_time, PersistentPageConsistencyCheckCallback callback); ~PersistentPageConsistencyCheckTask() override; @@ -58,9 +56,6 @@ OfflinePageMetadataStore* store_; // The archive manager storing archive directories. Not owned. ArchiveManager* archive_manager_; - // The policy controller which is used to acquire names of namespaces. Not - // owned. - ClientPolicyController* policy_controller_; base::Time check_time_; // The callback for the task. PersistentPageConsistencyCheckCallback callback_;
diff --git a/components/offline_pages/core/model/persistent_page_consistency_check_task_unittest.cc b/components/offline_pages/core/model/persistent_page_consistency_check_task_unittest.cc index d52c5540..a590207 100644 --- a/components/offline_pages/core/model/persistent_page_consistency_check_task_unittest.cc +++ b/components/offline_pages/core/model/persistent_page_consistency_check_task_unittest.cc
@@ -92,8 +92,7 @@ PublishedArchiveId{page5.system_download_id, page5.file_path}))); RunTask(std::make_unique<PersistentPageConsistencyCheckTask>( - store(), archive_manager(), policy_controller(), base::Time::Now(), - callback.Get())); + store(), archive_manager(), base::Time::Now(), callback.Get())); EXPECT_EQ(4LL, store_test_util()->GetPageCount()); EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(PrivateDir())); @@ -146,8 +145,7 @@ page.system_download_id, page.file_path}))); RunTask(std::make_unique<PersistentPageConsistencyCheckTask>( - store(), archive_manager(), policy_controller(), base::Time::Now(), - callback.Get())); + store(), archive_manager(), base::Time::Now(), callback.Get())); EXPECT_FALSE(store_test_util()->GetPageByOfflineId(page.offline_id)); histogram_tester()->ExpectUniqueSample(
diff --git a/components/offline_pages/core/model/startup_maintenance_task.cc b/components/offline_pages/core/model/startup_maintenance_task.cc index 4d421ab..d95873b 100644 --- a/components/offline_pages/core/model/startup_maintenance_task.cc +++ b/components/offline_pages/core/model/startup_maintenance_task.cc
@@ -17,7 +17,6 @@ #include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event.h" #include "components/offline_pages/core/archive_manager.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/delete_page_task.h" #include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_metadata_store.h" @@ -88,8 +87,6 @@ // Delete the files, since they're 'headless' and has no way to be accessed. SyncOperationResult ClearLegacyPagesInPrivateDirSync( sql::Database* db, - const std::vector<std::string>& temporary_namespaces, - const std::vector<std::string>& persistent_namespaces, const base::FilePath& private_dir) { // One large database transaction that will: // 1. Get temporary page infos from the database. @@ -107,9 +104,9 @@ return SyncOperationResult::TRANSACTION_BEGIN_ERROR; std::vector<PageInfo> temporary_page_infos = - GetPageInfosByNamespaces(temporary_namespaces, db); + GetPageInfosByNamespaces(GetTemporaryPolicyNamespaces(), db); std::vector<PageInfo> persistent_page_infos = - GetPageInfosByNamespaces(persistent_namespaces, db); + GetPageInfosByNamespaces(GetPersistentPolicyNamespaces(), db); std::map<base::FilePath, PageInfo> path_to_page_info; std::set<base::FilePath> archive_paths = GetAllArchives(private_dir); @@ -153,7 +150,6 @@ SyncOperationResult CheckTemporaryPageConsistencySync( sql::Database* db, - const std::vector<std::string>& namespaces, const base::FilePath& archives_dir) { // One large database transaction that will: // 1. Get page infos by |namespaces| from the database. @@ -163,7 +159,8 @@ if (!transaction.Begin()) return SyncOperationResult::TRANSACTION_BEGIN_ERROR; - std::vector<PageInfo> page_infos = GetPageInfosByNamespaces(namespaces, db); + std::vector<PageInfo> page_infos = + GetPageInfosByNamespaces(GetTemporaryPolicyNamespaces(), db); std::set<base::FilePath> page_info_paths; std::vector<int64_t> offline_ids_to_delete; @@ -213,12 +210,11 @@ return SyncOperationResult::SUCCESS; } -void ReportStorageUsageSync(sql::Database* db, - const std::vector<std::string>& namespaces) { +void ReportStorageUsageSync(sql::Database* db) { static const char kSql[] = "SELECT sum(file_size) FROM " OFFLINE_PAGES_TABLE_NAME " WHERE client_namespace = ?"; - for (const auto& name_space : namespaces) { + for (const auto& name_space : GetAllPolicyNamespaces()) { sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindString(0, name_space); int size_in_kib = 0; @@ -232,43 +228,34 @@ } bool StartupMaintenanceSync( - const std::vector<std::string>& persistent_namespaces, - const std::vector<std::string>& temporary_namespaces, const base::FilePath& temporary_archives_dir, const base::FilePath& private_archives_dir, sql::Database* db) { // Clear temporary pages that are in legacy directory, which is also the // directory that serves as the 'private' directory. - SyncOperationResult result = ClearLegacyPagesInPrivateDirSync( - db, temporary_namespaces, persistent_namespaces, private_archives_dir); + SyncOperationResult result = + ClearLegacyPagesInPrivateDirSync(db, private_archives_dir); // Clear temporary pages in cache directory. - result = CheckTemporaryPageConsistencySync(db, temporary_namespaces, - temporary_archives_dir); + result = CheckTemporaryPageConsistencySync(db, temporary_archives_dir); UMA_HISTOGRAM_ENUMERATION("OfflinePages.ConsistencyCheck.Temporary.Result", result); // Report storage usage UMA, |temporary_namespaces| + |persistent_namespaces| // should be all namespaces. This is implicitly checked by the // TestReportStorageUsage unit test. - ReportStorageUsageSync(db, temporary_namespaces); - ReportStorageUsageSync(db, persistent_namespaces); + ReportStorageUsageSync(db); return true; } } // namespace -StartupMaintenanceTask::StartupMaintenanceTask( - OfflinePageMetadataStore* store, - ArchiveManager* archive_manager, - ClientPolicyController* policy_controller) - : store_(store), - archive_manager_(archive_manager), - policy_controller_(policy_controller) { +StartupMaintenanceTask::StartupMaintenanceTask(OfflinePageMetadataStore* store, + ArchiveManager* archive_manager) + : store_(store), archive_manager_(archive_manager) { DCHECK(store_); DCHECK(archive_manager_); - DCHECK(policy_controller_); } StartupMaintenanceTask::~StartupMaintenanceTask() = default; @@ -276,16 +263,8 @@ void StartupMaintenanceTask::Run() { TRACE_EVENT_ASYNC_BEGIN0("offline_pages", "StartupMaintenanceTask running", this); - std::vector<std::string> all_namespaces = - policy_controller_->GetAllNamespaces(); - std::vector<std::string> temporary_namespaces = - policy_controller_->GetTemporaryNamespaces(); - std::vector<std::string> persistent_namespaces = - policy_controller_->GetPersistentNamespaces(); - store_->Execute( - base::BindOnce(&StartupMaintenanceSync, persistent_namespaces, - temporary_namespaces, + base::BindOnce(&StartupMaintenanceSync, archive_manager_->GetTemporaryArchivesDir(), archive_manager_->GetPrivateArchivesDir()), base::BindOnce(&StartupMaintenanceTask::OnStartupMaintenanceDone,
diff --git a/components/offline_pages/core/model/startup_maintenance_task.h b/components/offline_pages/core/model/startup_maintenance_task.h index fe85315..bab8ca6 100644 --- a/components/offline_pages/core/model/startup_maintenance_task.h +++ b/components/offline_pages/core/model/startup_maintenance_task.h
@@ -12,7 +12,6 @@ namespace offline_pages { class ArchiveManager; -class ClientPolicyController; class OfflinePageMetadataStore; // This task is responsible for executing maintenance sub-tasks during Chrome @@ -21,8 +20,7 @@ class StartupMaintenanceTask : public Task { public: StartupMaintenanceTask(OfflinePageMetadataStore* store, - ArchiveManager* archive_manager, - ClientPolicyController* policy_controller); + ArchiveManager* archive_manager); ~StartupMaintenanceTask() override; // Task implementation: @@ -35,9 +33,6 @@ OfflinePageMetadataStore* store_; // The archive manager storing archive directories. Not owned. ArchiveManager* archive_manager_; - // The policy controller which is used to acquire names of namespaces. Not - // owned. - ClientPolicyController* policy_controller_; base::WeakPtrFactory<StartupMaintenanceTask> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(StartupMaintenanceTask);
diff --git a/components/offline_pages/core/model/startup_maintenance_task_unittest.cc b/components/offline_pages/core/model/startup_maintenance_task_unittest.cc index 8595cda..0b5f645 100644 --- a/components/offline_pages/core/model/startup_maintenance_task_unittest.cc +++ b/components/offline_pages/core/model/startup_maintenance_task_unittest.cc
@@ -16,6 +16,7 @@ #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/model_task_test_base.h" #include "components/offline_pages/core/model/offline_page_test_utils.h" +#include "components/offline_pages/core/offline_page_client_policy.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -96,8 +97,8 @@ EXPECT_EQ(2LL, store_test_util()->GetPageCount()); EXPECT_EQ(4UL, test_utils::GetFileCountInDirectory(PrivateDir())); - auto task = std::make_unique<StartupMaintenanceTask>( - store(), archive_manager(), policy_controller()); + auto task = + std::make_unique<StartupMaintenanceTask>(store(), archive_manager()); RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); @@ -141,8 +142,8 @@ EXPECT_EQ(PagePresence::FILESYSTEM_ONLY, CheckPagePresence(temporary_page2)); EXPECT_EQ(PagePresence::FILESYSTEM_ONLY, CheckPagePresence(persistent_page2)); - auto task = std::make_unique<StartupMaintenanceTask>( - store(), archive_manager(), policy_controller()); + auto task = + std::make_unique<StartupMaintenanceTask>(store(), archive_manager()); RunTask(std::move(task)); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); @@ -195,8 +196,8 @@ EXPECT_EQ(PagePresence::DB_ONLY, CheckPagePresence(temporary_page2)); EXPECT_EQ(PagePresence::DB_ONLY, CheckPagePresence(persistent_page2)); - auto task = std::make_unique<StartupMaintenanceTask>( - store(), archive_manager(), policy_controller()); + auto task = + std::make_unique<StartupMaintenanceTask>(store(), archive_manager()); RunTask(std::move(task)); EXPECT_EQ(3LL, store_test_util()->GetPageCount()); @@ -251,8 +252,8 @@ EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(TemporaryDir())); EXPECT_EQ(4UL, test_utils::GetFileCountInDirectory(PrivateDir())); - auto task = std::make_unique<StartupMaintenanceTask>( - store(), archive_manager(), policy_controller()); + auto task = + std::make_unique<StartupMaintenanceTask>(store(), archive_manager()); RunTask(std::move(task)); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); @@ -298,8 +299,8 @@ EXPECT_EQ(0LL, store_test_util()->GetPageCount()); EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(PublicDir())); - auto task = std::make_unique<StartupMaintenanceTask>( - store(), archive_manager(), policy_controller()); + auto task = + std::make_unique<StartupMaintenanceTask>(store(), archive_manager()); RunTask(std::move(task)); EXPECT_EQ(0LL, store_test_util()->GetPageCount()); @@ -309,7 +310,7 @@ TEST_F(StartupMaintenanceTaskTest, TestReportStorageUsage) { generator()->SetFileSize(kTestFileSize); - std::vector<std::string> namespaces = policy_controller()->GetAllNamespaces(); + const std::vector<std::string>& namespaces = GetAllPolicyNamespaces(); // Adding pages into each namespace. for (const auto& name_space : namespaces) { @@ -317,7 +318,7 @@ // correct directories, otherwise they might be cleaned based on consistency // check. generator()->SetNamespace(name_space); - if (policy_controller()->IsTemporary(name_space)) + if (GetPolicy(name_space).lifetime_type == LifetimeType::TEMPORARY) generator()->SetArchiveDirectory(TemporaryDir()); else generator()->SetArchiveDirectory(PrivateDir()); @@ -328,8 +329,8 @@ AddPage(); } - auto task = std::make_unique<StartupMaintenanceTask>( - store(), archive_manager(), policy_controller()); + auto task = + std::make_unique<StartupMaintenanceTask>(store(), archive_manager()); RunTask(std::move(task)); // For each namespace, check if the storage usage was correctly reported,
diff --git a/components/offline_pages/core/offline_page_client_policy.cc b/components/offline_pages/core/offline_page_client_policy.cc index 7038fbb..8849aac9 100644 --- a/components/offline_pages/core/offline_page_client_policy.cc +++ b/components/offline_pages/core/offline_page_client_policy.cc
@@ -4,15 +4,168 @@ #include "components/offline_pages/core/offline_page_client_policy.h" +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "base/logging.h" +#include "base/no_destructor.h" +#include "base/time/time.h" +#include "components/offline_pages/core/client_namespace_constants.h" +#include "components/offline_pages/core/offline_page_client_policy.h" + namespace offline_pages { +namespace { +struct PolicyData { + std::map<std::string, OfflinePageClientPolicy> policies; + std::vector<std::string> temporary_namespaces; + std::vector<std::string> persistent_namespaces; + std::vector<std::string> all_namespaces; +}; + +PolicyData BuildPolicies() { + std::vector<OfflinePageClientPolicy> all_policies; + { + auto policy = OfflinePageClientPolicy::CreateTemporary( + kBookmarkNamespace, base::TimeDelta::FromDays(7)); + policy.pages_allowed_per_url = 1; + all_policies.push_back(policy); + } + { + auto policy = OfflinePageClientPolicy::CreateTemporary( + kLastNNamespace, base::TimeDelta::FromDays(30)); + policy.is_restricted_to_tab_from_client_id = true; + all_policies.push_back(policy); + } + { + auto policy = OfflinePageClientPolicy::CreatePersistent(kAsyncNamespace); + policy.is_supported_by_download = true; + all_policies.push_back(policy); + } + { + auto policy = OfflinePageClientPolicy::CreateTemporary( + kCCTNamespace, base::TimeDelta::FromDays(2)); + policy.pages_allowed_per_url = 1; + policy.requires_specific_user_settings = true; + all_policies.push_back(policy); + } + { + auto policy = OfflinePageClientPolicy::CreatePersistent(kDownloadNamespace); + policy.is_supported_by_download = true; + all_policies.push_back(policy); + } + { + auto policy = + OfflinePageClientPolicy::CreatePersistent(kNTPSuggestionsNamespace); + policy.is_supported_by_download = true; + all_policies.push_back(policy); + } + { + auto policy = OfflinePageClientPolicy::CreateTemporary( + kSuggestedArticlesNamespace, base::TimeDelta::FromDays(30)); + policy.is_supported_by_download = 1; + policy.is_suggested = true; + all_policies.push_back(policy); + } + { + auto policy = + OfflinePageClientPolicy::CreatePersistent(kBrowserActionsNamespace); + policy.is_supported_by_download = true; + policy.allows_conversion_to_background_file_download = true; + all_policies.push_back(policy); + } + { + auto policy = OfflinePageClientPolicy::CreateTemporary( + kLivePageSharingNamespace, base::TimeDelta::FromHours(1)); + policy.pages_allowed_per_url = 1; + policy.is_restricted_to_tab_from_client_id = true; + all_policies.push_back(policy); + } + { + auto policy = OfflinePageClientPolicy::CreateTemporary( + kAutoAsyncNamespace, base::TimeDelta::FromDays(30)); + policy.pages_allowed_per_url = 1; + policy.defer_background_fetch_while_page_is_active = true; + all_policies.push_back(policy); + } + + // Fallback policy. + { + OfflinePageClientPolicy policy = OfflinePageClientPolicy::CreateTemporary( + kDefaultNamespace, base::TimeDelta::FromDays(1)); + policy.page_limit = 10; + policy.pages_allowed_per_url = 1; + all_policies.push_back(policy); + } + + PolicyData policy_data; + for (const auto& policy : all_policies) { + policy_data.all_namespaces.push_back(policy.name_space); + switch (policy.lifetime_type) { + case LifetimeType::TEMPORARY: + policy_data.temporary_namespaces.push_back(policy.name_space); + break; + case LifetimeType::PERSISTENT: + policy_data.persistent_namespaces.push_back(policy.name_space); + break; + } + policy_data.policies.emplace(policy.name_space, policy); + } + + return policy_data; +} + +const PolicyData& GetPolicyData() { + static base::NoDestructor<PolicyData> instance(BuildPolicies()); + return *instance; +} + +} // namespace + OfflinePageClientPolicy::OfflinePageClientPolicy(std::string namespace_val, LifetimeType lifetime_type_val) : name_space(namespace_val), lifetime_type(lifetime_type_val) {} +// static +OfflinePageClientPolicy OfflinePageClientPolicy::CreateTemporary( + const std::string& name_space, + const base::TimeDelta& expiration_period) { + OfflinePageClientPolicy policy(name_space, LifetimeType::TEMPORARY); + policy.expiration_period = expiration_period; + return policy; +} + +// static +OfflinePageClientPolicy OfflinePageClientPolicy::CreatePersistent( + const std::string& name_space) { + return {name_space, LifetimeType::PERSISTENT}; +} + OfflinePageClientPolicy::OfflinePageClientPolicy( const OfflinePageClientPolicy& other) = default; OfflinePageClientPolicy::~OfflinePageClientPolicy() = default; +const OfflinePageClientPolicy& GetPolicy(const std::string& name) { + const std::map<std::string, OfflinePageClientPolicy>& policies = + GetPolicyData().policies; + const auto& iter = policies.find(name); + if (iter != policies.end()) + return iter->second; + // Fallback when the namespace isn't defined. + return policies.at(kDefaultNamespace); +} + +const std::vector<std::string>& GetAllPolicyNamespaces() { + return GetPolicyData().all_namespaces; +} +const std::vector<std::string>& GetTemporaryPolicyNamespaces() { + return GetPolicyData().temporary_namespaces; +} +const std::vector<std::string>& GetPersistentPolicyNamespaces() { + return GetPolicyData().persistent_namespaces; +} + } // namespace offline_pages
diff --git a/components/offline_pages/core/offline_page_client_policy.h b/components/offline_pages/core/offline_page_client_policy.h index 3a06d7d..bf29dd10 100644 --- a/components/offline_pages/core/offline_page_client_policy.h +++ b/components/offline_pages/core/offline_page_client_policy.h
@@ -8,6 +8,7 @@ #include <stdint.h> #include <string> +#include <vector> #include "base/time/time.h" @@ -33,6 +34,12 @@ struct OfflinePageClientPolicy { OfflinePageClientPolicy(std::string namespace_val, LifetimeType lifetime_type_val); + static OfflinePageClientPolicy CreateTemporary( + const std::string& name_space, + const base::TimeDelta& expiration_period); + static OfflinePageClientPolicy CreatePersistent( + const std::string& name_space); + OfflinePageClientPolicy(const OfflinePageClientPolicy& other); ~OfflinePageClientPolicy(); @@ -81,6 +88,15 @@ bool defer_background_fetch_while_page_is_active = false; }; +// Get the client policy for |name_space|. +const OfflinePageClientPolicy& GetPolicy(const std::string& name_space); +// Returns a list of all known namespaces. +const std::vector<std::string>& GetAllPolicyNamespaces(); +// Returns a list of all temporary namespaces. +const std::vector<std::string>& GetTemporaryPolicyNamespaces(); +// Returns a list of all persistent namespaces. +const std::vector<std::string>& GetPersistentPolicyNamespaces(); + } // namespace offline_pages #endif // COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_CLIENT_POLICY_H_
diff --git a/components/offline_pages/core/offline_page_client_policy_unittest.cc b/components/offline_pages/core/offline_page_client_policy_unittest.cc new file mode 100644 index 0000000..e7ab113f --- /dev/null +++ b/components/offline_pages/core/offline_page_client_policy_unittest.cc
@@ -0,0 +1,205 @@ +// 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/offline_pages/core/offline_page_client_policy.h" + +#include <algorithm> +#include <memory> +#include <set> + +#include "base/stl_util.h" +#include "components/offline_pages/core/client_namespace_constants.h" +#include "components/offline_pages/core/offline_page_feature.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { + +namespace { +const char kUndefinedNamespace[] = "undefined"; + +bool isTemporary(const OfflinePageClientPolicy& policy) { + return policy.lifetime_type == LifetimeType::TEMPORARY; +} +} // namespace + +class ClientPolicyTest : public testing::Test { + public: + // testing::Test + void SetUp() override {} + void TearDown() override {} + + protected: + void ExpectTemporary(std::string name_space); + void ExpectDownloadSupport(std::string name_space, bool expectation); + void ExpectPersistent(std::string name_space); + void ExpectRestrictedToTabFromClientId(std::string name_space, + bool expectation); + void ExpectRequiresSpecificUserSettings(std::string name_space, + bool expectation); +}; + +void ClientPolicyTest::ExpectTemporary(std::string name_space) { + EXPECT_TRUE(base::Contains(GetTemporaryPolicyNamespaces(), name_space)) + << "Namespace " << name_space + << " had incorrect lifetime type when getting temporary namespaces."; + EXPECT_EQ(GetPolicy(name_space).lifetime_type, LifetimeType::TEMPORARY) + << "Namespace " << name_space + << " had incorrect lifetime type setting when directly checking" + " if it is temporary."; + EXPECT_FALSE(base::Contains(GetPersistentPolicyNamespaces(), name_space)) + << "Namespace " << name_space + << " had incorrect lifetime type when getting persistent namespaces."; +} + +void ClientPolicyTest::ExpectDownloadSupport(std::string name_space, + bool expectation) { + EXPECT_EQ(expectation, GetPolicy(name_space).is_supported_by_download) + << "Namespace " << name_space + << " had incorrect download support when directly checking if supported" + " by download."; +} + +void ClientPolicyTest::ExpectPersistent(std::string name_space) { + EXPECT_FALSE(base::Contains(GetTemporaryPolicyNamespaces(), name_space)) + << "Namespace " << name_space + << " had incorrect lifetime type when getting temporary namespaces."; + EXPECT_EQ(GetPolicy(name_space).lifetime_type, LifetimeType::PERSISTENT) + << "Namespace " << name_space + << " had incorrect lifetime type setting when directly checking" + " if it is temporary."; + EXPECT_TRUE(base::Contains(GetPersistentPolicyNamespaces(), name_space)) + << "Namespace " << name_space + << " had incorrect lifetime type when getting persistent namespaces."; +} + +void ClientPolicyTest::ExpectRestrictedToTabFromClientId(std::string name_space, + bool expectation) { + EXPECT_EQ(expectation, + GetPolicy(name_space).is_restricted_to_tab_from_client_id) + << "Namespace " << name_space + << " had incorrect restriction when directly checking if the namespace" + " is restricted to the tab from the client id field"; +} + +void ClientPolicyTest::ExpectRequiresSpecificUserSettings( + std::string name_space, + bool expectation) { + EXPECT_EQ(expectation, GetPolicy(name_space).requires_specific_user_settings) + << "Namespace " << name_space + << " had incorrect download support when directly checking if disabled" + " when prefetch settings are disabled."; +} + +TEST_F(ClientPolicyTest, FallbackTest) { + const OfflinePageClientPolicy& policy = GetPolicy(kUndefinedNamespace); + EXPECT_EQ(policy.name_space, kDefaultNamespace); + EXPECT_TRUE(isTemporary(policy)); + ExpectTemporary(kDefaultNamespace); + EXPECT_FALSE( + base::Contains(GetTemporaryPolicyNamespaces(), kUndefinedNamespace)); + EXPECT_EQ(GetPolicy(kUndefinedNamespace).lifetime_type, + LifetimeType::TEMPORARY); + ExpectDownloadSupport(kUndefinedNamespace, false); + ExpectDownloadSupport(kDefaultNamespace, false); + ExpectRestrictedToTabFromClientId(kUndefinedNamespace, false); + ExpectRestrictedToTabFromClientId(kDefaultNamespace, false); + ExpectRequiresSpecificUserSettings(kUndefinedNamespace, false); + ExpectRequiresSpecificUserSettings(kDefaultNamespace, false); +} + +TEST_F(ClientPolicyTest, CheckBookmarkDefined) { + OfflinePageClientPolicy policy = GetPolicy(kBookmarkNamespace); + EXPECT_EQ(policy.name_space, kBookmarkNamespace); + EXPECT_TRUE(isTemporary(policy)); + ExpectTemporary(kBookmarkNamespace); + ExpectDownloadSupport(kBookmarkNamespace, false); + ExpectRestrictedToTabFromClientId(kBookmarkNamespace, false); + ExpectRequiresSpecificUserSettings(kBookmarkNamespace, false); +} + +TEST_F(ClientPolicyTest, CheckLastNDefined) { + OfflinePageClientPolicy policy = GetPolicy(kLastNNamespace); + EXPECT_EQ(policy.name_space, kLastNNamespace); + EXPECT_TRUE(isTemporary(policy)); + ExpectTemporary(kLastNNamespace); + ExpectDownloadSupport(kLastNNamespace, false); + ExpectRestrictedToTabFromClientId(kLastNNamespace, true); + ExpectRequiresSpecificUserSettings(kLastNNamespace, false); +} + +TEST_F(ClientPolicyTest, CheckAsyncDefined) { + OfflinePageClientPolicy policy = GetPolicy(kAsyncNamespace); + EXPECT_EQ(policy.name_space, kAsyncNamespace); + EXPECT_FALSE(isTemporary(policy)); + ExpectDownloadSupport(kAsyncNamespace, true); + ExpectPersistent(kAsyncNamespace); + ExpectRestrictedToTabFromClientId(kAsyncNamespace, false); + ExpectRequiresSpecificUserSettings(kAsyncNamespace, false); +} + +TEST_F(ClientPolicyTest, CheckCCTDefined) { + OfflinePageClientPolicy policy = GetPolicy(kCCTNamespace); + EXPECT_EQ(policy.name_space, kCCTNamespace); + EXPECT_TRUE(isTemporary(policy)); + ExpectTemporary(kCCTNamespace); + ExpectDownloadSupport(kCCTNamespace, false); + ExpectRestrictedToTabFromClientId(kCCTNamespace, false); + ExpectRequiresSpecificUserSettings(kCCTNamespace, true); +} + +TEST_F(ClientPolicyTest, CheckDownloadDefined) { + OfflinePageClientPolicy policy = GetPolicy(kDownloadNamespace); + EXPECT_EQ(policy.name_space, kDownloadNamespace); + EXPECT_FALSE(isTemporary(policy)); + ExpectDownloadSupport(kDownloadNamespace, true); + ExpectPersistent(kDownloadNamespace); + ExpectRestrictedToTabFromClientId(kDownloadNamespace, false); + ExpectRequiresSpecificUserSettings(kDownloadNamespace, false); +} + +TEST_F(ClientPolicyTest, CheckNTPSuggestionsDefined) { + OfflinePageClientPolicy policy = GetPolicy(kNTPSuggestionsNamespace); + EXPECT_EQ(policy.name_space, kNTPSuggestionsNamespace); + EXPECT_FALSE(isTemporary(policy)); + ExpectDownloadSupport(kNTPSuggestionsNamespace, true); + ExpectPersistent(kNTPSuggestionsNamespace); + ExpectRestrictedToTabFromClientId(kNTPSuggestionsNamespace, false); + ExpectRequiresSpecificUserSettings(kNTPSuggestionsNamespace, false); +} + +TEST_F(ClientPolicyTest, CheckSuggestedArticlesDefined) { + OfflinePageClientPolicy policy = GetPolicy(kSuggestedArticlesNamespace); + EXPECT_EQ(policy.name_space, kSuggestedArticlesNamespace); + EXPECT_TRUE(isTemporary(policy)); + ExpectTemporary(kSuggestedArticlesNamespace); + ExpectDownloadSupport(kSuggestedArticlesNamespace, IsOfflinePagesEnabled()); + ExpectRestrictedToTabFromClientId(kSuggestedArticlesNamespace, false); + ExpectRequiresSpecificUserSettings(kSuggestedArticlesNamespace, false); +} + +TEST_F(ClientPolicyTest, CheckLivePageSharingDefined) { + OfflinePageClientPolicy policy = GetPolicy(kLivePageSharingNamespace); + EXPECT_EQ(policy.name_space, kLivePageSharingNamespace); + EXPECT_TRUE(isTemporary(policy)); + ExpectTemporary(kLivePageSharingNamespace); + ExpectDownloadSupport(kLivePageSharingNamespace, false); + ExpectRestrictedToTabFromClientId(kLivePageSharingNamespace, true); + ExpectRequiresSpecificUserSettings(kLivePageSharingNamespace, false); +} + +TEST_F(ClientPolicyTest, AllTemporaryNamespaces) { + std::vector<std::string> all_namespaces = GetAllPolicyNamespaces(); + const std::vector<std::string>& cache_reset_namespaces_list = + GetTemporaryPolicyNamespaces(); + std::set<std::string> cache_reset_namespaces( + cache_reset_namespaces_list.begin(), cache_reset_namespaces_list.end()); + for (auto name_space : cache_reset_namespaces) { + if (cache_reset_namespaces.count(name_space) > 0) + ExpectTemporary(name_space); + else + ExpectPersistent(name_space); + } +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/offline_page_metadata_store_test_util.cc b/components/offline_pages/core/offline_page_metadata_store_test_util.cc index 2b67495..b121417 100644 --- a/components/offline_pages/core/offline_page_metadata_store_test_util.cc +++ b/components/offline_pages/core/offline_page_metadata_store_test_util.cc
@@ -94,7 +94,7 @@ criteria.offline_ids = std::vector<int64_t>{offline_id}; OfflinePageItem* page = nullptr; auto task = std::make_unique<GetPagesTask>( - store(), nullptr, criteria, + store(), criteria, base::BindOnce( [](OfflinePageItem** out_page, const std::vector<OfflinePageItem>& cb_pages) {
diff --git a/components/offline_pages/core/offline_page_model.h b/components/offline_pages/core/offline_page_model.h index 8a1f1d87..86c8e5a 100644 --- a/components/offline_pages/core/offline_page_model.h +++ b/components/offline_pages/core/offline_page_model.h
@@ -14,7 +14,6 @@ #include "base/supports_user_data.h" #include "components/keyed_service/core/keyed_service.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_event_logger.h" #include "components/offline_pages/core/offline_page_archive_publisher.h" #include "components/offline_pages/core/offline_page_archiver.h" @@ -191,9 +190,6 @@ const OfflinePageItem& offline_page, PublishPageCallback publish_done_callback) = 0; - // Returns the policy controller. - virtual ClientPolicyController* GetPolicyController() = 0; - // Get the archive directory based on client policy of the namespace. virtual const base::FilePath& GetInternalArchiveDirectory( const std::string& name_space) const = 0;
diff --git a/components/offline_pages/core/page_criteria.cc b/components/offline_pages/core/page_criteria.cc index 11f64128..b1dd8ca2 100644 --- a/components/offline_pages/core/page_criteria.cc +++ b/components/offline_pages/core/page_criteria.cc
@@ -6,7 +6,6 @@ #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_item_utils.h" @@ -18,9 +17,7 @@ PageCriteria::PageCriteria(const PageCriteria&) = default; PageCriteria::PageCriteria(PageCriteria&&) = default; -bool MeetsCriteria(const ClientPolicyController& policy_controller, - const PageCriteria& criteria, - const ClientId& client_id) { +bool MeetsCriteria(const PageCriteria& criteria, const ClientId& client_id) { if (criteria.client_ids && !base::Contains(criteria.client_ids.value(), client_id)) { return false; @@ -32,12 +29,10 @@ } if (!criteria.guid.empty() && client_id.id != criteria.guid) return false; - // Only fetches the policy if it will be needed allowing simpler criteria - // queries to not require a ClientPolicyController instance. + // Only fetches the policy if it will be needed. if (criteria.exclude_tab_bound_pages || criteria.pages_for_tab_id || criteria.supported_by_downloads || criteria.lifetime_type) { - const OfflinePageClientPolicy& policy = - policy_controller.GetPolicy(client_id.name_space); + const OfflinePageClientPolicy& policy = GetPolicy(client_id.name_space); if (criteria.exclude_tab_bound_pages && policy.is_restricted_to_tab_from_client_id) { return false; @@ -61,10 +56,8 @@ return true; } -bool MeetsCriteria(const ClientPolicyController& policy_controller, - const PageCriteria& criteria, - const OfflinePageItem& item) { - if (!MeetsCriteria(policy_controller, criteria, item.client_id)) +bool MeetsCriteria(const PageCriteria& criteria, const OfflinePageItem& item) { + if (!MeetsCriteria(criteria, item.client_id)) return false; if (criteria.file_size && item.file_size != criteria.file_size.value()) @@ -95,22 +88,20 @@ } std::vector<std::string> PotentiallyMatchingNamespaces( - const ClientPolicyController& policy_controller, const PageCriteria& criteria) { std::vector<std::string> matching_namespaces; if (criteria.supported_by_downloads || criteria.lifetime_type) { std::vector<std::string> allowed_namespaces = criteria.client_namespaces ? criteria.client_namespaces.value() - : policy_controller.GetAllNamespaces(); + : GetAllPolicyNamespaces(); std::vector<std::string> filtered; for (const std::string& name_space : allowed_namespaces) { - if (criteria.supported_by_downloads && - !policy_controller.IsSupportedByDownload(name_space)) { + const OfflinePageClientPolicy& policy = GetPolicy(name_space); + if (criteria.supported_by_downloads && !policy.is_supported_by_download) { continue; } if (criteria.lifetime_type && - criteria.lifetime_type.value() != - policy_controller.GetPolicy(name_space).lifetime_type) { + criteria.lifetime_type.value() != policy.lifetime_type) { continue; } matching_namespaces.push_back(name_space);
diff --git a/components/offline_pages/core/page_criteria.h b/components/offline_pages/core/page_criteria.h index 4725917..df4b34d0 100644 --- a/components/offline_pages/core/page_criteria.h +++ b/components/offline_pages/core/page_criteria.h
@@ -17,7 +17,6 @@ #include "url/gurl.h" namespace offline_pages { -class ClientPolicyController; struct OfflinePageItem; // Criteria for matching an offline page. The default |PageCriteria| matches @@ -76,19 +75,14 @@ // Returns true if an offline page with |client_id| could potentially match // |criteria|. -bool MeetsCriteria(const ClientPolicyController& policy_controller, - const PageCriteria& criteria, - const ClientId& client_id); +bool MeetsCriteria(const PageCriteria& criteria, const ClientId& client_id); // Returns whether |item| matches |criteria|. -bool MeetsCriteria(const ClientPolicyController& policy_controller, - const PageCriteria& criteria, - const OfflinePageItem& item); +bool MeetsCriteria(const PageCriteria& criteria, const OfflinePageItem& item); // Returns the list of offline page namespaces that could potentially match // Criteria. Returns an empty list if any namespace could match. std::vector<std::string> PotentiallyMatchingNamespaces( - const ClientPolicyController& policy_controller, const PageCriteria& criteria); } // namespace offline_pages
diff --git a/components/offline_pages/core/page_criteria_unittest.cc b/components/offline_pages/core/page_criteria_unittest.cc index d179e85..8db3774e2 100644 --- a/components/offline_pages/core/page_criteria_unittest.cc +++ b/components/offline_pages/core/page_criteria_unittest.cc
@@ -6,7 +6,6 @@ #include "base/bind.h" #include "components/offline_pages/core/client_namespace_constants.h" -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_page_item.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,8 +24,6 @@ } class PageCriteriaTest : public testing::Test { - protected: - ClientPolicyController policy_controller_; }; TEST_F(PageCriteriaTest, MeetsCriteria_Url) { @@ -36,13 +33,13 @@ OfflinePageItem item; item.url = TestURLWithFragment(); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.url = TestURL(); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.url = OtherURL(); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_UrlWithFragment) { @@ -52,13 +49,13 @@ OfflinePageItem item; item.url = TestURLWithFragment(); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.url = TestURL(); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.url = OtherURL(); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_ExcludeTabBoundPages) { @@ -67,13 +64,13 @@ OfflinePageItem item; item.client_id.name_space = kLastNNamespace; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id.name_space = ""; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id.name_space = kDownloadNamespace; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_PagesForTabId) { @@ -83,17 +80,17 @@ OfflinePageItem item; item.client_id.id = "0"; item.client_id.name_space = kLastNNamespace; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); // Namespace not restricted to tab. item.client_id.id = "1"; item.client_id.name_space = kDownloadNamespace; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); // Different tab id. item.client_id.id = "1"; item.client_id.name_space = kLastNNamespace; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_SupportedByDownloads) { @@ -102,12 +99,12 @@ OfflinePageItem item; item.client_id.name_space = kDownloadNamespace; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item.client_id)); item.client_id.name_space = kLastNNamespace; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item.client_id)); } TEST_F(PageCriteriaTest, MeetsCriteria_PersistentLifetime) { @@ -116,12 +113,12 @@ OfflinePageItem item; item.client_id.name_space = kDownloadNamespace; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item.client_id)); item.client_id.name_space = kLastNNamespace; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item.client_id)); } TEST_F(PageCriteriaTest, MeetsCriteria_TemporaryLifetime) { @@ -130,12 +127,12 @@ OfflinePageItem item; item.client_id.name_space = kLastNNamespace; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item.client_id)); item.client_id.name_space = kDownloadNamespace; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item.client_id)); } TEST_F(PageCriteriaTest, MeetsCriteria_FileSize) { @@ -144,13 +141,13 @@ OfflinePageItem item; item.file_size = 123; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.file_size = 124; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.file_size = 0; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_Digest) { @@ -159,13 +156,13 @@ OfflinePageItem item; item.digest = "abc"; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.digest = ""; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.digest = "def"; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_Namespaces) { @@ -174,16 +171,16 @@ OfflinePageItem item; item.client_id.name_space = "namespace1"; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item.client_id)); item.client_id.name_space = "namespace2"; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item.client_id)); item.client_id.name_space = ""; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item.client_id)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item.client_id)); } TEST_F(PageCriteriaTest, MeetsCriteria_MultipleNamespaces) { @@ -193,19 +190,19 @@ OfflinePageItem item; item.client_id.name_space = "namespace1"; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id.name_space = "foobar1"; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id.name_space = "namespace"; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id.name_space = "foobar"; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id.name_space = ""; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_ClientId) { @@ -214,16 +211,16 @@ OfflinePageItem item; item.client_id = ClientId("namespace1", "id"); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace2", "id"); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace1", "id2"); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id = ClientId(); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_MultipleClientId) { @@ -234,25 +231,25 @@ OfflinePageItem item; item.client_id = ClientId("namespace1", "id"); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace2", "id"); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace3", "id3"); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace", "i"); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace", ""); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id = ClientId("name", "id"); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace", "foo"); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_Guid) { @@ -261,16 +258,16 @@ OfflinePageItem item; item.client_id = ClientId("namespace", "abc"); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace2", "abc"); - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.client_id = ClientId("namespace", "abcd"); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.client_id = ClientId(); - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_RequestOrigin) { @@ -279,13 +276,13 @@ OfflinePageItem item; item.request_origin = "abc"; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.request_origin = "abcd"; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); item.request_origin = ""; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_OfflineId) { @@ -294,10 +291,10 @@ OfflinePageItem item; item.offline_id = 5; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.offline_id = 4; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } TEST_F(PageCriteriaTest, MeetsCriteria_AdditionalCriteria) { @@ -307,10 +304,10 @@ OfflinePageItem item; item.offline_id = 5; - EXPECT_TRUE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_TRUE(MeetsCriteria(criteria, item)); item.offline_id = 4; - EXPECT_FALSE(MeetsCriteria(policy_controller_, criteria, item)); + EXPECT_FALSE(MeetsCriteria(criteria, item)); } } // namespace
diff --git a/components/offline_pages/core/stub_offline_page_model.cc b/components/offline_pages/core/stub_offline_page_model.cc index b90e2ca01e..7163dc2 100644 --- a/components/offline_pages/core/stub_offline_page_model.cc +++ b/components/offline_pages/core/stub_offline_page_model.cc
@@ -64,9 +64,6 @@ return archive_directory_.IsParent(file_path); } -ClientPolicyController* StubOfflinePageModel::GetPolicyController() { - return &policy_controller_; -} OfflineEventLogger* StubOfflinePageModel::GetLogger() { return nullptr; }
diff --git a/components/offline_pages/core/stub_offline_page_model.h b/components/offline_pages/core/stub_offline_page_model.h index e076671f..05e207e8 100644 --- a/components/offline_pages/core/stub_offline_page_model.h +++ b/components/offline_pages/core/stub_offline_page_model.h
@@ -10,7 +10,6 @@ #include <string> #include <vector> -#include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_page_model.h" namespace offline_pages { @@ -57,11 +56,9 @@ const base::FilePath& GetInternalArchiveDirectory( const std::string& name_space) const override; bool IsArchiveInInternalDir(const base::FilePath& file_path) const override; - ClientPolicyController* GetPolicyController() override; OfflineEventLogger* GetLogger() override; private: - ClientPolicyController policy_controller_; std::vector<int64_t> offline_ids_; base::FilePath archive_directory_; };
diff --git a/components/safe_browsing/db/v4_database.cc b/components/safe_browsing/db/v4_database.cc index 303da575..cad85de 100644 --- a/components/safe_browsing/db/v4_database.cc +++ b/components/safe_browsing/db/v4_database.cc
@@ -69,9 +69,9 @@ const scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner = base::ThreadTaskRunnerHandle::Get(); db_task_runner->PostTask( - FROM_HERE, base::BindOnce(&V4Database::CreateOnTaskRunner, db_task_runner, - base_path, list_infos, callback_task_runner, - new_db_callback, TimeTicks::Now())); + FROM_HERE, + base::BindOnce(&V4Database::CreateOnTaskRunner, db_task_runner, base_path, + list_infos, callback_task_runner, new_db_callback)); } // static @@ -80,8 +80,7 @@ const base::FilePath& base_path, const ListInfos& list_infos, const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, - NewDatabaseReadyCallback new_db_callback, - const TimeTicks create_start_time) { + NewDatabaseReadyCallback new_db_callback) { DCHECK(db_task_runner->RunsTasksInCurrentSequence()); if (!g_store_factory.Get()) @@ -112,9 +111,6 @@ // thread. This would unblock resource loads. callback_task_runner->PostTask( FROM_HERE, base::BindOnce(new_db_callback, std::move(v4_database))); - - UMA_HISTOGRAM_TIMES("SafeBrowsing.V4DatabaseOpen.Time", - TimeTicks::Now() - create_start_time); } // static
diff --git a/components/safe_browsing/db/v4_database.h b/components/safe_browsing/db/v4_database.h index 459e744..2fe43952 100644 --- a/components/safe_browsing/db/v4_database.h +++ b/components/safe_browsing/db/v4_database.h
@@ -198,8 +198,7 @@ const base::FilePath& base_path, const ListInfos& list_infos, const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, - NewDatabaseReadyCallback callback, - const base::TimeTicks create_start_time); + NewDatabaseReadyCallback callback); // Makes the passed |factory| the factory used to instantiate a V4Database. // Only for tests.
diff --git a/components/sync/driver/glue/sync_engine_backend.cc b/components/sync/driver/glue/sync_engine_backend.cc index 6a043063..2539c36 100644 --- a/components/sync/driver/glue/sync_engine_backend.cc +++ b/components/sync/driver/glue/sync_engine_backend.cc
@@ -348,8 +348,8 @@ nigori_controller_ = std::make_unique<ModelTypeController>( NIGORI, std::make_unique<ForwardingModelTypeControllerDelegate>( nigori_processor->GetControllerDelegate().get())); - sync_encryption_handler_ = - std::make_unique<NigoriSyncBridgeImpl>(std::move(nigori_processor)); + sync_encryption_handler_ = std::make_unique<NigoriSyncBridgeImpl>( + std::move(nigori_processor), &encryptor_); } else { sync_encryption_handler_ = std::make_unique<SyncEncryptionHandlerImpl>( &user_share_, &encryptor_, params.restored_key_for_bootstrapping,
diff --git a/components/sync/nigori/cryptographer.h b/components/sync/nigori/cryptographer.h index 2eea3102..49a38389 100644 --- a/components/sync/nigori/cryptographer.h +++ b/components/sync/nigori/cryptographer.h
@@ -180,7 +180,8 @@ std::string GetDefaultNigoriKeyName() const; // Returns a serialized sync_pb::NigoriKey version of current default - // encryption key. + // encryption key. Returns empty string if Cryptographer is not initialized + // or protobuf serialization error occurs. std::string GetDefaultNigoriKeyData() const; // Generates a new Nigori from |serialized_nigori_key|, and if successful
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.cc b/components/sync/nigori/nigori_sync_bridge_impl.cc index 60b3f69..ca1fb10e 100644 --- a/components/sync/nigori/nigori_sync_bridge_impl.cc +++ b/components/sync/nigori/nigori_sync_bridge_impl.cc
@@ -8,6 +8,7 @@ #include "base/base64.h" #include "base/location.h" +#include "components/sync/base/encryptor.h" #include "components/sync/base/passphrase_enums.h" #include "components/sync/base/sync_base_switches.h" #include "components/sync/base/time.h" @@ -337,13 +338,39 @@ specifics->set_encrypt_web_apps(encrypted_types.Has(WEB_APPS)); } +// Packs explicit passphrase key in order to persist it. Should be aligned with +// Directory implementation (Cryptographer::GetBootstrapToken()) unless it is +// removed. Returns empty string in case of errors. +std::string PackExplicitPassphraseKey(const Encryptor& encryptor, + const Cryptographer& cryptographer) { + // Explicit passphrase key should always be default one. + std::string serialized_key = cryptographer.GetDefaultNigoriKeyData(); + if (serialized_key.empty()) { + DLOG(ERROR) << "Failed to serialize explicit passphrase key."; + return std::string(); + } + + std::string encrypted_key; + if (!encryptor.EncryptString(serialized_key, &encrypted_key)) { + DLOG(ERROR) << "Failed to encrypt explicit passphrase key."; + return std::string(); + } + + std::string encoded_key; + base::Base64Encode(encrypted_key, &encoded_key); + return encoded_key; +} + } // namespace NigoriSyncBridgeImpl::NigoriSyncBridgeImpl( - std::unique_ptr<NigoriLocalChangeProcessor> processor) - : processor_(std::move(processor)), + std::unique_ptr<NigoriLocalChangeProcessor> processor, + const Encryptor* encryptor) + : encryptor_(encryptor), + processor_(std::move(processor)), passphrase_type_(NigoriSpecifics::UNKNOWN), encrypt_everything_(false) { + DCHECK(encryptor); processor_->ModelReadyToSync(this, NigoriMetadataBatch()); } @@ -427,9 +454,9 @@ observer.OnEncryptedTypesChanged(EncryptableUserTypes(), encrypt_everything_); } + MaybeNotifyBootstrapTokenUpdated(); // OnLocalSetPassphraseEncryption() is intentionally not called here, because // it's needed only for the Directory implementation unit tests. - // TODO(crbug.com/922900): persist |passphrase| in corresponding storage. // TODO(crbug.com/922900): support SCRYPT key derivation method. NOTIMPLEMENTED(); } @@ -437,8 +464,8 @@ void NigoriSyncBridgeImpl::SetDecryptionPassphrase( const std::string& passphrase) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // |passphrase| should be a valid one already (verified by the UI part, using - // pending keys exposed by OnPassphraseRequired()). + // |passphrase| should be a valid one already (verified by SyncServiceCrypto, + // using pending keys exposed by OnPassphraseRequired()). DCHECK(!passphrase.empty()); DCHECK(cryptographer_.has_pending_keys()); KeyParams key_params = {GetKeyDerivationParamsForPendingKeys(), passphrase}; @@ -466,7 +493,7 @@ for (auto& observer : observers_) { observer.OnPassphraseAccepted(); } - // TODO(crbug.com/922900): persist |passphrase| in corresponding storage. + MaybeNotifyBootstrapTokenUpdated(); // TODO(crbug.com/922900): we may need to rewrite encryption_keybag in Nigori // node in case we have some keys in |cryptographer_| which is not stored in // encryption_keybag yet. @@ -831,4 +858,29 @@ } } +void NigoriSyncBridgeImpl::MaybeNotifyBootstrapTokenUpdated() const { + switch (passphrase_type_) { + case NigoriSpecifics::UNKNOWN: + case NigoriSpecifics::IMPLICIT_PASSPHRASE: + NOTREACHED(); + return; + case NigoriSpecifics::KEYSTORE_PASSPHRASE: + // TODO(crbug.com/922900): notify about keystore bootstrap token updates. + NOTIMPLEMENTED(); + return; + case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE: + case NigoriSpecifics::CUSTOM_PASSPHRASE: + // |packed_custom_passphrase_key| will be empty in case serialization or + // encryption error occurs. + std::string packed_custom_passphrase_key = + PackExplicitPassphraseKey(*encryptor_, cryptographer_); + if (!packed_custom_passphrase_key.empty()) { + for (auto& observer : observers_) { + observer.OnBootstrapTokenUpdated(packed_custom_passphrase_key, + PASSPHRASE_BOOTSTRAP_TOKEN); + } + } + } +} + } // namespace syncer
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.h b/components/sync/nigori/nigori_sync_bridge_impl.h index 5765b08..f655a832 100644 --- a/components/sync/nigori/nigori_sync_bridge_impl.h +++ b/components/sync/nigori/nigori_sync_bridge_impl.h
@@ -24,6 +24,8 @@ namespace syncer { +class Encryptor; + // USS implementation of SyncEncryptionHandler. // This class holds the current Nigori state and processes incoming changes and // queries: @@ -36,8 +38,9 @@ public NigoriSyncBridge, public SyncEncryptionHandler { public: - explicit NigoriSyncBridgeImpl( - std::unique_ptr<NigoriLocalChangeProcessor> processor); + // |encryptor| must be not null and must outlive this object. + NigoriSyncBridgeImpl(std::unique_ptr<NigoriLocalChangeProcessor> processor, + const Encryptor* encryptor); ~NigoriSyncBridgeImpl() override; // SyncEncryptionHandler implementation. @@ -90,6 +93,13 @@ // |passphrase_type_| is an explicit passphrase. KeyDerivationParams GetKeyDerivationParamsForPendingKeys() const; + // Persists Nigori derived from explicit passphrase into preferences, in case + // error occurs during serialization/encryption, corresponding preference + // just won't be updated. + void MaybeNotifyBootstrapTokenUpdated() const; + + const Encryptor* const encryptor_; + const std::unique_ptr<NigoriLocalChangeProcessor> processor_; // Base64 encoded keystore keys. The last element is the current keystore
diff --git a/components/sync/nigori/nigori_sync_bridge_impl_unittest.cc b/components/sync/nigori/nigori_sync_bridge_impl_unittest.cc index 5cc0301..d38e4a0 100644 --- a/components/sync/nigori/nigori_sync_bridge_impl_unittest.cc +++ b/components/sync/nigori/nigori_sync_bridge_impl_unittest.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/base64.h" +#include "components/sync/base/fake_encryptor.h" #include "components/sync/base/time.h" #include "components/sync/model/entity_data.h" #include "testing/gmock/include/gmock/gmock.h" @@ -152,7 +153,8 @@ auto processor = std::make_unique<testing::NiceMock<MockNigoriLocalChangeProcessor>>(); processor_ = processor.get(); - bridge_ = std::make_unique<NigoriSyncBridgeImpl>(std::move(processor)); + bridge_ = std::make_unique<NigoriSyncBridgeImpl>(std::move(processor), + &encryptor_); bridge_->AddObserver(&observer_); } @@ -238,6 +240,7 @@ } private: + const FakeEncryptor encryptor_; std::unique_ptr<NigoriSyncBridgeImpl> bridge_; // Ownership transferred to |bridge_|. testing::NiceMock<MockNigoriLocalChangeProcessor>* processor_; @@ -500,6 +503,8 @@ EXPECT_CALL(*observer(), OnPassphraseAccepted()); EXPECT_CALL(*observer(), OnCryptographerStateChanged(NotNull())); + EXPECT_CALL(*observer(), OnBootstrapTokenUpdated(Ne(std::string()), + PASSPHRASE_BOOTSTRAP_TOKEN)); bridge()->SetDecryptionPassphrase(passphrase_key_params.password); const Cryptographer& cryptographer = bridge()->GetCryptographerForTesting(); @@ -537,6 +542,8 @@ EXPECT_CALL(*observer(), OnPassphraseTypeChanged(PassphraseType::CUSTOM_PASSPHRASE, /*passphrase_time=*/NotNullTime())); + EXPECT_CALL(*observer(), OnBootstrapTokenUpdated(Ne(std::string()), + PASSPHRASE_BOOTSTRAP_TOKEN)); EXPECT_CALL(*processor(), Put(HasCustomPassphraseNigori())); bridge()->SetEncryptionPassphrase(kPassphraseKeyParams.password); EXPECT_THAT(bridge()->GetData(), HasCustomPassphraseNigori());
diff --git a/components/translate/ios/DEPS b/components/translate/ios/DEPS index 4dd6307..a63307e7 100644 --- a/components/translate/ios/DEPS +++ b/components/translate/ios/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+ios/web/public", + "+ios/web/common", "+third_party/ocmock", ]
diff --git a/components/translate/ios/browser/BUILD.gn b/components/translate/ios/browser/BUILD.gn index 04276a0..f5e3887c 100644 --- a/components/translate/ios/browser/BUILD.gn +++ b/components/translate/ios/browser/BUILD.gn
@@ -30,6 +30,7 @@ "//components/translate/core/common", "//components/translate/core/language_detection", "//ios/chrome/browser/metrics:ukm_url_recorder", + "//ios/web/common", "//ios/web/public", "//ios/web/public/deprecated", "//ios/web/public/js_messaging",
diff --git a/components/translate/ios/browser/language_detection_controller.mm b/components/translate/ios/browser/language_detection_controller.mm index ac7b521..5ff1aa79 100644 --- a/components/translate/ios/browser/language_detection_controller.mm +++ b/components/translate/ios/browser/language_detection_controller.mm
@@ -17,9 +17,9 @@ #include "components/translate/core/language_detection/language_detection_util.h" #import "components/translate/ios/browser/js_language_detection_manager.h" #include "components/translate/ios/browser/string_clipping_util.h" +#import "ios/web/common/url_scheme_util.h" #include "ios/web/public/js_messaging/web_frame.h" #import "ios/web/public/navigation/navigation_context.h" -#import "ios/web/public/url_scheme_util.h" #include "ios/web/public/web_state/web_state.h" #include "net/http/http_response_headers.h"
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc index 0da5887..1c0767d 100644 --- a/components/viz/common/resources/resource_format_utils.cc +++ b/components/viz/common/resources/resource_format_utils.cc
@@ -435,7 +435,7 @@ case RG_88: return VK_FORMAT_R8G8_UNORM; case RGBA_F16: - return VK_FORMAT_R16_SFLOAT; + return VK_FORMAT_R16G16B16A16_SFLOAT; case R16_EXT: return VK_FORMAT_R16_UNORM; case RGBX_8888:
diff --git a/components/viz/common/skia_helper.cc b/components/viz/common/skia_helper.cc index f6413733..54ab3fa 100644 --- a/components/viz/common/skia_helper.cc +++ b/components/viz/common/skia_helper.cc
@@ -4,6 +4,8 @@ #include "components/viz/common/skia_helper.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" +#include "third_party/skia/include/effects/SkColorFilterImageFilter.h" +#include "third_party/skia/include/effects/SkColorMatrix.h" #include "third_party/skia/include/effects/SkOverdrawColorFilter.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrContext.h" @@ -66,4 +68,11 @@ return SkOverdrawColorFilter::Make(colors); } +sk_sp<SkImageFilter> SkiaHelper::BuildOpacityFilter(float opacity) { + SkColorMatrix matrix; + matrix.setScale(1.f, 1.f, 1.f, opacity); + return SkColorFilterImageFilter::Make(SkColorFilters::Matrix(matrix), + nullptr); +} + } // namespace viz
diff --git a/components/viz/common/skia_helper.h b/components/viz/common/skia_helper.h index 8aefe8f..dc351b7 100644 --- a/components/viz/common/skia_helper.h +++ b/components/viz/common/skia_helper.h
@@ -29,6 +29,8 @@ bool flush); static sk_sp<SkColorFilter> MakeOverdrawColorFilter(); + + static sk_sp<SkImageFilter> BuildOpacityFilter(float opacity); }; } // namespace viz
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc index 5c173202..e2c5be9 100644 --- a/components/viz/service/display/gl_renderer.cc +++ b/components/viz/service/display/gl_renderer.cc
@@ -867,6 +867,8 @@ const gfx::Transform& backdrop_filter_bounds_transform) { DCHECK(ShouldApplyBackdropFilters(params->backdrop_filters)); DCHECK(params->backdrop_filter_quality); + DCHECK(!params->filters) + << "Filters should always be in a separate Effect node"; const RenderPassDrawQuad* quad = params->quad; auto use_gr_context = ScopedUseGrContext::Create(this); @@ -874,19 +876,8 @@ (params->background_rect.top_right() - unclipped_rect.top_right()) + (params->background_rect.bottom_left() - unclipped_rect.bottom_left()); - // Update the backdrop filter to include opacity. - cc::FilterOperations backdrop_filters_plus_opacity = - *params->backdrop_filters; - DCHECK(!params->filters) - << "Filters should always be in a separate Effect node"; - if (quad->shared_quad_state->opacity < 1.0) { - backdrop_filters_plus_opacity.Append( - cc::FilterOperation::CreateOpacityFilter( - quad->shared_quad_state->opacity)); - } - auto paint_filter = cc::RenderSurfaceFilters::BuildImageFilter( - backdrop_filters_plus_opacity, gfx::SizeF(params->background_rect.size()), + *params->backdrop_filters, gfx::SizeF(params->background_rect.size()), gfx::Vector2dF(clipping_offset)); // TODO(senorblanco): background filters should be moved to the @@ -971,6 +962,12 @@ surface->getCanvas()->resetMatrix(); } + SkPaint paint; + // Paint the filtered backdrop image with opacity. + if (quad->shared_quad_state->opacity < 1.0) { + paint.setImageFilter( + SkiaHelper::BuildOpacityFilter(quad->shared_quad_state->opacity)); + } // Apply the mask image, if present, to filtered backdrop content. Note that // this needs to be performed here, in addition to elsewhere, because of the // order of operations: @@ -979,7 +976,6 @@ // 2. Render the parent render pass (containing the "backdrop image" to be // filtered). // 3. Run this code, to filter, and possibly mask, the backdrop image. - SkPaint paint; const SkImage* mask_image = nullptr; base::Optional<DisplayResourceProvider::ScopedReadLockSkImage> backdrop_image_lock;
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc index 3709a55..914075ed 100644 --- a/components/viz/service/display/software_renderer.cc +++ b/components/viz/service/display/software_renderer.cc
@@ -17,6 +17,7 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/quads/tile_draw_quad.h" +#include "components/viz/common/skia_helper.h" #include "components/viz/common/viz_utils.h" #include "components/viz/service/display/output_surface.h" #include "components/viz/service/display/output_surface_frame.h" @@ -803,21 +804,13 @@ (unclipped_rect.top_right() - backdrop_rect.top_right()) + (backdrop_rect.bottom_left() - unclipped_rect.bottom_left()); - // Update the backdrop filter to include opacity. - cc::FilterOperations backdrop_filters_plus_opacity = *backdrop_filters; DCHECK(!regular_filters) << "Filters should always be in a separate Effect node"; - if (quad->shared_quad_state->opacity < 1.0) { - backdrop_filters_plus_opacity.Append( - cc::FilterOperation::CreateOpacityFilter( - quad->shared_quad_state->opacity)); - } - gfx::Rect bitmap_rect = gfx::Rect(0, 0, backdrop_bitmap.width(), backdrop_bitmap.height()); sk_sp<SkImageFilter> filter = cc::RenderSurfaceFilters::BuildImageFilter( - backdrop_filters_plus_opacity, + *backdrop_filters, gfx::SizeF(bitmap_rect.width(), bitmap_rect.height()), clipping_offset) ->cached_sk_filter_; @@ -844,9 +837,16 @@ canvas.resetMatrix(); } + // Paint the filtered backdrop image with opacity. + SkPaint paint; + if (quad->shared_quad_state->opacity < 1.0) { + paint.setImageFilter( + SkiaHelper::BuildOpacityFilter(quad->shared_quad_state->opacity)); + } + // Now paint the pre-filtered image onto the canvas. SkRect bitmap_skrect = RectToSkRect(bitmap_rect); - canvas.drawImageRect(filtered_image, bitmap_skrect, bitmap_skrect, nullptr); + canvas.drawImageRect(filtered_image, bitmap_skrect, bitmap_skrect, &paint); return SkImage::MakeFromBitmap(bitmap)->makeShader( content_tile_mode, content_tile_mode, &filter_backdrop_transform);
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 0a7cb483..3850348e 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -277,6 +277,27 @@ : BackgroundSyncType::PERIODIC; } +std::string GetSyncEventName(const BackgroundSyncType sync_type) { + if (sync_type == BackgroundSyncType::ONE_SHOT) + return "sync"; + else + return "periodicsync"; +} + +DevToolsBackgroundService GetDevToolsBackgroundService( + BackgroundSyncType sync_type) { + if (sync_type == BackgroundSyncType::ONE_SHOT) + return DevToolsBackgroundService::kBackgroundSync; + else + return DevToolsBackgroundService::kPeriodicBackgroundSync; +} + +std::string GetDelayAsString(base::TimeDelta delay) { + if (delay.is_max()) + return "infinite"; + return base::NumberToString(delay.InMilliseconds()); +} + std::string GetEventStatusString(blink::ServiceWorkerStatusCode status_code) { // The |status_code| is derived from blink::mojom::ServiceWorkerEventStatus. switch (status_code) { @@ -603,6 +624,7 @@ return; } + std::set<url::Origin> suspended_periodic_sync_origins; for (const std::pair<int64_t, std::string>& data : user_data) { BackgroundSyncRegistrationsProto registrations_proto; if (registrations_proto.ParseFromString(data.second)) { @@ -638,6 +660,9 @@ registration->set_num_attempts(registration_proto.num_attempts()); registration->set_delay_until( base::Time::FromInternalValue(registration_proto.delay_until())); + if (registration->is_suspended()) { + suspended_periodic_sync_origins.insert(registration->origin()); + } registration->set_resolved(); if (registration_proto.has_max_attempts()) registration->set_max_attempts(registration_proto.max_attempts()); @@ -649,6 +674,8 @@ FireReadyEvents(BackgroundSyncType::ONE_SHOT, base::DoNothing::Once()); FireReadyEvents(BackgroundSyncType::PERIODIC, base::DoNothing::Once()); + proxy_.SendSuspendedPeriodicSyncOrigins( + std::move(suspended_periodic_sync_origins)); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback)); } @@ -862,6 +889,16 @@ return; } + if (registration.sync_type() == BackgroundSyncType::PERIODIC && + ShouldLogToDevTools(registration.sync_type())) { + devtools_context_->LogBackgroundServiceEventOnIO( + sw_registration_id, registration.origin(), + DevToolsBackgroundService::kPeriodicBackgroundSync, + /* event_name= */ "Got next event delay", + /* instance_id= */ registration.options()->tag, + {{"Next Attempt Delay (ms)", GetDelayAsString(delay)}}); + } + AddOrUpdateActiveRegistration( sw_registration_id, url::Origin::Create(sw_registration->scope().GetOrigin()), registration); @@ -1109,9 +1146,20 @@ BackgroundSyncRegistrations* registrations = &active_registrations_[registration_info.service_worker_registration_id]; + const url::Origin& origin = registrations->origin; registrations->registration_map.erase( {registration_info.tag, registration_info.sync_type}); + + if (registration_info.sync_type == BackgroundSyncType::PERIODIC && + ShouldLogToDevTools(registration_info.sync_type)) { + devtools_context_->LogBackgroundServiceEventOnIO( + registration_info.service_worker_registration_id, origin, + DevToolsBackgroundService::kPeriodicBackgroundSync, + /* event_name= */ "Unregistered periodicsync", + /* instance_id= */ registration_info.tag, + /* event_metadata= */ {}); + } } void BackgroundSyncManager::AddOrUpdateActiveRegistration( @@ -1129,12 +1177,16 @@ ->registration_map[{sync_registration.options()->tag, sync_type}] = sync_registration; - if (ShouldLogToDevTools(sync_type)) { + if (ShouldLogToDevTools(sync_registration.sync_type())) { + std::map<std::string, std::string> event_metadata; + if (sync_registration.sync_type() == BackgroundSyncType::PERIODIC) { + event_metadata["minInterval"] = + base::NumberToString(sync_registration.options()->min_interval); + } devtools_context_->LogBackgroundServiceEventOnIO( - sw_registration_id, origin, DevToolsBackgroundService::kBackgroundSync, - /* event_name= */ "Registered sync", - /* instance_id= */ sync_registration.options()->tag, - /* event_metadata= */ {}); + sw_registration_id, origin, GetDevToolsBackgroundService(sync_type), + /* event_name= */ "Registered " + GetSyncEventName(sync_type), + /* instance_id= */ sync_registration.options()->tag, event_metadata); } } @@ -1235,7 +1287,15 @@ base::BindOnce(&OnSyncEventFinished, active_version, request_id, std::move(repeating_callback))); - // TODO(crbug.com/961238): Record Periodic Sync events for DevTools. + if (devtools_context_->IsRecording( + DevToolsBackgroundService::kPeriodicBackgroundSync)) { + devtools_context_->LogBackgroundServiceEventOnIO( + active_version->registration_id(), active_version->script_origin(), + DevToolsBackgroundService::kPeriodicBackgroundSync, + /* event_name= */ "Dispatched periodicsync event", + /* instance_id= */ tag, + /* event_metadata= */ {}); + } } base::CancelableOnceClosure& BackgroundSyncManager::get_delayed_task( @@ -1753,7 +1813,7 @@ if (ShouldLogToDevTools(registration->sync_type())) { devtools_context_->LogBackgroundServiceEventOnIO( registration_info->service_worker_registration_id, origin, - DevToolsBackgroundService::kBackgroundSync, + GetDevToolsBackgroundService(registration->sync_type()), /* event_name= */ "Sync event reregistered", /* instance_id= */ registration_info->tag, /* event_metadata= */ {}); @@ -1765,17 +1825,20 @@ registration->set_delay_until(GetDelayUntilAfterApplyingMinGapForOrigin( registration->origin(), delay)); + std::string event_name = GetSyncEventName(registration->sync_type()) + + (succeeded ? " event completed" : " event failed"); + std::map<std::string, std::string> event_metadata = { + {"Next Attempt Delay (ms)", GetDelayAsString(delay)}}; + if (!succeeded) { + event_metadata.emplace("Failure Reason", + GetEventStatusString(status_code)); + } + if (ShouldLogToDevTools(registration->sync_type())) { - std::string delay_ms = delay.is_max() - ? "infinite" - : base::NumberToString(delay.InMilliseconds()); devtools_context_->LogBackgroundServiceEventOnIO( registration_info->service_worker_registration_id, origin, - DevToolsBackgroundService::kBackgroundSync, - /* event_name= */ "Sync event failed", - /* instance_id= */ registration_info->tag, - {{"Next Attempt Delay (ms)", delay_ms}, - {"Failure Reason", GetEventStatusString(status_code)}}); + GetDevToolsBackgroundService(registration->sync_type()), event_name, + /* instance_id= */ registration_info->tag, event_metadata); } } @@ -1786,7 +1849,7 @@ if (ShouldLogToDevTools(registration->sync_type())) { devtools_context_->LogBackgroundServiceEventOnIO( registration_info->service_worker_registration_id, origin, - DevToolsBackgroundService::kBackgroundSync, + GetDevToolsBackgroundService(registration->sync_type()), /* event_name= */ "Sync completed", /* instance_id= */ registration_info->tag, {{"Status", GetEventStatusString(status_code)}}); @@ -1909,9 +1972,8 @@ } bool BackgroundSyncManager::ShouldLogToDevTools(BackgroundSyncType sync_type) { - return sync_type == BackgroundSyncType::ONE_SHOT && - devtools_context_->IsRecording( - DevToolsBackgroundService::kBackgroundSync); + return devtools_context_->IsRecording( + GetDevToolsBackgroundService(sync_type)); } } // namespace content
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h index cd0ae24..398cf71 100644 --- a/content/browser/background_sync/background_sync_manager.h +++ b/content/browser/background_sync/background_sync_manager.h
@@ -395,7 +395,7 @@ void SetMaxSyncAttemptsImpl(int max_sync_attempts, base::OnceClosure callback); - // Whether an event should be logged for debuggability. + // Whether an event should be logged for debuggability, for |sync_type|. bool ShouldLogToDevTools(blink::mojom::BackgroundSyncType sync_type); base::OnceClosure MakeEmptyCompletion();
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc index abb2a6b..5674277 100644 --- a/content/browser/background_sync/background_sync_manager_unittest.cc +++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -563,6 +563,13 @@ blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected)); } + void InitFailedPeriodicSyncEventTest() { + SetupForPeriodicSyncEvent(base::BindRepeating( + &BackgroundSyncManagerTest::DispatchPeriodicSyncStatusCallback, + base::Unretained(this), + blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected)); + } + void DispatchSyncDelayedCallback( scoped_refptr<ServiceWorkerVersion> active_version, ServiceWorkerVersion::StatusCallback callback) { @@ -2133,6 +2140,56 @@ } } +TEST_F(BackgroundSyncManagerTest, EventsLoggedForPeriodicSyncRegistration) { + storage_partition_impl_->GetDevToolsBackgroundServicesContext() + ->StartRecording(devtools::proto::PERIODIC_BACKGROUND_SYNC); + + SetMaxSyncAttemptsAndRestartManager(3); + InitFailedPeriodicSyncEventTest(); + + { + // We expect a "Registered" event, and a "GotDelay" event. + EXPECT_CALL(*this, OnEventReceived(_)).Times(2); + int thirteen_hours_ms = 13 * 60 * 60 * 1000; + sync_options_1_.min_interval = thirteen_hours_ms; + + EXPECT_TRUE(Register(sync_options_1_)); + EXPECT_TRUE(GetRegistration(sync_options_1_)); + EXPECT_TRUE( + test_background_sync_manager()->IsDelayedTaskScheduledPeriodicSync()); + } + + test_clock_.Advance( + test_background_sync_manager()->delayed_periodic_sync_task_delta()); + { + // Expect a "Fired" event. Dispatch is mocked out, so that event is not + // registered by this test. + EXPECT_CALL(*this, OnEventReceived(_)).Times(1); + test_background_sync_manager()->RunPeriodicSyncDelayedTask(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(GetRegistration(sync_options_1_)); + } + + // The event should succeed now. + InitSyncEventTest(); + + test_clock_.Advance( + test_background_sync_manager()->delayed_periodic_sync_task_delta()); + { + // Expect a "GotDelay" event. + EXPECT_CALL(*this, OnEventReceived(_)).Times(1); + test_background_sync_manager()->RunPeriodicSyncDelayedTask(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(GetRegistration(sync_options_1_)); + } + + { + // Expect a call for "Unregister" event. + EXPECT_CALL(*this, OnEventReceived(_)).Times(1); + Unregister(sync_options_1_); + } +} + TEST_F(BackgroundSyncManagerTest, UkmRecordedAtCompletion) { InitSyncEventTest(); {
diff --git a/content/browser/background_sync/background_sync_proxy.cc b/content/browser/background_sync/background_sync_proxy.cc index 1ddaf7e..2fcd3e3 100644 --- a/content/browser/background_sync/background_sync_proxy.cc +++ b/content/browser/background_sync/background_sync_proxy.cc
@@ -65,6 +65,18 @@ controller->ScheduleBrowserWakeUp(sync_type); } + void SendSuspendedPeriodicSyncOrigins( + std::set<url::Origin> suspended_origins) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!browser_context()) + return; + + auto* controller = browser_context()->GetBackgroundSyncController(); + DCHECK(controller); + + controller->NoteSuspendedPeriodicSyncOrigins(std::move(suspended_origins)); + } + private: base::WeakPtr<BackgroundSyncProxy> io_parent_; scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; @@ -95,4 +107,14 @@ ui_core_weak_ptr_, sync_type)); } +void BackgroundSyncProxy::SendSuspendedPeriodicSyncOrigins( + std::set<url::Origin> suspended_origins) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&Core::SendSuspendedPeriodicSyncOrigins, ui_core_weak_ptr_, + std::move(suspended_origins))); +} + } // namespace content
diff --git a/content/browser/background_sync/background_sync_proxy.h b/content/browser/background_sync/background_sync_proxy.h index 01c72cd6..90fe84e 100644 --- a/content/browser/background_sync/background_sync_proxy.h +++ b/content/browser/background_sync/background_sync_proxy.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_PROXY_H_ #include <memory> +#include <set> #include "base/callback.h" #include "base/memory/weak_ptr.h" @@ -13,6 +14,7 @@ #include "content/common/content_export.h" #include "content/public/browser/browser_thread.h" #include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h" +#include "url/origin.h" namespace content { @@ -29,6 +31,8 @@ ~BackgroundSyncProxy(); void ScheduleBrowserWakeUp(blink::mojom::BackgroundSyncType sync_type); + void SendSuspendedPeriodicSyncOrigins( + std::set<url::Origin> suspended_origins); private: // Constructed on the IO thread, lives and dies on the UI thread.
diff --git a/content/browser/devtools/devtools_background_services.proto b/content/browser/devtools/devtools_background_services.proto index 459f290..070e9c5 100644 --- a/content/browser/devtools/devtools_background_services.proto +++ b/content/browser/devtools/devtools_background_services.proto
@@ -19,9 +19,10 @@ PUSH_MESSAGING = 4; NOTIFICATIONS = 5; PAYMENT_HANDLER = 6; + PERIODIC_BACKGROUND_SYNC = 7; // Keep as last, must have the largest tag value. - COUNT = 7; + COUNT = 8; } // 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 d8c31d5..b0891f03 100644 --- a/content/browser/devtools/devtools_background_services_context_impl.cc +++ b/content/browser/devtools/devtools_background_services_context_impl.cc
@@ -53,6 +53,8 @@ return devtools::proto::NOTIFICATIONS; case DevToolsBackgroundService::kPaymentHandler: return devtools::proto::PAYMENT_HANDLER; + case DevToolsBackgroundService::kPeriodicBackgroundSync: + return devtools::proto::PERIODIC_BACKGROUND_SYNC; } }
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index 0e036011..7fce34ad 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -433,7 +433,7 @@ int routing_id, const std::string& devtools_request_id, const net::CookieStatusList& request_cookie_list, - const std::vector<std::pair<std::string, std::string>>& request_headers) { + const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers) { FrameTreeNode* ftn = GetFtnForNetworkRequest(process_id, routing_id); if (!ftn) return; @@ -447,7 +447,7 @@ int routing_id, const std::string& devtools_request_id, const net::CookieAndLineStatusList& response_cookie_list, - const std::vector<std::pair<std::string, std::string>>& response_headers, + const std::vector<network::mojom::HttpRawHeaderPairPtr>& response_headers, const base::Optional<std::string>& response_headers_text) { FrameTreeNode* ftn = GetFtnForNetworkRequest(process_id, routing_id); if (!ftn)
diff --git a/content/browser/devtools/devtools_instrumentation.h b/content/browser/devtools/devtools_instrumentation.h index 51bfa6b..2207045 100644 --- a/content/browser/devtools/devtools_instrumentation.h +++ b/content/browser/devtools/devtools_instrumentation.h
@@ -14,6 +14,7 @@ #include "base/optional.h" #include "content/common/navigation_params.mojom.h" #include "content/public/browser/certificate_request_result_type.h" +#include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" @@ -118,13 +119,13 @@ int routing_id, const std::string& devtools_request_id, const net::CookieStatusList& request_cookie_list, - const std::vector<std::pair<std::string, std::string>>& request_headers); + const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers); void OnResponseReceivedExtraInfo( int process_id, int routing_id, const std::string& devtools_request_id, const net::CookieAndLineStatusList& response_cookie_list, - const std::vector<std::pair<std::string, std::string>>& response_headers, + const std::vector<network::mojom::HttpRawHeaderPairPtr>& response_headers, const base::Optional<std::string>& response_headers_text); std::vector<std::unique_ptr<NavigationThrottle>> CreateNavigationThrottles(
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index 7ca7f3b..6e71433 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -695,6 +695,19 @@ return Object::fromValue(headers_dict.get(), nullptr); } +std::unique_ptr<Object> GetRawHeaders( + const std::vector<network::mojom::HttpRawHeaderPairPtr>& headers) { + std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create()); + for (const auto& header : headers) { + std::string value; + bool merge_with_another = headers_dict->getString(header->key, &value); + headers_dict->setString(header->key, merge_with_another + ? value + '\n' + header->value + : header->value); + } + return Object::fromValue(headers_dict.get(), nullptr); +} + String GetProtocol(const GURL& url, const network::ResourceResponseInfo& info) { std::string protocol = info.alpn_negotiated_protocol; if (protocol.empty() || protocol == "unknown") { @@ -2454,26 +2467,26 @@ void NetworkHandler::OnRequestWillBeSentExtraInfo( const std::string& devtools_request_id, const net::CookieStatusList& request_cookie_list, - const std::vector<std::pair<std::string, std::string>>& request_headers) { + const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers) { if (!enabled_) return; frontend_->RequestWillBeSentExtraInfo( devtools_request_id, BuildProtocolBlockedCookies(request_cookie_list), - GetHeaders(request_headers)); + GetRawHeaders(request_headers)); } void NetworkHandler::OnResponseReceivedExtraInfo( const std::string& devtools_request_id, const net::CookieAndLineStatusList& response_cookie_list, - const std::vector<std::pair<std::string, std::string>>& response_headers, + const std::vector<network::mojom::HttpRawHeaderPairPtr>& response_headers, const base::Optional<std::string>& response_headers_text) { if (!enabled_) return; frontend_->ResponseReceivedExtraInfo( devtools_request_id, BuildProtocolBlockedSetCookies(response_cookie_list), - GetHeaders(response_headers), + GetRawHeaders(response_headers), response_headers_text.has_value() ? response_headers_text.value() : Maybe<String>()); }
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h index a5b6a8b..d6c42bd2 100644 --- a/content/browser/devtools/protocol/network_handler.h +++ b/content/browser/devtools/protocol/network_handler.h
@@ -191,11 +191,11 @@ void OnRequestWillBeSentExtraInfo( const std::string& devtools_request_id, const net::CookieStatusList& request_cookie_list, - const std::vector<std::pair<std::string, std::string>>& request_headers); + const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers); void OnResponseReceivedExtraInfo( const std::string& devtools_request_id, const net::CookieAndLineStatusList& response_cookie_list, - const std::vector<std::pair<std::string, std::string>>& response_headers, + const std::vector<network::mojom::HttpRawHeaderPairPtr>& response_headers, const base::Optional<std::string>& response_headers_text); bool enabled() const { return enabled_; }
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc index 0380136..33bcde9 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -359,6 +359,8 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableGpu)) *reason += "through commandline switch --disable-gpu."; + else if (hardware_disabled_by_fallback_) + *reason += "due to frequent crashes."; else *reason += "in chrome://settings."; } @@ -904,6 +906,7 @@ #else switch (gpu_mode_) { case gpu::GpuMode::HARDWARE_ACCELERATED: + hardware_disabled_by_fallback_ = true; DisableHardwareAcceleration(); break; case gpu::GpuMode::SWIFTSHADER:
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.h b/content/browser/gpu/gpu_data_manager_impl_private.h index eaa2d3c..f7bca5e 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.h +++ b/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -201,6 +201,9 @@ // What the gpu process is being run for. gpu::GpuMode gpu_mode_ = gpu::GpuMode::HARDWARE_ACCELERATED; + // Used to tell if the gpu was disabled due to process crashes. + bool hardware_disabled_by_fallback_ = false; + // We disable histogram stuff in testing, especially in unit tests because // they cause random failures. bool update_histograms_ = true;
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index fea66c7..2f3c7e91 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -191,9 +191,11 @@ request_info->network_isolation_key; if (request_info->is_main_frame) { + new_request->update_network_isolation_key_on_redirect = network::mojom:: + UpdateNetworkIsolationKeyOnRedirect::kUpdateTopFrameAndFrameOrigin; + } else { new_request->update_network_isolation_key_on_redirect = - network::mojom::UpdateNetworkIsolationKeyOnRedirect:: - kUpdateTopFrameAndInitiatingFrameOrigin; + network::mojom::UpdateNetworkIsolationKeyOnRedirect::kUpdateFrameOrigin; } net::RequestPriority net_priority = net::HIGHEST; @@ -1152,12 +1154,20 @@ resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies; // See if navigation network isolation key needs to be updated. - // TODO(crbug.com/950069): Also add the case for ResourceType::kSubFrame. if (resource_request_->resource_type == static_cast<int>(ResourceType::kMainFrame)) { url::Origin origin = url::Origin::Create(resource_request_->url); resource_request_->trusted_network_isolation_key = net::NetworkIsolationKey(origin, origin); + } else { + DCHECK_EQ(static_cast<int>(ResourceType::kSubFrame), + resource_request_->resource_type); + url::Origin subframe_origin = url::Origin::Create(resource_request_->url); + base::Optional<url::Origin> top_frame_origin = + resource_request_->trusted_network_isolation_key.GetTopFrameOrigin(); + DCHECK(top_frame_origin); + resource_request_->trusted_network_isolation_key = + net::NetworkIsolationKey(top_frame_origin.value(), subframe_origin); } resource_request_->referrer = GURL(redirect_info_.new_referrer);
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index 4e217a1..a3d0bad 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -55,6 +55,7 @@ #include "content/test/content_browser_test_utils_internal.h" #include "content/test/did_commit_navigation_interceptor.h" #include "ipc/ipc_security_test_util.h" +#include "net/base/features.h" #include "net/base/filename_util.h" #include "net/base/load_flags.h" #include "net/dns/mock_host_resolver.h" @@ -252,6 +253,23 @@ NavigationBaseBrowserTest::SetUpOnMainThread(); ASSERT_TRUE(embedded_test_server()->Start()); } +}; + +class NetworkIsolationNavigationBrowserTest + : public ContentBrowserTest, + public ::testing::WithParamInterface<bool> { + protected: + void SetUpOnMainThread() override { + if (GetParam()) { + feature_list_.InitAndEnableFeature( + net::features::kAppendFrameOriginToNetworkIsolationKey); + } else { + feature_list_.InitAndDisableFeature( + net::features::kAppendFrameOriginToNetworkIsolationKey); + } + ASSERT_TRUE(embedded_test_server()->Start()); + ContentBrowserTest::SetUpOnMainThread(); + } // Navigate to |url| and for each ResourceRequest record its // trusted_network_isolation_key. Stop listening after |final_resource| has @@ -292,10 +310,12 @@ // Wait until the last resource we care about has been requested. run_loop.Run(); } + + base::test::ScopedFeatureList feature_list_; }; INSTANTIATE_TEST_SUITE_P(/* no prefix */, - NavigationBrowserTest, + NetworkIsolationNavigationBrowserTest, ::testing::Bool()); // Ensure that browser initiated basic navigations work. @@ -831,7 +851,7 @@ EXPECT_EQ("\"done\"", done); } -IN_PROC_BROWSER_TEST_P(NavigationBrowserTest, +IN_PROC_BROWSER_TEST_P(NetworkIsolationNavigationBrowserTest, BrowserNavigationNetworkIsolationKey) { std::map<GURL, net::NetworkIsolationKey> network_isolation_keys; std::map<GURL, network::mojom::UpdateNetworkIsolationKeyOnRedirect> @@ -845,11 +865,11 @@ EXPECT_EQ(net::NetworkIsolationKey(origin, origin), network_isolation_keys[url]); EXPECT_EQ(network::mojom::UpdateNetworkIsolationKeyOnRedirect:: - kUpdateTopFrameAndInitiatingFrameOrigin, + kUpdateTopFrameAndFrameOrigin, update_network_isolation_key_on_redirects[url]); } -IN_PROC_BROWSER_TEST_P(NavigationBrowserTest, +IN_PROC_BROWSER_TEST_P(NetworkIsolationNavigationBrowserTest, RenderNavigationNetworkIsolationKey) { std::map<GURL, net::NetworkIsolationKey> network_isolation_keys; std::map<GURL, network::mojom::UpdateNetworkIsolationKeyOnRedirect> @@ -863,11 +883,12 @@ EXPECT_EQ(net::NetworkIsolationKey(origin, origin), network_isolation_keys[url]); EXPECT_EQ(network::mojom::UpdateNetworkIsolationKeyOnRedirect:: - kUpdateTopFrameAndInitiatingFrameOrigin, + kUpdateTopFrameAndFrameOrigin, update_network_isolation_key_on_redirects[url]); } -IN_PROC_BROWSER_TEST_P(NavigationBrowserTest, SubframeNetworkIsolationKey) { +IN_PROC_BROWSER_TEST_P(NetworkIsolationNavigationBrowserTest, + SubframeNetworkIsolationKey) { std::map<GURL, net::NetworkIsolationKey> network_isolation_keys; std::map<GURL, network::mojom::UpdateNetworkIsolationKeyOnRedirect> update_network_isolation_key_on_redirects; @@ -882,12 +903,13 @@ EXPECT_EQ(net::NetworkIsolationKey(origin, origin), network_isolation_keys[url]); EXPECT_EQ(network::mojom::UpdateNetworkIsolationKeyOnRedirect:: - kUpdateTopFrameAndInitiatingFrameOrigin, + kUpdateTopFrameAndFrameOrigin, update_network_isolation_key_on_redirects[url]); EXPECT_EQ(net::NetworkIsolationKey(origin, iframe_origin), network_isolation_keys[iframe_document]); - EXPECT_EQ(network::mojom::UpdateNetworkIsolationKeyOnRedirect::kDoNotUpdate, - update_network_isolation_key_on_redirects[iframe_document]); + EXPECT_EQ( + network::mojom::UpdateNetworkIsolationKeyOnRedirect::kUpdateFrameOrigin, + update_network_isolation_key_on_redirects[iframe_document]); } // Helper class to extract the initiator values from URLLoaderFactory calls
diff --git a/content/browser/network_service_client.cc b/content/browser/network_service_client.cc index cb60866..b89e764f 100644 --- a/content/browser/network_service_client.cc +++ b/content/browser/network_service_client.cc
@@ -13,6 +13,7 @@ #include "base/threading/sequence_bound.h" #include "base/unguessable_token.h" #include "content/browser/browsing_data/clear_site_data_handler.h" +#include "content/browser/devtools/devtools_instrumentation.h" #include "content/browser/devtools/devtools_url_loader_interceptor.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" @@ -694,7 +695,7 @@ auth_negotiate->set_can_delegate(can_delegate); auto auth_token = std::make_unique<std::string>(); - auth_negotiate_raw->GenerateAuthToken( + auth_negotiate_raw->GenerateAuthTokenAndroid( nullptr, spn, std::string(), auth_token.get(), base::BindOnce(&FinishGenerateNegotiateAuthToken, std::move(auth_negotiate), std::move(auth_token), @@ -702,4 +703,26 @@ } #endif +void NetworkServiceClient::OnRawRequest( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers) { + devtools_instrumentation::OnRequestWillBeSentExtraInfo( + process_id, routing_id, devtools_request_id, cookies_with_status, + headers); +} + +void NetworkServiceClient::OnRawResponse( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieAndLineStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers, + const base::Optional<std::string>& raw_response_headers) { + devtools_instrumentation::OnResponseReceivedExtraInfo( + process_id, routing_id, devtools_request_id, cookies_with_status, headers, + raw_response_headers); +} } // namespace content
diff --git a/content/browser/network_service_client.h b/content/browser/network_service_client.h index 30f8ac1..0517ef64 100644 --- a/content/browser/network_service_client.h +++ b/content/browser/network_service_client.h
@@ -86,6 +86,19 @@ const std::string& spn, OnGenerateHttpNegotiateAuthTokenCallback callback) override; #endif + void OnRawRequest( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override; + void OnRawResponse( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieAndLineStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers, + const base::Optional<std::string>& raw_response_headers) override; // net::CertDatabase::Observer implementation: void OnCertDBChanged() override;
diff --git a/content/browser/notifications/blink_notification_service_impl.cc b/content/browser/notifications/blink_notification_service_impl.cc index 63a1fe8..ceb4bc62 100644 --- a/content/browser/notifications/blink_notification_service_impl.cc +++ b/content/browser/notifications/blink_notification_service_impl.cc
@@ -89,17 +89,17 @@ BrowserContext* browser_context, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, const url::Origin& origin, - mojo::InterfaceRequest<blink::mojom::NotificationService> request) + mojo::PendingReceiver<blink::mojom::NotificationService> receiver) : notification_context_(notification_context), browser_context_(browser_context), service_worker_context_(std::move(service_worker_context)), origin_(origin), - binding_(this, std::move(request)) { + receiver_(this, std::move(receiver)) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(notification_context_); DCHECK(browser_context_); - binding_.set_connection_error_handler(base::BindOnce( + receiver_.set_disconnect_handler(base::BindOnce( &BlinkNotificationServiceImpl::OnConnectionError, base::Unretained(this) /* the channel is owned by |this| */)); } @@ -129,7 +129,8 @@ const std::string& token, const blink::PlatformNotificationData& platform_notification_data, const blink::NotificationResources& notification_resources, - blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr) { + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> + event_listener_remote) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!ValidateNotificationResources(notification_resources)) return; @@ -147,7 +148,7 @@ NotificationEventDispatcherImpl* event_dispatcher = NotificationEventDispatcherImpl::GetInstance(); event_dispatcher->RegisterNonPersistentNotificationListener( - notification_id, std::move(event_listener_ptr)); + notification_id, std::move(event_listener_remote)); GetNotificationService(browser_context_) ->DisplayNotification(notification_id, origin_.GetURL(), @@ -188,7 +189,7 @@ if (notification_resources.image.drawsNothing() || base::FeatureList::IsEnabled(features::kNotificationContentImage)) return true; - binding_.ReportBadMessage(kBadMessageImproperNotificationImage); + receiver_.ReportBadMessage(kBadMessageImproperNotificationImage); // The above ReportBadMessage() closes |binding_| but does not trigger its // connection error handler, so we need to call the error handler explicitly // here to do some necessary work. @@ -200,7 +201,7 @@ bool BlinkNotificationServiceImpl::ValidateNotificationData( const blink::PlatformNotificationData& notification_data) { if (!CheckNotificationTriggerRange(notification_data)) { - binding_.ReportBadMessage(kBadMessageInvalidNotificationTriggerTimestamp); + receiver_.ReportBadMessage(kBadMessageInvalidNotificationTriggerTimestamp); OnConnectionError(); return false; }
diff --git a/content/browser/notifications/blink_notification_service_impl.h b/content/browser/notifications/blink_notification_service_impl.h index 3b7875f0..5253f6b 100644 --- a/content/browser/notifications/blink_notification_service_impl.h +++ b/content/browser/notifications/blink_notification_service_impl.h
@@ -5,13 +5,17 @@ #ifndef CONTENT_BROWSER_NOTIFICATIONS_BLINK_NOTIFICATION_SERVICE_IMPL_H_ #define CONTENT_BROWSER_NOTIFICATIONS_BLINK_NOTIFICATION_SERVICE_IMPL_H_ +#include <string> +#include <vector> + #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/common/content_export.h" #include "content/public/browser/browser_context.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "third_party/blink/public/mojom/notifications/notification_service.mojom.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" #include "url/origin.h" @@ -37,7 +41,7 @@ BrowserContext* browser_context, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, const url::Origin& origin, - mojo::InterfaceRequest<blink::mojom::NotificationService> request); + mojo::PendingReceiver<blink::mojom::NotificationService> receiver); ~BlinkNotificationServiceImpl() override; // blink::mojom::NotificationService implementation. @@ -46,7 +50,8 @@ const std::string& token, const blink::PlatformNotificationData& platform_notification_data, const blink::NotificationResources& notification_resources, - blink::mojom::NonPersistentNotificationListenerPtr listener_ptr) override; + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> + listener_remote) override; void CloseNonPersistentNotification(const std::string& token) override; void DisplayPersistentNotification( int64_t service_worker_registration_id, @@ -101,7 +106,7 @@ // The origin that this notification service is communicating with. url::Origin origin_; - mojo::Binding<blink::mojom::NotificationService> binding_; + mojo::Receiver<blink::mojom::NotificationService> receiver_; base::WeakPtrFactory<BlinkNotificationServiceImpl> weak_factory_for_io_{this}; base::WeakPtrFactory<BlinkNotificationServiceImpl> weak_factory_for_ui_{this};
diff --git a/content/browser/notifications/blink_notification_service_impl_unittest.cc b/content/browser/notifications/blink_notification_service_impl_unittest.cc index a1f8312..f64eb73 100644 --- a/content/browser/notifications/blink_notification_service_impl_unittest.cc +++ b/content/browser/notifications/blink_notification_service_impl_unittest.cc
@@ -4,6 +4,8 @@ #include <stdint.h> #include <memory> +#include <set> +#include <utility> #include <vector> #include "base/bind.h" @@ -30,8 +32,8 @@ #include "content/test/mock_platform_notification_service.h" #include "content/test/test_content_browser_client.h" #include "mojo/core/embedder/embedder.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/notifications/notification_constants.h" @@ -65,13 +67,14 @@ class MockNonPersistentNotificationListener : public blink::mojom::NonPersistentNotificationListener { public: - MockNonPersistentNotificationListener() : binding_(this) {} + MockNonPersistentNotificationListener() = default; ~MockNonPersistentNotificationListener() override = default; - blink::mojom::NonPersistentNotificationListenerPtr GetPtr() { - blink::mojom::NonPersistentNotificationListenerPtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> + GetRemote() { + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> remote; + receiver_.Bind(remote.InitWithNewPipeAndPassReceiver()); + return remote; } // NonPersistentNotificationListener interface. @@ -84,7 +87,8 @@ } private: - mojo::Binding<blink::mojom::NonPersistentNotificationListener> binding_; + mojo::Receiver<blink::mojom::NonPersistentNotificationListener> receiver_{ + this}; }; // This is for overriding the Platform Notification Service with a mock one. @@ -136,7 +140,7 @@ notification_context_.get(), &browser_context_, embedded_worker_helper_->context_wrapper(), url::Origin::Create(GURL(kTestOrigin)), - mojo::MakeRequest(¬ification_service_ptr_)); + notification_service_remote_.BindNewPipeAndPassReceiver()); // Provide a mock permission manager to the |browser_context_|. browser_context_.SetPermissionControllerDelegate( @@ -293,10 +297,11 @@ const std::string& token, const blink::PlatformNotificationData& platform_notification_data, const blink::NotificationResources& notification_resources, - blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr) { - notification_service_ptr_->DisplayNonPersistentNotification( + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> + event_listener_remote) { + notification_service_remote_->DisplayNonPersistentNotification( token, platform_notification_data, notification_resources, - std::move(event_listener_ptr)); + std::move(event_listener_remote)); // TODO(https://crbug.com/787459): Pass a callback to // DisplayNonPersistentNotification instead of waiting for all tasks to run // here; a callback parameter will be needed anyway to enable @@ -309,9 +314,8 @@ const blink::PlatformNotificationData& platform_notification_data, const blink::NotificationResources& notification_resources) { base::RunLoop run_loop; - notification_service_ptr_.set_connection_error_handler( - run_loop.QuitClosure()); - notification_service_ptr_->DisplayPersistentNotification( + notification_service_remote_.set_disconnect_handler(run_loop.QuitClosure()); + notification_service_remote_->DisplayPersistentNotification( service_worker_registration_id, platform_notification_data, notification_resources, base::BindOnce( @@ -422,7 +426,7 @@ std::unique_ptr<BlinkNotificationServiceImpl> notification_service_; - blink::mojom::NotificationServicePtr notification_service_ptr_; + mojo::Remote<blink::mojom::NotificationService> notification_service_remote_; TestBrowserContext browser_context_; @@ -502,7 +506,7 @@ DisplayNonPersistentNotification( "token", blink::PlatformNotificationData(), blink::NotificationResources(), - non_persistent_notification_listener_.GetPtr()); + non_persistent_notification_listener_.GetRemote()); EXPECT_EQ(1u, GetDisplayedNotifications().size()); } @@ -514,7 +518,7 @@ DisplayNonPersistentNotification( "token", blink::PlatformNotificationData(), blink::NotificationResources(), - non_persistent_notification_listener_.GetPtr()); + non_persistent_notification_listener_.GetRemote()); EXPECT_EQ(0u, GetDisplayedNotifications().size()); } @@ -527,7 +531,7 @@ resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA); DisplayNonPersistentNotification( "token", blink::PlatformNotificationData(), resources, - non_persistent_notification_listener_.GetPtr()); + non_persistent_notification_listener_.GetRemote()); EXPECT_EQ(1u, GetDisplayedNotifications().size()); } @@ -544,7 +548,7 @@ resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA); DisplayNonPersistentNotification( "token", blink::PlatformNotificationData(), resources, - non_persistent_notification_listener_.GetPtr()); + non_persistent_notification_listener_.GetRemote()); EXPECT_EQ(1u, bad_messages_.size()); EXPECT_EQ(kBadMessageImproperNotificationImage, bad_messages_[0]); }
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc index ba2bb907..4caf49c 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.cc +++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -434,11 +434,15 @@ void NotificationEventDispatcherImpl::RegisterNonPersistentNotificationListener( const std::string& notification_id, - blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr) { + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> + event_listener_remote) { + mojo::Remote<blink::mojom::NonPersistentNotificationListener> bound_remote( + std::move(event_listener_remote)); + // Observe connection errors, which occur when the JavaScript object or the // renderer hosting them goes away. (For example through navigation.) The // listener gets freed together with |this|, thus the Unretained is safe. - event_listener_ptr.set_connection_error_handler(base::BindOnce( + bound_remote.set_disconnect_handler(base::BindOnce( &NotificationEventDispatcherImpl:: HandleConnectionErrorForNonPersistentNotificationListener, base::Unretained(this), notification_id)); @@ -455,8 +459,8 @@ non_persistent_notification_listeners_.erase(notification_id); } - non_persistent_notification_listeners_.emplace(notification_id, - std::move(event_listener_ptr)); + non_persistent_notification_listeners_.insert( + {notification_id, std::move(bound_remote)}); } void NotificationEventDispatcherImpl::DispatchNonPersistentShowEvent(
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.h b/content/browser/notifications/notification_event_dispatcher_impl.h index 92de011..4c96848 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.h +++ b/content/browser/notifications/notification_event_dispatcher_impl.h
@@ -6,6 +6,8 @@ #define CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_EVENT_DISPATCHER_IMPL_H_ #include <map> +#include <string> +#include <utility> #include "base/callback_forward.h" #include "base/macros.h" @@ -13,6 +15,8 @@ #include "content/common/content_export.h" #include "content/public/browser/notification_database_data.h" #include "content/public/browser/notification_event_dispatcher.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/notifications/notification_service.mojom.h" namespace content { @@ -51,7 +55,8 @@ // non-persistent notification identified by |notification_id|. void RegisterNonPersistentNotificationListener( const std::string& notification_id, - blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr); + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> + event_listener_remote); private: friend class NotificationEventDispatcherImplTest; @@ -74,7 +79,8 @@ const std::string& notification_id); // Notification Id -> listener. - std::map<std::string, blink::mojom::NonPersistentNotificationListenerPtr> + std::map<std::string, + mojo::Remote<blink::mojom::NonPersistentNotificationListener>> non_persistent_notification_listeners_; DISALLOW_COPY_AND_ASSIGN(NotificationEventDispatcherImpl);
diff --git a/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc b/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc index 4643bdca..cca73db 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc +++ b/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
@@ -6,6 +6,7 @@ #include <stdint.h> #include <memory> +#include <utility> #include <vector> #include "base/bind_helpers.h" @@ -13,8 +14,8 @@ #include "base/test/scoped_task_environment.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/notifications/notification_service.mojom.h" @@ -28,17 +29,18 @@ class TestNotificationListener : public blink::mojom::NonPersistentNotificationListener { public: - TestNotificationListener() : binding_(this) {} + TestNotificationListener() = default; ~TestNotificationListener() override = default; // Closes the bindings associated with this listener. - void Close() { binding_.Close(); } + void Close() { receiver_.reset(); } // Returns an InterfacePtr to this listener. - blink::mojom::NonPersistentNotificationListenerPtr GetPtr() { - blink::mojom::NonPersistentNotificationListenerPtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> + GetRemote() { + mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener> remote; + receiver_.Bind(remote.InitWithNewPipeAndPassReceiver()); + return remote; } // Returns the number of OnShow events received by this listener. @@ -65,7 +67,8 @@ int on_show_count_ = 0; int on_click_count_ = 0; int on_close_count_ = 0; - mojo::Binding<blink::mojom::NonPersistentNotificationListener> binding_; + mojo::Receiver<blink::mojom::NonPersistentNotificationListener> receiver_{ + this}; DISALLOW_COPY_AND_ASSIGN(TestNotificationListener); }; @@ -97,10 +100,10 @@ DispatchNonPersistentShowEvent_NotifiesCorrectRegisteredListener) { auto listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener(kPrimaryUniqueId, - listener->GetPtr()); + listener->GetRemote()); auto other_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kSomeOtherUniqueId, other_listener->GetPtr()); + kSomeOtherUniqueId, other_listener->GetRemote()); dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId); @@ -121,7 +124,7 @@ RegisterNonPersistentListener_FirstListenerGetsOnClose) { auto original_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kPrimaryUniqueId, original_listener->GetPtr()); + kPrimaryUniqueId, original_listener->GetRemote()); dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId); @@ -129,7 +132,7 @@ auto replacement_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kPrimaryUniqueId, replacement_listener->GetPtr()); + kPrimaryUniqueId, replacement_listener->GetRemote()); WaitForMojoTasksToComplete(); @@ -141,7 +144,7 @@ RegisterNonPersistentListener_SecondListenerGetsOnShow) { auto original_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kPrimaryUniqueId, original_listener->GetPtr()); + kPrimaryUniqueId, original_listener->GetRemote()); dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId); @@ -151,7 +154,7 @@ auto replacement_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kPrimaryUniqueId, replacement_listener->GetPtr()); + kPrimaryUniqueId, replacement_listener->GetRemote()); dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId); @@ -165,13 +168,13 @@ RegisterNonPersistentListener_ReplacedListenerGetsOnClick) { auto original_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kPrimaryUniqueId, original_listener->GetPtr()); + kPrimaryUniqueId, original_listener->GetRemote()); dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId); auto replacement_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kPrimaryUniqueId, replacement_listener->GetPtr()); + kPrimaryUniqueId, replacement_listener->GetRemote()); WaitForMojoTasksToComplete(); @@ -190,10 +193,10 @@ DispatchNonPersistentClickEvent_NotifiesCorrectRegisteredListener) { auto listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener(kPrimaryUniqueId, - listener->GetPtr()); + listener->GetRemote()); auto other_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kSomeOtherUniqueId, other_listener->GetPtr()); + kSomeOtherUniqueId, other_listener->GetRemote()); dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId, base::DoNothing()); @@ -216,10 +219,10 @@ DispatchNonPersistentCloseEvent_NotifiesCorrectRegisteredListener) { auto listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener(kPrimaryUniqueId, - listener->GetPtr()); + listener->GetRemote()); auto other_listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener( - kSomeOtherUniqueId, other_listener->GetPtr()); + kSomeOtherUniqueId, other_listener->GetRemote()); dispatcher_->DispatchNonPersistentCloseEvent(kPrimaryUniqueId, base::DoNothing()); @@ -242,7 +245,7 @@ DispatchMultipleNonPersistentEvents_StopsNotifyingAfterClose) { auto listener = std::make_unique<TestNotificationListener>(); dispatcher_->RegisterNonPersistentNotificationListener(kPrimaryUniqueId, - listener->GetPtr()); + listener->GetRemote()); dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId); dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId,
diff --git a/content/browser/notifications/platform_notification_context_impl.cc b/content/browser/notifications/platform_notification_context_impl.cc index 74b9766d..564d4fdb 100644 --- a/content/browser/notifications/platform_notification_context_impl.cc +++ b/content/browser/notifications/platform_notification_context_impl.cc
@@ -208,11 +208,11 @@ void PlatformNotificationContextImpl::CreateService( const url::Origin& origin, - blink::mojom::NotificationServiceRequest request) { + mojo::PendingReceiver<blink::mojom::NotificationService> receiver) { DCHECK_CURRENTLY_ON(BrowserThread::UI); services_.push_back(std::make_unique<BlinkNotificationServiceImpl>( this, browser_context_, service_worker_context_, origin, - std::move(request))); + std::move(receiver))); } void PlatformNotificationContextImpl::RemoveService(
diff --git a/content/browser/notifications/platform_notification_context_impl.h b/content/browser/notifications/platform_notification_context_impl.h index f1710b6..83d7c93 100644 --- a/content/browser/notifications/platform_notification_context_impl.h +++ b/content/browser/notifications/platform_notification_context_impl.h
@@ -24,6 +24,7 @@ #include "content/common/content_export.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/platform_notification_context.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" #include "third_party/blink/public/mojom/notifications/notification_service.mojom.h" class GURL; @@ -65,8 +66,9 @@ void Shutdown(); // Creates a BlinkNotificationServiceImpl that is owned by this context. - void CreateService(const url::Origin& origin, - blink::mojom::NotificationServiceRequest request); + void CreateService( + const url::Origin& origin, + mojo::PendingReceiver<blink::mojom::NotificationService> receiver); // Removes |service| from the list of owned services, for example because the // Mojo pipe disconnected. Must be called on the UI thread.
diff --git a/content/browser/renderer_interface_binders.cc b/content/browser/renderer_interface_binders.cc index c7c8e49..cfdfae7 100644 --- a/content/browser/renderer_interface_binders.cc +++ b/content/browser/renderer_interface_binders.cc
@@ -4,6 +4,7 @@ #include "content/browser/renderer_interface_binders.h" +#include <memory> #include <utility> #include "base/bind.h" @@ -190,9 +191,9 @@ ->CreateService(std::move(request), origin); })); - parameterized_binder_registry_.AddInterface( - base::Bind([](blink::mojom::NotificationServiceRequest request, - RenderProcessHost* host, const url::Origin& origin) { + parameterized_binder_registry_.AddInterface(base::BindRepeating( + [](blink::mojom::NotificationServiceRequest request, + RenderProcessHost* host, const url::Origin& origin) { static_cast<StoragePartitionImpl*>(host->GetStoragePartition()) ->GetPlatformNotificationContext() ->CreateService(origin, std::move(request));
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index a932cd5..3db775f 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -290,6 +290,11 @@ process_manager_->set_storage_partition(storage_partition_); } +BrowserContext* ServiceWorkerContextWrapper::browser_context() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return process_manager()->browser_context(); +} + ResourceContext* ServiceWorkerContextWrapper::resource_context() { DCHECK_CURRENTLY_ON(BrowserThread::IO); return resource_context_; @@ -1118,19 +1123,6 @@ core_observer_list_->RemoveObserver(observer); } -base::WeakPtr<ServiceWorkerProviderHost> -ServiceWorkerContextWrapper::PreCreateHostForWorker( - int process_id, - blink::mojom::ServiceWorkerProviderType provider_type, - blink::mojom::ServiceWorkerProviderInfoForClientPtr* out_provider_info) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (!context_core_) - return nullptr; - return ServiceWorkerProviderHost::PreCreateForWebWorker( - context_core_->AsWeakPtr(), process_id, provider_type, out_provider_info); -} - ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() { for (auto& observer : observer_list_) observer.OnDestruct(static_cast<ServiceWorkerContext*>(this));
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index f636d99..3f0e309 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -96,6 +96,9 @@ void set_storage_partition(StoragePartitionImpl* storage_partition); + // UI thread. + BrowserContext* browser_context(); + // The ResourceContext for the associated BrowserContext. This should only // be accessed on the IO thread, and can be null during initialization and // shutdown. @@ -296,20 +299,6 @@ bool is_incognito() const { return is_incognito_; } - // Used for starting a web worker (dedicated worker or shared worker). Returns - // a provider host for the worker and fills |out_provider_info| with info to - // send to the renderer to connect to the host. The host stays alive as long - // as this info stays alive (namely, as long as - // |out_provider_info->host_ptr_info| stays alive). - // - // Returns null if context() is null. - // - // Must be called on the IO thread. - base::WeakPtr<ServiceWorkerProviderHost> PreCreateHostForWorker( - int process_id, - blink::mojom::ServiceWorkerProviderType provider_type, - blink::mojom::ServiceWorkerProviderInfoForClientPtr* out_provider_info); - // The core context is only for use on the IO thread. // Can be null before/during init, during/after shutdown, and after // DeleteAndStartOver fails.
diff --git a/content/browser/service_worker/service_worker_navigation_handle.cc b/content/browser/service_worker/service_worker_navigation_handle.cc index ca3a020..d25a8650 100644 --- a/content/browser/service_worker/service_worker_navigation_handle.cc +++ b/content/browser/service_worker/service_worker_navigation_handle.cc
@@ -55,4 +55,12 @@ *out_provider_info = std::move(provider_info_); } +void ServiceWorkerNavigationHandle::OnBeginWorkerCommit() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&ServiceWorkerNavigationHandleCore::OnBeginWorkerCommit, + base::Unretained(core_))); +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_navigation_handle.h b/content/browser/service_worker/service_worker_navigation_handle.h index d2e0708..20588a4 100644 --- a/content/browser/service_worker/service_worker_navigation_handle.h +++ b/content/browser/service_worker/service_worker_navigation_handle.h
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "content/common/content_export.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" namespace content { @@ -15,8 +16,9 @@ class ServiceWorkerNavigationHandleCore; // This class is used to manage the lifetime of ServiceWorkerProviderHosts -// created during navigation. This is a UI thread class, with a pendant class -// on the IO thread, the ServiceWorkerNavigationHandleCore. +// created for main resource requests (navigations and web workers). This is a +// UI thread class, with a pendant class on the IO thread, the +// ServiceWorkerNavigationHandleCore. // // The lifetime of the ServiceWorkerNavigationHandle, the // ServiceWorkerNavigationHandleCore and the ServiceWorkerProviderHost are the @@ -45,7 +47,9 @@ // the provider info which in turn leads to the destruction of an unclaimed // ServiceWorkerProviderHost, and posts a task to destroy the // ServiceWorkerNavigationHandleCore on the IO thread. -class ServiceWorkerNavigationHandle { +// +// TODO(falken): Rename ServiceWorkerMainResourceHandle. +class CONTENT_EXPORT ServiceWorkerNavigationHandle { public: explicit ServiceWorkerNavigationHandle( ServiceWorkerContextWrapper* context_wrapper); @@ -67,14 +71,25 @@ int render_frame_id, blink::mojom::ServiceWorkerProviderInfoForClientPtr* out_provider_info); + void OnBeginWorkerCommit(); + + blink::mojom::ServiceWorkerProviderInfoForClientPtr TakeProviderInfo() { + return std::move(provider_info_); + } + ServiceWorkerNavigationHandleCore* core() const { return core_; } const ServiceWorkerContextWrapper* context_wrapper() const { return context_wrapper_.get(); } + base::WeakPtr<ServiceWorkerNavigationHandle> AsWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + private: blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info_; + // TODO(leonhsl): Use std::unique_ptr<ServiceWorkerNavigationHandleCore, // BrowserThread::DeleteOnIOThread> instead. ServiceWorkerNavigationHandleCore* core_;
diff --git a/content/browser/service_worker/service_worker_navigation_handle_core.cc b/content/browser/service_worker/service_worker_navigation_handle_core.cc index 52d177d..e23d3e6 100644 --- a/content/browser/service_worker/service_worker_navigation_handle_core.cc +++ b/content/browser/service_worker/service_worker_navigation_handle_core.cc
@@ -51,4 +51,10 @@ provider_host_->OnBeginNavigationCommit(render_process_id, render_frame_id); } +void ServiceWorkerNavigationHandleCore::OnBeginWorkerCommit() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (provider_host_) + provider_host_->CompleteWebWorkerPreparation(); +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_navigation_handle_core.h b/content/browser/service_worker/service_worker_navigation_handle_core.h index 2e4d0b47..f3ab8705 100644 --- a/content/browser/service_worker/service_worker_navigation_handle_core.h +++ b/content/browser/service_worker/service_worker_navigation_handle_core.h
@@ -32,7 +32,7 @@ ServiceWorkerContextWrapper* context_wrapper); ~ServiceWorkerNavigationHandleCore(); - // Called when a ServiceWorkerProviderHost was created for the navigation. + // Called when a ServiceWorkerProviderHost was created. void OnCreatedProviderHost( base::WeakPtr<ServiceWorkerProviderHost> provider_host, blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info); @@ -41,6 +41,8 @@ // pre-created provider host. void OnBeginNavigationCommit(int render_process_id, int render_frame_id); + void OnBeginWorkerCommit(); + ServiceWorkerContextWrapper* context_wrapper() const { return context_wrapper_.get(); } @@ -65,6 +67,11 @@ ServiceWorkerControlleeRequestHandler* interceptor() { return interceptor_.get(); } + + base::WeakPtr<ServiceWorkerNavigationHandleCore> AsWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + ///////////////////////////////////////////////////////////////////////////// private: @@ -75,6 +82,8 @@ // NavigationLoaderOnUI: std::unique_ptr<ServiceWorkerControlleeRequestHandler> interceptor_; + base::WeakPtrFactory<ServiceWorkerNavigationHandleCore> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerNavigationHandleCore); };
diff --git a/content/browser/service_worker/service_worker_navigation_loader_interceptor.cc b/content/browser/service_worker/service_worker_navigation_loader_interceptor.cc index 7c3d34b..e3b66d96 100644 --- a/content/browser/service_worker/service_worker_navigation_loader_interceptor.cc +++ b/content/browser/service_worker/service_worker_navigation_loader_interceptor.cc
@@ -78,10 +78,7 @@ void MaybeCreateLoaderOnIO( base::WeakPtr<ServiceWorkerNavigationLoaderInterceptor> interceptor_on_ui, ServiceWorkerNavigationHandleCore* handle_core, - bool are_ancestors_secure, - int frame_tree_node_id, - ResourceType resource_type, - bool skip_service_worker, + const ServiceWorkerNavigationLoaderInterceptorParams& params, const network::ResourceRequest& tentative_resource_request, BrowserContext* browser_context, NavigationLoaderInterceptor::LoaderCallback loader_callback, @@ -110,17 +107,30 @@ // ServiceWorkerNavigationHandle on the UI thread, and finally passed to the // renderer when the navigation commits. provider_info = blink::mojom::ServiceWorkerProviderInfoForClient::New(); - provider_host = ServiceWorkerProviderHost::PreCreateNavigationHost( - context_core->AsWeakPtr(), are_ancestors_secure, frame_tree_node_id, - &provider_info); + if (params.resource_type == ResourceType::kMainFrame || + params.resource_type == ResourceType::kSubFrame) { + provider_host = ServiceWorkerProviderHost::PreCreateNavigationHost( + context_core->AsWeakPtr(), params.are_ancestors_secure, + params.frame_tree_node_id, &provider_info); + } else { + DCHECK(params.resource_type == ResourceType::kWorker || + params.resource_type == ResourceType::kSharedWorker); + auto provider_type = + params.resource_type == ResourceType::kWorker + ? blink::mojom::ServiceWorkerProviderType::kForDedicatedWorker + : blink::mojom::ServiceWorkerProviderType::kForSharedWorker; + provider_host = ServiceWorkerProviderHost::PreCreateForWebWorker( + context_core->AsWeakPtr(), params.process_id, provider_type, + &provider_info); + } handle_core->set_provider_host(provider_host); // Also make the inner interceptor. DCHECK(!handle_core->interceptor()); handle_core->set_interceptor( std::make_unique<ServiceWorkerControlleeRequestHandler>( - context_core->AsWeakPtr(), provider_host, resource_type, - skip_service_worker)); + context_core->AsWeakPtr(), provider_host, params.resource_type, + params.skip_service_worker)); } // If |initialize_provider_only| is true, we have already determined there is @@ -152,14 +162,9 @@ ServiceWorkerNavigationLoaderInterceptor:: ServiceWorkerNavigationLoaderInterceptor( - const NavigationRequestInfo& request_info, + const ServiceWorkerNavigationLoaderInterceptorParams& params, ServiceWorkerNavigationHandle* handle) - : handle_(handle), - are_ancestors_secure_(request_info.are_ancestors_secure), - frame_tree_node_id_(request_info.frame_tree_node_id), - resource_type_(request_info.is_main_frame ? ResourceType::kMainFrame - : ResourceType::kSubFrame), - skip_service_worker_(request_info.begin_params->skip_service_worker) { + : handle_(handle), params_(params) { DCHECK(NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()); DCHECK_CURRENTLY_ON(BrowserThread::UI); } @@ -194,10 +199,9 @@ base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, base::BindOnce(&MaybeCreateLoaderOnIO, GetWeakPtr(), handle_->core(), - are_ancestors_secure_, frame_tree_node_id_, resource_type_, - skip_service_worker_, tentative_resource_request, - browser_context, std::move(loader_callback), - std::move(fallback_callback), initialize_provider_only)); + params_, tentative_resource_request, browser_context, + std::move(loader_callback), std::move(fallback_callback), + initialize_provider_only)); } base::Optional<SubresourceLoaderParams>
diff --git a/content/browser/service_worker/service_worker_navigation_loader_interceptor.h b/content/browser/service_worker/service_worker_navigation_loader_interceptor.h index 302af35..9fa5afa 100644 --- a/content/browser/service_worker/service_worker_navigation_loader_interceptor.h +++ b/content/browser/service_worker/service_worker_navigation_loader_interceptor.h
@@ -11,19 +11,36 @@ #include "content/browser/loader/navigation_loader_interceptor.h" #include "content/browser/navigation_subresource_loader_params.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/common/child_process_host.h" #include "content/public/common/resource_type.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" namespace content { -struct NavigationRequestInfo; class ServiceWorkerNavigationHandle; +struct ServiceWorkerNavigationLoaderInterceptorParams { + // For all clients: + ResourceType resource_type = ResourceType::kMainFrame; + bool skip_service_worker = false; + + // For windows: + bool is_main_frame = false; + // Whether all ancestor frames of the frame that is navigating have a secure + // origin. True for main frames. + bool are_ancestors_secure = false; + int frame_tree_node_id = RenderFrameHost::kNoFrameTreeNodeId; + + // For web workers: + int process_id = ChildProcessHost::kInvalidUniqueID; +}; + // This class is a work in progress for https://crbug.com/824858. It is used // only when NavigationLoaderOnUI is enabled. // -// Handles navigations for service worker clients (for now just documents, not -// web workers). Lives on the UI thread. +// Handles navigations for service worker clients (windows and web workers). +// Lives on the UI thread. // // The corresponding legacy class is ServiceWorkerControlleeRequestHandler which // lives on the IO thread. Currently, this class just delegates to the @@ -32,7 +49,7 @@ : public NavigationLoaderInterceptor { public: ServiceWorkerNavigationLoaderInterceptor( - const NavigationRequestInfo& request_info, + const ServiceWorkerNavigationLoaderInterceptorParams& params, ServiceWorkerNavigationHandle* handle); ~ServiceWorkerNavigationLoaderInterceptor() override; @@ -74,10 +91,7 @@ // |handle_| owns |this|. ServiceWorkerNavigationHandle* const handle_; - const bool are_ancestors_secure_; - const int frame_tree_node_id_; - const ResourceType resource_type_; - const bool skip_service_worker_; + const ServiceWorkerNavigationLoaderInterceptorParams params_; base::Optional<SubresourceLoaderParams> subresource_loader_params_;
diff --git a/content/browser/service_worker/service_worker_request_handler.cc b/content/browser/service_worker/service_worker_request_handler.cc index 5f7efd7..fa33b20 100644 --- a/content/browser/service_worker/service_worker_request_handler.cc +++ b/content/browser/service_worker/service_worker_request_handler.cc
@@ -52,8 +52,16 @@ return nullptr; } + ServiceWorkerNavigationLoaderInterceptorParams params; + params.resource_type = request_info.is_main_frame ? ResourceType::kMainFrame + : ResourceType::kSubFrame; + params.skip_service_worker = request_info.begin_params->skip_service_worker; + params.is_main_frame = request_info.is_main_frame; + params.are_ancestors_secure = request_info.are_ancestors_secure; + params.frame_tree_node_id = request_info.frame_tree_node_id; + return std::make_unique<ServiceWorkerNavigationLoaderInterceptor>( - request_info, navigation_handle); + params, navigation_handle); } // static @@ -98,14 +106,16 @@ // static std::unique_ptr<NavigationLoaderInterceptor> -ServiceWorkerRequestHandler::CreateForWorker( +ServiceWorkerRequestHandler::CreateForWorkerUI( const network::ResourceRequest& resource_request, - ServiceWorkerProviderHost* host) { - DCHECK(host); - DCHECK(resource_request.resource_type == - static_cast<int>(ResourceType::kWorker) || - resource_request.resource_type == - static_cast<int>(ResourceType::kSharedWorker)) + int process_id, + ServiceWorkerNavigationHandle* navigation_handle) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + auto resource_type = + static_cast<ResourceType>(resource_request.resource_type); + DCHECK(resource_type == ResourceType::kWorker || + resource_type == ResourceType::kSharedWorker) << resource_request.resource_type; // Create the handler even for insecure HTTP since it's used in the @@ -115,9 +125,62 @@ return nullptr; } + ServiceWorkerNavigationLoaderInterceptorParams params; + params.resource_type = resource_type; + params.skip_service_worker = resource_request.skip_service_worker; + params.process_id = process_id; + + return std::make_unique<ServiceWorkerNavigationLoaderInterceptor>( + params, navigation_handle); +} + +// static +std::unique_ptr<NavigationLoaderInterceptor> +ServiceWorkerRequestHandler::CreateForWorkerIO( + const network::ResourceRequest& resource_request, + int process_id, + ServiceWorkerNavigationHandleCore* navigation_handle_core) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + // Create the handler even for insecure HTTP since it's used in the + // case of redirect to HTTPS. + if (!resource_request.url.SchemeIsHTTPOrHTTPS() && + !OriginCanAccessServiceWorkers(resource_request.url)) { + return nullptr; + } + + auto provider_info = blink::mojom::ServiceWorkerProviderInfoForClient::New(); + if (!navigation_handle_core->context_wrapper()) + return nullptr; + ServiceWorkerContextCore* context = + navigation_handle_core->context_wrapper()->context(); + if (!context) + return nullptr; + + auto resource_type = + static_cast<ResourceType>(resource_request.resource_type); + auto provider_type = blink::mojom::ServiceWorkerProviderType::kUnknown; + switch (resource_type) { + case ResourceType::kWorker: + provider_type = + blink::mojom::ServiceWorkerProviderType::kForDedicatedWorker; + break; + case ResourceType::kSharedWorker: + provider_type = blink::mojom::ServiceWorkerProviderType::kForSharedWorker; + break; + default: + NOTREACHED() << resource_request.resource_type; + return nullptr; + } + + // Initialize the SWProviderHost. + base::WeakPtr<ServiceWorkerProviderHost> host = + ServiceWorkerProviderHost::PreCreateForWebWorker( + context->AsWeakPtr(), process_id, provider_type, &provider_info); + navigation_handle_core->OnCreatedProviderHost(host, std::move(provider_info)); + return std::make_unique<ServiceWorkerControlleeRequestHandler>( - host->context(), host->AsWeakPtr(), - static_cast<ResourceType>(resource_request.resource_type), + context->AsWeakPtr(), host, resource_type, resource_request.skip_service_worker); }
diff --git a/content/browser/service_worker/service_worker_request_handler.h b/content/browser/service_worker/service_worker_request_handler.h index 25b886eb..399eda9 100644 --- a/content/browser/service_worker/service_worker_request_handler.h +++ b/content/browser/service_worker/service_worker_request_handler.h
@@ -46,11 +46,21 @@ const NavigationRequestInfo& request_info, base::WeakPtr<ServiceWorkerProviderHost>* out_provider_host); - // Same as above but for a dedicated worker or shared worker. Called on the IO + // Returns a loader interceptor for a dedicated worker or shared worker. May + // return nullptr if the worker cannot use service workers. Called on the IO // thread. - static std::unique_ptr<NavigationLoaderInterceptor> CreateForWorker( + static std::unique_ptr<NavigationLoaderInterceptor> CreateForWorkerUI( const network::ResourceRequest& resource_request, - ServiceWorkerProviderHost* host); + int process_id, + ServiceWorkerNavigationHandle* navigation_handle); + + // Returns a loader interceptor for a dedicated worker or shared worker. May + // return nullptr if the worker cannot use service workers. Called on the UI + // thread. + static std::unique_ptr<NavigationLoaderInterceptor> CreateForWorkerIO( + const network::ResourceRequest& resource_request, + int process_id, + ServiceWorkerNavigationHandleCore* navigation_handle_core); private: DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestHandler);
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index 86a38ab5..6b5be14 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -1422,8 +1422,8 @@ GenURL("a.com", "/navigation_controller/page_with_iframe.html"), GenURL("a.com", "/title1.html"), true)); - // Navigate to the same subframe document from a different top frame top frame - // origin. It should be a cache miss. + // Navigate to the same subframe document from a different top frame origin. + // It should be a cache miss. EXPECT_FALSE(NavigationResourceCached( GenURL("b.com", "/navigation_controller/page_with_iframe.html"), GenURL("a.com", "/title1.html"), false)); @@ -1431,10 +1431,48 @@ // See: http://crbug.com/983931 #if defined(OS_ANDROID) +#define MAYBE_SubframeNavigationResources DISABLED_SubframeNavigationResources +#else +#define MAYBE_SubframeNavigationResources SubframeNavigationResources +#endif +IN_PROC_BROWSER_TEST_F(WebContentsSplitCacheWithFrameOriginBrowserTest, + MAYBE_SubframeNavigationResources) { + // Navigate for the first time, and it's not cached. + NavigationResourceCached( + GenURL("a.com", "/navigation_controller/page_with_iframe.html"), + GenURL("a.com", "/title1.html"), false); + + // The second time it should be a cache hit. + NavigationResourceCached( + GenURL("a.com", "/navigation_controller/page_with_iframe.html"), + GenURL("a.com", "/title1.html"), true); + + // Navigate to the same subframe document from a different top frame origin. + // It should be a cache miss. + NavigationResourceCached( + GenURL("b.com", "/navigation_controller/page_with_iframe.html"), + GenURL("a.com", "/title1.html"), false); + + // Navigate the subframe to a.com/redirect_to_d which redirects to + // d.com/title1.html. + NavigationResourceCached( + GenURL("a.com", "/navigation_controller/page_with_iframe.html"), + GenURL("a.com", "/redirect_to_d"), false); + + // Navigate to d.com directly. The resource should be cached due to the + // earlier redirected navigation. + NavigationResourceCached( + GenURL("a.com", "/navigation_controller/page_with_iframe.html"), + GenURL("d.com", "/title1.html"), true); +} + +// See: http://crbug.com/983931 +#if defined(OS_ANDROID) #define MAYBE_SplitCacheDedicatedWorkers DISABLED_SplitCacheDedicatedWorkers #else #define MAYBE_SplitCacheDedicatedWorkers SplitCacheDedicatedWorkers #endif + IN_PROC_BROWSER_TEST_P(WebContentsSplitCacheBrowserTestEnabled, MAYBE_SplitCacheDedicatedWorkers) { // Load 3p.com/script from a.com's worker. The first time it's loaded from the
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index 4dcbdaa..7ef1dfd 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -15,6 +15,7 @@ #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/interface_provider_filtering.h" #include "content/browser/renderer_interface_binders.h" +#include "content/browser/service_worker/service_worker_navigation_handle.h" #include "content/browser/storage_partition_impl.h" #include "content/browser/websockets/websocket_connector_impl.h" #include "content/browser/worker_host/worker_script_fetch_initiator.h" @@ -108,13 +109,16 @@ appcache_handle_ = std::make_unique<AppCacheNavigationHandle>( storage_partition_impl->GetAppCacheService(), worker_process_id_); + service_worker_handle_ = std::make_unique<ServiceWorkerNavigationHandle>( + storage_partition_impl->GetServiceWorkerContext()); + WorkerScriptFetchInitiator::Start( worker_process_id_, script_url, request_initiator_origin, credentials_mode, std::move(outside_fetch_client_settings_object), ResourceType::kWorker, storage_partition_impl->GetServiceWorkerContext(), - appcache_handle_->core(), std::move(blob_url_loader_factory), nullptr, - storage_partition_impl, + service_worker_handle_.get(), appcache_handle_->core(), + std::move(blob_url_loader_factory), nullptr, storage_partition_impl, base::BindOnce(&DedicatedWorkerHost::DidStartScriptLoad, weak_factory_.GetWeakPtr())); } @@ -136,10 +140,6 @@ // Called from WorkerScriptFetchInitiator. Continues starting the dedicated // worker in the renderer process. // - // |service_worker_provider_info| is sent to the renderer process and contains - // information about its ServiceWorkerProviderHost, the browser-side host for - // supporting the dedicated worker as a service worker client. - // // |main_script_load_params| is sent to the renderer process and to be used to // load the dedicated worker main script pre-requested by the browser process. // @@ -153,8 +153,6 @@ // a ServiceWorker object about the controller is prepared, it is registered // to |controller_service_worker_object_host|. void DidStartScriptLoad( - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, @@ -170,8 +168,11 @@ return; } - auto* worker_process_host = RenderProcessHost::FromID(worker_process_id_); - if (!worker_process_host) { + // TODO(cammie): Change this approach when we support shared workers + // creating dedicated workers, as there might be no ancestor frame. + RenderFrameHostImpl* ancestor_render_frame_host = + GetAncestorRenderFrameHost(); + if (!ancestor_render_frame_host) { client_->OnScriptLoadStartFailed(); return; } @@ -181,7 +182,7 @@ pending_default_factory; CreateNetworkFactory( pending_default_factory.InitWithNewPipeAndPassReceiver(), - worker_process_host); + ancestor_render_frame_host); subresource_loader_factories->pending_default_factory() = std::move(pending_default_factory); @@ -197,7 +198,7 @@ service_worker_state = controller->object_info->state; } - client_->OnScriptLoadStarted(std::move(service_worker_provider_info), + client_->OnScriptLoadStarted(service_worker_handle_->TakeProviderInfo(), std::move(main_script_load_params), std::move(subresource_loader_factories), std::move(controller)); @@ -217,20 +218,20 @@ } void CreateNetworkFactory(network::mojom::URLLoaderFactoryRequest request, - RenderProcessHost* worker_process_host) { + RenderFrameHostImpl* render_frame_host) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(render_frame_host); network::mojom::TrustedURLLoaderHeaderClientPtrInfo no_header_client; // Get the origin of the frame tree's root to use as top-frame origin. - // TODO(cammie): Change this approach when we support shared workers - // creating dedicated workers, as there might be no ancestor frame. - RenderFrameHostImpl* ancestor_render_frame_host = - GetAncestorRenderFrameHost(); - url::Origin top_frame_origin(ancestor_render_frame_host->frame_tree_node() + // TODO(crbug.com/986167): Resolve issue of potential race condition. + url::Origin top_frame_origin(render_frame_host->frame_tree_node() ->frame_tree() ->root() ->current_origin()); + RenderProcessHost* worker_process_host = render_frame_host->GetProcess(); + DCHECK(worker_process_host); worker_process_host->CreateURLLoaderFactory( origin_, nullptr /* preferences */, net::NetworkIsolationKey(top_frame_origin, origin_), @@ -314,6 +315,7 @@ blink::mojom::DedicatedWorkerHostFactoryClientPtr client_; std::unique_ptr<AppCacheNavigationHandle> appcache_handle_; + std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_; service_manager::BinderRegistry registry_;
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc index 37e9b00..c11c026 100644 --- a/content/browser/worker_host/shared_worker_host.cc +++ b/content/browser/worker_host/shared_worker_host.cc
@@ -16,6 +16,7 @@ #include "content/browser/devtools/shared_worker_devtools_manager.h" #include "content/browser/interface_provider_filtering.h" #include "content/browser/renderer_interface_binders.h" +#include "content/browser/service_worker/service_worker_navigation_handle.h" #include "content/browser/storage_partition_impl.h" #include "content/browser/worker_host/shared_worker_content_settings_proxy_impl.h" #include "content/browser/worker_host/shared_worker_instance.h" @@ -166,8 +167,6 @@ void SharedWorkerHost::Start( blink::mojom::SharedWorkerFactoryPtr factory, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, @@ -175,7 +174,6 @@ base::WeakPtr<ServiceWorkerObjectHost> controller_service_worker_object_host) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(service_worker_provider_info); DCHECK(main_script_load_params); DCHECK(subresource_loader_factories); DCHECK(!subresource_loader_factories->pending_default_factory()); @@ -246,7 +244,7 @@ factory_->CreateSharedWorker( std::move(info), pause_on_start, devtools_worker_token, std::move(renderer_preferences), std::move(preference_watcher_request), - std::move(content_settings), std::move(service_worker_provider_info), + std::move(content_settings), service_worker_handle_->TakeProviderInfo(), appcache_handle_ ? base::make_optional(appcache_handle_->appcache_host_id()) : base::nullopt, @@ -520,6 +518,12 @@ appcache_handle_ = std::move(appcache_handle); } +void SharedWorkerHost::SetServiceWorkerHandle( + std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + service_worker_handle_ = std::move(service_worker_handle); +} + void SharedWorkerHost::OnClientConnectionLost() { // We'll get a notification for each dropped connection. for (auto it = clients_.begin(); it != clients_.end(); ++it) {
diff --git a/content/browser/worker_host/shared_worker_host.h b/content/browser/worker_host/shared_worker_host.h index 05f2ade..9395da7 100644 --- a/content/browser/worker_host/shared_worker_host.h +++ b/content/browser/worker_host/shared_worker_host.h
@@ -38,6 +38,7 @@ namespace content { class AppCacheNavigationHandle; +class ServiceWorkerNavigationHandle; class ServiceWorkerObjectHost; class SharedWorkerContentSettingsProxyImpl; class SharedWorkerInstance; @@ -69,10 +70,6 @@ // Starts the SharedWorker in the renderer process. // - // |service_worker_provider_info| is sent to the renderer process and contains - // information about its ServiceWorkerProviderHost, the browser-side host for - // supporting the shared worker as a service worker client. - // // |main_script_load_params| is sent to the renderer process and to be used to // load the shared worker main script pre-requested by the browser process. // @@ -86,8 +83,6 @@ // to |controller_service_worker_object_host|. void Start( blink::mojom::SharedWorkerFactoryPtr factory, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, @@ -114,6 +109,8 @@ void SetAppCacheHandle( std::unique_ptr<AppCacheNavigationHandle> appcache_handle); + void SetServiceWorkerHandle( + std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle); SharedWorkerInstance* instance() { return instance_.get(); } int worker_process_id() const { return worker_process_id_; } @@ -204,6 +201,8 @@ // renderer after main script loading finishes. std::unique_ptr<AppCacheNavigationHandle> appcache_handle_; + std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_; + Phase phase_ = Phase::kInitial; base::WeakPtrFactory<SharedWorkerHost> weak_factory_{this};
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc index 25d7af3..221e4f4 100644 --- a/content/browser/worker_host/shared_worker_host_unittest.cc +++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -13,6 +13,7 @@ #include "content/browser/appcache/chrome_appcache_service.h" #include "content/browser/navigation_subresource_loader_params.h" #include "content/browser/service_worker/embedded_worker_test_helper.h" +#include "content/browser/service_worker/service_worker_navigation_handle.h" #include "content/browser/worker_host/mock_shared_worker.h" #include "content/browser/worker_host/shared_worker_connector_impl.h" #include "content/browser/worker_host/shared_worker_instance.h" @@ -76,13 +77,6 @@ void StartWorker(SharedWorkerHost* host, blink::mojom::SharedWorkerFactoryPtr factory) { - auto provider_info = - blink::mojom::ServiceWorkerProviderInfoForClient::New(); - ServiceWorkerProviderHost::PreCreateForWebWorker( - helper_->context()->AsWeakPtr(), mock_render_process_host_.GetID(), - blink::mojom::ServiceWorkerProviderType::kForSharedWorker, - &provider_info); - auto main_script_load_params = blink::mojom::WorkerMainScriptLoadParams::New(); auto subresource_loader_factories = @@ -97,8 +91,21 @@ subresource_loader_params->pending_appcache_loader_factory = loader_factory_ptr.PassInterface(); - host->Start(std::move(factory), std::move(provider_info), - std::move(main_script_load_params), + // Set up for service worker. + auto service_worker_handle = + std::make_unique<ServiceWorkerNavigationHandle>( + helper_->context_wrapper()); + auto provider_info = + blink::mojom::ServiceWorkerProviderInfoForClient::New(); + base::WeakPtr<ServiceWorkerProviderHost> service_worker_host = + ServiceWorkerProviderHost::PreCreateForWebWorker( + helper_->context()->AsWeakPtr(), mock_render_process_host_.GetID(), + blink::mojom::ServiceWorkerProviderType::kForSharedWorker, + &provider_info); + service_worker_handle->OnCreatedProviderHost(std::move(provider_info)); + host->SetServiceWorkerHandle(std::move(service_worker_handle)); + + host->Start(std::move(factory), std::move(main_script_load_params), std::move(subresource_loader_factories), nullptr /* controller */, nullptr /* controller_service_worker_object_host */);
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc index c8af1e9a..d473c56 100644 --- a/content/browser/worker_host/shared_worker_service_impl.cc +++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -19,6 +19,7 @@ #include "content/browser/appcache/appcache_navigation_handle.h" #include "content/browser/appcache/appcache_navigation_handle_core.h" #include "content/browser/file_url_loader_factory.h" +#include "content/browser/service_worker/service_worker_navigation_handle.h" #include "content/browser/storage_partition_impl.h" #include "content/browser/url_loader_factory_getter.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -38,7 +39,6 @@ #include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h" -#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_client.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h" #include "url/origin.h" @@ -213,6 +213,11 @@ appcache_handle->core(); weak_host->SetAppCacheHandle(std::move(appcache_handle)); + auto service_worker_handle = std::make_unique<ServiceWorkerNavigationHandle>( + storage_partition_->GetServiceWorkerContext()); + auto* service_worker_handle_raw = service_worker_handle.get(); + weak_host->SetServiceWorkerHandle(std::move(service_worker_handle)); + // Fetch classic shared worker script with "same-origin" credentials mode. // https://html.spec.whatwg.org/C/#fetch-a-classic-worker-script // @@ -225,8 +230,9 @@ weak_host->instance()->constructor_origin(), credentials_mode, std::move(outside_fetch_client_settings_object), ResourceType::kSharedWorker, service_worker_context_, - appcache_handle_core, std::move(blob_url_loader_factory), - url_loader_factory_override_, storage_partition_, + service_worker_handle_raw, appcache_handle_core, + std::move(blob_url_loader_factory), url_loader_factory_override_, + storage_partition_, base::BindOnce(&SharedWorkerServiceImpl::DidCreateScriptLoader, weak_factory_.GetWeakPtr(), std::move(instance), weak_host, std::move(client), client_process_id, frame_id, @@ -240,8 +246,6 @@ int process_id, int frame_id, const blink::MessagePortChannel& message_port, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, @@ -260,7 +264,6 @@ StartWorker(std::move(instance), std::move(host), std::move(client), process_id, frame_id, message_port, - std::move(service_worker_provider_info), std::move(subresource_loader_factories), std::move(main_script_load_params), std::move(controller), std::move(controller_service_worker_object_host)); @@ -273,8 +276,6 @@ int client_process_id, int frame_id, const blink::MessagePortChannel& message_port, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, @@ -303,8 +304,7 @@ blink::mojom::SharedWorkerFactoryPtr factory; BindInterface(worker_process_host, &factory); - host->Start(std::move(factory), std::move(service_worker_provider_info), - std::move(main_script_load_params), + host->Start(std::move(factory), std::move(main_script_load_params), std::move(subresource_loader_factories), std::move(controller), std::move(controller_service_worker_object_host)); host->AddClient(std::move(client), client_process_id, frame_id, message_port);
diff --git a/content/browser/worker_host/shared_worker_service_impl.h b/content/browser/worker_host/shared_worker_service_impl.h index c4d2653..b9a650f 100644 --- a/content/browser/worker_host/shared_worker_service_impl.h +++ b/content/browser/worker_host/shared_worker_service_impl.h
@@ -18,7 +18,6 @@ #include "services/network/public/cpp/resource_response.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h" -#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_connector.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_factory.mojom.h" #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h" @@ -97,8 +96,6 @@ int client_process_id, int frame_id, const blink::MessagePortChannel& message_port, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, @@ -113,8 +110,6 @@ int client_process_id, int frame_id, const blink::MessagePortChannel& message_port, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc index 503d26a9..3ca89a1 100644 --- a/content/browser/worker_host/worker_script_fetch_initiator.cc +++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -19,8 +19,11 @@ #include "content/browser/data_url_loader_factory.h" #include "content/browser/file_url_loader_factory.h" #include "content/browser/loader/browser_initiated_resource_request.h" +#include "content/browser/loader/navigation_url_loader_impl.h" #include "content/browser/navigation_subresource_loader_params.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" +#include "content/browser/service_worker/service_worker_navigation_handle.h" +#include "content/browser/service_worker/service_worker_navigation_handle_core.h" #include "content/browser/storage_partition_impl.h" #include "content/browser/url_loader_factory_getter.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -51,6 +54,24 @@ namespace content { +namespace { + +// Runs |task| on the thread specified by |thread_id| if already on that thread, +// otherwise posts a task to that thread. +void RunOrPostTask(const base::Location& from_here, + BrowserThread::ID thread_id, + base::OnceClosure task) { + if (BrowserThread::CurrentlyOn(thread_id)) { + std::move(task).Run(); + return; + } + + base::PostTaskWithTraits(from_here, {thread_id}, std::move(task)); +} + +} // namespace + +// static void WorkerScriptFetchInitiator::Start( int worker_process_id, const GURL& script_url, @@ -60,6 +81,7 @@ outside_fetch_client_settings_object, ResourceType resource_type, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, + ServiceWorkerNavigationHandle* service_worker_handle, AppCacheNavigationHandleCore* appcache_handle_core, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_override, @@ -155,8 +177,22 @@ AddAdditionalRequestHeaders(resource_request.get(), browser_context); - // Bounce to the IO thread to setup service worker and appcache support in - // case the request for the worker script will need to be intercepted by them. + // When navigation on UI is enabled, service worker and appcache work on the + // UI thread. + if (NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) { + CreateScriptLoaderOnUI( + worker_process_id, std::move(resource_request), storage_partition, + std::move(factory_bundle_for_browser), + std::move(subresource_loader_factories), + std::move(service_worker_context), service_worker_handle, + appcache_handle_core, std::move(blob_url_loader_factory), + std::move(url_loader_factory_override), std::move(callback)); + return; + } + + // Otherwise, bounce to the IO thread to setup service worker and appcache + // support in case the request for the worker script will need to be + // intercepted by them. // // This passes |resource_context| to the IO thread. |resource_context| will // not be destroyed before the task runs, because the shutdown sequence is: @@ -172,13 +208,20 @@ storage_partition->url_loader_factory_getter(), std::move(factory_bundle_for_browser), std::move(subresource_loader_factories), resource_context, - std::move(service_worker_context), appcache_handle_core, + std::move(service_worker_context), service_worker_handle->core(), + appcache_handle_core, blob_url_loader_factory ? blob_url_loader_factory->Clone() : nullptr, url_loader_factory_override ? url_loader_factory_override->Clone() : nullptr, std::move(callback))); } +BrowserThread::ID WorkerScriptFetchInitiator::GetLoaderThreadID() { + return NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled() + ? BrowserThread::UI + : BrowserThread::IO; +} + std::unique_ptr<blink::URLLoaderFactoryBundleInfo> WorkerScriptFetchInitiator::CreateFactoryBundle( int worker_process_id, @@ -249,6 +292,89 @@ SetFetchMetadataHeadersForBrowserInitiatedRequest(resource_request); } +void WorkerScriptFetchInitiator::CreateScriptLoaderOnUI( + int worker_process_id, + std::unique_ptr<network::ResourceRequest> resource_request, + StoragePartitionImpl* storage_partition, + std::unique_ptr<blink::URLLoaderFactoryBundleInfo> + factory_bundle_for_browser_info, + std::unique_ptr<blink::URLLoaderFactoryBundleInfo> + subresource_loader_factories, + scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, + ServiceWorkerNavigationHandle* service_worker_handle, + AppCacheNavigationHandleCore* appcache_handle_core, + scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_override, + CompletionCallback callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // Create the URL loader factory for WorkerScriptLoaderFactory to use to load + // the main script. + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory; + if (blob_url_loader_factory) { + // If we have a blob_url_loader_factory just use that directly rather than + // creating a new URLLoaderFactoryBundle. + url_loader_factory = std::move(blob_url_loader_factory); + } else if (url_loader_factory_override) { + // For unit tests. + url_loader_factory = std::move(url_loader_factory_override); + } else { + // Add the default factory to the bundle for browser. + DCHECK(factory_bundle_for_browser_info); + + // Get the direct network factory. This doesn't support reconnection to the + // network service after a crash, but it's OK since it's used only for a + // single request to fetch the worker's main script during startup. If the + // network service crashes, worker startup should simply fail. + network::mojom::URLLoaderFactoryPtr network_factory_ptr; + auto network_factory = + storage_partition->GetURLLoaderFactoryForBrowserProcess(); + network_factory->Clone(mojo::MakeRequest(&network_factory_ptr)); + + factory_bundle_for_browser_info->pending_default_factory() = + network_factory_ptr.PassInterface(); + url_loader_factory = base::MakeRefCounted<blink::URLLoaderFactoryBundle>( + std::move(factory_bundle_for_browser_info)); + } + + base::WeakPtr<AppCacheHost> appcache_host = + appcache_handle_core ? appcache_handle_core->host()->GetWeakPtr() + : nullptr; + + // Start loading a web worker main script. + // TODO(nhiroki): Figure out what we should do in |wc_getter| for loading web + // worker's main script. Returning the WebContents of the closest ancestor's + // frame is a possible option, but it doesn't work when a shared worker + // creates a dedicated worker after the closest ancestor's frame is gone. The + // frame tree node ID has the same issue. + base::RepeatingCallback<WebContents*()> wc_getter = + base::BindRepeating([]() -> WebContents* { return nullptr; }); + std::vector<std::unique_ptr<URLLoaderThrottle>> throttles = + GetContentClient()->browser()->CreateURLLoaderThrottles( + *resource_request, storage_partition->browser_context(), wc_getter, + nullptr /* navigation_ui_data */, + RenderFrameHost::kNoFrameTreeNodeId); + + // Create a BrowserContext getter using |service_worker_context|. + // This context is aware of shutdown and safely returns a nullptr + // instead of a destroyed BrowserContext in that case. + auto browser_context_getter = + base::BindRepeating(&ServiceWorkerContextWrapper::browser_context, + std::move(service_worker_context)); + + WorkerScriptFetcher::CreateAndStart( + std::make_unique<WorkerScriptLoaderFactory>( + worker_process_id, service_worker_handle, + /*service_worker_handle_core=*/nullptr, std::move(appcache_host), + browser_context_getter, + base::RepeatingCallback<ResourceContext*(void)>(), + std::move(url_loader_factory)), + std::move(throttles), std::move(resource_request), + base::BindOnce(WorkerScriptFetchInitiator::DidCreateScriptLoader, + std::move(callback), + std::move(subresource_loader_factories))); +} + void WorkerScriptFetchInitiator::CreateScriptLoaderOnIO( int worker_process_id, std::unique_ptr<network::ResourceRequest> resource_request, @@ -259,6 +385,7 @@ subresource_loader_factories, ResourceContext* resource_context, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, + ServiceWorkerNavigationHandleCore* service_worker_handle_core, AppCacheNavigationHandleCore* appcache_handle_core, std::unique_ptr<network::SharedURLLoaderFactoryInfo> blob_url_loader_factory_info, @@ -267,6 +394,7 @@ CompletionCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(resource_context); + DCHECK(service_worker_handle_core); auto resource_type = static_cast<ResourceType>(resource_request->resource_type); @@ -284,12 +412,6 @@ break; } - // Set up for service worker. - auto provider_info = blink::mojom::ServiceWorkerProviderInfoForClient::New(); - base::WeakPtr<ServiceWorkerProviderHost> service_worker_host = - service_worker_context->PreCreateHostForWorker( - worker_process_id, provider_type, &provider_info); - // Create the URL loader factory for WorkerScriptLoaderFactory to use to load // the main script. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory; @@ -350,25 +472,26 @@ WorkerScriptFetcher::CreateAndStart( std::make_unique<WorkerScriptLoaderFactory>( - worker_process_id, std::move(service_worker_host), - std::move(appcache_host), resource_context_getter, - std::move(url_loader_factory)), + worker_process_id, + /*service_worker_handle=*/nullptr, service_worker_handle_core, + std::move(appcache_host), + base::RepeatingCallback<BrowserContext*(void)>(), + resource_context_getter, std::move(url_loader_factory)), std::move(throttles), std::move(resource_request), - base::BindOnce(WorkerScriptFetchInitiator::DidCreateScriptLoaderOnIO, - std::move(callback), std::move(provider_info), + base::BindOnce(WorkerScriptFetchInitiator::DidCreateScriptLoader, + std::move(callback), std::move(subresource_loader_factories))); } -void WorkerScriptFetchInitiator::DidCreateScriptLoaderOnIO( +void WorkerScriptFetchInitiator::DidCreateScriptLoader( CompletionCallback callback, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, base::Optional<SubresourceLoaderParams> subresource_loader_params, bool success) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + // This can be the UI thread or IO thread. + DCHECK_CURRENTLY_ON(GetLoaderThreadID()); // If a URLLoaderFactory for AppCache is supplied, use that. if (subresource_loader_params && @@ -388,11 +511,10 @@ subresource_loader_params->controller_service_worker_object_host; } - base::PostTaskWithTraits( - FROM_HERE, {BrowserThread::UI}, + RunOrPostTask( + FROM_HERE, BrowserThread::UI, base::BindOnce( - std::move(callback), std::move(service_worker_provider_info), - std::move(subresource_loader_factories), + std::move(callback), std::move(subresource_loader_factories), std::move(main_script_load_params), std::move(controller), std::move(controller_service_worker_object_host), success)); }
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.h b/content/browser/worker_host/worker_script_fetch_initiator.h index bc3f1bb..c2a1382 100644 --- a/content/browser/worker_host/worker_script_fetch_initiator.h +++ b/content/browser/worker_host/worker_script_fetch_initiator.h
@@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "content/public/browser/browser_thread.h" #include "content/public/common/resource_type.h" #include "content/public/common/url_loader_throttle.h" #include "services/network/public/cpp/resource_response.h" @@ -36,6 +37,8 @@ class BrowserContext; class ResourceContext; class ServiceWorkerContextWrapper; +class ServiceWorkerNavigationHandle; +class ServiceWorkerNavigationHandleCore; class ServiceWorkerObjectHost; class StoragePartitionImpl; class URLLoaderFactoryGetter; @@ -44,10 +47,11 @@ // PlzWorker: // WorkerScriptFetchInitiator is the entry point of browser-side script fetch // for WorkerScriptFetcher. +// TODO(falken): These are all static functions, it should just be a namespace +// or merged elsewhere. class WorkerScriptFetchInitiator { public: using CompletionCallback = base::OnceCallback<void( - blink::mojom::ServiceWorkerProviderInfoForClientPtr, std::unique_ptr<blink::URLLoaderFactoryBundleInfo>, blink::mojom::WorkerMainScriptLoadParamsPtr, blink::mojom::ControllerServiceWorkerInfoPtr, @@ -65,6 +69,7 @@ outside_fetch_client_settings_object, ResourceType resource_type, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, + ServiceWorkerNavigationHandle* service_worker_handle, AppCacheNavigationHandleCore* appcache_handle_core, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, scoped_refptr<network::SharedURLLoaderFactory> @@ -72,6 +77,12 @@ StoragePartitionImpl* storage_partition, CompletionCallback callback); + // Returns the BrowserThread::ID that the WorkerScriptLoaderFactory will be + // running on. + // TODO(crbug.com/824840): Remove this when non-NavigationLoaderOnUI code is + // removed. + static BrowserThread::ID GetLoaderThreadID(); + private: // Creates a loader factory bundle. Must be called on the UI thread. static std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CreateFactoryBundle( @@ -95,16 +106,32 @@ subresource_loader_factories, ResourceContext* resource_context, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, + ServiceWorkerNavigationHandleCore* service_worker_handle_core, AppCacheNavigationHandleCore* appcache_handle_core, std::unique_ptr<network::SharedURLLoaderFactoryInfo> blob_url_loader_factory_info, std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_override_info, CompletionCallback callback); - static void DidCreateScriptLoaderOnIO( + + static void CreateScriptLoaderOnUI( + int worker_process_id, + std::unique_ptr<network::ResourceRequest> resource_request, + StoragePartitionImpl* storage_partition, + std::unique_ptr<blink::URLLoaderFactoryBundleInfo> + factory_bundle_for_browser_info, + std::unique_ptr<blink::URLLoaderFactoryBundleInfo> + subresource_loader_factories, + scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, + ServiceWorkerNavigationHandle* service_worker_handle, + AppCacheNavigationHandleCore* appcache_handle_core, + scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, + scoped_refptr<network::SharedURLLoaderFactory> + url_loader_factory_override, + CompletionCallback callback); + + static void DidCreateScriptLoader( CompletionCallback callback, - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
diff --git a/content/browser/worker_host/worker_script_fetcher.cc b/content/browser/worker_host/worker_script_fetcher.cc index 782d4c0..76315dc 100644 --- a/content/browser/worker_host/worker_script_fetcher.cc +++ b/content/browser/worker_host/worker_script_fetcher.cc
@@ -6,6 +6,7 @@ #include "base/feature_list.h" #include "content/browser/loader/navigation_url_loader_impl.h" +#include "content/browser/worker_host/worker_script_fetch_initiator.h" #include "content/browser/worker_host/worker_script_loader.h" #include "content/browser/worker_host/worker_script_loader_factory.h" #include "content/common/throttling_url_loader.h" @@ -55,7 +56,7 @@ std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, std::unique_ptr<network::ResourceRequest> resource_request, CreateAndStartCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); // This fetcher will delete itself. See the class level comment. (new WorkerScriptFetcher(std::move(script_loader_factory), @@ -71,16 +72,16 @@ resource_request_(std::move(resource_request)), callback_(std::move(callback)), response_url_loader_binding_(this) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); } WorkerScriptFetcher::~WorkerScriptFetcher() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); } void WorkerScriptFetcher::Start( std::vector<std::unique_ptr<URLLoaderThrottle>> throttles) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); auto shared_url_loader_factory = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( @@ -104,13 +105,13 @@ void WorkerScriptFetcher::OnReceiveResponse( const network::ResourceResponseHead& response_head) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); response_head_ = response_head; } void WorkerScriptFetcher::OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle response_body) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); base::WeakPtr<WorkerScriptLoader> script_loader = script_loader_factory_->GetScriptLoader(); @@ -172,6 +173,7 @@ void WorkerScriptFetcher::OnReceiveRedirect( const net::RedirectInfo& redirect_info, const network::ResourceResponseHead& response_head) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); redirect_infos_.push_back(redirect_info); redirect_response_heads_.push_back(response_head); url_loader_->FollowRedirect({}, /* removed_headers */ @@ -194,6 +196,7 @@ void WorkerScriptFetcher::OnComplete( const network::URLLoaderCompletionStatus& status) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); // We can reach here only when loading fails before receiving a response_head. DCHECK_NE(net::OK, status.error_code); std::move(callback_).Run(nullptr /* main_script_load_params */,
diff --git a/content/browser/worker_host/worker_script_fetcher.h b/content/browser/worker_host/worker_script_fetcher.h index 68305e4..f8b6c7e 100644 --- a/content/browser/worker_host/worker_script_fetcher.h +++ b/content/browser/worker_host/worker_script_fetcher.h
@@ -32,7 +32,8 @@ // resource loader in the renderer process will take them over. // // WorkerScriptFetcher deletes itself when the ownership of the loader and -// client is passed to the renderer, or on failure. It lives on the IO thread. +// client is passed to the renderer, or on failure. It lives on the IO or UI +// thread. class WorkerScriptFetcher : public network::mojom::URLLoaderClient { public: using CreateAndStartCallback =
diff --git a/content/browser/worker_host/worker_script_loader.cc b/content/browser/worker_host/worker_script_loader.cc index 62899f1..72ddfc9 100644 --- a/content/browser/worker_host/worker_script_loader.cc +++ b/content/browser/worker_host/worker_script_loader.cc
@@ -5,18 +5,36 @@ #include "content/browser/worker_host/worker_script_loader.h" #include "base/bind.h" +#include "base/task/post_task.h" #include "content/browser/appcache/appcache_request_handler.h" #include "content/browser/loader/navigation_loader_interceptor.h" #include "content/browser/loader/navigation_url_loader_impl.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" -#include "content/browser/service_worker/service_worker_provider_host.h" +#include "content/browser/service_worker/service_worker_navigation_handle.h" +#include "content/browser/service_worker/service_worker_navigation_handle_core.h" #include "content/browser/service_worker/service_worker_request_handler.h" +#include "content/browser/worker_host/worker_script_fetch_initiator.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/resource_context.h" #include "net/url_request/redirect_util.h" #include "services/network/public/cpp/shared_url_loader_factory.h" namespace content { +namespace { +void CancelRequestOnIO(int process_id, + int request_id, + base::OnceClosure ui_continuation) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(ResourceDispatcherHostImpl::Get()); + ResourceDispatcherHostImpl::Get()->CancelRequest(process_id, request_id); + if (ui_continuation) + base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, + std::move(ui_continuation)); +} +} // namespace + WorkerScriptLoader::WorkerScriptLoader( int process_id, int32_t routing_id, @@ -24,8 +42,11 @@ uint32_t options, const network::ResourceRequest& resource_request, network::mojom::URLLoaderClientPtr client, - base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host, + base::WeakPtr<ServiceWorkerNavigationHandle> service_worker_handle /* UI */, + base::WeakPtr<ServiceWorkerNavigationHandleCore> + service_worker_handle_core /* IO */, base::WeakPtr<AppCacheHost> appcache_host, + const BrowserContextGetter& browser_context_getter, const ResourceContextGetter& resource_context_getter, scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) @@ -35,22 +56,38 @@ options_(options), resource_request_(resource_request), client_(std::move(client)), - service_worker_provider_host_(service_worker_provider_host), + service_worker_handle_(std::move(service_worker_handle)), + service_worker_handle_core_(std::move(service_worker_handle_core)), + browser_context_getter_(browser_context_getter), resource_context_getter_(resource_context_getter), default_loader_factory_(std::move(default_loader_factory)), traffic_annotation_(traffic_annotation), url_loader_client_binding_(this) { - if (service_worker_provider_host_) { - std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor = - ServiceWorkerRequestHandler::CreateForWorker( - resource_request_, service_worker_provider_host_.get()); - if (service_worker_interceptor) - interceptors_.push_back(std::move(service_worker_interceptor)); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); + + std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor; + if (NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) { + if (!service_worker_handle_) { + // The DedicatedWorkerHost or SharedWorkerHost is already destroyed. + Abort(); + return; + } + service_worker_interceptor = ServiceWorkerRequestHandler::CreateForWorkerUI( + resource_request_, process_id, service_worker_handle_.get()); + } else { + if (!service_worker_handle_core_) { + // The DedicatedWorkerHost or SharedWorkerHost is already destroyed. + Abort(); + return; + } + service_worker_interceptor = ServiceWorkerRequestHandler::CreateForWorkerIO( + resource_request_, process_id_, service_worker_handle_core_.get()); } - // TODO(http://crbug.com/824858): Run interceptors on UI thread. - if (!NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled() && - appcache_host) { + if (service_worker_interceptor) + interceptors_.push_back(std::move(service_worker_interceptor)); + + if (appcache_host) { std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor = AppCacheRequestHandler::InitializeForMainResourceNetworkService( resource_request_, appcache_host); @@ -61,26 +98,46 @@ Start(); } -WorkerScriptLoader::~WorkerScriptLoader() = default; +WorkerScriptLoader::~WorkerScriptLoader() { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); +} base::WeakPtr<WorkerScriptLoader> WorkerScriptLoader::GetWeakPtr() { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); return weak_factory_.GetWeakPtr(); } +void WorkerScriptLoader::Abort() { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); + CommitCompleted(network::URLLoaderCompletionStatus(net::ERR_ABORTED)); +} + void WorkerScriptLoader::Start() { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); DCHECK(!completed_); - ResourceContext* resource_context = resource_context_getter_.Run(); - if (!resource_context) { - CommitCompleted(network::URLLoaderCompletionStatus(net::ERR_ABORTED)); - return; + BrowserContext* browser_context = nullptr; + if (NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) { + browser_context = browser_context_getter_.Run(); + if (!browser_context) { + Abort(); + return; + } } - // TODO(http://crbug.com/824840): Support interceptors on the UI thread. + ResourceContext* resource_context = nullptr; + if (!NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) { + resource_context = resource_context_getter_.Run(); + if (!resource_context) { + Abort(); + return; + } + } + if (interceptor_index_ < interceptors_.size()) { auto* interceptor = interceptors_[interceptor_index_++].get(); interceptor->MaybeCreateLoader( - resource_request_, nullptr, resource_context, + resource_request_, browser_context, resource_context, base::BindOnce(&WorkerScriptLoader::MaybeStartLoader, weak_factory_.GetWeakPtr(), interceptor), base::BindOnce(&WorkerScriptLoader::LoadFromNetwork, @@ -94,6 +151,7 @@ void WorkerScriptLoader::MaybeStartLoader( NavigationLoaderInterceptor* interceptor, SingleRequestURLLoaderFactory::RequestHandler single_request_handler) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); DCHECK(!completed_); DCHECK(interceptor); @@ -127,6 +185,7 @@ } void WorkerScriptLoader::LoadFromNetwork(bool reset_subresource_loader_params) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); DCHECK(!completed_); default_loader_used_ = true; @@ -149,6 +208,7 @@ const std::vector<std::string>& removed_headers, const net::HttpRequestHeaders& modified_headers, const base::Optional<GURL>& new_url) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); DCHECK(!new_url.has_value()) << "Redirect with modified URL was not " "supported yet. crbug.com/845683"; DCHECK(redirect_info_); @@ -174,9 +234,17 @@ // Cancel the request on ResourceDispatcherHost so that we can fall back // to network again. - DCHECK(ResourceDispatcherHostImpl::Get()); - ResourceDispatcherHostImpl::Get()->CancelRequest(process_id_, request_id_); - + if (NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) { + // Hop to the IO thread to touch ResourceDispatcherHost. We continue on + // the UI thread in Start(). + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&CancelRequestOnIO, process_id_, request_id_, + base::BindOnce(&WorkerScriptLoader::Start, + weak_factory_.GetWeakPtr()))); + return; + } + CancelRequestOnIO(process_id_, request_id_, /*ui_continuation=*/{}); Start(); } @@ -190,16 +258,19 @@ // state or propagating state to a new URLLoader upon redirect. void WorkerScriptLoader::SetPriority(net::RequestPriority priority, int32_t intra_priority_value) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); if (url_loader_) url_loader_->SetPriority(priority, intra_priority_value); } void WorkerScriptLoader::PauseReadingBodyFromNet() { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); if (url_loader_) url_loader_->PauseReadingBodyFromNet(); } void WorkerScriptLoader::ResumeReadingBodyFromNet() { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); if (url_loader_) url_loader_->ResumeReadingBodyFromNet(); } @@ -212,12 +283,14 @@ void WorkerScriptLoader::OnReceiveResponse( const network::ResourceResponseHead& response_head) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); client_->OnReceiveResponse(response_head); } void WorkerScriptLoader::OnReceiveRedirect( const net::RedirectInfo& redirect_info, const network::ResourceResponseHead& response_head) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); if (--redirect_limit_ == 0) { CommitCompleted( network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS)); @@ -232,25 +305,30 @@ int64_t current_position, int64_t total_size, OnUploadProgressCallback ack_callback) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); client_->OnUploadProgress(current_position, total_size, std::move(ack_callback)); } void WorkerScriptLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); client_->OnReceiveCachedMetadata(std::move(data)); } void WorkerScriptLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); client_->OnTransferSizeUpdated(transfer_size_diff); } void WorkerScriptLoader::OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle consumer) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); client_->OnStartLoadingResponseBody(std::move(consumer)); } void WorkerScriptLoader::OnComplete( const network::URLLoaderCompletionStatus& status) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); CommitCompleted(status); } @@ -262,6 +340,8 @@ network::mojom::URLLoaderPtr* response_url_loader, network::mojom::URLLoaderClientRequest* response_client_request, ThrottlingURLLoader* url_loader) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); + // TODO(crbug/898755): This is odd that NavigationLoaderInterceptor:: // MaybeCreateLoader() is called directly from WorkerScriptLoader. But // NavigationLoaderInterceptor::MaybeCreateLoaderForResponse() is called from @@ -288,11 +368,18 @@ void WorkerScriptLoader::CommitCompleted( const network::URLLoaderCompletionStatus& status) { + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); DCHECK(!completed_); completed_ = true; - if (service_worker_provider_host_ && status.error_code == net::OK) - service_worker_provider_host_->CompleteWebWorkerPreparation(); + if (status.error_code == net::OK) { + if (service_worker_handle_) { + service_worker_handle_->OnBeginWorkerCommit(); + } else if (service_worker_handle_core_) { + service_worker_handle_core_->OnBeginWorkerCommit(); + } + } + client_->OnComplete(status); // We're done. Ensure we no longer send messages to our client, and no longer
diff --git a/content/browser/worker_host/worker_script_loader.h b/content/browser/worker_host/worker_script_loader.h index 6d0edd2..5328ef2 100644 --- a/content/browser/worker_host/worker_script_loader.h +++ b/content/browser/worker_host/worker_script_loader.h
@@ -26,10 +26,12 @@ namespace content { class AppCacheHost; +class BrowserContext; class ThrottlingURLLoader; class NavigationLoaderInterceptor; class ResourceContext; -class ServiceWorkerProviderHost; +class ServiceWorkerNavigationHandle; +class ServiceWorkerNavigationHandleCore; // The URLLoader for loading a shared worker script. Only used for the main // script request. @@ -41,7 +43,8 @@ // client. On redirects, it starts over with the new request URL, possibly // starting a new loader and becoming the client of that. // -// Lives on the IO thread. +// Lives on the UI thread when NavigationLoaderOnUI is enabled, and the IO +// thread otherwise. class WorkerScriptLoader : public network::mojom::URLLoader, public network::mojom::URLLoaderClient { public: @@ -49,6 +52,10 @@ // the IO thread. using ResourceContextGetter = base::RepeatingCallback<ResourceContext*(void)>; + // Returns the browser context, or nullptr during shutdown. Must be called on + // the UI thread. + using BrowserContextGetter = base::RepeatingCallback<BrowserContext*(void)>; + // |default_loader_factory| is used to load the script if the load is not // intercepted by a feature like service worker. Typically it will load the // script from the NetworkService. However, it may internally contain @@ -61,8 +68,12 @@ uint32_t options, const network::ResourceRequest& resource_request, network::mojom::URLLoaderClientPtr client, - base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host, + base::WeakPtr<ServiceWorkerNavigationHandle> + service_worker_handle /* UI */, + base::WeakPtr<ServiceWorkerNavigationHandleCore> + service_worker_handle_core /* IO */, base::WeakPtr<AppCacheHost> appcache_host, + const BrowserContextGetter& browser_context_getter, const ResourceContextGetter& resource_context_getter, scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation); @@ -114,6 +125,7 @@ bool default_loader_used_ = false; private: + void Abort(); void Start(); void MaybeStartLoader( NavigationLoaderInterceptor* interceptor, @@ -134,7 +146,9 @@ const uint32_t options_; network::ResourceRequest resource_request_; network::mojom::URLLoaderClientPtr client_; - base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_; + base::WeakPtr<ServiceWorkerNavigationHandle> service_worker_handle_; + base::WeakPtr<ServiceWorkerNavigationHandleCore> service_worker_handle_core_; + BrowserContextGetter browser_context_getter_; ResourceContextGetter resource_context_getter_; scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory_; net::MutableNetworkTrafficAnnotationTag traffic_annotation_; @@ -157,4 +171,5 @@ }; } // namespace content + #endif // CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_LOADER_H_
diff --git a/content/browser/worker_host/worker_script_loader_factory.cc b/content/browser/worker_host/worker_script_loader_factory.cc index 8e2383b91..c72ef92 100644 --- a/content/browser/worker_host/worker_script_loader_factory.cc +++ b/content/browser/worker_host/worker_script_loader_factory.cc
@@ -5,9 +5,13 @@ #include "content/browser/worker_host/worker_script_loader_factory.h" #include <memory> + #include "base/feature_list.h" +#include "content/browser/service_worker/service_worker_navigation_handle.h" +#include "content/browser/service_worker/service_worker_navigation_handle_core.h" #include "content/browser/service_worker/service_worker_provider_host.h" #include "content/browser/service_worker/service_worker_version.h" +#include "content/browser/worker_host/worker_script_fetch_initiator.h" #include "content/browser/worker_host/worker_script_loader.h" #include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/strong_binding.h" @@ -20,26 +24,30 @@ WorkerScriptLoaderFactory::WorkerScriptLoaderFactory( int process_id, - base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host, + ServiceWorkerNavigationHandle* service_worker_handle /* UI only */, + ServiceWorkerNavigationHandleCore* service_worker_handle_core /* IO only */, base::WeakPtr<AppCacheHost> appcache_host, + const BrowserContextGetter& browser_context_getter, const ResourceContextGetter& resource_context_getter, scoped_refptr<network::SharedURLLoaderFactory> loader_factory) : process_id_(process_id), - service_worker_provider_host_(std::move(service_worker_provider_host)), appcache_host_(std::move(appcache_host)), + browser_context_getter_(browser_context_getter), resource_context_getter_(resource_context_getter), loader_factory_(std::move(loader_factory)) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); - DCHECK(!service_worker_provider_host_ || - service_worker_provider_host_->provider_type() == - blink::mojom::ServiceWorkerProviderType::kForDedicatedWorker || - service_worker_provider_host_->provider_type() == - blink::mojom::ServiceWorkerProviderType::kForSharedWorker); + + if (service_worker_handle) { + service_worker_handle_ = service_worker_handle->AsWeakPtr(); + } + if (service_worker_handle_core) { + service_worker_handle_core_ = service_worker_handle_core->AsWeakPtr(); + } } WorkerScriptLoaderFactory::~WorkerScriptLoaderFactory() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); } void WorkerScriptLoaderFactory::CreateLoaderAndStart( @@ -50,7 +58,7 @@ const network::ResourceRequest& resource_request, network::mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(WorkerScriptFetchInitiator::GetLoaderThreadID()); DCHECK(resource_request.resource_type == static_cast<int>(ResourceType::kWorker) || resource_request.resource_type == @@ -61,8 +69,9 @@ // Create a WorkerScriptLoader to load the script. auto script_loader = std::make_unique<WorkerScriptLoader>( process_id_, routing_id, request_id, options, resource_request, - std::move(client), service_worker_provider_host_, appcache_host_, - resource_context_getter_, loader_factory_, traffic_annotation); + std::move(client), service_worker_handle_, service_worker_handle_core_, + appcache_host_, browser_context_getter_, resource_context_getter_, + loader_factory_, traffic_annotation); script_loader_ = script_loader->GetWeakPtr(); mojo::MakeStrongBinding(std::move(script_loader), std::move(request)); }
diff --git a/content/browser/worker_host/worker_script_loader_factory.h b/content/browser/worker_host/worker_script_loader_factory.h index 61b3165..afd3fef 100644 --- a/content/browser/worker_host/worker_script_loader_factory.h +++ b/content/browser/worker_host/worker_script_loader_factory.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_WORKER_HOST_WORKER_SCRIPT_LOADER_FACTORY_H_ #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "content/browser/navigation_subresource_loader_params.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" @@ -16,7 +17,9 @@ namespace content { class AppCacheHost; -class ServiceWorkerProviderHost; +class BrowserContext; +class ServiceWorkerNavigationHandle; +class ServiceWorkerNavigationHandleCore; class ResourceContext; class WorkerScriptLoader; @@ -26,8 +29,8 @@ // It's an error to call CreateLoaderAndStart() more than a total of one time // across this object or any of its clones. // -// This is created per one web worker. All functions of this class must be -// called on the IO thread. +// This is created per one web worker. It lives on the UI thread when +// NavigationLoaderOnUI is enabled, and the IO thread otherwise. class CONTENT_EXPORT WorkerScriptLoaderFactory : public network::mojom::URLLoaderFactory { public: @@ -35,14 +38,28 @@ // the IO thread. using ResourceContextGetter = base::RepeatingCallback<ResourceContext*(void)>; + // Returns the browser context, or nullptr during shutdown. Must be called on + // the UI thread. + using BrowserContextGetter = base::RepeatingCallback<BrowserContext*(void)>; + // |loader_factory| is used to load the script if the load is not intercepted // by a feature like service worker. Typically it will load the script from // the NetworkService. However, it may internally contain non-NetworkService // factories used for non-http(s) URLs, e.g., a chrome-extension:// URL. + // + // NavigationLoaderOnUI: + // |service_worker_handle| and |browser_context_getter| can be + // used. + // + // Non-NavigationLoaderOnUI: + // |service_worker_handle_core| and |resource_context_getter| can + // be used. WorkerScriptLoaderFactory( int process_id, - base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host, + ServiceWorkerNavigationHandle* service_worker_handle, + ServiceWorkerNavigationHandleCore* service_worker_handle_core, base::WeakPtr<AppCacheHost> appcache_host, + const BrowserContextGetter& browser_context_getter, const ResourceContextGetter& resource_context_getter, scoped_refptr<network::SharedURLLoaderFactory> loader_factory); ~WorkerScriptLoaderFactory() override; @@ -62,8 +79,10 @@ private: const int process_id_; - base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_; + base::WeakPtr<ServiceWorkerNavigationHandle> service_worker_handle_; + base::WeakPtr<ServiceWorkerNavigationHandleCore> service_worker_handle_core_; base::WeakPtr<AppCacheHost> appcache_host_; + BrowserContextGetter browser_context_getter_; ResourceContextGetter resource_context_getter_; scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
diff --git a/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/content/browser/worker_host/worker_script_loader_factory_unittest.cc index 1b1e314..7f73d13c 100644 --- a/content/browser/worker_host/worker_script_loader_factory_unittest.cc +++ b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -6,9 +6,12 @@ #include "base/bind_helpers.h" #include "base/run_loop.h" +#include "content/browser/loader/navigation_url_loader_impl.h" #include "content/browser/service_worker/embedded_worker_test_helper.h" #include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" +#include "content/browser/service_worker/service_worker_navigation_handle.h" +#include "content/browser/service_worker/service_worker_navigation_handle_core.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/test/fake_network_url_loader_factory.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" @@ -37,6 +40,10 @@ context->storage()->LazyInitializeForTest(base::DoNothing()); base::RunLoop().RunUntilIdle(); + browser_context_getter_ = + base::BindRepeating(&ServiceWorkerContextWrapper::browser_context, + helper_->context_wrapper()); + resource_context_getter_ = base::BindRepeating(&ServiceWorkerContextWrapper::resource_context, helper_->context_wrapper()); @@ -52,13 +59,8 @@ network::SharedURLLoaderFactory::Create(std::move(info)); // Set up a service worker host for the shared worker. - service_worker_provider_info_ = - blink::mojom::ServiceWorkerProviderInfoForClient::New(); - service_worker_provider_host_ = - ServiceWorkerProviderHost::PreCreateForWebWorker( - helper_->context()->AsWeakPtr(), kProcessId, - blink::mojom::ServiceWorkerProviderType::kForSharedWorker, - &service_worker_provider_info_); + service_worker_handle_ = std::make_unique<ServiceWorkerNavigationHandle>( + helper_->context_wrapper()); } protected: @@ -83,18 +85,17 @@ std::unique_ptr<EmbeddedWorkerTestHelper> helper_; std::unique_ptr<FakeNetworkURLLoaderFactory> network_loader_factory_instance_; scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_; + std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_; - blink::mojom::ServiceWorkerProviderInfoForClientPtr - service_worker_provider_info_; - base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_; - + WorkerScriptLoaderFactory::BrowserContextGetter browser_context_getter_; WorkerScriptLoaderFactory::ResourceContextGetter resource_context_getter_; }; TEST_F(WorkerScriptLoaderFactoryTest, ServiceWorkerProviderHost) { // Make the factory. auto factory = std::make_unique<WorkerScriptLoaderFactory>( - kProcessId, service_worker_provider_host_, nullptr /* appcache_host */, + kProcessId, service_worker_handle_.get(), service_worker_handle_->core(), + /*appcache_host=*/nullptr, browser_context_getter_, resource_context_getter_, network_loader_factory_); // Load the script. @@ -106,19 +107,26 @@ EXPECT_EQ(net::OK, client.completion_status().error_code); // The provider host should be set up. - EXPECT_TRUE(service_worker_provider_host_->is_response_committed()); - EXPECT_TRUE(service_worker_provider_host_->is_execution_ready()); - EXPECT_EQ(url, service_worker_provider_host_->url()); + base::WeakPtr<ServiceWorkerProviderHost> host = + service_worker_handle_->core()->provider_host(); + EXPECT_TRUE(host->is_response_committed()); + EXPECT_TRUE(host->is_execution_ready()); + EXPECT_EQ(url, host->url()); } -// Test a null service worker provider host. This typically only happens during +// Test a null service worker handle. This typically only happens during // shutdown or after a fatal error occurred in the service worker system. -TEST_F(WorkerScriptLoaderFactoryTest, NullServiceWorkerProviderHost) { - // Make the factory with null provider host. +TEST_F(WorkerScriptLoaderFactoryTest, NullServiceWorkerHandle) { + // Make the factory. auto factory = std::make_unique<WorkerScriptLoaderFactory>( - kProcessId, nullptr /* service_worker_provider_host */, - nullptr /* appcache_host */, resource_context_getter_, - network_loader_factory_); + kProcessId, service_worker_handle_.get(), service_worker_handle_->core(), + nullptr /* appcache_host */, browser_context_getter_, + resource_context_getter_, network_loader_factory_); + + // Destroy the handle. + service_worker_handle_.reset(); + // Let the IO thread task run to destroy the handle core. + base::RunLoop().RunUntilIdle(); // Load the script. GURL url("https://www.example.com/worker.js"); @@ -126,16 +134,22 @@ network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(url, factory.get(), &client); client.RunUntilComplete(); - EXPECT_EQ(net::OK, client.completion_status().error_code); + EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code); } // Test a null resource context when the request starts. This happens when // shutdown starts between the constructor and when CreateLoaderAndStart is // invoked. TEST_F(WorkerScriptLoaderFactoryTest, NullResourceContext) { + if (NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) { + // Resource context is irrelevant. + return; + } + // Make the factory. auto factory = std::make_unique<WorkerScriptLoaderFactory>( - kProcessId, service_worker_provider_host_, nullptr /* appcache_host */, + kProcessId, service_worker_handle_.get(), service_worker_handle_->core(), + nullptr /* appcache_host */, browser_context_getter_, resource_context_getter_, network_loader_factory_); // Set a null resource context. @@ -150,6 +164,33 @@ EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code); } +// Test a null browser context when the request starts. This happens when +// shutdown starts between the constructor and when CreateLoaderAndStart is +// invoked. +TEST_F(WorkerScriptLoaderFactoryTest, NullBrowserContext) { + if (!NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) { + // Browser context is irrelevant. + return; + } + + // Make the factory. + auto factory = std::make_unique<WorkerScriptLoaderFactory>( + kProcessId, service_worker_handle_.get(), service_worker_handle_->core(), + nullptr /* appcache_host */, browser_context_getter_, + resource_context_getter_, network_loader_factory_); + + // Set a null browser context. + helper_->context_wrapper()->Shutdown(); + + // Load the script. + GURL url("https://www.example.com/worker.js"); + network::TestURLLoaderClient client; + network::mojom::URLLoaderPtr loader = + CreateTestLoaderAndStart(url, factory.get(), &client); + client.RunUntilComplete(); + EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code); +} + // TODO(falken): Add a test for a shared worker that's controlled by a service // worker.
diff --git a/content/public/browser/background_sync_controller.h b/content/public/browser/background_sync_controller.h index f168c74..7b024f8 100644 --- a/content/public/browser/background_sync_controller.h +++ b/content/public/browser/background_sync_controller.h
@@ -7,6 +7,8 @@ #include <stdint.h> +#include <set> + #include "base/time/time.h" #include "content/common/content_export.h" #include "content/public/browser/background_sync_registration.h" @@ -91,6 +93,13 @@ // to finish firing one sync event. virtual std::unique_ptr<BackgroundSyncEventKeepAlive> CreateBackgroundSyncEventKeepAlive() = 0; + + // Updates its internal list of origins for which we have suspended periodic + // Background Sync registrations. This is compiled from each + // BackgroundSyncManager when they are initialized. This list used to ignore + // changes concerning origins we don't care about. + virtual void NoteSuspendedPeriodicSyncOrigins( + std::set<url::Origin> suspended_origins) = 0; }; } // namespace content
diff --git a/content/public/browser/background_sync_registration.h b/content/public/browser/background_sync_registration.h index db1d5eb..e43efbd 100644 --- a/content/public/browser/background_sync_registration.h +++ b/content/public/browser/background_sync_registration.h
@@ -62,6 +62,12 @@ void set_origin(const url::Origin& origin) { origin_ = origin; } + bool is_suspended() const { + if (sync_type() == blink::mojom::BackgroundSyncType::ONE_SHOT) + return false; + return delay_until_.is_max(); + } + private: blink::mojom::SyncRegistrationOptions options_; blink::mojom::BackgroundSyncState sync_state_ =
diff --git a/content/public/browser/devtools_background_services_context.h b/content/public/browser/devtools_background_services_context.h index c84b1a01..864af759 100644 --- a/content/public/browser/devtools_background_services_context.h +++ b/content/public/browser/devtools_background_services_context.h
@@ -24,9 +24,10 @@ kPushMessaging = 4, kNotifications = 5, kPaymentHandler = 6, + kPeriodicBackgroundSync = 7, // Keep at the end. - kMaxValue = kPaymentHandler, + kMaxValue = kPeriodicBackgroundSync, }; // This class is responsible for persisting the debugging events for the
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc index 6ba2e4d..e9fc1fb 100644 --- a/content/renderer/compositor/layer_tree_view.cc +++ b/content/renderer/compositor/layer_tree_view.cc
@@ -188,14 +188,6 @@ layer_tree_host_->SetNeedsAnimate(); } -void LayerTreeView::SetHaveScrollEventHandlers(bool has_handlers) { - layer_tree_host_->SetHaveScrollEventHandlers(has_handlers); -} - -bool LayerTreeView::HaveScrollEventHandlers() const { - return layer_tree_host_->have_scroll_event_handlers(); -} - void LayerTreeView::SetLayerTreeFrameSink( std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink) { if (!layer_tree_frame_sink) {
diff --git a/content/renderer/compositor/layer_tree_view.h b/content/renderer/compositor/layer_tree_view.h index 764bc34..f43510d 100644 --- a/content/renderer/compositor/layer_tree_view.h +++ b/content/renderer/compositor/layer_tree_view.h
@@ -127,8 +127,6 @@ // blink::WebLayerTreeView implementation. viz::FrameSinkId GetFrameSinkId() override; void SetNonBlinkManagedRootLayer(scoped_refptr<cc::Layer> layer); - void SetHaveScrollEventHandlers(bool) override; - bool HaveScrollEventHandlers() const override; int LayerTreeId() const override; void UpdateBrowserControlsState(cc::BrowserControlsState constraints,
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.cc b/content/renderer/loader/web_worker_fetch_context_impl.cc index d9393f6a..e659a2c 100644 --- a/content/renderer/loader/web_worker_fetch_context_impl.cc +++ b/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -282,11 +282,18 @@ std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { DCHECK(blink::features::IsPlzDedicatedWorkerEnabled()); - DCHECK(service_worker_provider_context); DCHECK(loader_factory_info); DCHECK(fallback_factory_info); DCHECK(task_runner); + if (!service_worker_provider_context) { + return CloneForNestedWorkerInternal( + /*service_worker_client_request=*/nullptr, + /*service_worker_worker_client_registry_ptr_info=*/nullptr, + /*container_host_ptr_info=*/nullptr, std::move(loader_factory_info), + std::move(fallback_factory_info), std::move(task_runner)); + } + blink::mojom::ServiceWorkerWorkerClientRegistryPtrInfo service_worker_worker_client_registry_ptr_info; service_worker_provider_context->CloneWorkerClientRegistry(
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 370773c..734c561 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -3303,6 +3303,11 @@ Send(new WidgetHostMsg_HasTouchEventHandlers(routing_id_, has_handlers)); } +void RenderWidget::SetHaveScrollEventHandlers(bool have_handlers) { + layer_tree_view_->layer_tree_host()->SetHaveScrollEventHandlers( + have_handlers); +} + void RenderWidget::SetNeedsLowLatencyInput(bool needs_low_latency) { if (input_event_queue_) input_event_queue_->SetNeedsLowLatency(needs_low_latency);
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 75b8ef6..20f02c0b 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -432,6 +432,7 @@ void RequestUnbufferedInputEvents() override; void SetHasPointerRawUpdateEventHandlers(bool has_handlers) override; void SetHasTouchEventHandlers(bool has_handlers) override; + void SetHaveScrollEventHandlers(bool have_handlers) override; void SetNeedsLowLatencyInput(bool) override; void SetNeedsUnbufferedInputForDebugger(bool) override; void AnimateDoubleTapZoomInMainFrame(const blink::WebPoint& point,
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc index ee076c5..ba0bfc5 100644 --- a/content/renderer/worker/dedicated_worker_host_factory_client.cc +++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -120,7 +120,6 @@ subresource_loader_factory_bundle_info, blink::mojom::ControllerServiceWorkerInfoPtr controller_info) { DCHECK(blink::features::IsPlzDedicatedWorkerEnabled()); - DCHECK(service_worker_provider_info); DCHECK(main_script_load_params); DCHECK(subresource_loader_factory_bundle_info); @@ -132,12 +131,14 @@ std::move(subresource_loader_factory_bundle_info))); DCHECK(!service_worker_provider_context_); - service_worker_provider_context_ = - base::MakeRefCounted<ServiceWorkerProviderContext>( - blink::mojom::ServiceWorkerProviderType::kForDedicatedWorker, - std::move(service_worker_provider_info->client_request), - std::move(service_worker_provider_info->host_ptr_info), - std::move(controller_info), subresource_loader_factory_bundle_); + if (service_worker_provider_info) { + service_worker_provider_context_ = + base::MakeRefCounted<ServiceWorkerProviderContext>( + blink::mojom::ServiceWorkerProviderType::kForDedicatedWorker, + std::move(service_worker_provider_info->client_request), + std::move(service_worker_provider_info->host_ptr_info), + std::move(controller_info), subresource_loader_factory_bundle_); + } // Initialize the response override for the main worker script loaded by the // browser process.
diff --git a/content/renderer/worker/service_worker_network_provider_for_shared_worker.cc b/content/renderer/worker/service_worker_network_provider_for_shared_worker.cc index 1422870..0984b816 100644 --- a/content/renderer/worker/service_worker_network_provider_for_shared_worker.cc +++ b/content/renderer/worker/service_worker_network_provider_for_shared_worker.cc
@@ -24,14 +24,15 @@ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory, bool is_secure_context, std::unique_ptr<NavigationResponseOverrideParameters> response_override) { - DCHECK(info); auto provider = base::WrapUnique(new ServiceWorkerNetworkProviderForSharedWorker( is_secure_context, std::move(response_override))); - provider->context_ = base::MakeRefCounted<ServiceWorkerProviderContext>( - blink::mojom::ServiceWorkerProviderType::kForSharedWorker, - std::move(info->client_request), std::move(info->host_ptr_info), - std::move(controller_info), std::move(fallback_loader_factory)); + if (info) { + provider->context_ = base::MakeRefCounted<ServiceWorkerProviderContext>( + blink::mojom::ServiceWorkerProviderType::kForSharedWorker, + std::move(info->client_request), std::move(info->host_ptr_info), + std::move(controller_info), std::move(fallback_loader_factory)); + } return provider; }
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 5ab0027..d35002a 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -136,14 +136,6 @@ # context loss which results in hardware decoder loss. crbug.com/580386 [ android ] Pixel_Video_Context_Loss_MP4 [ Skip ] -# Fails on Mac Pro FYI Release (AMD) -crbug.com/925744 [ mac amd-0x679e ] Pixel_Video_MP4 [ Skip ] -crbug.com/925744 [ mac amd-0x679e ] Pixel_Video_Context_Loss_MP4 [ Skip ] -crbug.com/911413 [ mac amd-0x679e ] Pixel_Video_MP4_FourColors_Aspect_4x3 [ Skip ] -crbug.com/911413 [ mac amd-0x679e ] Pixel_Video_MP4_FourColors_Rot_90 [ Skip ] -crbug.com/911413 [ mac amd-0x679e ] Pixel_Video_MP4_FourColors_Rot_180 [ Skip ] -crbug.com/911413 [ mac amd-0x679e ] Pixel_Video_MP4_FourColors_Rot_270 [ Skip ] - # Fails on multiple Android devices. crbug.com/927107 [ android no-skia-renderer ] Pixel_CSS3DBlueBox [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 53bc624..940cd706 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -182,7 +182,6 @@ crbug.com/963205 [ win nvidia opengl passthrough ] conformance/extensions/webgl-compressed-texture-s3tc-srgb.html [ RetryOnFailure ] crbug.com/715001 [ opengl win nvidia ] conformance/limits/gl-max-texture-dimensions.html [ Failure ] crbug.com/703779 [ opengl win nvidia ] conformance/textures/misc/texture-size.html [ Failure ] -crbug.com/830046 [ opengl win passthrough nvidia ] conformance2/rendering/blitframebuffer-size-overflow.html [ Skip ] crbug.com/781668 [ opengl win nvidia-0x1cb3 ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_byte.html [ Failure ] crbug.com/921055 [ opengl win passthrough nvidia-0x1cb3 ] conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-float.html [ RetryOnFailure ] crbug.com/905003 [ opengl win passthrough nvidia ] conformance2/textures/misc/integer-cubemap-specification-order-bug.html [ Failure ] @@ -548,9 +547,6 @@ crbug.com/680282 [ linux nvidia-0xf02 ] conformance2/textures/image/tex-3d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] crbug.com/694354 [ linux no-passthrough nvidia ] conformance2/textures/image_bitmap_from_image_data/tex-2d-srgb8-rgb-unsigned_byte.html [ RetryOnFailure ] -# Linux NVIDIA Quadro P400 -crbug.com/830046 [ linux passthrough nvidia-0x1cb3 ] conformance2/rendering/blitframebuffer-size-overflow.html [ Skip ] - # Observed flaky on Swarmed bots. Some of these were directly # observed, some not. We can't afford any flakes on the tryservers # so mark them all flaky. @@ -590,7 +586,6 @@ # It looks like AMD shader compiler rejects many valid ES3 semantics. crbug.com/844311 [ linux amd ] conformance/glsl/misc/fragcolor-fragdata-invariant.html [ Failure ] crbug.com/766776 [ linux amd ] conformance2/attribs/gl-vertex-attrib-normalized-int.html [ Failure ] -crbug.com/483282 [ linux amd ] conformance/glsl/misc/shaders-with-invariance.html [ Failure ] crbug.com/981070 [ linux amd ] conformance2/glsl3/matrix-row-major.html [ Failure ] crbug.com/709351 [ linux amd ] conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html [ Failure ] crbug.com/617290 [ linux amd ] deqp/functional/gles3/multisample.html [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 39cdb0a..5df13fe 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -196,7 +196,6 @@ # Win / OpenGL / AMD failures crbug.com/649824 [ win amd opengl ] conformance/attribs/gl-bindAttribLocation-aliasing.html [ Skip ] crbug.com/angleproject/1007 [ win amd opengl ] conformance/glsl/misc/shader-struct-scope.html [ Skip ] -crbug.com/angleproject/1007 [ win amd opengl no-passthrough ] conformance/glsl/misc/shaders-with-invariance.html [ Skip ] crbug.com/angleproject/1007 [ win amd opengl ] conformance/glsl/misc/struct-nesting-of-variable-names.html [ Failure ] crbug.com/angleproject/1506 [ win amd opengl ] conformance/rendering/clipping-wide-points.html [ Failure ] @@ -375,13 +374,11 @@ # AMD Radeon 6450 and/or R7 240 crbug.com/479260 [ linux amd no-angle ] conformance/extensions/angle-instanced-arrays.html [ Failure ] -crbug.com/479952 [ linux amd no-passthrough ] conformance/glsl/misc/shaders-with-invariance.html [ Failure ] # Linux passthrough AMD crbug.com/960808 [ linux amd passthrough ] conformance/glsl/misc/shader-with-non-reserved-words.html [ Failure ] # Linux passthrough AMD OpenGL -crbug.com/angleproject/1007 [ linux amd opengl passthrough ] conformance/glsl/misc/shaders-with-invariance.html [ Skip ] crbug.com/965594 [ linux amd opengl passthrough ] conformance/more/conformance/quickCheckAPI-S_V.html [ RetryOnFailure ] crbug.com/965594 [ linux amd opengl passthrough ] conformance/more/conformance/webGLArrays.html [ RetryOnFailure ] @@ -437,7 +434,6 @@ crbug.com/611943 [ android qualcomm-adreno-(tm)-330 ] conformance/glsl/matrices/glsl-mat4-to-mat3.html [ Failure ] crbug.com/611943 [ android qualcomm-adreno-(tm)-330 ] conformance/glsl/misc/shader-struct-scope.html [ Failure ] crbug.com/611943 [ android qualcomm-adreno-(tm)-330 ] conformance/glsl/misc/shader-with-vec4-vec3-vec4-conditional.html [ Failure ] -crbug.com/611943 [ android qualcomm-adreno-(tm)-330 no-passthrough ] conformance/glsl/misc/shaders-with-invariance.html [ Failure ] crbug.com/611943 [ android qualcomm-adreno-(tm)-330 ] conformance/glsl/misc/struct-equals.html [ Failure ] crbug.com/478572 [ android qualcomm-adreno-(tm)-330 ] deqp/data/gles2/shaders/linkage.html [ Failure ] [ android qualcomm-adreno-(tm)-330 no-passthrough ] WebglExtension_OES_texture_float_linear [ Failure ] @@ -495,7 +491,6 @@ # The list of tests which may be that future test is very long. It is # almost (but not quite) every webgl conformance test. crbug.com/614550 [ android qualcomm-adreno-(tm)-420 ] conformance/glsl/misc/shader-struct-scope.html [ Skip ] -crbug.com/611945 [ android qualcomm-adreno-(tm)-420 no-passthrough ] conformance/glsl/misc/shaders-with-invariance.html [ Failure ] # bindBufferBadArgs is causing the GPU thread to crash, taking # down the WebView shell, causing the next test to fail and
diff --git a/content/test/mock_background_sync_controller.cc b/content/test/mock_background_sync_controller.cc index 7df871e4..d97a2677 100644 --- a/content/test/mock_background_sync_controller.cc +++ b/content/test/mock_background_sync_controller.cc
@@ -6,6 +6,9 @@ namespace content { +MockBackgroundSyncController::MockBackgroundSyncController() = default; +MockBackgroundSyncController::~MockBackgroundSyncController() = default; + void MockBackgroundSyncController::NotifyOneShotBackgroundSyncRegistered( const url::Origin& origin, bool can_fire, @@ -59,4 +62,11 @@ return nullptr; } +void MockBackgroundSyncController::NoteSuspendedPeriodicSyncOrigins( + std::set<url::Origin> suspended_origins) { + for (auto& origin : suspended_origins) { + suspended_periodic_sync_origins_.insert(std::move(origin)); + } +} + } // namespace content
diff --git a/content/test/mock_background_sync_controller.h b/content/test/mock_background_sync_controller.h index ce42a07..36d2b1b3 100644 --- a/content/test/mock_background_sync_controller.h +++ b/content/test/mock_background_sync_controller.h
@@ -20,8 +20,8 @@ // Mocks a BackgroundSyncController, tracking state for use in tests. class MockBackgroundSyncController : public BackgroundSyncController { public: - MockBackgroundSyncController() = default; - ~MockBackgroundSyncController() override = default; + MockBackgroundSyncController(); + ~MockBackgroundSyncController() override; // BackgroundSyncController: void NotifyOneShotBackgroundSyncRegistered(const url::Origin& origin, @@ -35,6 +35,8 @@ BackgroundSyncParameters* parameters) override; std::unique_ptr<BackgroundSyncController::BackgroundSyncEventKeepAlive> CreateBackgroundSyncEventKeepAlive() override; + void NoteSuspendedPeriodicSyncOrigins( + std::set<url::Origin> suspended_registrations) override; int registration_count() const { return registration_count_; } const url::Origin& registration_origin() const { @@ -57,6 +59,7 @@ int run_in_background_for_one_shot_sync_count_ = 0; int run_in_background_for_periodic_sync_count_ = 0; BackgroundSyncParameters background_sync_parameters_; + std::set<url::Origin> suspended_periodic_sync_origins_; DISALLOW_COPY_AND_ASSIGN(MockBackgroundSyncController); };
diff --git a/device/fido/make_credential_handler_unittest.cc b/device/fido/make_credential_handler_unittest.cc index 57222e9..04cb0b3 100644 --- a/device/fido/make_credential_handler_unittest.cc +++ b/device/fido/make_credential_handler_unittest.cc
@@ -606,12 +606,11 @@ // keys in AuthenicatorSelectionCriteria. TEST_F(FidoMakeCredentialHandlerTest, SuccessfulMakeCredentialWithResidentKeyOption) { - auto device = std::make_unique<VirtualCtap2Device>(); - AuthenticatorSupportedOptions option; - option.supports_resident_key = true; - option.user_verification_availability = AuthenticatorSupportedOptions:: - UserVerificationAvailability::kSupportedAndConfigured; - device->SetAuthenticatorSupportedOptions(std::move(option)); + VirtualCtap2Device::Config config; + config.resident_key_support = true; + config.internal_uv_support = true; + auto state = base::MakeRefCounted<VirtualFidoDevice::State>(); + state->fingerprints_enrolled = true; auto request_handler = CreateMakeCredentialHandlerWithAuthenticatorSelectionCriteria( @@ -620,7 +619,8 @@ UserVerificationRequirement::kPreferred)); discovery()->WaitForCallToStartAndSimulateSuccess(); - discovery()->AddDevice(std::move(device)); + discovery()->AddDevice(std::make_unique<VirtualCtap2Device>( + std::move(state), std::move(config))); scoped_task_environment_.FastForwardUntilNoTasksRemain(); callback().WaitForCallback();
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc index 9af9f17..843bd0f 100644 --- a/device/fido/virtual_ctap2_device.cc +++ b/device/fido/virtual_ctap2_device.cc
@@ -699,11 +699,6 @@ return weak_factory_.GetWeakPtr(); } -void VirtualCtap2Device::SetAuthenticatorSupportedOptions( - const AuthenticatorSupportedOptions& options) { - device_info_->options = options; -} - base::Optional<CtapDeviceResponseCode> VirtualCtap2Device::OnMakeCredential( base::span<const uint8_t> request_bytes, std::vector<uint8_t>* response) {
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h index 983671e9..0dc4d33b9 100644 --- a/device/fido/virtual_ctap2_device.h +++ b/device/fido/virtual_ctap2_device.h
@@ -84,11 +84,11 @@ // sequence. This is used to simulate a security key that truncates strings // at a pre-defined byte length without concern for UTF-8 validity of the // result. - bool allow_invalid_utf8_in_credential_entities = true; + bool allow_invalid_utf8_in_credential_entities = false; }; VirtualCtap2Device(); - explicit VirtualCtap2Device(scoped_refptr<State> state, const Config& config); + VirtualCtap2Device(scoped_refptr<State> state, const Config& config); ~VirtualCtap2Device() override; // FidoDevice: @@ -97,9 +97,6 @@ DeviceCallback cb) override; base::WeakPtr<FidoDevice> GetWeakPtr() override; - void SetAuthenticatorSupportedOptions( - const AuthenticatorSupportedOptions& options); - private: base::Optional<CtapDeviceResponseCode> OnMakeCredential( base::span<const uint8_t> request,
diff --git a/docs/accessibility/select_to_speak.md b/docs/accessibility/select_to_speak.md new file mode 100644 index 0000000..da1b1b6 --- /dev/null +++ b/docs/accessibility/select_to_speak.md
@@ -0,0 +1,220 @@ +# Select to Speak (for developers) + +Select to Speak is a Chrome OS feature to read text on the screen out loud. + + +There are millions of users who greatly benefit from some text-to-speech but +don’t quite need a full screen reading experience where everything is read +aloud each step of the way. For these users, whether they are low vision, +dyslexic, neurologically diverse, or simply prefer to listen to text read +aloud instead of visually reading it, we have built Select-to-Speak. + +## Using Select to Speak + +Go to Chrome settings, Accessibility settings, “Manage accessibility Features”, +and enable “Select to Speak”. You can adjust the preferred voice, highlight +color, and access text-to-speech preferences from the settings page. + +With this feature enabled, you can read text on the screen in one of three ways: + +- Hold down the Search key, then use the touchpad or external mouse to tap or +drag a region to be spoken + +- Tap the Select-to-Speak icon in the status tray and use the mouse or +touchscreen to select a region to be spoken + +- Highlight text and use Search+S to speak only the selected text. + +Read more on the +[Chrome help page](https://support.google.com/chromebook/answer/9032490?hl=en) +under “Listen to part of a page”. + +## Reporting bugs + +Use bugs.chromium.org, filing bugs under the component +[UI>Accessibility>SelectToSpeak](https://bugs.chromium.org/p/chromium/issues/list?sort=-opened&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified&q=component%3AUI%3EAccessibility%3ESelectToSpeak%20&can=2). + +## Developing + +*Select to Speak will be abbreviated STS in this section.* + +### Code location + +STS code lives mainly in three places: + +- A component extension to do the bulk of the logic and processing, +chrome/browser/resources/chromeos/select_to_speak/ + +- An event handler, ash/events/select_to_speak_event_handler.h + +- The status tray button, ash/system/accessibility/select_to_speak_tray.h + +In addition, there are settings for STS in +chrome/browser/resources/settings/a11y_page/manage_a11y_page.* + +### Tests + +Tests are in ash_unittests and in browser_tests: + +``` +out/Release/ash_unittests --gtest_filter=”SelectToSpeak*” +out/Release/browser_tests --gtest_filter=”SelectToSpeak*” +``` +### Debugging + +Developers can add log lines to any of the C++ files and see output in the +console. To debug the STS extension, the easiest way is from an external +browser. Start Chrome OS on Linux with this command-line flag: + +``` +out/Release/chrome --remote-debugging-port=9222 +``` + +Now open http://localhost:9222 in a separate instance of the browser, and +debug the Select to Speak extension background page from there. + +## How it works + +Like [Chromevox](chromevox.md), STS is implemented mainly as a component +Chrome extension which is always loaded and running in the background when +enabled, and unloaded when disabled. The only STS code outside of the +extension is an EventRewriter which forwards keyboard and mouse events to +the extension as needed, so that the extension can get events systemwide. + +The STS extension does the following, at a high level: + +1. Tracks key and mouse events to determine when a user has either: + + a. Held down “search” and clicked & dragged a rectangle to specify a + selection + + b. Used “search” + “s” to indicate that selected text should be read + + c. Has requested speech to be canceled by tapping ‘control’ or ‘search’ + alone + +2. Determines the Accessibility nodes that make up the selected region + +3. Sends utterances to the Chrome Text-to-Speech extension to be spoken + +4. Tracks utterance progress and updates the focus ring and highlight as needed. + +### Select to Speak extension structure + +Most STS logic takes place in +[select_to_speak.js](https://cs.chromium.org/chromium/src/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js). + +#### User input + +Input to the extension is handled by input_handler.js, which handles user +input from mouse, keyboard, and touchscreen events. Most logic here revolves +around keeping track of state to see if the user has requested text using +one of the three ways to activate the feature, search + mouse, tray button ++ mouse, or search + s. + +#### Determining selected content + +Once input_handler determines that the user did request text to be spoken, +STS must determine which part of the page to read. To do this it requests +information from the Automation API, and then generates a list of +AutomationNodes to be read. + +##### With mouse or touchpad + +select_to_speak.js fires a HitTest to the Automation API at the center of +the rect selected by the user. When the API gets a result it returns via +SelectToSpeak.onAutomationHitTest_. This function walks up from the hit +test node to the nearest container to find a root, then back down through +all the root’s children to find ones that overlap with the selected rect. +Walking back down through the children occurs in NodeUtils.findAllMatching, +and results in a list of AutomationNodes that can be sent for speech. + +##### With search + s + +select_to_speak.js requests focus information from the Automation API. The +focus result is sent to SelectToSpeak.requestSpeakSelectedText_, which +uses Automation selection to determine which nodes are selected. The +complexity of logic here is converting between Automation selection and +its deep equivalent, i.e. from parent nodes and offsets to their leaves. +This occurs in NodeUtils.getDeepEquivalentForSelection. When the first and +last nodes in selection are found, SelectToSpeak.readNodesInSelection_ is +used to determine the entire list of AutomationNodes which should be sent +for speech. + +#### Speaking selected content + +SelectToSpeak.startSpeechQueue_ takes a list of AutomationNodes, determines +their text content, and sends the result to the Text to Speech API for +speech. It begins by mapping the text content of the nodes to the nodes +themselves, so that STS can speak smoothly across node boundaries (i.e. +across line breaks) and follow speech progress with a highlight. The mapping +between text and nodes occurs in repeated calls to +ParagraphUtils.buildNodeGroup to build lists of nodes that should be spoken +smoothly. + + +Each node group is sent to the Text to Speech API, with callbacks to allow +for speech progress tracking, enabling the highlight to be dynamically +updated with each word. + +#### Highlighting content during speech + +On each word boundary event, the TTS API sends a callback which is handled +by SelectToSpeak.onTtsWordEvent_. This is used to check against the list of +nodes being spoken to see which node is currently being spoken, and further +check against the words in the node to see which word is spoken. + +#### Edge cases + +STS must also handle cases where: + +- Nodes become invalid during speech, i.e. if a page was closed. Speech +should continue, but highlight stops. + +- Nodes disappear and re-appear during speech (a user may have switched +tabs and switched back, or scrolled). Highlight should resume. + +This occurs in SelectToSpeak.updateFromNodeState_. + +### Communication with SelectToSpeakTray + +STS runs in the extension process, but needs to communicate its three states +(Inactive, Selecting, and Speaking) to the STS button in the status tray. +It also needs to listen for users requesting state change using the +SelectToSpeakTray button. The STS extension uses the AccessibitilityPrivate +method onSelectToSpeakStateChanged to inform the SelectToSpeakTray of a +status change, and listens to onSelectToSpeakStateChangeRequested to know +when a user wants to change state. The STS extension is the source of truth +for STS state. + +### Special case: Google Drive apps + +Google Drive apps require a few work-arounds to work correctly with STS. + +- Any time a Google Drive document is loaded (such as a Doc, Sheet or Slides +document), the script +[select_to_speak_gdocs_script](https://cs.chromium.org/chromium/src/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_gdocs_script.js?q=select_to_speak_gdocs_script.js+file:%5Esrc/chrome/browser/resources/chromeos/select_to_speak/+package:%5Echromium$&dr) +must be executed to remove aria-hidden from the content container. + +- Using search+s to read highlighted text uses the clipboard to get text data +from Google Docs, as selection information may not be available in the +Automation API. This happens mostly in input_handler.js. + +## For Googlers + +For more, Googlers could check out the Select to Speak feature design docs +for more details on design as well as UMA. + +- Overall product design, [go/select-to-speak-design](go/select-to-speak-design) + +- On-Screen UI for touch and tablet modes, +[go/chromeos-sts-on-screen-ui](go/chromeos-sts-on-screen-ui) + +- Reading text at keystroke, +[go/chromeos-sts-selection-keystroke](go/chromeos-sts-selection-keystroke) + +- Reading text at keystroke in Google Drive apps, [go/sts-selection-in-drive](go/sts-selection-in-drive) + +- Per word highlighting, +[go/chrome-sts-sentences-and-words](go/chrome-sts-sentences-and-words) and +[go/chromeos-sts-highlight](go/chromeos-sts-highlight)
diff --git a/extensions/renderer/runtime_hooks_delegate.cc b/extensions/renderer/runtime_hooks_delegate.cc index 78197f1..6dc92ed 100644 --- a/extensions/renderer/runtime_hooks_delegate.cc +++ b/extensions/renderer/runtime_hooks_delegate.cc
@@ -89,6 +89,28 @@ : messaging_service_(messaging_service) {} RuntimeHooksDelegate::~RuntimeHooksDelegate() {} +// static +RequestResult RuntimeHooksDelegate::GetURL( + ScriptContext* script_context, + const std::vector<v8::Local<v8::Value>>& arguments) { + DCHECK_EQ(1u, arguments.size()); + DCHECK(arguments[0]->IsString()); + DCHECK(script_context->extension()); + + v8::Isolate* isolate = script_context->isolate(); + std::string path = gin::V8ToString(isolate, arguments[0]); + + RequestResult result(RequestResult::HANDLED); + std::string url = base::StringPrintf( + "chrome-extension://%s%s%s", script_context->extension()->id().c_str(), + !path.empty() && path[0] == '/' ? "" : "/", path.c_str()); + result.return_value = gin::StringToV8(isolate, url); + // TODO(tjudkins): Gather data on how often this is passed a bad URL (i.e. not + // a relative file path for the extension), so we can decide if it's fine to + // throw an error in those cases. + return result; +} + RequestResult RuntimeHooksDelegate::HandleRequest( const std::string& method_name, const APISignature* signature, @@ -174,20 +196,7 @@ RequestResult RuntimeHooksDelegate::HandleGetURL( ScriptContext* script_context, const std::vector<v8::Local<v8::Value>>& arguments) { - DCHECK_EQ(1u, arguments.size()); - DCHECK(arguments[0]->IsString()); - DCHECK(script_context->extension()); - - v8::Isolate* isolate = script_context->isolate(); - std::string path = gin::V8ToString(isolate, arguments[0]); - - RequestResult result(RequestResult::HANDLED); - std::string url = base::StringPrintf( - "chrome-extension://%s%s%s", script_context->extension()->id().c_str(), - !path.empty() && path[0] == '/' ? "" : "/", path.c_str()); - result.return_value = gin::StringToV8(isolate, url); - - return result; + return GetURL(script_context, arguments); } RequestResult RuntimeHooksDelegate::HandleSendMessage(
diff --git a/extensions/renderer/runtime_hooks_delegate.h b/extensions/renderer/runtime_hooks_delegate.h index c4a3b49e..41cda74 100644 --- a/extensions/renderer/runtime_hooks_delegate.h +++ b/extensions/renderer/runtime_hooks_delegate.h
@@ -22,6 +22,14 @@ NativeRendererMessagingService* messaging_service); ~RuntimeHooksDelegate() override; + // Returns an absolute url for a path inside of an extension, as requested + // through the getURL API call. + // NOTE: Static as the logic is used by both the runtime and extension + // hooks. + static APIBindingHooks::RequestResult GetURL( + ScriptContext* script_context, + const std::vector<v8::Local<v8::Value>>& arguments); + // APIBindingHooksDelegate: APIBindingHooks::RequestResult HandleRequest( const std::string& method_name,
diff --git a/extensions/renderer/runtime_hooks_delegate_unittest.cc b/extensions/renderer/runtime_hooks_delegate_unittest.cc index bf26381..582c14f 100644 --- a/extensions/renderer/runtime_hooks_delegate_unittest.cc +++ b/extensions/renderer/runtime_hooks_delegate_unittest.cc
@@ -168,6 +168,8 @@ get_url("''", extension()->url()); get_url("'foo'", extension()->GetResourceURL("foo")); get_url("'/foo'", extension()->GetResourceURL("foo")); + get_url("'https://www.google.com'", + GURL(extension()->url().spec() + "https://www.google.com")); } TEST_F(RuntimeHooksDelegateTest, Connect) { @@ -253,15 +255,12 @@ tester.TestSendMessage("null, {data: 'hello'}, function() {}", kStandardMessage, self_target, false, SendMessageTester::OPEN); - tester.TestSendMessage("null, 'test', function() {}", - R"("test")", self_target, false, - SendMessageTester::OPEN); - tester.TestSendMessage("null, 'test'", - R"("test")", self_target, false, + tester.TestSendMessage("null, 'test', function() {}", R"("test")", + self_target, false, SendMessageTester::OPEN); + tester.TestSendMessage("null, 'test'", R"("test")", self_target, false, SendMessageTester::CLOSED); - tester.TestSendMessage("undefined, 'test', function() {}", - R"("test")", self_target, false, - SendMessageTester::OPEN); + tester.TestSendMessage("undefined, 'test', function() {}", R"("test")", + self_target, false, SendMessageTester::OPEN); // Funny case. The only required argument is `message`, which can be any type. // This means that if an extension provides a <string, object> pair for the
diff --git a/ios/chrome/browser/app_launcher/BUILD.gn b/ios/chrome/browser/app_launcher/BUILD.gn index 3d59ccb..02f73a9 100644 --- a/ios/chrome/browser/app_launcher/BUILD.gn +++ b/ios/chrome/browser/app_launcher/BUILD.gn
@@ -23,6 +23,7 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/reading_list", "//ios/chrome/browser/u2f", + "//ios/web/common", "//ios/web/public", "//url", ]
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm index a9923dfe..2ca5b88 100644 --- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm +++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm
@@ -17,9 +17,9 @@ #import "ios/chrome/browser/chrome_url_util.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/u2f/u2f_tab_helper.h" +#import "ios/web/common/url_scheme_util.h" #import "ios/web/public/navigation/navigation_item.h" #import "ios/web/public/navigation/navigation_manager.h" -#import "ios/web/public/url_scheme_util.h" #import "ios/web/public/web_client.h" #import "net/base/mac/url_conversions.h" #include "url/gurl.h"
diff --git a/ios/chrome/browser/autofill/BUILD.gn b/ios/chrome/browser/autofill/BUILD.gn index c69f901..24a16bf 100644 --- a/ios/chrome/browser/autofill/BUILD.gn +++ b/ios/chrome/browser/autofill/BUILD.gn
@@ -72,6 +72,7 @@ "//ios/chrome/browser/webdata_services", "//ios/chrome/common/colors", "//ios/chrome/common/ui_util", + "//ios/web/common", "//ios/web/public/deprecated", "//ios/web/public/js_messaging", "//third_party/leveldatabase",
diff --git a/ios/chrome/browser/autofill/form_suggestion_controller.mm b/ios/chrome/browser/autofill/form_suggestion_controller.mm index 0489bda7..2d5b2b90 100644 --- a/ios/chrome/browser/autofill/form_suggestion_controller.mm +++ b/ios/chrome/browser/autofill/form_suggestion_controller.mm
@@ -20,9 +20,9 @@ #import "ios/chrome/browser/autofill/form_suggestion_view.h" #import "ios/chrome/browser/passwords/password_generation_utils.h" #include "ios/chrome/browser/ui/util/ui_util.h" +#import "ios/web/common/url_scheme_util.h" #import "ios/web/public/deprecated/crw_js_injection_receiver.h" #import "ios/web/public/js_messaging/web_frames_manager.h" -#import "ios/web/public/url_scheme_util.h" #import "ios/web/public/web_state/ui/crw_web_view_proxy.h" #import "ios/web/public/web_state/web_state.h"
diff --git a/ios/chrome/browser/browsing_data/cache_counter.cc b/ios/chrome/browser/browsing_data/cache_counter.cc index 1b4d67e..fadbec1e 100644 --- a/ios/chrome/browser/browsing_data/cache_counter.cc +++ b/ios/chrome/browser/browsing_data/cache_counter.cc
@@ -43,13 +43,12 @@ STEP_GET_BACKEND, // Get the disk_cache::Backend instance. STEP_COUNT, // Run CalculateSizeOfAllEntries() on it. STEP_CALLBACK, // Respond on the UI thread. - STEP_DONE // Calculation completed. }; void CountInternal(int64_t rv) { DCHECK_CURRENTLY_ON(web::WebThread::IO); - while (rv != net::ERR_IO_PENDING && next_step_ != STEP_DONE) { + while (rv != net::ERR_IO_PENDING) { // In case of an error, skip to the last step. if (rv < 0) next_step_ = STEP_CALLBACK; @@ -83,7 +82,6 @@ } case STEP_CALLBACK: { - next_step_ = STEP_DONE; result_ = rv; base::PostTaskWithTraits( @@ -91,11 +89,10 @@ base::BindOnce(&IOThreadCacheCounter::OnCountingFinished, base::Unretained(this))); - break; - } - - case STEP_DONE: { - NOTREACHED(); + // Return instead of break. + // The task above deletes this object; app would crash if this object + // is deleted before reentrance of the loop. + return; } } }
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index fddf59e6..d968917 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -61,9 +61,10 @@ #include "ios/chrome/browser/web/tab_id_tab_helper.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/web/common/origin_util.h" +#include "ios/web/common/url_scheme_util.h" #import "ios/web/public/deprecated/crw_js_injection_receiver.h" #include "ios/web/public/js_messaging/web_frame.h" -#include "ios/web/public/url_scheme_util.h" +#include "ios/web/public/js_messaging/web_frame_util.h" #import "ios/web/public/web_state/web_state.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "ui/base/l10n/l10n_util_mac.h"
diff --git a/ios/chrome/browser/send_tab_to_self/ios_send_tab_to_self_infobar_delegate.cc b/ios/chrome/browser/send_tab_to_self/ios_send_tab_to_self_infobar_delegate.cc index 6bf918b3b..52978bd9 100644 --- a/ios/chrome/browser/send_tab_to_self/ios_send_tab_to_self_infobar_delegate.cc +++ b/ios/chrome/browser/send_tab_to_self/ios_send_tab_to_self_infobar_delegate.cc
@@ -66,7 +66,7 @@ model_->MarkEntryOpened(entry_->GetGUID()); RecordNotificationHistogram(SendTabToSelfNotification::kOpened); infobar()->owner()->OpenURL(entry_->GetURL(), - WindowOpenDisposition::CURRENT_TAB); + WindowOpenDisposition::NEW_FOREGROUND_TAB); return true; }
diff --git a/ios/chrome/browser/ui/autofill/BUILD.gn b/ios/chrome/browser/ui/autofill/BUILD.gn index 3e35495..d54d0ac1 100644 --- a/ios/chrome/browser/ui/autofill/BUILD.gn +++ b/ios/chrome/browser/ui/autofill/BUILD.gn
@@ -58,6 +58,7 @@ "//ios/public/provider/chrome/browser", "//ios/third_party/material_components_ios", "//ios/third_party/material_roboto_font_loader_ios", + "//ios/web/common", "//ios/web/public/deprecated", "//ios/web/public/js_messaging", "//ui/base",
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm b/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm index 4ad983d..36d6d49 100644 --- a/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm +++ b/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm
@@ -26,10 +26,10 @@ #import "ios/chrome/browser/ui/util/keyboard_observer_helper.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/web/common/url_scheme_util.h" #import "ios/web/public/deprecated/crw_js_injection_receiver.h" #include "ios/web/public/js_messaging/web_frame.h" #include "ios/web/public/js_messaging/web_frames_manager.h" -#import "ios/web/public/url_scheme_util.h" #import "ios/web/public/web_state/web_state.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
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 a48d433..02a21d1f 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -182,13 +182,13 @@ #include "ios/public/provider/chrome/browser/voice/voice_search_controller.h" #include "ios/public/provider/chrome/browser/voice/voice_search_provider.h" #import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h" +#include "ios/web/common/url_scheme_util.h" #import "ios/web/public/deprecated/crw_js_injection_receiver.h" #import "ios/web/public/deprecated/crw_native_content_holder.h" #import "ios/web/public/deprecated/crw_native_content_provider.h" #import "ios/web/public/deprecated/crw_web_controller_util.h" #include "ios/web/public/navigation/navigation_item.h" #include "ios/web/public/thread/web_thread.h" -#include "ios/web/public/url_scheme_util.h" #include "ios/web/public/web_client.h" #import "ios/web/public/web_state/context_menu_params.h" #import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
diff --git a/ios/chrome/browser/ui/favicon/resources/BUILD.gn b/ios/chrome/browser/ui/favicon/resources/BUILD.gn index aa6b381..3d7c12a 100644 --- a/ios/chrome/browser/ui/favicon/resources/BUILD.gn +++ b/ios/chrome/browser/ui/favicon/resources/BUILD.gn
@@ -39,12 +39,3 @@ "default_favicon.imageset/default_favicon@3x.png", ] } - -imageset("default_favicon_incognito") { - sources = [ - "default_favicon_incognito.imageset/Contents.json", - "default_favicon_incognito.imageset/default_favicon_incognito.png", - "default_favicon_incognito.imageset/default_favicon_incognito@2x.png", - "default_favicon_incognito.imageset/default_favicon_incognito@3x.png", - ] -}
diff --git a/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/Contents.json b/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/Contents.json deleted file mode 100644 index d76f15b5..0000000 --- a/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/Contents.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "scale": "1x", - "filename": "default_favicon_incognito.png" - }, - { - "idiom": "universal", - "scale": "2x", - "filename": "default_favicon_incognito@2x.png" - }, - { - "idiom": "universal", - "scale": "3x", - "filename": "default_favicon_incognito@3x.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito.png b/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito.png deleted file mode 100644 index 5d59a8b6..0000000 --- a/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@2x.png b/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@2x.png deleted file mode 100644 index 39620f2..0000000 --- a/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@3x.png b/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@3x.png deleted file mode 100644 index 87c9560..0000000 --- a/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm index 879056b..d122353e 100644 --- a/ios/chrome/browser/ui/payments/payment_request_manager.mm +++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm
@@ -57,6 +57,7 @@ #import "ios/chrome/browser/ui/payments/payment_request_coordinator.h" #import "ios/chrome/browser/ui/payments/payment_request_error_coordinator.h" #include "ios/web/common/origin_util.h" +#import "ios/web/common/url_scheme_util.h" #import "ios/web/public/deprecated/crw_js_injection_receiver.h" #include "ios/web/public/deprecated/url_verification_constants.h" #include "ios/web/public/favicon/favicon_status.h" @@ -66,7 +67,6 @@ #include "ios/web/public/navigation/navigation_item.h" #include "ios/web/public/navigation/navigation_manager.h" #include "ios/web/public/security/ssl_status.h" -#import "ios/web/public/url_scheme_util.h" #import "ios/web/public/web_state/ui/crw_web_view_proxy.h" #import "ios/web/public/web_state/web_state.h" #import "ios/web/public/web_state/web_state_observer_bridge.h"
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h index 2bd0fca..4833e07 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h +++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h
@@ -14,7 +14,6 @@ // Returns whether the entry is read. - (BOOL)isItemRead:(id<ReadingListListItem>)item; -- (void)deleteItem:(id<ReadingListListItem>)item; - (void)openItemInNewTab:(id<ReadingListListItem>)item; - (void)openItemInNewIncognitoTab:(id<ReadingListListItem>)item; - (void)openItemOffline:(id<ReadingListListItem>)item;
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.mm b/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.mm index 47e4fd9..d93eca7 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.mm
@@ -55,11 +55,6 @@ - (NSArray<UIAccessibilityCustomAction*>*)customActionsForItem: (id<ReadingListListItem>)item { - ReadingListCustomAction* deleteAction = [[ReadingListCustomAction alloc] - initWithName:l10n_util::GetNSString(IDS_IOS_READING_LIST_DELETE_BUTTON) - target:self - selector:@selector(deleteItem:) - item:item]; ReadingListCustomAction* toggleReadStatus = nil; if ([self.accessibilityDelegate isItemRead:item]) { toggleReadStatus = [[ReadingListCustomAction alloc] @@ -97,7 +92,7 @@ item:item]; NSMutableArray* customActions = [NSMutableArray - arrayWithObjects:deleteAction, toggleReadStatus, openInNewTabAction, + arrayWithObjects:toggleReadStatus, openInNewTabAction, openInNewIncognitoTabAction, copyURLAction, nil]; if (item.distillationState == ReadingListUIDistillationStatusSuccess) { @@ -117,11 +112,6 @@ return customActions; } -- (BOOL)deleteItem:(ReadingListCustomAction*)action { - [self.accessibilityDelegate deleteItem:action.item]; - return YES; -} - - (BOOL)markRead:(ReadingListCustomAction*)action { [self.accessibilityDelegate markItemRead:action.item]; return YES;
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm index f0753dba..f9d5403 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -359,13 +359,6 @@ return [self.dataSource isItemRead:item]; } -- (void)deleteItem:(id<ReadingListListItem>)item { - TableViewModel* model = self.tableViewModel; - TableViewItem* tableViewItem = base::mac::ObjCCastStrict<TableViewItem>(item); - if ([model hasItem:tableViewItem]) - [self deleteItemsAtIndexPaths:@[ [model indexPathForItem:tableViewItem] ]]; -} - - (void)openItemInNewTab:(id<ReadingListListItem>)item { [self.delegate readingListListViewController:self openItemInNewTab:item
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn index 5271a7b..ee46488 100644 --- a/ios/chrome/browser/ui/tabs/BUILD.gn +++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -31,11 +31,10 @@ "resources:tabstrip_background_tab", "resources:tabstrip_foreground_tab", "resources:tabstrip_inactive_tab_close_button_color", + "resources:tabstrip_inactive_tab_text_color", "resources:tabstrip_incognito_background_tab", "resources:tabstrip_incognito_foreground_tab", "resources:tabstrip_new_tab", - "resources:tabstrip_new_tab_incognito", - "resources:tabstrip_new_tab_incognito_pressed", "resources:tabstrip_new_tab_pressed", "resources:tabstrip_tab_switcher_count_button", "resources:tabstrip_tab_switcher_count_button_pressed", @@ -52,7 +51,6 @@ "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/favicon/resources:default_favicon", - "//ios/chrome/browser/ui/favicon/resources:default_favicon_incognito", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/image_util", "//ios/chrome/browser/ui/ntp:util",
diff --git a/ios/chrome/browser/ui/tabs/resources/BUILD.gn b/ios/chrome/browser/ui/tabs/resources/BUILD.gn index 89aadda..b088fd30 100644 --- a/ios/chrome/browser/ui/tabs/resources/BUILD.gn +++ b/ios/chrome/browser/ui/tabs/resources/BUILD.gn
@@ -17,6 +17,7 @@ sources = [ "tabstrip_background_tab.imageset/Contents.json", "tabstrip_background_tab.imageset/tabstrip_background_tab@2x~ipad.png", + "tabstrip_background_tab.imageset/tabstrip_background_tab_dark@2x~ipad.png", ] } @@ -24,6 +25,7 @@ sources = [ "tabstrip_foreground_tab.imageset/Contents.json", "tabstrip_foreground_tab.imageset/tabstrip_foreground_tab@2x~ipad.png", + "tabstrip_foreground_tab.imageset/tabstrip_foreground_tab_dark@2x~ipad.png", ] } @@ -48,20 +50,6 @@ ] } -imageset("tabstrip_new_tab_incognito") { - sources = [ - "tabstrip_new_tab_incognito.imageset/Contents.json", - "tabstrip_new_tab_incognito.imageset/tabstrip_new_tab_incognito@2x~ipad.png", - ] -} - -imageset("tabstrip_new_tab_incognito_pressed") { - sources = [ - "tabstrip_new_tab_incognito_pressed.imageset/Contents.json", - "tabstrip_new_tab_incognito_pressed.imageset/tabstrip_new_tab_incognito_pressed@2x~ipad.png", - ] -} - imageset("tabstrip_new_tab_pressed") { sources = [ "tabstrip_new_tab_pressed.imageset/Contents.json", @@ -110,3 +98,9 @@ "tabstrip_inactive_tab_close_button_color.colorset/Contents.json", ] } + +colorset("tabstrip_inactive_tab_text_color") { + sources = [ + "tabstrip_inactive_tab_text_color.colorset/Contents.json", + ] +}
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_background_tab.imageset/Contents.json b/ios/chrome/browser/ui/tabs/resources/tabstrip_background_tab.imageset/Contents.json index 8ea30cd..3154c21 100644 --- a/ios/chrome/browser/ui/tabs/resources/tabstrip_background_tab.imageset/Contents.json +++ b/ios/chrome/browser/ui/tabs/resources/tabstrip_background_tab.imageset/Contents.json
@@ -4,8 +4,19 @@ "idiom": "ipad", "scale": "2x", "filename": "tabstrip_background_tab@2x~ipad.png" - } - ], + }, + { + "idiom" : "universal", + "filename" : "tabstrip_background_tab_dark@2x~ipad.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "scale" : "2x" + } + ], "info": { "version": 1, "author": "xcode"
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_background_tab.imageset/tabstrip_background_tab_dark@2x~ipad.png b/ios/chrome/browser/ui/tabs/resources/tabstrip_background_tab.imageset/tabstrip_background_tab_dark@2x~ipad.png new file mode 100644 index 0000000..cd601ff --- /dev/null +++ b/ios/chrome/browser/ui/tabs/resources/tabstrip_background_tab.imageset/tabstrip_background_tab_dark@2x~ipad.png Binary files differ
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_foreground_tab.imageset/Contents.json b/ios/chrome/browser/ui/tabs/resources/tabstrip_foreground_tab.imageset/Contents.json index 02c1a19..f489b46 100644 --- a/ios/chrome/browser/ui/tabs/resources/tabstrip_foreground_tab.imageset/Contents.json +++ b/ios/chrome/browser/ui/tabs/resources/tabstrip_foreground_tab.imageset/Contents.json
@@ -4,7 +4,18 @@ "idiom": "ipad", "scale": "2x", "filename": "tabstrip_foreground_tab@2x~ipad.png" - } + }, + { + "idiom" : "universal", + "filename" : "tabstrip_foreground_tab_dark@2x~ipad.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "scale" : "2x" + } ], "info": { "version": 1,
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_foreground_tab.imageset/tabstrip_foreground_tab_dark@2x~ipad.png b/ios/chrome/browser/ui/tabs/resources/tabstrip_foreground_tab.imageset/tabstrip_foreground_tab_dark@2x~ipad.png new file mode 100644 index 0000000..e3bab5ee --- /dev/null +++ b/ios/chrome/browser/ui/tabs/resources/tabstrip_foreground_tab.imageset/tabstrip_foreground_tab_dark@2x~ipad.png Binary files differ
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_inactive_tab_text_color.colorset/Contents.json b/ios/chrome/browser/ui/tabs/resources/tabstrip_inactive_tab_text_color.colorset/Contents.json new file mode 100644 index 0000000..be1320b3 --- /dev/null +++ b/ios/chrome/browser/ui/tabs/resources/tabstrip_inactive_tab_text_color.colorset/Contents.json
@@ -0,0 +1,38 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "display-p3", + "components" : { + "red" : "0x5F", + "alpha" : "1.000", + "blue" : "0x67", + "green" : "0x63" + } + } + }, + { + "idiom" : "universal", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "red" : "0x9A", + "alpha" : "1.000", + "blue" : "0xA6", + "green" : "0xA0" + } + } + } + ] +} \ No newline at end of file
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito.imageset/Contents.json b/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito.imageset/Contents.json deleted file mode 100644 index 104b951..0000000 --- a/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito.imageset/Contents.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "images": [ - { - "idiom": "ipad", - "scale": "2x", - "filename": "tabstrip_new_tab_incognito@2x~ipad.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito.imageset/tabstrip_new_tab_incognito@2x~ipad.png b/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito.imageset/tabstrip_new_tab_incognito@2x~ipad.png deleted file mode 100644 index 1817e4e..0000000 --- a/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito.imageset/tabstrip_new_tab_incognito@2x~ipad.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito_pressed.imageset/Contents.json b/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito_pressed.imageset/Contents.json deleted file mode 100644 index 7788e94..0000000 --- a/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito_pressed.imageset/Contents.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "images": [ - { - "idiom": "ipad", - "scale": "2x", - "filename": "tabstrip_new_tab_incognito_pressed@2x~ipad.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito_pressed.imageset/tabstrip_new_tab_incognito_pressed@2x~ipad.png b/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito_pressed.imageset/tabstrip_new_tab_incognito_pressed@2x~ipad.png deleted file mode 100644 index 1f822d0..0000000 --- a/ios/chrome/browser/ui/tabs/resources/tabstrip_new_tab_incognito_pressed.imageset/tabstrip_new_tab_incognito_pressed@2x~ipad.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm index afd36f5..8387bc0f 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -454,21 +454,15 @@ _buttonNewTab.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin); _buttonNewTab.imageView.contentMode = UIViewContentModeCenter; - UIImage* buttonNewTabImage = nil; - UIImage* buttonNewTabPressedImage = nil; - if (_style == INCOGNITO) { - buttonNewTabImage = [UIImage imageNamed:@"tabstrip_new_tab_incognito"]; - buttonNewTabPressedImage = - [UIImage imageNamed:@"tabstrip_new_tab_incognito_pressed"]; - } else { - buttonNewTabImage = [UIImage imageNamed:@"tabstrip_new_tab"]; - buttonNewTabPressedImage = - [UIImage imageNamed:@"tabstrip_new_tab_pressed"]; - } + UIImage* buttonNewTabImage = [UIImage imageNamed:@"tabstrip_new_tab"]; [_buttonNewTab setImage:buttonNewTabImage forState:UIControlStateNormal]; + + UIImage* buttonNewTabPressedImage = + [UIImage imageNamed:@"tabstrip_new_tab_pressed"]; [_buttonNewTab setImage:buttonNewTabPressedImage forState:UIControlStateHighlighted]; + UIEdgeInsets imageInsets = UIEdgeInsetsMake( kNewTabButtonTopImageInset, kNewTabButtonHorizontalImageInset, kNewTabButtonBottomImageInset, kNewTabButtonHorizontalImageInset);
diff --git a/ios/chrome/browser/ui/tabs/tab_view.mm b/ios/chrome/browser/ui/tabs/tab_view.mm index f95d90cf..d01a3aa 100644 --- a/ios/chrome/browser/ui/tabs/tab_view.mm +++ b/ios/chrome/browser/ui/tabs/tab_view.mm
@@ -17,6 +17,7 @@ #import "ios/chrome/browser/ui/image_util/image_util.h" #include "ios/chrome/browser/ui/util/rtl_geometry.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/colors/semantic_color_names.h" #import "ios/chrome/common/highlight_button.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #include "ios/chrome/grit/ios_strings.h" @@ -54,6 +55,11 @@ const CGFloat kCloseButtonSize = 24.0; const CGFloat kFaviconSize = 16.0; +// Returns a default favicon with |UIImageRenderingModeAlwaysTemplate|. +UIImage* DefaultFaviconImage() { + return [[UIImage imageNamed:@"default_favicon"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; +} } @interface TabView ()<DropAndNavigateDelegate> { @@ -89,9 +95,6 @@ // Creates the close button, favicon button, and title. - (void)createButtonsAndLabel; -// Return the default favicon image based on the current incognito style. -- (UIImage*)defaultFaviconImage; - // Returns the rect in which to draw the favicon. - (CGRect)faviconRectForBounds:(CGRect)bounds; @@ -170,15 +173,27 @@ - (void)setFavicon:(UIImage*)favicon { if (!favicon) - favicon = [self defaultFaviconImage]; + favicon = DefaultFaviconImage(); [_faviconView setImage:favicon]; } - (void)setIncognitoStyle:(BOOL)incognitoStyle { + if (_incognitoStyle == incognitoStyle) { + return; + } _incognitoStyle = incognitoStyle; - _titleLabel.textColor = - incognitoStyle ? [UIColor whiteColor] : [UIColor blackColor]; - [_faviconView setImage:[self defaultFaviconImage]]; + +#if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0) + if (@available(iOS 13, *)) { + // When iOS 12 is dropped, only the next line is needed for styling. + // Every other check for |incognitoStyle| can be removed, as well as the + // incognito specific assets. + self.overrideUserInterfaceStyle = _incognitoStyle + ? UIUserInterfaceStyleDark + : UIUserInterfaceStyleUnspecified; + return; + } +#endif [self updateStyleForSelected:self.selected]; } @@ -230,6 +245,24 @@ return CGRectContainsPoint(CGRectInset([self bounds], inset, 0), point); } +- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + +#if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0) + if (@available(iOS 13, *)) { + // As of iOS 13 Beta 4, resizable images are flaky for dark mode. + // This triggers the styling again, where the image is resolved instead of + // relying in the system's magic. Radar filled: + // b/137942721.hasDifferentColorAppearanceComparedToTraitCollection + if ([self.traitCollection + hasDifferentColorAppearanceComparedToTraitCollection: + previousTraitCollection]) { + [self updateStyleForSelected:self.selected]; + } + } +#endif +} + #pragma mark - Private - (void)createCommonViews { @@ -290,7 +323,7 @@ _faviconView = [[UIImageView alloc] initWithFrame:faviconFrame]; [_faviconView setTranslatesAutoresizingMaskIntoConstraints:NO]; [_faviconView setContentMode:UIViewContentModeScaleAspectFit]; - [_faviconView setImage:[self defaultFaviconImage]]; + [_faviconView setImage:DefaultFaviconImage()]; [_faviconView setAccessibilityIdentifier:@"Favicon"]; [self addSubview:_faviconView]; @@ -341,29 +374,44 @@ // Updates this tab's style based on the value of |selected| and the current // incognito style. - (void)updateStyleForSelected:(BOOL)selected { + // Style the background image first. NSString* state = (selected ? @"foreground" : @"background"); - NSString* incognito = _incognitoStyle ? @"incognito_" : @""; + NSString* incognito = self.incognitoStyle ? @"incognito_" : @""; NSString* imageName = [NSString stringWithFormat:@"tabstrip_%@%@_tab", incognito, state]; CGFloat leftInset = kTabBackgroundLeftCapInset; + // As of iOS 13 Beta 4, resizable images are flaky for dark mode. + // Radar filled: b/137942721. + UIImage* resolvedImage = [UIImage imageNamed:imageName + inBundle:nil + compatibleWithTraitCollection:self.traitCollection]; UIImage* backgroundImage = - StretchableImageFromUIImage([UIImage imageNamed:imageName], leftInset, 0); - [_backgroundImageView setImage:backgroundImage]; + StretchableImageFromUIImage(resolvedImage, leftInset, 0); + _backgroundImageView.image = backgroundImage; - NSString* colorName; + // Style the close button tint color. + NSString* closeButtonColorName; if (selected) { - colorName = _incognitoStyle - ? @"tabstrip_active_tab_incognito_close_button_color" - : @"tabstrip_active_tab_close_button_color"; + closeButtonColorName = + self.incognitoStyle + ? @"tabstrip_active_tab_incognito_close_button_color" + : @"tabstrip_active_tab_close_button_color"; } else { - colorName = @"tabstrip_inactive_tab_close_button_color"; + closeButtonColorName = @"tabstrip_inactive_tab_close_button_color"; } - _closeButton.tintColor = [UIColor colorNamed:colorName]; -} + _closeButton.tintColor = [UIColor colorNamed:closeButtonColorName]; -- (UIImage*)defaultFaviconImage { - return self.incognitoStyle ? [UIImage imageNamed:@"default_favicon_incognito"] - : [UIImage imageNamed:@"default_favicon"]; + // Style the favicon tint color and the title label. + NSString* faviconColorName; + if (selected) { + faviconColorName = kTextPrimaryColor; + } else { + faviconColorName = @"tabstrip_inactive_tab_text_color"; + } + _faviconView.tintColor = self.incognitoStyle && selected + ? [UIColor whiteColor] + : [UIColor colorNamed:faviconColorName]; + self.titleLabel.textColor = _faviconView.tintColor; } #pragma mark - DropAndNavigateDelegate
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm index d5647b8e..fe918cb 100644 --- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm +++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
@@ -211,7 +211,7 @@ : [UIColor whiteColor]; [cancelButton setTitle:l10n_util::GetNSString(IDS_CANCEL) forState:UIControlStateNormal]; - [cancelButton setContentHuggingPriority:UILayoutPriorityDefaultHigh + [cancelButton setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; [cancelButton setContentCompressionResistancePriority:UILayoutPriorityRequired
diff --git a/ios/chrome/browser/upgrade/BUILD.gn b/ios/chrome/browser/upgrade/BUILD.gn index d805333..905c5d7 100644 --- a/ios/chrome/browser/upgrade/BUILD.gn +++ b/ios/chrome/browser/upgrade/BUILD.gn
@@ -16,7 +16,7 @@ "//components/version_info", "//ios/chrome/app/strings", "//ios/chrome/browser/ui/commands", - "//ios/web", + "//ios/web/common", "//net", "//ui/base", "//ui/gfx",
diff --git a/ios/chrome/browser/upgrade/upgrade_center.mm b/ios/chrome/browser/upgrade/upgrade_center.mm index 90b0096..3a42859 100644 --- a/ios/chrome/browser/upgrade/upgrade_center.mm +++ b/ios/chrome/browser/upgrade/upgrade_center.mm
@@ -20,7 +20,7 @@ #import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" -#import "ios/web/public/url_scheme_util.h" +#import "ios/web/common/url_scheme_util.h" #import "net/base/mac/url_conversions.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/image/image.h"
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index c09fbb3e..483459e2 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -70,7 +70,6 @@ "browser_url_rewriter_impl.mm", "crw_navigation_item_storage.mm", "network_context_owner.cc", - "url_scheme_util.mm", "web_client.mm", ] @@ -283,7 +282,6 @@ "network_context_owner_unittest.cc", "service_manager_connection_impl_unittest.cc", "test/web_test_unittest.mm", - "url_scheme_util_unittest.mm", "web_client_unittest.mm", "web_thread_unittest.cc", ]
diff --git a/ios/web/common/BUILD.gn b/ios/web/common/BUILD.gn index 9103251..9e56cb40 100644 --- a/ios/web/common/BUILD.gn +++ b/ios/web/common/BUILD.gn
@@ -15,6 +15,8 @@ "origin_util.mm", "referrer_util.cc", "referrer_util.h", + "url_scheme_util.h", + "url_scheme_util.mm", "url_util.cc", "url_util.h", ] @@ -64,6 +66,7 @@ sources = [ "origin_util_unittest.mm", "referrer_util_unittest.cc", + "url_scheme_util_unittest.mm", "url_util_unittest.cc", ] }
diff --git a/ios/web/public/url_scheme_util.h b/ios/web/common/url_scheme_util.h similarity index 84% rename from ios/web/public/url_scheme_util.h rename to ios/web/common/url_scheme_util.h index 7300b2f..a64b785 100644 --- a/ios/web/public/url_scheme_util.h +++ b/ios/web/common/url_scheme_util.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_WEB_PUBLIC_URL_SCHEME_UTIL_H_ -#define IOS_WEB_PUBLIC_URL_SCHEME_UTIL_H_ +#ifndef IOS_WEB_COMMON_URL_SCHEME_UTIL_H_ +#define IOS_WEB_COMMON_URL_SCHEME_UTIL_H_ class GURL; @class NSURL; @@ -22,4 +22,4 @@ } // namespace web -#endif // IOS_WEB_PUBLIC_URL_SCHEME_UTIL_H_ +#endif // IOS_WEB_COMMON_URL_SCHEME_UTIL_H_
diff --git a/ios/web/url_scheme_util.mm b/ios/web/common/url_scheme_util.mm similarity index 86% rename from ios/web/url_scheme_util.mm rename to ios/web/common/url_scheme_util.mm index 6c60e52..ce2fde28 100644 --- a/ios/web/url_scheme_util.mm +++ b/ios/web/common/url_scheme_util.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/web/public/url_scheme_util.h" +#import "ios/web/common/url_scheme_util.h" #import <Foundation/Foundation.h> @@ -16,8 +16,7 @@ namespace web { bool UrlHasWebScheme(const GURL& url) { - return url.SchemeIs(url::kHttpScheme) || - url.SchemeIs(url::kHttpsScheme) || + return url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme) || url.SchemeIs(url::kDataScheme); }
diff --git a/ios/web/url_scheme_util_unittest.mm b/ios/web/common/url_scheme_util_unittest.mm similarity index 96% rename from ios/web/url_scheme_util_unittest.mm rename to ios/web/common/url_scheme_util_unittest.mm index c1f171b..569e006 100644 --- a/ios/web/url_scheme_util_unittest.mm +++ b/ios/web/common/url_scheme_util_unittest.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/web/public/url_scheme_util.h" +#import "ios/web/common/url_scheme_util.h" #import <Foundation/Foundation.h>
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm index 2589f00..dc3f3cb 100644 --- a/ios/web/navigation/crw_wk_navigation_handler.mm +++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -10,6 +10,7 @@ #include "base/timer/timer.h" #import "ios/net/http_response_headers_util.h" #include "ios/web/common/features.h" +#import "ios/web/common/url_scheme_util.h" #import "ios/web/js_messaging/crw_js_injector.h" #import "ios/web/js_messaging/web_frames_manager_impl.h" #import "ios/web/navigation/crw_pending_navigation_info.h" @@ -26,7 +27,6 @@ #import "ios/web/navigation/wk_navigation_util.h" #include "ios/web/public/browser_state.h" #import "ios/web/public/download/download_controller.h" -#import "ios/web/public/url_scheme_util.h" #import "ios/web/public/web_client.h" #import "ios/web/security/crw_cert_verification_controller.h" #import "ios/web/security/wk_web_view_security_util.h"
diff --git a/ios/web/public/BUILD.gn b/ios/web/public/BUILD.gn index d5f228e8..1ebc6ea 100644 --- a/ios/web/public/BUILD.gn +++ b/ios/web/public/BUILD.gn
@@ -30,7 +30,6 @@ "java_script_dialog_presenter.h", "java_script_dialog_type.h", "service_manager_connection.h", - "url_scheme_util.h", "url_schemes.mm", "web_client.h", "web_state/page_display_state.mm",
diff --git a/ios/web_view/internal/passwords/cwv_password_controller.mm b/ios/web_view/internal/passwords/cwv_password_controller.mm index 29e06e2..6a3ad2b 100644 --- a/ios/web_view/internal/passwords/cwv_password_controller.mm +++ b/ios/web_view/internal/passwords/cwv_password_controller.mm
@@ -16,8 +16,9 @@ #import "components/password_manager/ios/password_form_helper.h" #import "components/password_manager/ios/password_suggestion_helper.h" #import "ios/web/common/origin_util.h" +#include "ios/web/common/url_scheme_util.h" #include "ios/web/public/js_messaging/web_frame.h" -#include "ios/web/public/url_scheme_util.h" +#include "ios/web/public/js_messaging/web_frame_util.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" #import "ios/web_view/internal/autofill/cwv_autofill_suggestion_internal.h" #import "ios/web_view/internal/passwords/web_view_password_manager_client.h"
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index 9ca3c31f..ca67530 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -14,6 +14,7 @@ #include "cc/paint/paint_flags.h" #include "cc/paint/paint_image_builder.h" #include "components/viz/common/gpu/context_provider.h" +#include "components/viz/common/resources/resource_format.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -90,7 +91,7 @@ gfx::ColorSpace video_color_space, VideoPixelFormat video_format, GrBackendTexture* yuv_textures, - GrBackendTexture* result_texture = nullptr) { + const GrBackendTexture& result_texture) { // TODO(hubbe): This should really default to rec709. // https://crbug.com/828599 SkYUVColorSpace color_space = kRec601_SkYUVColorSpace; @@ -98,34 +99,62 @@ switch (video_format) { case PIXEL_FORMAT_NV12: - if (result_texture) { - return SkImage::MakeFromNV12TexturesCopyWithExternalBackend( - gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin, - result_texture[0]); - } else { - return SkImage::MakeFromNV12TexturesCopy( - gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin); - } + return SkImage::MakeFromNV12TexturesCopyWithExternalBackend( + gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin, + result_texture); case PIXEL_FORMAT_I420: - if (result_texture) { - return SkImage::MakeFromYUVTexturesCopyWithExternalBackend( - gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin, - result_texture[0]); - } else { - return SkImage::MakeFromYUVTexturesCopy( - gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin); - } + return SkImage::MakeFromYUVTexturesCopyWithExternalBackend( + gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin, + result_texture); default: NOTREACHED(); return nullptr; } } +// Helper class that begins/ends access to a mailbox within a scope. The mailbox +// must have been imported into |texture|. +class ScopedSharedImageAccess { + public: + ScopedSharedImageAccess( + gpu::gles2::GLES2Interface* gl, + GLuint texture, + const gpu::Mailbox& mailbox, + GLenum access = GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM) + : gl(gl), texture(texture), is_shared_image(mailbox.IsSharedImage()) { + if (is_shared_image) + gl->BeginSharedImageAccessDirectCHROMIUM(texture, access); + } + + ~ScopedSharedImageAccess() { + if (is_shared_image) + gl->EndSharedImageAccessDirectCHROMIUM(texture); + } + + private: + gpu::gles2::GLES2Interface* gl; + GLuint texture; + bool is_shared_image; +}; + +// Waits for a sync token and import the mailbox as texture. +GLuint SynchronizeAndImportMailbox(gpu::gles2::GLES2Interface* gl, + const gpu::SyncToken& sync_token, + const gpu::Mailbox& mailbox) { + gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); + if (mailbox.IsSharedImage()) { + return gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name); + } else { + return gl->CreateAndConsumeTextureCHROMIUM(mailbox.name); + } +} + static constexpr size_t kNumYUVPlanes = 3; struct YUVPlaneTextureInfo { GrGLTextureInfo texture = {0, 0}; GLint minFilter = 0; GLint magFilter = 0; + bool is_shared_image = false; }; using YUVTexturesInfo = std::array<YUVPlaneTextureInfo, kNumYUVPlanes>; @@ -147,9 +176,15 @@ mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB) << "Unsupported texture target " << std::hex << std::showbase << mailbox_holder.texture_target; - gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); - yuv_textures_info[i].texture.fID = - gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name); + yuv_textures_info[i].texture.fID = SynchronizeAndImportMailbox( + gl, mailbox_holder.sync_token, mailbox_holder.mailbox); + if (mailbox_holder.mailbox.IsSharedImage()) { + yuv_textures_info[i].is_shared_image = true; + gl->BeginSharedImageAccessDirectCHROMIUM( + yuv_textures_info[i].texture.fID, + GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM); + } + yuv_textures_info[i].texture.fTarget = mailbox_holder.texture_target; yuv_textures_info[i].texture.fFormat = skia_texture_format; @@ -177,47 +212,12 @@ GL_TEXTURE_MIN_FILTER, yuv_textures_info[i].minFilter); gl->TexParameteri(yuv_textures_info[i].texture.fTarget, GL_TEXTURE_MAG_FILTER, yuv_textures_info[i].magFilter); + if (yuv_textures_info[i].is_shared_image) + gl->EndSharedImageAccessDirectCHROMIUM(yuv_textures_info[i].texture.fID); gl->DeleteTextures(1, &yuv_textures_info[i].texture.fID); } } -sk_sp<SkImage> NewSkImageFromVideoFrameYUVTextures( - const VideoFrame* video_frame, - viz::ContextProvider* context_provider) { - DCHECK(video_frame->HasTextures()); - GrContext* gr_context = context_provider->GrContext(); - DCHECK(gr_context); - // TODO: We should compare the DCHECK vs when UpdateLastImage calls this - // function. (crbug.com/674185) - DCHECK(video_frame->format() == PIXEL_FORMAT_I420 || - video_frame->format() == PIXEL_FORMAT_NV12); - - gfx::Size ya_tex_size = video_frame->coded_size(); - gfx::Size uv_tex_size((ya_tex_size.width() + 1) / 2, - (ya_tex_size.height() + 1) / 2); - - YUVTexturesInfo yuv_textures_info = - GetYUVTexturesInfo(video_frame, context_provider); - - GrBackendTexture yuv_textures[3] = { - GrBackendTexture(ya_tex_size.width(), ya_tex_size.height(), - GrMipMapped::kNo, yuv_textures_info[0].texture), - GrBackendTexture(uv_tex_size.width(), uv_tex_size.height(), - GrMipMapped::kNo, yuv_textures_info[1].texture), - GrBackendTexture(uv_tex_size.width(), uv_tex_size.height(), - GrMipMapped::kNo, yuv_textures_info[2].texture), - }; - - sk_sp<SkImage> img = - YUVGrBackendTexturesToSkImage(gr_context, video_frame->ColorSpace(), - video_frame->format(), yuv_textures); - gr_context->flush(); - - DeleteYUVTextures(video_frame, context_provider, yuv_textures_info); - - return img; -} - sk_sp<SkImage> NewSkImageFromVideoFrameYUVTexturesWithExternalBackend( const VideoFrame* video_frame, viz::ContextProvider* context_provider, @@ -251,11 +251,9 @@ backend_texture.fID = texture_id; backend_texture.fTarget = texture_target; backend_texture.fFormat = GL_RGBA8; - GrBackendTexture result_texture[1] = { - GrBackendTexture(video_frame->coded_size().width(), - video_frame->coded_size().height(), GrMipMapped::kNo, - backend_texture), - }; + GrBackendTexture result_texture(video_frame->coded_size().width(), + video_frame->coded_size().height(), + GrMipMapped::kNo, backend_texture); sk_sp<SkImage> img = YUVGrBackendTexturesToSkImage( gr_context, video_frame->ColorSpace(), video_frame->format(), @@ -267,12 +265,15 @@ return img; } -// Creates a SkImage from a |video_frame| backed by native resources. -// The SkImage will take ownership of the underlying resource. -sk_sp<SkImage> NewSkImageFromVideoFrameNative( - VideoFrame* video_frame, - viz::ContextProvider* context_provider, - bool wrap_texture) { +// Imports a VideoFrame that contains a single mailbox into a newly created GL +// texture, after synchronization with the sync token. Returns the GL texture. +// |mailbox| is set to the imported mailbox. +GLuint ImportVideoFrameSingleMailbox(gpu::gles2::GLES2Interface* gl, + VideoFrame* video_frame, + gpu::Mailbox* mailbox) { + DCHECK(video_frame->HasTextures()); + DCHECK_EQ(video_frame->NumTextures(), 1u); + DCHECK(PIXEL_FORMAT_ARGB == video_frame->format() || PIXEL_FORMAT_XRGB == video_frame->format() || PIXEL_FORMAT_RGB24 == video_frame->format() || @@ -285,43 +286,31 @@ DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB || mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES) - << "Unsupported texture target " << std::hex << std::showbase << mailbox_holder.texture_target; - gpu::gles2::GLES2Interface* gl = context_provider->ContextGL(); - gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); - GLuint frame_texture = - gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name); - unsigned source_texture = 0; - gfx::ColorSpace color_space_for_skia; - if (wrap_texture) { - // Fast path where we can avoid a copy, by having last_image_ directly wrap - // the VideoFrame texture. - source_texture = frame_texture; - color_space_for_skia = video_frame->ColorSpace(); - } else { - gl->GenTextures(1, &source_texture); - DCHECK(source_texture); - gl->BindTexture(GL_TEXTURE_2D, source_texture); - gl->CopyTextureCHROMIUM(frame_texture, 0, GL_TEXTURE_2D, source_texture, 0, - GL_RGBA, GL_UNSIGNED_BYTE, false, false, false); - gl->DeleteTextures(1, &frame_texture); - } - GrGLTextureInfo source_texture_info; - source_texture_info.fID = source_texture; - source_texture_info.fTarget = GL_TEXTURE_2D; - // TODO(bsalomon): GrGLTextureInfo::fFormat and SkColorType passed to SkImage - // factory should reflect video_frame->format(). Update once Skia supports - // GL_RGB. - // skbug.com/7533 - source_texture_info.fFormat = GL_RGBA8_OES; - GrBackendTexture source_backend_texture( - video_frame->coded_size().width(), video_frame->coded_size().height(), - GrMipMapped::kNo, source_texture_info); - return SkImage::MakeFromAdoptedTexture( - context_provider->GrContext(), source_backend_texture, - kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, - color_space_for_skia.ToSkColorSpace()); + *mailbox = mailbox_holder.mailbox; + return SynchronizeAndImportMailbox(gl, mailbox_holder.sync_token, *mailbox); +} + +// Wraps a GL RGBA texture into a SkImage. +sk_sp<SkImage> WrapGLTexture(GLenum target, + GLuint texture_id, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + viz::ContextProvider* context_provider) { + GrGLTextureInfo texture_info; + texture_info.fID = texture_id; + texture_info.fTarget = target; + // TODO(bsalomon): GrGLTextureInfo::fFormat and SkColorType passed to + // SkImage factory should reflect video_frame->format(). Update once + // Skia supports GL_RGB. skbug.com/7533 + texture_info.fFormat = GL_RGBA8_OES; + GrBackendTexture backend_texture(size.width(), size.height(), + GrMipMapped::kNo, texture_info); + return SkImage::MakeFromTexture( + context_provider->GrContext(), backend_texture, kTopLeft_GrSurfaceOrigin, + kRGBA_8888_SkColorType, kPremul_SkAlphaType, color_space.ToSkColorSpace(), + nullptr, nullptr); } void VideoFrameCopyTextureOrSubTexture(gpu::gles2::GLES2Interface* gl, @@ -593,6 +582,14 @@ cc::PaintImage image = cache_->paint_image; DCHECK(image); + base::Optional<ScopedSharedImageAccess> source_access; + if (video_frame->HasTextures()) { + DCHECK(!cache_->source_mailbox.IsZero()); + DCHECK(cache_->source_texture); + source_access.emplace(context_provider->ContextGL(), cache_->source_texture, + cache_->source_mailbox); + } + cc::PaintFlags video_flags; video_flags.setAlpha(flags.getAlpha()); video_flags.setBlendMode(flags.getBlendMode()); @@ -659,6 +656,7 @@ canvas->flush(); if (video_frame->HasTextures()) { + source_access.reset(); // Synchronize |video_frame| with the read operations in UpdateLastImage(), // which are triggered by canvas->flush(). SynchronizeVideoFrameRead(std::move(video_frame), @@ -1056,19 +1054,16 @@ DCHECK(video_frame); DCHECK(video_frame->HasTextures()); - const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0); - DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || - mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB || - mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES) - << mailbox_holder.texture_target; - - gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); + gpu::Mailbox mailbox; uint32_t source_texture = - gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name); - VideoFrameCopyTextureOrSubTexture(gl, video_frame->coded_size(), - video_frame->visible_rect(), source_texture, - target, texture, internal_format, format, - type, level, premultiply_alpha, flip_y); + ImportVideoFrameSingleMailbox(gl, video_frame, &mailbox); + { + ScopedSharedImageAccess access(gl, source_texture, mailbox); + VideoFrameCopyTextureOrSubTexture( + gl, video_frame->coded_size(), video_frame->visible_rect(), + source_texture, target, texture, internal_format, format, type, level, + premultiply_alpha, flip_y); + } gl->DeleteTextures(1, &source_texture); gl->ShallowFlushCHROMIUM(); // The caller must call SynchronizeVideoFrameRead() after this operation, but @@ -1104,36 +1099,24 @@ } DCHECK(cache_); - DCHECK(cache_->source_image); - GrBackendTexture backend_texture = - cache_->source_image->getBackendTexture(true); - if (!backend_texture.isValid()) - return false; - GrGLTextureInfo texture_info; - if (!backend_texture.getGLTextureInfo(&texture_info)) - return false; - + DCHECK(!cache_->source_mailbox.IsZero()); gpu::gles2::GLES2Interface* canvas_gl = context_provider->ContextGL(); - gpu::MailboxHolder mailbox_holder; - mailbox_holder.texture_target = texture_info.fTarget; - canvas_gl->ProduceTextureDirectCHROMIUM(texture_info.fID, - mailbox_holder.mailbox.name); + gpu::SyncToken sync_token; // Wait for mailbox creation on canvas context before consuming it and // copying from it on the consumer context. - canvas_gl->GenUnverifiedSyncTokenCHROMIUM( - mailbox_holder.sync_token.GetData()); + canvas_gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); - destination_gl->WaitSyncTokenCHROMIUM( - mailbox_holder.sync_token.GetConstData()); - uint32_t intermediate_texture = - destination_gl->CreateAndConsumeTextureCHROMIUM( - mailbox_holder.mailbox.name); - - VideoFrameCopyTextureOrSubTexture( - destination_gl, cache_->coded_size, cache_->visible_rect, - intermediate_texture, target, texture, internal_format, format, type, - level, premultiply_alpha, flip_y); + uint32_t intermediate_texture = SynchronizeAndImportMailbox( + destination_gl, sync_token, cache_->source_mailbox); + { + ScopedSharedImageAccess access(destination_gl, intermediate_texture, + cache_->source_mailbox); + VideoFrameCopyTextureOrSubTexture( + destination_gl, cache_->coded_size, cache_->visible_rect, + intermediate_texture, target, texture, internal_format, format, type, + level, premultiply_alpha, flip_y); + } destination_gl->DeleteTextures(1, &intermediate_texture); @@ -1322,10 +1305,8 @@ yuv_cache_.mailbox = sii->CreateSharedImage( viz::ResourceFormat::RGBA_8888, video_frame.coded_size(), gfx::ColorSpace(), gpu::SHARED_IMAGE_USAGE_GLES2); - auto creation_sync_token = sii->GenUnverifiedSyncToken(); - source_gl->WaitSyncTokenCHROMIUM(creation_sync_token.GetConstData()); - yuv_cache_.texture = source_gl->CreateAndTexStorage2DSharedImageCHROMIUM( - yuv_cache_.mailbox.name); + yuv_cache_.texture = SynchronizeAndImportMailbox( + source_gl, sii->GenUnverifiedSyncToken(), yuv_cache_.mailbox); } // On the source GL context, do the YUV->RGB conversion using Skia. @@ -1344,7 +1325,7 @@ sk_sp<SkImage> yuv_image = YUVGrBackendTexturesToSkImage( gr_context, video_frame.ColorSpace(), video_frame.format(), - yuv_textures, &result_texture); + yuv_textures, result_texture); gr_context->flush(); source_gl->EndSharedImageAccessDirectCHROMIUM(yuv_cache_.texture); @@ -1362,25 +1343,19 @@ // On the destination GL context, do a copy (with cropping) into the // destination texture. + GLuint intermediate_texture = SynchronizeAndImportMailbox( + destination_gl, post_conversion_sync_token, yuv_cache_.mailbox); { - destination_gl->WaitSyncTokenCHROMIUM( - post_conversion_sync_token.GetConstData()); - GLuint intermediate_texture = - destination_gl->CreateAndTexStorage2DSharedImageCHROMIUM( - yuv_cache_.mailbox.name); - destination_gl->BeginSharedImageAccessDirectCHROMIUM( - intermediate_texture, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM); - + ScopedSharedImageAccess access(destination_gl, intermediate_texture, + yuv_cache_.mailbox); VideoFrameCopyTextureOrSubTexture( destination_gl, video_frame.coded_size(), video_frame.visible_rect(), intermediate_texture, target, texture, internal_format, format, type, level, premultiply_alpha, flip_y); - - destination_gl->EndSharedImageAccessDirectCHROMIUM(intermediate_texture); - destination_gl->DeleteTextures(1, &intermediate_texture); - destination_gl->GenUnverifiedSyncTokenCHROMIUM( - yuv_cache_.sync_token.GetData()); } + destination_gl->DeleteTextures(1, &intermediate_texture); + destination_gl->GenUnverifiedSyncTokenCHROMIUM( + yuv_cache_.sync_token.GetData()); // video_frame->UpdateReleaseSyncToken is not necessary since the video frame // data we used was CPU-side (IsMappable) to begin with. If there were any @@ -1473,7 +1448,21 @@ PaintCanvasVideoRenderer::Cache::Cache(int frame_id) : frame_id(frame_id) {} -PaintCanvasVideoRenderer::Cache::~Cache() = default; +PaintCanvasVideoRenderer::Cache::~Cache() { + if (!context_provider) + return; + + DCHECK(!source_mailbox.IsZero()); + DCHECK(source_texture); + auto* gl = context_provider->ContextGL(); + gl->DeleteTextures(1, &source_texture); + if (!wraps_video_frame_texture) { + gpu::SyncToken sync_token; + gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); + auto* sii = context_provider->SharedImageInterface(); + sii->DestroySharedImage(sync_token, source_mailbox); + } +} bool PaintCanvasVideoRenderer::UpdateLastImage( scoped_refptr<VideoFrame> video_frame, @@ -1481,14 +1470,13 @@ bool allow_wrap_texture) { DCHECK(!cache_ || !cache_->wraps_video_frame_texture); if (!cache_ || video_frame->unique_id() != cache_->frame_id || - !cache_->source_image) { - cache_.emplace(video_frame->unique_id()); - + cache_->source_mailbox.IsZero()) { auto paint_image_builder = cc::PaintImageBuilder::WithDefault() .set_id(renderer_stable_id_) .set_animation_type(cc::PaintImage::AnimationType::VIDEO) .set_completion_state(cc::PaintImage::CompletionState::DONE); + // Generate a new image. // Note: Skia will hold onto |video_frame| via |video_generator| only when // |video_frame| is software. @@ -1497,27 +1485,73 @@ if (video_frame->HasTextures()) { DCHECK(context_provider); DCHECK(context_provider->GrContext()); - DCHECK(context_provider->ContextGL()); - if (video_frame->NumTextures() > 1) { - cache_->source_image = NewSkImageFromVideoFrameYUVTextures( - video_frame.get(), context_provider); + auto* gl = context_provider->ContextGL(); + DCHECK(gl); + + sk_sp<SkImage> source_image; + + if (allow_wrap_texture && video_frame->NumTextures() == 1) { + cache_.emplace(video_frame->unique_id()); + cache_->source_texture = ImportVideoFrameSingleMailbox( + gl, video_frame.get(), &cache_->source_mailbox); + cache_->wraps_video_frame_texture = true; + source_image = + WrapGLTexture(video_frame->mailbox_holder(0).texture_target, + cache_->source_texture, video_frame->coded_size(), + video_frame->ColorSpace(), context_provider); } else { - cache_->source_image = NewSkImageFromVideoFrameNative( - video_frame.get(), context_provider, allow_wrap_texture); - cache_->wraps_video_frame_texture = allow_wrap_texture; + if (cache_ && cache_->context_provider == context_provider && + cache_->coded_size == video_frame->coded_size()) { + // We can reuse the shared image from the previous cache. + cache_->frame_id = video_frame->unique_id(); + } else { + cache_.emplace(video_frame->unique_id()); + auto* sii = context_provider->SharedImageInterface(); + cache_->source_mailbox = sii->CreateSharedImage( + viz::ResourceFormat::RGBA_8888, video_frame->coded_size(), + gfx::ColorSpace(), gpu::SHARED_IMAGE_USAGE_GLES2); + cache_->source_texture = SynchronizeAndImportMailbox( + gl, sii->GenUnverifiedSyncToken(), cache_->source_mailbox); + } + ScopedSharedImageAccess dest_access( + gl, cache_->source_texture, cache_->source_mailbox, + GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM); + if (video_frame->NumTextures() == 1) { + gpu::Mailbox mailbox; + GLuint frame_texture = + ImportVideoFrameSingleMailbox(gl, video_frame.get(), &mailbox); + { + ScopedSharedImageAccess access(gl, frame_texture, mailbox); + gl->CopySubTextureCHROMIUM(frame_texture, 0, GL_TEXTURE_2D, + cache_->source_texture, 0, 0, 0, 0, 0, + video_frame->coded_size().width(), + video_frame->coded_size().height(), + GL_FALSE, GL_FALSE, GL_FALSE); + } + gl->DeleteTextures(1, &frame_texture); + source_image = WrapGLTexture(GL_TEXTURE_2D, cache_->source_texture, + video_frame->coded_size(), + gfx::ColorSpace(), context_provider); + } else { + source_image = NewSkImageFromVideoFrameYUVTexturesWithExternalBackend( + video_frame.get(), context_provider, GL_TEXTURE_2D, + cache_->source_texture); + } + context_provider->GrContext()->flush(); } - if (!cache_->source_image) { + if (!source_image) { // Couldn't create the SkImage. cache_.reset(); return false; } + cache_->context_provider = context_provider; cache_->coded_size = video_frame->coded_size(); cache_->visible_rect = video_frame->visible_rect(); paint_image_builder.set_image( - cache_->source_image->makeSubset( - gfx::RectToSkIRect(cache_->visible_rect)), + source_image->makeSubset(gfx::RectToSkIRect(cache_->visible_rect)), cc::PaintImage::GetNextContentId()); } else { + cache_.emplace(video_frame->unique_id()); paint_image_builder.set_paint_image_generator( sk_make_sp<VideoImageGenerator>(video_frame)); } @@ -1555,11 +1589,11 @@ DCHECK(context_provider); DCHECK(context_provider->GrContext()); DCHECK(context_provider->ContextGL()); + sk_sp<SkImage> source_image; if (video_frame->NumTextures() > 1) { - cache_->source_image = - NewSkImageFromVideoFrameYUVTexturesWithExternalBackend( - video_frame.get(), context_provider, textureTarget, texture); - if (!cache_->source_image) { + source_image = NewSkImageFromVideoFrameYUVTexturesWithExternalBackend( + video_frame.get(), context_provider, textureTarget, texture); + if (!source_image) { // Couldn't create the SkImage. cache_.reset(); return false; @@ -1571,9 +1605,9 @@ } cache_->coded_size = video_frame->coded_size(); cache_->visible_rect = video_frame->visible_rect(); - paint_image_builder.set_image(cache_->source_image->makeSubset( - gfx::RectToSkIRect(cache_->visible_rect)), - cc::PaintImage::GetNextContentId()); + paint_image_builder.set_image( + source_image->makeSubset(gfx::RectToSkIRect(cache_->visible_rect)), + cc::PaintImage::GetNextContentId()); } else { paint_image_builder.set_paint_image_generator( sk_make_sp<VideoImageGenerator>(video_frame));
diff --git a/media/renderers/paint_canvas_video_renderer.h b/media/renderers/paint_canvas_video_renderer.h index 4664b93f..2628f28 100644 --- a/media/renderers/paint_canvas_video_renderer.h +++ b/media/renderers/paint_canvas_video_renderer.h
@@ -17,6 +17,7 @@ #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" #include "cc/paint/paint_image.h" +#include "gpu/command_buffer/common/mailbox.h" #include "media/base/media_export.h" #include "media/base/timestamp_constants.h" #include "media/base/video_frame.h" @@ -198,14 +199,22 @@ // to the visible size of the VideoFrame. Its contents are generated lazily. cc::PaintImage paint_image; - // A SkImage that contain the source texture for |paint_image|. This can be - // either the source VideoFrame's texture (if wraps_video_frame_texture is - // true) or a newly allocated texture (if wraps_video_frame_texture is - // false) if a copy or conversion was necessary. - // This is only set if the VideoFrame was texture-backed. - sk_sp<SkImage> source_image; + // The context provider used to generate |source_mailbox| and + // |source_texture|. This is only set if the VideoFrame was texture-backed. + scoped_refptr<viz::ContextProvider> context_provider; - // The allocated size of |source_image|. + // The mailbox for the source texture. This can be either the source + // VideoFrame's texture (if |wraps_video_frame_texture| is true) or a newly + // allocated shared image (if |wraps_video_frame_texture| is false) if a + // copy or conversion was necessary. + // This is only set if the VideoFrame was texture-backed. + gpu::Mailbox source_mailbox; + + // The texture ID created when importing |source_mailbox|. + // This is only set if the VideoFrame was texture-backed. + uint32_t source_texture = 0; + + // The allocated size of |source_mailbox|. // This is only set if the VideoFrame was texture-backed. gfx::Size coded_size; @@ -214,8 +223,8 @@ // This is only set if the VideoFrame was texture-backed. gfx::Rect visible_rect; - // Whether |source_image| directly points to a texture of the VideoFrame - // (if true), or to an allocated texture (if false). + // Whether |source_mailbox| directly points to a texture of the VideoFrame + // (if true), or to an allocated shared image (if false). bool wraps_video_frame_texture = false; };
diff --git a/net/BUILD.gn b/net/BUILD.gn index 0a9727a..be5b930f 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -80,7 +80,7 @@ "ENABLE_WEBSOCKETS=$enable_websockets", "INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=$include_transport_security_state_preload_list", "USE_KERBEROS=$use_kerberos", - "DLOPEN_KERBEROS=$use_external_gssapi", + "USE_EXTERNAL_GSSAPI=$use_external_gssapi", "TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=$trial_comparison_cert_verifier_supported", "BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED=$builtin_cert_verifier_feature_supported", ]
diff --git a/net/android/dummy_spnego_authenticator.h b/net/android/dummy_spnego_authenticator.h index 5525c62..ae51b02 100644 --- a/net/android/dummy_spnego_authenticator.h +++ b/net/android/dummy_spnego_authenticator.h
@@ -137,6 +137,9 @@ }; } // namespace android + +using MockAuthLibrary = android::DummySpnegoAuthenticator; + } // namespace net #endif // NET_ANDROID_DUMMY_SPNEGO_AUTHENTICATOR_H_
diff --git a/net/android/http_auth_negotiate_android.cc b/net/android/http_auth_negotiate_android.cc index f8263c8..4beca16 100644 --- a/net/android/http_auth_negotiate_android.cc +++ b/net/android/http_auth_negotiate_android.cc
@@ -16,6 +16,7 @@ #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/http_auth_multi_round_parse.h" #include "net/http/http_auth_preferences.h" +#include "net/log/net_log_with_source.h" #include "net/net_jni_headers/HttpNegotiateAuthenticator_jni.h" using base::android::AttachCurrentThread; @@ -69,7 +70,7 @@ HttpAuthNegotiateAndroid::~HttpAuthNegotiateAndroid() { } -bool HttpAuthNegotiateAndroid::Init() { +bool HttpAuthNegotiateAndroid::Init(const NetLogWithSource& net_log) { return true; } @@ -92,11 +93,22 @@ &decoded_auth_token); } +int HttpAuthNegotiateAndroid::GenerateAuthTokenAndroid( + const AuthCredentials* credentials, + const std::string& spn, + const std::string& channel_bindings, + std::string* auth_token, + net::CompletionOnceCallback callback) { + return GenerateAuthToken(credentials, spn, channel_bindings, auth_token, + NetLogWithSource(), std::move(callback)); +} + int HttpAuthNegotiateAndroid::GenerateAuthToken( const AuthCredentials* credentials, const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const NetLogWithSource& net_log, net::CompletionOnceCallback callback) { if (GetAuthAndroidNegotiateAccountType().empty()) { // This can happen if there is a policy change, removing the account type,
diff --git a/net/android/http_auth_negotiate_android.h b/net/android/http_auth_negotiate_android.h index 2bd89fc..78e29a1 100644 --- a/net/android/http_auth_negotiate_android.h +++ b/net/android/http_auth_negotiate_android.h
@@ -74,7 +74,7 @@ ~HttpAuthNegotiateAndroid() override; // HttpNegotiateAuthSystem implementation: - bool Init() override; + bool Init(const NetLogWithSource& net_log) override; bool NeedsIdentity() const override; bool AllowsExplicitCredentials() const override; HttpAuth::AuthorizationResult ParseChallenge( @@ -83,9 +83,20 @@ const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const NetLogWithSource& net_log, CompletionOnceCallback callback) override; void SetDelegation(HttpAuth::DelegationType delegation_type) override; + // Unlike the platform agnostic GenerateAuthToken(), the Android specific + // version doesn't require a NetLogWithSource. The call is made across service + // boundaries, so currently the goings-on within the GenerateAuthToken() + // handler is outside the scope of the NetLog. + int GenerateAuthTokenAndroid(const AuthCredentials* credentials, + const std::string& spn, + const std::string& channel_bindings, + std::string* auth_token, + CompletionOnceCallback callback); + bool can_delegate() const { return can_delegate_; } void set_can_delegate(bool can_delegate) { can_delegate_ = can_delegate; }
diff --git a/net/android/http_auth_negotiate_android_unittest.cc b/net/android/http_auth_negotiate_android_unittest.cc index 154084b..e88265d0 100644 --- a/net/android/http_auth_negotiate_android_unittest.cc +++ b/net/android/http_auth_negotiate_android_unittest.cc
@@ -11,6 +11,7 @@ #include "net/base/test_completion_callback.h" #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/mock_allow_http_auth_preferences.h" +#include "net/log/net_log_with_source.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -32,12 +33,12 @@ prefs.set_auth_android_negotiate_account_type( "org.chromium.test.DummySpnegoAuthenticator"); HttpAuthNegotiateAndroid auth(&prefs); - EXPECT_TRUE(auth.Init()); + EXPECT_TRUE(auth.Init(NetLogWithSource())); TestCompletionCallback callback; - EXPECT_EQ(OK, callback.GetResult( - auth.GenerateAuthToken(nullptr, "Dummy", std::string(), - &auth_token, callback.callback()))); + EXPECT_EQ(OK, callback.GetResult(auth.GenerateAuthToken( + nullptr, "Dummy", std::string(), &auth_token, + NetLogWithSource(), callback.callback()))); EXPECT_EQ("Negotiate DummyToken", auth_token);
diff --git a/net/dns/context_host_resolver_unittest.cc b/net/dns/context_host_resolver_unittest.cc index 7f00e24..6109aee 100644 --- a/net/dns/context_host_resolver_unittest.cc +++ b/net/dns/context_host_resolver_unittest.cc
@@ -51,6 +51,7 @@ std::make_unique<MockDnsClient>(DnsConfig(), std::move(rules)); dns_client_ = dns_client.get(); manager_->SetDnsClientForTesting(std::move(dns_client)); + manager_->SetInsecureDnsClientEnabled(true); scoped_refptr<HostResolverProc> proc = CreateCatchAllHostResolverProc(); manager_->set_proc_params_for_test(ProcTaskParams(proc.get(), 1u));
diff --git a/net/dns/fuzzed_host_resolver_util.cc b/net/dns/fuzzed_host_resolver_util.cc index c384abf..b76c8809 100644 --- a/net/dns/fuzzed_host_resolver_util.cc +++ b/net/dns/fuzzed_host_resolver_util.cc
@@ -85,6 +85,62 @@ return FuzzIPv6Address(data_provider); } +DnsConfig GetFuzzedDnsConfig(FuzzedDataProvider* data_provider) { + // Fuzz DNS configuration. + DnsConfig config; + + // Fuzz name servers. + uint32_t num_nameservers = data_provider->ConsumeIntegralInRange(0, 4); + for (uint32_t i = 0; i < num_nameservers; ++i) { + config.nameservers.push_back( + IPEndPoint(FuzzIPAddress(data_provider), FuzzPort(data_provider))); + } + + // Fuzz suffix search list. + switch (data_provider->ConsumeIntegralInRange(0, 3)) { + case 3: + config.search.push_back("foo.com"); + FALLTHROUGH; + case 2: + config.search.push_back("bar"); + FALLTHROUGH; + case 1: + config.search.push_back("com"); + FALLTHROUGH; + default: + break; + } + + net::DnsHosts hosts; + // Fuzz hosts file. + uint8_t num_hosts_entries = data_provider->ConsumeIntegral<uint8_t>(); + for (uint8_t i = 0; i < num_hosts_entries; ++i) { + const char* kHostnames[] = {"foo", "foo.com", "a.foo.com", + "bar", "localhost", "localhost6"}; + const char* hostname = data_provider->PickValueInArray(kHostnames); + net::IPAddress address = FuzzIPAddress(data_provider); + config.hosts[net::DnsHostsKey(hostname, net::GetAddressFamily(address))] = + address; + } + + config.unhandled_options = data_provider->ConsumeBool(); + config.append_to_multi_label_name = data_provider->ConsumeBool(); + config.randomize_ports = data_provider->ConsumeBool(); + config.ndots = data_provider->ConsumeIntegralInRange(0, 3); + config.attempts = data_provider->ConsumeIntegralInRange(1, 3); + + // Timeouts don't really work for fuzzing. Even a timeout of 0 milliseconds + // will be increased after the first timeout, resulting in inconsistent + // behavior. + config.timeout = base::TimeDelta::FromDays(10); + + config.rotate = data_provider->ConsumeBool(); + + config.use_local_ipv6 = data_provider->ConsumeBool(); + + return config; +} + // HostResolverProc that returns a random set of results, and can succeed or // fail. Must only be run on the thread it's created on. class FuzzedHostResolverProc : public HostResolverProc { @@ -311,9 +367,6 @@ socket_factory_(data_provider_), net_log_(net_log), data_provider_weak_factory_(data_provider) { - // Use SetDnsClientEnabled() to ensure fuzzed client is used. - DCHECK(!options.dns_client_enabled); - ProcTaskParams proc_task_params( new FuzzedHostResolverProc(data_provider_weak_factory_.GetWeakPtr()), // Retries are only used when the original request hangs, which this @@ -323,16 +376,20 @@ SetTaskRunnerForTesting(base::SequencedTaskRunnerHandle::Get()); SetMdnsSocketFactoryForTesting( std::make_unique<FuzzedMdnsSocketFactory>(data_provider_)); + std::unique_ptr<DnsClient> dns_client = DnsClient::CreateClientForTesting( + net_log_, &socket_factory_, + base::Bind(&FuzzedDataProvider::ConsumeIntegralInRange<int32_t>, + base::Unretained(data_provider_))); + dns_client->SetConfig(GetFuzzedDnsConfig(data_provider_)); + HostResolverManager::SetDnsClientForTesting(std::move(dns_client)); } ~FuzzedHostResolverManager() override = default; - // Enable / disable the async resolver. When enabled, installs a - // DnsClient with fuzzed UDP and TCP sockets. - void SetDnsClientEnabled(bool enabled) override; - void SetDnsClientForTesting(std::unique_ptr<DnsClient> dns_client) { - // Should only call SetDnsClientEnabled() to ensure a fuzzed client is used. + // The only DnsClient that is supported is the one created by the + // FuzzedHostResolverManager since that DnsClient contains the necessary + // fuzzing logic. NOTREACHED(); } @@ -362,73 +419,6 @@ DISALLOW_COPY_AND_ASSIGN(FuzzedHostResolverManager); }; -void FuzzedHostResolverManager::SetDnsClientEnabled(bool enabled) { - if (!enabled) { - HostResolverManager::SetDnsClientEnabled(false); - return; - } - - // Fuzz DNS configuration. - - DnsConfig config; - - // Fuzz name servers. - uint32_t num_nameservers = data_provider_->ConsumeIntegralInRange(0, 4); - for (uint32_t i = 0; i < num_nameservers; ++i) { - config.nameservers.push_back( - IPEndPoint(FuzzIPAddress(data_provider_), FuzzPort(data_provider_))); - } - - // Fuzz suffix search list. - switch (data_provider_->ConsumeIntegralInRange(0, 3)) { - case 3: - config.search.push_back("foo.com"); - FALLTHROUGH; - case 2: - config.search.push_back("bar"); - FALLTHROUGH; - case 1: - config.search.push_back("com"); - FALLTHROUGH; - default: - break; - } - - net::DnsHosts hosts; - // Fuzz hosts file. - uint8_t num_hosts_entries = data_provider_->ConsumeIntegral<uint8_t>(); - for (uint8_t i = 0; i < num_hosts_entries; ++i) { - const char* kHostnames[] = {"foo", "foo.com", "a.foo.com", - "bar", "localhost", "localhost6"}; - const char* hostname = data_provider_->PickValueInArray(kHostnames); - net::IPAddress address = FuzzIPAddress(data_provider_); - config.hosts[net::DnsHostsKey(hostname, net::GetAddressFamily(address))] = - address; - } - - config.unhandled_options = data_provider_->ConsumeBool(); - config.append_to_multi_label_name = data_provider_->ConsumeBool(); - config.randomize_ports = data_provider_->ConsumeBool(); - config.ndots = data_provider_->ConsumeIntegralInRange(0, 3); - config.attempts = data_provider_->ConsumeIntegralInRange(1, 3); - - // Timeouts don't really work for fuzzing. Even a timeout of 0 milliseconds - // will be increased after the first timeout, resulting in inconsistent - // behavior. - config.timeout = base::TimeDelta::FromDays(10); - - config.rotate = data_provider_->ConsumeBool(); - - config.use_local_ipv6 = data_provider_->ConsumeBool(); - - std::unique_ptr<DnsClient> dns_client = DnsClient::CreateClientForTesting( - net_log_, &socket_factory_, - base::Bind(&FuzzedDataProvider::ConsumeIntegralInRange<int32_t>, - base::Unretained(data_provider_))); - dns_client->SetConfig(config); - HostResolverManager::SetDnsClientForTesting(std::move(dns_client)); -} - } // namespace std::unique_ptr<ContextHostResolver> CreateFuzzedContextHostResolver( @@ -436,16 +426,8 @@ NetLog* net_log, FuzzedDataProvider* data_provider, bool enable_caching) { - // FuzzedHostResolverManager only handles fuzzing DnsClient when enabled - // through SetDnsClientEnabled(). - bool enable_dns_client = options.dns_client_enabled; - HostResolver::ManagerOptions filtered_options(options); - filtered_options.dns_client_enabled = false; - - auto manager = std::make_unique<FuzzedHostResolverManager>( - filtered_options, net_log, data_provider); - manager->SetDnsClientEnabled(enable_dns_client); - + auto manager = std::make_unique<FuzzedHostResolverManager>(options, net_log, + data_provider); return std::make_unique<ContextHostResolver>( std::move(manager), enable_caching ? HostCache::CreateDefaultCache() : nullptr);
diff --git a/net/dns/fuzzed_host_resolver_util.h b/net/dns/fuzzed_host_resolver_util.h index 11ac006..337955e 100644 --- a/net/dns/fuzzed_host_resolver_util.h +++ b/net/dns/fuzzed_host_resolver_util.h
@@ -20,9 +20,11 @@ // return. It inherits from ContextHostResolver, unlike MockHostResolver, so // more closely matches real behavior. // -// By default uses a mocked out system resolver, though can be configured (using -// SetDnsClientEnabled() on the underlying manager) to use the built-in async -// resolver (Built in DNS stub resolver) with a fuzzed set of UDP/TCP sockets. +// By default uses a mocked out system resolver, though can be configured to use +// the built-in async resolver (Built in DNS stub resolver) with a fuzzed set +// of UDP/TCP sockets by setting ManagerOptions.insecure_dns_client_enabled to +// true or calling SetInsecureDnsClientEnabled on the underlying +// HostResolverManager. // // To make behavior most deterministic, does not use the WorkerPool to run its // simulated platform host resolver calls, instead runs them on the thread it is
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h index 46550c3..d445710 100644 --- a/net/dns/host_resolver.h +++ b/net/dns/host_resolver.h
@@ -69,6 +69,9 @@ // an incompatible IP literal (e.g. IPv6 is disabled and it is an IPv6 // literal). // + // Results in ERR_DNS_CACHE_MISS if only fast local sources are to be + // queried and a cache lookup attempt fails. + // // The parent HostResolver must still be alive when Start() is called, but // if it is destroyed before an asynchronous result completes, the request // will be automatically cancelled. @@ -131,10 +134,10 @@ // |kDefaultRetryAttempts| for the resolver to choose a default value. size_t max_system_retry_attempts = kDefaultRetryAttempts; - // Initial setting for whether the built-in asynchronous DnsClient is - // enabled or disabled. See HostResolverManager::SetDnsClientEnabled() for - // details. - bool dns_client_enabled = false; + // Initial setting for whether the insecure portion of the built-in + // asynchronous DnsClient is enabled or disabled. See HostResolverManager:: + // SetInsecureDnsClientEnabled() for details. + bool insecure_dns_client_enabled = false; // Initial configuration overrides for the built-in asynchronous DnsClient. // See HostResolverManager::SetDnsConfigOverrides() for details.
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index b629c8b9..9a81b86 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -535,7 +535,7 @@ return true; } -const unsigned HostResolverManager::kMaximumDnsFailures = 16; +const unsigned HostResolverManager::kMaximumInsecureDnsTaskFailures = 16; // Holds the callback and request parameters for an outstanding request. // @@ -568,30 +568,7 @@ priority_(parameters_.initial_priority), job_(nullptr), resolver_(resolver), - complete_(false) { - // If the query name matches one of the DoH server names, set the - // secure_dns_mode_override field in ResolveHostParameters to OFF to avoid - // infinite recursion. - // TODO(crbug.com/878582): Add a URLRequest-level parameter to skip DoH that - // can be set when a URLRequest to a DoH server is built. This will avoid - // unnecessarily skipping DoH when a connection to the DoH server has been - // established but the query happens to be for a DoH server hostname. - DCHECK(resolver_); - if (resolver_->HaveDnsConfig()) { - std::unique_ptr<base::Value> dns_config = - resolver_->GetDnsConfigAsValue(); - for (const base::Value& doh_server : - dns_config->FindKey("doh_servers")->GetList()) { - if (request_host_.host().compare( - GURL(GetURLFromTemplateWithoutParameters( - doh_server.FindKey("server_template")->GetString())) - .host()) == 0) { - parameters_.secure_dns_mode_override = DnsConfig::SecureDnsMode::OFF; - break; - } - } - } - } + complete_(false) {} ~RequestImpl() override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -1047,6 +1024,8 @@ return needs_two_transactions() && !transaction2_; } + bool secure() const { return secure_; } + void StartFirstTransaction() { DCHECK(client_); DCHECK_EQ(0u, num_completed_transactions_); @@ -1467,15 +1446,17 @@ struct HostResolverManager::JobKey { bool operator<(const JobKey& other) const { - return std::tie(query_type, flags, source, request_context, hostname) < - std::tie(other.query_type, other.flags, other.source, - other.request_context, other.hostname); + return std::tie(query_type, flags, source, secure_dns_mode, request_context, + hostname) < std::tie(other.query_type, other.flags, + other.source, other.secure_dns_mode, + other.request_context, other.hostname); } std::string hostname; DnsQueryType query_type; HostResolverFlags flags; HostResolverSource source; + DnsConfig::SecureDnsMode secure_dns_mode; URLRequestContext* request_context; }; @@ -1639,30 +1620,32 @@ CompleteRequestsWithError(ERR_NETWORK_CHANGED); } - // Gets a closure that will abort a DnsTask (see AbortDnsTask()) iff |this| is - // still valid. Useful if aborting a list of Jobs as some may be cancelled - // while aborting others. - base::OnceClosure GetAbortDnsTaskClosure(int error, bool fallback_only) { - return base::BindOnce(&Job::AbortDnsTask, weak_ptr_factory_.GetWeakPtr(), - error, fallback_only); + // Gets a closure that will abort an insecure DnsTask (see + // AbortInsecureDnsTask()) iff |this| is still valid. Useful if aborting a + // list of Jobs as some may be cancelled while aborting others. + base::OnceClosure GetAbortInsecureDnsTaskClosure(int error, + bool fallback_only) { + return base::BindOnce(&Job::AbortInsecureDnsTask, + weak_ptr_factory_.GetWeakPtr(), error, fallback_only); } - // Aborts or removes any current/future DnsTasks if a ProcTask is available - // for fallback. If no fallback is available and |fallback_only| is false, a - // job that is currently running a DnsTask will be completed with |error|. - void AbortDnsTask(int error, bool fallback_only) { + // Aborts or removes any current/future insecure DnsTasks if a ProcTask is + // available for fallback. If no fallback is available and |fallback_only| is + // false, a job that is currently running an insecure DnsTask will be + // completed with |error|. + void AbortInsecureDnsTask(int error, bool fallback_only) { bool has_proc_fallback = std::find(tasks_.begin(), tasks_.end(), TaskType::PROC) != tasks_.end(); if (has_proc_fallback) { for (auto it = tasks_.begin(); it != tasks_.end();) { - if (*it == TaskType::DNS || *it == TaskType::SECURE_DNS) + if (*it == TaskType::DNS) it = tasks_.erase(it); else ++it; } } - if (dns_task_) { + if (dns_task_ && !dns_task_->secure()) { if (has_proc_fallback) { KillDnsTask(); dns_task_error_ = OK; @@ -1707,7 +1690,8 @@ DCHECK_GT(num_active_requests(), 0u); base::Optional<HostCache::Entry> results = resolver_->ServeFromHosts( hostname_, query_type_, - host_resolver_flags_ & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6); + host_resolver_flags_ & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6, + tasks_); if (results) { // This will destroy the Job. CompleteRequests(results.value(), base::TimeDelta(), @@ -1868,7 +1852,8 @@ DCHECK(proc_task_); if (dns_task_error_ != OK) { - // This ProcTask was a fallback resolution after a failed DnsTask. + // This ProcTask was a fallback resolution after a failed insecure + // DnsTask. if (net_error == OK) { resolver_->OnFallbackResolve(dns_task_error_); } @@ -1914,28 +1899,17 @@ void StartDnsTask(bool secure) { DCHECK_EQ(1u, num_occupied_job_slots_); + DCHECK(resolver_->HaveDnsConfig()); + DCHECK(!resolver_->HaveTestProcOverride()); // Need to create the task even if we're going to post a failure instead of // running it, as a "started" job needs a task to be properly cleaned up. dns_task_.reset(new DnsTask(resolver_->dns_client_.get(), hostname_, query_type_, request_context_, secure, this, net_log_, tick_clock_)); - - if (resolver_->HaveDnsConfig()) { - dns_task_->StartFirstTransaction(); - // Schedule a second transaction, if needed. - if (dns_task_->needs_two_transactions()) - Schedule(true); - } else { - // Cannot start a DNS task when DnsClient or config is not available. - // Since we cannot complete synchronously from here, post a failure. - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - &Job::OnDnsTaskFailure, weak_ptr_factory_.GetWeakPtr(), - dns_task_->AsWeakPtr(), base::TimeDelta(), - HostCache::Entry(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN), - secure)); - } + dns_task_->StartFirstTransaction(); + // Schedule a second transaction, if needed. + if (dns_task_->needs_two_transactions()) + Schedule(true); } void StartSecondDnsTransaction() { @@ -1997,7 +1971,10 @@ UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.SuccessTime", duration); - resolver_->OnDnsTaskResolve(); + // Reset the insecure DNS failure counter if an insecure DnsTask completed + // successfully. + if (!secure) + resolver_->num_insecure_dns_task_failures_ = 0; base::TimeDelta bounded_ttl = std::max( results.ttl(), base::TimeDelta::FromSeconds(kMinimumTTLSeconds)); @@ -2349,22 +2326,20 @@ HostResolverManager::HostResolverManager( const HostResolver::ManagerOptions& options, - NetLog* net_log, - DnsClientFactory dns_client_factory_for_testing) + NetLog* net_log) : max_queued_jobs_(0), proc_params_(nullptr, options.max_system_retry_attempts), net_log_(net_log), - dns_client_factory_for_testing_( - std::move(dns_client_factory_for_testing)), received_dns_config_(false), dns_config_overrides_(options.dns_config_overrides), - num_dns_failures_(0), + num_insecure_dns_task_failures_(0), check_ipv6_on_wifi_(options.check_ipv6_on_wifi), use_local_ipv6_(false), last_ipv6_probe_result_(true), additional_resolver_flags_(0), - use_proctask_by_default_(false), allow_fallback_to_proctask_(true), + bypass_insecure_dns_client_(false), + insecure_dns_client_enabled_(false), tick_clock_(base::DefaultTickClock::GetInstance()), invalidation_in_progress_(false) { PrioritizedDispatcher::Limits job_limits = GetDispatcherLimits(options); @@ -2394,15 +2369,17 @@ OnConnectionTypeChanged(NetworkChangeNotifier::GetConnectionType()); - SetDnsClientEnabled(options.dns_client_enabled); + DnsConfig dns_config = GetBaseDnsConfig(false); - { - DnsConfig dns_config = GetBaseDnsConfig(false); - // Conservatively assume local IPv6 is needed when DnsConfig is not valid. - use_local_ipv6_ = !dns_config.IsValid() || dns_config.use_local_ipv6; - UpdateModeForHistogram(dns_config); - } +#if defined(ENABLE_BUILT_IN_DNS) + dns_client_ = DnsClient::CreateClient(net_log_); + DCHECK(dns_client_); + if (!dns_client_->GetConfig()) + dns_client_->SetConfig(dns_config); +#endif + use_local_ipv6_ = !dns_config.IsValid() || dns_config.use_local_ipv6; + SetInsecureDnsClientEnabled(options.insecure_dns_client_enabled); allow_fallback_to_proctask_ = !ConfigureAsyncDnsNoFallbackFieldTrial(); } @@ -2461,34 +2438,23 @@ return listener; } -void HostResolverManager::SetDnsClientEnabled(bool enabled) { +void HostResolverManager::SetInsecureDnsClientEnabled(bool enabled) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - if (enabled && !dns_client_) { - if (dns_client_factory_for_testing_) { - SetDnsClient(dns_client_factory_for_testing_.Run(net_log_)); - } else { -#if defined(ENABLE_BUILT_IN_DNS) - SetDnsClient(DnsClient::CreateClient(net_log_)); -#endif - } + if (insecure_dns_client_enabled_ == enabled) return; - } - if (!enabled && dns_client_) { - SetDnsClient(nullptr); - } + insecure_dns_client_enabled_ = enabled; + AbortInsecureDnsTasks(ERR_NETWORK_CHANGED, false /* fallback_only */); + + DnsConfig dns_config = GetBaseDnsConfig(false); + UpdateModeForHistogram(dns_config); } std::unique_ptr<base::Value> HostResolverManager::GetDnsConfigAsValue() const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // Check if async DNS is disabled. if (!dns_client_.get()) return nullptr; - // Check if async DNS is enabled, but we currently have no configuration - // for it. const DnsConfig* dns_config = dns_client_->GetConfig(); if (!dns_config) return std::make_unique<base::DictionaryValue>(); @@ -2518,6 +2484,17 @@ host_cache_invalidators_.RemoveObserver(invalidator); } +bool HostResolverManager::GetInsecureDnsClientEnabledForTesting() { + return insecure_dns_client_enabled_; +} + +DnsConfig::SecureDnsMode HostResolverManager::GetSecureDnsModeForTesting() { + if (!HaveDnsConfig()) + return DnsConfig::SecureDnsMode::OFF; + + return dns_client_->GetConfig()->secure_dns_mode; +} + const std::vector<DnsConfig::DnsOverHttpsServerConfig>* HostResolverManager::GetDnsOverHttpsServersForTesting() const { if (!dns_config_overrides_.dns_over_https_servers || @@ -2565,10 +2542,8 @@ void HostResolverManager::SetDnsClientForTesting( std::unique_ptr<DnsClient> dns_client) { - // Use SetDnsClientEnabled(false) to disable. DCHECK(dns_client); - - SetDnsClient(std::move(dns_client)); + dns_client_ = std::move(dns_client); } void HostResolverManager::SetTaskRunnerForTesting( @@ -2596,6 +2571,7 @@ DnsQueryType effective_query_type; HostResolverFlags effective_host_resolver_flags; + DnsConfig::SecureDnsMode effective_secure_dns_mode; std::deque<TaskType> tasks; base::Optional<HostCache::EntryStaleness> stale_info; HostCache::Entry results = ResolveLocally( @@ -2604,9 +2580,11 @@ request->parameters().secure_dns_mode_override, request->parameters().cache_usage, request->source_net_log(), request->host_cache(), &effective_query_type, - &effective_host_resolver_flags, &tasks, &stale_info); + &effective_host_resolver_flags, &effective_secure_dns_mode, &tasks, + &stale_info); if (results.error() != ERR_DNS_CACHE_MISS || - request->parameters().source == HostResolverSource::LOCAL_ONLY) { + request->parameters().source == HostResolverSource::LOCAL_ONLY || + tasks.empty()) { if (results.error() == OK && !request->parameters().is_speculative) { request->set_results( results.CopyWithDefaultPort(request->request_host().port())); @@ -2621,7 +2599,7 @@ int rv = CreateAndStartJob(effective_query_type, effective_host_resolver_flags, - std::move(tasks), request); + effective_secure_dns_mode, std::move(tasks), request); // At this point, expect only async or errors. DCHECK_NE(OK, rv); @@ -2639,6 +2617,7 @@ HostCache* cache, DnsQueryType* out_effective_query_type, HostResolverFlags* out_effective_host_resolver_flags, + DnsConfig::SecureDnsMode* out_effective_secure_dns_mode, std::deque<TaskType>* out_tasks, base::Optional<HostCache::EntryStaleness>* out_stale_info) { DCHECK(out_stale_info); @@ -2665,7 +2644,8 @@ GetEffectiveParametersForRequest( hostname, dns_query_type, source, flags, secure_dns_mode_override, cache_usage, ip_address_ptr, source_net_log, out_effective_query_type, - out_effective_host_resolver_flags, out_tasks); + out_effective_host_resolver_flags, out_effective_secure_dns_mode, + out_tasks); bool resolve_canonname = *out_effective_host_resolver_flags & HOST_RESOLVER_CANONNAME; @@ -2727,7 +2707,7 @@ // TODO(szym): Do not do this if nsswitch.conf instructs not to. // http://crbug.com/117655 resolved = ServeFromHosts(hostname, *out_effective_query_type, - default_family_due_to_no_ipv6); + default_family_due_to_no_ipv6, *out_tasks); if (resolved) { NetLogHostCacheEntry(source_net_log, NetLogEventType::HOST_RESOLVER_IMPL_HOSTS_HIT, @@ -2741,12 +2721,13 @@ int HostResolverManager::CreateAndStartJob( DnsQueryType effective_query_type, HostResolverFlags effective_host_resolver_flags, + DnsConfig::SecureDnsMode effective_secure_dns_mode, std::deque<TaskType> tasks, RequestImpl* request) { DCHECK(!tasks.empty()); JobKey key = {request->request_host().host(), effective_query_type, - effective_host_resolver_flags, request->parameters().source, - request->request_context()}; + effective_host_resolver_flags, request->parameters().source, + effective_secure_dns_mode, request->request_context()}; auto jobit = jobs_.find(key); Job* job; @@ -2858,8 +2839,12 @@ base::Optional<HostCache::Entry> HostResolverManager::ServeFromHosts( base::StringPiece hostname, DnsQueryType query_type, - bool default_family_due_to_no_ipv6) { - if (!HaveDnsConfig() || !IsAddressType(query_type)) + bool default_family_due_to_no_ipv6, + const std::deque<TaskType>& tasks) { + // Don't attempt a HOSTS lookup if there is no DnsConfig or the HOSTS lookup + // is going to be done next as part of a system lookup. + if (!HaveDnsConfig() || !IsAddressType(query_type) || + (!tasks.empty() && tasks.front() == TaskType::PROC)) return base::nullopt; // HOSTS lookups are case-insensitive. @@ -2890,7 +2875,7 @@ // If got only loopback addresses and the family was restricted, resolve // again, without restrictions. See SystemHostResolverCall for rationale. if (default_family_due_to_no_ipv6 && IsAllIPv4Loopback(addresses)) { - return ServeFromHosts(hostname, DnsQueryType::UNSPECIFIED, false); + return ServeFromHosts(hostname, DnsQueryType::UNSPECIFIED, false, tasks); } if (!addresses.empty()) { @@ -2989,12 +2974,13 @@ } bool HostResolverManager::HasAvailableDohServer() { - // TODO(crbug.com/878582): Once DoH probes are sent, update this such that a + // TODO(crbug.com/985589): Once DoH probes are sent, update this such that a // DoH server is considered successful if it has a successful probe state. return dns_client_->GetConfig()->dns_over_https_servers.size() > 0; } DnsConfig::SecureDnsMode HostResolverManager::GetEffectiveSecureDnsMode( + const std::string& hostname, base::Optional<DnsConfig::SecureDnsMode> secure_dns_mode_override) { DnsConfig::SecureDnsMode secure_dns_mode = DnsConfig::SecureDnsMode::OFF; if (secure_dns_mode_override) { @@ -3002,64 +2988,107 @@ } else if (HaveDnsConfig()) { secure_dns_mode = dns_client_->GetConfig()->secure_dns_mode; } + + // If the query name matches one of the DoH server names, downgrade to OFF to + // avoid infinite recursion. + // TODO(crbug.com/985589): Add a URLRequest-level parameter to skip DoH that + // can be set when a URLRequest to a DoH server is built, and use this + // parameters to set |secure_dns_mode_override| in ResolveHostParameters. This + // improvement will prevent us from unnecessarily skipping DoH when a + // connection to the DoH server has been established but the query happens to + // be for a DoH server hostname. + if (HaveDnsConfig()) { + for (auto& server : dns_client_->GetConfig()->dns_over_https_servers) { + if (hostname.compare( + GURL(GetURLFromTemplateWithoutParameters(server.server_template)) + .host()) == 0) { + secure_dns_mode = DnsConfig::SecureDnsMode::OFF; + break; + } + } + } + return secure_dns_mode; } +bool HostResolverManager::HaveTestProcOverride() { + return !proc_params_.resolver_proc && HostResolverProc::GetDefault(); +} + void HostResolverManager::PushDnsTasks( - bool allow_proc_fallback, + bool proc_task_allowed, DnsConfig::SecureDnsMode secure_dns_mode, + bool insecure_tasks_allowed, ResolveHostParameters::CacheUsage cache_usage, std::deque<TaskType>* out_tasks) { + DCHECK(HaveDnsConfig()); bool allow_cache = cache_usage != ResolveHostParameters::CacheUsage::DISALLOWED; + // If a catch-all DNS block has been set for unit tests, we shouldn't send + // DnsTasks. It is still necessary to call this method, however, so that the + // correct cache tasks for the secure dns mode are added. + bool dns_tasks_allowed = !HaveTestProcOverride(); // Upgrade the insecure DnsTask depending on the secure dns mode. switch (secure_dns_mode) { case DnsConfig::SecureDnsMode::SECURE: DCHECK(dns_client_->GetConfig()->dns_over_https_servers.size() != 0); - // Replace the insecure DnsTask with a secure cache lookup followed - // by a secure DnsTask. if (allow_cache) out_tasks->push_back(TaskType::SECURE_CACHE_LOOKUP); - out_tasks->push_back(TaskType::SECURE_DNS); + if (dns_tasks_allowed) + out_tasks->push_back(TaskType::SECURE_DNS); break; case DnsConfig::SecureDnsMode::AUTOMATIC: - // TODO(crbug.com/878582): For a DnsTask in AUTOMATIC mode, the async + // TODO(crbug.com/985589): For a DnsTask in AUTOMATIC mode, the async // resolver should only send insecure requests if it is enabled on this // platform. if (!HasAvailableDohServer()) { // Don't run a secure DnsTask if there are no available DoH servers. if (allow_cache) out_tasks->push_back(TaskType::CACHE_LOOKUP); - out_tasks->push_back(TaskType::DNS); + if (dns_tasks_allowed && insecure_tasks_allowed) + out_tasks->push_back(TaskType::DNS); } else if (cache_usage == HostResolver::ResolveHostParameters:: CacheUsage::STALE_ALLOWED) { // If stale results are allowed, the cache should be checked for both // secure and insecure results prior to running a secure DnsTask. out_tasks->push_back(TaskType::CACHE_LOOKUP); - out_tasks->push_back(TaskType::SECURE_DNS); - out_tasks->push_back(TaskType::DNS); + if (dns_tasks_allowed) { + out_tasks->push_back(TaskType::SECURE_DNS); + if (insecure_tasks_allowed) + out_tasks->push_back(TaskType::DNS); + } } else { if (allow_cache) out_tasks->push_back(TaskType::SECURE_CACHE_LOOKUP); - out_tasks->push_back(TaskType::SECURE_DNS); + if (dns_tasks_allowed) + out_tasks->push_back(TaskType::SECURE_DNS); if (allow_cache) out_tasks->push_back(TaskType::INSECURE_CACHE_LOOKUP); - out_tasks->push_back(TaskType::DNS); + if (dns_tasks_allowed && insecure_tasks_allowed) + out_tasks->push_back(TaskType::DNS); } break; case DnsConfig::SecureDnsMode::OFF: if (allow_cache) out_tasks->push_back(TaskType::CACHE_LOOKUP); - out_tasks->push_back(TaskType::DNS); + if (dns_tasks_allowed && insecure_tasks_allowed) + out_tasks->push_back(TaskType::DNS); break; default: NOTREACHED(); break; } - // The system resolver can be used as a fallback if allowed by the request - // parameters. - if (allow_proc_fallback && allow_fallback_to_proctask_) + bool added_dns_task = false; + for (auto it = out_tasks->begin(); it != out_tasks->end(); ++it) { + if (*it == TaskType::DNS || *it == TaskType::SECURE_DNS) { + added_dns_task = true; + break; + } + } + // The system resolver can be used as a fallback for a non-existent or + // failing DnsTask if allowed by the request parameters. + if (proc_task_allowed && (!added_dns_task || allow_fallback_to_proctask_)) out_tasks->push_back(TaskType::PROC); } @@ -3070,10 +3099,11 @@ HostResolverFlags flags, base::Optional<DnsConfig::SecureDnsMode> secure_dns_mode_override, ResolveHostParameters::CacheUsage cache_usage, + DnsConfig::SecureDnsMode* out_effective_secure_dns_mode, std::deque<TaskType>* out_tasks) { DCHECK(out_tasks->empty()); - DnsConfig::SecureDnsMode secure_dns_mode = - GetEffectiveSecureDnsMode(secure_dns_mode_override); + *out_effective_secure_dns_mode = + GetEffectiveSecureDnsMode(hostname, secure_dns_mode_override); // A cache lookup should generally be performed first. For jobs involving a // DnsTask, this task will be removed before DnsTasks and other related tasks @@ -3094,22 +3124,24 @@ if ((flags & HOST_RESOLVER_CANONNAME) && IsAddressType(dns_query_type)) { out_tasks->push_back(TaskType::PROC); } else if (!ResemblesMulticastDNSName(hostname)) { - bool allow_proc_fallback = + bool proc_task_allowed = IsAddressType(dns_query_type) && - secure_dns_mode != DnsConfig::SecureDnsMode::SECURE; - // DnsClient or config is not available, but we're allowed to switch to - // ProcTask instead. - if ((!HaveDnsConfig() || use_proctask_by_default_) && - allow_proc_fallback) { - out_tasks->push_back(TaskType::PROC); - } else { + *out_effective_secure_dns_mode != DnsConfig::SecureDnsMode::SECURE; + if (HaveDnsConfig()) { // Remove the initial cache lookup task. if (!out_tasks->empty()) out_tasks->pop_front(); - PushDnsTasks(allow_proc_fallback, secure_dns_mode, cache_usage, - out_tasks); + PushDnsTasks( + proc_task_allowed, *out_effective_secure_dns_mode, + insecure_dns_client_enabled_ && !bypass_insecure_dns_client_, + cache_usage, out_tasks); + } else if (proc_task_allowed) { + out_tasks->push_back(TaskType::PROC); } } else if (IsAddressType(dns_query_type)) { + // For *.local address queries, try the system resolver even if the + // secure dns mode is SECURE. Public recursive resolvers aren't expected + // to handle these queries. out_tasks->push_back(TaskType::PROC); } else { out_tasks->push_back(TaskType::MDNS); @@ -3119,11 +3151,14 @@ out_tasks->push_back(TaskType::PROC); break; case HostResolverSource::DNS: - // Remove the initial cache lookup task. - if (!out_tasks->empty()) - out_tasks->pop_front(); - PushDnsTasks(false /* allow_proc_fallback */, secure_dns_mode, - cache_usage, out_tasks); + if (HaveDnsConfig()) { + // Remove the initial cache lookup task. + if (!out_tasks->empty()) + out_tasks->pop_front(); + PushDnsTasks(false /* proc_task_allowed */, + *out_effective_secure_dns_mode, + insecure_dns_client_enabled_, cache_usage, out_tasks); + } break; case HostResolverSource::MULTICAST_DNS: out_tasks->push_back(TaskType::MDNS); @@ -3145,6 +3180,7 @@ const NetLogWithSource& net_log, DnsQueryType* out_effective_type, HostResolverFlags* out_effective_flags, + DnsConfig::SecureDnsMode* out_effective_secure_dns_mode, std::deque<TaskType>* out_tasks) { *out_effective_flags = flags | additional_resolver_flags_; *out_effective_type = dns_query_type; @@ -3162,7 +3198,7 @@ CreateTaskSequence(hostname, *out_effective_type, source, *out_effective_flags, secure_dns_mode_override, - cache_usage, out_tasks); + cache_usage, out_effective_secure_dns_mode, out_tasks); } bool HostResolverManager::IsIPv6Reachable(const NetLogWithSource& net_log) { @@ -3261,35 +3297,13 @@ dispatcher_->SetLimits(limits); } -void HostResolverManager::SetDnsClient(std::unique_ptr<DnsClient> dns_client) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // DnsClient and config must be updated before aborting DnsTasks, since doing - // so may start new jobs. - dns_client_ = std::move(dns_client); - if (dns_client_ && !dns_client_->GetConfig() && - num_dns_failures_ < kMaximumDnsFailures) { - dns_client_->SetConfig(GetBaseDnsConfig(false)); - num_dns_failures_ = 0; - } - - AbortDnsTasks(ERR_NETWORK_CHANGED, false /* fallback_only */); - DnsConfig dns_config; - if (!HaveDnsConfig()) { - // UpdateModeForHistogram() needs to know the DnsConfig when - // !HaveDnsConfig() - dns_config = GetBaseDnsConfig(false); - } - UpdateModeForHistogram(dns_config); -} - -void HostResolverManager::AbortDnsTasks(int error, bool fallback_only) { +void HostResolverManager::AbortInsecureDnsTasks(int error, bool fallback_only) { // Aborting jobs potentially modifies |jobs_| and may even delete some jobs. // Create safe closures of all current jobs. std::vector<base::OnceClosure> job_abort_closures; for (auto& job : jobs_) { job_abort_closures.push_back( - job.second->GetAbortDnsTaskClosure(error, fallback_only)); + job.second->GetAbortInsecureDnsTaskClosure(error, fallback_only)); } // Pause the dispatcher so it won't start any new dispatcher jobs while @@ -3378,6 +3392,7 @@ received_dns_config_ = dns_config.IsValid(); } + // TODO(crbug.com/985589): Upgrade DoH servers for automatic mode here. return dns_config_overrides_.ApplyOverrides(dns_config); } @@ -3387,8 +3402,6 @@ // Conservatively assume local IPv6 is needed when DnsConfig is not valid. use_local_ipv6_ = !dns_config.IsValid() || dns_config.use_local_ipv6; - num_dns_failures_ = 0; - // We want a new DnsSession in place, before we Abort running Jobs, so that // the newly started jobs use the new config. if (dns_client_.get()) { @@ -3398,11 +3411,14 @@ dns_client_->GetConfig()->Equals(dns_config)); dns_client_->SetConfig(dns_config); } - use_proctask_by_default_ = false; if (config_changed) { InvalidateCaches(); + // Reset the insecure DNS task failure counter. + num_insecure_dns_task_failures_ = 0; + bypass_insecure_dns_client_ = false; + // Life check to bail once |this| is deleted. base::WeakPtr<HostResolverManager> self = weak_ptr_factory_.GetWeakPtr(); @@ -3419,35 +3435,25 @@ } bool HostResolverManager::HaveDnsConfig() const { - // Use DnsClient only if it's fully configured and there is no override by - // ScopedDefaultHostResolverProc. - // The alternative is to use NetworkChangeNotifier to override DnsConfig, - // but that would introduce construction order requirements for NCN and SDHRP. - return dns_client_ && dns_client_->GetConfig() && - (proc_params_.resolver_proc || !HostResolverProc::GetDefault()); -} - -void HostResolverManager::OnDnsTaskResolve() { - DCHECK(dns_client_); - num_dns_failures_ = 0; + return dns_client_ && dns_client_->GetConfig(); } void HostResolverManager::OnFallbackResolve(int dns_task_error) { DCHECK(dns_client_); DCHECK_NE(OK, dns_task_error); - ++num_dns_failures_; - if (num_dns_failures_ < kMaximumDnsFailures) + ++num_insecure_dns_task_failures_; + if (num_insecure_dns_task_failures_ < kMaximumInsecureDnsTaskFailures) return; - // Force fallback until the next DNS change. Must be done before aborting - // DnsTasks, since doing so may start new jobs. Do not fully clear out or - // disable the DnsClient as some requests (e.g. those specifying DNS source) - // are not allowed to fallback and will continue using DnsTask. - use_proctask_by_default_ = true; + // Skip insecure DNS lookups until the next DNS config change. Must be done + // before aborting DnsTasks, since doing so may start new jobs. Do not fully + // clear out or disable the DnsClient as some requests (e.g. those specifying + // DNS source) are not allowed to fallback and will continue using DnsTask. + bypass_insecure_dns_client_ = true; - // Fallback all fallback-allowed DnsTasks to ProcTasks. - AbortDnsTasks(ERR_FAILED, true /* fallback_only */); + // Fallback all fallback-allowed insecure DnsTasks to ProcTasks. + AbortInsecureDnsTasks(ERR_FAILED, true /* fallback_only */); } int HostResolverManager::GetOrCreateMdnsClient(MDnsClient** out_client) { @@ -3474,9 +3480,10 @@ #endif } +// TODO(crbug.com/985589): Update these metrics for DoH. void HostResolverManager::UpdateModeForHistogram(const DnsConfig& dns_config) { // Resolving with Async DNS resolver? - if (HaveDnsConfig()) { + if (HaveDnsConfig() && insecure_dns_client_enabled_) { mode_for_histogram_ = MODE_FOR_HISTOGRAM_ASYNC_DNS; for (const auto& dns_server : dns_client_->GetConfig()->nameservers) { if (DnsServerSupportsDoh(dns_server.address())) {
diff --git a/net/dns/host_resolver_manager.h b/net/dns/host_resolver_manager.h index 8f904491..b83f4f8 100644 --- a/net/dns/host_resolver_manager.h +++ b/net/dns/host_resolver_manager.h
@@ -89,8 +89,6 @@ using MdnsListener = HostResolver::MdnsListener; using ResolveHostRequest = HostResolver::ResolveHostRequest; using ResolveHostParameters = HostResolver::ResolveHostParameters; - using DnsClientFactory = - base::RepeatingCallback<std::unique_ptr<DnsClient>(NetLog*)>; using SecureDnsMode = DnsConfig::SecureDnsMode; class CancellableRequest : public ResolveHostRequest { @@ -112,14 +110,8 @@ // outstanding DNS transactions (not counting retransmissions and retries). // // |net_log| must remain valid for the life of the HostResolverManager. - // - // |dns_client_factory_for_testing| may be used to inject a factory to be used - // for ManagerOptions::dns_client_enabled and SetDnsClientEnabled(). If not - // set, standard DnsClient::CreateClient() will be used. - HostResolverManager( - const HostResolver::ManagerOptions& options, - NetLog* net_log, - DnsClientFactory dns_client_factory_for_testing = base::NullCallback()); + HostResolverManager(const HostResolver::ManagerOptions& options, + NetLog* net_log); // If any completion callbacks are pending when the resolver is destroyed, // the host resolutions are cancelled, and the completion callbacks will not @@ -148,7 +140,7 @@ // DnsConfig, a new config is fetched from NetworkChangeNotifier. // // Setting to |true| has no effect if |ENABLE_BUILT_IN_DNS| not defined. - virtual void SetDnsClientEnabled(bool enabled); + virtual void SetInsecureDnsClientEnabled(bool enabled); std::unique_ptr<base::Value> GetDnsConfigAsValue() const; @@ -170,6 +162,13 @@ void AddHostCacheInvalidator(HostCache::Invalidator* invalidator); void RemoveHostCacheInvalidator(const HostCache::Invalidator* invalidator); + // Returns the state of the insecure part of the DnsClient. + bool GetInsecureDnsClientEnabledForTesting(); + + // Returns the currently configured secure dns mode. Returns OFF if there is + // not a valid config. + SecureDnsMode GetSecureDnsModeForTesting(); + // Returns the currently configured DNS over HTTPS servers. Returns nullptr if // DNS over HTTPS is not enabled. const std::vector<DnsConfig::DnsOverHttpsServerConfig>* @@ -193,8 +192,6 @@ void SetBaseDnsConfigForTesting(const DnsConfig& base_config); - // Similar to SetDnsClientEnabled(true) except allows setting |dns_client| - // as the instance to be used. void SetDnsClientForTesting(std::unique_ptr<DnsClient> dns_client); // Allows the tests to catch slots leaking out of the dispatcher. One @@ -217,6 +214,7 @@ private: friend class HostResolverManagerTest; + friend class HostResolverManagerDnsTest; FRIEND_TEST_ALL_PREFIXES(HostResolverManagerDnsTest, ModeForHistogram); class Job; struct JobKey; @@ -253,9 +251,10 @@ SECURE_CACHE_LOOKUP, }; - // Number of consecutive failures of DnsTask (with successful fallback to - // ProcTask) before the DnsClient is disabled until the next DNS change. - static const unsigned kMaximumDnsFailures; + // Number of consecutive failures of an insecure DnsTask (with successful + // fallback to ProcTask) before the insecure portion of the DnsClient is + // disabled until the next DNS change. + static const unsigned kMaximumInsecureDnsTaskFailures; // Attempts host resolution for |request|. Generally only expected to be // called from RequestImpl::Start(). @@ -268,9 +267,9 @@ // sources. // // On ERR_DNS_CACHE_MISS and OK, effective request parameters are written to - // |out_effective_query_type| and |out_effective_host_resolver_flags|. - // |out_tasks| contains the tentative sequence of tasks that a future job - // should run. + // |out_effective_query_type|, |out_effective_host_resolver_flags|, and + // |out_effective_secure_dns_mode|. |out_tasks| contains the tentative + // sequence of tasks that a future job should run. // // If results are returned from the host cache, |out_stale_info| will be // filled in with information on how stale or fresh the result is. Otherwise, @@ -289,6 +288,7 @@ HostCache* cache, DnsQueryType* out_effective_query_type, HostResolverFlags* out_effective_host_resolver_flags, + DnsConfig::SecureDnsMode* out_effective_secure_dns_mode, std::deque<TaskType>* out_tasks, base::Optional<HostCache::EntryStaleness>* out_stale_info); @@ -297,6 +297,7 @@ // |request|. On error, marks |request| completed and returns the error. int CreateAndStartJob(DnsQueryType effective_query_type, HostResolverFlags effective_host_resolver_flags, + DnsConfig::SecureDnsMode effective_secure_dns_mode, std::deque<TaskType> tasks, RequestImpl* request); @@ -318,12 +319,14 @@ const NetLogWithSource& source_net_log, base::Optional<HostCache::EntryStaleness>* out_stale_info); - // Iff we have a DnsClient with a valid DnsConfig, and |key| can be resolved - // from the HOSTS file, return the results. + // Iff we have a DnsClient with a valid DnsConfig and we're not about to + // attempt a system lookup, then try to resolve the query using the HOSTS + // file. base::Optional<HostCache::Entry> ServeFromHosts( base::StringPiece hostname, DnsQueryType query_type, - bool default_family_due_to_no_ipv6); + bool default_family_due_to_no_ipv6, + const std::deque<TaskType>& tasks); // Iff |key| is for a localhost name (RFC 6761) and address DNS query type, // returns a results entry with the loopback IP. @@ -337,14 +340,21 @@ bool HasAvailableDohServer(); // Returns the secure dns mode to use for a job, taking into account the - // global DnsConfig mode and any per-request override. + // global DnsConfig mode and any per-request override. Requests matching DoH + // server hostnames are downgraded to off mode to avoid infinite loops. SecureDnsMode GetEffectiveSecureDnsMode( + const std::string& hostname, base::Optional<SecureDnsMode> secure_dns_mode_override); + // Returns true if a catch-all DNS block has been set for unit tests. No + // DnsTasks should be issued in this case. + bool HaveTestProcOverride(); + // Helper method to add DnsTasks and related tasks based on the SecureDnsMode // and fallback parameters. - void PushDnsTasks(bool allow_proc_fallback, + void PushDnsTasks(bool proc_task_allowed, SecureDnsMode secure_dns_mode, + bool insecure_tasks_allowed, ResolveHostParameters::CacheUsage cache_usage, std::deque<TaskType>* out_tasks); @@ -357,6 +367,7 @@ HostResolverFlags flags, base::Optional<SecureDnsMode> secure_dns_mode_override, ResolveHostParameters::CacheUsage cache_usage, + DnsConfig::SecureDnsMode* out_effective_secure_dns_mode, std::deque<TaskType>* out_tasks); // Determines "effective" request parameters using manager properties and IPv6 @@ -372,6 +383,7 @@ const NetLogWithSource& net_log, DnsQueryType* out_effective_type, HostResolverFlags* out_effective_flags, + DnsConfig::SecureDnsMode* out_effective_secure_dns_mode, std::deque<TaskType>* out_tasks); // Probes IPv6 support and returns true if IPv6 support is enabled. @@ -405,14 +417,13 @@ // true. Might start new jobs. void AbortAllJobs(bool in_progress_only); - void SetDnsClient(std::unique_ptr<DnsClient> dns_client); - - // Aborts all in progress DnsTasks. In-progress jobs will fall back to - // ProcTasks if able and otherwise abort with |error|. Might start new jobs, - // if any jobs were taking up two dispatcher slots. + // Aborts all in progress insecure DnsTasks. In-progress jobs will fall back + // to ProcTasks if able and otherwise abort with |error|. Might start new + // jobs, if any jobs were taking up two dispatcher slots. // - // If |fallback_only|, tasks will only abort if they can fallback to ProcTask. - void AbortDnsTasks(int error, bool fallback_only); + // If |fallback_only|, insecure DnsTasks will only abort if they can fallback + // to ProcTask. + void AbortInsecureDnsTasks(int error, bool fallback_only); // Attempts to serve each Job in |jobs_| from the HOSTS file if we have // a DnsClient with a valid DnsConfig. @@ -437,8 +448,6 @@ // True if have a DnsClient with a valid DnsConfig. bool HaveDnsConfig() const; - // Called on successful DnsTask resolve. - void OnDnsTaskResolve(); // Called on successful resolve after falling back to ProcTask after a failed // DnsTask resolve. void OnFallbackResolve(int dns_task_error); @@ -470,9 +479,6 @@ NetLog* net_log_; - // If set, used for construction of DnsClients for SetDnsClientEnabled(). - const DnsClientFactory dns_client_factory_for_testing_; - // If present, used by DnsTask and ServeFromHosts to resolve requests. std::unique_ptr<DnsClient> dns_client_; @@ -489,8 +495,9 @@ // resolution. DnsConfigOverrides dns_config_overrides_; - // Number of consecutive failures of DnsTask, counted when fallback succeeds. - unsigned num_dns_failures_; + // Number of consecutive failures of insecure DnsTask, counted when fallback + // succeeds. + unsigned num_insecure_dns_task_failures_; // False if IPv6 should not be attempted and assumed unreachable when on a // WiFi connection. See https://crbug.com/696569 for further context. @@ -506,15 +513,14 @@ // Any resolver flags that should be added to a request by default. HostResolverFlags additional_resolver_flags_; - // |true| if requests that would otherwise be handled via DnsTask should - // instead use ProcTask when able. Used in cases where there have been - // multiple failures in DnsTask that succeeded in ProcTask, leading to the - // conclusion that the resolver has a bad DNS configuration. - bool use_proctask_by_default_; - // Allow fallback to ProcTask if DnsTask fails. bool allow_fallback_to_proctask_; + // Whether insecure DnsTasks should not be added to the task sequence even if + // the insecure part of the DnsClient is enabled. This is set to true when + // there are too many successive insecure DnsTask failures. + bool bypass_insecure_dns_client_; + // Task runner used for DNS lookups using the system resolver. Normally a // ThreadPool task runner, but can be overridden for tests. scoped_refptr<base::TaskRunner> proc_task_runner_; @@ -522,6 +528,13 @@ // Current resolver mode, useful for breaking down histogram data. ModeForHistogram mode_for_histogram_; + // Whether insecure requests should be issued by DnsClient. This field is + // complementary to the SecureDnsMode in DnsConfig. If we're in AUTOMATIC + // mode, |insecure_dns_client_enabled_| will determine whether or not we + // fallback to the insecure part of DnsClient before falling back to the + // system resolver. + bool insecure_dns_client_enabled_; + // Shared tick clock, overridden for testing. const base::TickClock* tick_clock_;
diff --git a/net/dns/host_resolver_manager_fuzzer.cc b/net/dns/host_resolver_manager_fuzzer.cc index 0606e0a..23795a6 100644 --- a/net/dns/host_resolver_manager_fuzzer.cc +++ b/net/dns/host_resolver_manager_fuzzer.cc
@@ -205,7 +205,7 @@ net::HostResolver::ManagerOptions options; options.max_concurrent_resolves = data_provider.ConsumeIntegralInRange(1, 8); - options.dns_client_enabled = data_provider.ConsumeBool(); + options.insecure_dns_client_enabled = data_provider.ConsumeBool(); bool enable_caching = data_provider.ConsumeBool(); std::unique_ptr<net::ContextHostResolver> host_resolver = net::CreateFuzzedContextHostResolver(options, &net_log, &data_provider,
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index f332b9c..860fca3 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -426,12 +426,10 @@ NetLog* net_log) : TestHostResolverManager(options, net_log, true) {} - TestHostResolverManager( - const HostResolver::ManagerOptions& options, - NetLog* net_log, - bool ipv6_reachable, - DnsClientFactory dns_client_factory_for_testing = base::NullCallback()) - : HostResolverManager(options, net_log, dns_client_factory_for_testing), + TestHostResolverManager(const HostResolver::ManagerOptions& options, + NetLog* net_log, + bool ipv6_reachable) + : HostResolverManager(options, net_log), ipv6_reachable_(ipv6_reachable) {} ~TestHostResolverManager() override = default; @@ -541,7 +539,7 @@ const ProcTaskParams& params, bool ipv6_reachable) { // Use HostResolverManagerDnsTest if enabling DNS client. - DCHECK(!options.dns_client_enabled); + DCHECK(!options.insecure_dns_client_enabled); DestroyResolver(); @@ -564,8 +562,8 @@ resolver_->allow_fallback_to_proctask_ = allow_fallback_to_proctask; } - static unsigned maximum_dns_failures() { - return HostResolverManager::kMaximumDnsFailures; + static unsigned maximum_insecure_dns_task_failures() { + return HostResolverManager::kMaximumInsecureDnsTaskFailures; } bool IsIPv6Reachable(const NetLogWithSource& net_log) { @@ -3406,28 +3404,21 @@ HostResolver::ManagerOptions DefaultOptions() override { HostResolver::ManagerOptions options = HostResolverManagerTest::DefaultOptions(); - options.dns_client_enabled = true; + options.insecure_dns_client_enabled = true; return options; } - // Implements HostResolverManager::DnsClientFactory to create a MockDnsClient - // with empty config and default rules. - std::unique_ptr<DnsClient> CreateMockClient(NetLog* net_log) { - auto dns_client = - std::make_unique<MockDnsClient>(DnsConfig(), CreateDefaultDnsRules()); - dns_client_ = dns_client.get(); - return dns_client; - } - void CreateResolverWithOptionsAndParams(HostResolver::ManagerOptions options, const ProcTaskParams& params, bool ipv6_reachable) override { DestroyResolver(); resolver_ = std::make_unique<TestHostResolverManager>( - options, nullptr /* net_log */, ipv6_reachable, - base::BindRepeating(&HostResolverManagerDnsTest::CreateMockClient, - base::Unretained(this))); + options, nullptr /* net_log */, ipv6_reachable); + auto dns_client = + std::make_unique<MockDnsClient>(DnsConfig(), CreateDefaultDnsRules()); + dns_client_ = dns_client.get(); + resolver_->SetDnsClientForTesting(std::move(dns_client)); resolver_->set_proc_params_for_test(params); if (host_cache_) @@ -3443,6 +3434,7 @@ std::make_unique<MockDnsClient>(DnsConfig(), std::move(rules)); dns_client_ = dns_client.get(); resolver_->SetDnsClientForTesting(std::move(dns_client)); + resolver_->SetInsecureDnsClientEnabled(true); if (!config.Equals(DnsConfig())) ChangeDnsConfig(config); } @@ -3537,6 +3529,11 @@ AddDnsRule(&rules, "insecure_automatic", dns_protocol::kTypeAAAA, MockDnsClientRule::OK, false /* delay */); + AddSecureDnsRule(&rules, "secure", dns_protocol::kTypeA, + MockDnsClientRule::OK, false /* delay */); + AddSecureDnsRule(&rules, "secure", dns_protocol::kTypeAAAA, + MockDnsClientRule::OK, false /* delay */); + return rules; } @@ -3600,7 +3597,7 @@ MockDnsClient* dns_client_; }; -TEST_F(HostResolverManagerDnsTest, DisableAndEnableDnsClient) { +TEST_F(HostResolverManagerDnsTest, DisableAndEnableInsecureDnsClient) { // Disable fallback to allow testing how requests are initially handled. set_allow_fallback_to_proctask(false); @@ -3608,7 +3605,7 @@ proc_->AddRuleForAllFamilies("nx_succeed", "192.168.2.47"); proc_->SignalMultiple(1u); - resolver_->SetDnsClientEnabled(false); + resolver_->SetInsecureDnsClientEnabled(false); ResolveHostResponseHelper response_proc(resolver_->CreateRequest( HostPortPair("nx_succeed", 1212), NetLogWithSource(), base::nullopt, request_context_.get(), host_cache_.get())); @@ -3616,7 +3613,7 @@ EXPECT_THAT(response_proc.request()->GetAddressResults().value().endpoints(), testing::ElementsAre(CreateExpected("192.168.2.47", 1212))); - resolver_->SetDnsClientEnabled(true); + resolver_->SetInsecureDnsClientEnabled(true); ResolveHostResponseHelper response_dns_client(resolver_->CreateRequest( HostPortPair("ok_fail", 1212), NetLogWithSource(), base::nullopt, request_context_.get(), host_cache_.get())); @@ -3757,32 +3754,18 @@ initial_response1.request()->GetAddressResults().value().endpoints(), testing::ElementsAre(CreateExpected("192.168.1.102", 80))); + // Switch to a valid config. ChangeDnsConfig(CreateValidDnsConfig()); - - ResolveHostResponseHelper abort_response0(resolver_->CreateRequest( - HostPortPair("ok_abort", 80), NetLogWithSource(), base::nullopt, - request_context_.get(), host_cache_.get())); - ResolveHostResponseHelper abort_response1(resolver_->CreateRequest( - HostPortPair("nx_abort", 80), NetLogWithSource(), base::nullopt, - request_context_.get(), host_cache_.get())); - - // Simulate the case when the preference or policy has disabled the DNS - // client causing AbortDnsTasks. - UseMockDnsClient(CreateValidDnsConfig(), CreateDefaultDnsRules()); - // First request is resolved by MockDnsClient, others should fail due to // disabled fallback to ProcTask. ResolveHostResponseHelper response0(resolver_->CreateRequest( HostPortPair("ok_fail", 80), NetLogWithSource(), base::nullopt, request_context_.get(), host_cache_.get())); ResolveHostResponseHelper response1(resolver_->CreateRequest( - HostPortPair("nx_fail", 80), NetLogWithSource(), base::nullopt, + HostPortPair("nx_succeed", 80), NetLogWithSource(), base::nullopt, request_context_.get(), host_cache_.get())); proc_->SignalMultiple(6u); - // Aborted due to Network Change. - EXPECT_THAT(abort_response0.result_error(), IsError(ERR_NETWORK_CHANGED)); - EXPECT_THAT(abort_response1.result_error(), IsError(ERR_NETWORK_CHANGED)); // Resolved by MockDnsClient. EXPECT_THAT(response0.result_error(), IsOk()); EXPECT_THAT(response0.request()->GetAddressResults().value().endpoints(), @@ -3889,9 +3872,9 @@ request_context_.get(), host_cache_.get())); proc_->SignalMultiple(2u); - // Simulate the case when the preference or policy has disabled the DNS client - // causing AbortDnsTasks. - resolver_->SetDnsClientEnabled(false); + // Simulate the case when the preference or policy has disabled the insecure + // DNS client causing AbortInsecureDnsTasks. + resolver_->SetInsecureDnsClientEnabled(false); // All requests should fallback to proc resolver. EXPECT_THAT(response0.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); @@ -3922,15 +3905,45 @@ // instead of hanging. proc_->SignalMultiple(2u); - // Simulate the case when the preference or policy has disabled the DNS client - // causing AbortDnsTasks. - resolver_->SetDnsClientEnabled(false); + // Simulate the case when the preference or policy has disabled the insecure + // DNS client causing AbortInsecureDnsTasks. + resolver_->SetInsecureDnsClientEnabled(false); // No fallback expected. All requests should fail. EXPECT_THAT(response0.result_error(), IsError(ERR_NETWORK_CHANGED)); EXPECT_THAT(response1.result_error(), IsError(ERR_NETWORK_CHANGED)); } +// Insecure DnsClient change shouldn't affect secure DnsTasks. +TEST_F(HostResolverManagerDnsTest, + DisableInsecureDnsClient_SecureDnsTasksUnaffected) { + // Ensure fallback is otherwise allowed by resolver settings. + set_allow_fallback_to_proctask(true); + + proc_->AddRuleForAllFamilies("automatic", "192.168.1.102"); + // All other hostnames will fail in proc_. + + ChangeDnsConfig(CreateValidDnsConfig()); + + HostResolver::ResolveHostParameters secure_parameters; + secure_parameters.secure_dns_mode_override = + DnsConfig::SecureDnsMode::AUTOMATIC; + ResolveHostResponseHelper response_secure(resolver_->CreateRequest( + HostPortPair("automatic", 80), NetLogWithSource(), secure_parameters, + request_context_.get(), host_cache_.get())); + EXPECT_FALSE(response_secure.complete()); + + // Simulate the case when the preference or policy has disabled the insecure + // DNS client causing AbortInsecureDnsTasks. + resolver_->SetInsecureDnsClientEnabled(false); + + EXPECT_THAT(response_secure.result_error(), IsOk()); + EXPECT_THAT( + response_secure.request()->GetAddressResults().value().endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 80), + CreateExpected("::1", 80))); +} + TEST_F(HostResolverManagerDnsTest, DnsTaskUnspec) { ChangeDnsConfig(CreateValidDnsConfig()); @@ -4077,6 +4090,28 @@ testing::ElementsAre(CreateExpected("127.0.0.1", 80))); } +TEST_F(HostResolverManagerDnsTest, SkipHostsWithUpcomingProcTask) { + // Disable the DnsClient. + resolver_->SetInsecureDnsClientEnabled(false); + + proc_->AddRuleForAllFamilies(std::string(), + std::string()); // Default to failures. + proc_->SignalMultiple(1u); // For the first request which misses. + + DnsConfig config = CreateValidDnsConfig(); + DnsHosts hosts; + hosts[DnsHostsKey("hosts", ADDRESS_FAMILY_IPV4)] = IPAddress::IPv4Localhost(); + + // Update HOSTS file. + config.hosts = hosts; + ChangeDnsConfig(config); + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair("hosts", 80), NetLogWithSource(), base::nullopt, + request_context_.get(), host_cache_.get())); + EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); +} + // Test that hosts ending in ".local" or ".local." are resolved using the system // resolver. TEST_F(HostResolverManagerDnsTest, BypassDnsTask) { @@ -4202,7 +4237,8 @@ EXPECT_THAT(system_response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); } -TEST_F(HostResolverManagerDnsTest, DisableDnsClientOnPersistentFailure) { +TEST_F(HostResolverManagerDnsTest, + DisableInsecureDnsClientOnPersistentFailure) { ChangeDnsConfig(CreateValidDnsConfig()); proc_->AddRuleForAllFamilies(std::string(), @@ -4215,7 +4251,7 @@ EXPECT_THAT(initial_response.result_error(), IsOk()); std::vector<std::unique_ptr<ResolveHostResponseHelper>> responses; - for (unsigned i = 0; i < maximum_dns_failures(); ++i) { + for (unsigned i = 0; i < maximum_insecure_dns_task_failures(); ++i) { // Use custom names to require separate Jobs. std::string hostname = base::StringPrintf("nx_%u", i); // Ensure fallback to ProcTask succeeds. @@ -4233,7 +4269,8 @@ ASSERT_FALSE(proc_->HasBlockedRequests()); - // DnsTask should be disabled by now unless explictly requested via |source|. + // Insecure DnsTasks should be disabled by now unless explicitly requested via + // |source|. ResolveHostResponseHelper fail_response(resolver_->CreateRequest( HostPortPair("ok_2", 80), NetLogWithSource(), base::nullopt, request_context_.get(), host_cache_.get())); @@ -4246,6 +4283,15 @@ EXPECT_THAT(fail_response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); EXPECT_THAT(dns_response.result_error(), IsOk()); + // Secure DnsTasks should not be affected. + HostResolver::ResolveHostParameters secure_parameters; + secure_parameters.secure_dns_mode_override = + DnsConfig::SecureDnsMode::AUTOMATIC; + ResolveHostResponseHelper secure_response(resolver_->CreateRequest( + HostPortPair("automatic", 80), NetLogWithSource(), secure_parameters, + request_context_.get(), host_cache_.get())); + EXPECT_THAT(secure_response.result_error(), IsOk()); + // Check that it is re-enabled after DNS change. ChangeDnsConfig(CreateValidDnsConfig()); ResolveHostResponseHelper reenabled_response(resolver_->CreateRequest( @@ -4298,7 +4344,7 @@ proc_->AddRuleForAllFamilies(std::string(), std::string()); // Try without DnsClient. - resolver_->SetDnsClientEnabled(false); + resolver_->SetInsecureDnsClientEnabled(false); ResolveHostResponseHelper system_response(resolver_->CreateRequest( HostPortPair("localhost", 80), NetLogWithSource(), base::nullopt, request_context_.get(), host_cache_.get())); @@ -4334,6 +4380,63 @@ CreateExpected("::1", 80))); } +TEST_F(HostResolverManagerDnsTest, SeparateJobsBySecureDnsMode) { + MockDnsClientRuleList rules; + rules.emplace_back("a", dns_protocol::kTypeA, true /* secure */, + MockDnsClientRule::Result(MockDnsClientRule::FAIL), + true /* delay */); + rules.emplace_back("a", dns_protocol::kTypeAAAA, true /* secure */, + MockDnsClientRule::Result(MockDnsClientRule::FAIL), + true /* delay */); + rules.emplace_back("a", dns_protocol::kTypeA, false /* secure */, + MockDnsClientRule::Result(MockDnsClientRule::OK), + false /* delay */); + rules.emplace_back("a", dns_protocol::kTypeAAAA, false /* secure */, + MockDnsClientRule::Result(MockDnsClientRule::OK), + false /* delay */); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + DnsConfigOverrides overrides; + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; + resolver_->SetDnsConfigOverrides(overrides); + + // Create three requests. One with a SECURE mode override, one with no + // mode override, and one with an AUTOMATIC mode override (which is a no-op + // since the DnsConfig uses AUTOMATIC). + HostResolver::ResolveHostParameters parameters_secure_override; + parameters_secure_override.secure_dns_mode_override = + DnsConfig::SecureDnsMode::SECURE; + ResolveHostResponseHelper secure_response(resolver_->CreateRequest( + HostPortPair("a", 80), NetLogWithSource(), parameters_secure_override, + request_context_.get(), host_cache_.get())); + EXPECT_EQ(1u, resolver_->num_jobs_for_testing()); + + ResolveHostResponseHelper automatic_response0(resolver_->CreateRequest( + HostPortPair("a", 80), NetLogWithSource(), base::nullopt, + request_context_.get(), host_cache_.get())); + EXPECT_EQ(2u, resolver_->num_jobs_for_testing()); + + HostResolver::ResolveHostParameters parameters_automatic_override; + parameters_automatic_override.secure_dns_mode_override = + DnsConfig::SecureDnsMode::AUTOMATIC; + ResolveHostResponseHelper automatic_response1(resolver_->CreateRequest( + HostPortPair("a", 80), NetLogWithSource(), parameters_automatic_override, + request_context_.get(), host_cache_.get())); + // The AUTOMATIC mode requests should be joined into the same job. + EXPECT_EQ(2u, resolver_->num_jobs_for_testing()); + + // All requests should be blocked on the secure transactions. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(secure_response.complete()); + EXPECT_FALSE(automatic_response0.complete()); + EXPECT_FALSE(automatic_response1.complete()); + + // Complete secure transactions. + dns_client_->CompleteDelayedTransactions(); + EXPECT_THAT(secure_response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); + EXPECT_THAT(automatic_response0.result_error(), IsOk()); + EXPECT_THAT(automatic_response1.result_error(), IsOk()); +} + // Cancel a request with a single DNS transaction active. TEST_F(HostResolverManagerDnsTest, CancelWithOneTransactionActive) { // Disable ipv6 to ensure we'll only try a single transaction for the host. @@ -4862,18 +4965,73 @@ EXPECT_TRUE(response_stale.request()->GetStaleInfo()->is_stale()); } +TEST_F(HostResolverManagerDnsTest, + SecureDnsMode_Automatic_InsecureAsyncDisabled) { + proc_->AddRuleForAllFamilies("insecure_automatic", "192.168.1.100"); + ChangeDnsConfig(CreateValidDnsConfig()); + resolver_->SetInsecureDnsClientEnabled(false); + DnsConfigOverrides overrides; + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; + resolver_->SetDnsConfigOverrides(overrides); + + const std::pair<const HostCache::Key, HostCache::Entry>* cache_result; + + // The secure part of the dns client should be enabled. + ResolveHostResponseHelper response_secure(resolver_->CreateRequest( + HostPortPair("automatic", 80), NetLogWithSource(), base::nullopt, + request_context_.get(), host_cache_.get())); + ASSERT_THAT(response_secure.result_error(), IsOk()); + EXPECT_THAT( + response_secure.request()->GetAddressResults().value().endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 80), + CreateExpected("::1", 80))); + HostCache::Key secure_key = + HostCache::Key("automatic", DnsQueryType::UNSPECIFIED, + 0 /* host_resolver_flags */, HostResolverSource::ANY); + secure_key.secure = true; + cache_result = GetCacheHit(secure_key); + EXPECT_TRUE(!!cache_result); + + // The insecure part of the dns client is disabled so insecure requests + // should be skipped. + ResolveHostResponseHelper response_insecure(resolver_->CreateRequest( + HostPortPair("insecure_automatic", 80), NetLogWithSource(), base::nullopt, + request_context_.get(), host_cache_.get())); + proc_->SignalMultiple(1u); + ASSERT_THAT(response_insecure.result_error(), IsOk()); + EXPECT_THAT( + response_insecure.request()->GetAddressResults().value().endpoints(), + testing::ElementsAre(CreateExpected("192.168.1.100", 80))); + HostCache::Key insecure_key = + HostCache::Key("insecure_automatic", DnsQueryType::UNSPECIFIED, + 0 /* host_resolver_flags */, HostResolverSource::ANY); + cache_result = GetCacheHit(insecure_key); + EXPECT_TRUE(!!cache_result); + + HostCache::Key cached_insecure_key = + HostCache::Key("insecure_automatic_cached", DnsQueryType::UNSPECIFIED, + 0 /* host_resolver_flags */, HostResolverSource::ANY); + IPEndPoint kExpectedInsecureIP = CreateExpected("192.168.1.101", 80); + PopulateCache(cached_insecure_key, kExpectedInsecureIP); + + // The insecure cache should still be checked even if the insecure part of + // the dns client is disabled. + ResolveHostResponseHelper response_insecure_cached(resolver_->CreateRequest( + HostPortPair("insecure_automatic_cached", 80), NetLogWithSource(), + base::nullopt, request_context_.get(), host_cache_.get())); + EXPECT_THAT(response_insecure_cached.result_error(), IsOk()); + EXPECT_THAT(response_insecure_cached.request() + ->GetAddressResults() + .value() + .endpoints(), + testing::ElementsAre(kExpectedInsecureIP)); +} + TEST_F(HostResolverManagerDnsTest, SecureDnsMode_Secure) { proc_->AddRuleForAllFamilies("nx_succeed", "192.168.1.100"); set_allow_fallback_to_proctask(true); - MockDnsClientRuleList rules; - rules.emplace_back("secure", dns_protocol::kTypeA, true /* secure */, - MockDnsClientRule::Result(MockDnsClientRule::OK), - false /* delay */); - rules.emplace_back("secure", dns_protocol::kTypeAAAA, true /* secure */, - MockDnsClientRule::Result(MockDnsClientRule::OK), - false /* delay */); - UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + ChangeDnsConfig(CreateValidDnsConfig()); DnsConfigOverrides overrides; overrides.secure_dns_mode = DnsConfig::SecureDnsMode::SECURE; resolver_->SetDnsConfigOverrides(overrides); @@ -4908,6 +5066,30 @@ EXPECT_THAT(response_proc.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); } +TEST_F(HostResolverManagerDnsTest, SecureDnsMode_Secure_InsecureAsyncDisabled) { + proc_->AddRuleForAllFamilies("nx_succeed", "192.168.1.100"); + set_allow_fallback_to_proctask(true); + resolver_->SetInsecureDnsClientEnabled(false); + + ChangeDnsConfig(CreateValidDnsConfig()); + DnsConfigOverrides overrides; + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::SECURE; + resolver_->SetDnsConfigOverrides(overrides); + const std::pair<const HostCache::Key, HostCache::Entry>* cache_result; + + // The secure part of the dns client should be enabled. + ResolveHostResponseHelper response_secure(resolver_->CreateRequest( + HostPortPair("secure", 80), NetLogWithSource(), base::nullopt, + request_context_.get(), host_cache_.get())); + ASSERT_THAT(response_secure.result_error(), IsOk()); + HostCache::Key secure_key = + HostCache::Key("secure", DnsQueryType::UNSPECIFIED, + 0 /* host_resolver_flags */, HostResolverSource::ANY); + secure_key.secure = true; + cache_result = GetCacheHit(secure_key); + EXPECT_TRUE(!!cache_result); +} + // Test the case where only a single transaction slot is available. TEST_F(HostResolverManagerDnsTest, SerialResolver) { CreateSerialResolver(); @@ -5090,10 +5272,10 @@ EXPECT_THAT(response.result_error(), IsOk()); } -// Tests the case that DnsClient is automatically disabled due to failures -// while there are active DnsTasks. +// Tests the case that the insecure part of the DnsClient is automatically +// disabled due to failures while there are active DnsTasks. TEST_F(HostResolverManagerDnsTest, - AutomaticallyDisableDnsClientWithPendingRequests) { + AutomaticallyDisableInsecureDnsClientWithPendingRequests) { // Trying different limits is important for this test: Different limits // result in different behavior when aborting in-progress DnsTasks. Having // a DnsTask that has one job active and one in the queue when another job @@ -5106,10 +5288,10 @@ ChangeDnsConfig(CreateValidDnsConfig()); - // Queue up enough failures to disable DnsTasks. These will all fall back - // to ProcTasks, and succeed there. + // Queue up enough failures to disable insecure DnsTasks. These will all + // fall back to ProcTasks, and succeed there. std::vector<std::unique_ptr<ResolveHostResponseHelper>> failure_responses; - for (unsigned i = 0u; i < maximum_dns_failures(); ++i) { + for (unsigned i = 0u; i < maximum_insecure_dns_task_failures(); ++i) { std::string host = base::StringPrintf("nx%u", i); proc_->AddRuleForAllFamilies(host, "192.168.0.1"); failure_responses.emplace_back( @@ -5119,8 +5301,8 @@ EXPECT_FALSE(failure_responses[i]->complete()); } - // These requests should all bypass DnsTasks, due to the above failures, - // so should end up using ProcTasks. + // These requests should all bypass insecure DnsTasks, due to the above + // failures, so should end up using ProcTasks. proc_->AddRuleForAllFamilies("slow_ok1", "192.168.0.2"); ResolveHostResponseHelper response0(resolver_->CreateRequest( HostPortPair("slow_ok1", 80), NetLogWithSource(), base::nullopt, @@ -5155,9 +5337,18 @@ request_context_.get(), host_cache_.get())); EXPECT_FALSE(response_system.complete()); - proc_->SignalMultiple(maximum_dns_failures() + 5); + // Secure DnsTasks should not be affected. + HostResolver::ResolveHostParameters secure_parameters; + secure_parameters.secure_dns_mode_override = + DnsConfig::SecureDnsMode::AUTOMATIC; + ResolveHostResponseHelper response_secure(resolver_->CreateRequest( + HostPortPair("automatic", 80), NetLogWithSource(), secure_parameters, + request_context_.get(), host_cache_.get())); + EXPECT_FALSE(response_secure.complete()); - for (size_t i = 0u; i < maximum_dns_failures(); ++i) { + proc_->SignalMultiple(maximum_insecure_dns_task_failures() + 6); + + for (size_t i = 0u; i < maximum_insecure_dns_task_failures(); ++i) { EXPECT_THAT(failure_responses[i]->result_error(), IsOk()); EXPECT_THAT(failure_responses[i] ->request() @@ -5184,6 +5375,8 @@ EXPECT_THAT( response_system.request()->GetAddressResults().value().endpoints(), testing::ElementsAre(CreateExpected("192.168.0.5", 80))); + + EXPECT_THAT(response_secure.result_error(), IsOk()); } } @@ -5228,7 +5421,7 @@ // Clear DnsClient. The two in-progress jobs should fall back to a ProcTask, // and the next one should be started with a ProcTask. - resolver_->SetDnsClientEnabled(false); + resolver_->SetInsecureDnsClientEnabled(false); // All three in-progress requests should now be running a ProcTask. EXPECT_EQ(3u, num_running_dispatcher_jobs()); @@ -5249,7 +5442,7 @@ // DnsClient disabled should result in an error. TEST_F(HostResolverManagerDnsTest, DnsCallsWithDisabledDnsClient) { ChangeDnsConfig(CreateValidDnsConfig()); - resolver_->SetDnsClientEnabled(false); + resolver_->SetInsecureDnsClientEnabled(false); HostResolver::ResolveHostParameters params; params.source = HostResolverSource::DNS; @@ -5257,13 +5450,13 @@ HostPortPair("host", 80), NetLogWithSource(), params, request_context_.get(), host_cache_.get())); - EXPECT_THAT(response.result_error(), IsError(ERR_FAILED)); + EXPECT_THAT(response.result_error(), IsError(ERR_DNS_CACHE_MISS)); } TEST_F(HostResolverManagerDnsTest, DnsCallsWithDisabledDnsClient_DisabledAtConstruction) { HostResolver::ManagerOptions options = DefaultOptions(); - options.dns_client_enabled = false; + options.insecure_dns_client_enabled = false; CreateResolverWithOptionsAndParams(std::move(options), DefaultParams(proc_.get()), true /* ipv6_reachable */); @@ -5275,7 +5468,7 @@ HostPortPair("host", 80), NetLogWithSource(), params, request_context_.get(), host_cache_.get())); - EXPECT_THAT(response.result_error(), IsError(ERR_FAILED)); + EXPECT_THAT(response.result_error(), IsError(ERR_DNS_CACHE_MISS)); } // Same as DnsClient disabled, requests with source=DNS and no usable DnsConfig @@ -5289,7 +5482,7 @@ HostPortPair("host", 80), NetLogWithSource(), params, request_context_.get(), host_cache_.get())); - EXPECT_THAT(response.result_error(), IsError(ERR_FAILED)); + EXPECT_THAT(response.result_error(), IsError(ERR_DNS_CACHE_MISS)); } TEST_F(HostResolverManagerDnsTest, NoCheckIpv6OnWifi) { @@ -5741,6 +5934,7 @@ DnsConfigOverrides overrides; overrides.dns_over_https_servers.emplace( {DnsConfig::DnsOverHttpsServerConfig(server, true)}); + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; resolver_->SetDnsConfigOverrides(overrides); base::DictionaryValue* config; @@ -5763,6 +5957,8 @@ std::string server_template; EXPECT_TRUE(server_method->GetString("server_template", &server_template)); EXPECT_EQ(server_template, server); + EXPECT_EQ(config->FindKey("secure_dns_mode")->GetInt(), + static_cast<int>(DnsConfig::SecureDnsMode::AUTOMATIC)); } TEST_F(HostResolverManagerDnsTest, AddDnsOverHttpsServerBeforeConfig) { @@ -5773,6 +5969,7 @@ DnsConfigOverrides overrides; overrides.dns_over_https_servers.emplace( {DnsConfig::DnsOverHttpsServerConfig(server, true)}); + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; resolver_->SetDnsConfigOverrides(overrides); notifier.mock_network_change_notifier()->SetConnectionType( @@ -5799,6 +5996,8 @@ std::string server_template; EXPECT_TRUE(server_method->GetString("server_template", &server_template)); EXPECT_EQ(server_template, server); + EXPECT_EQ(config->FindKey("secure_dns_mode")->GetInt(), + static_cast<int>(DnsConfig::SecureDnsMode::AUTOMATIC)); } TEST_F(HostResolverManagerDnsTest, AddDnsOverHttpsServerBeforeClient) { @@ -5809,6 +6008,7 @@ DnsConfigOverrides overrides; overrides.dns_over_https_servers.emplace( {DnsConfig::DnsOverHttpsServerConfig(server, true)}); + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; resolver_->SetDnsConfigOverrides(overrides); notifier.mock_network_change_notifier()->SetConnectionType( @@ -5835,6 +6035,8 @@ std::string server_template; EXPECT_TRUE(server_method->GetString("server_template", &server_template)); EXPECT_EQ(server_template, server); + EXPECT_EQ(config->FindKey("secure_dns_mode")->GetInt(), + static_cast<int>(DnsConfig::SecureDnsMode::AUTOMATIC)); } TEST_F(HostResolverManagerDnsTest, AddDnsOverHttpsServerAndThenRemove) { @@ -5845,6 +6047,7 @@ DnsConfigOverrides overrides; overrides.dns_over_https_servers.emplace( {DnsConfig::DnsOverHttpsServerConfig(server, true)}); + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; resolver_->SetDnsConfigOverrides(overrides); notifier.mock_network_change_notifier()->SetConnectionType( @@ -5873,6 +6076,8 @@ std::string server_template; EXPECT_TRUE(server_method->GetString("server_template", &server_template)); EXPECT_EQ(server_template, server); + EXPECT_EQ(config->FindKey("secure_dns_mode")->GetInt(), + static_cast<int>(DnsConfig::SecureDnsMode::AUTOMATIC)); resolver_->SetDnsConfigOverrides(DnsConfigOverrides()); value = resolver_->GetDnsConfigAsValue(); @@ -5885,6 +6090,8 @@ if (!doh_servers) return; EXPECT_EQ(doh_servers->GetSize(), 0u); + EXPECT_EQ(config->FindKey("secure_dns_mode")->GetInt(), + static_cast<int>(DnsConfig::SecureDnsMode::OFF)); } TEST_F(HostResolverManagerDnsTest, SetDnsConfigOverrides) { @@ -6217,7 +6424,7 @@ } // Test system resolver is detected. - resolver_->SetDnsClientEnabled(false); + resolver_->SetInsecureDnsClientEnabled(false); ChangeDnsConfig(CreateValidDnsConfig()); EXPECT_EQ(resolver_->mode_for_histogram_, HostResolverManager::MODE_FOR_HISTOGRAM_SYSTEM); @@ -6274,6 +6481,20 @@ bar_records.begin(), bar_records.end())); } +TEST_F(HostResolverManagerDnsTest, TxtQuery_InvalidConfig) { + set_allow_fallback_to_proctask(false); + // Set empty DnsConfig. + ChangeDnsConfig(DnsConfig()); + + HostResolver::ResolveHostParameters parameters; + parameters.dns_query_type = DnsQueryType::TXT; + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair("host", 108), NetLogWithSource(), parameters, + request_context_.get(), host_cache_.get())); + EXPECT_THAT(response.result_error(), IsError(ERR_DNS_CACHE_MISS)); +} + TEST_F(HostResolverManagerDnsTest, TxtQuery_NonexistentDomain) { // Setup fallback to confirm it is not used for non-address results. set_allow_fallback_to_proctask(true);
diff --git a/net/http/http_auth_gssapi_posix.cc b/net/http/http_auth_gssapi_posix.cc index 4428629..f100b62 100644 --- a/net/http/http_auth_gssapi_posix.cc +++ b/net/http/http_auth_gssapi_posix.cc
@@ -18,10 +18,13 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_restrictions.h" -#include "net/base/hex_utils.h" +#include "base/values.h" #include "net/base/net_errors.h" #include "net/http/http_auth_gssapi_posix.h" #include "net/http/http_auth_multi_round_parse.h" +#include "net/log/net_log_event_type.h" +#include "net/log/net_log_values.h" +#include "net/log/net_log_with_source.h" #include "net/net_buildflags.h" namespace net { @@ -39,9 +42,6 @@ gss_OID CHROME_GSS_SPNEGO_MECH_OID_DESC = &CHROME_GSS_SPNEGO_MECH_OID_DESC_VAL; -// Debugging helpers. -namespace { - OM_uint32 DelegationTypeToFlag(DelegationType delegation_type) { switch (delegation_type) { case DelegationType::kNone: @@ -66,10 +66,9 @@ OM_uint32 minor_status = 0; OM_uint32 major_status = gssapi_lib_->release_buffer(&minor_status, buffer_); - if (major_status != GSS_S_COMPLETE) { - DLOG(WARNING) << "Problem releasing buffer. major=" << major_status - << ", minor=" << minor_status; - } + DLOG_IF(WARNING, major_status != GSS_S_COMPLETE) + << "Problem releasing buffer. major=" << major_status + << ", minor=" << minor_status; buffer_ = GSS_C_NO_BUFFER; } } @@ -94,9 +93,10 @@ OM_uint32 minor_status = 0; OM_uint32 major_status = gssapi_lib_->release_name(&minor_status, &name_); if (major_status != GSS_S_COMPLETE) { - DLOG(WARNING) << "Problem releasing name. " - << GetGssStatusValue(nullptr, "gss_release_name", - major_status, minor_status); + DLOG_IF(WARNING, major_status != GSS_S_COMPLETE) + << "Problem releasing name. " + << GetGssStatusValue(nullptr, "gss_release_name", major_status, + minor_status); } name_ = GSS_C_NO_NAME; } @@ -115,8 +115,6 @@ return 0 == memcmp(left->elements, right->elements, right->length); } -} // namespace - base::Value GetGssStatusCodeValue(GSSAPILibrary* gssapi_lib, OM_uint32 status, OM_uint32 status_code_type) { @@ -205,10 +203,9 @@ // Cap OID content at arbitrary limit 1k. constexpr OM_uint32 kMaxOidDataSize = 1024; - const base::StringPiece oid_contents(reinterpret_cast<char*>(oid->elements), - std::min(kMaxOidDataSize, oid->length)); - - params.SetStringKey("bytes", HexDump(oid_contents)); + params.SetKey( + "bytes", + NetLogBinaryValue(oid->elements, std::min(kMaxOidDataSize, oid->length))); // Based on RFC 2744 Appendix A. Hardcoding the OIDs in the list below to // avoid having a static dependency on the library. @@ -256,9 +253,9 @@ } auto name_string = base::StringPiece(reinterpret_cast<const char*>(name.value), name.length); - rv.SetStringKey("name", base::IsStringUTF8(name_string) - ? name_string - : HexDump(name_string)); + rv.SetKey("name", base::IsStringUTF8(name_string) + ? NetLogStringValue(name_string) + : NetLogBinaryValue(name.value, name.length)); rv.SetKey("type", OidToValue(name_type)); return rv; } @@ -315,6 +312,20 @@ return rv; } +namespace { + +// NetLogParametersCallback for the result of loading a library. +base::Value LibraryLoadResultCallback(base::StringPiece library_name, + base::StringPiece load_result) { + base::Value params{base::Value::Type::DICTIONARY}; + params.SetStringKey("library_name", library_name); + if (!load_result.empty()) + params.SetStringKey("load_result", load_result); + return params; +} + +} // namespace + GSSAPISharedLibrary::GSSAPISharedLibrary(const std::string& gssapi_library_name) : gssapi_library_name_(gssapi_library_name) {} @@ -325,24 +336,23 @@ } } -bool GSSAPISharedLibrary::Init() { +bool GSSAPISharedLibrary::Init(const NetLogWithSource& net_log) { if (!initialized_) - InitImpl(); + InitImpl(net_log); return initialized_; } -bool GSSAPISharedLibrary::InitImpl() { +bool GSSAPISharedLibrary::InitImpl(const NetLogWithSource& net_log) { DCHECK(!initialized_); -#if BUILDFLAG(DLOPEN_KERBEROS) - gssapi_library_ = LoadSharedLibrary(); + gssapi_library_ = LoadSharedLibrary(net_log); if (gssapi_library_ == nullptr) return false; -#endif // BUILDFLAG(DLOPEN_KERBEROS) initialized_ = true; return true; } -base::NativeLibrary GSSAPISharedLibrary::LoadSharedLibrary() { +base::NativeLibrary GSSAPISharedLibrary::LoadSharedLibrary( + const NetLogWithSource& net_log) { const char* const* library_names; size_t num_lib_names; const char* user_specified_library[1]; @@ -367,64 +377,104 @@ num_lib_names = base::size(kDefaultLibraryNames); } + net_log.BeginEvent(NetLogEventType::AUTH_LIBRARY_LOAD); + + // There has to be at least one candidate. + DCHECK_NE(0u, num_lib_names); + + const char* library_name = nullptr; + base::NativeLibraryLoadError load_error; + for (size_t i = 0; i < num_lib_names; ++i) { - const char* library_name = library_names[i]; + load_error = base::NativeLibraryLoadError(); + library_name = library_names[i]; base::FilePath file_path(library_name); // TODO(asanka): Move library loading to a separate thread. // http://crbug.com/66702 base::ThreadRestrictions::ScopedAllowIO allow_io_temporarily; - base::NativeLibraryLoadError load_error; base::NativeLibrary lib = base::LoadNativeLibrary(file_path, &load_error); if (lib) { - // Only return this library if we can bind the functions we need. - if (BindMethods(lib)) + if (BindMethods(lib, library_name, net_log)) { + net_log.EndEvent(NetLogEventType::AUTH_LIBRARY_LOAD, [&] { + return LibraryLoadResultCallback(library_name, ""); + }); return lib; + } base::UnloadNativeLibrary(lib); - } else { - // If this is the only library available, log the reason for failure. - DLOG_IF(WARNING, num_lib_names == 1) << load_error.ToString(); } } - DLOG(WARNING) << "Unable to find a compatible GSSAPI library"; + + // If loading failed, then log the result of the final attempt. Doing so + // is specially important on platforms where there's only one possible + // library. Doing so also always logs the failure when the GSSAPI library + // name is explicitly specified. + net_log.EndEvent(NetLogEventType::AUTH_LIBRARY_LOAD, [&] { + return LibraryLoadResultCallback(library_name, load_error.ToString()); + }); return nullptr; } -#if BUILDFLAG(DLOPEN_KERBEROS) - namespace { -template <typename T> -bool BindGssMethod(base::NativeLibrary lib, const char* method, T* receiver) { - *receiver = reinterpret_cast<T>( - base::GetFunctionPointerFromNativeLibrary(lib, method)); - if (*receiver == nullptr) { - DLOG(WARNING) << "Unable to bind function \"" << method << "\""; - return false; +base::Value BindFailureCallback(base::StringPiece library_name, + base::StringPiece method) { + base::Value params{base::Value::Type::DICTIONARY}; + params.SetStringKey("library_name", library_name); + params.SetStringKey("method", method); + return params; +} + +void* BindUntypedMethod(base::NativeLibrary lib, + base::StringPiece library_name, + base::StringPiece method, + const NetLogWithSource& net_log) { + void* ptr = base::GetFunctionPointerFromNativeLibrary(lib, method); + if (ptr == nullptr) { + std::string method_string = method.as_string(); + net_log.AddEvent(NetLogEventType::AUTH_LIBRARY_BIND_FAILED, + [&] { return BindFailureCallback(library_name, method); }); } - return true; + return ptr; +} + +template <typename T> +bool BindMethod(base::NativeLibrary lib, + base::StringPiece library_name, + base::StringPiece method, + T* receiver, + const NetLogWithSource& net_log) { + *receiver = reinterpret_cast<T>( + BindUntypedMethod(lib, library_name, method, net_log)); + return *receiver != nullptr; } } // namespace -bool GSSAPISharedLibrary::BindMethods(base::NativeLibrary lib) { - bool rv = true; - // It's unlikely for BindMethods() to fail if LoadNativeLibrary() succeeded. - // A failure in this function indicates an interoperability issue whose - // diagnosis requires knowing all the methods that are missing. Hence |rv| is +bool GSSAPISharedLibrary::BindMethods(base::NativeLibrary lib, + base::StringPiece name, + const NetLogWithSource& net_log) { + bool ok = true; + // It's unlikely for BindMethods() to fail if LoadNativeLibrary() succeeded. A + // failure in this function indicates an interoperability issue whose + // diagnosis requires knowing all the methods that are missing. Hence |ok| is // updated in a manner that prevents short-circuiting the BindGssMethod() // invocations. - rv = BindGssMethod(lib, "gss_delete_sec_context", &delete_sec_context_) && rv; - rv = BindGssMethod(lib, "gss_display_name", &display_name_) && rv; - rv = BindGssMethod(lib, "gss_display_status", &display_status_) && rv; - rv = BindGssMethod(lib, "gss_import_name", &import_name_) && rv; - rv = BindGssMethod(lib, "gss_init_sec_context", &init_sec_context_) && rv; - rv = BindGssMethod(lib, "gss_inquire_context", &inquire_context_) && rv; - rv = BindGssMethod(lib, "gss_release_buffer", &release_buffer_) && rv; - rv = BindGssMethod(lib, "gss_release_name", &release_name_) && rv; - rv = BindGssMethod(lib, "gss_wrap_size_limit", &wrap_size_limit_) && rv; + ok &= BindMethod(lib, name, "gss_delete_sec_context", &delete_sec_context_, + net_log); + ok &= BindMethod(lib, name, "gss_display_name", &display_name_, net_log); + ok &= BindMethod(lib, name, "gss_display_status", &display_status_, net_log); + ok &= BindMethod(lib, name, "gss_import_name", &import_name_, net_log); + ok &= BindMethod(lib, name, "gss_init_sec_context", &init_sec_context_, + net_log); + ok &= + BindMethod(lib, name, "gss_inquire_context", &inquire_context_, net_log); + ok &= BindMethod(lib, name, "gss_release_buffer", &release_buffer_, net_log); + ok &= BindMethod(lib, name, "gss_release_name", &release_name_, net_log); + ok &= + BindMethod(lib, name, "gss_wrap_size_limit", &wrap_size_limit_, net_log); - if (LIKELY(rv)) + if (LIKELY(ok)) return true; delete_sec_context_ = nullptr; @@ -439,24 +489,6 @@ return false; } -#else // DLOPEN_KERBEROS - -bool GSSAPISharedLibrary::BindMethods(base::NativeLibrary lib) { - // When not using dlopen(), statically bind to libgssapi methods. - import_name_ = gss_import_name; - release_name_ = gss_release_name; - release_buffer_ = gss_release_buffer; - display_name_ = gss_display_name; - display_status_ = gss_display_status; - init_sec_context_ = gss_init_sec_context; - wrap_size_limit_ = gss_wrap_size_limit; - delete_sec_context_ = gss_delete_sec_context; - inquire_context_ = gss_inquire_context; - return true; -} - -#endif // DLOPEN_KERBEROS - OM_uint32 GSSAPISharedLibrary::import_name( OM_uint32* minor_status, const gss_buffer_t input_name_buffer, @@ -603,11 +635,10 @@ OM_uint32 minor_status = 0; OM_uint32 major_status = gssapi_lib_->delete_sec_context( &minor_status, &security_context_, &output_token); - if (major_status != GSS_S_COMPLETE) { - LOG(WARNING) << "Problem releasing security_context. " - << GetGssStatusValue(gssapi_lib_, "gss_delete_sec_context", - major_status, minor_status); - } + DLOG_IF(WARNING, major_status != GSS_S_COMPLETE) + << "Problem releasing security_context. " + << GetGssStatusValue(gssapi_lib_, "delete_sec_context", major_status, + minor_status); security_context_ = GSS_C_NO_CONTEXT; } } @@ -624,10 +655,10 @@ HttpAuthGSSAPI::~HttpAuthGSSAPI() = default; -bool HttpAuthGSSAPI::Init() { +bool HttpAuthGSSAPI::Init(const NetLogWithSource& net_log) { if (!library_) return false; - return library_->Init(); + return library_->Init(net_log); } bool HttpAuthGSSAPI::NeedsIdentity() const { @@ -656,6 +687,7 @@ const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const NetLogWithSource& net_log, CompletionOnceCallback /*callback*/) { DCHECK(auth_token); @@ -666,8 +698,8 @@ : nullptr; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; ScopedBuffer scoped_output_token(&output_token, library_); - int rv = - GetNextSecurityToken(spn, channel_bindings, &input_token, &output_token); + int rv = GetNextSecurityToken(spn, channel_bindings, &input_token, + &output_token, net_log); if (rv != OK) return rv; @@ -680,7 +712,6 @@ return OK; } - namespace { // GSSAPI status codes consist of a calling error (essentially, a programmer @@ -689,7 +720,6 @@ // This means a simple switch on the return codes is not sufficient. int MapImportNameStatusToError(OM_uint32 major_status) { - VLOG(1) << "import_name returned 0x" << std::hex << major_status; if (major_status == GSS_S_COMPLETE) return OK; if (GSS_CALLING_ERROR(major_status) != 0) @@ -716,7 +746,6 @@ } int MapInitSecContextStatusToError(OM_uint32 major_status) { - VLOG(1) << "init_sec_context returned 0x" << std::hex << major_status; // Although GSS_S_CONTINUE_NEEDED is an additional bit, it seems like // other code just checks if major_status is equivalent to it to indicate // that there are no other errors included. @@ -772,12 +801,38 @@ return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS; } +base::Value ImportNameErrorCallback(GSSAPILibrary* library, + base::StringPiece spn, + OM_uint32 major_status, + OM_uint32 minor_status) { + base::Value params{base::Value::Type::DICTIONARY}; + params.SetStringKey("spn", spn); + if (major_status != GSS_S_COMPLETE) + params.SetKey("status", GetGssStatusValue(library, "import_name", + major_status, minor_status)); + return params; +} + +base::Value InitSecContextErrorCallback(GSSAPILibrary* library, + gss_ctx_id_t context, + OM_uint32 major_status, + OM_uint32 minor_status) { + base::Value params{base::Value::Type::DICTIONARY}; + if (major_status != GSS_S_COMPLETE) + params.SetKey("status", GetGssStatusValue(library, "gss_init_sec_context", + major_status, minor_status)); + if (context != GSS_C_NO_CONTEXT) + params.SetKey("context", GetContextStateAsValue(library, context)); + return params; +} + } // anonymous namespace int HttpAuthGSSAPI::GetNextSecurityToken(const std::string& spn, const std::string& channel_bindings, gss_buffer_t in_token, - gss_buffer_t out_token) { + gss_buffer_t out_token, + const NetLogWithSource& net_log) { // GSSAPI header files, to this day, require OIDs passed in as non-const // pointers. Rather than const casting, let's just leave this as non-const. // Even if the OID pointer is const, the inner |elements| pointer is still @@ -793,38 +848,33 @@ spn_buffer.length = spn_principal.size() + 1; OM_uint32 minor_status = 0; gss_name_t principal_name = GSS_C_NO_NAME; + OM_uint32 major_status = library_->import_name(&minor_status, &spn_buffer, &kGSS_C_NT_HOSTBASED_SERVICE, &principal_name); + net_log.AddEvent(NetLogEventType::AUTH_LIBRARY_IMPORT_NAME, [&] { + return ImportNameErrorCallback(library_, spn, major_status, minor_status); + }); int rv = MapImportNameStatusToError(major_status); - if (rv != OK) { - LOG(ERROR) << "Problem importing name from " - << "spn \"" << spn_principal << "\"\n" - << GetGssStatusValue(library_, "gss_import_name", major_status, - minor_status); + if (rv != OK) return rv; - } ScopedName scoped_name(principal_name, library_); // Continue creating a security context. - OM_uint32 req_flags = DelegationTypeToFlag(delegation_type_); + net_log.BeginEvent(NetLogEventType::AUTH_LIBRARY_INIT_SEC_CTX); major_status = library_->init_sec_context( &minor_status, GSS_C_NO_CREDENTIAL, scoped_sec_context_.receive(), - principal_name, gss_oid_, req_flags, GSS_C_INDEFINITE, - GSS_C_NO_CHANNEL_BINDINGS, in_token, + principal_name, gss_oid_, DelegationTypeToFlag(delegation_type_), + GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, in_token, nullptr, // actual_mech_type out_token, nullptr, // ret flags nullptr); - rv = MapInitSecContextStatusToError(major_status); - if (rv != OK) { - LOG(ERROR) << "Problem initializing context. \n" - << GetGssStatusValue(library_, "gss_init_sec_context", - major_status, minor_status) - << '\n' - << GetContextStateAsValue(library_, scoped_sec_context_.get()); - } - return rv; + net_log.EndEvent(NetLogEventType::AUTH_LIBRARY_INIT_SEC_CTX, [&] { + return InitSecContextErrorCallback(library_, scoped_sec_context_.get(), + major_status, minor_status); + }); + return MapInitSecContextStatusToError(major_status); } } // namespace net
diff --git a/net/http/http_auth_gssapi_posix.h b/net/http/http_auth_gssapi_posix.h index c0966e9..c118e5b 100644 --- a/net/http/http_auth_gssapi_posix.h +++ b/net/http/http_auth_gssapi_posix.h
@@ -43,7 +43,7 @@ // Initializes the library, including any necessary dynamic libraries. // This is done separately from construction (which happens at startup time) // in order to delay work until the class is actually needed. - virtual bool Init() = 0; + virtual bool Init(const NetLogWithSource& net_log) = 0; // These methods match the ones in the GSSAPI library. virtual OM_uint32 import_name( @@ -116,7 +116,7 @@ ~GSSAPISharedLibrary() override; // GSSAPILibrary methods: - bool Init() override; + bool Init(const NetLogWithSource& net_log) override; OM_uint32 import_name(OM_uint32* minor_status, const gss_buffer_t input_name_buffer, const gss_OID input_name_type, @@ -171,12 +171,14 @@ private: FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup); - bool InitImpl(); + bool InitImpl(const NetLogWithSource& net_log); // Finds a usable dynamic library for GSSAPI and loads it. The criteria are: // 1. The library must exist. // 2. The library must export the functions we need. - base::NativeLibrary LoadSharedLibrary(); - bool BindMethods(base::NativeLibrary lib); + base::NativeLibrary LoadSharedLibrary(const NetLogWithSource& net_log); + bool BindMethods(base::NativeLibrary lib, + base::StringPiece library_name, + const NetLogWithSource& net_log); bool initialized_ = false; @@ -207,7 +209,7 @@ gss_ctx_id_t* receive() { return &security_context_; } private: - gss_ctx_id_t security_context_; + gss_ctx_id_t security_context_ = GSS_C_NO_CONTEXT; GSSAPILibrary* gssapi_lib_; DISALLOW_COPY_AND_ASSIGN(ScopedSecurityContext); @@ -223,7 +225,7 @@ ~HttpAuthGSSAPI() override; // HttpNegotiateAuthSystem implementation: - bool Init() override; + bool Init(const NetLogWithSource& net_log) override; bool NeedsIdentity() const override; bool AllowsExplicitCredentials() const override; HttpAuth::AuthorizationResult ParseChallenge( @@ -232,6 +234,7 @@ const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const NetLogWithSource& net_log, CompletionOnceCallback callback) override; void SetDelegation(HttpAuth::DelegationType delegation_type) override; @@ -239,7 +242,8 @@ int GetNextSecurityToken(const std::string& spn, const std::string& channel_bindings, gss_buffer_t in_token, - gss_buffer_t out_token); + gss_buffer_t out_token, + const NetLogWithSource& net_log); std::string scheme_; gss_OID gss_oid_;
diff --git a/net/http/http_auth_gssapi_posix_unittest.cc b/net/http/http_auth_gssapi_posix_unittest.cc index c9b277c9..be8f549 100644 --- a/net/http/http_auth_gssapi_posix_unittest.cc +++ b/net/http/http_auth_gssapi_posix_unittest.cc
@@ -16,6 +16,9 @@ #include "net/base/net_errors.h" #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/mock_gssapi_library_posix.h" +#include "net/log/net_log_with_source.h" +#include "net/log/test_net_log.h" +#include "net/log/test_net_log_util.h" #include "net/net_buildflags.h" #include "testing/gtest/include/gtest/gtest.h" @@ -86,31 +89,74 @@ } // namespace TEST(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup) { + BoundTestNetLog log; // TODO(ahendrickson): Manipulate the libraries and paths to test each of the // libraries we expect, and also whether or not they have the interface // functions we want. std::unique_ptr<GSSAPILibrary> gssapi(new GSSAPISharedLibrary(std::string())); DCHECK(gssapi.get()); - EXPECT_TRUE(gssapi.get()->Init()); + EXPECT_TRUE(gssapi.get()->Init(log.bound())); + + // Should've logged a AUTH_LIBRARY_LOAD event, but not + // AUTH_LIBRARY_BIND_FAILED. + auto entries = log.GetEntries(); + auto offset = ExpectLogContainsSomewhere( + entries, 0u, NetLogEventType::AUTH_LIBRARY_LOAD, NetLogEventPhase::BEGIN); + offset = ExpectLogContainsSomewhereAfter(entries, offset, + NetLogEventType::AUTH_LIBRARY_LOAD, + NetLogEventPhase::END); + ASSERT_LT(offset, entries.size()); + + auto& entry = entries[offset]; + const std::string* library_name = entry.params.FindStringKey("library_name"); + const std::string* load_result = entry.params.FindStringPath("load_result"); + ASSERT_TRUE(library_name); + EXPECT_FALSE(library_name->empty()); + EXPECT_FALSE(load_result); // No load_result since it succeeded. } -#if BUILDFLAG(DLOPEN_KERBEROS) TEST(HttpAuthGSSAPIPOSIXTest, CustomLibraryMissing) { + BoundTestNetLog log; + std::unique_ptr<GSSAPILibrary> gssapi( new GSSAPISharedLibrary("/this/library/does/not/exist")); - EXPECT_FALSE(gssapi.get()->Init()); + EXPECT_FALSE(gssapi.get()->Init(log.bound())); + + auto entries = log.GetEntries(); + auto offset = ExpectLogContainsSomewhere( + entries, 0, NetLogEventType::AUTH_LIBRARY_LOAD, NetLogEventPhase::END); + ASSERT_LT(offset, entries.size()); + + auto& entry = entries[offset]; + const std::string* load_result = entry.params.FindStringKey("load_result"); + ASSERT_TRUE(load_result); + EXPECT_FALSE(load_result->empty()); } TEST(HttpAuthGSSAPIPOSIXTest, CustomLibraryExists) { + BoundTestNetLog log; base::FilePath module; ASSERT_TRUE(base::PathService::Get(base::DIR_MODULE, &module)); auto basename = base::GetNativeLibraryName("test_gssapi"); module = module.AppendASCII(basename); auto gssapi = std::make_unique<GSSAPISharedLibrary>(module.value()); - EXPECT_TRUE(gssapi.get()->Init()); + EXPECT_TRUE(gssapi.get()->Init(log.bound())); + + auto entries = log.GetEntries(); + auto offset = ExpectLogContainsSomewhere( + entries, 0, NetLogEventType::AUTH_LIBRARY_LOAD, NetLogEventPhase::END); + ASSERT_LT(offset, entries.size()); + + auto& entry = entries[offset]; + const std::string* load_result = entry.params.FindStringKey("load_result"); + const std::string* library_name = entry.params.FindStringKey("library_name"); + EXPECT_FALSE(load_result); + ASSERT_TRUE(library_name); + EXPECT_EQ(*library_name, module.AsUTF8Unsafe()); } TEST(HttpAuthGSSAPIPOSIXTest, CustomLibraryMethodsMissing) { + BoundTestNetLog log; base::FilePath module; ASSERT_TRUE(base::PathService::Get(base::DIR_MODULE, &module)); auto basename = base::GetNativeLibraryName("test_badgssapi"); @@ -125,19 +171,25 @@ // // To resolve this issue, make sure that //net:test_badgssapi target in // //net/BUILD.gn should have an empty `deps` and an empty `libs`. - EXPECT_FALSE(gssapi.get()->Init()); + EXPECT_FALSE(gssapi.get()->Init(log.bound())); - // Logs something like "gss_import_name" during loading process. - // TODO(asanka): Once GSSAPI library loading starts emitting NetLogs verify - // that the missing method is correctly identified. + auto entries = log.GetEntries(); + auto offset = ExpectLogContainsSomewhere( + entries, 0, NetLogEventType::AUTH_LIBRARY_BIND_FAILED, + NetLogEventPhase::NONE); + ASSERT_LT(offset, entries.size()); + + auto& entry = entries[offset]; + const std::string* method = entry.params.FindStringKey("method"); + ASSERT_TRUE(method); + EXPECT_EQ(*method, "gss_import_name"); } -#endif // DLOPEN_KERBEROS TEST(HttpAuthGSSAPIPOSIXTest, GSSAPICycle) { std::unique_ptr<test::MockGSSAPILibrary> mock_library( new test::MockGSSAPILibrary); DCHECK(mock_library.get()); - mock_library->Init(); + mock_library->Init(NetLogWithSource()); const char kAuthResponse[] = "Mary had a little lamb"; test::GssContextMockImpl context1( "localhost", // Source name @@ -233,6 +285,7 @@ } TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) { + BoundTestNetLog log; // The first round should just have "Negotiate", and the second round should // have a valid base64 token associated with it. test::MockGSSAPILibrary mock_library; @@ -247,15 +300,30 @@ // Generate an auth token and create another thing. EstablishInitialContext(&mock_library); std::string auth_token; - EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken( - nullptr, "HTTP/intranet.google.com", std::string(), - &auth_token, base::BindOnce(&UnexpectedCallback))); + EXPECT_EQ( + OK, auth_gssapi.GenerateAuthToken(nullptr, "HTTP/intranet.google.com", + std::string(), &auth_token, log.bound(), + base::BindOnce(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate Zm9vYmFy"; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), second_challenge_text.end()); EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, auth_gssapi.ParseChallenge(&second_challenge)); + + auto entries = log.GetEntries(); + auto offset = ExpectLogContainsSomewhere( + entries, 0, NetLogEventType::AUTH_LIBRARY_INIT_SEC_CTX, + NetLogEventPhase::END); + // There should be two of these. + offset = ExpectLogContainsSomewhere( + entries, offset, NetLogEventType::AUTH_LIBRARY_INIT_SEC_CTX, + NetLogEventPhase::END); + ASSERT_LT(offset, entries.size()); + const std::string* source = + entries[offset].params.FindStringPath("context.source.name"); + ASSERT_TRUE(source); + EXPECT_EQ("localhost", *source); } TEST(HttpAuthGSSAPITest, ParseChallenge_UnexpectedTokenFirstRound) { @@ -285,9 +353,10 @@ EstablishInitialContext(&mock_library); std::string auth_token; - EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken( - nullptr, "HTTP/intranet.google.com", std::string(), - &auth_token, base::BindOnce(&UnexpectedCallback))); + EXPECT_EQ(OK, + auth_gssapi.GenerateAuthToken( + nullptr, "HTTP/intranet.google.com", std::string(), &auth_token, + NetLogWithSource(), base::BindOnce(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate"; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), second_challenge_text.end()); @@ -309,9 +378,10 @@ EstablishInitialContext(&mock_library); std::string auth_token; - EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken( - nullptr, "HTTP/intranet.google.com", std::string(), - &auth_token, base::BindOnce(&UnexpectedCallback))); + EXPECT_EQ(OK, + auth_gssapi.GenerateAuthToken( + nullptr, "HTTP/intranet.google.com", std::string(), &auth_token, + NetLogWithSource(), base::BindOnce(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate =happyjoy="; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), second_challenge_text.end()); @@ -334,7 +404,7 @@ { "oid" : "GSS_C_NT_ANONYMOUS", "length": 6, - "bytes" : "0x0000: 2b06 0105 0603 +.....\n" + "bytes" : "KwYBBQYD" } )"); ASSERT_TRUE(expected.has_value()); @@ -347,7 +417,7 @@ auto expected = base::JSONReader::Read(R"( { "length": 6, - "bytes" : "0x0000: 2b06 0105 0605 +.....\n" + "bytes" : "KwYBBQYF" } )"); ASSERT_TRUE(expected.has_value());
diff --git a/net/http/http_auth_handler_factory.cc b/net/http/http_auth_handler_factory.cc index d3242e0..9961e044 100644 --- a/net/http/http_auth_handler_factory.cc +++ b/net/http/http_auth_handler_factory.cc
@@ -103,8 +103,7 @@ std::unique_ptr<HttpAuthHandlerRegistryFactory> HttpAuthHandlerFactory::CreateDefault( const HttpAuthPreferences* prefs -#if (defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)) || \ - defined(OS_FUCHSIA) +#if BUILDFLAG(USE_EXTERNAL_GSSAPI) , const std::string& gssapi_library_name #endif @@ -116,7 +115,7 @@ std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes), std::end(kDefaultAuthSchemes)); return HttpAuthHandlerRegistryFactory::Create(prefs, auth_types -#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#if BUILDFLAG(USE_EXTERNAL_GSSAPI) , gssapi_library_name #endif @@ -132,8 +131,7 @@ HttpAuthHandlerRegistryFactory::Create( const HttpAuthPreferences* prefs, const std::vector<std::string>& auth_schemes -#if (defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)) || \ - defined(OS_FUCHSIA) +#if BUILDFLAG(USE_EXTERNAL_GSSAPI) , const std::string& gssapi_library_name #endif @@ -172,11 +170,9 @@ new HttpAuthHandlerNegotiate::Factory(negotiate_auth_system_factory); #if defined(OS_WIN) negotiate_factory->set_library(std::make_unique<SSPILibraryDefault>()); -#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#elif BUILDFLAG(USE_EXTERNAL_GSSAPI) negotiate_factory->set_library( std::make_unique<GSSAPISharedLibrary>(gssapi_library_name)); -#elif defined(OS_CHROMEOS) - negotiate_factory->set_library(std::make_unique<GSSAPISharedLibrary>("")); #endif registry_factory->RegisterSchemeFactory(kNegotiateAuthScheme, negotiate_factory);
diff --git a/net/http/http_auth_handler_factory.h b/net/http/http_auth_handler_factory.h index d7215cc1..f4f985e3 100644 --- a/net/http/http_auth_handler_factory.h +++ b/net/http/http_auth_handler_factory.h
@@ -141,8 +141,7 @@ // used by the Negotiate authentication handler. static std::unique_ptr<HttpAuthHandlerRegistryFactory> CreateDefault( const HttpAuthPreferences* prefs = nullptr -#if (defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)) || \ - defined(OS_FUCHSIA) +#if BUILDFLAG(USE_EXTERNAL_GSSAPI) , const std::string& gssapi_library_name = "" #endif @@ -204,8 +203,7 @@ static std::unique_ptr<HttpAuthHandlerRegistryFactory> Create( const HttpAuthPreferences* prefs, const std::vector<std::string>& auth_schemes -#if (defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)) || \ - defined(OS_FUCHSIA) +#if BUILDFLAG(USE_EXTERNAL_GSSAPI) , const std::string& gssapi_library_name = "" #endif
diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc index 4ca1a27..83e8872 100644 --- a/net/http/http_auth_handler_negotiate.cc +++ b/net/http/http_auth_handler_negotiate.cc
@@ -131,7 +131,7 @@ if (!http_auth_preferences()->AllowGssapiLibraryLoad()) return ERR_UNSUPPORTED_AUTH_SCHEME; #endif - if (!auth_library_->Init()) { + if (!auth_library_->Init(net_log)) { is_unsupported_ = true; return ERR_UNSUPPORTED_AUTH_SCHEME; } @@ -185,7 +185,7 @@ bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge, const SSLInfo& ssl_info) { #if defined(OS_POSIX) - if (!auth_system_->Init()) { + if (!auth_system_->Init(net_log())) { VLOG(1) << "can't initialize GSSAPI library"; return false; } @@ -387,7 +387,7 @@ next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; AuthCredentials* credentials = has_credentials_ ? &credentials_ : nullptr; return auth_system_->GenerateAuthToken( - credentials, spn_, channel_bindings_, auth_token_, + credentials, spn_, channel_bindings_, auth_token_, net_log(), base::BindOnce(&HttpAuthHandlerNegotiate::OnIOComplete, base::Unretained(this))); }
diff --git a/net/http/http_auth_handler_negotiate_unittest.cc b/net/http/http_auth_handler_negotiate_unittest.cc index 1a85397..e4111c8a 100644 --- a/net/http/http_auth_handler_negotiate_unittest.cc +++ b/net/http/http_auth_handler_negotiate_unittest.cc
@@ -26,12 +26,18 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +#if !BUILDFLAG(USE_KERBEROS) +#error "use_kerberos should be true to use Negotiate authentication scheme." +#endif + #if defined(OS_ANDROID) #include "net/android/dummy_spnego_authenticator.h" #elif defined(OS_WIN) #include "net/http/mock_sspi_library_win.h" -#elif defined(OS_POSIX) +#elif BUILDFLAG(USE_EXTERNAL_GSSAPI) #include "net/http/mock_gssapi_library_posix.h" +#else +#error "use_kerberos is true, but no Kerberos implementation available." #endif using net::test::IsError; @@ -41,14 +47,6 @@ constexpr char kFakeToken[] = "FakeToken"; -#if defined(OS_ANDROID) -typedef net::android::DummySpnegoAuthenticator MockAuthLibrary; -#elif defined(OS_WIN) -typedef MockSSPILibrary MockAuthLibrary; -#elif defined(OS_POSIX) -typedef test::MockGSSAPILibrary MockAuthLibrary; -#endif - class HttpAuthHandlerNegotiateTest : public PlatformTest, public WithScopedTaskEnvironment { public: @@ -66,10 +64,9 @@ http_auth_preferences_->set_auth_android_negotiate_account_type( "org.chromium.test.DummySpnegoAuthenticator"); MockAuthLibrary::EnsureTestAccountExists(); -#endif -#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_ANDROID)) +#else factory_->set_library(base::WrapUnique(auth_library_)); -#endif +#endif // !OS_ANDROID } #if defined(OS_ANDROID) @@ -83,7 +80,7 @@ security_package_->cbMaxToken = 1337; mock_library->ExpectQuerySecurityPackageInfo( L"Negotiate", SEC_E_OK, security_package_.get()); -#elif defined(OS_POSIX) +#else // Copied from an actual transaction! static const char kAuthResponse[] = "\x60\x82\x02\xCA\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x01" @@ -172,7 +169,7 @@ queries[i].expected_input_token, queries[i].output_token); } -#endif // defined(OS_POSIX) +#endif // !OS_WIN } #if defined(OS_POSIX) @@ -203,7 +200,6 @@ query.expected_input_token, query.output_token); } - #endif // defined(OS_POSIX) int CreateHandler(bool disable_cname_lookup, @@ -268,7 +264,7 @@ nullptr, &request_info, callback.callback(), &token))); #if defined(OS_WIN) EXPECT_EQ("HTTP/alias", auth_handler->spn_for_testing()); -#elif defined(OS_POSIX) +#else EXPECT_EQ("HTTP@alias", auth_handler->spn_for_testing()); #endif } @@ -286,7 +282,7 @@ nullptr, &request_info, callback.callback(), &token))); #if defined(OS_WIN) EXPECT_EQ("HTTP/alias", auth_handler->spn_for_testing()); -#elif defined(OS_POSIX) +#else EXPECT_EQ("HTTP@alias", auth_handler->spn_for_testing()); #endif } @@ -304,7 +300,7 @@ nullptr, &request_info, callback.callback(), &token))); #if defined(OS_WIN) EXPECT_EQ("HTTP/alias:500", auth_handler->spn_for_testing()); -#elif defined(OS_POSIX) +#else EXPECT_EQ("HTTP@alias:500", auth_handler->spn_for_testing()); #endif } @@ -322,7 +318,7 @@ nullptr, &request_info, callback.callback(), &token))); #if defined(OS_WIN) EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn_for_testing()); -#elif defined(OS_POSIX) +#else EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn_for_testing()); #endif } @@ -342,7 +338,7 @@ EXPECT_THAT(callback.WaitForResult(), IsOk()); #if defined(OS_WIN) EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn_for_testing()); -#elif defined(OS_POSIX) +#else EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn_for_testing()); #endif } @@ -383,7 +379,7 @@ EXPECT_THAT(callback.WaitForResult(), IsError(ERR_MISSING_AUTH_CREDENTIALS)); } -#if BUILDFLAG(DLOPEN_KERBEROS) +#if BUILDFLAG(USE_EXTERNAL_GSSAPI) TEST_F(HttpAuthHandlerNegotiateTest, MissingGSSAPI) { MockAllowHttpAuthPreferences http_auth_preferences; std::unique_ptr<HttpAuthHandlerNegotiate::Factory> negotiate_factory( @@ -401,7 +397,7 @@ EXPECT_THAT(rv, IsError(ERR_UNSUPPORTED_AUTH_SCHEME)); EXPECT_TRUE(generic_handler.get() == nullptr); } -#endif // BUILDFLAG(DLOPEN_KERBEROS) +#endif // BUILDFLAG(USE_EXTERNAL_GSSAPI) // AllowGssapiLibraryLoad() is only supported on Chrome OS. #if defined(OS_CHROMEOS) @@ -430,7 +426,7 @@ ~TestAuthSystem() override = default; // HttpNegotiateAuthSystem implementation: - bool Init() override { return true; } + bool Init(const NetLogWithSource&) override { return true; } bool NeedsIdentity() const override { return true; } bool AllowsExplicitCredentials() const override { return true; } @@ -443,6 +439,7 @@ const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const NetLogWithSource& net_log, net::CompletionOnceCallback callback) override { *auth_token = kFakeToken; return net::OK;
diff --git a/net/http/http_auth_handler_ntlm.cc b/net/http/http_auth_handler_ntlm.cc index 926f62c..5dd7093 100644 --- a/net/http/http_auth_handler_ntlm.cc +++ b/net/http/http_auth_handler_ntlm.cc
@@ -41,7 +41,7 @@ std::string* auth_token) { #if defined(NTLM_SSPI) return auth_sspi_.GenerateAuthToken(credentials, CreateSPN(origin_), - channel_bindings_, auth_token, + channel_bindings_, auth_token, net_log(), std::move(callback)); #else // !defined(NTLM_SSPI) // TODO(cbentzel): Shouldn't be hitting this case.
diff --git a/net/http/http_auth_sspi_win.cc b/net/http/http_auth_sspi_win.cc index d9c098f..8bc2665 100644 --- a/net/http/http_auth_sspi_win.cc +++ b/net/http/http_auth_sspi_win.cc
@@ -263,7 +263,7 @@ } } -bool HttpAuthSSPI::Init() { +bool HttpAuthSSPI::Init(const NetLogWithSource&) { return true; } @@ -300,6 +300,7 @@ const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const NetLogWithSource&, CompletionOnceCallback /*callback*/) { // Initial challenge. if (!SecIsValidHandle(&cred_)) {
diff --git a/net/http/http_auth_sspi_win.h b/net/http/http_auth_sspi_win.h index e672c89f..408ac59 100644 --- a/net/http/http_auth_sspi_win.h +++ b/net/http/http_auth_sspi_win.h
@@ -116,7 +116,7 @@ ~HttpAuthSSPI() override; // HttpNegotiateAuthSystem implementation: - bool Init() override; + bool Init(const NetLogWithSource& net_log) override; bool NeedsIdentity() const override; bool AllowsExplicitCredentials() const override; HttpAuth::AuthorizationResult ParseChallenge( @@ -125,6 +125,7 @@ const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const NetLogWithSource& net_log, CompletionOnceCallback callback) override; void SetDelegation(HttpAuth::DelegationType delegation_type) override;
diff --git a/net/http/http_auth_sspi_win_unittest.cc b/net/http/http_auth_sspi_win_unittest.cc index 3c42767..d9031fa7 100644 --- a/net/http/http_auth_sspi_win_unittest.cc +++ b/net/http/http_auth_sspi_win_unittest.cc
@@ -3,10 +3,12 @@ // found in the LICENSE file. #include "net/http/http_auth_sspi_win.h" + #include "base/bind.h" #include "net/base/net_errors.h" #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/mock_sspi_library_win.h" +#include "net/log/net_log_with_source.h" #include "net/test/gtest_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -96,9 +98,10 @@ // Generate an auth token and create another thing. std::string auth_token; - EXPECT_EQ(OK, auth_sspi.GenerateAuthToken( - nullptr, "HTTP/intranet.google.com", std::string(), - &auth_token, base::BindOnce(&UnexpectedCallback))); + EXPECT_EQ(OK, + auth_sspi.GenerateAuthToken( + nullptr, "HTTP/intranet.google.com", std::string(), &auth_token, + NetLogWithSource(), base::BindOnce(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate Zm9vYmFy"; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), @@ -133,9 +136,10 @@ auth_sspi.ParseChallenge(&first_challenge)); std::string auth_token; - EXPECT_EQ(OK, auth_sspi.GenerateAuthToken( - nullptr, "HTTP/intranet.google.com", std::string(), - &auth_token, base::BindOnce(&UnexpectedCallback))); + EXPECT_EQ(OK, + auth_sspi.GenerateAuthToken( + nullptr, "HTTP/intranet.google.com", std::string(), &auth_token, + NetLogWithSource(), base::BindOnce(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate"; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), second_challenge_text.end()); @@ -156,9 +160,10 @@ auth_sspi.ParseChallenge(&first_challenge)); std::string auth_token; - EXPECT_EQ(OK, auth_sspi.GenerateAuthToken( - nullptr, "HTTP/intranet.google.com", std::string(), - &auth_token, base::BindOnce(&UnexpectedCallback))); + EXPECT_EQ(OK, + auth_sspi.GenerateAuthToken( + nullptr, "HTTP/intranet.google.com", std::string(), &auth_token, + NetLogWithSource(), base::BindOnce(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate =happyjoy="; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), second_challenge_text.end());
diff --git a/net/http/http_negotiate_auth_system.h b/net/http/http_negotiate_auth_system.h index cf90cd6..15dcc6c4 100644 --- a/net/http/http_negotiate_auth_system.h +++ b/net/http/http_negotiate_auth_system.h
@@ -13,12 +13,13 @@ class AuthCredentials; class HttpAuthChallengeTokenizer; +class NetLogWithSource; class NET_EXPORT_PRIVATE HttpNegotiateAuthSystem { public: virtual ~HttpNegotiateAuthSystem() = default; - virtual bool Init() = 0; + virtual bool Init(const NetLogWithSource& net_log) = 0; // True if authentication needs the identity of the user from Chrome. virtual bool NeedsIdentity() const = 0; @@ -57,6 +58,7 @@ const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const NetLogWithSource& net_log, CompletionOnceCallback callback) = 0; // Sets the delegation type allowed on the Kerberos ticket. This allows
diff --git a/net/http/mock_gssapi_library_posix.cc b/net/http/mock_gssapi_library_posix.cc index 6766602..e492bd99 100644 --- a/net/http/mock_gssapi_library_posix.cc +++ b/net/http/mock_gssapi_library_posix.cc
@@ -253,7 +253,7 @@ expected_security_queries_.push_back(security_query); } -bool MockGSSAPILibrary::Init() { +bool MockGSSAPILibrary::Init(const NetLogWithSource&) { return true; }
diff --git a/net/http/mock_gssapi_library_posix.h b/net/http/mock_gssapi_library_posix.h index 9ed109b..d04ca82 100644 --- a/net/http/mock_gssapi_library_posix.h +++ b/net/http/mock_gssapi_library_posix.h
@@ -113,7 +113,7 @@ // Initializes the library, including any necessary dynamic libraries. // This is done separately from construction (which happens at startup time) // in order to delay work until the class is actually needed. - bool Init() override; + bool Init(const NetLogWithSource& net_log) override; // These methods match the ones in the GSSAPI library. OM_uint32 import_name(OM_uint32* minor_status, @@ -203,6 +203,8 @@ } // namespace test +using MockAuthLibrary = test::MockGSSAPILibrary; + } // namespace net #endif // NET_HTTP_MOCK_GSSAPI_LIBRARY_POSIX_H_
diff --git a/net/http/mock_sspi_library_win.h b/net/http/mock_sspi_library_win.h index b042ebf..c0b7692 100644 --- a/net/http/mock_sspi_library_win.h +++ b/net/http/mock_sspi_library_win.h
@@ -106,6 +106,8 @@ std::set<PSecPkgInfoW> expected_freed_packages_; }; +using MockAuthLibrary = MockSSPILibrary; + } // namespace net #endif // NET_HTTP_MOCK_SSPI_LIBRARY_WIN_H_
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h index 6bf9428d..b6db4a7 100644 --- a/net/log/net_log_event_type_list.h +++ b/net/log/net_log_event_type_list.h
@@ -2169,6 +2169,79 @@ // ------------------------------------------------------------------------ // HTTP Authentication // ------------------------------------------------------------------------ +// +// Structure of common GSSAPI / SSPI values. +// ----------------------------------------- +// For convenience some structured GSSAPI/SSPI values are serialized +// consistently across different events. They are explained below. +// +// ** GSSAPI Status: +// +// A major/minor status code returned by a GSSAPI function. The major status +// code indicates the GSSAPI level error, while the minor code provides a +// mechanism specific error code if a specific GSSAPI mechanism was involved in +// the error. +// +// The status value has the following structure: +// { +// "function": <name of GSSAPI function that returned the error> +// "major_status": { +// "status" : <status value as a number>, +// "message": [ +// <list of strings hopefully explaining what that number means> +// ] +// }, +// "minor_status": { +// "status" : <status value as a number>, +// "message": [ +// <list of strings hopefully explaining what that number means> +// ] +// } +// } +// +// ** OID: +// +// An ASN.1 OID that's used for GSSAPI is serialized thusly: +// { +// "oid": <symbolic name of OID if it is known> +// "length": <length in bytes of serialized OID>, +// "bytes": <serialized bytes of OID encoded via NetLogBinaryValue()> +// } +// +// ** GSS Display Name: +// +// A serialization of GSSAPI principal name to something that can be consumed by +// humans. If the encoding of the string is not UTF-8 (since there's no +// requirement that they use any specific encoding) the field is serialized +// using NetLogBinaryValue(). +// { +// "name" : <GSSAPI principal name> +// "type" : <OID indicating type of name. See OID above.> +// "error": <If the display name lookup operation failed, then this field +// contains the error in the form of a GSSAPI Status.> +// } +// +// ** GSSAPI Context Description +// +// A serialization of the GSSAPI context. It takes the following form: +// { +// "source" : <GSS Display Name for the source of the authentication +// attempt. In practice this is always the user's identity.> +// "target" : <GSS Display Name for the target of the authentication +// attempt. This the target server or proxy service +// principal.> +// "open" : <Boolean indicating whether the context is "open", which +// means that the handshake is still in progress. In +// particular, the flags, lifetime, and mechanism fields are +// not considered final until "open" is false. +// "lifetime": <A decimal string indicating the lifetime in seconds of the +// authentication context. The identity as established by this +// handshake is only valid for this long since the time at +// which it was established.> +// "mechanism":<OID indicating inner authentication mechanism.> +// "flags" :<Flags. See RFC 2744 Section 5.19 for meanings. Flag +// bitmasks can be found in RFC 2744 Appendix A.> +// } // Lifetime event for HttpAuthController. // @@ -2212,11 +2285,56 @@ // } EVENT_TYPE(AUTH_HANDLE_CHALLENGE) +// An attempt was made to load an authentication library. +// +// If the request succeeded, the parameters are: +// { +// "library_name": <Name of library> +// } +// Otherwise, the parameters are: +// { +// "library_name": <Name of library> +// "load_error": <An error string> +// } +EVENT_TYPE(AUTH_LIBRARY_LOAD) + +// A required method was not found while attempting to load an authentication +// library. +// +// Parameters are: +// { +// "library_name": <Name of the library where the method lookup failed> +// "method": <Name of method that was not found> +// } +EVENT_TYPE(AUTH_LIBRARY_BIND_FAILED) + +// Construction of the GSSAPI service principal name. +// +// Parameters: +// { +// "spn": <Service principal name as a string> +// "status": <GSSAPI Status. See GSSAPI Status above. This is field is only +// logged if the operation failed.> +// } +EVENT_TYPE(AUTH_LIBRARY_IMPORT_NAME) + +// Initialize security context. +// +// This operation involves invoking an external library which may perform disk, +// IPC, and network IO as a part of its work. +// +// The END phase has the following parameters. +// { +// "context": <GSSAPI Context Description>, +// "status": <GSSAPI Status if the operation failed> +// } +EVENT_TYPE(AUTH_LIBRARY_INIT_SEC_CTX) + // The channel bindings generated for the connection. // { -// "token": <Hex encoded RFC 5929 'tls-server-endpoint' channel binding -// token. Could be empty if one could not be generated (e.g. -// because the underlying channel was not TLS> +// "token": <Hex encoded RFC 5929 'tls-server-endpoint' channel binding +// token. Could be empty if one could not be generated (e.g. +// because the underlying channel was not TLS.)> // } EVENT_TYPE(AUTH_CHANNEL_BINDINGS)
diff --git a/net/network_error_logging/OWNERS b/net/network_error_logging/OWNERS new file mode 100644 index 0000000..7117a80a --- /dev/null +++ b/net/network_error_logging/OWNERS
@@ -0,0 +1 @@ +chlily@chromium.org
diff --git a/net/reporting/OWNERS b/net/reporting/OWNERS new file mode 100644 index 0000000..7117a80a --- /dev/null +++ b/net/reporting/OWNERS
@@ -0,0 +1 @@ +chlily@chromium.org
diff --git a/net/test/embedded_test_server/default_handlers.cc b/net/test/embedded_test_server/default_handlers.cc index 68d19bb7..3a7c68be 100644 --- a/net/test/embedded_test_server/default_handlers.cc +++ b/net/test/embedded_test_server/default_handlers.cc
@@ -206,6 +206,22 @@ return http_response; } +// /set-invalid-cookie +// Sets invalid response cookies "\x01" (chosen via fuzzer to not be a parsable +// cookie). +std::unique_ptr<HttpResponse> HandleSetInvalidCookie( + const HttpRequest& request) { + auto http_response = std::make_unique<BasicHttpResponse>(); + http_response->set_content_type("text/html"); + std::string content; + GURL request_url = request.GetURL(); + + http_response->AddCustomHeader("Set-Cookie", "\x01"); + + http_response->set_content("TEST"); + return http_response; +} + // /set-many-cookies?N // Sets N cookies in the response. std::unique_ptr<HttpResponse> HandleSetManyCookies(const HttpRequest& request) { @@ -365,6 +381,9 @@ "Basic realm=\"" + realm + "\""); if (query.find("set-cookie-if-challenged") != query.end()) http_response->AddCustomHeader("Set-Cookie", "got_challenged=true"); + if (query.find("set-secure-cookie-if-challenged") != query.end()) + http_response->AddCustomHeader("Set-Cookie", + "got_challenged=true;Secure"); http_response->set_content(base::StringPrintf( "<html><head><title>Denied: %s</title></head>" "<body>auth=%s<p>b64str=%s<p>username: %s<p>userpass: %s<p>" @@ -542,6 +561,27 @@ return http_response; } +// /server-redirect-with-secure-cookie?URL +// Returns a server redirect to URL, and sets the cookie +// server-redirect=true;Secure. +std::unique_ptr<HttpResponse> HandleServerRedirectWithSecureCookie( + HttpStatusCode redirect_code, + const HttpRequest& request) { + GURL request_url = request.GetURL(); + std::string dest = UnescapeBinaryURLComponent(request_url.query_piece()); + RequestQuery query = ParseQuery(request_url); + + auto http_response = std::make_unique<BasicHttpResponse>(); + http_response->set_code(redirect_code); + http_response->AddCustomHeader("Location", dest); + http_response->AddCustomHeader("Set-Cookie", "server-redirect=true;Secure"); + http_response->set_content_type("text/html"); + http_response->set_content(base::StringPrintf( + "<html><head></head><body>Redirecting to %s</body></html>", + dest.c_str())); + return http_response; +} + // /cross-site?URL // Returns a cross-site redirect to URL. std::unique_ptr<HttpResponse> HandleCrossSiteRedirect( @@ -753,6 +793,8 @@ server->RegisterDefaultHandler( PREFIXED_HANDLER("/set-cookie", &HandleSetCookie)); server->RegisterDefaultHandler( + PREFIXED_HANDLER("/set-invalid-cookie", &HandleSetInvalidCookie)); + server->RegisterDefaultHandler( PREFIXED_HANDLER("/set-many-cookies", &HandleSetManyCookies)); server->RegisterDefaultHandler( PREFIXED_HANDLER("/expect-and-set-cookie", &HandleExpectAndSetCookie)); @@ -783,6 +825,9 @@ server->RegisterDefaultHandler(SERVER_REDIRECT_HANDLER( "/server-redirect-with-cookie", &HandleServerRedirectWithCookie, HTTP_MOVED_PERMANENTLY)); + server->RegisterDefaultHandler(SERVER_REDIRECT_HANDLER( + "/server-redirect-with-secure-cookie", + &HandleServerRedirectWithSecureCookie, HTTP_MOVED_PERMANENTLY)); server->RegisterDefaultHandler( base::BindRepeating(&HandleCrossSiteRedirect, server));
diff --git a/services/network/host_resolver_unittest.cc b/services/network/host_resolver_unittest.cc index 42296b9..a87fc24 100644 --- a/services/network/host_resolver_unittest.cc +++ b/services/network/host_resolver_unittest.cc
@@ -1177,6 +1177,7 @@ net::HostResolver::CreateStandaloneContextResolver(&net_log); inner_resolver->GetManagerForTesting()->SetDnsClientForTesting( std::move(dns_client)); + inner_resolver->GetManagerForTesting()->SetInsecureDnsClientEnabled(true); inner_resolver->SetBaseDnsConfigForTesting(CreateValidDnsConfig()); HostResolver resolver(inner_resolver.get(), &net_log); @@ -1216,6 +1217,7 @@ net::HostResolver::CreateStandaloneContextResolver(&net_log); inner_resolver->GetManagerForTesting()->SetDnsClientForTesting( std::move(dns_client)); + inner_resolver->GetManagerForTesting()->SetInsecureDnsClientEnabled(true); inner_resolver->SetBaseDnsConfigForTesting(CreateValidDnsConfig()); HostResolver resolver(inner_resolver.get(), &net_log);
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 0e3fb93f..ded9272 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -1324,7 +1324,7 @@ // different overrides. But since this is only used for special cases for // now, much easier to create entirely separate net::HostResolver instances. net::HostResolver::ManagerOptions options; - options.dns_client_enabled = true; + options.insecure_dns_client_enabled = true; options.dns_config_overrides = config_overrides.value(); private_internal_resolver = network_service_->host_resolver_factory()->CreateStandaloneResolver(
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index 3dcc6d2b..7d803bb 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -5690,6 +5690,274 @@ EXPECT_EQ(base::ASCIIToUTF16(kPassword), entry->credentials().password()); } +static ResourceRequest CreateResourceRequest(const char* method, + const GURL& url) { + ResourceRequest request; + request.method = std::string(method); + request.url = url; + request.site_for_cookies = url; // bypass third-party cookie blocking + request.request_initiator = + url::Origin::Create(url); // ensure initiator is set + request.allow_download = true; + return request; +} + +class NetworkContextSplitCacheTest : public NetworkContextTest { + protected: + NetworkContextSplitCacheTest() { + feature_list_.InitAndEnableFeature( + net::features::kSplitCacheByNetworkIsolationKey); + test_server_.AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("services/test/data"))); + EXPECT_TRUE(test_server_.Start()); + + // Set up a scoped host resolver to access other origins. + scoped_refptr<net::RuleBasedHostResolverProc> mock_resolver_proc = + base::MakeRefCounted<net::RuleBasedHostResolverProc>(nullptr); + mock_resolver_proc->AddRule("*", "127.0.0.1"); + mock_host_resolver_ = std::make_unique<net::ScopedDefaultHostResolverProc>( + mock_resolver_proc.get()); + + mojom::NetworkContextParamsPtr context_params = CreateContextParams(); + network_context_ = CreateContextWithParams(std::move(context_params)); + } + + net::EmbeddedTestServer* test_server() { return &test_server_; } + + void LoadAndVerifyCached( + const GURL& url, + const net::NetworkIsolationKey& key, + bool was_cached, + bool is_navigation, + mojom::UpdateNetworkIsolationKeyOnRedirect + update_network_isolation_key_on_redirect = + mojom::UpdateNetworkIsolationKeyOnRedirect::kDoNotUpdate, + bool expect_redirect = false, + base::Optional<GURL> new_url = base::nullopt) { + ResourceRequest request = CreateResourceRequest("GET", url); + request.load_flags |= net::LOAD_SKIP_CACHE_VALIDATION; + request.update_network_isolation_key_on_redirect = + update_network_isolation_key_on_redirect; + + mojom::URLLoaderFactoryPtr loader_factory; + auto params = mojom::URLLoaderFactoryParams::New(); + params->process_id = mojom::kBrowserProcessId; + params->is_corb_enabled = false; + if (is_navigation) { + request.trusted_network_isolation_key = key; + } else { + params->network_isolation_key = key; + } + network_context_->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory), + std::move(params)); + auto client = std::make_unique<TestURLLoaderClient>(); + mojom::URLLoaderPtr loader; + loader_factory->CreateLoaderAndStart( + mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */, + mojom::kURLLoadOptionNone, request, client->CreateInterfacePtr(), + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); + + if (expect_redirect) { + client->RunUntilRedirectReceived(); + loader->FollowRedirect({}, {}, new_url); + client->ClearHasReceivedRedirect(); + } + + if (new_url) { + client->RunUntilRedirectReceived(); + loader->FollowRedirect({}, {}, base::nullopt); + } + + client->RunUntilComplete(); + + EXPECT_EQ(net::OK, client->completion_status().error_code); + EXPECT_EQ(was_cached, client->completion_status().exists_in_cache); + } + + private: + base::test::ScopedFeatureList feature_list_; + net::EmbeddedTestServer test_server_; + std::unique_ptr<net::ScopedDefaultHostResolverProc> mock_host_resolver_; + std::unique_ptr<NetworkContext> network_context_; +}; + +TEST_F(NetworkContextSplitCacheTest, CachedUsingNetworkIsolationKey) { + GURL url = test_server()->GetURL("/resource"); + url::Origin origin_a = url::Origin::Create(GURL("http://a.test/")); + net::NetworkIsolationKey key_a(origin_a, origin_a); + LoadAndVerifyCached(url, key_a, false /* was_cached */, + false /* is_navigation */); + + // Load again with a different isolation key. The cached entry should not be + // loaded. + url::Origin origin_b = url::Origin::Create(GURL("http://b.test/")); + net::NetworkIsolationKey key_b(origin_b, origin_b); + LoadAndVerifyCached(url, key_b, false /* was_cached */, + false /* is_navigation */); + + // Load again with the same isolation key. The cached entry should be loaded. + LoadAndVerifyCached(url, key_b, true /* was_cached */, + false /* is_navigation */); +} + +TEST_F(NetworkContextSplitCacheTest, + NavigationResourceCachedUsingNetworkIsolationKey) { + GURL url = test_server()->GetURL("othersite.test", "/main.html"); + url::Origin origin_a = url::Origin::Create(url); + net::NetworkIsolationKey key_a(origin_a, origin_a); + LoadAndVerifyCached(url, key_a, false /* was_cached */, + true /* is_navigation */); + + // Load again with a different isolation key. The cached entry should not be + // loaded. + GURL url_b = test_server()->GetURL("/main.html"); + url::Origin origin_b = url::Origin::Create(url_b); + net::NetworkIsolationKey key_b(origin_b, origin_b); + LoadAndVerifyCached(url_b, key_b, false /* was_cached */, + true /* is_navigation */); + + // Load again with the same isolation key. The cached entry should be loaded. + LoadAndVerifyCached(url_b, key_b, true /* was_cached */, + true /* is_navigation */); +} + +TEST_F(NetworkContextSplitCacheTest, + CachedUsingNetworkIsolationKeyWithFrameOrigin) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {net::features::kSplitCacheByNetworkIsolationKey, + net::features::kAppendFrameOriginToNetworkIsolationKey}, + {}); + + GURL url = test_server()->GetURL("/resource"); + url::Origin origin_a = url::Origin::Create(GURL("http://a.test/")); + net::NetworkIsolationKey key_a(origin_a, origin_a); + LoadAndVerifyCached(url, key_a, false /* was_cached */, + false /* is_navigation */); + + // Load again with a different isolation key. The cached entry should not be + // loaded. + url::Origin origin_b = url::Origin::Create(GURL("http://b.test/")); + net::NetworkIsolationKey key_b(origin_a, origin_b); + LoadAndVerifyCached(url, key_b, false /* was_cached */, + false /* is_navigation */); +} + +TEST_F(NetworkContextSplitCacheTest, + NavigationResourceRedirectNetworkIsolationKey) { + // Create a request that redirects. + GURL url = test_server()->GetURL( + "/server-redirect?" + + test_server()->GetURL("othersite.test", "/title1.html").spec()); + url::Origin origin = url::Origin::Create(url); + net::NetworkIsolationKey key(origin, origin); + LoadAndVerifyCached( + url, key, false /* was_cached */, true /* is_navigation */, + mojom::UpdateNetworkIsolationKeyOnRedirect::kUpdateTopFrameAndFrameOrigin, + true /* expect_redirect */); + + // Now directly load with the key using the redirected URL. This should be a + // cache hit. + GURL redirected_url = test_server()->GetURL("othersite.test", "/title1.html"); + url::Origin redirected_origin = url::Origin::Create(redirected_url); + LoadAndVerifyCached( + redirected_url, + net::NetworkIsolationKey(redirected_origin, redirected_origin), + true /* was_cached */, true /* is_navigation */); + + // A non-navigation resource with the same key and url should also be cached. + LoadAndVerifyCached( + redirected_url, + net::NetworkIsolationKey(redirected_origin, redirected_origin), + true /* was_cached */, false /* is_navigation */); +} + +TEST_F(NetworkContextSplitCacheTest, + NavigationResourceRedirectNetworkIsolationKeyWithNewUrl) { + // Create a request that redirects to othersite.test/title1.html. + GURL url = test_server()->GetURL( + "/server-redirect?" + + test_server()->GetURL("othersite.test", "/title1.html").spec()); + url::Origin origin = url::Origin::Create(url); + net::NetworkIsolationKey key(origin, origin); + + // Create a new url that should be used in the network isolation key computed + // in FollowRedirect instead of the redirected url. + GURL new_url = test_server()->GetURL("othersite.test", "/title2.html"); + LoadAndVerifyCached( + url, key, false /* was_cached */, true /* is_navigation */, + mojom::UpdateNetworkIsolationKeyOnRedirect::kUpdateTopFrameAndFrameOrigin, + true /* expect_redirect */, new_url); + + // Load with the key using the new url should be a cache hit. + origin = url::Origin::Create(new_url); + LoadAndVerifyCached(new_url, net::NetworkIsolationKey(origin, origin), + true /* was_cached */, true /* is_navigation */); + + // Now directly load with the key using the redirected URL. This should be a + // cache miss. + GURL redirected_url = test_server()->GetURL("othersite.test", "/title1.html"); + origin = url::Origin::Create(redirected_url); + LoadAndVerifyCached(redirected_url, net::NetworkIsolationKey(origin, origin), + false /* was_cached */, true /* is_navigation */); +} + +TEST_F(NetworkContextSplitCacheTest, + NavigationResourceCachedUsingNetworkIsolationKeyWithFrameOrigin) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {net::features::kSplitCacheByNetworkIsolationKey, + net::features::kAppendFrameOriginToNetworkIsolationKey}, + {}); + GURL url = test_server()->GetURL("othersite.test", "/main.html"); + url::Origin origin_a = url::Origin::Create(url); + net::NetworkIsolationKey key_a(origin_a, origin_a); + LoadAndVerifyCached(url, key_a, false /* was_cached */, + true /* is_navigation */); + + // Load again with a isolation key using a different subframe origin. The + // cached entry should not be loaded. + url::Origin origin_b = url::Origin::Create(test_server()->base_url()); + net::NetworkIsolationKey key_b(origin_a, origin_b); + LoadAndVerifyCached(url, key_b, false /* was_cached */, + true /* is_navigation */); + + // Load again with the same isolation key. The cached entry should be loaded. + LoadAndVerifyCached(url, key_b, true /* was_cached */, + true /* is_navigation */); + + // Same for a non-navigation entry. + LoadAndVerifyCached(url, key_b, true /* was_cached */, + false /* is_navigation */); +} + +TEST_F(NetworkContextSplitCacheTest, + NavigationResourceRedirectNetworkIsolationKeyWithFrameOrigin) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {net::features::kSplitCacheByNetworkIsolationKey, + net::features::kAppendFrameOriginToNetworkIsolationKey}, + {}); + // Create a request that redirects to othersite.test/title1.html. + GURL url = test_server()->GetURL( + "/server-redirect?" + + test_server()->GetURL("othersite.test", "/title1.html").spec()); + url::Origin origin = url::Origin::Create(url); + net::NetworkIsolationKey key(origin, origin); + LoadAndVerifyCached( + url, key, false /* was_cached */, true /* is_navigation */, + mojom::UpdateNetworkIsolationKeyOnRedirect::kUpdateFrameOrigin, + true /* expect_redirect */); + + // Now directly load with the key using the redirected URL. This should be a + // cache hit. + GURL redirected_url = test_server()->GetURL("othersite.test", "/title1.html"); + LoadAndVerifyCached( + redirected_url, + net::NetworkIsolationKey(origin, url::Origin::Create(redirected_url)), + true /* was_cached */, true /* is_navigation */); +} + } // namespace } // namespace network
diff --git a/services/network/network_service.cc b/services/network/network_service.cc index e5291c8b..3cf5a41 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc
@@ -150,7 +150,9 @@ ~NetworkServiceAuthNegotiateAndroid() override = default; // HttpNegotiateAuthSystem implementation: - bool Init() override { return auth_negotiate_.Init(); } + bool Init(const net::NetLogWithSource& net_log) override { + return auth_negotiate_.Init(net_log); + } bool NeedsIdentity() const override { return auth_negotiate_.NeedsIdentity(); @@ -169,6 +171,7 @@ const std::string& spn, const std::string& channel_bindings, std::string* auth_token, + const net::NetLogWithSource& net_log, net::CompletionOnceCallback callback) override { network_service_->client()->OnGenerateHttpNegotiateAuthToken( auth_negotiate_.server_auth_token(), auth_negotiate_.can_delegate(), @@ -456,9 +459,9 @@ DCHECK(stub_resolver_enabled || !dns_over_https_servers); DCHECK(!dns_over_https_servers || !dns_over_https_servers->empty()); - // Enable or disable the stub resolver, as needed. "DnsClient" is class that - // implements the stub resolver. - host_resolver_manager_->SetDnsClientEnabled(stub_resolver_enabled); + // Enable or disable the insecure part of DnsClient. "DnsClient" is the class + // that implements the stub resolver. + host_resolver_manager_->SetInsecureDnsClientEnabled(stub_resolver_enabled); // Configure DNS over HTTPS. if (!dns_over_https_servers || dns_over_https_servers.value().empty()) { @@ -472,7 +475,8 @@ overrides.dns_over_https_servers.value().emplace_back( doh_server->server_template, doh_server->use_post); } - // TODO(dalyk): Allow the secure dns mode to be set. + // TODO(crbug.com/985589): Allow the secure dns mode to be set independently + // of the insecure part of the stub resolver. overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::AUTOMATIC; host_resolver_manager_->SetDnsConfigOverrides(overrides); } @@ -491,8 +495,7 @@ http_auth_handler_factory_ = net::HttpAuthHandlerRegistryFactory::Create( &http_auth_preferences_, http_auth_static_params->supported_schemes -#if (defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)) || \ - defined(OS_FUCHSIA) +#if BUILDFLAG(USE_EXTERNAL_GSSAPI) , http_auth_static_params->gssapi_library_name #endif
diff --git a/services/network/network_service_unittest.cc b/services/network/network_service_unittest.cc index ce8f35df..7f5af33 100644 --- a/services/network/network_service_unittest.cc +++ b/services/network/network_service_unittest.cc
@@ -230,9 +230,7 @@ EXPECT_FALSE(auth_handler_factory->GetSchemeFactory(net::kNtlmAuthScheme)); } -// |gssapi_library_name| is only supported on certain POSIX platforms. -#if BUILDFLAG(USE_KERBEROS) && defined(OS_POSIX) && !defined(OS_ANDROID) && \ - !defined(OS_CHROMEOS) +#if BUILDFLAG(USE_EXTERNAL_GSSAPI) TEST_F(NetworkServiceTest, AuthGssapiLibraryName) { const std::string kGssapiLibraryName = "Jim"; mojom::HttpAuthStaticParamsPtr auth_params = @@ -249,7 +247,7 @@ EXPECT_EQ(kGssapiLibraryName, GetNegotiateFactory(&network_context)->GetLibraryNameForTesting()); } -#endif +#endif // BUILDFLAG(USE_EXTERNAL_GSSAPI) TEST_F(NetworkServiceTest, AuthServerWhitelist) { // Add one server to the whitelist before creating any NetworkContexts. @@ -447,15 +445,21 @@ TEST_F(NetworkServiceTest, DnsClientEnableDisable) { // HostResolver::GetDnsConfigAsValue() returns nullptr if the stub resolver is // disabled. - EXPECT_FALSE(service()->host_resolver_manager()->GetDnsConfigAsValue()); + EXPECT_FALSE(service() + ->host_resolver_manager() + ->GetInsecureDnsClientEnabledForTesting()); service()->ConfigureStubHostResolver( true /* stub_resolver_enabled */, base::nullopt /* dns_over_https_servers */); - EXPECT_TRUE(service()->host_resolver_manager()->GetDnsConfigAsValue()); + EXPECT_TRUE(service() + ->host_resolver_manager() + ->GetInsecureDnsClientEnabledForTesting()); service()->ConfigureStubHostResolver( false /* stub_resolver_enabled */, base::nullopt /* dns_over_https_servers */); - EXPECT_FALSE(service()->host_resolver_manager()->GetDnsConfigAsValue()); + EXPECT_FALSE(service() + ->host_resolver_manager() + ->GetInsecureDnsClientEnabledForTesting()); } TEST_F(NetworkServiceTest, DnsOverHttpsEnableDisable) { @@ -466,10 +470,6 @@ const std::string kServer3 = "https://grapefruit/resolver/query{?dns}"; const bool kServer3UsePost = false; - // HostResolver::GetDnsClientForTesting() returns nullptr if the stub resolver - // is disabled. - EXPECT_FALSE(service()->host_resolver_manager()->GetDnsConfigAsValue()); - // Create the primary NetworkContext before enabling DNS over HTTPS. mojom::NetworkContextPtr network_context; mojom::NetworkContextParamsPtr context_params = CreateContextParams();
diff --git a/services/network/public/cpp/url_request_mojom_traits_unittest.cc b/services/network/public/cpp/url_request_mojom_traits_unittest.cc index fa111e6c..b71e5cf 100644 --- a/services/network/public/cpp/url_request_mojom_traits_unittest.cc +++ b/services/network/public/cpp/url_request_mojom_traits_unittest.cc
@@ -53,9 +53,8 @@ original.top_frame_origin = origin; original.trusted_network_isolation_key = net::NetworkIsolationKey(origin, origin); - original.update_network_isolation_key_on_redirect = - network::mojom::UpdateNetworkIsolationKeyOnRedirect:: - kUpdateTopFrameAndInitiatingFrameOrigin; + original.update_network_isolation_key_on_redirect = network::mojom:: + UpdateNetworkIsolationKeyOnRedirect::kUpdateTopFrameAndFrameOrigin; original.attach_same_site_cookies = true; original.update_first_party_url_on_redirect = false; original.request_initiator = url::Origin::Create(original.url);
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index c88ed7b..012e70b9 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -85,6 +85,7 @@ "digitally_signed.mojom", "fetch_api.mojom", "host_resolver.mojom", + "http_raw_headers.mojom", "http_request_headers.mojom", "mdns_responder.mojom", "net_log.mojom",
diff --git a/services/network/public/mojom/http_raw_headers.mojom b/services/network/public/mojom/http_raw_headers.mojom new file mode 100644 index 0000000..ec601fbb --- /dev/null +++ b/services/network/public/mojom/http_raw_headers.mojom
@@ -0,0 +1,10 @@ +// 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. + +module network.mojom; + +struct HttpRawHeaderPair { + string key; + string value; +}; \ No newline at end of file
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom index 85c34c1..c51da43 100644 --- a/services/network/public/mojom/network_service.mojom +++ b/services/network/public/mojom/network_service.mojom
@@ -13,6 +13,7 @@ import "mojo/public/mojom/base/values.mojom"; import "services/network/public/mojom/cookie_manager.mojom"; import "services/network/public/mojom/host_resolver.mojom"; +import "services/network/public/mojom/http_raw_headers.mojom"; import "services/network/public/mojom/net_log.mojom"; import "services/network/public/mojom/network_change_manager.mojom"; import "services/network/public/mojom/network_context.mojom"; @@ -171,6 +172,27 @@ string auth_negotiate_android_account_type, string spn) => (int32 result, string auth_token); + + // Called to send raw header information and information about excluded + // cookies. Only called when |devtool_request_id| is available to the + // URLLoader. + OnRawRequest( + int32 process_id, + int32 routing_id, + string devtool_request_id, + array<CookieWithStatus> cookies_with_status, + array<HttpRawHeaderPair> headers); + + // Called to send information about the cookies blocked from storage from a + // received response. Only called when |devtool_request_id| is available to + // the URLLoader. + OnRawResponse( + int32 process_id, + int32 routing_id, + string devtool_request_id, + array<CookieAndLineWithStatus> cookies_with_status, + array<HttpRawHeaderPair> headers, + string? raw_response_headers); }; // Values for configuring HTTP authentication that can only be set once. @@ -180,8 +202,10 @@ // behavior of NetworkService when no HttpAuthStaticParams is specified. array<string> supported_schemes; - // File name the GSSAPI library to load. Only supported on - // (OS_POSIX && !OS_ANDROID && !OS_CHROMEOS && OS_IOS) platforms. + // File name the GSSAPI library to load. Only supported on platforms where an + // external GSSAPI library is necessary for Kerberos/SPNEGO support. See the + // |use_external_gssapi| variable definition in //net/BUILD.gn for details on + // platforms where this setting is applicable. string gssapi_library_name; };
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom index c31aab4..bffe40f 100644 --- a/services/network/public/mojom/url_loader.mojom +++ b/services/network/public/mojom/url_loader.mojom
@@ -77,13 +77,13 @@ kDoNotUpdate, // The updated network isolation key will take the redirected url's origin as - // the top frame origin and initiating frame origin. - kUpdateTopFrameAndInitiatingFrameOrigin, + // the top frame origin and frame origin. + kUpdateTopFrameAndFrameOrigin, // The updated network isolation key will take existing // |trusted_network_isolation_key|'s top frame origin and redirected url's - // origin as the initiating frame origin. - kUpdateInitiatingFrameOrigin + // origin as the frame origin. + kUpdateFrameOrigin }; // Typemapped to network::ResourceRequest.
diff --git a/services/network/test/test_network_service_client.cc b/services/network/test/test_network_service_client.cc index e02cc608..721da42 100644 --- a/services/network/test/test_network_service_client.cc +++ b/services/network/test/test_network_service_client.cc
@@ -112,4 +112,19 @@ } #endif +void TestNetworkServiceClient::OnRawRequest( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers) {} + +void TestNetworkServiceClient::OnRawResponse( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieAndLineStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers, + const base::Optional<std::string>& raw_response_headers) {} + } // namespace network
diff --git a/services/network/test/test_network_service_client.h b/services/network/test/test_network_service_client.h index 454f481..3d517d2 100644 --- a/services/network/test/test_network_service_client.h +++ b/services/network/test/test_network_service_client.h
@@ -76,6 +76,19 @@ const std::string& spn, OnGenerateHttpNegotiateAuthTokenCallback callback) override; #endif + void OnRawRequest( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override; + void OnRawResponse( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieAndLineStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers, + const base::Optional<std::string>& raw_response_headers) override; private: bool upload_files_invalid_ = false;
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 423fcb0..7b65fe39 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -18,6 +18,7 @@ #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/optional.h" +#include "base/strings/strcat.h" #include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -699,15 +700,25 @@ // See if network isolation key needs to be updated. // TODO(crbug.com/979296): Consider changing this code to copy an origin // instead of creating one from a URL which lacks opacity information - // TODO(crbug.com/950069): Also add the case for kUpdateInitiatingFrameOrigin. - if ((update_network_isolation_key_on_redirect_ == - mojom::UpdateNetworkIsolationKeyOnRedirect:: - kUpdateTopFrameAndInitiatingFrameOrigin) && - !url_request_->network_isolation_key().IsEmpty()) { - url::Origin new_origin = url::Origin::Create(*(deferred_redirect_url_)); - url_request_->set_network_isolation_key( - net::NetworkIsolationKey(new_origin /* top frame origin */, - new_origin /* initiating frame origin */)); + if (url_request_->network_isolation_key().IsFullyPopulated() && + update_network_isolation_key_on_redirect_ != + mojom::UpdateNetworkIsolationKeyOnRedirect::kDoNotUpdate) { + const GURL& url = new_url ? new_url.value() : *deferred_redirect_url_; + const url::Origin& new_origin = url::Origin::Create(url); + + if (update_network_isolation_key_on_redirect_ == + mojom::UpdateNetworkIsolationKeyOnRedirect:: + kUpdateTopFrameAndFrameOrigin) { + url_request_->set_network_isolation_key(net::NetworkIsolationKey( + new_origin /* top frame origin */, new_origin /* frame origin */)); + } else if (update_network_isolation_key_on_redirect_ == + mojom::UpdateNetworkIsolationKeyOnRedirect::kUpdateFrameOrigin) { + base::Optional<url::Origin> top_frame_origin = + url_request_->network_isolation_key().GetTopFrameOrigin(); + DCHECK(top_frame_origin); + url_request_->set_network_isolation_key( + net::NetworkIsolationKey(top_frame_origin.value(), new_origin)); + } } deferred_redirect_url_.reset(); @@ -1397,6 +1408,23 @@ void URLLoader::SetRawRequestHeadersAndNotify( net::HttpRawRequestHeaders headers) { + if (network_service_client_ && devtools_request_id()) { + std::vector<network::mojom::HttpRawHeaderPairPtr> header_array; + header_array.reserve(headers.headers().size()); + + for (const auto& header : headers.headers()) { + network::mojom::HttpRawHeaderPairPtr pair = + network::mojom::HttpRawHeaderPair::New(); + pair->key = header.first; + pair->value = header.second; + header_array.push_back(std::move(pair)); + } + + network_service_client_->OnRawRequest( + GetProcessId(), GetRenderFrameId(), devtools_request_id().value(), + url_request_->maybe_sent_cookies(), std::move(header_array)); + } + if (network_context_client_) { net::CookieStatusList reported_cookies; for (const auto& cookie_and_status : url_request_->maybe_sent_cookies()) { @@ -1414,8 +1442,6 @@ } } - // TODO(crbug.com/856777): Add OnRawRequest once implemented - if (want_raw_headers_) raw_request_headers_.Assign(std::move(headers)); } @@ -1578,6 +1604,39 @@ } void URLLoader::ReportFlaggedResponseCookies() { + if (network_service_client_ && devtools_request_id() && + url_request_->response_headers()) { + std::vector<network::mojom::HttpRawHeaderPairPtr> header_array; + + size_t iterator = 0; + std::string name, value; + while (url_request_->response_headers()->EnumerateHeaderLines( + &iterator, &name, &value)) { + network::mojom::HttpRawHeaderPairPtr pair = + network::mojom::HttpRawHeaderPair::New(); + pair->key = name; + pair->value = value; + header_array.push_back(std::move(pair)); + } + + // Only send the "raw" header text when the headers were actually send in + // text form (i.e. not QUIC or SPDY) + base::Optional<std::string> raw_response_headers; + + const net::HttpResponseInfo& response_info = url_request_->response_info(); + + if (!response_info.DidUseQuic() && !response_info.was_fetched_via_spdy) { + raw_response_headers = + base::make_optional(net::HttpUtil::ConvertHeadersBackToHTTPResponse( + url_request_->response_headers()->raw_headers())); + } + + network_service_client_->OnRawResponse( + GetProcessId(), GetRenderFrameId(), devtools_request_id().value(), + url_request_->maybe_stored_cookies(), std::move(header_array), + raw_response_headers); + } + if (network_context_client_) { net::CookieStatusList reported_cookies; for (const auto& cookie_line_and_status : @@ -1596,9 +1655,6 @@ reported_cookies); } } - - // TODO(crbug.com/856777): add OnRawResponse once implemented. - // (might want to change method name at that point). } } // namespace network
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index d606496..52be1d67 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -41,6 +41,7 @@ #include "net/base/load_flags.h" #include "net/base/mime_sniffer.h" #include "net/base/net_errors.h" +#include "net/cert/test_root_certs.h" #include "net/dns/mock_host_resolver.h" #include "net/http/http_response_info.h" #include "net/ssl/client_cert_identity_test_util.h" @@ -48,6 +49,7 @@ #include "net/test/embedded_test_server/controllable_http_response.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_response.h" +#include "net/test/quic_simple_test_server.h" #include "net/test/test_data_directory.h" #include "net/test/url_request/url_request_failed_job.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" @@ -385,7 +387,19 @@ : scoped_task_environment_( base::test::ScopedTaskEnvironment::MainThreadType::IO), resource_scheduler_(true) { + net::TestRootCerts* root_certs = net::TestRootCerts::GetInstance(); + root_certs->AddFromFile( + net::GetTestCertsDirectory().AppendASCII("quic-root.pem")); + + net::QuicSimpleTestServer::Start(); + net::HttpNetworkSession::Params params; + params.quic_params.origins_to_force_quic_on.insert( + net::HostPortPair(net::QuicSimpleTestServer::GetHost(), + net::QuicSimpleTestServer::GetPort())); + params.enable_quic = true; + net::URLRequestContextBuilder context_builder; + context_builder.set_http_network_session_params(params); context_builder.set_proxy_resolution_service( net::ProxyResolutionService::CreateDirect()); auto test_network_delegate = std::make_unique<net::TestNetworkDelegate>(); @@ -413,11 +427,13 @@ // the loopback address and will let us access |test_server_|. scoped_refptr<net::RuleBasedHostResolverProc> mock_resolver_proc = base::MakeRefCounted<net::RuleBasedHostResolverProc>(nullptr); - mock_resolver_proc->AddRule(kInsecureHost, "127.0.0.1"); + mock_resolver_proc->AddRule("*", "127.0.0.1"); mock_host_resolver_ = std::make_unique<net::ScopedDefaultHostResolverProc>( mock_resolver_proc.get()); } + void TearDown() override { net::QuicSimpleTestServer::Shutdown(); } + // Attempts to load |url| and returns the resulting error code. If |body| is // non-NULL, also attempts to read the response body. The advantage of using // |body| instead of calling ReadBody() after Load is that it will load the @@ -746,63 +762,6 @@ TestURLLoaderClient client_; }; -class URLLoaderNetworkIsolationTest : public URLLoaderTest { - protected: - void SetUp() override { - feature_list_.InitAndEnableFeature( - net::features::kSplitCacheByNetworkIsolationKey); - URLLoaderTest::SetUp(); - } - - void LoadAndVerifyCached(const GURL& url, - const net::NetworkIsolationKey& key, - bool was_cached, - bool is_navigation, - bool expect_redirect = false) { - ResourceRequest request = CreateResourceRequest("GET", url); - request.load_flags |= net::LOAD_SKIP_CACHE_VALIDATION; - - TestURLLoaderClient client; - base::RunLoop delete_run_loop; - mojom::URLLoaderPtr loader; - std::unique_ptr<URLLoader> url_loader; - mojom::URLLoaderFactoryParams params; - params.process_id = mojom::kBrowserProcessId; - params.is_corb_enabled = false; - - if (is_navigation) { - request.trusted_network_isolation_key = key; - request.update_network_isolation_key_on_redirect = - mojom::UpdateNetworkIsolationKeyOnRedirect:: - kUpdateTopFrameAndInitiatingFrameOrigin; - } else { - params.network_isolation_key = key; - } - url_loader = std::make_unique<URLLoader>( - context(), nullptr /* network_service_client */, - nullptr /* network_context_client */, - DeleteLoaderCallback(&delete_run_loop, &url_loader), - mojo::MakeRequest(&loader), 0, request, client.CreateInterfacePtr(), - TRAFFIC_ANNOTATION_FOR_TESTS, ¶ms, 0 /* request_id */, - resource_scheduler_client(), nullptr, - nullptr /* network_usage_accumulator */, nullptr /* header_client */); - - if (expect_redirect) { - client.RunUntilRedirectReceived(); - loader->FollowRedirect({}, {}, base::nullopt); - } - - client.RunUntilComplete(); - delete_run_loop.Run(); - - EXPECT_EQ(net::OK, client.completion_status().error_code); - EXPECT_EQ(was_cached, client.completion_status().exists_in_cache); - } - - private: - base::test::ScopedFeatureList feature_list_; -}; - constexpr int URLLoaderTest::kProcessId; constexpr int URLLoaderTest::kRouteId; @@ -2559,6 +2518,65 @@ ++on_certificate_requested_counter_; } + void OnRawRequest( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override { + raw_request_cookies_.insert(raw_request_cookies_.end(), + cookies_with_status.begin(), + cookies_with_status.end()); + + devtools_request_id_ = devtools_request_id; + + if (wait_for_raw_request_ && + raw_request_cookies_.size() >= wait_for_raw_request_goal_) { + std::move(wait_for_raw_request_).Run(); + } + } + + void OnRawResponse( + int32_t process_id, + int32_t routing_id, + const std::string& devtools_request_id, + const net::CookieAndLineStatusList& cookies_with_status, + std::vector<network::mojom::HttpRawHeaderPairPtr> headers, + const base::Optional<std::string>& raw_response_headers) override { + raw_response_cookies_.insert(raw_response_cookies_.end(), + cookies_with_status.begin(), + cookies_with_status.end()); + + devtools_request_id_ = devtools_request_id; + + raw_response_headers_ = raw_response_headers; + + if (wait_for_raw_response_ && + raw_response_cookies_.size() >= wait_for_raw_response_goal_) { + std::move(wait_for_raw_response_).Run(); + } + } + + void WaitUntilRawResponse(size_t goal) { + if (raw_response_cookies_.size() < goal) { + wait_for_raw_response_goal_ = goal; + base::RunLoop run_loop; + wait_for_raw_response_ = run_loop.QuitClosure(); + run_loop.Run(); + } + EXPECT_EQ(goal, raw_response_cookies_.size()); + } + + void WaitUntilRawRequest(size_t goal) { + if (raw_request_cookies_.size() < goal) { + wait_for_raw_request_goal_ = goal; + base::RunLoop run_loop; + wait_for_raw_request_ = run_loop.QuitClosure(); + run_loop.Run(); + } + EXPECT_EQ(goal, raw_request_cookies_.size()); + } + void set_credentials_response(CredentialsResponse credentials_response) { credentials_response_ = credentials_response; } @@ -2595,6 +2613,20 @@ return on_certificate_requested_counter_; } + const net::CookieAndLineStatusList& raw_response_cookies() const { + return raw_response_cookies_; + } + + const net::CookieStatusList& raw_request_cookies() const { + return raw_request_cookies_; + } + + const std::string devtools_request_id() { return devtools_request_id_; } + + const base::Optional<std::string> raw_response_headers() { + return raw_response_headers_; + } + private: CredentialsResponse credentials_response_ = CredentialsResponse::NO_CREDENTIALS; @@ -2609,6 +2641,15 @@ std::string provider_name_; std::vector<uint16_t> algorithm_preferences_; int on_certificate_requested_counter_ = 0; + net::CookieAndLineStatusList raw_response_cookies_; + base::OnceClosure wait_for_raw_response_; + size_t wait_for_raw_response_goal_ = 0u; + std::string devtools_request_id_; + base::Optional<std::string> raw_response_headers_; + + net::CookieStatusList raw_request_cookies_; + base::OnceClosure wait_for_raw_request_; + size_t wait_for_raw_request_goal_ = 0u; DISALLOW_COPY_AND_ASSIGN(MockNetworkServiceClient); }; @@ -3066,95 +3107,6 @@ delete_run_loop.Run(); } -TEST_F(URLLoaderNetworkIsolationTest, CachedUsingNetworkIsolationKey) { - GURL url = test_server()->GetURL("/resource"); - url::Origin origin_a = url::Origin::Create(GURL("http://a.test/")); - net::NetworkIsolationKey key_a(origin_a, origin_a); - LoadAndVerifyCached(url, key_a, false /* was_cached */, - false /* is_navigation */); - - // Load again with a different isolation key. The cached entry should not be - // loaded. - url::Origin origin_b = url::Origin::Create(GURL("http://b.test/")); - net::NetworkIsolationKey key_b(origin_b, origin_b); - LoadAndVerifyCached(url, key_b, false /* was_cached */, - false /* is_navigation */); - - // Load again with the same isolation key. The cached entry should be loaded. - LoadAndVerifyCached(url, key_b, true /* was_cached */, - false /* is_navigation */); -} - -TEST_F(URLLoaderNetworkIsolationTest, - NavigationResourceCachedUsingNetworkIsolationKey) { - GURL url = test_server()->GetURL("othersite.test", "/main.html"); - url::Origin origin_a = url::Origin::Create(url); - net::NetworkIsolationKey key_a(origin_a, origin_a); - LoadAndVerifyCached(url, key_a, false /* was_cached */, - true /* is_navigation */); - - // Load again with a different isolation key. The cached entry should not be - // loaded. - GURL url_b = test_server()->GetURL("/main.html"); - url::Origin origin_b = url::Origin::Create(url_b); - net::NetworkIsolationKey key_b(origin_b, origin_b); - LoadAndVerifyCached(url_b, key_b, false /* was_cached */, - true /* is_navigation */); - - // Load again with the same isolation key. The cached entry should be loaded. - LoadAndVerifyCached(url_b, key_b, true /* was_cached */, - true /* is_navigation */); -} - -TEST_F(URLLoaderNetworkIsolationTest, - CachedUsingNetworkIsolationKeyWithFrameOrigin) { - base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {net::features::kSplitCacheByNetworkIsolationKey, - net::features::kAppendFrameOriginToNetworkIsolationKey}, - {}); - - GURL url = test_server()->GetURL("/resource"); - url::Origin origin_a = url::Origin::Create(GURL("http://a.test/")); - net::NetworkIsolationKey key_a(origin_a, origin_a); - LoadAndVerifyCached(url, key_a, false /* was_cached */, - false /* is_navigation */); - - // Load again with a different isolation key. The cached entry should not be - // loaded. - url::Origin origin_b = url::Origin::Create(GURL("http://b.test/")); - net::NetworkIsolationKey key_b(origin_a, origin_b); - LoadAndVerifyCached(url, key_b, false /* was_cached */, - false /* is_navigation */); -} - -TEST_F(URLLoaderNetworkIsolationTest, - NavigationResourceRedirectNetworkIsolationKey) { - // Create a request that redirects to d.com/title1.html. - GURL url = test_server()->GetURL( - "/server-redirect-301?" + - test_server()->GetURL("othersite.test", "/title1.html").spec()); - url::Origin origin = url::Origin::Create(url); - net::NetworkIsolationKey key(origin, origin); - LoadAndVerifyCached(url, key, false /* was_cached */, - true /* is_navigation */, true /* expect_redirect */); - - // Now directly load now with the key using the redirected URL. This should be - // a cache hit. - GURL redirected_url = test_server()->GetURL("othersite.test", "/title1.html"); - url::Origin redirected_origin = url::Origin::Create(redirected_url); - LoadAndVerifyCached( - redirected_url, - net::NetworkIsolationKey(redirected_origin, redirected_origin), - true /* was_cached */, true /* is_navigation */); - - // A non-navigation resource with the same key and url should also be cached. - LoadAndVerifyCached( - redirected_url, - net::NetworkIsolationKey(redirected_origin, redirected_origin), - true /* was_cached */, false /* is_navigation */); -} - class TestSSLPrivateKey : public net::SSLPrivateKey { public: explicit TestSSLPrivateKey(scoped_refptr<net::SSLPrivateKey> key) @@ -3783,6 +3735,384 @@ } } +TEST_F(URLLoaderTest, RawRequestCookies) { + MockNetworkServiceClient network_service_client; + MockNetworkContextClient network_context_client; + { + TestURLLoaderClient loader_client; + ResourceRequest request = CreateResourceRequest( + "GET", test_server()->GetURL("/echoheader?cookie")); + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + context()->cookie_store()->SetCookieWithOptionsAsync( + test_server()->GetURL("/"), "a=b", net::CookieOptions(), + base::DoNothing()); + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + delete_run_loop.Run(); + loader_client.RunUntilComplete(); + EXPECT_EQ(net::OK, loader_client.completion_status().error_code); + + network_service_client.WaitUntilRawRequest(1u); + EXPECT_EQ("a", + network_service_client.raw_request_cookies()[0].cookie.Name()); + EXPECT_EQ("b", + network_service_client.raw_request_cookies()[0].cookie.Value()); + EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE, + network_service_client.raw_request_cookies()[0].status); + + EXPECT_EQ("TEST", network_service_client.devtools_request_id()); + } +} + +TEST_F(URLLoaderTest, RawRequestCookiesFlagged) { + MockNetworkServiceClient network_service_client; + MockNetworkContextClient network_context_client; + { + TestURLLoaderClient loader_client; + ResourceRequest request = CreateResourceRequest( + "GET", test_server()->GetURL("/echoheader?cookie")); + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + // Set the path to an irrelevant url to block the cookie from sending + context()->cookie_store()->SetCookieWithOptionsAsync( + test_server()->GetURL("/"), "a=b;Path=/something-else", + net::CookieOptions(), base::DoNothing()); + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + delete_run_loop.Run(); + loader_client.RunUntilComplete(); + EXPECT_EQ(net::OK, loader_client.completion_status().error_code); + + network_service_client.WaitUntilRawRequest(1u); + EXPECT_EQ("a", + network_service_client.raw_request_cookies()[0].cookie.Name()); + EXPECT_EQ("b", + network_service_client.raw_request_cookies()[0].cookie.Value()); + EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH, + network_service_client.raw_request_cookies()[0].status); + + EXPECT_EQ("TEST", network_service_client.devtools_request_id()); + } +} + +TEST_F(URLLoaderTest, RawResponseCookies) { + MockNetworkServiceClient network_service_client; + MockNetworkContextClient network_context_client; + { + TestURLLoaderClient loader_client; + ResourceRequest request = + CreateResourceRequest("GET", test_server()->GetURL("/set-cookie?a=b")); + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + delete_run_loop.Run(); + loader_client.RunUntilComplete(); + EXPECT_EQ(net::OK, loader_client.completion_status().error_code); + + network_service_client.WaitUntilRawResponse(1u); + EXPECT_EQ("a", + network_service_client.raw_response_cookies()[0].cookie->Name()); + EXPECT_EQ("b", + network_service_client.raw_response_cookies()[0].cookie->Value()); + EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE, + network_service_client.raw_response_cookies()[0].status); + + EXPECT_EQ("TEST", network_service_client.devtools_request_id()); + + ASSERT_TRUE(network_service_client.raw_response_headers()); + EXPECT_NE( + network_service_client.raw_response_headers()->find("Set-Cookie: a=b"), + std::string::npos); + } +} + +TEST_F(URLLoaderTest, RawResponseCookiesInvalid) { + MockNetworkServiceClient network_service_client; + MockNetworkContextClient network_context_client; + { + TestURLLoaderClient loader_client; + ResourceRequest request = CreateResourceRequest( + "GET", test_server()->GetURL("/set-invalid-cookie")); + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + delete_run_loop.Run(); + loader_client.RunUntilComplete(); + EXPECT_EQ(net::OK, loader_client.completion_status().error_code); + + network_service_client.WaitUntilRawResponse(1u); + // On these failures the cookie object is not created + EXPECT_FALSE(network_service_client.raw_response_cookies()[0].cookie); + EXPECT_EQ( + net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE, + network_service_client.raw_response_cookies()[0].status); + + EXPECT_EQ("TEST", network_service_client.devtools_request_id()); + } +} + +TEST_F(URLLoaderTest, RawResponseCookiesRedirect) { + // Check a valid cookie + { + MockNetworkServiceClient network_service_client; + MockNetworkContextClient network_context_client; + GURL dest_url = test_server()->GetURL("/nocontent"); + GURL redirecting_url = test_server()->GetURL( + "/server-redirect-with-cookie?" + dest_url.spec()); + + TestURLLoaderClient loader_client; + ResourceRequest request = CreateResourceRequest("GET", redirecting_url); + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + loader_client.RunUntilRedirectReceived(); + + ASSERT_TRUE(network_service_client.raw_response_headers()); + EXPECT_NE(network_service_client.raw_response_headers()->find( + "Set-Cookie: server-redirect=true"), + std::string::npos); + + loader->FollowRedirect({}, {}, base::nullopt); + loader_client.RunUntilComplete(); + delete_run_loop.Run(); + EXPECT_EQ(net::OK, loader_client.completion_status().error_code); + + network_service_client.WaitUntilRawResponse(1u); + EXPECT_EQ("server-redirect", + network_service_client.raw_response_cookies()[0].cookie->Name()); + EXPECT_EQ("true", + network_service_client.raw_response_cookies()[0].cookie->Value()); + EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE, + network_service_client.raw_response_cookies()[0].status); + + EXPECT_EQ("TEST", network_service_client.devtools_request_id()); + } + + // Check a flagged cookie (secure cookie over an insecure connection) + { + MockNetworkServiceClient network_service_client; + MockNetworkContextClient network_context_client; + GURL dest_url = test_server()->GetURL("/nocontent"); + GURL redirecting_url = test_server()->GetURL( + "/server-redirect-with-secure-cookie?" + dest_url.spec()); + + TestURLLoaderClient loader_client; + ResourceRequest request = CreateResourceRequest("GET", redirecting_url); + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + loader_client.RunUntilRedirectReceived(); + loader->FollowRedirect({}, {}, base::nullopt); + loader_client.RunUntilComplete(); + delete_run_loop.Run(); + EXPECT_EQ(net::OK, loader_client.completion_status().error_code); + + network_service_client.WaitUntilRawResponse(1u); + // On these failures the cookie object is not created + EXPECT_FALSE(network_service_client.raw_response_cookies()[0].cookie); + EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY, + network_service_client.raw_response_cookies()[0].status); + } +} + +TEST_F(URLLoaderTest, RawResponseCookiesAuth) { + // Check a valid cookie + { + MockNetworkServiceClient network_service_client; + network_service_client.set_credentials_response( + MockNetworkServiceClient::CredentialsResponse::NO_CREDENTIALS); + MockNetworkContextClient network_context_client; + + GURL url = test_server()->GetURL( + "/auth-basic?set-cookie-if-challenged&password=PASS"); + TestURLLoaderClient loader_client; + ResourceRequest request = CreateResourceRequest("GET", url); + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + loader_client.RunUntilComplete(); + delete_run_loop.Run(); + EXPECT_EQ(net::OK, loader_client.completion_status().error_code); + + network_service_client.WaitUntilRawResponse(1u); + EXPECT_EQ("got_challenged", + network_service_client.raw_response_cookies()[0].cookie->Name()); + EXPECT_EQ("true", + network_service_client.raw_response_cookies()[0].cookie->Value()); + EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE, + network_service_client.raw_response_cookies()[0].status); + + EXPECT_EQ("TEST", network_service_client.devtools_request_id()); + } + + // Check a flagged cookie (secure cookie from insecure connection) + { + MockNetworkServiceClient network_service_client; + network_service_client.set_credentials_response( + MockNetworkServiceClient::CredentialsResponse::NO_CREDENTIALS); + MockNetworkContextClient network_context_client; + + GURL url = test_server()->GetURL( + "/auth-basic?set-secure-cookie-if-challenged&password=PASS"); + TestURLLoaderClient loader_client; + ResourceRequest request = CreateResourceRequest("GET", url); + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + loader_client.RunUntilComplete(); + delete_run_loop.Run(); + EXPECT_EQ(net::OK, loader_client.completion_status().error_code); + network_service_client.WaitUntilRawResponse(1u); + // On these failures the cookie object is not created + EXPECT_FALSE(network_service_client.raw_response_cookies()[0].cookie); + EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY, + network_service_client.raw_response_cookies()[0].status); + + EXPECT_EQ("TEST", network_service_client.devtools_request_id()); + } +} + +TEST_F(URLLoaderTest, RawResponseQUIC) { + MockNetworkServiceClient network_service_client; + MockNetworkContextClient network_context_client; + { + TestURLLoaderClient loader_client; + ResourceRequest request = + CreateResourceRequest("GET", net::QuicSimpleTestServer::GetFileURL("")); + + // Set the devtools id to trigger the RawResponse call + request.devtools_request_id = "TEST"; + + base::RunLoop delete_run_loop; + mojom::URLLoaderPtr loader; + mojom::URLLoaderFactoryParams params; + params.process_id = kProcessId; + params.is_corb_enabled = false; + std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>( + context(), &network_service_client, &network_context_client, + DeleteLoaderCallback(&delete_run_loop, &url_loader), + mojo::MakeRequest(&loader), mojom::kURLLoadOptionNone, request, + loader_client.CreateInterfacePtr(), TRAFFIC_ANNOTATION_FOR_TESTS, + ¶ms, 0 /* request_id */, resource_scheduler_client(), nullptr, + nullptr /* network_usage_accumulator */, nullptr /* header_client */); + + delete_run_loop.Run(); + loader_client.RunUntilComplete(); + ASSERT_EQ(net::OK, loader_client.completion_status().error_code); + + network_service_client.WaitUntilRawResponse(0u); + EXPECT_EQ("TEST", network_service_client.devtools_request_id()); + + // QUIC responses don't have raw header text, so there shouldn't be any here + EXPECT_FALSE(network_service_client.raw_response_headers()); + } +} + TEST_F(URLLoaderTest, CookieReportingCategories) { MockNetworkServiceClient network_service_client;
diff --git a/testing/libfuzzer/getting_started.md b/testing/libfuzzer/getting_started.md index 8de58a84..ee68f2b 100644 --- a/testing/libfuzzer/getting_started.md +++ b/testing/libfuzzer/getting_started.md
@@ -117,6 +117,10 @@ For more information about libFuzzer's output, please refer to [its own documentation]. +*Note*: if you observe an `odr-violation` error in the log, please try setting +the following environment variable: `ASAN_OPTIONS=detect_odr_violation=0` and +running the fuzz target again. + ### Symbolize Stacktrace If your fuzz target crashes when running locally and you see non-symbolized
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index b18b23e..babae7e 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -498,7 +498,6 @@ "web/web_settings.h", "web/web_shared_worker.h", "web/web_shared_worker_client.h", - "web/web_surrounding_text.h", "web/web_testing_support.h", "web/web_text_check_client.h", "web/web_text_checking_completion.h",
diff --git a/third_party/blink/public/mojom/notifications/notification_service.mojom b/third_party/blink/public/mojom/notifications/notification_service.mojom index c471479..fac9b0c 100644 --- a/third_party/blink/public/mojom/notifications/notification_service.mojom +++ b/third_party/blink/public/mojom/notifications/notification_service.mojom
@@ -47,7 +47,7 @@ string token, NotificationData notification_data, NotificationResources notification_resources, - NonPersistentNotificationListener event_listener); + pending_remote<NonPersistentNotificationListener> event_listener); // Closes a notification that is not associated with a service worker. // |token| identifies which notification should be closed (must be non-empty).
diff --git a/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom b/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom index 741f242..70f2cb8 100644 --- a/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom +++ b/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
@@ -35,7 +35,11 @@ OnScriptLoadStarted( // The info about the service worker provider in the browser process that // provides support for this worker to be a service worker client. - ServiceWorkerProviderInfoForClient service_worker_provider_info, + // + // This is null if the dedicated worker cannot be a service + // worker client, because for example, the worker's URL is + // not http(s) or another service worker supported scheme. + ServiceWorkerProviderInfoForClient? service_worker_provider_info, // Used for passing the main script pre-requested by the browser process // and its redirect information.
diff --git a/third_party/blink/public/mojom/worker/shared_worker_factory.mojom b/third_party/blink/public/mojom/worker/shared_worker_factory.mojom index 78989a0..c05ed08 100644 --- a/third_party/blink/public/mojom/worker/shared_worker_factory.mojom +++ b/third_party/blink/public/mojom/worker/shared_worker_factory.mojom
@@ -40,7 +40,11 @@ // The info about the service worker provider in the browser process that // provides support for this worker to be a service worker client. - ServiceWorkerProviderInfoForClient service_worker_provider_info, + // + // This is null if the shared worker cannot be a service + // worker client, because for example, the worker's URL is + // not http(s) or another service worker supported scheme. + ServiceWorkerProviderInfoForClient? service_worker_provider_info, // The ID of the AppCacheHost in the browser process that serves resources // for this shared worker. This is not specified when AppCache doesn't
diff --git a/third_party/blink/public/platform/web_layer_tree_view.h b/third_party/blink/public/platform/web_layer_tree_view.h index ad83def8..30eb30c 100644 --- a/third_party/blink/public/platform/web_layer_tree_view.h +++ b/third_party/blink/public/platform/web_layer_tree_view.h
@@ -68,15 +68,12 @@ bool shrink_viewport) {} // Input properties --------------------------------------------------- - virtual void SetHaveScrollEventHandlers(bool) {} // Returns the FrameSinkId of the widget associated with this layer tree view. virtual viz::FrameSinkId GetFrameSinkId() { return viz::FrameSinkId(); } // Debugging / dangerous --------------------------------------------- - virtual bool HaveScrollEventHandlers() const { return false; } - virtual int LayerTreeId() const { return 0; } virtual void RequestBeginMainFrameNotExpected(bool new_state) {}
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h index c8b46daa..94d0749 100644 --- a/third_party/blink/public/web/web_widget_client.h +++ b/third_party/blink/public/web/web_widget_client.h
@@ -193,6 +193,9 @@ // Called to update if touch events should be sent. virtual void SetHasTouchEventHandlers(bool) {} + // Called to update if scroll events should be sent. + virtual void SetHaveScrollEventHandlers(bool) {} + // Called to update whether low latency input mode is enabled or not. virtual void SetNeedsLowLatencyInput(bool) {}
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 9785869e..3b859313 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1165,7 +1165,6 @@ "exported/web_scoped_window_focus_allowed_indicator_test.cc", "exported/web_searchable_form_data_test.cc", "exported/web_selector_test.cc", - "exported/web_surrounding_text_test.cc", "exported/web_user_gesture_token_test.cc", "exported/web_view_test.cc", "feature_policy/feature_policy_test.cc", @@ -1454,6 +1453,7 @@ "page/touch_adjustment_test.cc", "page/viewport_test.cc", "page/window_features_test.cc", + "page/zoom_test.cc", "paint/block_painter_test.cc", "paint/box_paint_invalidator_test.cc", "paint/box_painter_test.cc",
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.cc b/third_party/blink/renderer/core/animation/compositor_animations.cc index dd07a8d..ad9f756c 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -35,6 +35,7 @@ #include <memory> #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/core/animation/animation_effect.h" +#include "third_party/blink/renderer/core/animation/css/compositor_keyframe_color.h" #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_double.h" #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_filter_operations.h" #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_transform.h" @@ -51,6 +52,7 @@ #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/platform/animation/animation_translation_util.h" #include "third_party/blink/renderer/platform/animation/compositor_animation.h" +#include "third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h" #include "third_party/blink/renderer/platform/animation/compositor_filter_animation_curve.h" #include "third_party/blink/renderer/platform/animation/compositor_filter_keyframe.h" #include "third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h" @@ -265,14 +267,20 @@ // Backdrop-filter pixel moving filters do not change the layer bounds // like regular filters do, so they can still be composited. break; - case CSSPropertyID::kVariable: + case CSSPropertyID::kVariable: { // Custom properties are supported only in the case of // OffMainThreadCSSPaintEnabled, and even then only for some specific // property types. Otherwise they are treated as unsupported. - if (keyframe->GetCompositorKeyframeValue()) { + const CompositorKeyframeValue* keyframe_value = + keyframe->GetCompositorKeyframeValue(); + if (keyframe_value) { DCHECK(RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()); - DCHECK(keyframe->GetCompositorKeyframeValue()->IsDouble() || - keyframe->GetCompositorKeyframeValue()->IsColor()); + DCHECK(keyframe_value->IsDouble() || keyframe_value->IsColor()); + // TODO: Add support for keyframes containing different types + if (keyframes.front()->GetCompositorKeyframeValue()->GetType() != + keyframe_value->GetType()) { + reasons |= kMixedKeyframeValueTypes; + } } else { // We skip the rest of the loop in this case for the same reason as // unsupported CSS properties - see below. @@ -280,6 +288,7 @@ continue; } break; + } default: // We skip the rest of the loop in this case for two reasons: // i. Getting a CompositorElementId below will DCHECK if we pass it @@ -587,6 +596,16 @@ curve.AddKeyframe(float_keyframe); } +void AddKeyframeToCurve(CompositorColorAnimationCurve& curve, + Keyframe::PropertySpecificKeyframe* keyframe, + const CompositorKeyframeValue* value, + const TimingFunction& keyframe_timing_function) { + CompositorColorKeyframe color_keyframe( + keyframe->Offset(), ToCompositorKeyframeColor(value)->ToColor(), + keyframe_timing_function); + curve.AddKeyframe(color_keyframe); +} + void AddKeyframeToCurve(CompositorTransformAnimationCurve& curve, Keyframe::PropertySpecificKeyframe* keyframe, const CompositorKeyframeValue* value, @@ -693,12 +712,21 @@ DCHECK(RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()); custom_property_name = property.CustomPropertyName(); target_property = compositor_target_property::CSS_CUSTOM_PROPERTY; - // TODO(kevers): Extend support to non-float types. - auto float_curve = std::make_unique<CompositorFloatAnimationCurve>(); - AddKeyframesToCurve(*float_curve, values); - float_curve->SetTimingFunction(*timing.timing_function); - float_curve->SetScaledDuration(scale); - curve = std::move(float_curve); + + // Create curve based on the keyframe value type + if (values.front()->GetCompositorKeyframeValue()->IsColor()) { + auto color_curve = std::make_unique<CompositorColorAnimationCurve>(); + AddKeyframesToCurve(*color_curve, values); + color_curve->SetTimingFunction(*timing.timing_function); + color_curve->SetScaledDuration(scale); + curve = std::move(color_curve); + } else { + auto float_curve = std::make_unique<CompositorFloatAnimationCurve>(); + AddKeyframesToCurve(*float_curve, values); + float_curve->SetTimingFunction(*timing.timing_function); + float_curve->SetScaledDuration(scale); + curve = std::move(float_curve); + } break; } default:
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.h b/third_party/blink/renderer/core/animation/compositor_animations.h index 1609de2..3b222c9 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations.h +++ b/third_party/blink/renderer/core/animation/compositor_animations.h
@@ -90,12 +90,13 @@ kFilterRelatedPropertyMayMovePixels = 1 << 12, kUnsupportedCSSProperty = 1 << 13, kMultipleTransformAnimationsOnSameTarget = 1 << 14, + kMixedKeyframeValueTypes = 1 << 15, // The maximum number of flags in this enum (excluding itself). New flags // should increment this number but it should never be decremented because // the values are used in UMA histograms. It should also be noted that it // excludes the kNoFailure value. - kFailureReasonCount = 15, + kFailureReasonCount = 16, }; static FailureReasons CheckCanStartAnimationOnCompositor(
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc index f594f0e..f3ce839 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -60,6 +60,7 @@ #include "third_party/blink/renderer/core/style/filter_operations.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" +#include "third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h" #include "third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h" #include "third_party/blink/renderer/platform/animation/compositor_float_keyframe.h" #include "third_party/blink/renderer/platform/animation/compositor_keyframe_model.h" @@ -1585,6 +1586,54 @@ } TEST_P(AnimationCompositorAnimationsTest, + CreateSimpleCustomColorPropertyAnimation) { + ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true); + + RegisterProperty(GetDocument(), "--foo", "<color>", "rgb(0, 0, 0)", false); + SetCustomProperty("--foo", "rgb(0, 0, 0)"); + + StringKeyframeEffectModel* effect = CreateKeyframeEffectModel( + CreateReplaceOpKeyframe("--foo", "rgb(0, 0, 0)", 0), + CreateReplaceOpKeyframe("--foo", "rgb(0, 255, 0)", 1.0)); + + std::unique_ptr<CompositorKeyframeModel> keyframe_model = + ConvertToCompositorAnimation(*effect); + EXPECT_EQ(compositor_target_property::CSS_CUSTOM_PROPERTY, + keyframe_model->TargetProperty()); + + std::unique_ptr<CompositorColorAnimationCurve> keyframed_color_curve = + keyframe_model->ColorCurveForTesting(); + + CompositorColorAnimationCurve::Keyframes keyframes = + keyframed_color_curve->KeyframesForTesting(); + ASSERT_EQ(2UL, keyframes.size()); + + EXPECT_EQ(0, keyframes[0]->Time()); + EXPECT_EQ(SkColorSetRGB(0, 0, 0), keyframes[0]->Value()); + EXPECT_EQ(TimingFunction::Type::LINEAR, + keyframes[0]->GetTimingFunctionForTesting()->GetType()); + + EXPECT_EQ(1.0, keyframes[1]->Time()); + EXPECT_EQ(SkColorSetRGB(0, 0xFF, 0), keyframes[1]->Value()); + EXPECT_EQ(TimingFunction::Type::LINEAR, + keyframes[1]->GetTimingFunctionForTesting()->GetType()); +} + +TEST_P(AnimationCompositorAnimationsTest, MixedCustomPropertyAnimation) { + ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true); + + RegisterProperty(GetDocument(), "--foo", "<number> | <color>", "0", false); + SetCustomProperty("--foo", "0"); + + StringKeyframeEffectModel* effect = CreateKeyframeEffectModel( + CreateReplaceOpKeyframe("--foo", "20", 0), + CreateReplaceOpKeyframe("--foo", "rgb(0, 255, 0)", 1.0)); + + EXPECT_TRUE(CanStartEffectOnCompositor(timing_, *effect) & + CompositorAnimations::kMixedKeyframeValueTypes); +} + +TEST_P(AnimationCompositorAnimationsTest, CancelIncompatibleCompositorAnimations) { Persistent<HeapVector<Member<StringKeyframe>>> key_frames = MakeGarbageCollected<HeapVector<Member<StringKeyframe>>>();
diff --git a/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h b/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h index 879ff95..26bef21a 100644 --- a/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h +++ b/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h
@@ -25,7 +25,6 @@ virtual void Trace(Visitor*) {} - protected: enum class Type { kDouble, kFilterOperations, @@ -33,7 +32,6 @@ kColor, }; - private: virtual Type GetType() const = 0; };
diff --git a/third_party/blink/renderer/core/editing/BUILD.gn b/third_party/blink/renderer/core/editing/BUILD.gn index b9cd4355..0e4f2edd 100644 --- a/third_party/blink/renderer/core/editing/BUILD.gn +++ b/third_party/blink/renderer/core/editing/BUILD.gn
@@ -299,6 +299,8 @@ "suggestion/text_suggestion_controller.cc", "suggestion/text_suggestion_controller.h", "suggestion/text_suggestion_info.h", + "surrounding_text.cc", + "surrounding_text.h", "text_affinity.cc", "text_affinity.h", "text_granularity.h", @@ -410,6 +412,7 @@ "state_machines/state_machine_test_util.h", "state_machines/state_machine_util_test.cc", "suggestion/text_suggestion_controller_test.cc", + "surrounding_text_test.cc", "testing/editing_test_base.cc", "testing/editing_test_base.h", "testing/editing_test_base_test.cc",
diff --git a/third_party/blink/renderer/core/exported/web_surrounding_text.cc b/third_party/blink/renderer/core/editing/surrounding_text.cc similarity index 86% rename from third_party/blink/renderer/core/exported/web_surrounding_text.cc rename to third_party/blink/renderer/core/editing/surrounding_text.cc index 37f1698..cb9d29a 100644 --- a/third_party/blink/renderer/core/exported/web_surrounding_text.cc +++ b/third_party/blink/renderer/core/editing/surrounding_text.cc
@@ -23,7 +23,7 @@ * DAMAGE. */ -#include "third_party/blink/public/web/web_surrounding_text.h" +#include "third_party/blink/renderer/core/editing/surrounding_text.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" @@ -33,32 +33,28 @@ #include "third_party/blink/renderer/core/editing/iterators/character_iterator.h" #include "third_party/blink/renderer/core/editing/visible_selection.h" #include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/html/forms/html_form_control_element.h" namespace blink { namespace { -EphemeralRange ComputeRangeFromFrameSelection(WebLocalFrame* frame) { - LocalFrame* web_frame = To<WebLocalFrameImpl>(frame)->GetFrame(); - +EphemeralRange ComputeRangeFromFrameSelection(LocalFrame* frame) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - web_frame->GetDocument()->UpdateStyleAndLayout(); + frame->GetDocument()->UpdateStyleAndLayout(); - return web_frame->Selection() + return frame->Selection() .ComputeVisibleSelectionInDOMTree() .ToNormalizedEphemeralRange(); } } // namespace -WebSurroundingText::WebSurroundingText(WebLocalFrame* frame, size_t max_length) - : WebSurroundingText(ComputeRangeFromFrameSelection(frame), max_length) {} +SurroundingText::SurroundingText(LocalFrame* frame, size_t max_length) + : SurroundingText(ComputeRangeFromFrameSelection(frame), max_length) {} -WebSurroundingText::WebSurroundingText(const EphemeralRange& range, - size_t max_length) +SurroundingText::SurroundingText(const EphemeralRange& range, size_t max_length) : start_offset_in_text_content_(0), end_offset_in_text_content_(0) { const Position start_position = range.StartPosition(); const Position end_position = range.EndPosition(); @@ -126,19 +122,19 @@ TextIteratorBehavior::EmitsObjectReplacementCharacterBehavior()); } -WebString WebSurroundingText::TextContent() const { +String SurroundingText::TextContent() const { return text_content_; } -size_t WebSurroundingText::StartOffsetInTextContent() const { +size_t SurroundingText::StartOffsetInTextContent() const { return start_offset_in_text_content_; } -size_t WebSurroundingText::EndOffsetInTextContent() const { +size_t SurroundingText::EndOffsetInTextContent() const { return end_offset_in_text_content_; } -bool WebSurroundingText::IsEmpty() const { +bool SurroundingText::IsEmpty() const { return text_content_.IsEmpty(); }
diff --git a/third_party/blink/public/web/web_surrounding_text.h b/third_party/blink/renderer/core/editing/surrounding_text.h similarity index 73% rename from third_party/blink/public/web/web_surrounding_text.h rename to third_party/blink/renderer/core/editing/surrounding_text.h index ae03edd..1891bad 100644 --- a/third_party/blink/public/web/web_surrounding_text.h +++ b/third_party/blink/renderer/core/editing/surrounding_text.h
@@ -22,48 +22,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SURROUNDING_TEXT_H_ -#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SURROUNDING_TEXT_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SURROUNDING_TEXT_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SURROUNDING_TEXT_H_ + +#include "third_party/blink/renderer/core/core_export.h" #if INSIDE_BLINK #include "third_party/blink/renderer/core/editing/forward.h" // nogncheck #endif -#include "third_party/blink/public/platform/web_string.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { -class WebLocalFrame; +class LocalFrame; -// WebSurroundingText is a Blink API that gives access to the SurroundingText +// SurroundingText is a Blink API that gives access to the SurroundingText // API. It allows caller to know the text surrounding a point or a range. -class WebSurroundingText { +class CORE_EXPORT SurroundingText { public: // Initializes the object with the current selection in a given frame. // The maximum length of the contents retrieved is defined by max_length. // It does not include the text inside the range. - BLINK_EXPORT WebSurroundingText(WebLocalFrame*, size_t max_length); + SurroundingText(LocalFrame*, size_t max_length); #if INSIDE_BLINK - BLINK_EXPORT WebSurroundingText(const EphemeralRange&, size_t max_length); + SurroundingText(const EphemeralRange&, size_t max_length); #endif - BLINK_EXPORT bool IsEmpty() const; + bool IsEmpty() const; // Surrounding text content retrieved. - BLINK_EXPORT WebString TextContent() const; + String TextContent() const; // Start offset of the initial text in the text content. - BLINK_EXPORT size_t StartOffsetInTextContent() const; + size_t StartOffsetInTextContent() const; // End offset of the initial text in the text content. - BLINK_EXPORT size_t EndOffsetInTextContent() const; + size_t EndOffsetInTextContent() const; private: - WebString text_content_; + String text_content_; size_t start_offset_in_text_content_; size_t end_offset_in_text_content_; }; } // namespace blink -#endif +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SURROUNDING_TEXT_H_
diff --git a/third_party/blink/renderer/core/exported/web_surrounding_text_test.cc b/third_party/blink/renderer/core/editing/surrounding_text_test.cc similarity index 79% rename from third_party/blink/renderer/core/exported/web_surrounding_text_test.cc rename to third_party/blink/renderer/core/editing/surrounding_text_test.cc index 4a087bc0..4809afa 100644 --- a/third_party/blink/renderer/core/exported/web_surrounding_text_test.cc +++ b/third_party/blink/renderer/core/editing/surrounding_text_test.cc
@@ -1,8 +1,8 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/public/web/web_surrounding_text.h" +#include "third_party/blink/renderer/core/editing/surrounding_text.h" #include <memory> #include "testing/gtest/include/gtest/gtest.h" @@ -18,7 +18,7 @@ namespace blink { -class WebSurroundingTextTest : public testing::Test { +class SurroundingTextTest : public testing::Test { protected: Document& GetDocument() const { return dummy_page_holder_->GetDocument(); } void SetHTML(const String&); @@ -31,27 +31,27 @@ std::unique_ptr<DummyPageHolder> dummy_page_holder_; }; -void WebSurroundingTextTest::SetUp() { +void SurroundingTextTest::SetUp() { dummy_page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600)); } -void WebSurroundingTextTest::SetHTML(const String& content) { +void SurroundingTextTest::SetHTML(const String& content) { GetDocument().body()->SetInnerHTMLFromString(content); GetDocument().UpdateStyleAndLayout(); } -EphemeralRange WebSurroundingTextTest::Select(int start, int end) { +EphemeralRange SurroundingTextTest::Select(int start, int end) { Element* element = GetDocument().getElementById("selection"); return EphemeralRange(Position(element->firstChild(), start), Position(element->firstChild(), end)); } -TEST_F(WebSurroundingTextTest, BasicCaretSelection) { +TEST_F(SurroundingTextTest, BasicCaretSelection) { SetHTML(String("<p id='selection'>foo bar</p>")); { EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 1); + SurroundingText surrounding_text(selection, 1); EXPECT_EQ("f", surrounding_text.TextContent()); EXPECT_EQ(0u, surrounding_text.StartOffsetInTextContent()); @@ -60,7 +60,7 @@ { EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 5); + SurroundingText surrounding_text(selection, 5); // maxlength/2 is used on the left and right. EXPECT_EQ("foo", @@ -71,7 +71,7 @@ { EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 42); + SurroundingText surrounding_text(selection, 42); EXPECT_EQ("foo bar", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -81,7 +81,7 @@ { EphemeralRange selection = Select(7); - WebSurroundingText surrounding_text(selection, 42); + SurroundingText surrounding_text(selection, 42); EXPECT_EQ("foo bar", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -91,7 +91,7 @@ { EphemeralRange selection = Select(6); - WebSurroundingText surrounding_text(selection, 2); + SurroundingText surrounding_text(selection, 2); EXPECT_EQ("ar", surrounding_text.TextContent()); EXPECT_EQ(1u, surrounding_text.StartOffsetInTextContent()); @@ -100,7 +100,7 @@ { EphemeralRange selection = Select(6); - WebSurroundingText surrounding_text(selection, 42); + SurroundingText surrounding_text(selection, 42); EXPECT_EQ("foo bar", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -109,12 +109,12 @@ } } -TEST_F(WebSurroundingTextTest, BasicRangeSelection) { +TEST_F(SurroundingTextTest, BasicRangeSelection) { SetHTML(String("<p id='selection'>Lorem ipsum dolor sit amet</p>")); { EphemeralRange selection = Select(0, 5); - WebSurroundingText surrounding_text(selection, 1); + SurroundingText surrounding_text(selection, 1); EXPECT_EQ("Lorem ", surrounding_text.TextContent()); EXPECT_EQ(0u, surrounding_text.StartOffsetInTextContent()); @@ -123,7 +123,7 @@ { EphemeralRange selection = Select(0, 5); - WebSurroundingText surrounding_text(selection, 5); + SurroundingText surrounding_text(selection, 5); EXPECT_EQ("Lorem ip", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -133,7 +133,7 @@ { EphemeralRange selection = Select(0, 5); - WebSurroundingText surrounding_text(selection, 42); + SurroundingText surrounding_text(selection, 42); EXPECT_EQ("Lorem ipsum dolor sit amet", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -143,7 +143,7 @@ { EphemeralRange selection = Select(6, 11); - WebSurroundingText surrounding_text(selection, 2); + SurroundingText surrounding_text(selection, 2); EXPECT_EQ(" ipsum ", surrounding_text.TextContent()); EXPECT_EQ(1u, surrounding_text.StartOffsetInTextContent()); @@ -152,7 +152,7 @@ { EphemeralRange selection = Select(6, 11); - WebSurroundingText surrounding_text(selection, 42); + SurroundingText surrounding_text(selection, 42); EXPECT_EQ("Lorem ipsum dolor sit amet", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -163,7 +163,7 @@ { // Last word. EphemeralRange selection = Select(22, 26); - WebSurroundingText surrounding_text(selection, 8); + SurroundingText surrounding_text(selection, 8); EXPECT_EQ("sit amet", surrounding_text.TextContent()); EXPECT_EQ(4u, surrounding_text.StartOffsetInTextContent()); @@ -171,14 +171,14 @@ } } -TEST_F(WebSurroundingTextTest, TreeCaretSelection) { +TEST_F(SurroundingTextTest, TreeCaretSelection) { SetHTML( String("<div>This is outside of <p id='selection'>foo bar</p> the " "selected node</div>")); { EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 1); + SurroundingText surrounding_text(selection, 1); EXPECT_EQ("f", surrounding_text.TextContent()); EXPECT_EQ(0u, surrounding_text.StartOffsetInTextContent()); @@ -187,7 +187,7 @@ { EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 5); + SurroundingText surrounding_text(selection, 5); EXPECT_EQ("foo", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -197,7 +197,7 @@ { EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 1337); + SurroundingText surrounding_text(selection, 1337); EXPECT_EQ("This is outside of foo bar the selected node", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -207,7 +207,7 @@ { EphemeralRange selection = Select(6); - WebSurroundingText surrounding_text(selection, 2); + SurroundingText surrounding_text(selection, 2); EXPECT_EQ("ar", surrounding_text.TextContent()); EXPECT_EQ(1u, surrounding_text.StartOffsetInTextContent()); @@ -216,7 +216,7 @@ { EphemeralRange selection = Select(6); - WebSurroundingText surrounding_text(selection, 1337); + SurroundingText surrounding_text(selection, 1337); EXPECT_EQ("This is outside of foo bar the selected node", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -225,14 +225,14 @@ } } -TEST_F(WebSurroundingTextTest, TreeRangeSelection) { +TEST_F(SurroundingTextTest, TreeRangeSelection) { SetHTML( String("<div>This is outside of <p id='selection'>foo bar</p> the " "selected node</div>")); { EphemeralRange selection = Select(0, 1); - WebSurroundingText surrounding_text(selection, 1); + SurroundingText surrounding_text(selection, 1); EXPECT_EQ("fo", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -242,7 +242,7 @@ { EphemeralRange selection = Select(0, 3); - WebSurroundingText surrounding_text(selection, 12); + SurroundingText surrounding_text(selection, 12); EXPECT_EQ("e of foo bar", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -252,7 +252,7 @@ { EphemeralRange selection = Select(0, 3); - WebSurroundingText surrounding_text(selection, 1337); + SurroundingText surrounding_text(selection, 1337); EXPECT_EQ("This is outside of foo bar the selected node", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -262,7 +262,7 @@ { EphemeralRange selection = Select(4, 7); - WebSurroundingText surrounding_text(selection, 12); + SurroundingText surrounding_text(selection, 12); EXPECT_EQ("foo bar the se", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -272,7 +272,7 @@ { EphemeralRange selection = Select(0, 7); - WebSurroundingText surrounding_text(selection, 1337); + SurroundingText surrounding_text(selection, 1337); EXPECT_EQ("This is outside of foo bar the selected node", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -281,19 +281,19 @@ } } -TEST_F(WebSurroundingTextTest, TextAreaSelection) { +TEST_F(SurroundingTextTest, TextAreaSelection) { SetHTML( String("<p>First paragraph</p>" "<textarea id='selection'>abc def ghi</textarea>" "<p>Second paragraph</p>")); - TextControlElement* text_ctrl = - (TextControlElement*)GetDocument().getElementById("selection"); + TextControlElement* text_ctrl = reinterpret_cast<TextControlElement*>( + GetDocument().getElementById("selection")); text_ctrl->SetSelectionRange(4, 7); EphemeralRange selection = text_ctrl->Selection().ComputeRange(); - WebSurroundingText surrounding_text(selection, 20); + SurroundingText surrounding_text(selection, 20); EXPECT_EQ("abc def ghi", String(surrounding_text.TextContent()).SimplifyWhiteSpace()); @@ -301,11 +301,11 @@ EXPECT_EQ(7u, surrounding_text.EndOffsetInTextContent()); } -TEST_F(WebSurroundingTextTest, EmptyInputElementWithChild) { +TEST_F(SurroundingTextTest, EmptyInputElementWithChild) { SetHTML(String("<input type=\"text\" id=\"input_name\"/>")); - TextControlElement* input_element = - (TextControlElement*)GetDocument().getElementById("input_name"); + TextControlElement* input_element = reinterpret_cast<TextControlElement*>( + GetDocument().getElementById("input_name")); input_element->SetInnerEditorValue("John Smith"); GetDocument().UpdateStyleAndLayout(); @@ -320,11 +320,11 @@ const Position end = Position(inner_editor, 0); // Surrounding text should not crash. See http://crbug.com/758438. - WebSurroundingText surrounding_text(EphemeralRange(start, end), 8); + SurroundingText surrounding_text(EphemeralRange(start, end), 8); EXPECT_TRUE(surrounding_text.TextContent().IsEmpty()); } -TEST_F(WebSurroundingTextTest, ButtonsAndParagraph) { +TEST_F(SurroundingTextTest, ButtonsAndParagraph) { SetHTML( String("<button>.</button>12345" "<p id='selection'>6789 12345</p>" @@ -332,7 +332,7 @@ { EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 100); + SurroundingText surrounding_text(selection, 100); EXPECT_EQ("12345\n6789 12345\n\n6789", surrounding_text.TextContent()); EXPECT_EQ(6u, surrounding_text.StartOffsetInTextContent()); @@ -341,7 +341,7 @@ { EphemeralRange selection = Select(5); - WebSurroundingText surrounding_text(selection, 6); + SurroundingText surrounding_text(selection, 6); EXPECT_EQ("89 123", surrounding_text.TextContent()); EXPECT_EQ(3u, surrounding_text.StartOffsetInTextContent()); @@ -350,14 +350,14 @@ { EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 0); + SurroundingText surrounding_text(selection, 0); EXPECT_TRUE(surrounding_text.TextContent().IsEmpty()); } { EphemeralRange selection = Select(5); - WebSurroundingText surrounding_text(selection, 1); + SurroundingText surrounding_text(selection, 1); EXPECT_EQ("1", surrounding_text.TextContent()); EXPECT_EQ(0u, surrounding_text.StartOffsetInTextContent()); @@ -366,7 +366,7 @@ { EphemeralRange selection = Select(6); - WebSurroundingText surrounding_text(selection, 2); + SurroundingText surrounding_text(selection, 2); EXPECT_EQ("12", surrounding_text.TextContent()); EXPECT_EQ(1u, surrounding_text.StartOffsetInTextContent()); @@ -374,7 +374,7 @@ } } -TEST_F(WebSurroundingTextTest, SelectElementAndText) { +TEST_F(SurroundingTextTest, SelectElementAndText) { SetHTML(String( "<select>.</select>" "<div>57th Street and Lake Shore Drive</div>" @@ -382,7 +382,7 @@ "<select>.</select>")); EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 100); + SurroundingText surrounding_text(selection, 100); EXPECT_EQ("\xEF\xBF\xBC\n57th Street and Lake Shore Drive\nChicago IL 60637", surrounding_text.TextContent().Utf8()); @@ -390,21 +390,21 @@ EXPECT_EQ(43u, surrounding_text.EndOffsetInTextContent()); } -TEST_F(WebSurroundingTextTest, FieldsetElementAndText) { +TEST_F(SurroundingTextTest, FieldsetElementAndText) { SetHTML( String("<fieldset>.</fieldset>12345<button>abc</button>" "<p>6789<br><span id='selection'>12345</span></p>" "6789<textarea>abc</textarea>0123<fieldset>.</fieldset>")); EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 100); + SurroundingText surrounding_text(selection, 100); EXPECT_EQ("\n6789\n12345\n\n6789", surrounding_text.TextContent()); EXPECT_EQ(6u, surrounding_text.StartOffsetInTextContent()); EXPECT_EQ(6u, surrounding_text.EndOffsetInTextContent()); } -TEST_F(WebSurroundingTextTest, ButtonScriptAndComment) { +TEST_F(SurroundingTextTest, ButtonScriptAndComment) { SetHTML( String("<button>.</button>" "<div id='selection'>This is <!-- comment --!>a test " @@ -412,28 +412,28 @@ "example<button>.</button>")); EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 100); + SurroundingText surrounding_text(selection, 100); EXPECT_EQ("\nThis is a test example", surrounding_text.TextContent()); EXPECT_EQ(1u, surrounding_text.StartOffsetInTextContent()); EXPECT_EQ(1u, surrounding_text.EndOffsetInTextContent()); } -TEST_F(WebSurroundingTextTest, ButtonAndLongDiv) { +TEST_F(SurroundingTextTest, ButtonAndLongDiv) { SetHTML( String("<button>.</button>" "<div id='selection'>012345678901234567890123456789</div>" "<button>.</button>")); EphemeralRange selection = Select(15); - WebSurroundingText surrounding_text(selection, 12); + SurroundingText surrounding_text(selection, 12); EXPECT_EQ("901234567890", surrounding_text.TextContent()); EXPECT_EQ(6u, surrounding_text.StartOffsetInTextContent()); EXPECT_EQ(6u, surrounding_text.EndOffsetInTextContent()); } -TEST_F(WebSurroundingTextTest, EmptyWebSurroundingTextInOptionsAndButton) { +TEST_F(SurroundingTextTest, EmptySurroundingTextInOptionsAndButton) { SetHTML( String("<option>.</option>12345" "<button id='selection'>test</button>" @@ -441,24 +441,24 @@ { EphemeralRange selection = Select(1); - WebSurroundingText surrounding_text(selection, 100); + SurroundingText surrounding_text(selection, 100); EXPECT_TRUE(surrounding_text.TextContent().IsEmpty()); } { EphemeralRange selection = Select(3); - WebSurroundingText surrounding_text(selection, 100); + SurroundingText surrounding_text(selection, 100); EXPECT_TRUE(surrounding_text.TextContent().IsEmpty()); } } -TEST_F(WebSurroundingTextTest, SingleDotParagraph) { +TEST_F(SurroundingTextTest, SingleDotParagraph) { SetHTML(String("<p id='selection'>.</p>")); EphemeralRange selection = Select(0); - WebSurroundingText surrounding_text(selection, 2); + SurroundingText surrounding_text(selection, 2); EXPECT_EQ("\n.", surrounding_text.TextContent()); EXPECT_EQ(1u, surrounding_text.StartOffsetInTextContent());
diff --git a/third_party/blink/renderer/core/exported/BUILD.gn b/third_party/blink/renderer/core/exported/BUILD.gn index b0afed24..e28dd92 100644 --- a/third_party/blink/renderer/core/exported/BUILD.gn +++ b/third_party/blink/renderer/core/exported/BUILD.gn
@@ -73,7 +73,6 @@ "web_settings_impl.h", "web_shared_worker_impl.cc", "web_shared_worker_impl.h", - "web_surrounding_text.cc", "web_text_checking_result.cc", "web_user_gesture_indicator.cc", "web_user_gesture_token.cc",
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc index 40ab28f..975d53a 100644 --- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc +++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -175,9 +175,8 @@ void SetHasScrollEventHandlers(LocalFrame* frame, bool has_event_handlers) override { - DCHECK(frame->IsMainFrame()); - if (popup_->layer_tree_view_) - popup_->layer_tree_view_->SetHaveScrollEventHandlers(has_event_handlers); + // WebPagePopup's compositor does not handle compositor thread input (set up + // in RenderWidget) so there is no need to signal this. } void SetTouchAction(LocalFrame* frame, TouchAction touch_action) override {
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc index dd3ba27..d728705 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -672,6 +672,10 @@ injected_scroll_gesture_data_.push_back(data); } +void TestWebWidgetClient::SetHaveScrollEventHandlers(bool have_handlers) { + have_scroll_event_handlers_ = have_handlers; +} + void TestWebWidgetClient::SetEventListenerProperties( cc::EventListenerClass event_class, cc::EventListenerProperties properties) {
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h index 725df37..d2a3b9130 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.h +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -210,7 +210,7 @@ explicit TestWebWidgetClient(content::LayerTreeViewDelegate* = nullptr); ~TestWebWidgetClient() override = default; - // WebWidgetClient: + // WebWidgetClient implementation. void ScheduleAnimation() override { animation_scheduled_ = true; } void SetRootLayer(scoped_refptr<cc::Layer> layer) override; void RegisterViewportLayers(const cc::ViewportLayers& layOAers) override; @@ -226,6 +226,7 @@ ScrollGranularity granularity, cc::ElementId scrollable_area_element_id, WebInputEvent::Type injected_type) override; + void SetHaveScrollEventHandlers(bool) override; void SetEventListenerProperties( cc::EventListenerClass event_class, cc::EventListenerProperties properties) override; @@ -235,6 +236,7 @@ override; void StartDeferringCommits(base::TimeDelta timeout) override; void StopDeferringCommits(cc::PaintHoldingCommitTrigger) override; + void DidMeaningfulLayout(WebMeaningfulLayout) override; content::LayerTreeView* layer_tree_view() { return layer_tree_view_; } cc::LayerTreeHost* layer_tree_host() { @@ -248,7 +250,8 @@ bool AnimationScheduled() { return animation_scheduled_; } void ClearAnimationScheduled() { animation_scheduled_ = false; } - void DidMeaningfulLayout(WebMeaningfulLayout) override; + // Returns the last value given to SetHaveScrollEventHandlers(). + bool HaveScrollEventHandlers() const { return have_scroll_event_handlers_; } int VisuallyNonEmptyLayoutCount() const { return visually_non_empty_layout_count_; @@ -270,6 +273,7 @@ LayerTreeViewFactory layer_tree_view_factory_; Vector<InjectedScrollGestureData> injected_scroll_gesture_data_; bool animation_scheduled_ = false; + bool have_scroll_event_handlers_ = false; int visually_non_empty_layout_count_ = 0; int finished_parsing_layout_count_ = 0; int finished_loading_layout_count_ = 0; @@ -365,6 +369,9 @@ content::LayerTreeView* GetLayerTreeView() const { return test_web_widget_client_->layer_tree_view(); } + TestWebWidgetClient* GetWebWidgetClient() const { + return test_web_widget_client_; + } WebLocalFrameImpl* LocalMainFrame() const; WebRemoteFrameImpl* RemoteMainFrame() const;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 1985d03..54ca4aa1 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -990,9 +990,14 @@ } FloatSize LocalFrameView::ViewportSizeForMediaQueries() const { - FloatSize viewport_size(GetLayoutSize()); - if (!frame_->GetDocument() || !frame_->GetDocument()->Printing()) - viewport_size.Scale(1 / GetFrame().PageZoomFactor()); + FloatSize viewport_size(layout_size_); + if (!frame_->GetDocument()->Printing()) { + float zoom = GetFrame().PageZoomFactor(); + viewport_size.SetWidth( + AdjustForAbsoluteZoom::AdjustInt(layout_size_.Width(), zoom)); + viewport_size.SetHeight( + AdjustForAbsoluteZoom::AdjustInt(layout_size_.Height(), zoom)); + } return viewport_size; }
diff --git a/third_party/blink/renderer/core/frame/surrounding_text_impl.cc b/third_party/blink/renderer/core/frame/surrounding_text_impl.cc index 9817788..43516b1 100644 --- a/third_party/blink/renderer/core/frame/surrounding_text_impl.cc +++ b/third_party/blink/renderer/core/frame/surrounding_text_impl.cc
@@ -7,7 +7,7 @@ #include <utility> #include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/public/web/web_surrounding_text.h" +#include "third_party/blink/renderer/core/editing/surrounding_text.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/platform/heap/persistent.h" @@ -35,7 +35,7 @@ void SurroundingTextImpl::GetTextSurroundingSelection( uint32_t max_length, GetTextSurroundingSelectionCallback callback) { - blink::WebSurroundingText surrounding_text(frame_, max_length); + blink::SurroundingText surrounding_text(frame_->GetFrame(), max_length); if (surrounding_text.IsEmpty()) { // |surrounding_text| might not be correctly initialized, for example if
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 9ddb242..f3b5dc3 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -3513,9 +3513,21 @@ ImageChanged(static_cast<WrappedImagePtr>(image), defer); } -void LayoutObject::ImageNotifyFinished(ImageResourceContent*) { +void LayoutObject::ImageNotifyFinished(ImageResourceContent* image) { if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) cache->ImageLoaded(this); + + if (RuntimeEnabledFeatures::ElementTimingEnabled(&GetDocument())) { + LocalDOMWindow* window = GetDocument().domWindow(); + if (window) { + ImageElementTiming::From(*window).NotifyImageFinished(*this, image); + } + } + if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) { + if (LocalFrameView* frame_view = GetFrameView()) { + frame_view->GetPaintTimingDetector().NotifyImageFinished(*this, image); + } + } } Element* LayoutObject::OffsetParent(const Element* base) const {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc index 885a1b3..1b483aa 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
@@ -21,60 +21,6 @@ // kMainSize - width / height enum class LengthResolveType { kMinSize, kMaxSize, kMainSize }; -bool ContentShrinkToFitMayChange(const ComputedStyle& style, - const NGConstraintSpace& new_space, - const NGConstraintSpace& old_space, - const NGLayoutResult& layout_result) { - if (old_space.AvailableSize().inline_size == - new_space.AvailableSize().inline_size) - return false; - - NGBoxStrut margins = ComputeMarginsForSelf(new_space, style); - -#if DCHECK_IS_ON() - // The margins must be the same, as this function won't be called if we have - // percentage inline margins, and the percentage resolution size changes. - NGBoxStrut old_margins = ComputeMarginsForSelf(old_space, style); - DCHECK_EQ(margins.inline_start, old_margins.inline_start); - DCHECK_EQ(margins.inline_end, old_margins.inline_end); -#endif - - LayoutUnit old_available_inline_size = - std::max(LayoutUnit(), - old_space.AvailableSize().inline_size - margins.InlineSum()); - LayoutUnit new_available_inline_size = - std::max(LayoutUnit(), - new_space.AvailableSize().inline_size - margins.InlineSum()); - - LayoutUnit inline_size = - NGFragment(style.GetWritingMode(), layout_result.PhysicalFragment()) - .InlineSize(); - - // If the previous fragment was at its min-content size (indicated by the old - // available size being smaller than the fragment), we may be able to skip - // layout if the new available size is also smaller. - bool unaffected_as_min_content_size = - old_available_inline_size < inline_size && - new_available_inline_size <= inline_size; - - // If the previous fragment was at its max-content size (indicated by the old - // available size being larger than the fragment), we may be able to skip - // layout if the new available size is also larger. - bool unaffected_as_max_content_size = - old_available_inline_size > inline_size && - new_available_inline_size >= inline_size; - - // TODO(crbug.com/935634): There is an additional optimization where if we - // detect (by setting a flag in the layout result) that the - // min-content == max-content we can simply just skip layout, as the - // available size won't have any effect. - - if (unaffected_as_min_content_size || unaffected_as_max_content_size) - return false; - - return true; -} - inline bool InlineLengthMayChange(const ComputedStyle& style, const Length& length, LengthResolveType type, @@ -100,20 +46,6 @@ old_space.PercentageResolutionInlineSize())) return true; - // For elements which shrink to fit, we can perform a specific optimization - // where we can skip relayout if the element was sized to its min-content or - // max-content size. - bool is_content_shrink_to_fit = - type == LengthResolveType::kMainSize && - (new_space.IsShrinkToFit() || length.IsFitContent()); - - // TODO(ikilpatrick): Test if we can remove this optimization now that we - // compute the initial size of the fragment. - if (is_content_shrink_to_fit) { - return ContentShrinkToFitMayChange(style, new_space, old_space, - layout_result); - } - if (is_unspecified) { if (new_space.AvailableSize().inline_size != old_space.AvailableSize().inline_size)
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index d4fc2b1..6005d8c 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -1059,17 +1059,16 @@ void ChromeClientImpl::SetHasScrollEventHandlers(LocalFrame* frame, bool has_event_handlers) { - // |frame| might be null if called via TreeScopeAdopter:: - // moveNodeToNewDocument() and the new document has no frame attached. - // Since a document without a frame cannot attach one later, it is safe to - // exit early. + // |frame| might be null if called via + // TreeScopeAdopter::MoveNodeToNewDocument() and the new document has no frame + // attached. Since a document without a frame cannot attach one later, it is + // safe to exit early. if (!frame) return; - WebFrameWidgetBase* widget = - WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget(); - if (widget && widget->GetLayerTreeView()) - widget->GetLayerTreeView()->SetHaveScrollEventHandlers(has_event_handlers); + WebWidgetClient* client = + WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget()->Client(); + client->SetHaveScrollEventHandlers(has_event_handlers); } void ChromeClientImpl::SetNeedsLowLatencyInput(LocalFrame* frame,
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc index d9952417..26038093 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -127,13 +127,8 @@ WebViewImpl* GetWebView() const { return helper_.GetWebView(); } LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); } - - WebLayerTreeView* GetWebLayerTreeView() const { - return GetWebView()->LayerTreeView(); - } - - WebWidgetClient* GetWidgetClient() const { - return GetWebView()->WidgetClient(); + frame_test_helpers::TestWebWidgetClient* GetWidgetClient() const { + return helper_.GetWebWidgetClient(); } void LoadAhem() { helper_.LoadAhem(); } @@ -572,7 +567,7 @@ NavigateTo(base_url_ + "scroll-event-handler.html"); ForceFullCompositingUpdate(); - ASSERT_TRUE(GetWebLayerTreeView()->HaveScrollEventHandlers()); + ASSERT_TRUE(GetWidgetClient()->HaveScrollEventHandlers()); } TEST_P(ScrollingCoordinatorTest, updateEventHandlersDuringTeardown) {
diff --git a/third_party/blink/renderer/core/page/zoom_test.cc b/third_party/blink/renderer/core/page/zoom_test.cc new file mode 100644 index 0000000..487d9586 --- /dev/null +++ b/third_party/blink/renderer/core/page/zoom_test.cc
@@ -0,0 +1,30 @@ +// 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 "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/local_frame_view.h" +#include "third_party/blink/renderer/core/testing/sim/sim_test.h" + +namespace blink { + +class FractionalZoomSimTest : public SimTest {}; + +TEST_F(FractionalZoomSimTest, CheckCSSMediaQueryWidthEqualsWindowInnerWidth) { + WebView().MainFrameWidget()->Resize(WebSize(1081, 1921)); + + // 1081/2.75 = 393.091 + // 1081/2.00 = 540.500 + // 1081/1.50 = 720.667 + std::vector<float> factors = {2.75f, 2.00f, 1.50f}; + for (auto factor : factors) { + WebView().SetZoomFactorForDeviceScaleFactor(factor); + EXPECT_EQ(GetDocument().View()->ViewportSizeForMediaQueries().Width(), + GetDocument().GetFrame()->DomWindow()->innerWidth()); + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/paint/image_element_timing.cc b/third_party/blink/renderer/core/paint/image_element_timing.cc index 9541f0b7..25a4ce2 100644 --- a/third_party/blink/renderer/core/paint/image_element_timing.cc +++ b/third_party/blink/renderer/core/paint/image_element_timing.cc
@@ -65,6 +65,16 @@ GetSupplementable()->document())); } +void ImageElementTiming::NotifyImageFinished( + const LayoutObject& layout_object, + const ImageResourceContent* cached_image) { + if (!internal::IsExplicitlyRegisteredForTiming(&layout_object)) + return; + + images_notified_.Set(std::make_pair(&layout_object, cached_image), + ImageInfo(base::TimeTicks::Now())); +} + void ImageElementTiming::NotifyImagePainted( const LayoutObject* layout_object, const ImageResourceContent* cached_image, @@ -74,11 +84,13 @@ if (!internal::IsExplicitlyRegisteredForTiming(layout_object)) return; - auto result = - images_notified_.insert(std::make_pair(layout_object, cached_image)); - if (result.is_new_entry && cached_image) { + auto it = images_notified_.find(std::make_pair(layout_object, cached_image)); + DCHECK(it != images_notified_.end()); + if (!it->value.is_painted_ && cached_image) { + it->value.is_painted_ = true; NotifyImagePaintedInternal(layout_object->GetNode(), *layout_object, - *cached_image, current_paint_chunk_properties); + *cached_image, current_paint_chunk_properties, + it->value.load_time_); } } @@ -86,7 +98,8 @@ Node* node, const LayoutObject& layout_object, const ImageResourceContent& cached_image, - const PropertyTreeState& current_paint_chunk_properties) { + const PropertyTreeState& current_paint_chunk_properties, + base::TimeTicks load_time) { LocalFrame* frame = GetSupplementable()->GetFrame(); DCHECK(frame == layout_object.GetDocument().GetFrame()); DCHECK(node); @@ -134,7 +147,7 @@ // Create an entry with a |startTime| of 0. performance->AddElementTiming( ImagePaintString(), url.GetString(), intersection_rect, - base::TimeTicks(), cached_image.LoadResponseEnd(), attr, + base::TimeTicks(), load_time, attr, cached_image.IntrinsicSize(kDoNotRespectImageOrientation), id, element); } @@ -149,7 +162,7 @@ ? url.GetString().Left(kInlineImageMaxChars) : url.GetString(); element_timings_.emplace_back(MakeGarbageCollected<ElementTimingInfo>( - image_url, intersection_rect, cached_image.LoadResponseEnd(), attr, + image_url, intersection_rect, load_time, attr, cached_image.IntrinsicSize(kDoNotRespectImageOrientation), id, element)); // Only queue a swap promise when |element_timings_| was empty. All of the // records in |element_timings_| will be processed when the promise succeeds @@ -180,11 +193,20 @@ if (!cached_image || !cached_image->IsLoaded()) return; - auto result = - images_notified_.insert(std::make_pair(layout_object, cached_image)); - if (result.is_new_entry) { - NotifyImagePaintedInternal(node, *layout_object, *cached_image, - current_paint_chunk_properties); + std::pair<const LayoutObject*, const ImageResourceContent*> pair = + std::make_pair(layout_object, cached_image); + auto it = images_notified_.find(pair); + // TODO(crbug.com/986891): ideally |images_notified_| would always be able to + // find the pair here. However, for some background images that is currently + // not possible. Therefore, in those cases we create the entry here with + // loadTime of 0. Once the bug is fixed, we should replace that with a DCHECK. + if (it == images_notified_.end()) + images_notified_.Set(pair, ImageInfo(base::TimeTicks())); + if (!it->value.is_painted_ && cached_image) { + it->value.is_painted_ = true; + NotifyImagePaintedInternal(layout_object->GetNode(), *layout_object, + *cached_image, current_paint_chunk_properties, + it->value.load_time_); } }
diff --git a/third_party/blink/renderer/core/paint/image_element_timing.h b/third_party/blink/renderer/core/paint/image_element_timing.h index ea5b0e57..b0cd009c 100644 --- a/third_party/blink/renderer/core/paint/image_element_timing.h +++ b/third_party/blink/renderer/core/paint/image_element_timing.h
@@ -40,6 +40,8 @@ static ImageElementTiming& From(LocalDOMWindow&); + void NotifyImageFinished(const LayoutObject&, const ImageResourceContent*); + // Called when the LayoutObject has been painted. This method might queue a // swap promise to compute and report paint timestamps. void NotifyImagePainted( @@ -64,7 +66,8 @@ Node*, const LayoutObject&, const ImageResourceContent& cached_image, - const PropertyTreeState& current_paint_chunk_properties); + const PropertyTreeState& current_paint_chunk_properties, + base::TimeTicks load_time); // Callback for the swap promise. Reports paint timestamps. void ReportImagePaintSwapTime(WebWidgetClient::SwapResult, @@ -107,11 +110,20 @@ // Vector containing the element timing infos that will be reported during the // next swap promise callback. HeapVector<Member<ElementTimingInfo>> element_timings_; + struct ImageInfo { + // HashMap values require default constructor so we set default value for + // |load_time|. + ImageInfo(base::TimeTicks load_time = base::TimeTicks()) + : load_time_(load_time), is_painted_(false) {} + + base::TimeTicks load_time_; + bool is_painted_; + }; + typedef std::pair<const LayoutObject*, const ImageResourceContent*> RecordId; // Hashmap of pairs of elements, LayoutObjects (for the elements) and // ImageResourceContent (for the src) which correspond to either images or // background images whose paint has been observed. - WTF::HashSet<std::pair<const LayoutObject*, const ImageResourceContent*>> - images_notified_; + WTF::HashMap<RecordId, ImageInfo> images_notified_; DISALLOW_COPY_AND_ASSIGN(ImageElementTiming); };
diff --git a/third_party/blink/renderer/core/paint/image_element_timing_test.cc b/third_party/blink/renderer/core/paint/image_element_timing_test.cc index 7ab9bc9..bebc1d83 100644 --- a/third_party/blink/renderer/core/paint/image_element_timing_test.cc +++ b/third_party/blink/renderer/core/paint/image_element_timing_test.cc
@@ -55,10 +55,16 @@ return layout_image; } - const WTF::HashSet< - std::pair<const LayoutObject*, const ImageResourceContent*>>& - GetImagesNotified() { - return ImageElementTiming::From(*GetDoc()->domWindow()).images_notified_; + bool ImagesNotifiedContains( + const std::pair<const LayoutObject*, const ImageResourceContent*>& + record_id) { + return ImageElementTiming::From(*GetDoc()->domWindow()) + .images_notified_.Contains(record_id); + } + + unsigned ImagesNotifiedSize() { + return ImageElementTiming::From(*GetDoc()->domWindow()) + .images_notified_.size(); } Document* GetDoc() { @@ -143,7 +149,7 @@ LayoutImage* layout_image = SetImageResource("target", 5, 5); ASSERT_TRUE(layout_image); UpdateAllLifecyclePhases(); - EXPECT_FALSE(GetImagesNotified().Contains( + EXPECT_FALSE(ImagesNotifiedContains( std::make_pair(layout_image, layout_image->CachedImage()))); } @@ -165,7 +171,7 @@ UpdateAllLifecyclePhases(); // |layout_image| should have had its paint notified to ImageElementTiming. - EXPECT_TRUE(GetImagesNotified().Contains( + EXPECT_TRUE(ImagesNotifiedContains( std::make_pair(layout_image, layout_image->CachedImage()))); } @@ -178,13 +184,13 @@ LayoutImage* layout_image = SetImageResource("target", 5, 5); ASSERT_TRUE(layout_image); UpdateAllLifecyclePhases(); - EXPECT_TRUE(GetImagesNotified().Contains( + EXPECT_TRUE(ImagesNotifiedContains( std::make_pair(layout_image, layout_image->CachedImage()))); GetDoc()->getElementById("target")->remove(); // |layout_image| should no longer be part of |images_notified| since it will // be destroyed. - EXPECT_TRUE(GetImagesNotified().IsEmpty()); + EXPECT_EQ(ImagesNotifiedSize(), 0u); } TEST_F(ImageElementTimingTest, SVGImageRemoved) { @@ -198,13 +204,13 @@ LayoutSVGImage* layout_image = SetSVGImageResource("target", 5, 5); ASSERT_TRUE(layout_image); UpdateAllLifecyclePhases(); - EXPECT_TRUE(GetImagesNotified().Contains(std::make_pair( + EXPECT_TRUE(ImagesNotifiedContains(std::make_pair( layout_image, layout_image->ImageResource()->CachedImage()))); GetDoc()->getElementById("target")->remove(); // |layout_image| should no longer be part of |images_notified| since it will // be destroyed. - EXPECT_TRUE(GetImagesNotified().IsEmpty()); + EXPECT_EQ(ImagesNotifiedSize(), 0u); } TEST_F(ImageElementTimingTest, BackgroundImageRemoved) { @@ -224,11 +230,11 @@ ImageResourceContent* content = object->Style()->BackgroundLayers().GetImage()->CachedImage(); UpdateAllLifecyclePhases(); - EXPECT_EQ(GetImagesNotified().size(), 1u); - EXPECT_TRUE(GetImagesNotified().Contains(std::make_pair(object, content))); + EXPECT_EQ(ImagesNotifiedSize(), 1u); + EXPECT_TRUE(ImagesNotifiedContains(std::make_pair(object, content))); GetDoc()->getElementById("target")->remove(); - EXPECT_TRUE(GetImagesNotified().IsEmpty()); + EXPECT_EQ(ImagesNotifiedSize(), 0u); } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc index 09ce324b..25be884 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -169,6 +169,7 @@ if (!is_recording_) return; RecordId record_id = std::make_pair(&object, cached_image); + records_manager_.RemoveImageFinishedRecord(record_id); if (!records_manager_.IsRecordedVisibleImage(record_id)) return; records_manager_.RemoveVisibleRecord(record_id); @@ -280,12 +281,25 @@ } } +void ImagePaintTimingDetector::NotifyImageFinished( + const LayoutObject& object, + const ImageResourceContent* cached_image) { + RecordId record_id = std::make_pair(&object, cached_image); + records_manager_.NotifyImageFinished(record_id); +} + ImageRecordsManager::ImageRecordsManager() : size_ordered_set_(&LargeImageFirst) {} void ImageRecordsManager::OnImageLoaded(const RecordId& record_id, unsigned current_frame_index) { base::WeakPtr<ImageRecord> record = FindVisibleRecord(record_id); + DCHECK(record); + // TODO(crbug.com/986891): some background images are not being tracked + // properly, so we cannot add a DCHECK that |image_finished_times| contains + // |record_id|. Once that bug is fixed, we should add that check, as otherwise + // we'll be exposing a loadTime of 0. + record->load_time = image_finished_times_.at(record_id); OnImageLoadedInternal(record, current_frame_index); }
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h index 84be249f..9d310649 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
@@ -49,6 +49,7 @@ unsigned insertion_index; // The time of the first paint after fully loaded. 0 means not painted yet. base::TimeTicks paint_time = base::TimeTicks(); + base::TimeTicks load_time = base::TimeTicks(); bool loaded = false; }; @@ -75,6 +76,10 @@ invisible_images_.erase(&object); } + inline void RemoveImageFinishedRecord(const RecordId& record_id) { + image_finished_times_.erase(record_id); + } + inline void RemoveVisibleRecord(const RecordId& record_id) { base::WeakPtr<ImageRecord> record = visible_images_.find(record_id)->value->AsWeakPtr(); @@ -95,6 +100,16 @@ return invisible_images_.Contains(&object); } + void NotifyImageFinished(const RecordId& record_id) { + // TODO(npm): Ideally NotifyImageFinished() would only be called when the + // record has not yet been inserted in |image_finished_times_| but that's + // not currently the case. If we plumb some information from + // ImageResourceContent we may be able to ensure that this call does not + // require the Contains() check, which would save time. + if (!image_finished_times_.Contains(record_id)) + image_finished_times_.insert(record_id, base::TimeTicks::Now()); + } + inline bool IsVisibleImageLoaded(const RecordId& record_id) const { DCHECK(visible_images_.Contains(record_id)); return visible_images_.at(record_id)->loaded; @@ -156,6 +171,9 @@ // |ImageRecord|s waiting for paint time are stored in this queue // until they get a swap time. Deque<base::WeakPtr<ImageRecord>> images_queued_for_paint_time_; + // Map containing timestamps of when LayoutObject::ImageNotifyFinished is + // first called. + HashMap<RecordId, base::TimeTicks> image_finished_times_; DISALLOW_COPY_AND_ASSIGN(ImageRecordsManager); }; @@ -190,11 +208,7 @@ const IntSize& intrinsic_size, const ImageResourceContent&, const PropertyTreeState& current_paint_chunk_properties); - void RecordBackgroundImage( - const LayoutObject&, - const IntSize& intrinsic_size, - const ImageResourceContent& cached_image, - const PropertyTreeState& current_paint_chunk_properties); + void NotifyImageFinished(const LayoutObject&, const ImageResourceContent*); void OnPaintFinished(); void LayoutObjectWillBeDestroyed(const LayoutObject&); void NotifyImageRemoved(const LayoutObject&, const ImageResourceContent*);
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 08b42087..9af0352 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
@@ -128,7 +128,10 @@ ->records_manager_.size_ordered_set_.size() + GetPaintTimingDetector() .GetImagePaintTimingDetector() - ->records_manager_.images_queued_for_paint_time_.size(); + ->records_manager_.images_queued_for_paint_time_.size() + + GetPaintTimingDetector() + .GetImagePaintTimingDetector() + ->records_manager_.image_finished_times_.size(); } size_t CountChildFrameRecords() { @@ -629,7 +632,7 @@ )HTML"); SetImageAndPaint("target", 5, 5); UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); - EXPECT_EQ(ContainerTotalSize(), 2u); + EXPECT_EQ(ContainerTotalSize(), 3u); GetDocument().getElementById("parent")->RemoveChild( GetDocument().getElementById("target")); @@ -657,7 +660,7 @@ )HTML"); SetImageAndPaint("target", 5, 5); UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); - EXPECT_EQ(ContainerTotalSize(), 1u); + EXPECT_EQ(ContainerTotalSize(), 2u); EXPECT_EQ(CountInvisibleRecords(), 1u); GetDocument().body()->RemoveChild(GetDocument().getElementById("parent")); @@ -680,7 +683,7 @@ </div> )HTML"); UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); - EXPECT_EQ(ContainerTotalSize(), 2u); + EXPECT_EQ(ContainerTotalSize(), 3u); GetDocument().getElementById("parent")->RemoveChild( GetDocument().getElementById("target")); @@ -696,7 +699,7 @@ )HTML"); SetImageAndPaint("target", 5, 5); UpdateAllLifecyclePhases(); - EXPECT_EQ(ContainerTotalSize(), 3u); + EXPECT_EQ(ContainerTotalSize(), 4u); GetDocument().getElementById("parent")->RemoveChild( GetDocument().getElementById("target"));
diff --git a/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc b/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc index 692efaf..9ce51de3 100644 --- a/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc +++ b/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc
@@ -21,6 +21,7 @@ largest_image_->first_size = largest_image->first_size; largest_image_->paint_time = largest_image->paint_time; largest_image_->cached_image = largest_image->cached_image; + largest_image_->load_time = largest_image->load_time; } if (LargestImageSize() > LargestTextSize()) { @@ -95,7 +96,7 @@ image_element ? image_element->GetIdAttribute() : AtomicString(); window_performance_->OnLargestContentfulPaintUpdated( largest_image_->paint_time, largest_image_->first_size, - cached_image->LoadResponseEnd(), image_id, image_url, image_element); + largest_image_->load_time, image_id, image_url, image_element); } else { Node* text_node = DOMNodeIds::NodeForId(largest_text_->node_id); // |text_node| could be null and |largest_text_| should be ignored in this
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/third_party/blink/renderer/core/paint/paint_timing_detector.cc index d9be144e..88c7503 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -118,6 +118,13 @@ object, intrinsic_size, *cached_image, current_paint_chunk_properties); } +void PaintTimingDetector::NotifyImageFinished( + const LayoutObject& object, + const ImageResourceContent* cached_image) { + if (image_paint_timing_detector_) + image_paint_timing_detector_->NotifyImageFinished(object, cached_image); +} + void PaintTimingDetector::LayoutObjectWillBeDestroyed( const LayoutObject& object) { if (text_paint_timing_detector_)
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.h b/third_party/blink/renderer/core/paint/paint_timing_detector.h index 8f1c04d..92f2bb5 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.h
@@ -50,6 +50,7 @@ const PropertyTreeState& current_paint_chunk_properties); inline static void NotifyTextPaint(const IntRect& text_visual_rect); + void NotifyImageFinished(const LayoutObject&, const ImageResourceContent*); void LayoutObjectWillBeDestroyed(const LayoutObject&); void NotifyImageRemoved(const LayoutObject&, const ImageResourceContent*); void NotifyPaintFinished();
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/index.mjs b/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/index.mjs index 1eaff8a..18b48cc8 100644 --- a/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/index.mjs +++ b/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/index.mjs
@@ -13,6 +13,7 @@ import * as reflection from '../internal/reflection.mjs'; const DEFAULT_DURATION = 3000; +const TYPES = new Set(['success', 'warning', 'error']); function stylesheetFactory() { let stylesheet; @@ -38,6 +39,18 @@ .default-closebutton { user-select: none; } + + :host([type=success i]) { + border-color: green; + } + + :host([type=warning i]) { + border-color: orange; + } + + :host([type=error i]) { + border-color: red; + } `); // TODO(jacksteinberg): use offset-block-end: / offset-inline-end: over bottom: / right: // when implemented https://bugs.chromium.org/p/chromium/issues/detail?id=538475 @@ -127,6 +140,25 @@ } } + get type() { + const typeAttr = this.getAttribute('type'); + if (typeAttr === null) { + return ''; + } + + const typeAttrLower = typeAttr.toLowerCase(); + + if (TYPES.has(typeAttrLower)) { + return typeAttrLower; + } + + return ''; + } + + set type(val) { + this.setAttribute('type', val); + } + show({duration = DEFAULT_DURATION} = {}) { this.setAttribute('open', ''); clearTimeout(this.#timeoutID);
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.cc b/third_party/blink/renderer/core/timing/largest_contentful_paint.cc index 09824cf..40d2483 100644 --- a/third_party/blink/renderer/core/timing/largest_contentful_paint.cc +++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.cc
@@ -12,14 +12,14 @@ LargestContentfulPaint::LargestContentfulPaint(double render_time, uint64_t size, - double response_end, + double load_time, const AtomicString& id, const String& url, Element* element) : PerformanceEntry(g_empty_atom, 0, 0), size_(size), render_time_(render_time), - response_end_(response_end), + load_time_(load_time), id_(id), url_(url), element_(element) {} @@ -44,7 +44,8 @@ void LargestContentfulPaint::BuildJSONValue(V8ObjectBuilder& builder) const { PerformanceEntry::BuildJSONValue(builder); builder.Add("size", size_); - builder.Add("responseEnd", response_end_); + builder.Add("renderTime", render_time_); + builder.Add("loadTime", load_time_); builder.Add("id", id_); builder.Add("url", url_); builder.Add("element", element_);
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.h b/third_party/blink/renderer/core/timing/largest_contentful_paint.h index 8dc5ccb..ba0847d 100644 --- a/third_party/blink/renderer/core/timing/largest_contentful_paint.h +++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.h
@@ -19,7 +19,7 @@ public: LargestContentfulPaint(double render_time, uint64_t size, - double response_end, + double load_time, const AtomicString& id, const String& url, Element*); @@ -30,7 +30,7 @@ uint64_t size() const { return size_; } DOMHighResTimeStamp renderTime() const { return render_time_; } - DOMHighResTimeStamp responseEnd() const { return response_end_; } + DOMHighResTimeStamp loadTime() const { return load_time_; } const AtomicString& id() const { return id_; } const String& url() const { return url_; } Element* element() const; @@ -42,7 +42,7 @@ uint64_t size_; DOMHighResTimeStamp render_time_; - DOMHighResTimeStamp response_end_; + DOMHighResTimeStamp load_time_; AtomicString id_; String url_; WeakMember<Element> element_;
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.idl b/third_party/blink/renderer/core/timing/largest_contentful_paint.idl index d50a313..54cdaef 100644 --- a/third_party/blink/renderer/core/timing/largest_contentful_paint.idl +++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.idl
@@ -6,7 +6,7 @@ [Exposed=Window, RuntimeEnabled=LargestContentfulPaint] interface LargestContentfulPaint : PerformanceEntry { readonly attribute DOMHighResTimeStamp renderTime; - readonly attribute DOMHighResTimeStamp responseEnd; + readonly attribute DOMHighResTimeStamp loadTime; readonly attribute unsigned long long size; readonly attribute DOMString id; readonly attribute DOMString url;
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.cc b/third_party/blink/renderer/core/timing/performance_element_timing.cc index b369d6f4..1a03016 100644 --- a/third_party/blink/renderer/core/timing/performance_element_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_element_timing.cc
@@ -15,7 +15,7 @@ const String& url, const FloatRect& intersection_rect, DOMHighResTimeStamp render_time, - DOMHighResTimeStamp response_end, + DOMHighResTimeStamp load_time, const AtomicString& identifier, int naturalWidth, int naturalHeight, @@ -27,7 +27,7 @@ DCHECK_GE(naturalHeight, 0); DCHECK(element); return MakeGarbageCollected<PerformanceElementTiming>( - name, url, intersection_rect, render_time, response_end, identifier, + name, url, intersection_rect, render_time, load_time, identifier, naturalWidth, naturalHeight, id, element); } @@ -36,7 +36,7 @@ const String& url, const FloatRect& intersection_rect, DOMHighResTimeStamp render_time, - DOMHighResTimeStamp response_end, + DOMHighResTimeStamp load_time, const AtomicString& identifier, int naturalWidth, int naturalHeight, @@ -46,7 +46,7 @@ element_(element), intersection_rect_(DOMRectReadOnly::FromFloatRect(intersection_rect)), render_time_(render_time), - response_end_(response_end), + load_time_(load_time), identifier_(identifier), naturalWidth_(naturalWidth), naturalHeight_(naturalHeight), @@ -72,7 +72,15 @@ void PerformanceElementTiming::BuildJSONValue(V8ObjectBuilder& builder) const { PerformanceEntry::BuildJSONValue(builder); + builder.Add("renderTime", render_time_); + builder.Add("loadTime", load_time_); builder.Add("intersectionRect", intersection_rect_); + builder.Add("identifier", identifier_); + builder.Add("naturalWidth", naturalWidth_); + builder.Add("naturalHeight", naturalHeight_); + builder.Add("id", id_); + builder.Add("element", element()); + builder.Add("url", url_); } void PerformanceElementTiming::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.h b/third_party/blink/renderer/core/timing/performance_element_timing.h index 575b09a..f60fc2e0 100644 --- a/third_party/blink/renderer/core/timing/performance_element_timing.h +++ b/third_party/blink/renderer/core/timing/performance_element_timing.h
@@ -25,7 +25,7 @@ const String& url, const FloatRect& intersection_rect, DOMHighResTimeStamp render_time, - DOMHighResTimeStamp response_end, + DOMHighResTimeStamp load_time, const AtomicString& identifier, int naturalWidth, int naturalHeight, @@ -35,7 +35,7 @@ const String& url, const FloatRect& intersection_rect, DOMHighResTimeStamp render_time, - DOMHighResTimeStamp response_end, + DOMHighResTimeStamp load_time, const AtomicString& identifier, int naturalWidth, int naturalHeight, @@ -49,7 +49,7 @@ DOMRectReadOnly* intersectionRect() const { return intersection_rect_; } DOMHighResTimeStamp renderTime() const { return render_time_; } - DOMHighResTimeStamp responseEnd() const { return response_end_; } + DOMHighResTimeStamp loadTime() const { return load_time_; } AtomicString identifier() const { return identifier_; } unsigned naturalWidth() const { return naturalWidth_; } unsigned naturalHeight() const { return naturalHeight_; } @@ -65,7 +65,7 @@ WeakMember<Element> element_; Member<DOMRectReadOnly> intersection_rect_; DOMHighResTimeStamp render_time_; - DOMHighResTimeStamp response_end_; + DOMHighResTimeStamp load_time_; AtomicString identifier_; unsigned naturalWidth_; unsigned naturalHeight_;
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.idl b/third_party/blink/renderer/core/timing/performance_element_timing.idl index 0d7c088..e691f56 100644 --- a/third_party/blink/renderer/core/timing/performance_element_timing.idl +++ b/third_party/blink/renderer/core/timing/performance_element_timing.idl
@@ -6,7 +6,7 @@ [RuntimeEnabled=ElementTiming] interface PerformanceElementTiming : PerformanceEntry { readonly attribute DOMHighResTimeStamp renderTime; - readonly attribute DOMHighResTimeStamp responseEnd; + readonly attribute DOMHighResTimeStamp loadTime; readonly attribute DOMRectReadOnly intersectionRect; readonly attribute DOMString identifier; readonly attribute unsigned long naturalWidth;
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc index a7c70f6..2bc6e072 100644 --- a/third_party/blink/renderer/core/timing/window_performance.cc +++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -391,7 +391,7 @@ const String& url, const FloatRect& rect, base::TimeTicks start_time, - base::TimeTicks response_end, + base::TimeTicks load_time, const AtomicString& identifier, const IntSize& intrinsic_size, const AtomicString& id, @@ -399,7 +399,7 @@ DCHECK(RuntimeEnabledFeatures::ElementTimingEnabled(GetExecutionContext())); PerformanceElementTiming* entry = PerformanceElementTiming::Create( name, url, rect, MonotonicTimeToDOMHighResTimeStamp(start_time), - MonotonicTimeToDOMHighResTimeStamp(response_end), identifier, + MonotonicTimeToDOMHighResTimeStamp(load_time), identifier, intrinsic_size.Width(), intrinsic_size.Height(), id, element); if (HasObserverFor(PerformanceEntry::kElement)) { UseCounter::Count(GetExecutionContext(), @@ -442,13 +442,13 @@ void WindowPerformance::OnLargestContentfulPaintUpdated( base::TimeTicks paint_time, uint64_t paint_size, - base::TimeTicks response_end, + base::TimeTicks load_time, const AtomicString& id, const String& url, Element* element) { auto* entry = MakeGarbageCollected<LargestContentfulPaint>( MonotonicTimeToDOMHighResTimeStamp(paint_time), paint_size, - MonotonicTimeToDOMHighResTimeStamp(response_end), id, url, element); + MonotonicTimeToDOMHighResTimeStamp(load_time), id, url, element); if (HasObserverFor(PerformanceEntry::kLargestContentfulPaint)) NotifyObserversOfEntry(*entry); AddLargestContentfulPaint(entry);
diff --git a/third_party/blink/renderer/core/timing/window_performance.h b/third_party/blink/renderer/core/timing/window_performance.h index 383c55c..43fe1f4 100644 --- a/third_party/blink/renderer/core/timing/window_performance.h +++ b/third_party/blink/renderer/core/timing/window_performance.h
@@ -78,7 +78,7 @@ const String& url, const FloatRect& rect, base::TimeTicks start_time, - base::TimeTicks response_end, + base::TimeTicks load_time, const AtomicString& identifier, const IntSize& intrinsic_size, const AtomicString& id, @@ -90,7 +90,7 @@ void OnLargestContentfulPaintUpdated(base::TimeTicks paint_time, uint64_t paint_size, - base::TimeTicks response_end, + base::TimeTicks load_time, const AtomicString& id, const String& url, Element*);
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc index d36cb8f..ca69ced 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -69,6 +69,7 @@ void BaseRenderingContext2D::save() { state_stack_.back()->Save(); + ValidateStateStack(); } void BaseRenderingContext2D::restore() { @@ -124,6 +125,7 @@ sk_canvas->restore(); } } + ValidateStateStack(); } void BaseRenderingContext2D::Reset() {
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index bcbf7096..39c7b13 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -443,6 +443,8 @@ } cc::PaintCanvas* CanvasRenderingContext2D::ExistingDrawingCanvas() const { + if (isContextLost()) + return nullptr; if (IsPaintable()) return canvas()->GetCanvas2DLayerBridge()->Canvas(); return nullptr;
diff --git a/third_party/blink/renderer/modules/notifications/notification.cc b/third_party/blink/renderer/modules/notifications/notification.cc index 1806be1..88db765 100644 --- a/third_party/blink/renderer/modules/notifications/notification.cc +++ b/third_party/blink/renderer/modules/notifications/notification.cc
@@ -30,7 +30,11 @@ #include "third_party/blink/renderer/modules/notifications/notification.h" +#include <memory> +#include <utility> + #include "base/unguessable_token.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/platform/modules/notifications/web_notification_constants.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h" @@ -165,8 +169,7 @@ data_(std::move(data)), prepare_show_timer_(context->GetTaskRunner(TaskType::kMiscPlatformAPI), this, - &Notification::PrepareShow), - listener_binding_(this) { + &Notification::PrepareShow) { if (data_->show_trigger_timestamp.has_value()) { show_trigger_ = TimestampTrigger::Create(static_cast<DOMTimeStamp>( data_->show_trigger_timestamp.value().ToJsTime())); @@ -202,12 +205,13 @@ void Notification::DidLoadResources(NotificationResourcesLoader* loader) { DCHECK_EQ(loader, loader_.Get()); - mojom::blink::NonPersistentNotificationListenerPtr event_listener; + mojo::PendingRemote<mojom::blink::NonPersistentNotificationListener> + event_listener; scoped_refptr<base::SingleThreadTaskRunner> task_runner = GetExecutionContext()->GetTaskRunner(blink::TaskType::kInternalDefault); - listener_binding_.Bind(mojo::MakeRequest(&event_listener, task_runner), - task_runner); + listener_receiver_.Bind(event_listener.InitWithNewPipeAndPassReceiver(), + task_runner); NotificationManager::From(GetExecutionContext()) ->DisplayNonPersistentNotification(token_, data_->Clone(), @@ -478,7 +482,7 @@ } void Notification::ContextDestroyed(ExecutionContext* context) { - listener_binding_.Close(); + listener_receiver_.reset(); state_ = State::kClosed;
diff --git a/third_party/blink/renderer/modules/notifications/notification.h b/third_party/blink/renderer/modules/notifications/notification.h index b7492dd3..11347c6 100644 --- a/third_party/blink/renderer/modules/notifications/notification.h +++ b/third_party/blink/renderer/modules/notifications/notification.h
@@ -31,7 +31,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NOTIFICATIONS_NOTIFICATION_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_NOTIFICATIONS_NOTIFICATION_H_ -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "third_party/blink/public/mojom/notifications/notification_service.mojom-blink.h" #include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink.h" @@ -192,8 +192,8 @@ Member<NotificationResourcesLoader> loader_; - mojo::Binding<mojom::blink::NonPersistentNotificationListener> - listener_binding_; + mojo::Receiver<mojom::blink::NonPersistentNotificationListener> + listener_receiver_{this}; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/notifications/notification_manager.cc b/third_party/blink/renderer/modules/notifications/notification_manager.cc index 2e0a282..6aa4311 100644 --- a/third_party/blink/renderer/modules/notifications/notification_manager.cc +++ b/third_party/blink/renderer/modules/notifications/notification_manager.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/modules/notifications/notification_manager.h" +#include <utility> + #include "base/numerics/safe_conversions.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/mojom/notifications/notification.mojom-blink.h" @@ -117,7 +119,8 @@ const String& token, mojom::blink::NotificationDataPtr notification_data, mojom::blink::NotificationResourcesPtr notification_resources, - mojom::blink::NonPersistentNotificationListenerPtr event_listener) { + mojo::PendingRemote<mojom::blink::NonPersistentNotificationListener> + event_listener) { DCHECK(!token.IsEmpty()); DCHECK(notification_resources); GetNotificationService()->DisplayNonPersistentNotification( @@ -224,7 +227,7 @@ resolver->Resolve(notifications); } -const mojom::blink::NotificationServicePtr& +const mojo::Remote<mojom::blink::NotificationService>& NotificationManager::GetNotificationService() { if (!notification_service_) { if (auto* provider = GetSupplementable()->GetInterfaceProvider()) { @@ -232,9 +235,9 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner = GetSupplementable()->GetTaskRunner(TaskType::kMiscPlatformAPI); provider->GetInterface( - mojo::MakeRequest(¬ification_service_, std::move(task_runner))); + notification_service_.BindNewPipeAndPassReceiver(task_runner)); - notification_service_.set_connection_error_handler( + notification_service_.set_disconnect_handler( WTF::Bind(&NotificationManager::OnNotificationServiceConnectionError, WrapWeakPersistent(this))); }
diff --git a/third_party/blink/renderer/modules/notifications/notification_manager.h b/third_party/blink/renderer/modules/notifications/notification_manager.h index b0f90bc..abea5e77 100644 --- a/third_party/blink/renderer/modules/notifications/notification_manager.h +++ b/third_party/blink/renderer/modules/notifications/notification_manager.h
@@ -6,6 +6,8 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_NOTIFICATIONS_NOTIFICATION_MANAGER_H_ #include "base/macros.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/notifications/notification_service.mojom-blink.h" #include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h" #include "third_party/blink/public/platform/web_string.h" @@ -53,7 +55,8 @@ const String& token, mojom::blink::NotificationDataPtr notification_data, mojom::blink::NotificationResourcesPtr notification_resources, - mojom::blink::NonPersistentNotificationListenerPtr event_listener); + mojo::PendingRemote<mojom::blink::NonPersistentNotificationListener> + event_listener); // Closes the notification that was most recently displayed with this token. void CloseNonPersistentNotification(const String& token); @@ -89,9 +92,10 @@ const Vector<String>& notification_ids, Vector<mojom::blink::NotificationDataPtr> notification_datas); - // Returns an initialized NotificationServicePtr. A connection will be + // Returns an initialized NotificationService remote. A connection will be // established the first time this method is called. - const mojom::blink::NotificationServicePtr& GetNotificationService(); + const mojo::Remote<mojom::blink::NotificationService>& + GetNotificationService(); void OnPermissionRequestComplete( ScriptPromiseResolver* resolver, @@ -101,7 +105,7 @@ void OnNotificationServiceConnectionError(); void OnPermissionServiceConnectionError(); - mojom::blink::NotificationServicePtr notification_service_; + mojo::Remote<mojom::blink::NotificationService> notification_service_; mojom::blink::PermissionServicePtr permission_service_; DISALLOW_COPY_AND_ASSIGN(NotificationManager);
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 1fe682f9..a764b5e 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -257,6 +257,10 @@ "animation/compositor_animation_delegate.h", "animation/compositor_animation_timeline.cc", "animation/compositor_animation_timeline.h", + "animation/compositor_color_animation_curve.cc", + "animation/compositor_color_animation_curve.h", + "animation/compositor_color_keyframe.cc", + "animation/compositor_color_keyframe.h", "animation/compositor_filter_animation_curve.cc", "animation/compositor_filter_animation_curve.h", "animation/compositor_filter_keyframe.cc", @@ -1612,6 +1616,7 @@ "animation/animation_translation_util_test.cc", "animation/compositor_animation_test.cc", "animation/compositor_animation_timeline_test.cc", + "animation/compositor_color_animation_curve_test.cc", "animation/compositor_float_animation_curve_test.cc", "animation/compositor_keyframe_model_test.cc", "animation/timing_function_test.cc",
diff --git a/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.cc b/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.cc new file mode 100644 index 0000000..5e9b97c --- /dev/null +++ b/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.cc
@@ -0,0 +1,65 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h" + +#include <memory> +#include <utility> + +#include "base/memory/ptr_util.h" +#include "cc/animation/animation_curve.h" +#include "cc/animation/keyframed_animation_curve.h" +#include "cc/animation/timing_function.h" + +namespace blink { + +CompositorColorAnimationCurve::CompositorColorAnimationCurve() + : curve_(cc::KeyframedColorAnimationCurve::Create()) {} + +CompositorColorAnimationCurve::CompositorColorAnimationCurve( + std::unique_ptr<cc::KeyframedColorAnimationCurve> curve) + : curve_(std::move(curve)) {} + +CompositorColorAnimationCurve::~CompositorColorAnimationCurve() = default; + +std::unique_ptr<CompositorColorAnimationCurve> +CompositorColorAnimationCurve::CreateForTesting( + std::unique_ptr<cc::KeyframedColorAnimationCurve> curve) { + return base::WrapUnique(new CompositorColorAnimationCurve(std::move(curve))); +} + +CompositorColorAnimationCurve::Keyframes +CompositorColorAnimationCurve::KeyframesForTesting() const { + Keyframes keyframes; + for (const auto& cc_keyframe : curve_->keyframes_for_testing()) { + keyframes.push_back( + base::WrapUnique(new CompositorColorKeyframe(cc_keyframe->Clone()))); + } + return keyframes; +} + +void CompositorColorAnimationCurve::AddKeyframe( + const CompositorColorKeyframe& keyframe) { + curve_->AddKeyframe(keyframe.CloneToCC()); +} + +void CompositorColorAnimationCurve::SetTimingFunction( + const TimingFunction& timing_function) { + curve_->SetTimingFunction(timing_function.CloneToCC()); +} + +void CompositorColorAnimationCurve::SetScaledDuration(double scaled_duration) { + curve_->set_scaled_duration(scaled_duration); +} + +SkColor CompositorColorAnimationCurve::GetValue(double time) const { + return curve_->GetValue(base::TimeDelta::FromSecondsD(time)); +} + +std::unique_ptr<cc::AnimationCurve> +CompositorColorAnimationCurve::CloneToAnimationCurve() const { + return curve_->Clone(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h b/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h new file mode 100644 index 0000000..bbdbc9f --- /dev/null +++ b/third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h
@@ -0,0 +1,60 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_COLOR_ANIMATION_CURVE_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_COLOR_ANIMATION_CURVE_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/scoped_refptr.h" +#include "third_party/blink/renderer/platform/animation/compositor_animation_curve.h" +#include "third_party/blink/renderer/platform/animation/compositor_color_keyframe.h" +#include "third_party/blink/renderer/platform/animation/timing_function.h" +#include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace cc { +class KeyframedColorAnimationCurve; +} + +namespace blink { + +class CompositorColorKeyframe; + +// A keyframed color animation curve. +class PLATFORM_EXPORT CompositorColorAnimationCurve + : public CompositorAnimationCurve { + public: + CompositorColorAnimationCurve(); + ~CompositorColorAnimationCurve() override; + + void AddKeyframe(const CompositorColorKeyframe&); + void SetTimingFunction(const TimingFunction&); + void SetScaledDuration(double); + SkColor GetValue(double time) const; + + // CompositorAnimationCurve implementation. + std::unique_ptr<cc::AnimationCurve> CloneToAnimationCurve() const override; + + static std::unique_ptr<CompositorColorAnimationCurve> CreateForTesting( + std::unique_ptr<cc::KeyframedColorAnimationCurve>); + + using Keyframes = Vector<std::unique_ptr<CompositorColorKeyframe>>; + Keyframes KeyframesForTesting() const; + + private: + CompositorColorAnimationCurve( + std::unique_ptr<cc::KeyframedColorAnimationCurve>); + + std::unique_ptr<cc::KeyframedColorAnimationCurve> curve_; + + DISALLOW_COPY_AND_ASSIGN(CompositorColorAnimationCurve); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_COLOR_ANIMATION_CURVE_H_
diff --git a/third_party/blink/renderer/platform/animation/compositor_color_animation_curve_test.cc b/third_party/blink/renderer/platform/animation/compositor_color_animation_curve_test.cc new file mode 100644 index 0000000..e0f27cb --- /dev/null +++ b/third_party/blink/renderer/platform/animation/compositor_color_animation_curve_test.cc
@@ -0,0 +1,275 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h" + +#include <memory> + +#include "cc/animation/timing_function.h" +#include "testing/gtest/include/gtest/gtest.h" + +using blink::CompositorAnimationCurve; +using blink::CompositorColorAnimationCurve; +using blink::CompositorColorKeyframe; + +namespace blink { + +// Tests that a color animation with one keyframe works as expected. +TEST(WebColorAnimationCurveTest, OneColorKeyframe) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe(0, SK_ColorGREEN, + *LinearTimingFunction::Shared())); + EXPECT_EQ(SK_ColorGREEN, curve->GetValue(-1)); + EXPECT_EQ(SK_ColorGREEN, curve->GetValue(0)); + EXPECT_EQ(SK_ColorGREEN, curve->GetValue(0.5)); + EXPECT_EQ(SK_ColorGREEN, curve->GetValue(1)); + EXPECT_EQ(SK_ColorGREEN, curve->GetValue(2)); +} + +// Tests that a color animation with two keyframes works as expected. +TEST(WebColorAnimationCurveTest, TwoColorKeyframe) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe(0, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 200, 100), + *LinearTimingFunction::Shared())); + EXPECT_EQ(SkColorSetRGB(0, 100, 0), curve->GetValue(-1)); + EXPECT_EQ(SkColorSetRGB(0, 100, 0), curve->GetValue(0)); + EXPECT_EQ(SkColorSetRGB(0, 150, 50), curve->GetValue(0.5)); + EXPECT_EQ(SkColorSetRGB(0, 200, 100), curve->GetValue(1)); + EXPECT_EQ(SkColorSetRGB(0, 200, 100), curve->GetValue(2)); +} + +// Tests that a color animation with changing alpha channel +TEST(WebColorAnimationCurveTest, TwoAlphaKeyframe) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe(0, SkColorSetARGB(100, 0, 100, 0), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe( + 1, SkColorSetARGB(255, 0, 200, 100), *LinearTimingFunction::Shared())); + EXPECT_EQ(SkColorSetARGB(100, 0, 100, 0), curve->GetValue(-1)); + EXPECT_EQ(SkColorSetARGB(100, 0, 100, 0), curve->GetValue(0)); + EXPECT_EQ(SkColorSetARGB(178, 0, 172, 72), curve->GetValue(0.5)); + EXPECT_EQ(SkColorSetARGB(255, 0, 200, 100), curve->GetValue(1)); + EXPECT_EQ(SkColorSetARGB(255, 0, 200, 100), curve->GetValue(2)); +} + +// Tests that a color animation with three keyframes works as expected. +TEST(WebColorAnimationCurveTest, ThreeColorKeyframe) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe(0, SkColorSetRGB(0, 50, 0), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 50), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(2, SkColorSetRGB(0, 200, 200), + *LinearTimingFunction::Shared())); + EXPECT_EQ(SkColorSetRGB(0, 50, 0), curve->GetValue(-1)); + EXPECT_EQ(SkColorSetRGB(0, 50, 0), curve->GetValue(0)); + EXPECT_EQ(SkColorSetRGB(0, 75, 25), curve->GetValue(0.5)); + EXPECT_EQ(SkColorSetRGB(0, 100, 50), curve->GetValue(1)); + EXPECT_EQ(SkColorSetRGB(0, 150, 125), curve->GetValue(1.5)); + EXPECT_EQ(SkColorSetRGB(0, 200, 200), curve->GetValue(2)); + EXPECT_EQ(SkColorSetRGB(0, 200, 200), curve->GetValue(3)); +} + +// Tests that a color animation with multiple keys at a given time works sanely. +TEST(WebColorAnimationCurveTest, RepeatedColorKeyTimes) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe(0, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 200, 0), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(2, SkColorSetRGB(0, 200, 0), + *LinearTimingFunction::Shared())); + + EXPECT_EQ(SkColorSetRGB(0, 100, 0), curve->GetValue(-1)); + EXPECT_EQ(SkColorSetRGB(0, 100, 0), curve->GetValue(0)); + EXPECT_EQ(SkColorSetRGB(0, 100, 0), curve->GetValue(0.5)); + + // There is a discontinuity at 1. Any value between 100 and 200 in the green + // channel is valid + SkColor value = curve->GetValue(1); + EXPECT_EQ(SkColorGetR(value), 0U); + EXPECT_TRUE(SkColorGetG(value) >= 100U && SkColorGetG(value) <= 200U); + EXPECT_EQ(SkColorGetB(value), 0U); + + EXPECT_EQ(SkColorSetRGB(0, 200, 0), curve->GetValue(1.5)); + EXPECT_EQ(SkColorSetRGB(0, 200, 0), curve->GetValue(2)); + EXPECT_EQ(SkColorSetRGB(0, 200, 0), curve->GetValue(3)); +} + +// Tests that the keyframes may be added out of order. +TEST(WebColorAnimationCurveTest, UnsortedKeyframes) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe(2, SkColorSetRGB(0, 200, 200), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(0, SkColorSetRGB(0, 50, 0), + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 50), + *LinearTimingFunction::Shared())); + EXPECT_EQ(SkColorSetRGB(0, 50, 0), curve->GetValue(-1)); + EXPECT_EQ(SkColorSetRGB(0, 50, 0), curve->GetValue(0)); + EXPECT_EQ(SkColorSetRGB(0, 75, 25), curve->GetValue(0.5)); + EXPECT_EQ(SkColorSetRGB(0, 100, 50), curve->GetValue(1)); + EXPECT_EQ(SkColorSetRGB(0, 150, 125), curve->GetValue(1.5)); + EXPECT_EQ(SkColorSetRGB(0, 200, 200), curve->GetValue(2)); + EXPECT_EQ(SkColorSetRGB(0, 200, 200), curve->GetValue(3)); +} + +// Tests that a cubic bezier timing function works as expected. +TEST(WebColorAnimationCurveTest, CubicBezierTimingFunction) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + scoped_refptr<CubicBezierTimingFunction> cubic = + CubicBezierTimingFunction::Create(0.25, 0, 0.75, 1); + curve->AddKeyframe(CompositorColorKeyframe(0, SK_ColorBLACK, *cubic)); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + + EXPECT_EQ(0U, SkColorGetG(curve->GetValue(0))); + EXPECT_LT(0U, SkColorGetG(curve->GetValue(0.25))); + EXPECT_GT(25U, SkColorGetG(curve->GetValue(0.25))); + EXPECT_EQ(50U, SkColorGetG(curve->GetValue(0.5))); + EXPECT_LT(75U, SkColorGetG(curve->GetValue(0.75))); + EXPECT_GT(100U, SkColorGetG(curve->GetValue(0.75))); + EXPECT_EQ(100U, SkColorGetG(curve->GetValue(1))); +} + +// Tests that an ease timing function works as expected. +TEST(WebColorAnimationCurveTest, EaseTimingFunction) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe( + CompositorColorKeyframe(0, SK_ColorBLACK, + *CubicBezierTimingFunction::Preset( + CubicBezierTimingFunction::EaseType::EASE))); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + + std::unique_ptr<cc::TimingFunction> timing_function( + cc::CubicBezierTimingFunction::CreatePreset( + CubicBezierTimingFunction::EaseType::EASE)); + for (int i = 0; i <= 4; ++i) { + const double time = i * 0.25; + EXPECT_EQ((unsigned)round(timing_function->GetValue(time) * 100), + SkColorGetG(curve->GetValue(time))); + } +} + +// Tests using a linear timing function. +TEST(WebColorAnimationCurveTest, LinearTimingFunction) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe(0, SK_ColorBLACK, + *LinearTimingFunction::Shared())); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + + for (int i = 0; i <= 4; ++i) { + EXPECT_EQ(i * 25U, SkColorGetG(curve->GetValue(i * 0.25))); + } +} + +// Tests that an ease in timing function works as expected. +TEST(WebColorAnimationCurveTest, EaseInTimingFunction) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe( + 0, SK_ColorBLACK, + *CubicBezierTimingFunction::Preset( + CubicBezierTimingFunction::EaseType::EASE_IN))); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + + std::unique_ptr<cc::TimingFunction> timing_function( + cc::CubicBezierTimingFunction::CreatePreset( + CubicBezierTimingFunction::EaseType::EASE_IN)); + for (int i = 0; i <= 4; ++i) { + const double time = i * 0.25; + EXPECT_EQ((unsigned)round(timing_function->GetValue(time) * 100), + SkColorGetG(curve->GetValue(time))); + } +} + +// Tests that an ease in timing function works as expected. +TEST(WebColorAnimationCurveTest, EaseOutTimingFunction) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe( + 0, SK_ColorBLACK, + *CubicBezierTimingFunction::Preset( + CubicBezierTimingFunction::EaseType::EASE_OUT))); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + + std::unique_ptr<cc::TimingFunction> timing_function( + cc::CubicBezierTimingFunction::CreatePreset( + CubicBezierTimingFunction::EaseType::EASE_OUT)); + for (int i = 0; i <= 4; ++i) { + const double time = i * 0.25; + EXPECT_EQ((unsigned)round(timing_function->GetValue(time) * 100), + SkColorGetG(curve->GetValue(time))); + } +} + +// Tests that an ease in timing function works as expected. +TEST(WebColorAnimationCurveTest, EaseInOutTimingFunction) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe(CompositorColorKeyframe( + 0, SK_ColorBLACK, + *CubicBezierTimingFunction::Preset( + CubicBezierTimingFunction::EaseType::EASE_IN_OUT))); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + + std::unique_ptr<cc::TimingFunction> timing_function( + cc::CubicBezierTimingFunction::CreatePreset( + CubicBezierTimingFunction::EaseType::EASE_IN_OUT)); + for (int i = 0; i <= 4; ++i) { + const double time = i * 0.25; + EXPECT_EQ((unsigned)round(timing_function->GetValue(time) * 100), + SkColorGetG(curve->GetValue(time))); + } +} + +// Tests that an ease in timing function works as expected. +TEST(WebColorAnimationCurveTest, CustomBezierTimingFunction) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + double x1 = 0.3; + double y1 = 0.2; + double x2 = 0.8; + double y2 = 0.7; + scoped_refptr<CubicBezierTimingFunction> cubic = + CubicBezierTimingFunction::Create(x1, y1, x2, y2); + curve->AddKeyframe(CompositorColorKeyframe(0, SK_ColorBLACK, *cubic)); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + + std::unique_ptr<cc::TimingFunction> timing_function( + cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)); + for (int i = 0; i <= 4; ++i) { + const double time = i * 0.25; + EXPECT_EQ((unsigned)round(timing_function->GetValue(time) * 100), + SkColorGetG(curve->GetValue(time))); + } +} + +// Tests that the default timing function is indeed ease. +TEST(WebColorAnimationCurveTest, DefaultTimingFunction) { + auto curve = std::make_unique<CompositorColorAnimationCurve>(); + curve->AddKeyframe( + CompositorColorKeyframe(0, SK_ColorBLACK, + *CubicBezierTimingFunction::Preset( + CubicBezierTimingFunction::EaseType::EASE))); + curve->AddKeyframe(CompositorColorKeyframe(1, SkColorSetRGB(0, 100, 0), + *LinearTimingFunction::Shared())); + + std::unique_ptr<cc::TimingFunction> timing_function( + cc::CubicBezierTimingFunction::CreatePreset( + CubicBezierTimingFunction::EaseType::EASE)); + for (int i = 0; i <= 4; ++i) { + const double time = i * 0.25; + EXPECT_EQ((unsigned)round(timing_function->GetValue(time) * 100), + SkColorGetG(curve->GetValue(time))); + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/animation/compositor_color_keyframe.cc b/third_party/blink/renderer/platform/animation/compositor_color_keyframe.cc new file mode 100644 index 0000000..1f11e4d --- /dev/null +++ b/third_party/blink/renderer/platform/animation/compositor_color_keyframe.cc
@@ -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. + +#include "third_party/blink/renderer/platform/animation/compositor_color_keyframe.h" + +#include "third_party/blink/renderer/platform/animation/timing_function.h" + +namespace blink { + +CompositorColorKeyframe::CompositorColorKeyframe( + double time, + SkColor value, + const TimingFunction& timing_function) + : color_keyframe_( + cc::ColorKeyframe::Create(base::TimeDelta::FromSecondsD(time), + value, + timing_function.CloneToCC())) {} + +CompositorColorKeyframe::CompositorColorKeyframe( + std::unique_ptr<cc::ColorKeyframe> color_keyframe) + : color_keyframe_(std::move(color_keyframe)) {} + +CompositorColorKeyframe::~CompositorColorKeyframe() = default; + +double CompositorColorKeyframe::Time() const { + return color_keyframe_->Time().InSecondsF(); +} + +const cc::TimingFunction* CompositorColorKeyframe::CcTimingFunction() const { + return color_keyframe_->timing_function(); +} + +std::unique_ptr<cc::ColorKeyframe> CompositorColorKeyframe::CloneToCC() const { + return color_keyframe_->Clone(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/animation/compositor_color_keyframe.h b/third_party/blink/renderer/platform/animation/compositor_color_keyframe.h new file mode 100644 index 0000000..beb4fc1a --- /dev/null +++ b/third_party/blink/renderer/platform/animation/compositor_color_keyframe.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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_COLOR_KEYFRAME_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_COLOR_KEYFRAME_H_ + +#include "base/macros.h" +#include "cc/animation/keyframed_animation_curve.h" +#include "third_party/blink/renderer/platform/animation/compositor_keyframe.h" +#include "third_party/blink/renderer/platform/platform_export.h" + +namespace blink { + +class TimingFunction; + +class PLATFORM_EXPORT CompositorColorKeyframe : public CompositorKeyframe { + public: + CompositorColorKeyframe(double time, SkColor value, const TimingFunction&); + CompositorColorKeyframe(std::unique_ptr<cc::ColorKeyframe>); + ~CompositorColorKeyframe() override; + + // CompositorKeyframe implementation. + double Time() const override; + const cc::TimingFunction* CcTimingFunction() const override; + + SkColor Value() { return color_keyframe_->Value(); } + std::unique_ptr<cc::ColorKeyframe> CloneToCC() const; + + private: + std::unique_ptr<cc::ColorKeyframe> color_keyframe_; + + DISALLOW_COPY_AND_ASSIGN(CompositorColorKeyframe); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_ANIMATION_COMPOSITOR_COLOR_KEYFRAME_H_
diff --git a/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc b/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc index 60a8fb9..656f2f2 100644 --- a/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc +++ b/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc
@@ -10,6 +10,7 @@ #include "cc/animation/animation_id_provider.h" #include "cc/animation/keyframed_animation_curve.h" #include "third_party/blink/renderer/platform/animation/compositor_animation_curve.h" +#include "third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h" #include "third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h" using cc::KeyframeModel; @@ -137,4 +138,15 @@ std::move(keyframed_curve)); } +std::unique_ptr<CompositorColorAnimationCurve> +CompositorKeyframeModel::ColorCurveForTesting() const { + const cc::AnimationCurve* curve = keyframe_model_->curve(); + DCHECK_EQ(cc::AnimationCurve::COLOR, curve->Type()); + + auto keyframed_curve = base::WrapUnique( + static_cast<cc::KeyframedColorAnimationCurve*>(curve->Clone().release())); + return CompositorColorAnimationCurve::CreateForTesting( + std::move(keyframed_curve)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h b/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h index 8c6af44e9..9a3f4b8 100644 --- a/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h +++ b/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h
@@ -24,6 +24,7 @@ class CompositorAnimationCurve; class CompositorFloatAnimationCurve; +class CompositorColorAnimationCurve; // A compositor driven animation. class PLATFORM_EXPORT CompositorKeyframeModel { @@ -79,6 +80,7 @@ std::unique_ptr<cc::KeyframeModel> ReleaseCcKeyframeModel(); std::unique_ptr<CompositorFloatAnimationCurve> FloatCurveForTesting() const; + std::unique_ptr<CompositorColorAnimationCurve> ColorCurveForTesting() const; const std::string& GetCustomPropertyNameForTesting() const { return keyframe_model_->GetCustomPropertyNameForTesting();
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=NavigationLoaderOnUI b/third_party/blink/web_tests/FlagExpectations/enable-features=NavigationLoaderOnUI index edc53d75..9df6181 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-features=NavigationLoaderOnUI +++ b/third_party/blink/web_tests/FlagExpectations/enable-features=NavigationLoaderOnUI
@@ -1,9 +1,2 @@ # These tests currently fail when run with --enable-features=NavigationLoaderOnUI # See https://crbug.com/824840 - -# service worker -Bug(none) external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https.html [ Skip ] -Bug(none) virtual/not-omt-sw-fetch/external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https.html [ Skip ] -Bug(none) virtual/omt-worker-fetch/external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https.html [ Skip ] - -Bug(none) http/tests/misc/xhtml.php [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index ad644e4..34eae48 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3400,7 +3400,6 @@ crbug.com/626703 [ Retina ] virtual/blink-cors/external/wpt/referrer-policy/no-referrer-when-downgrade/http-rp/same-origin/http-https/iframe-tag/no-redirect/upgrade-protocol.http.html [ Timeout ] crbug.com/626703 [ Retina ] virtual/blink-cors/external/wpt/referrer-policy/origin-when-cross-origin/http-rp/same-origin/http-http/a-tag/no-redirect/same-origin-insecure.http.html [ Timeout ] crbug.com/626703 [ Retina ] virtual/blink-cors/external/wpt/referrer-policy/origin-when-cross-origin/http-rp/cross-origin/http-https/iframe-tag/swap-origin-redirect/cross-origin.http.html [ Timeout ] -crbug.com/626703 [ Retina ] virtual/at-property/external/wpt/css/css-properties-values-api/idlharness.html [ Timeout ] crbug.com/626703 [ Retina ] virtual/blink-cors/external/wpt/referrer-policy/no-referrer/attr-referrer/same-origin/http-https/script-tag/keep-origin-redirect/generic.http.html [ Timeout ] crbug.com/626703 [ Retina ] virtual/blink-cors/external/wpt/referrer-policy/origin-when-cross-origin/http-rp/same-origin/http-https/iframe-tag/swap-origin-redirect/same-origin-insecure.http.html [ Timeout ] crbug.com/626703 [ Retina ] virtual/blink-cors/external/wpt/referrer-policy/origin-when-cross-origin/meta-referrer/cross-origin/http-http/iframe-tag/keep-origin-redirect/cross-origin.http.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json index 64c1ecc4..90554a1 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -139782,6 +139782,9 @@ "css/css-properties-values-api/OWNERS": [ [] ], + "css/css-properties-values-api/idlharness-expected.txt": [ + [] + ], "css/css-properties-values-api/registered-property-computation-expected.txt": [ [] ], @@ -369102,6 +369105,10 @@ "b4de63045f339d163830921e4e201e698edae47c", "testharness" ], + "css/css-properties-values-api/idlharness-expected.txt": [ + "a1c521155355a9f7e3e315af5d5dd9dfc56172e3", + "support" + ], "css/css-properties-values-api/idlharness.html": [ "6f053757c3cef099f0cea41716a942dfa7e66100", "testharness" @@ -423047,11 +423054,11 @@ "support" ], "html/dom/interfaces.https.html": [ - "47254a4361c46ad5fdc46efd2165da1bbab4c9b5", + "6ca7721253200d4511758f5ba15a61f756509370", "testharness" ], "html/dom/interfaces.https_exclude=(Document_Window_HTML._)-expected.txt": [ - "efc72ac6e85df27db2bee1d3de2d0524ece4421c", + "6f2011e1588d0ff0d5ba675c9b6e32ddfec0a556", "support" ], "html/dom/interfaces.https_include=(Document_Window)-expected.txt": [ @@ -439919,7 +439926,7 @@ "support" ], "interfaces/css-properties-values-api.idl": [ - "4ba38970e30ac2610e35c266e07f381e3a6b4ec5", + "ee444ebb29d8b5b15c96d259bb8a1f2bdd280d5f", "support" ], "interfaces/css-pseudo.idl": [ @@ -440007,7 +440014,7 @@ "support" ], "interfaces/geometry.idl": [ - "5d5fe4fc2c48305c0ea7e9ce0859af3700d9b14c", + "1b83959465cf5f76bf52d2f8db51426281c07470", "support" ], "interfaces/gyroscope.idl": [ @@ -483735,7 +483742,7 @@ "testharness" ], "webrtc/RTCPeerConnection-createDataChannel-expected.txt": [ - "8d92a639d7d1dc0e642a262d781ea70d510d7478", + "74dac5eded6acf2de528ce5336c2ab23adb2bcea", "support" ], "webrtc/RTCPeerConnection-createDataChannel.html": [ @@ -483807,7 +483814,7 @@ "testharness" ], "webrtc/RTCPeerConnection-ondatachannel-expected.txt": [ - "d04de3ba27102ce318f9cd68e1cb91b1b76da7b6", + "1e0c99b89ba14704f795efd5e43f8d7a7d448c40", "support" ], "webrtc/RTCPeerConnection-ondatachannel.html": [ @@ -484155,7 +484162,7 @@ "testharness" ], "webrtc/historical-expected.txt": [ - "4353e8649e10e9f6c79895c7ff82bbbe2324c2c4", + "68050e46488fde9f9ec27a45e978ca73790faf18", "support" ], "webrtc/historical.html": [ @@ -484163,7 +484170,7 @@ "testharness" ], "webrtc/idlharness.https.window-expected.txt": [ - "1f26f0d506c51105c2e769caa4270ebc6d3e472a", + "2dd1e4d624cedabafd9df11798efa63e9334690a", "support" ], "webrtc/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/idlharness-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/idlharness-expected.txt new file mode 100644 index 0000000..a1c52115 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/idlharness-expected.txt
@@ -0,0 +1,20 @@ +This is a testharness.js-based test. +PASS idl_test setup +PASS Partial namespace CSS: original namespace defined +PASS Partial interface CSSRule: original interface defined +FAIL CSSPropertyRule interface: existence and properties of interface object assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface object length assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface object name assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: existence and properties of interface prototype object assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: attribute name assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: attribute syntax assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: attribute inherits assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: attribute initialValue assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSRule interface: constant PROPERTY_RULE on interface object assert_own_property: expected property "PROPERTY_RULE" missing +FAIL CSSRule interface: constant PROPERTY_RULE on interface prototype object assert_own_property: expected property "PROPERTY_RULE" missing +PASS CSS namespace: operation escape(CSSOMString) +PASS CSS namespace: operation registerProperty(PropertyDefinition) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/percent-width-cell-dynamic.html b/third_party/blink/web_tests/external/wpt/css/css-tables/percent-width-cell-dynamic.html new file mode 100644 index 0000000..5c7ef3b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-tables/percent-width-cell-dynamic.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<link rel="help" href="https://crbug.com/984642" /> +<link rel="match" href="../reference/ref-filled-green-100px-square-only.html"> +<style> +html { overflow: hidden; } +</style> +<p>Test passes if there is a filled green square.</p> +<div id="target"> + <div style="width: 10%;"> + <div style="display: inline-table;"> + <div style="display: table-cell; width: 100%;"> + <span style="display: inline-block; width: 100%; height: 100px; background: green;"></span> + </div> + <div style="display: table-cell;"> + <span style="display: inline-block; width: 10px; height: 100px; background: green;"></span> + </div> + </div> + </div> +</div> +<script> +document.body.offsetTop; +document.getElementById('target').style.width = '1000px'; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity-ref.html new file mode 100644 index 0000000..347b7a6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity-ref.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>backdrop-filter: Correctly apply backdrop-filter with opacity</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> + + + +<p>Expected: A green box.</p> + +<div class="greenbox"></div> + + +<style> +.greenbox { + position: absolute; + background: green; + width: 100px; + height: 100px; + top: 100px; + left: 60px; +} +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity.html new file mode 100644 index 0000000..cb189f9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>backdrop-filter: Correctly apply backdrop-filter with opacity</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> +<link rel="match" href="backdrop-filter-plus-opacity-ref.html"> + +<p>Expected: A green box.</p> + +<div class="greenbox"></div> +<div class="filter"></div> + +<style> +.greenbox { + position: absolute; + background: green; + width: 100px; + height: 100px; + top: 100px; + left: 60px; +} +.filter { + position: absolute; + width: 200px; + height: 200px; + top: 50px; + left: 10px; + backdrop-filter: invert(1); + opacity: 0; +} +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/width-equals-window-inner-width.html b/third_party/blink/web_tests/external/wpt/css/mediaqueries/width-equals-window-inner-width.html new file mode 100644 index 0000000..775c111 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/width-equals-window-inner-width.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<title>CSS Test: CSS media query width equals window innerWidth</title> + +<link rel="author" title="Jinfeng Ma" href="mailto:majinfeng1@xiaomi.org"> +<link rel="help" href="https://www.w3.org/TR/css3-mediaqueries/#width"> +<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-window-innerwidth"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<!-- +It'd be best to programmatically change device scale factor so that the document +width becomes non integral but for now this test is only effective when run on +devices with a fractional device scale factor. +--> +<script type="text/javascript"> + 'use strict'; + test(() => { + assert_true(window.matchMedia('(width: ' + window.innerWidth + 'px)').matches); + }, 'CSS media query width equals window innerWidth.'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/images-repeated-resource.html b/third_party/blink/web_tests/external/wpt/element-timing/images-repeated-resource.html index 9bc8b5f4..a6ad7ace 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/images-repeated-resource.html +++ b/third_party/blink/web_tests/external/wpt/element-timing/images-repeated-resource.html
@@ -13,8 +13,10 @@ <script> let beforeRender; let numEntries = 0; - let responseEnd1; - let responseEnd2; + let loadTime1; + let loadTime2; + let renderTime1; + let renderTime2; let img; let img2; const index = window.location.href.lastIndexOf('/'); @@ -26,23 +28,33 @@ } const observer = new PerformanceObserver( t.step_func(function(entryList) { - entryList.getEntries().forEach(entry => { - // Easier to check the |element| attribute here since element ID is the same for both images. - checkElement(entry, pathname, entry.identifier, 'image_id', beforeRender, null); - checkNaturalSize(entry, 100, 100); - if (entry.identifier === 'my_image') { - ++numEntries; - responseEnd1 = entry.responseEnd; - assert_equals(entry.element, img); - } - else if (entry.identifier === 'my_image2') { - ++numEntries; - responseEnd2 = entry.responseEnd; - assert_equals(entry.element, img2); - } - }); + assert_equals(entryList.getEntries().length, 1); + const entry = entryList.getEntries()[0]; + // Easier to check the |element| attribute here since element ID is the same for both images. + checkElement(entry, pathname, entry.identifier, 'image_id', beforeRender, null); + checkNaturalSize(entry, 100, 100); + if (entry.identifier === 'my_image') { + ++numEntries; + loadTime1 = entry.loadTime; + renderTime1 = entry.renderTime; + assert_equals(entry.element, img); + + img2 = document.createElement('img'); + img2.src = 'resources/square100.png'; + img2.setAttribute('elementtiming', 'my_image2'); + img2.setAttribute('id', 'image_id'); + document.body.appendChild(img2); + beforeRender = performance.now(); + } + else if (entry.identifier === 'my_image2') { + ++numEntries; + loadTime2 = entry.loadTime; + renderTime2 = entry.renderTime; + assert_equals(entry.element, img2); + } if (numEntries == 2) { - assert_equals(responseEnd1, responseEnd2); + assert_greater_than(loadTime2, loadTime1, 'Second image loads after first.'); + assert_greater_than(renderTime2, renderTime1, 'Second image renders after first'); t.done(); } }) @@ -57,16 +69,9 @@ img.setAttribute('elementtiming', 'my_image'); img.setAttribute('id', 'image_id'); document.body.appendChild(img); - - img2 = document.createElement('img'); - img2.src = 'resources/square100.png'; - img2.setAttribute('elementtiming', 'my_image2'); - img2.setAttribute('id', 'image_id'); - document.body.appendChild(img2); - beforeRender = performance.now(); }; - }, 'Element with elementtiming attribute is observable.'); + }, 'Elements with elementtiming and same src are observable.'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js b/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js index f98f9b2..8933732 100644 --- a/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js +++ b/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js
@@ -22,7 +22,8 @@ assert_equals(entry.name, 'image-paint'); const rt_entries = performance.getEntriesByName(expectedUrl, 'resource'); assert_equals(rt_entries.length, 1); - assert_equals(rt_entries[0].responseEnd, entry.responseEnd); + assert_greater_than_equal(entry.loadTime, rt_entries[0].responseEnd, + 'Image loadTime is after the resource responseEnd'); } function checkElementWithoutResourceTiming(entry, expectedUrl, expectedIdentifier, @@ -30,8 +31,8 @@ checkElementInternal(entry, expectedUrl, expectedIdentifier, expectedID, beforeRender, expectedElement); assert_equals(entry.name, 'image-paint'); - // No associated resource from ResourceTiming, so the responseEnd should be 0. - assert_equals(entry.responseEnd, 0); + // No associated resource from ResourceTiming, so not much to compare loadTime with. + assert_greater_than(entry.loadTime, 0); } // Checks that the rect matches the desired values [left right top bottom]. @@ -57,5 +58,5 @@ checkElementInternal(entry, '', expectedIdentifier, expectedID, beforeRender, expectedElement); assert_equals(entry.name, 'text-paint'); - assert_equals(entry.responseEnd, 0); + assert_equals(entry.loadTime, 0); }
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https.html b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https.html index 47254a4..6ca7721 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https.html +++ b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https.html
@@ -8,6 +8,7 @@ <script src=/resources/testharness.js></script> <script src=/resources/testharnessreport.js></script> <script src=/common/subset-tests-by-key.js></script> +<script src=/common/get-host-info.sub.js></script> <script src=/resources/WebIDLParser.js></script> <script src=/resources/idlharness.js></script> @@ -200,7 +201,8 @@ PeerConnection: [], MediaStreamEvent: [], ErrorEvent: [], - WebSocket: ['new WebSocket("wss://foo")'], + // https://web-platform-tests.org/writing-tests/server-features.html?tests-involving-multiple-origins + WebSocket: ['new WebSocket("wss://nonexistent.' + get_host_info().ORIGINAL_HOST + '")'], CloseEvent: ['new CloseEvent("close")'], AbstractWorker: [], Worker: [],
diff --git "a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt" "b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt" index efc72ac6..6f2011e1 100644 --- "a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt" +++ "b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt"
@@ -1031,32 +1031,32 @@ PASS WebSocket interface: operation send(Blob) PASS WebSocket interface: operation send(ArrayBuffer) PASS WebSocket interface: operation send(ArrayBufferView) -PASS WebSocket must be primary interface of new WebSocket("wss://foo") -PASS Stringification of new WebSocket("wss://foo") -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "url" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "CONNECTING" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "OPEN" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "CLOSING" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "CLOSED" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "readyState" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "bufferedAmount" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "onopen" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "onerror" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "onclose" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "extensions" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "protocol" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "close(unsigned short, USVString)" with the proper type -PASS WebSocket interface: calling close(unsigned short, USVString) on new WebSocket("wss://foo") with too few arguments must throw TypeError -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "onmessage" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "binaryType" with the proper type -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "send(USVString)" with the proper type -PASS WebSocket interface: calling send(USVString) on new WebSocket("wss://foo") with too few arguments must throw TypeError -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "send(Blob)" with the proper type -PASS WebSocket interface: calling send(Blob) on new WebSocket("wss://foo") with too few arguments must throw TypeError -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "send(ArrayBuffer)" with the proper type -PASS WebSocket interface: calling send(ArrayBuffer) on new WebSocket("wss://foo") with too few arguments must throw TypeError -PASS WebSocket interface: new WebSocket("wss://foo") must inherit property "send(ArrayBufferView)" with the proper type -PASS WebSocket interface: calling send(ArrayBufferView) on new WebSocket("wss://foo") with too few arguments must throw TypeError +PASS WebSocket must be primary interface of new WebSocket("wss://nonexistent.web-platform.test") +PASS Stringification of new WebSocket("wss://nonexistent.web-platform.test") +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "url" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "CONNECTING" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "OPEN" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "CLOSING" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "CLOSED" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "readyState" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "bufferedAmount" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "onopen" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "onerror" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "onclose" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "extensions" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "protocol" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "close(unsigned short, USVString)" with the proper type +PASS WebSocket interface: calling close(unsigned short, USVString) on new WebSocket("wss://nonexistent.web-platform.test") with too few arguments must throw TypeError +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "onmessage" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "binaryType" with the proper type +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "send(USVString)" with the proper type +PASS WebSocket interface: calling send(USVString) on new WebSocket("wss://nonexistent.web-platform.test") with too few arguments must throw TypeError +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "send(Blob)" with the proper type +PASS WebSocket interface: calling send(Blob) on new WebSocket("wss://nonexistent.web-platform.test") with too few arguments must throw TypeError +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "send(ArrayBuffer)" with the proper type +PASS WebSocket interface: calling send(ArrayBuffer) on new WebSocket("wss://nonexistent.web-platform.test") with too few arguments must throw TypeError +PASS WebSocket interface: new WebSocket("wss://nonexistent.web-platform.test") must inherit property "send(ArrayBufferView)" with the proper type +PASS WebSocket interface: calling send(ArrayBufferView) on new WebSocket("wss://nonexistent.web-platform.test") with too few arguments must throw TypeError PASS CloseEvent interface: existence and properties of interface object PASS CloseEvent interface object length PASS CloseEvent interface object name
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/css-properties-values-api.idl b/third_party/blink/web_tests/external/wpt/interfaces/css-properties-values-api.idl index 4ba38970e..ee444eb 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/css-properties-values-api.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/css-properties-values-api.idl
@@ -3,7 +3,7 @@ // (https://github.com/tidoust/reffy-reports) // Source: CSS Properties and Values API Level 1 (https://drafts.css-houdini.org/css-properties-values-api-1/) -dictionary PropertyDescriptor { +dictionary PropertyDefinition { required DOMString name; DOMString syntax = "*"; required boolean inherits; @@ -11,5 +11,17 @@ }; partial namespace CSS { - void registerProperty(PropertyDescriptor descriptor); + void registerProperty(PropertyDefinition definition); +}; + +partial interface CSSRule { + const unsigned short PROPERTY_RULE = 18; +}; + +[Exposed=Window] +interface CSSPropertyRule : CSSRule { + readonly attribute CSSOMString name; + readonly attribute CSSOMString syntax; + readonly attribute boolean inherits; + readonly attribute CSSOMString? initialValue; };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/geometry.idl b/third_party/blink/web_tests/external/wpt/interfaces/geometry.idl index 5d5fe4fc2..1b83959 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/geometry.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/geometry.idl
@@ -15,7 +15,7 @@ readonly attribute unrestricted double z; readonly attribute unrestricted double w; - DOMPoint matrixTransform(optional DOMMatrixInit matrix); + [NewObject] DOMPoint matrixTransform(optional DOMMatrixInit matrix); [Default] object toJSON(); };
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/cross-origin-image.sub.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/cross-origin-image.sub.html index 6e86f13..88775b8 100644 --- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/cross-origin-image.sub.html +++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/cross-origin-image.sub.html
@@ -9,6 +9,7 @@ if (!window.LargestContentfulPaint) { assert_unreached("LargestContentfulPaint is not implemented"); } + const beforeLoad = performance.now(); const observer = new PerformanceObserver( t.step_func_done(function(entryList) { assert_equals(entryList.getEntries().length, 1); @@ -22,8 +23,8 @@ assert_equals(entry.id, 'image_id'); const pathname = 'http://{{domains[www]}}:{{ports[http][1]}}/images/blue.png'; assert_equals(entry.url, pathname); - assert_equals(entry.responseEnd, - performance.getEntriesByName(pathname, 'resource')[0].responseEnd); + assert_greater_than_equal(entry.loadTime, beforeLoad); + assert_less_than(entry.loadTime, performance.now()); assert_equals(entry.element, document.getElementById('image_id')); }) );
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/loadTime-after-appendChild.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/loadTime-after-appendChild.html new file mode 100644 index 0000000..fb0eddb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/loadTime-after-appendChild.html
@@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Largest Contentful Paint: delayed appended image.</title> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + async_test(function (t) { + if (!window.LargestContentfulPaint) { + assert_unreached("LargestContentfulPaint is not implemented"); + } + let beforeLoad; + const observer = new PerformanceObserver( + t.step_func_done(entryList => { + assert_equals(entryList.getEntries().length, 1); + const entry = entryList.getEntries()[0]; + assert_equals(entry.entryType, 'largest-contentful-paint'); + assert_equals(entry.startTime, 0); + assert_equals(entry.duration, 0); + assert_equals(entry.url, window.location.origin + '/images/black-rectangle.png'); + assert_greater_than(entry.renderTime, entry.loadTime, + 'The image render time should occur after it is appended to the div.'); + assert_greater_than(entry.loadTime, beforeLoad, + 'The image load timestamp should occur after script starts running.'); + assert_less_than(entry.renderTime, performance.now(), + 'Image render time should be before the observer callback is executed.') + }) + ); + observer.observe({type: 'largest-contentful-paint', buffered: true}); + const img = document.createElement('img'); + img.src = '/images/black-rectangle.png'; + t.step_timeout(() => { + beforeLoad = performance.now(); + document.getElementById('image_div').appendChild(img); + }, 200) + }, 'Image loadTime occurs after appendChild is called.'); +</script> +<div id='image_div'></div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-image.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-image.html index 4d56cc2..16b3502 100644 --- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-image.html +++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-image.html
@@ -9,7 +9,7 @@ if (!window.LargestContentfulPaint) { assert_unreached("LargestContentfulPaint is not implemented"); } - let beforeRender = performance.now(); + const beforeRender = performance.now(); const observer = new PerformanceObserver( t.step_func_done(function(entryList) { assert_equals(entryList.getEntries().length, 1); @@ -28,8 +28,10 @@ const index = window.location.href.lastIndexOf('/') - 25; const pathname = window.location.href.substring(0, index) + '/images/blue.png'; assert_equals(entry.url, pathname); - assert_equals(entry.responseEnd, - performance.getEntriesByName(pathname, 'resource')[0].responseEnd); + assert_greater_than(entry.loadTime, beforeRender, + 'The load timestamp should occur after script starts running.'); + assert_less_than(entry.loadTime, entry.renderTime, + 'The load timestamp should occur before the render timestamp.') assert_equals(entry.element, document.getElementById('image_id')); }) );
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-text.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-text.html index 7dbfbe52..2cf1344f 100644 --- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-text.html +++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-text.html
@@ -10,11 +10,11 @@ } </style> <script> - let beforeRender; async_test(function (t) { if (!window.LargestContentfulPaint) { assert_unreached("LargestContentfulPaint is not implemented"); } + let beforeRender; const observer = new PerformanceObserver( t.step_func_done(function(entryList) { assert_equals(entryList.getEntries().length, 1); @@ -28,7 +28,7 @@ // Width of at least 100 px. // TODO: find a good way to bound text width. assert_greater_than_equal(entry.size, 1200); - assert_equals(entry.responseEnd, 0); + assert_equals(entry.loadTime, 0); assert_equals(entry.id, 'my_text'); assert_equals(entry.url, ''); assert_equals(entry.element, document.getElementById('my_text'));
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/repeated-image.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/repeated-image.html new file mode 100644 index 0000000..94406b20 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/repeated-image.html
@@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Largest Contentful Paint: repeated image.</title> +<style> + #image_id { + width: 10px; + height: 10px; + } +</style> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + async_test(function (t) { + if (!window.LargestContentfulPaint) { + assert_unreached("LargestContentfulPaint is not implemented"); + } + const beforeFirstLoad = performance.now(); + let firstCallback = true; + const path = window.location.origin + '/images/black-rectangle.png'; + let beforeSecondLoad; + const observer = new PerformanceObserver( + t.step_func(entryList => { + assert_equals(entryList.getEntries().length, 1); + const entry = entryList.getEntries()[0]; + assert_equals(entry.entryType, 'largest-contentful-paint'); + assert_equals(entry.startTime, 0); + assert_equals(entry.duration, 0); + assert_equals(entry.url, path); + assert_less_than(entry.renderTime, performance.now(), + 'Image render time should be before the observer callback is executed.') + if (firstCallback) { + assert_equals(entry.id, 'image_id'); + assert_greater_than(entry.renderTime, entry.loadTime, + 'The first image render time should occur after its load time.'); + assert_greater_than(entry.loadTime, beforeFirstLoad, + 'The first image load timestamp should occur after script starts running.'); + // Image is shrunk to be 10 x 10. + assert_equals(entry.size, 100); + const img = document.createElement('img'); + img.src = '/images/black-rectangle.png'; + beforeSecondLoad = performance.now(); + document.getElementById('image_div').appendChild(img); + firstCallback = false; + return; + } + // The second image is added at its natural size: 100 x 50. + assert_equals(entry.size, 5000); + assert_greater_than(entry.loadTime, beforeSecondLoad, + 'The second image load time should occur after adding it to the document body.'); + assert_greater_than(entry.renderTime, entry.loadTime, + 'The second image render time should occur after its load time.'); + t.done(); + }) + ); + observer.observe({type: 'largest-contentful-paint', buffered: true}); + }, 'Repeated image produces different timestamps.'); +</script> +<img src='/images/black-rectangle.png' id='image_id'/> +<div id='image_div'></div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/loading/lazyload/picture-loading-lazy.tentative.html b/third_party/blink/web_tests/external/wpt/loading/lazyload/picture-loading-lazy.tentative.html new file mode 100644 index 0000000..58f8c3a4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/loading/lazyload/picture-loading-lazy.tentative.html
@@ -0,0 +1,68 @@ +<!DOCTYPE html> +<head> + <title>Images with loading='lazy' in picture elements load when near the viewport</title> + <link rel="author" title="Raj T" href="mailto:rajendrant@chromium.org"> + <link rel="help" href="https://github.com/scott-little/lazyload"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="common.js"></script> +</head> + +<!-- +Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed. +--> + +<script> +const in_viewport_img = new ElementLoadPromise("in_viewport_img"); +const lazy_attribute_img = new ElementLoadPromise("lazy_attribute_img"); +const eager_attribute_img = new ElementLoadPromise("eager_attribute_img"); + +const document_load_promise = new Promise(resolve => { + window.addEventListener("load", resolve); +}); + +async_test(function(t) { + document_load_promise.then(t.step_func_done(function() { + assert_false(lazy_attribute_img.element().complete); + lazy_attribute_img.element().scrollIntoView(); + })); +}, "Test that the loading=lazy <picture> element below viewport was deferred, on document load."); + +async_test(function(t) { + in_viewport_img.promise.then(t.step_func_done()); +}, "Test that in viewport <picture> element was loaded"); + +async_test(function(t) { + eager_attribute_img.promise.then(t.step_func_done()); +}, "Test that eager <picture> element was loaded"); + +async_test(function(t) { + lazy_attribute_img.promise.then(t.step_func_done()); +}, "Test that deferred <picture> element was loaded-in as well, after scrolled down"); + +</script> + +<body> +<picture> + <source sizes='50vw' srcset='resources/image.png?in_viewport_img'> + <img id='in_viewport_img' src='img-not-loaded.png' loading="lazy" onload="in_viewport_img.resolve();"> +</picture> +<div style="height:10000px;"></div> +<picture> + <source sizes='50vw' srcset='resources/image.png?lazy_attribute_img'> + <img id='lazy_attribute_img' src='img-not-loaded.png' loading="lazy" onload="lazy_attribute_img.resolve();"> +</picture> +<picture> + <source sizes='50vw' srcset='resources/image.png?eager_attribute_img'> + <img id='eager_attribute_img' src='img-not-loaded.png' loading="eager" onload="eager_attribute_img.resolve();"> +</picture> + +<!-- + This async script loads very slowly in order to ensure that, if the + below_viewport image has started loading, it has a chance to finish + loading before window.load() happens, so that the test will dependably fail + in that case instead of potentially passing depending on how long different + resource fetches take. +--> +<script async src="/common/slow.py"></script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/std-toast/attributes.html b/third_party/blink/web_tests/external/wpt/std-toast/attributes.html index 97bab58..6b6aca624 100644 --- a/third_party/blink/web_tests/external/wpt/std-toast/attributes.html +++ b/third_party/blink/web_tests/external/wpt/std-toast/attributes.html
@@ -115,7 +115,48 @@ }, 'toggling open attribute does not start timeout'); testToastElement((toast) => { - const permitted_properties = ['constructor', 'show', 'hide', 'toggle', 'open', 'action', 'closeButton']; + const permitted_properties = ['constructor', 'show', 'hide', 'toggle', 'open', 'action', 'closeButton', 'type']; assert_array_equals(permitted_properties.sort(), Object.getOwnPropertyNames(toast.__proto__).sort()); }, 'toast only exposes certain properties'); + +testToastElement((toast) => { + assert_false(toast.hasAttribute('type')); + assert_equals(toast.type, ''); +}, 'default type is empty string without attribute present'); + +testToastElement((toast) => { + toast.type = 'warning'; + assert_equals(toast.getAttribute('type'), 'warning'); + assert_equals(toast.type, 'warning'); +}, 'setting type property to an enumerated value changes the type attribute to that value'); + +testToastElement((toast) => { + toast.type = 'WaRnInG'; + assert_equals(toast.getAttribute('type'), 'WaRnInG'); + assert_equals(toast.type, 'warning'); +}, 'setting type property to an enumerated value is case-insensitive'); + +testToastElement((toast) => { + toast.type = ' WaRnInG '; + assert_equals(toast.getAttribute('type'), ' WaRnInG '); + assert_equals(toast.type, ''); +}, 'setting type property to an enumerated value with whitespace does not work'); + +testToastElement((toast) => { + toast.type = 'test'; + assert_equals(toast.type, ''); + assert_equals(toast.getAttribute('type'), 'test'); +}, 'setting type to a non-enumerated value sets the type property to empty string'); + +testToastElement((toast) => { + toast.setAttribute('type', 'test'); + assert_equals(toast.type, ''); + assert_equals(toast.getAttribute('type'), 'test'); +}, 'setting type attribute to a non-enumerated value sets the type property to empty string'); + +testToastElement((toast) => { + toast.type = 'info'; + assert_equals(toast.type, ''); + assert_equals(toast.getAttribute('type'), 'info'); +}, 'info was briefly a valid type, but no longer is, so it will return empty string'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/std-toast/styles.html b/third_party/blink/web_tests/external/wpt/std-toast/styles.html index 98e6723..1db8620 100644 --- a/third_party/blink/web_tests/external/wpt/std-toast/styles.html +++ b/third_party/blink/web_tests/external/wpt/std-toast/styles.html
@@ -61,4 +61,40 @@ assertComputedStyleMapsEqual(toast, mockToast); }, 'the computed style map of a closed unstyled toast is the same as a span given toast defaults'); -</script> \ No newline at end of file + +testToastElement((toast) => { + toast.type = 'error'; + + const styles = window.getComputedStyle(toast); + assert_equals(styles.borderColor, 'rgb(255, 0, 0)'); +}, 'changing type to error changes the border color to red'); + +testToastElement((toast) => { + toast.type = 'warning'; + + const styles = window.getComputedStyle(toast); + assert_equals(styles.borderColor, 'rgb(255, 165, 0)'); +}, 'changing type to warning changes the border color to orange'); + +testToastElement((toast) => { + toast.type = 'success'; + + const styles = window.getComputedStyle(toast); + assert_equals(styles.borderColor, 'rgb(0, 128, 0)'); +}, 'changing type to success changes the border color to green'); + +testToastElement((toast) => { + const styler = document.createElement('style'); + styler.append(` + [type=error i] { + border-color: pink; + } + `); + document.querySelector('main').appendChild(styler); + + toast.type = 'error'; + + const styles = window.getComputedStyle(toast); + assert_equals(styles.borderColor, 'rgb(255, 192, 203)'); +}, 'outside styles can set type styles'); +</script>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-events-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-events-expected.txt index 304db523..698d7a5e 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-events-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-events-expected.txt
@@ -244,7 +244,7 @@ value : 300000 } ] - eventName : Sync event failed + eventName : sync event failed instanceId : background-sync-reject origin : http://127.0.0.1:8000/ service : backgroundSync
diff --git a/third_party/blink/web_tests/scrollingcoordinator/donot-compute-non-fast-scrollable-region-for-hidden-frames.html b/third_party/blink/web_tests/scrollingcoordinator/donot-compute-non-fast-scrollable-region-for-hidden-frames.html index 8e62385b..e1cc76d 100644 --- a/third_party/blink/web_tests/scrollingcoordinator/donot-compute-non-fast-scrollable-region-for-hidden-frames.html +++ b/third_party/blink/web_tests/scrollingcoordinator/donot-compute-non-fast-scrollable-region-for-hidden-frames.html
@@ -22,15 +22,21 @@ async_test((t) => { var iframeWindow = document.querySelector("iframe").contentWindow; iframeWindow.addEventListener("load", () => { - nonFastScrollableRects = internals.nonFastScrollableRects(document); - assert_equals(nonFastScrollableRects.length, 3); - - var iframeElement = document.querySelector("iframe"); - iframeElement.style.visibility = 'hidden'; + t.step(function() { + nonFastScrollableRects = internals.nonFastScrollableRects(document); + assert_equals(nonFastScrollableRects.length, 3); + assert_equals(rectToString(nonFastScrollableRects[0]), '[51, 102, 200, 200]'); + assert_equals(rectToString(nonFastScrollableRects[1]), '[51, 402, 211, 211]'); + assert_equals(rectToString(nonFastScrollableRects[2]), '[51, 702, 222, 222]'); + var iframeElement = document.querySelector("iframe"); + iframeElement.style.visibility = 'hidden'; + }); runAfterLayoutAndPaint(() => { - nonFastScrollableRects = internals.nonFastScrollableRects(document); - assert_equals(nonFastScrollableRects.length, 0); + t.step(function() { + nonFastScrollableRects = internals.nonFastScrollableRects(document); + assert_equals(nonFastScrollableRects.length, 0); + }); t.done(); }); });
diff --git a/third_party/blink/web_tests/scrollingcoordinator/plugin-with-wheel-handler-expected.txt b/third_party/blink/web_tests/scrollingcoordinator/plugin-with-wheel-handler-expected.txt index 6d70833b..ff20003 100644 --- a/third_party/blink/web_tests/scrollingcoordinator/plugin-with-wheel-handler-expected.txt +++ b/third_party/blink/web_tests/scrollingcoordinator/plugin-with-wheel-handler-expected.txt
@@ -2,8 +2,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS internals.nonFastScrollableRects(document).length is 1 +PASS nonFastScrollableRects.length is 1 +PASS rectToString(nonFastScrollableRects[0]) is "[8, 8, 300, 150]" PASS successfullyParsed is true TEST COMPLETE +
diff --git a/third_party/blink/web_tests/scrollingcoordinator/plugin-with-wheel-handler.html b/third_party/blink/web_tests/scrollingcoordinator/plugin-with-wheel-handler.html index b6d74933..cd8cf2e 100644 --- a/third_party/blink/web_tests/scrollingcoordinator/plugin-with-wheel-handler.html +++ b/third_party/blink/web_tests/scrollingcoordinator/plugin-with-wheel-handler.html
@@ -1,18 +1,25 @@ <!DOCTYPE html> <script src="../resources/js-test.js"></script> <script src="../resources/run-after-layout-and-paint.js"></script> +<script src="resources/non-fast-scrollable-region-testing.js"></script> <script> +// Perform the test without any description text (with the plugin at the top +// left) so the non-fast rect is not affected by platform-specific differences +// in text height. +setPrintTestResultsLazily(); description('This test ensures that a plugin which wants to receive wheel ' + 'events is included in the non-fast scrollable region.'); window.jsTestIsAsync = true; onload = function() { runAfterLayoutAndPaint(function() { + nonFastScrollableRects = internals.nonFastScrollableRects(document); if (window.internals) { - shouldBe('internals.nonFastScrollableRects(document).length', '1'); + shouldBe('nonFastScrollableRects.length', '1'); + shouldBeEqualToString('rectToString(nonFastScrollableRects[0])', '[8, 8, 300, 150]'); } else { - debug('This test requires access to internals.nonFastScrollableRects.'); + debug('This test requires access to internals.nonFastScrollableRects.'); } finishJSTest();
diff --git a/third_party/blink/web_tests/virtual/at-property/external/wpt/css/css-properties-values-api/idlharness-expected.txt b/third_party/blink/web_tests/virtual/at-property/external/wpt/css/css-properties-values-api/idlharness-expected.txt new file mode 100644 index 0000000..97f17b0 --- /dev/null +++ b/third_party/blink/web_tests/virtual/at-property/external/wpt/css/css-properties-values-api/idlharness-expected.txt
@@ -0,0 +1,20 @@ +This is a testharness.js-based test. +PASS idl_test setup +PASS Partial namespace CSS: original namespace defined +PASS Partial interface CSSRule: original interface defined +PASS CSSPropertyRule interface: existence and properties of interface object +PASS CSSPropertyRule interface object length +PASS CSSPropertyRule interface object name +PASS CSSPropertyRule interface: existence and properties of interface prototype object +PASS CSSPropertyRule interface: existence and properties of interface prototype object's "constructor" property +PASS CSSPropertyRule interface: existence and properties of interface prototype object's @@unscopables property +FAIL CSSPropertyRule interface: attribute name assert_true: The prototype object must have a property "name" expected true got false +FAIL CSSPropertyRule interface: attribute syntax assert_true: The prototype object must have a property "syntax" expected true got false +FAIL CSSPropertyRule interface: attribute inherits assert_true: The prototype object must have a property "inherits" expected true got false +FAIL CSSPropertyRule interface: attribute initialValue assert_true: The prototype object must have a property "initialValue" expected true got false +FAIL CSSRule interface: constant PROPERTY_RULE on interface object assert_equals: property has wrong value expected 18 but got 1001 +FAIL CSSRule interface: constant PROPERTY_RULE on interface prototype object assert_equals: property has wrong value expected 18 but got 1001 +PASS CSS namespace: operation escape(CSSOMString) +PASS CSS namespace: operation registerProperty(PropertyDefinition) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/cascade/external/wpt/css/css-properties-values-api/idlharness-expected.txt b/third_party/blink/web_tests/virtual/cascade/external/wpt/css/css-properties-values-api/idlharness-expected.txt new file mode 100644 index 0000000..a1c52115 --- /dev/null +++ b/third_party/blink/web_tests/virtual/cascade/external/wpt/css/css-properties-values-api/idlharness-expected.txt
@@ -0,0 +1,20 @@ +This is a testharness.js-based test. +PASS idl_test setup +PASS Partial namespace CSS: original namespace defined +PASS Partial interface CSSRule: original interface defined +FAIL CSSPropertyRule interface: existence and properties of interface object assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface object length assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface object name assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: existence and properties of interface prototype object assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: attribute name assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: attribute syntax assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: attribute inherits assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSPropertyRule interface: attribute initialValue assert_own_property: self does not have own property "CSSPropertyRule" expected property "CSSPropertyRule" missing +FAIL CSSRule interface: constant PROPERTY_RULE on interface object assert_own_property: expected property "PROPERTY_RULE" missing +FAIL CSSRule interface: constant PROPERTY_RULE on interface prototype object assert_own_property: expected property "PROPERTY_RULE" missing +PASS CSS namespace: operation escape(CSSOMString) +PASS CSS namespace: operation registerProperty(PropertyDefinition) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index c38208eb8..fcb21cc 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -4421,8 +4421,8 @@ attribute @@toStringTag getter element getter id + getter loadTime getter renderTime - getter responseEnd getter size getter url method constructor @@ -5439,10 +5439,10 @@ getter id getter identifier getter intersectionRect + getter loadTime getter naturalHeight getter naturalWidth getter renderTime - getter responseEnd getter url method constructor method toJSON
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 1d1c2e1..a5120181 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -1309,11 +1309,6 @@ self.WriteFailureAndRaise('No command line for %s found (test type %s).' % (target, test_type), output_path=None) - if is_win and asan: - # Sandbox is not yet supported by ASAN for Windows. - # Perhaps this is only needed for tests that use the sandbox? - cmdline.append('--no-sandbox') - cmdline += isolate_map[target].get('args', []) return cmdline, extra_files
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 69b065c..be0f71d3 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -860,7 +860,7 @@ 'win7-rel': 'gpu_tests_release_trybot_x86_resource_whitelisting', 'win_x64_archive': 'release_trybot', 'win_archive': 'release_trybot_x86', - 'win_chromium_compile_dbg_ng': 'gpu_tests_debug_trybot_x86', + 'win_chromium_compile_dbg_ng': 'gpu_tests_debug_trybot_x86_compile_only', 'win_chromium_compile_rel_ng': 'gpu_tests_release_trybot_x86_resource_whitelisting', 'win_chromium_dbg_ng': 'gpu_tests_debug_trybot_x86', 'win_chromium_x64_rel_ng': 'gpu_tests_release_trybot', @@ -1551,8 +1551,8 @@ 'gpu_tests', 'debug_trybot', 'x86', ], - 'gpu_tests_debug_trybot_x86': [ - 'gpu_tests', 'debug_trybot', 'x86', + 'gpu_tests_debug_trybot_x86_compile_only': [ + 'gpu_tests', 'debug_trybot', 'x86', 'compile_only', ], 'gpu_tests_release_bot_minimal_symbols': [
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index dc95f3c..498dec7 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -9101,6 +9101,9 @@ <int value="14" label="Animation has an unsupported CSS property"/> <int value="15" label="There are multiple transform animations on the target element"/> + <int value="16" + label="Custom property contains different value types in keyframe + animation"/> </enum> <enum name="CompositorFrameSinkSubmitResult"> @@ -12994,6 +12997,7 @@ <int value="4" label="Push Messaging"/> <int value="5" label="Notifications"/> <int value="6" label="Payment Handler"/> + <int value="7" label="Periodic Background Sync"/> </enum> <enum name="DevToolsPanel">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 17be21c..6a3f6584 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -10161,10 +10161,9 @@ </histogram> <histogram name="Autofill.ManageCardsPrompt" enum="AutofillManageCardsPrompt" - expires_after="2019-09-01"> + expires_after="2020-09-01"> <owner>manasverma@google.com</owner> <owner>jsaul@google.com</owner> - <owner>sebsg@chromium.org</owner> <summary> The frequency of user interactions with the Manage Cards prompt. </summary> @@ -17082,6 +17081,9 @@ <histogram name="CachedImageFetcher.ImageLoadFromCacheTime" units="ms" expires_after="2019-12-01"> + <obsolete> + Renamed to ImageFetcher.ImageLoadFromCacheTime on 06/2019. + </obsolete> <owner>fgorski@chromium.org</owner> <owner>wylieb@chromium.org</owner> <summary> @@ -17092,6 +17094,9 @@ <histogram name="CachedImageFetcher.ImageLoadFromCacheTimeJava" units="ms" expires_after="2019-12-01"> + <obsolete> + Renamed to ImageFetcher.ImageLoadFromCacheTimeJava on 06/2019. + </obsolete> <owner>fgorski@chromium.org</owner> <owner>wylieb@chromium.org</owner> <summary> @@ -17102,6 +17107,9 @@ <histogram name="CachedImageFetcher.ImageLoadFromNativeTimeJava" units="ms" expires_after="2019-12-01"> + <obsolete> + Renamed to ImageFetcher.ImageLoadFromNativeTimeJava on 06/2019. + </obsolete> <owner>fgorski@chromium.org</owner> <owner>wylieb@chromium.org</owner> <summary> @@ -17112,6 +17120,9 @@ <histogram name="CachedImageFetcher.ImageLoadFromNetworkAfterCacheHit" units="ms" expires_after="2019-12-01"> + <obsolete> + Renamed to ImageFetcher.ImageLoadFromNetworkAfterCacheHit on 06/2019. + </obsolete> <owner>fgorski@chromium.org</owner> <owner>wylieb@chromium.org</owner> <summary> @@ -17122,6 +17133,9 @@ <histogram name="CachedImageFetcher.ImageLoadFromNetworkTime" units="ms" expires_after="2019-12-01"> + <obsolete> + Renamed to ImageFetcher.ImageLoadFromNetworkTime on 06/2019. + </obsolete> <owner>fgorski@chromium.org</owner> <owner>wylieb@chromium.org</owner> <summary> @@ -17132,6 +17146,9 @@ <histogram name="CachedImageFetcher.LoadImageMetadata" units="ms" expires_after="2020-06-30"> + <obsolete> + Renamed to ImageFetcher.LoadImageMetadata on 06/2019. + </obsolete> <owner>fgorski@chromium.org</owner> <owner>wylieb@chromium.org</owner> <summary> @@ -17141,6 +17158,9 @@ <histogram name="CachedImageFetcher.TimeSinceLastCacheLRUEviction" units="ms" expires_after="2019-12-01"> + <obsolete> + Renamed to ImageFetcher.TimeSinceLastCacheLRUEviction on 06/2019. + </obsolete> <owner>fgorski@chromium.org</owner> <owner>wylieb@chromium.org</owner> <summary> @@ -31055,6 +31075,9 @@ <histogram name="Download.InterruptedAtEndReason" enum="InterruptReason" expires_after="M77"> + <obsolete> + Removed in 07/2019. + </obsolete> <owner>dtrainor@chromium.org</owner> <summary> The reason that a download was interrupted at the *end* of a download (when @@ -31072,6 +31095,9 @@ </histogram> <histogram name="Download.InterruptedOverrunBytes" expires_after="M77"> + <obsolete> + Removed in 07/2019. + </obsolete> <owner>dtrainor@chromium.org</owner> <summary> The total number of bytes minus the received number of bytes at the time @@ -31090,6 +31116,9 @@ <histogram name="Download.InterruptedReceivedSizeK" units="KB" expires_after="M77"> + <obsolete> + Removed in 07/2019. + </obsolete> <owner>dtrainor@chromium.org</owner> <summary> The number of kilobytes received for a download at the time it is @@ -31109,6 +31138,9 @@ </histogram> <histogram name="Download.InterruptedUnderrunBytes"> + <obsolete> + Removed in 07/2019. + </obsolete> <owner>dtrainor@chromium.org</owner> <summary> The excessive number of bytes which have been received at the time that a @@ -45656,6 +45688,15 @@ </summary> </histogram> +<histogram name="GCM.SendWebPushMessagePayloadSize" expires_after="2020-02-02"> + <owner>alexchau@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Size of web push messages payload. Recorded right before the message is + sent. + </summary> +</histogram> + <histogram name="GCM.SendWebPushMessageResult" enum="SendWebPushMessageResult" expires_after="2020-02-02"> <owner>alexchau@chromium.org</owner> @@ -50062,6 +50103,76 @@ </summary> </histogram> +<histogram name="ImageFetcher.ImageLoadFromCacheTime" units="ms" + expires_after="2020-06-06"> + <owner>fgorski@chromium.org</owner> + <owner>wylieb@chromium.org</owner> + <summary> + The time it takes for cached_image_fetcher to load an image from the cache + in native. + </summary> +</histogram> + +<histogram name="ImageFetcher.ImageLoadFromCacheTimeJava" units="ms" + expires_after="2020-06-06"> + <owner>fgorski@chromium.org</owner> + <owner>wylieb@chromium.org</owner> + <summary> + The time it takes for cached_image_fetcher to load an image from the cache + in Java. + </summary> +</histogram> + +<histogram name="ImageFetcher.ImageLoadFromNativeTimeJava" units="ms" + expires_after="2020-06-06"> + <owner>fgorski@chromium.org</owner> + <owner>wylieb@chromium.org</owner> + <summary> + The time it takes for cached_image_fetcher to load an image from native + code. Only recorded on successful loads. + </summary> +</histogram> + +<histogram name="ImageFetcher.ImageLoadFromNetworkAfterCacheHit" units="ms" + expires_after="2020-06-06"> + <owner>fgorski@chromium.org</owner> + <owner>wylieb@chromium.org</owner> + <summary> + The time it takes for cached_image_fetcher to load an image from the network + after a cache hit. + </summary> +</histogram> + +<histogram name="ImageFetcher.ImageLoadFromNetworkTime" units="ms" + expires_after="2020-06-06"> + <owner>fgorski@chromium.org</owner> + <owner>wylieb@chromium.org</owner> + <summary> + The time it takes for cached_image_fetcher to load an image from the + network. + </summary> +</histogram> + +<histogram name="ImageFetcher.LoadImageMetadata" units="ms" + expires_after="2020-06-30"> + <owner>fgorski@chromium.org</owner> + <owner>wylieb@chromium.org</owner> + <summary> + The time it takes to load an image's metadata from the metadata store. + </summary> +</histogram> + +<histogram name="ImageFetcher.TimeSinceLastCacheLRUEviction" units="ms" + expires_after="2019-12-01"> + <owner>fgorski@chromium.org</owner> + <owner>wylieb@chromium.org</owner> + <summary> + The time since the last LRU eviction from the image cache. Recorded when two + LRU evictions occur within closure proximity to one another. Will be used to + determine if LRU eviction is happening too frequently. + </summary> +</histogram> + <histogram name="ImageLoader.Client.Cache.HitMiss" enum="BooleanCacheHit" expires_after="2019-01-01"> <owner>chromeos-files-app@google.com</owner> @@ -83630,6 +83741,9 @@ <histogram name="NewTabPage.TileFaviconFetchStatus.Server" enum="GoogleFaviconServerRequestStatus" expires_after="M77"> + <obsolete> + Deprecated 07/2019 because the histogram was unused and close to expiration. + </obsolete> <owner>jkrcal@chromium.org</owner> <summary> Mobile only. The result of fetching a favicon for a tile on the New Tab @@ -83640,6 +83754,9 @@ <histogram name="NewTabPage.TileFaviconFetchSuccess.Popular" enum="BooleanSuccess" expires_after="M77"> + <obsolete> + Deprecated 07/2019 because the histogram was unused and close to expiration. + </obsolete> <owner>jkrcal@chromium.org</owner> <summary> Mobile only. The result of fetching a favicon for a tile on the New Tab @@ -85824,7 +85941,7 @@ </histogram> <histogram name="OfflinePages.AutoFetch.CompleteNotificationAction" - enum="OfflinePagesAutoFetchNotificationAction" expires_after="2019-08-30"> + enum="OfflinePagesAutoFetchNotificationAction" expires_after="2020-03-30"> <owner>harringtond@google.com</owner> <owner>carlosk@chromium.org</owner> <summary> @@ -85834,7 +85951,7 @@ </histogram> <histogram name="OfflinePages.AutoFetch.InProgressNotificationAction" - enum="OfflinePagesAutoFetchNotificationAction" expires_after="2019-08-30"> + enum="OfflinePagesAutoFetchNotificationAction" expires_after="2020-03-30"> <owner>harringtond@google.com</owner> <owner>carlosk@chromium.org</owner> <summary> @@ -102358,6 +102475,15 @@ </summary> </histogram> +<histogram name="Power.Mac.IsOnBattery" enum="BooleanOnBattery" + expires_after="2020-07-19"> + <owner>lgrey@chromium.org</owner> + <owner>sdy@chromium.org</owner> + <summary> + Whether the user's machine is on battery power. Sampled once per minute. + </summary> +</histogram> + <histogram name="Power.Mac.ThermalState" enum="MacThermalState" expires_after="2020-05-13"> <owner>lgrey@chromium.org</owner> @@ -113019,7 +113145,11 @@ </histogram> <histogram name="SafeBrowsing.V4GetHash.Parse.Result" - enum="SafeBrowsingParseV4HashResult" expires_after="M77"> + enum="SafeBrowsingParseV4HashResult" expires_after="never"> +<!-- expires-never: This reports the reason for the failure to parse the response +from Safe Browsing. Keeping track of these errors is critical to ensure that +Safe Browsing lookup mechanism is working as expected --> + <owner>vakh@chromium.org</owner> <owner>kcarattini@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> @@ -115146,8 +115276,8 @@ </histogram> <histogram name="SBClientDownload.DownloadFileHasDetachedSignatures" - enum="Boolean" expires_after="M77"> - <owner>vakh@chromium.org</owner> + enum="Boolean" expires_after="M78"> + <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> A Mac-only metric that records whether a given download contains a detached @@ -115559,8 +115689,8 @@ </histogram> <histogram name="SBClientDownload.ZipFileFailureByType" - enum="SBClientDownloadExtensions" expires_after="M77"> - <owner>vakh@chromium.org</owner> + enum="SBClientDownloadExtensions" expires_after="M78"> + <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> Counts of ZIP-like file types that failed to be successfully analyzed by the @@ -115608,8 +115738,8 @@ </histogram> <histogram name="SBClientDownload.ZipFileSuccess" enum="BooleanSuccess" - expires_after="M77"> - <owner>vakh@chromium.org</owner> + expires_after="M78"> + <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> For each zip file analyzed by the SafeBrowsing download service, records if @@ -145430,7 +145560,7 @@ </histogram> <histogram name="VoiceInteraction.FailureEventSource" - enum="VoiceInteractionEventSource" expires_after="M77"> + enum="VoiceInteractionEventSource" expires_after="M81"> <owner>tedchoc@chromium.org</owner> <owner>yusufo@chromium.org</owner> <summary> @@ -145479,7 +145609,7 @@ </histogram> <histogram name="VoiceInteraction.VoiceResultConfidenceValue" units="%" - expires_after="M77"> + expires_after="M81"> <owner>tedchoc@chromium.org</owner> <owner>yusufo@chromium.org</owner> <summary> @@ -155334,7 +155464,7 @@ <suffix name="SendBeginMainFrameToCommit" label="The time from when the BeginMainFrame is sent to the beginning of the commit."/> - <suffix name="SubmitCompositorFrameToPresentCompositorFrame" + <suffix name="SubmitCompositorFrameToPresentationCompositorFrame" label="The time from when the a compositor frame is submitted to the display compositor to when it is presented."/> <suffix name="TotalLatency" @@ -158507,19 +158637,20 @@ label="Showing cache patterns only for AssistantDetails."/> <suffix name="ContextualSuggestions" label="Showing cache patterns only for ContextualSuggestions."/> + <suffix name="EntitySuggestions" + label="Showing cache patterns only for EntitySuggestions."/> <suffix name="Feed" label="Showing cache patterns only for Feed."/> <suffix name="Internal" label="Showing cache patterns only for Internal."/> <suffix name="NewTabPageAnimatedLogo" label="Showing cache patterns only for NewTabPageAnimatedLogo."/> <suffix name="OfflinePages" label="Showing cache patterns only for OfflinePages."/> - <affected-histogram name="CachedImageFetcher.ImageLoadFromCacheTime"/> - <affected-histogram name="CachedImageFetcher.ImageLoadFromCacheTimeJava"/> - <affected-histogram name="CachedImageFetcher.ImageLoadFromNativeTimeJava"/> - <affected-histogram - name="CachedImageFetcher.ImageLoadFromNetworkAfterCacheHit"/> - <affected-histogram name="CachedImageFetcher.ImageLoadFromNetworkTime"/> <affected-histogram name="ImageFetcher.Events"/> + <affected-histogram name="ImageFetcher.ImageLoadFromCacheTime"/> + <affected-histogram name="ImageFetcher.ImageLoadFromCacheTimeJava"/> + <affected-histogram name="ImageFetcher.ImageLoadFromNativeTimeJava"/> + <affected-histogram name="ImageFetcher.ImageLoadFromNetworkAfterCacheHit"/> + <affected-histogram name="ImageFetcher.ImageLoadFromNetworkTime"/> </histogram_suffixes> <histogram_suffixes name="IMEAutoCorrect" separator=".">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 65b0af4..114de02 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -89,6 +89,13 @@ with non-zero bytes. Recorded when a page is destroyed or when the app is backgrounded on mobile. </summary> + <metric name="CpuTime.PeakWindowedPercent"> + <summary> + The peak percentage of CPU utilization attributed to the frame in any 30 + second window prior to user activation. Frames that exist for less than 30 + seconds still use 30 seconds as the denominator for the calculation. + </summary> + </metric> <metric name="CpuTime.PreActivation"> <summary> Wall time of tasks attributed to the frame after the frame recieved user
diff --git a/tools/perf/core/minidump_unittest.py b/tools/perf/core/minidump_unittest.py index 23cf7a7..4085a37 100644 --- a/tools/perf/core/minidump_unittest.py +++ b/tools/perf/core/minidump_unittest.py
@@ -3,6 +3,7 @@ # found in the LICENSE file. import logging +import os import time from telemetry.testing import tab_test_case @@ -16,12 +17,12 @@ # ChromeOS and Android are currently hard coded to return None for minidump # paths, so disable on those platforms. Windows 7 doesn't find any minidump # paths for some reason. - @decorators.Disabled('chromeos', 'android', 'win7', 'linux') + @decorators.Disabled('chromeos', 'android', 'win7') def testSymbolizeMinidump(self): # Wait for the browser to restart fully before crashing self._LoadPageThenWait('var sam = "car";', 'sam') self._browser.tabs.New().Navigate('chrome://gpucrash', timeout=5) - crash_minidump_path = self._browser.GetMostRecentMinidumpPath() + crash_minidump_path = self._browser.GetRecentMinidumpPathWithTimeout() self.assertIsNotNone(crash_minidump_path) if crash_minidump_path is not None: @@ -91,13 +92,12 @@ # Disabled on Mac 10.12 (Sierra) due to it not getting a stack trace to # symbolize from the second crash. # Test is flaky on 10.13 (HighSierra). See https://crbug.com/986644. - @decorators.Disabled('chromeos', 'android', 'win7', 'sierra', 'linux', - 'highsierra') + @decorators.Disabled('chromeos', 'android', 'win7', 'sierra', 'highsierra') def testMultipleCrashMinidumps(self): # Wait for the browser to restart fully before crashing self._LoadPageThenWait('var cat = "dog";', 'cat') self._browser.tabs.New().Navigate('chrome://gpucrash', timeout=5) - first_crash_path = self._browser.GetMostRecentMinidumpPath() + first_crash_path = self._browser.GetRecentMinidumpPathWithTimeout() self.assertIsNotNone(first_crash_path) if first_crash_path is not None: @@ -122,7 +122,11 @@ self._LoadPageThenWait('var foo = "bar";', 'foo') self._browser.tabs.New().Navigate('chrome://gpucrash', timeout=5) - second_crash_path = self._browser.GetMostRecentMinidumpPath() + # Make the oldest allowable timestamp slightly after the first dump's + # timestamp so we don't get the first one returned to us again + oldest_ts = os.path.getmtime(first_crash_path) + 1 + second_crash_path = self._browser.GetRecentMinidumpPathWithTimeout( + oldest_ts=oldest_ts) self.assertIsNotNone(second_crash_path) if second_crash_path is not None: logging.info('testMultipleCrashMinidumps: second crash most recent path'
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc index 1739e75..6af53ea 100644 --- a/ui/accessibility/ax_event_generator.cc +++ b/ui/accessibility/ax_event_generator.cc
@@ -14,9 +14,11 @@ namespace ui { namespace { -bool IsLiveRegion(const AXTreeObserver::Change& change) { +bool IsActiveLiveRegion(const AXTreeObserver::Change& change) { return change.node->data().HasStringAttribute( - ax::mojom::StringAttribute::kLiveStatus); + ax::mojom::StringAttribute::kLiveStatus) && + change.node->data().GetStringAttribute( + ax::mojom::StringAttribute::kLiveStatus) != "off"; } bool IsContainedInLiveRegion(const AXTreeObserver::Change& change) { @@ -517,16 +519,12 @@ continue; } - if (IsLiveRegion(change)) { - if (IsAlert(change.node->data().role)) { - AddEvent(change.node, Event::ALERT); - } else if (change.node->data().GetStringAttribute( - ax::mojom::StringAttribute::kLiveStatus) != "off") { - AddEvent(change.node, Event::LIVE_REGION_CREATED); - } - } else if (IsContainedInLiveRegion(change)) { + if (IsAlert(change.node->data().role)) + AddEvent(change.node, Event::ALERT); + else if (IsActiveLiveRegion(change)) + AddEvent(change.node, Event::LIVE_REGION_CREATED); + else if (IsContainedInLiveRegion(change)) FireLiveRegionEvents(change.node); - } } FireActiveDescendantEvents();
diff --git a/ui/accessibility/ax_event_generator_unittest.cc b/ui/accessibility/ax_event_generator_unittest.cc index d1df0fa8..a676881 100644 --- a/ui/accessibility/ax_event_generator_unittest.cc +++ b/ui/accessibility/ax_event_generator_unittest.cc
@@ -401,26 +401,36 @@ AXEventGenerator event_generator(&tree); AXTreeUpdate update = initial_state; - update.nodes.resize(3); + update.nodes.resize(4); update.nodes[0].child_ids.push_back(2); update.nodes[0].child_ids.push_back(3); + update.nodes[0].child_ids.push_back(4); + update.nodes[1].id = 2; update.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kLiveStatus, "polite"); + + // Blink should automatically add aria-live="assertive" to elements with role + // kAlert, but we should fire an alert event regardless. update.nodes[2].id = 3; update.nodes[2].role = ax::mojom::Role::kAlert; - update.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kLiveStatus, - "polite"); + + // Elements with role kAlertDialog will *not* usually have a live region + // status, but again, we should always fire an alert event. + update.nodes[3].id = 4; + update.nodes[3].role = ax::mojom::Role::kAlertDialog; ASSERT_TRUE(tree.Unserialize(update)); EXPECT_THAT( event_generator, UnorderedElementsAre( HasEventAtNode(AXEventGenerator::Event::ALERT, 3), + HasEventAtNode(AXEventGenerator::Event::ALERT, 4), HasEventAtNode(AXEventGenerator::Event::CHILDREN_CHANGED, 1), HasEventAtNode(AXEventGenerator::Event::LIVE_REGION_CREATED, 2), HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 2), - HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 3))); + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 3), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 4))); } TEST(AXEventGeneratorTest, LiveRegionChanged) {
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index 0d994c5e..b88ff7b 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc
@@ -16,6 +16,7 @@ #include "build/build_config.h" #include "cc/base/switches.h" #include "cc/test/pixel_test_output_surface.h" +#include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/frame_sinks/delay_based_time_source.h" #include "components/viz/common/gpu/context_provider.h" @@ -25,8 +26,11 @@ #include "components/viz/service/display/display_scheduler.h" #include "components/viz/service/display/output_surface_client.h" #include "components/viz/service/display/output_surface_frame.h" +#include "components/viz/service/display_embedder/skia_output_surface_dependency_impl.h" +#include "components/viz/service/display_embedder/skia_output_surface_impl.h" #include "components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/test/test_gpu_service_holder.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/common/context_creation_attribs.h" @@ -156,6 +160,14 @@ InProcessContextFactory::InProcessContextFactory( viz::HostFrameSinkManager* host_frame_sink_manager, viz::FrameSinkManagerImpl* frame_sink_manager) + : InProcessContextFactory(host_frame_sink_manager, + frame_sink_manager, + features::IsUsingSkiaRenderer()) {} + +InProcessContextFactory::InProcessContextFactory( + viz::HostFrameSinkManager* host_frame_sink_manager, + viz::FrameSinkManagerImpl* frame_sink_manager, + bool use_skia_renderer) : frame_sink_id_allocator_(kDefaultClientId), use_test_surface_(true), disable_vsync_(base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -166,6 +178,8 @@ DCHECK_NE(gl::GetGLImplementation(), gl::kGLImplementationNone) << "If running tests, ensure that main() is calling " << "gl::GLSurfaceTestSupport::InitializeOneOff()"; + if (use_skia_renderer) + renderer_settings_.use_skia_renderer = true; #if defined(OS_MACOSX) renderer_settings_.release_overlay_resources_after_gpu_query = true; // Ensure that tests don't wait for frames that will never come. @@ -229,7 +243,14 @@ "UICompositor", support_locking); std::unique_ptr<viz::OutputSurface> display_output_surface; - if (use_test_surface_) { + + if (renderer_settings_.use_skia_renderer) { + display_output_surface = viz::SkiaOutputSurfaceImpl::Create( + std::make_unique<viz::SkiaOutputSurfaceDependencyImpl>( + viz::TestGpuServiceHolder::GetInstance()->gpu_service(), + gpu::kNullSurfaceHandle), + renderer_settings_); + } else if (use_test_surface_) { bool flipped_output_surface = false; display_output_surface = std::make_unique<cc::PixelTestOutputSurface>( context_provider, flipped_output_surface);
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h index 74bcae6..8456536c 100644 --- a/ui/compositor/test/in_process_context_factory.h +++ b/ui/compositor/test/in_process_context_factory.h
@@ -32,11 +32,15 @@ public ContextFactoryPrivate { public: // Both |host_frame_sink_manager| and |frame_sink_manager| must outlive the - // ContextFactory. + // ContextFactory. The constructor without |use_skia_renderer| will use + // SkiaRenderer if the feature is enabled. // TODO(crbug.com/657959): |frame_sink_manager| should go away and we should // use the LayerTreeFrameSink from the HostFrameSinkManager. InProcessContextFactory(viz::HostFrameSinkManager* host_frame_sink_manager, viz::FrameSinkManagerImpl* frame_sink_manager); + InProcessContextFactory(viz::HostFrameSinkManager* host_frame_sink_manager, + viz::FrameSinkManagerImpl* frame_sink_manager, + bool use_skia_renderer); ~InProcessContextFactory() override; viz::FrameSinkManagerImpl* GetFrameSinkManager() {
diff --git a/ui/display/manager/configure_displays_task.cc b/ui/display/manager/configure_displays_task.cc index 6ef399a..6db2868 100644 --- a/ui/display/manager/configure_displays_task.cc +++ b/ui/display/manager/configure_displays_task.cc
@@ -77,15 +77,9 @@ size_t index = pending_request_indexes_.front(); DisplayConfigureRequest* request = &requests_[index]; pending_request_indexes_.pop(); - // Non-native displays do not require configuration through the - // NativeDisplayDelegate. - if (!IsPhysicalDisplayType(request->display->type())) { - OnConfigured(index, true); - } else { - delegate_->Configure(*request->display, request->mode, request->origin, - base::Bind(&ConfigureDisplaysTask::OnConfigured, - weak_ptr_factory_.GetWeakPtr(), index)); - } + delegate_->Configure(*request->display, request->mode, request->origin, + base::Bind(&ConfigureDisplaysTask::OnConfigured, + weak_ptr_factory_.GetWeakPtr(), index)); } }
diff --git a/ui/display/manager/content_protection_manager.cc b/ui/display/manager/content_protection_manager.cc index 59e8613b..986d961 100644 --- a/ui/display/manager/content_protection_manager.cc +++ b/ui/display/manager/content_protection_manager.cc
@@ -12,7 +12,6 @@ #include "base/stl_util.h" #include "ui/display/manager/apply_content_protection_task.h" #include "ui/display/manager/display_layout_manager.h" -#include "ui/display/manager/display_util.h" #include "ui/display/manager/query_content_protection_task.h" #include "ui/display/types/display_constants.h" #include "ui/display/types/display_snapshot.h" @@ -79,10 +78,7 @@ QueryContentProtectionCallback callback) { DCHECK(disabled() || GetContentProtections(client_id)); - // Exclude virtual displays so that protected content will not be recaptured - // through the cast stream. - const DisplaySnapshot* display = GetDisplay(display_id); - if (disabled() || !display || !IsPhysicalDisplayType(display->type())) { + if (disabled() || !GetDisplay(display_id)) { std::move(callback).Run(/*success=*/false, DISPLAY_CONNECTION_TYPE_NONE, CONTENT_PROTECTION_METHOD_NONE); return; @@ -277,11 +273,6 @@ for (DisplaySnapshot* display : layout_manager_->GetDisplayStates()) { int64_t display_id = display->display_id(); - if (!IsPhysicalDisplayType(display->type())) { - NotifyDisplaySecurityObservers(display_id, /*secure=*/false); - continue; - } - QueueTask(std::make_unique<QueryContentProtectionTask>( layout_manager_, native_display_delegate_, display_id, base::BindOnce(&ContentProtectionManager::OnDisplaySecurityQueried, @@ -300,18 +291,12 @@ (protection_mask != CONTENT_PROTECTION_METHOD_NONE || connection_mask == DISPLAY_CONNECTION_TYPE_INTERNAL); - NotifyDisplaySecurityObservers(display_id, secure); + for (Observer& observer : observers_) + observer.OnDisplaySecurityChanged(display_id, secure); } if (status != Task::Status::KILLED) DequeueTask(); } -void ContentProtectionManager::NotifyDisplaySecurityObservers( - int64_t display_id, - bool secure) { - for (Observer& observer : observers_) - observer.OnDisplaySecurityChanged(display_id, secure); -} - } // namespace display
diff --git a/ui/display/manager/content_protection_manager.h b/ui/display/manager/content_protection_manager.h index 6364e93..0d4af4cb 100644 --- a/ui/display/manager/content_protection_manager.h +++ b/ui/display/manager/content_protection_manager.h
@@ -158,7 +158,6 @@ Task::Status status, uint32_t connection_mask, uint32_t protection_mask); - void NotifyDisplaySecurityObservers(int64_t display_id, bool secure); DisplayLayoutManager* const layout_manager_; // Not owned. NativeDisplayDelegate* native_display_delegate_ = nullptr; // Not owned.
diff --git a/ui/display/manager/content_protection_manager_unittest.cc b/ui/display/manager/content_protection_manager_unittest.cc index 0a05e3ce..ee4c0fc 100644 --- a/ui/display/manager/content_protection_manager_unittest.cc +++ b/ui/display/manager/content_protection_manager_unittest.cc
@@ -18,7 +18,7 @@ namespace { -constexpr int64_t kDisplayIds[] = {123, 456}; +constexpr int64_t kDisplayIds[] = {123, 456, 789}; const DisplayMode kDisplayMode{gfx::Size(1366, 768), false, 60.0f}; } // namespace @@ -67,6 +67,12 @@ .SetCurrentMode(kDisplayMode.Clone()) .Build(); + displays_[2] = FakeDisplaySnapshot::Builder() + .SetId(kDisplayIds[2]) + .SetType(DISPLAY_CONNECTION_TYPE_VGA) + .SetCurrentMode(kDisplayMode.Clone()) + .Build(); + UpdateDisplays(2); } @@ -122,7 +128,7 @@ uint32_t connection_mask_ = DISPLAY_CONNECTION_TYPE_NONE; uint32_t protection_mask_ = CONTENT_PROTECTION_METHOD_NONE; - std::unique_ptr<DisplaySnapshot> displays_[2]; + std::unique_ptr<DisplaySnapshot> displays_[3]; DISALLOW_COPY_AND_ASSIGN(ContentProtectionManagerTest); }; @@ -674,5 +680,81 @@ observer.security_changes()); } +TEST_F(ContentProtectionManagerTest, AnalogDisplaySecurity) { + UpdateDisplays(3); + TestObserver observer(&manager_); + + EXPECT_EQ(SecurityChanges({{kDisplayIds[0], true}, + {kDisplayIds[1], false}, + {kDisplayIds[2], false}}), + observer.security_changes()); + observer.Reset(); + + auto id = manager_.RegisterClient(); + EXPECT_TRUE(id); + + native_display_delegate_.set_run_async(true); + + for (int64_t display_id : kDisplayIds) { + manager_.ApplyContentProtection( + id, display_id, CONTENT_PROTECTION_METHOD_HDCP, + base::BindOnce( + &ContentProtectionManagerTest::ApplyContentProtectionCallback, + base::Unretained(this))); + } + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(observer.security_changes().empty()); + + EXPECT_TRUE(TriggerDisplaySecurityTimeout()); + base::RunLoop().RunUntilIdle(); + + // Analog display is never secure. + EXPECT_EQ(SecurityChanges({{kDisplayIds[0], true}, + {kDisplayIds[1], true}, + {kDisplayIds[2], false}}), + observer.security_changes()); + observer.Reset(); + + layout_manager_.set_display_state(MULTIPLE_DISPLAY_STATE_MULTI_MIRROR); + TriggerDisplayConfiguration(); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(TriggerDisplaySecurityTimeout()); + base::RunLoop().RunUntilIdle(); + + // Internal display is not secure if mirrored to an analog display. + EXPECT_EQ(SecurityChanges({{kDisplayIds[0], false}, + {kDisplayIds[1], false}, + {kDisplayIds[2], false}}), + observer.security_changes()); + observer.Reset(); + + layout_manager_.set_display_state(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED); + TriggerDisplayConfiguration(); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(TriggerDisplaySecurityTimeout()); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(SecurityChanges({{kDisplayIds[0], true}, + {kDisplayIds[1], true}, + {kDisplayIds[2], false}}), + observer.security_changes()); + observer.Reset(); + + manager_.UnregisterClient(id); + + // Timer should be stopped when no client requests protection. + EXPECT_FALSE(TriggerDisplaySecurityTimeout()); + base::RunLoop().RunUntilIdle(); + + // Observer should be notified when client unregisters. + EXPECT_EQ(SecurityChanges({{kDisplayIds[0], true}, + {kDisplayIds[1], false}, + {kDisplayIds[2], false}}), + observer.security_changes()); +} + } // namespace test } // namespace display
diff --git a/ui/display/manager/display_util.cc b/ui/display/manager/display_util.cc index 5f299ae..c8c273c4 100644 --- a/ui/display/manager/display_util.cc +++ b/ui/display/manager/display_util.cc
@@ -119,10 +119,6 @@ return "INVALID"; } -bool IsPhysicalDisplayType(DisplayConnectionType type) { - return !(type & DISPLAY_CONNECTION_TYPE_NETWORK); -} - bool GetContentProtectionMethods(DisplayConnectionType type, uint32_t* protection_mask) { switch (type) {
diff --git a/ui/display/manager/display_util.h b/ui/display/manager/display_util.h index 2f2a3a7..e90f055 100644 --- a/ui/display/manager/display_util.h +++ b/ui/display/manager/display_util.h
@@ -37,11 +37,6 @@ // Returns a string describing |state|. std::string MultipleDisplayStateToString(MultipleDisplayState state); -// Returns whether the DisplayConnectionType |type| is a physically connected -// display. Currently only DISPLAY_CONNECTION_TYPE_NETWORK return false. -// All other types return true. -bool IsPhysicalDisplayType(DisplayConnectionType type); - // Sets bits in |protection_mask| for each ContentProtectionMethod supported by // the display |type|. Returns false for unknown display types. bool GetContentProtectionMethods(DisplayConnectionType type,
diff --git a/ui/display/manager/query_content_protection_task.cc b/ui/display/manager/query_content_protection_task.cc index 8488b96..a627324 100644 --- a/ui/display/manager/query_content_protection_task.cc +++ b/ui/display/manager/query_content_protection_task.cc
@@ -48,8 +48,14 @@ return; } + // Collect displays to be queried based on HDCP capability. For unprotected + // displays not inherently secure through an internal connection, record the + // existence of an unsecure display to report no protection for all displays + // in mirroring mode. if (protection_mask & CONTENT_PROTECTION_METHOD_HDCP) hdcp_capable_displays.push_back(display); + else if (display->type() != DISPLAY_CONNECTION_TYPE_INTERNAL) + no_protection_mask_ |= CONTENT_PROTECTION_METHOD_HDCP; } pending_requests_ = hdcp_capable_displays.size();
diff --git a/ui/display/manager/query_content_protection_task_unittest.cc b/ui/display/manager/query_content_protection_task_unittest.cc index 69b2759c..7404e3b8 100644 --- a/ui/display/manager/query_content_protection_task_unittest.cc +++ b/ui/display/manager/query_content_protection_task_unittest.cc
@@ -81,7 +81,7 @@ ASSERT_TRUE(response_); EXPECT_EQ(Status::SUCCESS, response_->status); EXPECT_EQ(DISPLAY_CONNECTION_TYPE_INTERNAL, response_->connection_mask); - EXPECT_EQ(0u, response_->protection_mask); + EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, response_->protection_mask); } TEST_F(QueryContentProtectionTaskTest, QueryUnknownDisplay) { @@ -99,7 +99,7 @@ ASSERT_TRUE(response_); EXPECT_EQ(Status::FAILURE, response_->status); EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN, response_->connection_mask); - EXPECT_EQ(0u, response_->protection_mask); + EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, response_->protection_mask); } TEST_F(QueryContentProtectionTaskTest, QueryDisplayThatCannotGetHdcp) { @@ -135,7 +135,7 @@ ASSERT_TRUE(response_); EXPECT_EQ(Status::SUCCESS, response_->status); EXPECT_EQ(DISPLAY_CONNECTION_TYPE_HDMI, response_->connection_mask); - EXPECT_EQ(0u, response_->protection_mask); + EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, response_->protection_mask); } TEST_F(QueryContentProtectionTaskTest, QueryDisplayWithHdcpEnabled) { @@ -173,7 +173,7 @@ ASSERT_TRUE(response_); EXPECT_EQ(Status::SUCCESS, response_->status); EXPECT_EQ(DISPLAY_CONNECTION_TYPE_HDMI, response_->connection_mask); - EXPECT_EQ(0u, response_->protection_mask); + EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, response_->protection_mask); } TEST_F(QueryContentProtectionTaskTest, QueryInMirroringMode) { @@ -194,7 +194,63 @@ EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI | DISPLAY_CONNECTION_TYPE_DVI), response_->connection_mask); - EXPECT_EQ(0u, response_->protection_mask); + EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, response_->protection_mask); +} + +TEST_F(QueryContentProtectionTaskTest, QueryAnalogDisplay) { + std::vector<std::unique_ptr<DisplaySnapshot>> displays; + displays.push_back(CreateDisplaySnapshot(1, DISPLAY_CONNECTION_TYPE_VGA)); + TestDisplayLayoutManager layout_manager(std::move(displays), + MULTIPLE_DISPLAY_STATE_SINGLE); + + QueryContentProtectionTask task( + &layout_manager, &display_delegate_, 1, + base::Bind(&QueryContentProtectionTaskTest::ResponseCallback, + base::Unretained(this))); + task.Run(); + + ASSERT_TRUE(response_); + EXPECT_EQ(Status::SUCCESS, response_->status); + EXPECT_EQ(DISPLAY_CONNECTION_TYPE_VGA, response_->connection_mask); + EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, response_->protection_mask); +} + +TEST_F(QueryContentProtectionTaskTest, QueryAnalogDisplayMirror) { + std::vector<std::unique_ptr<DisplaySnapshot>> displays; + displays.push_back(CreateDisplaySnapshot(1, DISPLAY_CONNECTION_TYPE_HDMI)); + displays.push_back(CreateDisplaySnapshot(2, DISPLAY_CONNECTION_TYPE_VGA)); + TestDisplayLayoutManager layout_manager(std::move(displays), + MULTIPLE_DISPLAY_STATE_MULTI_MIRROR); + + display_delegate_.set_hdcp_state(HDCP_STATE_ENABLED); + + QueryContentProtectionTask task1( + &layout_manager, &display_delegate_, 1, + base::Bind(&QueryContentProtectionTaskTest::ResponseCallback, + base::Unretained(this))); + task1.Run(); + + ASSERT_TRUE(response_); + EXPECT_EQ(Status::SUCCESS, response_->status); + EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI | + DISPLAY_CONNECTION_TYPE_VGA), + response_->connection_mask); + EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, response_->protection_mask); + + response_.reset(); + + QueryContentProtectionTask task2( + &layout_manager, &display_delegate_, 2, + base::Bind(&QueryContentProtectionTaskTest::ResponseCallback, + base::Unretained(this))); + task2.Run(); + + ASSERT_TRUE(response_); + EXPECT_EQ(Status::SUCCESS, response_->status); + EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI | + DISPLAY_CONNECTION_TYPE_VGA), + response_->connection_mask); + EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, response_->protection_mask); } } // namespace test
diff --git a/ui/events/ozone/evdev/event_device_test_util.cc b/ui/events/ozone/evdev/event_device_test_util.cc index 0cdb1f6a..2cdb518 100644 --- a/ui/events/ozone/evdev/event_device_test_util.cc +++ b/ui/events/ozone/evdev/event_device_test_util.cc
@@ -211,6 +211,45 @@ base::size(kEveTouchScreenAbsAxes), }; +// Captured from Pixel Slate. +const DeviceAbsoluteAxis kNocturneTouchScreenAbsAxes[] = { + {ABS_X, {0, 0, 10404, 0, 0, 40}}, + {ABS_Y, {0, 0, 6936, 0, 0, 40}}, + {ABS_PRESSURE, {0, 0, 255, 0, 0, 0}}, + {ABS_MT_SLOT, {0, 0, 9, 0, 0, 0}}, + {ABS_MT_TOUCH_MAJOR, {0, 0, 255, 0, 0, 1}}, + {ABS_MT_TOUCH_MINOR, {0, 0, 255, 0, 0, 1}}, + {ABS_MT_ORIENTATION, {0, 0, 1, 0, 0, 0}}, + {ABS_MT_POSITION_X, {0, 0, 10404, 0, 0, 40}}, + {ABS_MT_POSITION_Y, {0, 0, 6936, 0, 0, 40}}, + {ABS_MT_TOOL_TYPE, {0, 0, 2, 0, 0, 0}}, + {ABS_MT_TRACKING_ID, {0, 0, 65535, 0, 0, 0}}, + {ABS_MT_PRESSURE, {0, 0, 255, 0, 0, 0}}, +}; +const DeviceCapabilities kNocturneTouchScreen = { + /* path */ + "/sys/devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-6/" + "i2c-WCOM50C1:00/0018:2D1F:486C.0001/input/input2/event2", + /* name */ "WCOM50C1:00 2D1F:486C", + /* phys */ "i2c-WCOM50C1:00", + /* uniq */ "", + /* bustype */ "0018", + /* vendor */ "2d1f", + /* product */ "486c", + /* version */ "0100", + /* prop */ "2", + /* ev */ "1b", + /* key */ "400 0 0 0 0 0", + /* rel */ "0", + /* abs */ "6f3800001000003", + /* msc */ "20", + /* sw */ "0", + /* led */ "0", + /* ff */ "0", + kNocturneTouchScreenAbsAxes, + base::size(kNocturneTouchScreenAbsAxes), +}; + // Captured from Chromebook Pixel. const DeviceCapabilities kLinkKeyboard = { /* path */ "/sys/devices/platform/i8042/serio0/input/input6/event6", @@ -639,6 +678,36 @@ base::size(kEveStylusAbsAxes), }; +// Captured from Pixel Slate +const DeviceAbsoluteAxis kNocturneStylusAbsAxes[] = { + {ABS_X, {0, 0, 26010, 0, 0, 100}}, {ABS_Y, {0, 0, 17340, 0, 0, 100}}, + {ABS_PRESSURE, {0, 0, 2047, 0, 0, 0}}, {ABS_TILT_X, {0, -90, 90, 0, 0, 57}}, + {ABS_TILT_Y, {0, -90, 90, 0, 0, 57}}, {ABS_MISC, {0, 0, 65535, 0, 0, 0}}, +}; +const DeviceCapabilities kNocturneStylus = { + /* path */ + "/sys/devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-6/" + "i2c-WCOM50C1:00/0018:2D1F:486C.0001/input/input3/event3", + /* name */ "WCOM50C1:00 2D1F:486C Pen", + /* phys */ "", + /* uniq */ "", + /* bustype */ "0018", + /* vendor */ "2d1f", + /* product */ "486c", + /* version */ "0100", + /* prop */ "0", + /* ev */ "1b", + /* key */ "1c03 1 0 0 0 0", + /* rel */ "0", + /* abs */ "1000d000003", + /* msc */ "11", + /* sw */ "0", + /* led */ "0", + /* ff */ "0", + kNocturneStylusAbsAxes, + base::size(kNocturneStylusAbsAxes), +}; + const DeviceCapabilities kHammerKeyboard = { /* path */ "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/0003:18D1:5030.0002/"
diff --git a/ui/events/ozone/evdev/event_device_test_util.h b/ui/events/ozone/evdev/event_device_test_util.h index 203b8aa..bbb7c7cfa 100644 --- a/ui/events/ozone/evdev/event_device_test_util.h +++ b/ui/events/ozone/evdev/event_device_test_util.h
@@ -82,6 +82,8 @@ extern const DeviceCapabilities kIlitekTP_Mouse; extern const DeviceCapabilities kIlitekTP; extern const DeviceCapabilities kSideVolumeButton; +extern const DeviceCapabilities kNocturneTouchScreen; +extern const DeviceCapabilities kNocturneStylus; } // namspace ui
diff --git a/ui/events/platform/x11/x11_event_source_libevent.cc b/ui/events/platform/x11/x11_event_source_libevent.cc index 500a520..8ef771f 100644 --- a/ui/events/platform/x11/x11_event_source_libevent.cc +++ b/ui/events/platform/x11/x11_event_source_libevent.cc
@@ -250,4 +250,12 @@ NOTREACHED(); } +void XEventDispatcher::CheckCanDispatchNextPlatformEvent(XEvent* xev) {} + +void XEventDispatcher::PlatformEventDispatchFinished() {} + +PlatformEventDispatcher* XEventDispatcher::GetPlatformEventDispatcher() { + return nullptr; +} + } // namespace ui
diff --git a/ui/events/platform/x11/x11_event_source_libevent.h b/ui/events/platform/x11/x11_event_source_libevent.h index a7f1aba..bc8a848 100644 --- a/ui/events/platform/x11/x11_event_source_libevent.h +++ b/ui/events/platform/x11/x11_event_source_libevent.h
@@ -20,25 +20,25 @@ // X11 currently. class EVENTS_EXPORT XEventDispatcher { public: + // Sends XEvent to XEventDispatcher for handling. Returns true if the XEvent + // was dispatched, otherwise false. After the first XEventDispatcher returns + // true XEvent dispatching stops. + virtual bool DispatchXEvent(XEvent* xevent) = 0; + // XEventDispatchers can be used to test if they are able to process next // translated event sent by a PlatformEventSource. If so, they must make a // promise internally to process next event sent by PlatformEventSource. - virtual void CheckCanDispatchNextPlatformEvent(XEvent* xev) = 0; + virtual void CheckCanDispatchNextPlatformEvent(XEvent* xev); // Tells that an event has been dispatched and an event handling promise must // be removed. - virtual void PlatformEventDispatchFinished() = 0; + virtual void PlatformEventDispatchFinished(); // Returns PlatformEventDispatcher if this XEventDispatcher is associated with // a PlatformEventDispatcher as well. Used to explicitly add a // PlatformEventDispatcher during a call from an XEventDispatcher to // AddXEventDispatcher. - virtual PlatformEventDispatcher* GetPlatformEventDispatcher() = 0; - - // Sends XEvent to XEventDispatcher for handling. Returns true if the XEvent - // was dispatched, otherwise false. After the first XEventDispatcher returns - // true XEvent dispatching stops. - virtual bool DispatchXEvent(XEvent* xevent) = 0; + virtual PlatformEventDispatcher* GetPlatformEventDispatcher(); protected: virtual ~XEventDispatcher() {}
diff --git a/ui/ozone/platform/x11/gl_surface_glx_ozone.cc b/ui/ozone/platform/x11/gl_surface_glx_ozone.cc index a4be7c87..583823d2 100644 --- a/ui/ozone/platform/x11/gl_surface_glx_ozone.cc +++ b/ui/ozone/platform/x11/gl_surface_glx_ozone.cc
@@ -30,14 +30,6 @@ event_source->RemoveXEventDispatcher(this); } -void GLSurfaceGLXOzone::CheckCanDispatchNextPlatformEvent(XEvent* xev) {} - -void GLSurfaceGLXOzone::PlatformEventDispatchFinished() {} - -PlatformEventDispatcher* GLSurfaceGLXOzone::GetPlatformEventDispatcher() { - return nullptr; -} - bool GLSurfaceGLXOzone::DispatchXEvent(XEvent* event) { if (!CanHandleEvent(event)) return false;
diff --git a/ui/ozone/platform/x11/gl_surface_glx_ozone.h b/ui/ozone/platform/x11/gl_surface_glx_ozone.h index 0c468010..3a65b96 100644 --- a/ui/ozone/platform/x11/gl_surface_glx_ozone.h +++ b/ui/ozone/platform/x11/gl_surface_glx_ozone.h
@@ -11,8 +11,6 @@ namespace ui { -class PlatformEventDispatcher; - // Ozone specific implementation of GLX surface. Registers as a XEventDispatcher // to handle XEvents. class GLSurfaceGLXOzone : public gl::NativeViewGLSurfaceGLX, @@ -28,9 +26,6 @@ void UnregisterEvents() override; // XEventDispatcher: - void CheckCanDispatchNextPlatformEvent(XEvent* xev) override; - void PlatformEventDispatchFinished() override; - PlatformEventDispatcher* GetPlatformEventDispatcher() override; bool DispatchXEvent(XEvent* xevent) override; private: