diff --git a/AUTHORS b/AUTHORS index bc76c72..856ac7b 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -1020,6 +1020,7 @@ Collabora Limited <*@collabora.com> Comodo CA Limited Cosium <*@cosium.com> +Duck Duck Go, Inc. <*@duckduckgo.com> Endless Mobile, Inc. <*@endlessm.com> Estimote, Inc. <*@estimote.com> Facebook, Inc. <*@fb.com>
diff --git a/DEPS b/DEPS index 064b036..8320f7e 100644 --- a/DEPS +++ b/DEPS
@@ -129,11 +129,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': '731eaa372a59ad3951ef2d461771b86e9e66c74e', + 'skia_revision': '7656b2c18ce88e023f7911274535a3df34118817', # 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': 'ce2242080787636827dd629ed5ee4e11a4368b9e', + 'v8_revision': 'c796dae269b97c5a146a50e8bc710e3bbfae77f1', # 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. @@ -141,11 +141,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '90b1865e2a8b644bc3e200726de9e3a321ee5c18', + 'angle_revision': '9f958344898ce0c4259d36c09c79e1a9de8ce47c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '3bb94905928d271476a7fb2c6a14912f2de94d9f', + 'swiftshader_revision': 'eba396cc66d3d3d64859b769eb63a359b2d8c065', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -180,7 +180,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '067afa275dcb4b3c6eca979ea5e3fe75073c4080', + 'nacl_revision': '6abc006f6760ec49350cd45e8bccbff4809725ac', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -252,7 +252,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': 'e8c2d95ed45f0b839e7f04c05675921a5f624eff', + 'spv_tools_revision': '7ce37d66a86d5869ed64e996c9ae694cd47796b8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -805,7 +805,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'de64cb214d81c5af372b16e1f51c415f851358f6', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '36589c6fccb25e55bdc289495fcebde2af994840', 'condition': 'checkout_linux', }, @@ -899,7 +899,7 @@ }, 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'e06c7e9a515b716c731bda13f507546f107775d1', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '0527c9db8148ce37442fa4a9c99a2a23ad50b0b7', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1172,7 +1172,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '094a5527955836c210acb17ebffa744233963159', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'fb43b375bc15b88f115841f7ce336efa61df1ce6', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1343,7 +1343,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '688fbfe33779392aa210d67d4aa12cb012f112c2', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '59e875ce18bb24aa6d1ec5cdf128d7ef244fa37a', + Var('webrtc_git') + '/src.git' + '@' + 'e9d2b4efdd5dddaa3a476c0ac2a9cf9125b39929', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1384,7 +1384,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@40c6e15502942f8074065e6174ff40d8889bd439', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fa0935506a93a988c095b6e860c3cb9c3939e5da', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/MonochromeLibraryPreloader.java b/android_webview/glue/java/src/com/android/webview/chromium/MonochromeLibraryPreloader.java index 0d0b824..b8e9f3cf 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/MonochromeLibraryPreloader.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/MonochromeLibraryPreloader.java
@@ -4,7 +4,7 @@ package com.android.webview.chromium; -import android.content.Context; +import android.content.pm.ApplicationInfo; import android.webkit.WebViewFactory; import org.chromium.base.library_loader.NativeLibraryPreloader; @@ -14,10 +14,9 @@ * between Chrome and WebView. */ public class MonochromeLibraryPreloader extends NativeLibraryPreloader { - @Override - public int loadLibrary(Context context) { - return WebViewFactory.loadWebViewNativeLibraryFromPackage(context.getPackageName(), - getClass().getClassLoader()); + public int loadLibrary(ApplicationInfo appInfo) { + return WebViewFactory.loadWebViewNativeLibraryFromPackage( + appInfo.packageName, getClass().getClassLoader()); } }
diff --git a/ash/media/media_notification_controller.cc b/ash/media/media_notification_controller.cc index 4f843be2..8ba97a5 100644 --- a/ash/media/media_notification_controller.cc +++ b/ash/media/media_notification_controller.cc
@@ -69,7 +69,8 @@ notifications_.emplace( std::piecewise_construct, std::forward_as_tuple(id), - std::forward_as_tuple(id, std::move(controller), + std::forward_as_tuple(id, session->source_name.value_or(std::string()), + std::move(controller), std::move(session->session_info))); }
diff --git a/ash/media/media_notification_controller_unittest.cc b/ash/media/media_notification_controller_unittest.cc index f1808fd..c9836d7 100644 --- a/ash/media/media_notification_controller_unittest.cc +++ b/ash/media/media_notification_controller_unittest.cc
@@ -13,6 +13,7 @@ #include "ash/test/ash_test_base.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/unguessable_token.h" #include "services/media_session/public/mojom/audio_focus.mojom.h" @@ -72,9 +73,17 @@ return metadata; } + void ExpectHistogramSourceRecorded(MediaNotificationItem::Source source) { + histogram_tester_.ExpectUniqueSample( + MediaNotificationItem::kSourceHistogramName, + static_cast<base::HistogramBase::Sample>(source), 1); + } + private: base::test::ScopedFeatureList scoped_feature_list_; + base::HistogramTester histogram_tester_; + DISALLOW_COPY_AND_ASSIGN(MediaNotificationControllerTest); }; @@ -315,4 +324,84 @@ ExpectNotificationCount(0); } +TEST_F(MediaNotificationControllerTest, RecordHistogramSource_Unknown) { + base::UnguessableToken id = base::UnguessableToken::Create(); + + ExpectNotificationCount(0); + + Shell::Get()->media_notification_controller()->OnFocusGained( + GetRequestStateWithId(id)); + + Shell::Get() + ->media_notification_controller() + ->GetItem(id.ToString()) + ->MediaSessionMetadataChanged(BuildMediaMetadata()); + + ExpectNotificationCount(1); + ExpectHistogramSourceRecorded(MediaNotificationItem::Source::kUnknown); +} + +TEST_F(MediaNotificationControllerTest, RecordHistogramSource_Web) { + base::UnguessableToken id = base::UnguessableToken::Create(); + + ExpectNotificationCount(0); + + media_session::mojom::AudioFocusRequestStatePtr request = + GetRequestStateWithId(id); + request->source_name = "web"; + + Shell::Get()->media_notification_controller()->OnFocusGained( + std::move(request)); + + Shell::Get() + ->media_notification_controller() + ->GetItem(id.ToString()) + ->MediaSessionMetadataChanged(BuildMediaMetadata()); + + ExpectNotificationCount(1); + ExpectHistogramSourceRecorded(MediaNotificationItem::Source::kWeb); +} + +TEST_F(MediaNotificationControllerTest, RecordHistogramSource_Assistant) { + base::UnguessableToken id = base::UnguessableToken::Create(); + + ExpectNotificationCount(0); + + media_session::mojom::AudioFocusRequestStatePtr request = + GetRequestStateWithId(id); + request->source_name = "assistant"; + + Shell::Get()->media_notification_controller()->OnFocusGained( + std::move(request)); + + Shell::Get() + ->media_notification_controller() + ->GetItem(id.ToString()) + ->MediaSessionMetadataChanged(BuildMediaMetadata()); + + ExpectNotificationCount(1); + ExpectHistogramSourceRecorded(MediaNotificationItem::Source::kAssistant); +} + +TEST_F(MediaNotificationControllerTest, RecordHistogramSource_Arc) { + base::UnguessableToken id = base::UnguessableToken::Create(); + + ExpectNotificationCount(0); + + media_session::mojom::AudioFocusRequestStatePtr request = + GetRequestStateWithId(id); + request->source_name = "arc"; + + Shell::Get()->media_notification_controller()->OnFocusGained( + std::move(request)); + + Shell::Get() + ->media_notification_controller() + ->GetItem(id.ToString()) + ->MediaSessionMetadataChanged(BuildMediaMetadata()); + + ExpectNotificationCount(1); + ExpectHistogramSourceRecorded(MediaNotificationItem::Source::kArc); +} + } // namespace ash
diff --git a/ash/media/media_notification_item.cc b/ash/media/media_notification_item.cc index 67c796f..ae61958d 100644 --- a/ash/media/media_notification_item.cc +++ b/ash/media/media_notification_item.cc
@@ -31,17 +31,36 @@ constexpr base::TimeDelta kDefaultSeekTime = base::TimeDelta::FromSeconds(media_session::mojom::kDefaultSeekTimeSeconds); +MediaNotificationItem::Source GetSource(const std::string& name) { + if (name == "web") + return MediaNotificationItem::Source::kWeb; + + if (name == "arc") + return MediaNotificationItem::Source::kArc; + + if (name == "assistant") + return MediaNotificationItem::Source::kAssistant; + + return MediaNotificationItem::Source::kUnknown; +} + } // namespace // static +const char MediaNotificationItem::kSourceHistogramName[] = + "Media.Notification.Source"; + +// static const char MediaNotificationItem::kUserActionHistogramName[] = "Media.Notification.UserAction"; MediaNotificationItem::MediaNotificationItem( const std::string& id, + const std::string& source_name, media_session::mojom::MediaControllerPtr controller, media_session::mojom::MediaSessionInfoPtr session_info) : id_(id), + source_(GetSource(source_name)), media_controller_ptr_(std::move(controller)), session_info_(std::move(session_info)) { if (media_controller_ptr_.is_bound()) { @@ -180,6 +199,8 @@ message_center::MessageCenter::Get()->AddNotification( std::move(notification)); + + UMA_HISTOGRAM_ENUMERATION(kSourceHistogramName, source_); } void MediaNotificationItem::HideNotification() {
diff --git a/ash/media/media_notification_item.h b/ash/media/media_notification_item.h index 944e2d5..74a73022 100644 --- a/ash/media/media_notification_item.h +++ b/ash/media/media_notification_item.h
@@ -29,7 +29,21 @@ // The name of the histogram used when recording user actions. static const char kUserActionHistogramName[]; + // The name of the histogram used when recording the source. + static const char kSourceHistogramName[]; + + // The source of the media session. This is used in metrics so new values must + // only be added to the end. + enum class Source { + kUnknown, + kWeb, + kAssistant, + kArc, + kMaxValue = kArc, + }; + MediaNotificationItem(const std::string& id, + const std::string& source_name, media_session::mojom::MediaControllerPtr controller, media_session::mojom::MediaSessionInfoPtr session_info); ~MediaNotificationItem() override; @@ -74,6 +88,9 @@ // media session. const std::string id_; + // The source of the media session (e.g. arc, web). + const Source source_; + media_session::mojom::MediaControllerPtr media_controller_ptr_; media_session::mojom::MediaSessionInfoPtr session_info_;
diff --git a/ash/public/interfaces/shell_test_api.test-mojom b/ash/public/interfaces/shell_test_api.test-mojom index 4b17732..4dbd33d1 100644 --- a/ash/public/interfaces/shell_test_api.test-mojom +++ b/ash/public/interfaces/shell_test_api.test-mojom
@@ -27,6 +27,9 @@ // Enters or exits overview mode. ToggleOverviewMode() => (); + // Returns true if it is in overview selecting mode. + IsOverviewSelecting() => (bool is_selecting); + // Used to emulate display change when run in a desktop environment instead // of on a device. AddRemoveDisplay(); @@ -38,4 +41,8 @@ // longer holding pointer events. See // |aura::WindowTreeHost::holding_pointer_moves_| for details. WaitForNoPointerHoldLock() => (); + + // Runs the callback when the compositor of the primary display has presented + // a frame on screen. + WaitForNextFrame() => (); };
diff --git a/ash/public/interfaces/user_info.mojom b/ash/public/interfaces/user_info.mojom index c40bb51..e74b5b3 100644 --- a/ash/public/interfaces/user_info.mojom +++ b/ash/public/interfaces/user_info.mojom
@@ -64,4 +64,6 @@ bool is_device_owner; // True if the user has a gaia account. bool has_gaia_account; + // True if user is managed. + bool is_managed; };
diff --git a/ash/session/session_controller.cc b/ash/session/session_controller.cc index efa4f2f..3f0d8daf 100644 --- a/ash/session/session_controller.cc +++ b/ash/session/session_controller.cc
@@ -235,6 +235,13 @@ return GetUserSession(0)->user_info->is_new_profile; } +bool SessionController::IsUserManaged() const { + if (!IsActiveUserSessionStarted()) + return false; + + return GetUserSession(0)->user_info->is_managed; +} + void SessionController::LockScreen() { if (client_) client_->RequestLockScreen();
diff --git a/ash/session/session_controller.h b/ash/session/session_controller.h index e530938f..5d7009b 100644 --- a/ash/session/session_controller.h +++ b/ash/session/session_controller.h
@@ -135,6 +135,12 @@ // device (i.e. first time login on the device). bool IsUserFirstLogin() const; + // Returns true if the current user is managed, and false otherwise. + // For public sessions, kiosk app and arc kiosk app accounts returns true. + // NOTE: Returns false if there is no profile (example: login screen in + // ChromeOS). + bool IsUserManaged() const; + // Locks the screen. The locking happens asynchronously. void LockScreen();
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc index be6517e..3204e01 100644 --- a/ash/shell_test_api.cc +++ b/ash/shell_test_api.cc
@@ -169,6 +169,10 @@ std::move(cb).Run(); } +void ShellTestApi::IsOverviewSelecting(IsOverviewSelectingCallback callback) { + std::move(callback).Run(shell_->overview_controller()->IsSelecting()); +} + void ShellTestApi::AddRemoveDisplay() { shell_->display_manager()->AddRemoveDisplay(); } @@ -186,4 +190,16 @@ std::move(callback).Run(); } +void ShellTestApi::WaitForNextFrame(WaitForNextFrameCallback callback) { + Shell::GetPrimaryRootWindowController() + ->GetHost() + ->compositor() + ->RequestPresentationTimeForNextFrame(base::BindOnce( + [](WaitForNextFrameCallback callback, + const gfx::PresentationFeedback& feedback) { + std::move(callback).Run(); + }, + std::move(callback))); +} + } // namespace ash
diff --git a/ash/shell_test_api.h b/ash/shell_test_api.h index 93e62afa..c883c4d 100644 --- a/ash/shell_test_api.h +++ b/ash/shell_test_api.h
@@ -61,10 +61,12 @@ SnapWindowInSplitViewCallback cb) override; void ToggleFullscreen(ToggleFullscreenCallback cb) override; void ToggleOverviewMode(ToggleOverviewModeCallback cb) override; + void IsOverviewSelecting(IsOverviewSelectingCallback callback) override; void AddRemoveDisplay() override; void SetMinFlingVelocity(float velocity) override; void WaitForNoPointerHoldLock( WaitForNoPointerHoldLockCallback callback) override; + void WaitForNextFrame(WaitForNextFrameCallback callback) override; private: Shell* shell_; // not owned
diff --git a/ash/system/unified/unified_system_info_view.cc b/ash/system/unified/unified_system_info_view.cc index 5d750ad..efe5893 100644 --- a/ash/system/unified/unified_system_info_view.cc +++ b/ash/system/unified/unified_system_info_view.cc
@@ -7,6 +7,7 @@ #include "ash/public/cpp/ash_view_ids.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/session/session_controller.h" +#include "ash/session/session_observer.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/enterprise/enterprise_domain_observer.h" @@ -265,7 +266,8 @@ // by observing EnterpriseDomainModel. class EnterpriseManagedView : public ManagedStateView, public views::ButtonListener, - public EnterpriseDomainObserver { + public EnterpriseDomainObserver, + public SessionObserver { public: explicit EnterpriseManagedView(UnifiedSystemTrayController* controller); ~EnterpriseManagedView() override; @@ -276,6 +278,9 @@ // EnterpriseDomainObserver: void OnEnterpriseDomainChanged() override; + // SessionObserver: + void OnLoginStatusChanged(LoginStatus status) override; + private: void Update(); @@ -293,11 +298,13 @@ DCHECK(Shell::Get()); set_id(VIEW_ID_TRAY_ENTERPRISE); Shell::Get()->system_tray_model()->enterprise_domain()->AddObserver(this); + Shell::Get()->session_controller()->AddObserver(this); Update(); } EnterpriseManagedView::~EnterpriseManagedView() { Shell::Get()->system_tray_model()->enterprise_domain()->RemoveObserver(this); + Shell::Get()->session_controller()->RemoveObserver(this); } void EnterpriseManagedView::ButtonPressed(views::Button* sender, @@ -309,10 +316,16 @@ Update(); } +void EnterpriseManagedView::OnLoginStatusChanged(LoginStatus status) { + Update(); +} + void EnterpriseManagedView::Update() { EnterpriseDomainModel* model = Shell::Get()->system_tray_model()->enterprise_domain(); - SetVisible(model->active_directory_managed() || + SessionController* session_controller = Shell::Get()->session_controller(); + SetVisible(session_controller->IsUserManaged() || + model->active_directory_managed() || !model->enterprise_display_domain().empty()); if (model->active_directory_managed()) {
diff --git a/base/BUILD.gn b/base/BUILD.gn index 215417e..fadacd7 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -804,6 +804,7 @@ "task/task_features.cc", "task/task_features.h", "task/task_observer.h", + "task/task_scheduler/can_schedule_sequence_observer.h", "task/task_scheduler/delayed_task_manager.cc", "task/task_scheduler/delayed_task_manager.h", "task/task_scheduler/environment_config.cc", @@ -2580,7 +2581,6 @@ "task/sequence_manager/work_deduplicator_unittest.cc", "task/sequence_manager/work_queue_sets_unittest.cc", "task/sequence_manager/work_queue_unittest.cc", - "task/task_scheduler/can_run_policy_test.h", "task/task_scheduler/delayed_task_manager_unittest.cc", "task/task_scheduler/priority_queue_unittest.cc", "task/task_scheduler/scheduler_lock_unittest.cc",
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index 599428c..398e081 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -8,6 +8,7 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.StrictMode; @@ -117,6 +118,10 @@ // One-way switch becomes true when the libraries are loaded. private boolean mLoaded; + // Similar to |mLoaded| but is limited case of being loaded in app zygote. + // This is exposed to clients. + private boolean mLoadedByZygote; + // One-way switch becomes true when the Java command line is switched to // native. private boolean mCommandLineSwitched; @@ -184,6 +189,13 @@ private LibraryLoader() {} /** + * Return if library is already loaded successfully by the zygote. + */ + public boolean isLoadedByZygote() { + return mLoadedByZygote; + } + + /** * This method blocks until the library is fully loaded and initialized. * * @param processType the process the shared library is loaded in. @@ -194,7 +206,8 @@ // Already initialized, nothing to do. return; } - loadAlreadyLocked(ContextUtils.getApplicationContext()); + loadAlreadyLocked(ContextUtils.getApplicationContext().getApplicationInfo(), + false /* inZygote */); initializeAlreadyLocked(processType); } } @@ -215,17 +228,17 @@ public void preloadNowOverrideApplicationContext(Context appContext) { synchronized (mLock) { if (!useCrazyLinker()) { - preloadAlreadyLocked(appContext); + preloadAlreadyLocked(appContext.getApplicationInfo()); } } } - private void preloadAlreadyLocked(Context appContext) { + private void preloadAlreadyLocked(ApplicationInfo appInfo) { try (TraceEvent te = TraceEvent.scoped("LibraryLoader.preloadAlreadyLocked")) { // Preloader uses system linker, we shouldn't preload if Chromium linker is used. assert !useCrazyLinker(); if (mLibraryPreloader != null && !mLibraryPreloaderCalled) { - mLibraryPreloaderStatus = mLibraryPreloader.loadLibrary(appContext); + mLibraryPreloaderStatus = mLibraryPreloader.loadLibrary(appInfo); mLibraryPreloaderCalled = true; } } @@ -264,7 +277,15 @@ if (mLoaded && appContext != ContextUtils.getApplicationContext()) { throw new IllegalStateException("Attempt to load again from alternate context."); } - loadAlreadyLocked(appContext); + loadAlreadyLocked(appContext.getApplicationInfo(), false /* inZygote */); + } + } + + public void loadNowInZygote(ApplicationInfo appInfo) throws ProcessInitException { + synchronized (mLock) { + assert !mLoaded; + loadAlreadyLocked(appInfo, true /* inZygote */); + mLoadedByZygote = true; } } @@ -422,31 +443,31 @@ // Experience shows that on some devices, the system sometimes fails to extract native libraries // at installation or update time from the APK. This function will extract the library and // return the extracted file path. - static String getExtractedLibraryPath(Context appContext, String libName) { + static String getExtractedLibraryPath(ApplicationInfo appInfo, String libName) { assert PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION; Log.w(TAG, "Failed to load libName %s, attempting fallback extraction then trying again", libName); String libraryEntry = LibraryLoader.makeLibraryPathInZipFile(libName, false, false); - return extractFileIfStale(appContext, libraryEntry, makeLibraryDirAndSetPermission()); + return extractFileIfStale(appInfo, libraryEntry, makeLibraryDirAndSetPermission()); } // Invoke either Linker.loadLibrary(...), System.loadLibrary(...) or System.load(...), // triggering JNI_OnLoad in native code. // TODO(crbug.com/635567): Fix this properly. @SuppressLint({"DefaultLocale", "UnsafeDynamicallyLoadedCode"}) - private void loadAlreadyLocked(Context appContext) throws ProcessInitException { + private void loadAlreadyLocked(ApplicationInfo appInfo, boolean inZygote) + throws ProcessInitException { try (TraceEvent te = TraceEvent.scoped("LibraryLoader.loadAlreadyLocked")) { if (!mLoaded) { assert !mInitialized; long startTime = SystemClock.uptimeMillis(); - if (useCrazyLinker()) { + if (useCrazyLinker() && !inZygote) { // Load libraries using the Chromium linker. Linker linker = Linker.getInstance(); - String apkFilePath = - isInZipFile() ? appContext.getApplicationInfo().sourceDir : null; + String apkFilePath = isInZipFile() ? appInfo.sourceDir : null; linker.prepareLibraryLoad(apkFilePath); for (String library : NativeLibraries.LIBRARIES) { @@ -475,7 +496,7 @@ if (!isInZipFile() && PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION) { loadLibraryWithCustomLinkerAlreadyLocked( - linker, null, getExtractedLibraryPath(appContext, library)); + linker, null, getExtractedLibraryPath(appInfo, library)); incrementRelinkerCountHitHistogram(); } else { Log.e(TAG, "Unable to load library: " + library); @@ -487,7 +508,7 @@ linker.finishLibraryLoad(); } else { setEnvForNative(); - preloadAlreadyLocked(appContext); + preloadAlreadyLocked(appInfo); // If the libraries are located in the zip file, assert that the device API // level is M or higher. On devices lower than M, the libraries should @@ -504,7 +525,7 @@ } else { // Load directly from the APK. boolean is64Bit = ApiHelperForM.isProcess64Bit(); - String zipFilePath = appContext.getApplicationInfo().sourceDir; + String zipFilePath = appInfo.sourceDir; // In API level 23 and above, it’s possible to open a .so file // directly from the APK of the path form // "my_zip_file.zip!/libs/libstuff.so". See: @@ -744,10 +765,10 @@ // This function manually extract libraries as a fallback. @SuppressLint({"SetWorldReadable"}) private static String extractFileIfStale( - Context appContext, String pathWithinApk, File destDir) { + ApplicationInfo appInfo, String pathWithinApk, File destDir) { assert PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION; - String apkPath = appContext.getApplicationInfo().sourceDir; + String apkPath = appInfo.sourceDir; String fileName = (new File(pathWithinApk)).getName() + BuildInfo.getInstance().extractedFileSuffix; File libraryFile = new File(destDir, fileName);
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java index 0d401ab..68c42ef 100644 --- a/base/android/java/src/org/chromium/base/library_loader/Linker.java +++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -434,7 +434,8 @@ } catch (UnsatisfiedLinkError e) { if (LibraryLoader.PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION) { System.load(LibraryLoader.getExtractedLibraryPath( - ContextUtils.getApplicationContext(), LINKER_JNI_LIBRARY)); + ContextUtils.getApplicationContext().getApplicationInfo(), + LINKER_JNI_LIBRARY)); LibraryLoader.incrementRelinkerCountHitHistogram(); } }
diff --git a/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java b/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java index 6f8008d..56f2cbc 100644 --- a/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java +++ b/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java
@@ -4,7 +4,7 @@ package org.chromium.base.library_loader; -import android.content.Context; +import android.content.pm.ApplicationInfo; /** * This is interface to preload the native library before calling System.loadLibrary. @@ -16,5 +16,5 @@ * only subclass (MonochromeLibraryPreloader) is doing. */ public abstract class NativeLibraryPreloader { - public abstract int loadLibrary(Context context); + public abstract int loadLibrary(ApplicationInfo appInfo); }
diff --git a/base/sequence_checker.h b/base/sequence_checker.h index 81e74a6..e2ce10f 100644 --- a/base/sequence_checker.h +++ b/base/sequence_checker.h
@@ -55,7 +55,7 @@ DCHECK((name).CalledOnValidSequence()) #define DETACH_FROM_SEQUENCE(name) (name).DetachFromSequence() #else // DCHECK_IS_ON() -#if __OBJC__ && defined(OS_IOS) && !__has_feature(objc_cxx_static_assert) +#if __OBJC__ && defined(OS_IOS) && !HAS_FEATURE(objc_cxx_static_assert) // TODO(thakis): Remove this branch once Xcode's clang has clang r356148. #define SEQUENCE_CHECKER(name) #else
diff --git a/base/task/task_scheduler/can_run_policy_test.h b/base/task/task_scheduler/can_run_policy_test.h deleted file mode 100644 index 7a4fe2e..0000000 --- a/base/task/task_scheduler/can_run_policy_test.h +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TASK_TASK_SCHEDULER_CAN_RUN_POLICY_TEST_H_ -#define BASE_TASK_TASK_SCHEDULER_CAN_RUN_POLICY_TEST_H_ - -#include "base/synchronization/atomic_flag.h" -#include "base/synchronization/waitable_event.h" -#include "base/task/task_scheduler/task_tracker.h" -#include "base/task/task_scheduler/test_utils.h" -#include "base/task_runner.h" -#include "base/test/bind_test_util.h" -#include "base/test/test_timeouts.h" -#include "base/threading/platform_thread.h" - -namespace base { -namespace internal { -namespace test { - -// Verify that tasks only run when allowed by the CanRunPolicy. |target| is the -// object on which DidUpdateCanRunPolicy() must be called after updating the -// CanRunPolicy in |task_tracker|. |create_task_runner| is a function that -// receives a TaskPriority and returns a TaskRunner. |task_tracker| is the -// TaskTracker. -template <typename Target, typename CreateTaskRunner> -void TestCanRunPolicyBasic(Target* target, - CreateTaskRunner create_task_runner, - TaskTracker* task_tracker) { - AtomicFlag foreground_can_run; - WaitableEvent foreground_did_run; - AtomicFlag best_effort_can_run; - WaitableEvent best_effort_did_run; - - task_tracker->SetCanRunPolicy(CanRunPolicy::kNone); - target->DidUpdateCanRunPolicy(); - - const auto user_visible_task_runner = - create_task_runner(TaskPriority::USER_VISIBLE); - user_visible_task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() { - EXPECT_TRUE(foreground_can_run.IsSet()); - foreground_did_run.Signal(); - })); - const auto best_effort_task_runner = - create_task_runner(TaskPriority::BEST_EFFORT); - best_effort_task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() { - EXPECT_TRUE(best_effort_can_run.IsSet()); - best_effort_did_run.Signal(); - })); - - PlatformThread::Sleep(TestTimeouts::tiny_timeout()); - - foreground_can_run.Set(); - task_tracker->SetCanRunPolicy(CanRunPolicy::kForegroundOnly); - target->DidUpdateCanRunPolicy(); - foreground_did_run.Wait(); - - PlatformThread::Sleep(TestTimeouts::tiny_timeout()); - - best_effort_can_run.Set(); - task_tracker->SetCanRunPolicy(CanRunPolicy::kAll); - target->DidUpdateCanRunPolicy(); - best_effort_did_run.Wait(); -} - -// Verify that if a task was allowed to run by the CanRunPolicy when it was -// posted, but the CanRunPolicy is updated to disallow it from running before it -// starts running, it doesn't run. |target| is the object on which -// DidUpdateCanRunPolicy() must be called after updating the CanRunPolicy in -// |task_tracker|. |create_task_runner| is a function that receives a -// TaskPriority and returns a *Sequenced*TaskRunner. |task_tracker| is the -// TaskTracker. -template <typename Target, typename CreateTaskRunner> -void TestCanRunPolicyChangedBeforeRun(Target* target, - CreateTaskRunner create_task_runner, - TaskTracker* task_tracker) { - constexpr struct { - // Descriptor for the test case. - const char* descriptor; - // Task priority being tested. - TaskPriority priority; - // Policy that disallows running tasks with |priority|. - CanRunPolicy disallow_policy; - // Policy that allows running tasks with |priority|. - CanRunPolicy allow_policy; - } kTestCases[] = { - {"BestEffort/kNone/kAll", TaskPriority::BEST_EFFORT, CanRunPolicy::kNone, - CanRunPolicy::kAll}, - {"BestEffort/kForegroundOnly/kAll", TaskPriority::BEST_EFFORT, - CanRunPolicy::kForegroundOnly, CanRunPolicy::kAll}, - {"UserVisible/kNone/kForegroundOnly", TaskPriority::USER_VISIBLE, - CanRunPolicy::kNone, CanRunPolicy::kForegroundOnly}, - {"UserVisible/kNone/kAll", TaskPriority::USER_VISIBLE, - CanRunPolicy::kNone, CanRunPolicy::kAll}}; - - for (auto& test_case : kTestCases) { - SCOPED_TRACE(test_case.descriptor); - - WaitableEvent first_task_started; - WaitableEvent first_task_blocked; - AtomicFlag second_task_can_run; - - task_tracker->SetCanRunPolicy(test_case.allow_policy); - target->DidUpdateCanRunPolicy(); - - const auto task_runner = create_task_runner(test_case.priority); - task_runner->PostTask( - FROM_HERE, BindLambdaForTesting([&]() { - first_task_started.Signal(); - test::WaitWithoutBlockingObserver(&first_task_blocked); - })); - task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() { - EXPECT_TRUE(second_task_can_run.IsSet()); - })); - - first_task_started.Wait(); - task_tracker->SetCanRunPolicy(test_case.disallow_policy); - target->DidUpdateCanRunPolicy(); - first_task_blocked.Signal(); - - PlatformThread::Sleep(TestTimeouts::tiny_timeout()); - - second_task_can_run.Set(); - task_tracker->SetCanRunPolicy(test_case.allow_policy); - target->DidUpdateCanRunPolicy(); - task_tracker->FlushForTesting(); - } -} - -} // namespace test -} // namespace internal -} // namespace base - -#endif // BASE_TASK_TASK_SCHEDULER_CAN_RUN_POLICY_TEST_H_
diff --git a/base/task/task_scheduler/can_schedule_sequence_observer.h b/base/task/task_scheduler/can_schedule_sequence_observer.h new file mode 100644 index 0000000..50284a1 --- /dev/null +++ b/base/task/task_scheduler/can_schedule_sequence_observer.h
@@ -0,0 +1,27 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TASK_TASK_SCHEDULER_CAN_SCHEDULE_SEQUENCE_OBSERVER_H_ +#define BASE_TASK_TASK_SCHEDULER_CAN_SCHEDULE_SEQUENCE_OBSERVER_H_ + +#include "base/task/task_scheduler/sequence.h" + +namespace base { +namespace internal { + +class CanScheduleSequenceObserver { + public: + // Called when |sequence| can be scheduled. It is expected that + // TaskTracker::RunNextTask() will be called with |sequence| as argument after + // this is called. + virtual void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) = 0; + + protected: + virtual ~CanScheduleSequenceObserver() = default; +}; + +} // namespace internal +} // namespace base + +#endif // BASE_TASK_TASK_SCHEDULER_CAN_SCHEDULE_SEQUENCE_OBSERVER_H_
diff --git a/base/task/task_scheduler/platform_native_worker_pool.cc b/base/task/task_scheduler/platform_native_worker_pool.cc index a9fd60f6..d32f278b 100644 --- a/base/task/task_scheduler/platform_native_worker_pool.cc +++ b/base/task/task_scheduler/platform_native_worker_pool.cc
@@ -80,7 +80,7 @@ scoped_refptr<Sequence> sequence = GetWork(); DCHECK(sequence); - sequence = task_tracker_->RunAndPopNextTask(std::move(sequence)); + sequence = task_tracker_->RunAndPopNextTask(std::move(sequence), this); if (sequence) { ScopedWorkersExecutor workers_executor(this); @@ -103,11 +103,6 @@ // PriorityQueue after RemoveSequence(). if (priority_queue_.IsEmpty()) return nullptr; - - // Enforce the CanRunPolicy. - const TaskPriority priority = priority_queue_.PeekSortKey().priority(); - if (!task_tracker_->CanRunPriority(priority)) - return nullptr; return priority_queue_.PopSequence(); } @@ -130,10 +125,7 @@ return; // Ensure that there is at least one pending threadpool work per Sequence in // the PriorityQueue. - const size_t desired_num_pending_threadpool_work = - GetNumQueuedCanRunBestEffortSequences() + - GetNumQueuedCanRunForegroundSequences(); - + const size_t desired_num_pending_threadpool_work = priority_queue_.Size(); if (desired_num_pending_threadpool_work > num_pending_threadpool_work_) { static_cast<ScopedWorkersExecutor*>(executor) ->set_num_threadpool_work_to_submit( @@ -157,11 +149,5 @@ // number of worker threads created. } -void PlatformNativeWorkerPool::DidUpdateCanRunPolicy() { - ScopedWorkersExecutor executor(this); - AutoSchedulerLock auto_lock(lock_); - EnsureEnoughWorkersLockRequired(&executor); -} - } // namespace internal } // namespace base
diff --git a/base/task/task_scheduler/platform_native_worker_pool.h b/base/task/task_scheduler/platform_native_worker_pool.h index f82b132..79e680a4 100644 --- a/base/task/task_scheduler/platform_native_worker_pool.h +++ b/base/task/task_scheduler/platform_native_worker_pool.h
@@ -26,7 +26,6 @@ void JoinForTesting() override; size_t GetMaxConcurrentNonBlockedTasksDeprecated() const override; void ReportHeartbeatMetrics() const override; - void DidUpdateCanRunPolicy() override; protected: PlatformNativeWorkerPool(TrackedRef<TaskTracker> task_tracker,
diff --git a/base/task/task_scheduler/scheduler_single_thread_task_runner_manager.cc b/base/task/task_scheduler/scheduler_single_thread_task_runner_manager.cc index b10a2ed..c5cb647 100644 --- a/base/task/task_scheduler/scheduler_single_thread_task_runner_manager.cc +++ b/base/task/task_scheduler/scheduler_single_thread_task_runner_manager.cc
@@ -79,17 +79,22 @@ class SchedulerWorkerDelegate : public SchedulerWorker::Delegate { public: SchedulerWorkerDelegate(const std::string& thread_name, - SchedulerWorker::ThreadLabel thread_label, - TrackedRef<TaskTracker> task_tracker) - : thread_name_(thread_name), - thread_label_(thread_label), - task_tracker_(std::move(task_tracker)) {} + SchedulerWorker::ThreadLabel thread_label) + : thread_name_(thread_name), thread_label_(thread_label) {} void set_worker(SchedulerWorker* worker) { DCHECK(!worker_); worker_ = worker; } + // SchedulerWorker::Delegate: + void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override { + DCHECK(worker_); + ReEnqueueSequence( + SequenceAndTransaction::FromSequence(std::move(sequence))); + worker_->WakeUp(); + } + SchedulerWorker::ThreadLabel GetThreadLabel() const final { return thread_label_; } @@ -101,35 +106,26 @@ scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { AutoSchedulerLock auto_lock(lock_); - auto sequence = GetWorkLockRequired(worker); - if (sequence == nullptr) { - // The worker will sleep after this returns nullptr. - worker_awake_ = false; - } - return sequence; + return priority_queue_.IsEmpty() ? nullptr : priority_queue_.PopSequence(); } void DidRunTask(scoped_refptr<Sequence> sequence) override { if (sequence) { - EnqueueSequence( + ReEnqueueSequence( SequenceAndTransaction::FromSequence(std::move(sequence))); } } - TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } - - void PostTaskNow(scoped_refptr<Sequence> sequence, Task task) { - auto sequence_and_transaction = - SequenceAndTransaction::FromSequence(std::move(sequence)); - const bool task_source_should_be_queued = - sequence_and_transaction.transaction.PushTask(std::move(task)); - if (task_source_should_be_queued) { - bool should_wakeup = EnqueueSequence(std::move(sequence_and_transaction)); - if (should_wakeup) - worker_->WakeUp(); - } + void ReEnqueueSequence(SequenceAndTransaction sequence_and_transaction) { + const SequenceSortKey sequence_sort_key = + sequence_and_transaction.transaction.GetSortKey(); + AutoSchedulerLock auto_lock(lock_); + priority_queue_.Push(std::move(sequence_and_transaction.sequence), + sequence_sort_key); } + TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } + bool RunsTasksInCurrentSequence() { // We check the thread ref instead of the sequence for the benefit of COM // callbacks which may execute without a sequence context. @@ -138,69 +134,22 @@ void OnMainExit(SchedulerWorker* /* worker */) override {} - void DidUpdateCanRunPolicy() { - bool should_wakeup = false; - { - AutoSchedulerLock auto_lock(lock_); - if (!worker_awake_ && CanRunNextSequence()) { - should_wakeup = true; - worker_awake_ = true; - } - } - if (should_wakeup) - worker_->WakeUp(); - } - void EnableFlushPriorityQueueSequencesOnDestroyForTesting() { AutoSchedulerLock auto_lock(lock_); priority_queue_.EnableFlushSequencesOnDestroyForTesting(); } - protected: - scoped_refptr<Sequence> GetWorkLockRequired(SchedulerWorker* worker) - EXCLUSIVE_LOCKS_REQUIRED(lock_) { - if (!CanRunNextSequence()) { - return nullptr; - } - return priority_queue_.PopSequence(); - } - - const TrackedRef<TaskTracker>& task_tracker() { return task_tracker_; } - - SchedulerLock lock_; - bool worker_awake_ GUARDED_BY(lock_) = false; - private: - // Enqueues a sequence in this single-threaded worker's priority queue. - // Returns true iff the worker must wakeup, i.e. sequence is allowed to run - // and the worker was not awake. - bool EnqueueSequence(SequenceAndTransaction sequence_and_transaction) { - AutoSchedulerLock auto_lock(lock_); - priority_queue_.Push(std::move(sequence_and_transaction.sequence), - sequence_and_transaction.transaction.GetSortKey()); - if (!worker_awake_ && CanRunNextSequence()) { - worker_awake_ = true; - return true; - } - return false; - } - - bool CanRunNextSequence() EXCLUSIVE_LOCKS_REQUIRED(lock_) { - return !priority_queue_.IsEmpty() && - task_tracker_->CanRunPriority( - priority_queue_.PeekSortKey().priority()); - } - const std::string thread_name_; const SchedulerWorker::ThreadLabel thread_label_; // The SchedulerWorker that has |this| as a delegate. Must be set before // starting or posting a task to the SchedulerWorker, because it's used in - // OnMainEntry() and PostTaskNow(). + // OnMainEntry() and OnCanScheduleSequence() (called when a sequence held up + // by WillScheduleSequence() in PostTaskNow() can be scheduled). SchedulerWorker* worker_ = nullptr; - const TrackedRef<TaskTracker> task_tracker_; - + SchedulerLock lock_; PriorityQueue priority_queue_ GUARDED_BY(lock_); AtomicThreadRefChecker thread_ref_checker_; @@ -215,9 +164,8 @@ SchedulerWorkerCOMDelegate(const std::string& thread_name, SchedulerWorker::ThreadLabel thread_label, TrackedRef<TaskTracker> task_tracker) - : SchedulerWorkerDelegate(thread_name, - thread_label, - std::move(task_tracker)) {} + : SchedulerWorkerDelegate(thread_name, thread_label), + task_tracker_(std::move(task_tracker)) {} ~SchedulerWorkerCOMDelegate() override { DCHECK(!scoped_com_initializer_); } @@ -237,16 +185,14 @@ // * Both SchedulerWorkerDelegate::GetWork() and the Windows Message Queue // have work: // Process sequences from each source round-robin style. - AutoSchedulerLock auto_lock(lock_); scoped_refptr<Sequence> sequence; if (get_work_first_) { - sequence = SchedulerWorkerDelegate::GetWorkLockRequired(worker); + sequence = SchedulerWorkerDelegate::GetWork(worker); if (sequence) get_work_first_ = false; } if (!sequence) { - AutoSchedulerUnlock auto_unlock(lock_); sequence = GetWorkFromWindowsMessageQueue(); if (sequence) get_work_first_ = true; @@ -257,11 +203,7 @@ // and found there was no work. We don't want to return null immediately // as that could cause the thread to go to sleep while work is waiting via // SchedulerWorkerDelegate::GetWork(). - sequence = SchedulerWorkerDelegate::GetWorkLockRequired(worker); - } - if (sequence == nullptr) { - // The worker will sleep after this returns nullptr. - worker_awake_ = false; + sequence = SchedulerWorkerDelegate::GetWork(worker); } return sequence; } @@ -276,12 +218,8 @@ const DWORD milliseconds_wait = checked_cast<DWORD>( sleep_time.is_max() ? INFINITE : sleep_time.InMilliseconds()); const HANDLE wake_up_event_handle = wake_up_event->handle(); - DWORD reason = MsgWaitForMultipleObjectsEx( - 1, &wake_up_event_handle, milliseconds_wait, QS_ALLINPUT, 0); - if (reason != WAIT_OBJECT_0) { - AutoSchedulerLock auto_lock(lock_); - worker_awake_ = true; - } + MsgWaitForMultipleObjectsEx(1, &wake_up_event_handle, milliseconds_wait, + QS_ALLINPUT, 0); } private: @@ -296,8 +234,8 @@ }, std::move(msg)), TimeDelta()); - if (task_tracker()->WillPostTask( - &pump_message_task, TaskShutdownBehavior::SKIP_ON_SHUTDOWN)) { + if (task_tracker_->WillPostTask(&pump_message_task, + TaskShutdownBehavior::SKIP_ON_SHUTDOWN)) { bool was_empty = message_pump_sequence_->BeginTransaction().PushTask( std::move(pump_message_task)); DCHECK(was_empty) << "GetWorkFromWindowsMessageQueue() does not expect " @@ -313,6 +251,7 @@ MakeRefCounted<Sequence>(TaskTraits(MayBlock()), nullptr, TaskSourceExecutionMode::kParallel); + const TrackedRef<TaskTracker> task_tracker_; std::unique_ptr<win::ScopedCOMInitializer> scoped_com_initializer_; DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerCOMDelegate); @@ -358,15 +297,11 @@ } if (task.delayed_run_time.is_null()) { - GetDelegate()->PostTaskNow(sequence_, std::move(task)); + PostTaskNow(std::move(task)); } else { - // Unretained(GetDelegate()) is safe because this TaskRunner and its - // worker are kept alive as long as there are pending Tasks. outer_->delayed_task_manager_->AddDelayedTask( std::move(task), - BindOnce(&SchedulerWorkerDelegate::PostTaskNow, - Unretained(GetDelegate()), sequence_), - this); + BindOnce(&SchedulerSingleThreadTaskRunner::PostTaskNow, this), this); } return true; } @@ -410,6 +345,20 @@ } } + void PostTaskNow(Task task) { + auto sequence_and_transaction = + SequenceAndTransaction::FromSequence(sequence_); + const bool task_source_should_be_queued = + sequence_and_transaction.transaction.PushTask(std::move(task)); + if (task_source_should_be_queued) { + if (outer_->task_tracker_->WillScheduleSequence( + sequence_and_transaction.transaction, GetDelegate())) { + GetDelegate()->ReEnqueueSequence(std::move(sequence_and_transaction)); + worker_->WakeUp(); + } + } + } + SchedulerWorkerDelegate* GetDelegate() const { return static_cast<SchedulerWorkerDelegate*>(worker_->delegate()); } @@ -469,27 +418,8 @@ // SchedulerSingleThreadTaskRunner::PostTaskNow(). As a result, it's // unnecessary to call WakeUp() for each worker (in fact, an extraneous // WakeUp() would be racy and wrong - see https://crbug.com/862582). - for (scoped_refptr<SchedulerWorker> worker : workers_to_start) { + for (scoped_refptr<SchedulerWorker> worker : workers_to_start) worker->Start(scheduler_worker_observer_); - } -} - -void SchedulerSingleThreadTaskRunnerManager::DidUpdateCanRunPolicy() { - decltype(workers_) workers_to_update; - - { - AutoSchedulerLock auto_lock(lock_); - if (!started_) - return; - workers_to_update = workers_; - } - // Any worker created after the lock is released will see the latest - // CanRunPolicy if tasks are posted to it and thus doesn't need a - // DidUpdateCanRunPolicy() notification. - for (auto& worker : workers_to_update) { - static_cast<SchedulerWorkerDelegate*>(worker->delegate()) - ->DidUpdateCanRunPolicy(); - } } scoped_refptr<SingleThreadTaskRunner> @@ -605,8 +535,7 @@ StringPrintf("TaskSchedulerSingleThread%s%d", name.c_str(), id), thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED ? SchedulerWorker::ThreadLabel::DEDICATED - : SchedulerWorker::ThreadLabel::SHARED, - task_tracker_); + : SchedulerWorker::ThreadLabel::SHARED); } #if defined(OS_WIN)
diff --git a/base/task/task_scheduler/scheduler_single_thread_task_runner_manager.h b/base/task/task_scheduler/scheduler_single_thread_task_runner_manager.h index 9d33d3d..220dde2ce 100644 --- a/base/task/task_scheduler/scheduler_single_thread_task_runner_manager.h +++ b/base/task/task_scheduler/scheduler_single_thread_task_runner_manager.h
@@ -63,10 +63,6 @@ // JoinForTesting() has returned (must never be destroyed in production). void Start(SchedulerWorkerObserver* scheduler_worker_observer = nullptr); - // Wakes up workers as appropriate for the new CanRunPolicy policy. Must be - // called after an update to CanRunPolicy in TaskTracker. - void DidUpdateCanRunPolicy(); - // Creates a SingleThreadTaskRunner which runs tasks with |traits| on a thread // named "TaskSchedulerSingleThread[Shared]" + // kEnvironmentParams[GetEnvironmentIndexForTraits(traits)].name_suffix +
diff --git a/base/task/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc b/base/task/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc index 65b50ef7..f33be2fb 100644 --- a/base/task/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc +++ b/base/task/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
@@ -11,14 +11,11 @@ #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/task/post_task.h" -#include "base/task/task_scheduler/can_run_policy_test.h" #include "base/task/task_scheduler/delayed_task_manager.h" #include "base/task/task_scheduler/environment_config.h" #include "base/task/task_scheduler/scheduler_worker_pool_params.h" #include "base/task/task_scheduler/task_tracker.h" -#include "base/task/task_scheduler/test_utils.h" #include "base/task/task_traits.h" -#include "base/test/bind_test_util.h" #include "base/test/gtest_util.h" #include "base/test/test_timeouts.h" #include "base/threading/platform_thread.h" @@ -41,7 +38,7 @@ namespace { class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test { - protected: + public: TaskSchedulerSingleThreadTaskRunnerManagerTest() : service_thread_("TaskSchedulerServiceThread") {} @@ -60,6 +57,7 @@ service_thread_.Stop(); } + protected: virtual void StartSingleThreadTaskRunnerManagerFromSetUp() { single_thread_task_runner_manager_->Start(); } @@ -118,7 +116,7 @@ task_runner_2->PostTask(FROM_HERE, BindOnce(&CaptureThreadRef, &thread_ref_2)); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); ASSERT_FALSE(thread_ref_1.is_null()); ASSERT_FALSE(thread_ref_2.is_null()); @@ -144,7 +142,7 @@ task_runner_2->PostTask(FROM_HERE, BindOnce(&CaptureThreadRef, &thread_ref_2)); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); ASSERT_FALSE(thread_ref_1.is_null()); ASSERT_FALSE(thread_ref_2.is_null()); @@ -187,7 +185,7 @@ }, task_runner_1, task_runner_2)); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); } TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, @@ -232,7 +230,7 @@ ->PostTask(FROM_HERE, DoNothing()); // Shutdown should not hang even though the first task hasn't finished. - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); // Let the first task finish. task_can_continue.Signal(); @@ -250,12 +248,6 @@ public: TaskSchedulerSingleThreadTaskRunnerManagerCommonTest() = default; - scoped_refptr<SingleThreadTaskRunner> CreateTaskRunner( - TaskTraits traits = TaskTraits()) { - return single_thread_task_runner_manager_ - ->CreateSingleThreadTaskRunnerWithTraits(traits, GetParam()); - } - private: DISALLOW_COPY_AND_ASSIGN( TaskSchedulerSingleThreadTaskRunnerManagerCommonTest); @@ -269,9 +261,13 @@ // Shutting down can cause priorities to get raised. This means we have to use // events to determine when a task is run. scoped_refptr<SingleThreadTaskRunner> task_runner_background = - CreateTaskRunner({TaskPriority::BEST_EFFORT}); + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits({TaskPriority::BEST_EFFORT}, + GetParam()); scoped_refptr<SingleThreadTaskRunner> task_runner_normal = - CreateTaskRunner({TaskPriority::USER_VISIBLE}); + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits({TaskPriority::USER_VISIBLE}, + GetParam()); ThreadPriority thread_priority_background; task_runner_background->PostTask( @@ -303,7 +299,8 @@ constexpr TaskTraits foo_traits = {TaskPriority::BEST_EFFORT, TaskShutdownBehavior::BLOCK_SHUTDOWN}; scoped_refptr<SingleThreadTaskRunner> foo_task_runner = - CreateTaskRunner(foo_traits); + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits(foo_traits, GetParam()); std::string foo_captured_name; foo_task_runner->PostTask(FROM_HERE, BindOnce(&CaptureThreadName, &foo_captured_name)); @@ -320,7 +317,7 @@ user_blocking_task_runner->PostTask( FROM_HERE, BindOnce(&CaptureThreadName, &user_blocking_captured_name)); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); EXPECT_NE(std::string::npos, foo_captured_name.find( @@ -343,8 +340,10 @@ TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, PostTaskAfterShutdown) { - auto task_runner = CreateTaskRunner(); - test::ShutdownTaskTracker(&task_tracker_); + auto task_runner = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits(), GetParam()); + task_tracker_.Shutdown(); EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); } @@ -354,7 +353,9 @@ WaitableEvent task_ran(WaitableEvent::ResetPolicy::AUTOMATIC, WaitableEvent::InitialState::NOT_SIGNALED); - auto task_runner = CreateTaskRunner(); + auto task_runner = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits(), GetParam()); // Wait until the task runner is up and running to make sure the test below is // solely timing the delayed task, not bringing up a physical thread. @@ -383,30 +384,15 @@ // but doesn't crash. TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, PostTaskAfterDestroy) { - auto task_runner = CreateTaskRunner(); + auto task_runner = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits(), GetParam()); EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing())); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); TearDownSingleThreadTaskRunnerManager(); EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); } -// Verify that tasks only run when allowed by the CanRunPolicy. -TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, - CanRunPolicyBasic) { - test::TestCanRunPolicyBasic( - single_thread_task_runner_manager_.get(), - [this](TaskPriority priority) { return CreateTaskRunner({priority}); }, - &task_tracker_); -} - -TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, - CanRunPolicyUpdatedBeforeRun) { - test::TestCanRunPolicyChangedBeforeRun( - single_thread_task_runner_manager_.get(), - [this](TaskPriority priority) { return CreateTaskRunner({priority}); }, - &task_tracker_); -} - INSTANTIATE_TEST_SUITE_P( AllModes, TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, @@ -523,7 +509,7 @@ com_task_runner->PostTask(FROM_HERE, BindOnce(&win::AssertComApartmentType, win::ComApartmentType::STA)); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); } TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTASameThreadUsed) { @@ -543,7 +529,7 @@ task_runner_2->PostTask(FROM_HERE, BindOnce(&CaptureThreadRef, &thread_ref_2)); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); ASSERT_FALSE(thread_ref_1.is_null()); ASSERT_FALSE(thread_ref_2.is_null()); @@ -621,7 +607,7 @@ com_task_runner->PostTask( FROM_HERE, BindOnce([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd)); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); } #endif // defined(OS_WIN)
diff --git a/base/task/task_scheduler/scheduler_worker.cc b/base/task/task_scheduler/scheduler_worker.cc index deb098b8..c8d951c3 100644 --- a/base/task/task_scheduler/scheduler_worker.cc +++ b/base/task/task_scheduler/scheduler_worker.cc
@@ -337,7 +337,8 @@ continue; } - sequence = task_tracker_->RunAndPopNextTask(std::move(sequence)); + sequence = + task_tracker_->RunAndPopNextTask(std::move(sequence), delegate_.get()); delegate_->DidRunTask(std::move(sequence));
diff --git a/base/task/task_scheduler/scheduler_worker.h b/base/task/task_scheduler/scheduler_worker.h index 37f4232d..88d1608 100644 --- a/base/task/task_scheduler/scheduler_worker.h +++ b/base/task/task_scheduler/scheduler_worker.h
@@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/synchronization/atomic_flag.h" #include "base/synchronization/waitable_event.h" +#include "base/task/task_scheduler/can_schedule_sequence_observer.h" #include "base/task/task_scheduler/scheduler_lock.h" #include "base/task/task_scheduler/scheduler_worker_params.h" #include "base/task/task_scheduler/sequence.h" @@ -60,11 +61,12 @@ #endif // defined(OS_WIN) }; - // Delegate interface for SchedulerWorker. All methods are called from the - // thread managed by the SchedulerWorker instance. - class BASE_EXPORT Delegate { + // Delegate interface for SchedulerWorker. All methods except + // OnCanScheduleSequence() (inherited from CanScheduleSequenceObserver) are + // called from the thread managed by the SchedulerWorker instance. + class BASE_EXPORT Delegate : public CanScheduleSequenceObserver { public: - virtual ~Delegate() = default; + ~Delegate() override = default; // Returns the ThreadLabel the Delegate wants its SchedulerWorkers' stacks // to be labeled with.
diff --git a/base/task/task_scheduler/scheduler_worker_pool.cc b/base/task/task_scheduler/scheduler_worker_pool.cc index 0adb6d1..14e5e36 100644 --- a/base/task/task_scheduler/scheduler_worker_pool.cc +++ b/base/task/task_scheduler/scheduler_worker_pool.cc
@@ -73,6 +73,17 @@ return GetCurrentWorkerPool() == this; } +void SchedulerWorkerPool::OnCanScheduleSequence( + scoped_refptr<Sequence> sequence) { + if (replacement_pool_) { + replacement_pool_->OnCanScheduleSequence(std::move(sequence)); + return; + } + + PushSequenceAndWakeUpWorkers( + SequenceAndTransaction::FromSequence(std::move(sequence))); +} + void SchedulerWorkerPool::PostTaskWithSequenceNow( Task task, SequenceAndTransaction sequence_and_transaction) { @@ -85,31 +96,14 @@ const bool task_source_should_be_queued = sequence_and_transaction.transaction.PushTask(std::move(task)); if (task_source_should_be_queued) { - PushSequenceAndWakeUpWorkers(std::move(sequence_and_transaction)); + // Try to schedule the Sequence locked by |sequence_transaction|. + if (task_tracker_->WillScheduleSequence( + sequence_and_transaction.transaction, this)) { + PushSequenceAndWakeUpWorkers(std::move(sequence_and_transaction)); + } } } -size_t SchedulerWorkerPool::GetNumQueuedCanRunBestEffortSequences() const { - const size_t num_queued = - priority_queue_.GetNumSequencesWithPriority(TaskPriority::BEST_EFFORT); - if (num_queued == 0 || - !task_tracker_->CanRunPriority(TaskPriority::BEST_EFFORT)) { - return 0U; - } - return num_queued; -} - -size_t SchedulerWorkerPool::GetNumQueuedCanRunForegroundSequences() const { - const size_t num_queued = - priority_queue_.GetNumSequencesWithPriority(TaskPriority::USER_VISIBLE) + - priority_queue_.GetNumSequencesWithPriority(TaskPriority::USER_BLOCKING); - if (num_queued == 0 || - !task_tracker_->CanRunPriority(TaskPriority::HIGHEST)) { - return 0U; - } - return num_queued; -} - bool SchedulerWorkerPool::RemoveSequence(scoped_refptr<Sequence> sequence) { AutoSchedulerLock auto_lock(lock_); return priority_queue_.RemoveSequence(std::move(sequence));
diff --git a/base/task/task_scheduler/scheduler_worker_pool.h b/base/task/task_scheduler/scheduler_worker_pool.h index 414e289..9c14fe3 100644 --- a/base/task/task_scheduler/scheduler_worker_pool.h +++ b/base/task/task_scheduler/scheduler_worker_pool.h
@@ -7,6 +7,7 @@ #include "base/base_export.h" #include "base/memory/ref_counted.h" +#include "base/task/task_scheduler/can_schedule_sequence_observer.h" #include "base/task/task_scheduler/priority_queue.h" #include "base/task/task_scheduler/scheduler_lock.h" #include "base/task/task_scheduler/sequence.h" @@ -19,8 +20,8 @@ class TaskTracker; -// Interface and base implementation for a worker pool. -class BASE_EXPORT SchedulerWorkerPool { +// Interface for a worker pool. +class BASE_EXPORT SchedulerWorkerPool : public CanScheduleSequenceObserver { public: // Delegate interface for SchedulerWorkerPool. class BASE_EXPORT Delegate { @@ -43,7 +44,10 @@ #endif // defined(OS_WIN) }; - virtual ~SchedulerWorkerPool(); + ~SchedulerWorkerPool() override; + + // CanScheduleSequenceObserver: + void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) final; // Posts |task| to be executed by this SchedulerWorkerPool as part of // the Sequence in |sequence_and_transaction|. This must only be called after @@ -108,10 +112,6 @@ // Reports relevant metrics per implementation. virtual void ReportHeartbeatMetrics() const = 0; - // Wakes up workers as appropriate for the new CanRunPolicy policy. Must be - // called after an update to CanRunPolicy in TaskTracker. - virtual void DidUpdateCanRunPolicy() = 0; - protected: // Derived classes must implement a ScopedWorkersExecutor that derives from // this to perform operations on workers at the end of a scope, when all locks @@ -156,16 +156,6 @@ const TrackedRef<TaskTracker> task_tracker_; const TrackedRef<Delegate> delegate_; - // Returns the number of queued BEST_EFFORT sequences allowed to run by the - // current CanRunPolicy. - size_t GetNumQueuedCanRunBestEffortSequences() const - EXCLUSIVE_LOCKS_REQUIRED(lock_); - - // Returns the number of queued USER_VISIBLE/USER_BLOCKING sequences allowed - // to run by the current CanRunPolicy. - size_t GetNumQueuedCanRunForegroundSequences() const - EXCLUSIVE_LOCKS_REQUIRED(lock_); - // Ensures that there are enough workers to run queued sequences. |executor| // is forwarded from the one received in PushSequenceAndWakeUpWorkersImpl() virtual void EnsureEnoughWorkersLockRequired(
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl.cc b/base/task/task_scheduler/scheduler_worker_pool_impl.cc index 286753c..1effafe 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task/task_scheduler/scheduler_worker_pool_impl.cc
@@ -210,6 +210,7 @@ ~SchedulerWorkerDelegateImpl() override; // SchedulerWorker::Delegate: + void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override; SchedulerWorker::ThreadLabel GetThreadLabel() const override; void OnMainEntry(const SchedulerWorker* worker) override; scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override; @@ -563,6 +564,11 @@ SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl:: ~SchedulerWorkerDelegateImpl() = default; +void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl:: + OnCanScheduleSequence(scoped_refptr<Sequence> sequence) { + outer_->OnCanScheduleSequence(std::move(sequence)); +} + SchedulerWorker::ThreadLabel SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetThreadLabel() const { return SchedulerWorker::ThreadLabel::POOLED; @@ -628,14 +634,13 @@ return nullptr; } - // Enforce the CanRunPolicy and that no more than |max_best_effort_tasks_| - // BEST_EFFORT tasks run concurrently. - const TaskPriority priority = - outer_->priority_queue_.PeekSortKey().priority(); - if (!outer_->task_tracker_->CanRunPriority(priority) || - (priority == TaskPriority::BEST_EFFORT && - outer_->num_running_best_effort_tasks_ >= - outer_->max_best_effort_tasks_)) { + // Enforce that no more than |max_best_effort_tasks_| BEST_EFFORT tasks run + // concurrently. + const bool next_sequence_is_best_effort = + outer_->priority_queue_.PeekSortKey().priority() == + TaskPriority::BEST_EFFORT; + if (next_sequence_is_best_effort && outer_->num_running_best_effort_tasks_ >= + outer_->max_best_effort_tasks_) { OnWorkerBecomesIdleLockRequired(worker); return nullptr; } @@ -646,7 +651,7 @@ DCHECK(!outer_->idle_workers_stack_.Contains(worker)); // Running BEST_EFFORT task bookkeeping. - if (priority == TaskPriority::BEST_EFFORT) { + if (next_sequence_is_best_effort) { write_worker().is_running_best_effort_task = true; ++outer_->num_running_best_effort_tasks_; } @@ -1034,25 +1039,15 @@ } size_t SchedulerWorkerPoolImpl::GetDesiredNumAwakeWorkersLockRequired() const { - if (!task_tracker_->CanRunPriority(TaskPriority::HIGHEST)) - return 0U; - - // Number of BEST_EFFORT sequences that are running or queued and allowed to - // run by the CanRunPolicy. - const size_t num_running_or_queued_can_run_best_effort_sequences = - num_running_best_effort_tasks_ + GetNumQueuedCanRunBestEffortSequences(); - - // Number of USER_{VISIBLE|BLOCKING} sequences that are running or queued. + const size_t num_running_or_queued_best_effort_sequences = + num_running_best_effort_tasks_ + + priority_queue_.GetNumSequencesWithPriority(TaskPriority::BEST_EFFORT); const size_t num_running_or_queued_foreground_sequences = - (num_running_tasks_ - num_running_best_effort_tasks_) + - priority_queue_.GetNumSequencesWithPriority(TaskPriority::USER_VISIBLE) + - priority_queue_.GetNumSequencesWithPriority(TaskPriority::USER_BLOCKING); + num_running_tasks_ + priority_queue_.Size() - + num_running_or_queued_best_effort_sequences; - const size_t workers_for_best_effort_sequences = - std::max(std::min(num_running_or_queued_can_run_best_effort_sequences, - max_best_effort_tasks_), - num_running_best_effort_tasks_); - + const size_t workers_for_best_effort_sequences = std::min( + num_running_or_queued_best_effort_sequences, max_best_effort_tasks_); const size_t workers_for_foreground_sequences = num_running_or_queued_foreground_sequences; @@ -1061,12 +1056,6 @@ max_tasks_, kMaxNumberOfWorkers}); } -void SchedulerWorkerPoolImpl::DidUpdateCanRunPolicy() { - ScopedWorkersExecutor executor(this); - AutoSchedulerLock auto_lock(lock_); - EnsureEnoughWorkersLockRequired(&executor); -} - void SchedulerWorkerPoolImpl::EnsureEnoughWorkersLockRequired( BaseScopedWorkersExecutor* base_executor) { // Don't do anything if the pool isn't started.
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl.h b/base/task/task_scheduler/scheduler_worker_pool_impl.h index 3526d8e..6949e51 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_impl.h +++ b/base/task/task_scheduler/scheduler_worker_pool_impl.h
@@ -91,7 +91,6 @@ void JoinForTesting() override; size_t GetMaxConcurrentNonBlockedTasksDeprecated() const override; void ReportHeartbeatMetrics() const override; - void DidUpdateCanRunPolicy() override; const HistogramBase* num_tasks_before_detach_histogram() const { return num_tasks_before_detach_histogram_;
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc index 93afc77f..d3afa74 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc +++ b/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -1044,9 +1044,9 @@ DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolBlockingTest); }; -// Verify that SaturateWithBlockingTasks() causes max tasks to increase and -// creates a worker if needed. Also verify that UnblockBlockingTasks() decreases -// max tasks after an increase. +// Verify that BlockingScopeEntered() causes max tasks to increase and creates a +// worker if needed. Also verify that BlockingScopeExited() decreases max tasks +// after an increase. TEST_P(TaskSchedulerWorkerPoolBlockingTest, ThreadBlockedUnblocked) { CreateAndStartWorkerPool(); @@ -1066,69 +1066,6 @@ EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks); } -// Verify that flooding the pool with more BEST_EFFORT tasks than -// kMaxBestEffortTasks doesn't prevent USER_VISIBLE tasks from running. -TEST_P(TaskSchedulerWorkerPoolBlockingTest, TooManyBestEffortTasks) { - constexpr size_t kMaxBestEffortTasks = kMaxTasks / 2; - - CreateAndStartWorkerPool(TimeDelta::Max(), kMaxTasks, kMaxBestEffortTasks); - - WaitableEvent threads_continue; - { - WaitableEvent entered_blocking_scope; - RepeatingClosure entered_blocking_scope_barrier = BarrierClosure( - kMaxBestEffortTasks + 1, - BindOnce(&WaitableEvent::Signal, Unretained(&entered_blocking_scope))); - WaitableEvent exit_blocking_scope; - - WaitableEvent threads_running; - RepeatingClosure threads_running_barrier = BarrierClosure( - kMaxBestEffortTasks + 1, - BindOnce(&WaitableEvent::Signal, Unretained(&threads_running))); - - const auto best_effort_task_runner = test::CreateTaskRunnerWithTraits( - {TaskPriority::BEST_EFFORT, MayBlock()}, - &mock_scheduler_task_runner_delegate_); - for (size_t i = 0; i < kMaxBestEffortTasks + 1; ++i) { - best_effort_task_runner->PostTask( - FROM_HERE, BindLambdaForTesting([&]() { - { - NestedScopedBlockingCall scoped_blocking_call(GetParam()); - entered_blocking_scope_barrier.Run(); - test::WaitWithoutBlockingObserver(&exit_blocking_scope); - } - threads_running_barrier.Run(); - test::WaitWithoutBlockingObserver(&threads_continue); - })); - } - entered_blocking_scope.Wait(); - exit_blocking_scope.Signal(); - threads_running.Wait(); - } - - // At this point, kMaxBestEffortTasks + 1 threads are running (plus - // potentially the idle thread), but max_task and max_best_effort_task are - // back to normal. - EXPECT_GE(worker_pool_->NumberOfWorkersForTesting(), kMaxBestEffortTasks + 1); - EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(), kMaxBestEffortTasks + 2); - EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks); - - WaitableEvent threads_running; - task_runner_->PostTask(FROM_HERE, BindLambdaForTesting([&]() { - threads_running.Signal(); - test::WaitWithoutBlockingObserver(&threads_continue); - })); - - // This should not block forever. - threads_running.Wait(); - - EXPECT_GE(worker_pool_->NumberOfWorkersForTesting(), kMaxBestEffortTasks + 2); - EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(), kMaxBestEffortTasks + 3); - threads_continue.Signal(); - - task_tracker_.FlushForTesting(); -} - // Verify that tasks posted in a saturated pool before a ScopedBlockingCall will // execute after ScopedBlockingCall is instantiated. TEST_P(TaskSchedulerWorkerPoolBlockingTest, PostBeforeBlocking) {
diff --git a/base/task/task_scheduler/scheduler_worker_pool_unittest.cc b/base/task/task_scheduler/scheduler_worker_pool_unittest.cc index 25d3db5..c3b236c 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_unittest.cc +++ b/base/task/task_scheduler/scheduler_worker_pool_unittest.cc
@@ -11,7 +11,6 @@ #include "base/bind_helpers.h" #include "base/location.h" #include "base/memory/ref_counted.h" -#include "base/task/task_scheduler/can_run_policy_test.h" #include "base/task/task_scheduler/delayed_task_manager.h" #include "base/task/task_scheduler/scheduler_sequenced_task_runner.h" #include "base/task/task_scheduler/scheduler_worker_pool_impl.h" @@ -167,13 +166,6 @@ } } - scoped_refptr<TaskRunner> CreateTaskRunner( - const TaskTraits& traits = TaskTraits()) { - return test::CreateTaskRunnerWithExecutionMode( - GetParam().execution_mode, &mock_scheduler_task_runner_delegate_, - traits); - } - Thread service_thread_; TaskTracker task_tracker_ = {"Test"}; DelayedTaskManager delayed_task_manager_; @@ -248,8 +240,9 @@ // Verify that a Task can't be posted after shutdown. TEST_P(TaskSchedulerWorkerPoolTest, PostTaskAfterShutdown) { StartWorkerPool(); - auto task_runner = CreateTaskRunner(); - test::ShutdownTaskTracker(&task_tracker_); + auto task_runner = test::CreateTaskRunnerWithExecutionMode( + GetParam().execution_mode, &mock_scheduler_task_runner_delegate_); + task_tracker_.Shutdown(); EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); } @@ -257,9 +250,10 @@ // crash. TEST_P(TaskSchedulerWorkerPoolTest, PostAfterDestroy) { StartWorkerPool(); - auto task_runner = CreateTaskRunner(); + auto task_runner = test::CreateTaskRunnerWithExecutionMode( + GetParam().execution_mode, &mock_scheduler_task_runner_delegate_); EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing())); - test::ShutdownTaskTracker(&task_tracker_); + task_tracker_.Shutdown(); worker_pool_->JoinForTesting(); worker_pool_.reset(); EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); @@ -271,7 +265,9 @@ WaitableEvent task_ran(WaitableEvent::ResetPolicy::AUTOMATIC, WaitableEvent::InitialState::NOT_SIGNALED); - auto task_runner = CreateTaskRunner(); + + auto task_runner = test::CreateTaskRunnerWithExecutionMode( + GetParam().execution_mode, &mock_scheduler_task_runner_delegate_); // Wait until the task runner is up and running to make sure the test below is // solely timing the delayed task, not bringing up a physical thread. @@ -304,7 +300,8 @@ // complements it to get full coverage of that method. TEST_P(TaskSchedulerWorkerPoolTest, SequencedRunsTasksInCurrentSequence) { StartWorkerPool(); - auto task_runner = CreateTaskRunner(); + auto task_runner = test::CreateTaskRunnerWithExecutionMode( + GetParam().execution_mode, &mock_scheduler_task_runner_delegate_); auto sequenced_task_runner = test::CreateSequencedTaskRunnerWithTraits( TaskTraits(), &mock_scheduler_task_runner_delegate_); @@ -326,7 +323,9 @@ WaitableEvent task_1_running; WaitableEvent task_2_running; - auto task_runner = CreateTaskRunner(); + scoped_refptr<TaskRunner> task_runner = test::CreateTaskRunnerWithTraits( + {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_); + task_runner->PostTask( FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_1_running))); task_runner->PostTask( @@ -347,27 +346,6 @@ task_tracker_.FlushForTesting(); } -// Verify that tasks only run when allowed by the CanRunPolicy. -TEST_P(TaskSchedulerWorkerPoolTest, CanRunPolicyBasic) { - StartWorkerPool(); - test::TestCanRunPolicyBasic( - worker_pool_.get(), - [this](TaskPriority priority) { return CreateTaskRunner({priority}); }, - &task_tracker_); -} - -TEST_P(TaskSchedulerWorkerPoolTest, CanRunPolicyUpdatedBeforeRun) { - StartWorkerPool(); - // This test only works with SequencedTaskRunner become it assumes - // ordered execution of 2 posted tasks. - if (GetParam().execution_mode != test::ExecutionMode::SEQUENCED) - return; - test::TestCanRunPolicyChangedBeforeRun( - worker_pool_.get(), - [this](TaskPriority priority) { return CreateTaskRunner({priority}); }, - &task_tracker_); -} - // Verify that the maximum number of BEST_EFFORT tasks that can run concurrently // in a pool does not affect Sequences with a priority that was increased from // BEST_EFFORT to USER_BLOCKING.
diff --git a/base/task/task_scheduler/scheduler_worker_stack_unittest.cc b/base/task/task_scheduler/scheduler_worker_stack_unittest.cc index f94d2a7..f78243b 100644 --- a/base/task/task_scheduler/scheduler_worker_stack_unittest.cc +++ b/base/task/task_scheduler/scheduler_worker_stack_unittest.cc
@@ -21,6 +21,9 @@ class MockSchedulerWorkerDelegate : public SchedulerWorker::Delegate { public: + void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override { + ADD_FAILURE() << "Unexpected call to OnCanScheduleSequence()."; + } SchedulerWorker::ThreadLabel GetThreadLabel() const override { return SchedulerWorker::ThreadLabel::DEDICATED; }
diff --git a/base/task/task_scheduler/scheduler_worker_unittest.cc b/base/task/task_scheduler/scheduler_worker_unittest.cc index 9803f81..4e9bac7 100644 --- a/base/task/task_scheduler/scheduler_worker_unittest.cc +++ b/base/task/task_scheduler/scheduler_worker_unittest.cc
@@ -53,6 +53,9 @@ SchedulerWorkerDefaultDelegate() = default; // SchedulerWorker::Delegate: + void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override { + ADD_FAILURE() << "Unexpected call to OnCanScheduleSequence()."; + } SchedulerWorker::ThreadLabel GetThreadLabel() const override { return SchedulerWorker::ThreadLabel::DEDICATED; } @@ -195,6 +198,8 @@ outer_->created_sequences_.push_back(sequence); } + EXPECT_TRUE(outer_->task_tracker_.WillScheduleSequence( + sequence_transaction, nullptr)); return sequence; } @@ -457,7 +462,10 @@ TimeDelta()); EXPECT_TRUE( task_tracker_->WillPostTask(&task, sequence->shutdown_behavior())); - sequence->BeginTransaction().PushTask(std::move(task)); + Sequence::Transaction sequence_transaction(sequence->BeginTransaction()); + sequence_transaction.PushTask(std::move(task)); + EXPECT_TRUE( + task_tracker_->WillScheduleSequence(sequence_transaction, nullptr)); return sequence; } @@ -593,7 +601,7 @@ worker->WakeUp(); controls->WaitForWorkToRun(); - test::ShutdownTaskTracker(&task_tracker); + task_tracker.Shutdown(); worker->Cleanup(); worker = nullptr; controls->UnblockWork(); @@ -737,11 +745,6 @@ TaskTracker task_tracker("Test"); - // Block shutdown to ensure that the worker doesn't exit when StartShutdown() - // is called. - Task task(FROM_HERE, DoNothing(), TimeDelta()); - task_tracker.WillPostTask(&task, TaskShutdownBehavior::BLOCK_SHUTDOWN); - std::unique_ptr<ExpectThreadPriorityDelegate> delegate( new ExpectThreadPriorityDelegate); ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); @@ -758,7 +761,7 @@ // Verify that the thread priority is bumped to NORMAL during shutdown. delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); - task_tracker.StartShutdown(); + task_tracker.SetHasShutdownStartedForTesting(); worker->WakeUp(); delegate_raw->WaitForPriorityVerifiedInGetWork();
diff --git a/base/task/task_scheduler/task_scheduler.cc b/base/task/task_scheduler/task_scheduler.cc index 6075029a7..02c9297 100644 --- a/base/task/task_scheduler/task_scheduler.cc +++ b/base/task/task_scheduler/task_scheduler.cc
@@ -35,12 +35,12 @@ TaskScheduler::ScopedExecutionFence::ScopedExecutionFence() { DCHECK(g_task_scheduler); - g_task_scheduler->SetCanRun(false); + g_task_scheduler->SetExecutionFenceEnabled(true); } TaskScheduler::ScopedExecutionFence::~ScopedExecutionFence() { DCHECK(g_task_scheduler); - g_task_scheduler->SetCanRun(true); + g_task_scheduler->SetExecutionFenceEnabled(false); } #if !defined(OS_NACL)
diff --git a/base/task/task_scheduler/task_scheduler.h b/base/task/task_scheduler/task_scheduler.h index 02bad08..185e8536 100644 --- a/base/task/task_scheduler/task_scheduler.h +++ b/base/task/task_scheduler/task_scheduler.h
@@ -209,9 +209,8 @@ virtual int GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated( const TaskTraits& traits) const = 0; - // Sets whether tasks of any / BEST_EFFORT priority are allowed to run. - virtual void SetCanRun(bool can_run) = 0; - virtual void SetCanRunBestEffort(bool can_run) = 0; + // Enables/disables an execution fence that prevents tasks from running. + virtual void SetExecutionFenceEnabled(bool execution_fence_enabled) = 0; }; } // namespace base
diff --git a/base/task/task_scheduler/task_scheduler_impl.cc b/base/task/task_scheduler/task_scheduler_impl.cc index 8b71a26..7acd6f68 100644 --- a/base/task/task_scheduler/task_scheduler_impl.cc +++ b/base/task/task_scheduler/task_scheduler_impl.cc
@@ -8,10 +8,8 @@ #include <string> #include <utility> -#include "base/base_switches.h" #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/command_line.h" #include "base/compiler_specific.h" #include "base/feature_list.h" #include "base/message_loop/message_loop.h" @@ -40,15 +38,6 @@ constexpr EnvironmentParams kBackgroundPoolEnvironmentParams{ "Background", base::ThreadPriority::BACKGROUND}; -// Indicates whether BEST_EFFORT tasks are disabled by a command line switch. -bool HasDisableBestEffortTasksSwitch() { - // The CommandLine might not be initialized if TaskScheduler is initialized - // in a dynamic library which doesn't have access to argc/argv. - return CommandLine::InitializedForCurrentProcess() && - CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableBestEffortTasks); -} - } // namespace TaskSchedulerImpl::TaskSchedulerImpl(StringPiece histogram_label) @@ -65,7 +54,6 @@ Unretained(this)))), single_thread_task_runner_manager_(task_tracker_->GetTrackedRef(), &delayed_task_manager_), - can_run_best_effort_(!HasDisableBestEffortTasksSwitch()), tracked_ref_factory_(this) { DCHECK(!histogram_label.empty()); @@ -103,9 +91,6 @@ void TaskSchedulerImpl::Start( const TaskScheduler::InitParams& init_params, SchedulerWorkerObserver* scheduler_worker_observer) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!started_); - internal::InitializeThreadPrioritiesFeature(); // This is set in Start() and not in the constructor because variation params @@ -187,8 +172,6 @@ service_thread_task_runner, scheduler_worker_observer, worker_environment); } - - started_ = true; } bool TaskSchedulerImpl::PostDelayedTaskWithTraits(const Location& from_here, @@ -252,18 +235,7 @@ } void TaskSchedulerImpl::Shutdown() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - task_tracker_->StartShutdown(); - - // Allow all tasks to run. Done after initiating shutdown to ensure that non- - // BLOCK_SHUTDOWN tasks don't get a chance to run and that BLOCK_SHUTDOWN - // tasks run with a normal thread priority. - can_run_ = true; - can_run_best_effort_ = true; - UpdateCanRunPolicy(); - - task_tracker_->CompleteShutdown(); + task_tracker_->Shutdown(); } void TaskSchedulerImpl::FlushForTesting() { @@ -292,18 +264,8 @@ #endif } -void TaskSchedulerImpl::SetCanRun(bool can_run) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_NE(can_run_, can_run); - can_run_ = can_run; - UpdateCanRunPolicy(); -} - -void TaskSchedulerImpl::SetCanRunBestEffort(bool can_run_best_effort) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_NE(can_run_best_effort_, can_run_best_effort); - can_run_best_effort_ = can_run_best_effort; - UpdateCanRunPolicy(); +void TaskSchedulerImpl::SetExecutionFenceEnabled(bool execution_fence_enabled) { + task_tracker_->SetExecutionFenceEnabled(execution_fence_enabled); } bool TaskSchedulerImpl::PostTaskWithSequence(Task task, @@ -406,20 +368,6 @@ return &foreground_pool_.value(); } -void TaskSchedulerImpl::UpdateCanRunPolicy() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - const CanRunPolicy can_run_policy = - can_run_ ? (can_run_best_effort_ ? CanRunPolicy::kAll - : CanRunPolicy::kForegroundOnly) - : CanRunPolicy::kNone; - task_tracker_->SetCanRunPolicy(can_run_policy); - GetForegroundWorkerPool()->DidUpdateCanRunPolicy(); - if (background_pool_) - background_pool_->DidUpdateCanRunPolicy(); - single_thread_task_runner_manager_.DidUpdateCanRunPolicy(); -} - TaskTraits TaskSchedulerImpl::SetUserBlockingPriorityIfNeeded( TaskTraits traits) const { if (all_tasks_user_blocking_.IsSet())
diff --git a/base/task/task_scheduler/task_scheduler_impl.h b/base/task/task_scheduler/task_scheduler_impl.h index ab70eb5..adad3a4 100644 --- a/base/task/task_scheduler/task_scheduler_impl.h +++ b/base/task/task_scheduler/task_scheduler_impl.h
@@ -14,7 +14,6 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/sequence_checker.h" #include "base/strings/string_piece.h" #include "base/synchronization/atomic_flag.h" #include "base/task/single_thread_task_runner_thread_mode.h" @@ -79,8 +78,7 @@ void FlushForTesting() override; void FlushAsyncForTesting(OnceClosure flush_callback) override; void JoinForTesting() override; - void SetCanRun(bool can_run) override; - void SetCanRunBestEffort(bool can_run_best_effort) override; + void SetExecutionFenceEnabled(bool execution_fence_enabled) override; // TaskExecutor: bool PostDelayedTaskWithTraits(const Location& from_here, @@ -104,10 +102,6 @@ const TaskTraits& traits); private: - // Invoked after |can_run_| or |can_run_best_effort_| is updated. Sets the - // CanRunPolicy in TaskTracker and wakes up workers as appropriate. - void UpdateCanRunPolicy(); - // Returns |traits|, with priority set to TaskPriority::USER_BLOCKING if // |all_tasks_user_blocking_| is set. TaskTraits SetUserBlockingPriorityIfNeeded(TaskTraits traits) const; @@ -148,15 +142,6 @@ Optional<SchedulerWorkerPoolImpl> foreground_pool_; Optional<SchedulerWorkerPoolImpl> background_pool_; - // Whether this TaskScheduler was started. Access controlled by - // |sequence_checker_|. - bool started_ = false; - - // Whether starting to run a Task with any/BEST_EFFORT priority is currently - // allowed. Access controlled by |sequence_checker_|. - bool can_run_ = true; - bool can_run_best_effort_; - #if defined(OS_WIN) Optional<PlatformNativeWorkerPoolWin> native_foreground_pool_; #elif defined(OS_MACOSX) @@ -173,9 +158,6 @@ base::win::ComInitCheckHook com_init_check_hook_; #endif - // Asserts that operations occur in sequence with Start(). - SEQUENCE_CHECKER(sequence_checker_); - TrackedRefFactory<SchedulerWorkerPool::Delegate> tracked_ref_factory_; DISALLOW_COPY_AND_ASSIGN(TaskSchedulerImpl);
diff --git a/base/task/task_scheduler/task_scheduler_impl_unittest.cc b/base/task/task_scheduler/task_scheduler_impl_unittest.cc index 7187c196..f5c710ef 100644 --- a/base/task/task_scheduler/task_scheduler_impl_unittest.cc +++ b/base/task/task_scheduler/task_scheduler_impl_unittest.cc
@@ -495,75 +495,6 @@ flush_event.Wait(); } -// Verifies that tasks only run when allowed by SetCanRun(). -TEST_P(TaskSchedulerImplTest, SetCanRun) { - StartTaskScheduler(); - - AtomicFlag can_run; - WaitableEvent did_run; - scheduler_.SetCanRun(false); - - CreateTaskRunnerWithTraitsAndExecutionMode(&scheduler_, GetParam().traits, - GetParam().execution_mode) - ->PostTask(FROM_HERE, BindLambdaForTesting([&]() { - EXPECT_TRUE(can_run.IsSet()); - did_run.Signal(); - })); - - PlatformThread::Sleep(TestTimeouts::tiny_timeout()); - - can_run.Set(); - scheduler_.SetCanRun(true); - did_run.Wait(); -} - -// Verifies that a call to SetCanRun(false) before Start() is honored. -TEST_P(TaskSchedulerImplTest, SetCanRunBeforeStart) { - scheduler_.SetCanRun(false); - StartTaskScheduler(); - - AtomicFlag can_run; - WaitableEvent did_run; - - CreateTaskRunnerWithTraitsAndExecutionMode(&scheduler_, GetParam().traits, - GetParam().execution_mode) - ->PostTask(FROM_HERE, BindLambdaForTesting([&]() { - EXPECT_TRUE(can_run.IsSet()); - did_run.Signal(); - })); - - PlatformThread::Sleep(TestTimeouts::tiny_timeout()); - - can_run.Set(); - scheduler_.SetCanRun(true); - did_run.Wait(); -} - -// Verifies that BEST_EFFORT tasks only run when allowed by -// SetCanRunBestEffort(). -TEST_P(TaskSchedulerImplTest, SetCanRunBestEffort) { - StartTaskScheduler(); - - AtomicFlag can_run; - WaitableEvent did_run; - scheduler_.SetCanRunBestEffort(false); - - CreateTaskRunnerWithTraitsAndExecutionMode(&scheduler_, GetParam().traits, - GetParam().execution_mode) - ->PostTask( - FROM_HERE, BindLambdaForTesting([&]() { - if (GetParam().traits.priority() == TaskPriority::BEST_EFFORT) - EXPECT_TRUE(can_run.IsSet()); - did_run.Signal(); - })); - - PlatformThread::Sleep(TestTimeouts::tiny_timeout()); - - can_run.Set(); - scheduler_.SetCanRunBestEffort(true); - did_run.Wait(); -} - INSTANTIATE_TEST_SUITE_P(OneTaskSchedulerImplTestParams, TaskSchedulerImplTest, ::testing::ValuesIn(GetTaskSchedulerImplTestParams()));
diff --git a/base/task/task_scheduler/task_tracker.cc b/base/task/task_scheduler/task_tracker.cc index 211f1261..6a218ab3 100644 --- a/base/task/task_scheduler/task_tracker.cc +++ b/base/task/task_scheduler/task_tracker.cc
@@ -8,7 +8,9 @@ #include <string> #include <vector> +#include "base/base_switches.h" #include "base/callback.h" +#include "base/command_line.h" #include "base/compiler_specific.h" #include "base/debug/alias.h" #include "base/json/json_writer.h" @@ -128,6 +130,19 @@ : 0]; } +// Returns the maximum number of TaskPriority::BEST_EFFORT sequences that can be +// scheduled concurrently based on command line flags. +int GetMaxNumScheduledBestEffortSequences() { + // The CommandLine might not be initialized if TaskScheduler is initialized + // in a dynamic library which doesn't have access to argc/argv. + if (CommandLine::InitializedForCurrentProcess() && + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableBestEffortTasks)) { + return 0; + } + return std::numeric_limits<int>::max(); +} + // Returns shutdown behavior based on |traits|; returns SKIP_ON_SHUTDOWN if // shutdown behavior is BLOCK_SHUTDOWN and |is_delayed|, because delayed tasks // are not allowed to block shutdown. @@ -229,10 +244,47 @@ DISALLOW_COPY_AND_ASSIGN(State); }; -// TODO(jessemckenna): Write a helper function to avoid code duplication below. +struct TaskTracker::PreemptedSequence { + PreemptedSequence() = default; + PreemptedSequence(scoped_refptr<Sequence> sequence_in, + TimeTicks next_task_sequenced_time_in, + CanScheduleSequenceObserver* observer_in) + : sequence(std::move(sequence_in)), + next_task_sequenced_time(next_task_sequenced_time_in), + observer(observer_in) {} + PreemptedSequence(PreemptedSequence&& other) = default; + ~PreemptedSequence() = default; + PreemptedSequence& operator=(PreemptedSequence&& other) = default; + bool operator<(const PreemptedSequence& other) const { + return next_task_sequenced_time < other.next_task_sequenced_time; + } + bool operator>(const PreemptedSequence& other) const { + return next_task_sequenced_time > other.next_task_sequenced_time; + } + + // A sequence waiting to be scheduled. + scoped_refptr<Sequence> sequence; + + // The sequenced time of the next task in |sequence|. + TimeTicks next_task_sequenced_time; + + // An observer to notify when |sequence| can be scheduled. + CanScheduleSequenceObserver* observer = nullptr; + + private: + DISALLOW_COPY_AND_ASSIGN(PreemptedSequence); +}; + +TaskTracker::PreemptionState::PreemptionState() = default; +TaskTracker::PreemptionState::~PreemptionState() = default; + TaskTracker::TaskTracker(StringPiece histogram_label) + : TaskTracker(histogram_label, GetMaxNumScheduledBestEffortSequences()) {} + +// TODO(jessemckenna): Write a helper function to avoid code duplication below. +TaskTracker::TaskTracker(StringPiece histogram_label, + int max_num_scheduled_best_effort_sequences) : state_(new State), - can_run_policy_(CanRunPolicy::kAll), flush_cv_(flush_lock_.CreateConditionVariable()), shutdown_lock_(&flush_lock_), task_latency_histograms_{ @@ -297,44 +349,50 @@ DCHECK(*(&task_latency_histograms_[static_cast<int>(TaskPriority::HIGHEST) + 1][0] - 1)); + preemption_state_[static_cast<int>(TaskPriority::BEST_EFFORT)] + .max_scheduled_sequences = max_num_scheduled_best_effort_sequences; + DETACH_FROM_SEQUENCE(sequence_checker_); } TaskTracker::~TaskTracker() = default; -void TaskTracker::StartShutdown() { - AutoSchedulerLock auto_lock(shutdown_lock_); +void TaskTracker::SetExecutionFenceEnabled(bool execution_fence_enabled) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // This method can only be called once. - DCHECK(!shutdown_event_); - DCHECK(!state_->HasShutdownStarted()); +#if DCHECK_IS_ON() + // It is invalid to have two fences at the same time. + DCHECK_NE(execution_fence_enabled_, execution_fence_enabled); + execution_fence_enabled_ = execution_fence_enabled; +#endif - shutdown_event_ = std::make_unique<WaitableEvent>(); + for (int priority_index = static_cast<int>(TaskPriority::HIGHEST); + priority_index >= static_cast<int>(TaskPriority::LOWEST); + --priority_index) { + int max_scheduled_sequences; + if (execution_fence_enabled) { + preemption_state_[priority_index].max_scheduled_sequences_before_fence = + preemption_state_[priority_index].max_scheduled_sequences; + max_scheduled_sequences = 0; + } else { + max_scheduled_sequences = preemption_state_[priority_index] + .max_scheduled_sequences_before_fence; + } - const bool tasks_are_blocking_shutdown = state_->StartShutdown(); - - // From now, if a thread causes the number of tasks blocking shutdown to - // become zero, it will call OnBlockingShutdownTasksComplete(). - - if (!tasks_are_blocking_shutdown) { - // If another thread posts a BLOCK_SHUTDOWN task at this moment, it will - // block until this method releases |shutdown_lock_|. Then, it will fail - // DCHECK(!shutdown_event_->IsSignaled()). This is the desired behavior - // because posting a BLOCK_SHUTDOWN task after StartShutdown() when no - // tasks are blocking shutdown isn't allowed. - shutdown_event_->Signal(); - return; + SetMaxNumScheduledSequences(max_scheduled_sequences, + static_cast<TaskPriority>(priority_index)); } } -void TaskTracker::CompleteShutdown() { - DCHECK(shutdown_event_); - // It is safe to access |shutdown_event_| without holding |lock_| because the - // pointer never changes after being set by StartShutdown(), which must be - // called before this. - { - base::ScopedAllowBaseSyncPrimitives allow_wait; - shutdown_event_->Wait(); - } +size_t TaskTracker::GetPreemptedSequenceCountForTesting( + TaskPriority task_priority) { + int priority_index = static_cast<int>(task_priority); + AutoSchedulerLock auto_lock(preemption_state_[priority_index].lock); + return preemption_state_[priority_index].preempted_sequences.size(); +} + +void TaskTracker::Shutdown() { + PerformShutdown(); + DCHECK(IsShutdownComplete()); // Unblock FlushForTesting() and perform the FlushAsyncForTesting callback // when shutdown completes. @@ -368,10 +426,6 @@ } } -void TaskTracker::SetCanRunPolicy(CanRunPolicy can_run_policy) { - can_run_policy_.store(can_run_policy); -} - bool TaskTracker::WillPostTask(Task* task, TaskShutdownBehavior shutdown_behavior) { DCHECK(task); @@ -390,22 +444,33 @@ return true; } -bool TaskTracker::CanRunPriority(TaskPriority priority) const { - auto can_run_policy = can_run_policy_.load(); +bool TaskTracker::WillScheduleSequence( + const Sequence::Transaction& sequence_transaction, + CanScheduleSequenceObserver* observer) { + const SequenceSortKey sort_key = sequence_transaction.GetSortKey(); + const int priority_index = static_cast<int>(sort_key.priority()); - if (can_run_policy == CanRunPolicy::kAll) - return true; + AutoSchedulerLock auto_lock(preemption_state_[priority_index].lock); - if (can_run_policy == CanRunPolicy::kForegroundOnly && - priority >= TaskPriority::USER_VISIBLE) { + if (preemption_state_[priority_index].current_scheduled_sequences < + preemption_state_[priority_index].max_scheduled_sequences) { + ++preemption_state_[priority_index].current_scheduled_sequences; return true; } + // It is convenient not to have to specify an observer when scheduling + // foreground sequences in tests. + DCHECK(observer); + + preemption_state_[priority_index].preempted_sequences.emplace( + WrapRefCounted(sequence_transaction.sequence()), + sort_key.next_task_sequenced_time(), observer); return false; } scoped_refptr<Sequence> TaskTracker::RunAndPopNextTask( - scoped_refptr<Sequence> sequence) { + scoped_refptr<Sequence> sequence, + CanScheduleSequenceObserver* observer) { DCHECK(sequence); // Run the next task in |sequence|. @@ -438,10 +503,15 @@ const bool sequence_must_be_queued = sequence->BeginTransaction().DidRunTask(); - // The sequence should be reenqueued iff requested by DidRunTask(). + // Never reschedule a Sequence empty after DidRunTask(). The contract is such + // that next poster to make it non-empty is responsible to schedule it. if (!sequence_must_be_queued) - return nullptr; - return sequence; + sequence = nullptr; + + // Allow |sequence| to be rescheduled only if its next task is set to run + // earlier than the earliest currently preempted sequence + return ManageSequencesAfterRunningTask(std::move(sequence), observer, + traits.priority()); } bool TaskTracker::HasShutdownStarted() const { @@ -453,6 +523,16 @@ return shutdown_event_ && shutdown_event_->IsSignaled(); } +void TaskTracker::SetHasShutdownStartedForTesting() { + AutoSchedulerLock auto_lock(shutdown_lock_); + + // Create a dummy |shutdown_event_| to satisfy TaskTracker's expectation of + // its existence during shutdown (e.g. in OnBlockingShutdownTasksComplete()). + shutdown_event_ = std::make_unique<WaitableEvent>(); + + state_->StartShutdown(); +} + void TaskTracker::RecordLatencyHistogram( LatencyHistogramType latency_histogram_type, TaskTraits task_traits, @@ -575,6 +655,105 @@ ThreadRestrictions::SetSingletonAllowed(previous_singleton_allowed); } +void TaskTracker::PerformShutdown() { + { + AutoSchedulerLock auto_lock(shutdown_lock_); + + // This method can only be called once. + DCHECK(!shutdown_event_); + DCHECK(!state_->HasShutdownStarted()); + + shutdown_event_ = std::make_unique<WaitableEvent>(); + + const bool tasks_are_blocking_shutdown = state_->StartShutdown(); + + // From now, if a thread causes the number of tasks blocking shutdown to + // become zero, it will call OnBlockingShutdownTasksComplete(). + + if (!tasks_are_blocking_shutdown) { + // If another thread posts a BLOCK_SHUTDOWN task at this moment, it will + // block until this method releases |shutdown_lock_|. Then, it will fail + // DCHECK(!shutdown_event_->IsSignaled()). This is the desired behavior + // because posting a BLOCK_SHUTDOWN task when TaskTracker::Shutdown() has + // started and no tasks are blocking shutdown isn't allowed. + shutdown_event_->Signal(); + return; + } + } + + // Remove the cap on the maximum number of sequences that can be scheduled + // concurrently. Done after starting shutdown to ensure that non- + // BLOCK_SHUTDOWN sequences don't get a chance to run and that BLOCK_SHUTDOWN + // sequences run on threads running with a normal priority. + for (int priority_index = static_cast<int>(TaskPriority::HIGHEST); + priority_index >= static_cast<int>(TaskPriority::LOWEST); + --priority_index) { + SetMaxNumScheduledSequences(std::numeric_limits<int>::max(), + static_cast<TaskPriority>(priority_index)); + } + + // It is safe to access |shutdown_event_| without holding |lock_| because the + // pointer never changes after being set above. + { + base::ScopedAllowBaseSyncPrimitives allow_wait; + shutdown_event_->Wait(); + } +} + +void TaskTracker::SetMaxNumScheduledSequences(int max_scheduled_sequences, + TaskPriority task_priority) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + std::vector<PreemptedSequence> sequences_to_schedule; + int priority_index = static_cast<int>(task_priority); + + { + AutoSchedulerLock auto_lock(preemption_state_[priority_index].lock); + preemption_state_[priority_index].max_scheduled_sequences = + max_scheduled_sequences; + + while (preemption_state_[priority_index].current_scheduled_sequences < + max_scheduled_sequences && + !preemption_state_[priority_index].preempted_sequences.empty()) { + sequences_to_schedule.push_back( + GetPreemptedSequenceToScheduleLockRequired(task_priority)); + } + } + + for (auto& sequence_to_schedule : sequences_to_schedule) + SchedulePreemptedSequence(std::move(sequence_to_schedule)); +} + +TaskTracker::PreemptedSequence +TaskTracker::GetPreemptedSequenceToScheduleLockRequired( + TaskPriority task_priority) { + int priority_index = static_cast<int>(task_priority); + + preemption_state_[priority_index].lock.AssertAcquired(); + DCHECK(!preemption_state_[priority_index].preempted_sequences.empty()); + + ++preemption_state_[priority_index].current_scheduled_sequences; + DCHECK_LE(preemption_state_[priority_index].current_scheduled_sequences, + preemption_state_[priority_index].max_scheduled_sequences); + + // The const_cast on top is okay since the PreemptedSequence is + // transactionnaly being popped from + // |preemption_state_[priority_index].preempted_sequences| right after and the + // move doesn't alter the sort order (a requirement for the Windows STL's + // consistency debug-checks for std::priority_queue::top()). + PreemptedSequence popped_sequence = std::move(const_cast<PreemptedSequence&>( + preemption_state_[priority_index].preempted_sequences.top())); + preemption_state_[priority_index].preempted_sequences.pop(); + return popped_sequence; +} + +void TaskTracker::SchedulePreemptedSequence( + PreemptedSequence sequence_to_schedule) { + DCHECK(sequence_to_schedule.observer); + sequence_to_schedule.observer->OnCanScheduleSequence( + std::move(sequence_to_schedule.sequence)); +} + bool TaskTracker::HasIncompleteUndelayedTasksForTesting() const { return subtle::Acquire_Load(&num_incomplete_undelayed_tasks_) != 0; } @@ -690,6 +869,56 @@ } } +scoped_refptr<Sequence> TaskTracker::ManageSequencesAfterRunningTask( + scoped_refptr<Sequence> just_ran_sequence, + CanScheduleSequenceObserver* observer, + TaskPriority task_priority) { + const TimeTicks next_task_sequenced_time = + just_ran_sequence ? just_ran_sequence->BeginTransaction() + .GetSortKey() + .next_task_sequenced_time() + : TimeTicks(); + PreemptedSequence sequence_to_schedule; + int priority_index = static_cast<int>(task_priority); + + { + AutoSchedulerLock auto_lock(preemption_state_[priority_index].lock); + + --preemption_state_[priority_index].current_scheduled_sequences; + + const bool can_schedule_sequence = + preemption_state_[priority_index].current_scheduled_sequences < + preemption_state_[priority_index].max_scheduled_sequences; + + if (just_ran_sequence) { + if (can_schedule_sequence && + (preemption_state_[priority_index].preempted_sequences.empty() || + preemption_state_[priority_index] + .preempted_sequences.top() + .next_task_sequenced_time > next_task_sequenced_time)) { + ++preemption_state_[priority_index].current_scheduled_sequences; + return just_ran_sequence; + } + + preemption_state_[priority_index].preempted_sequences.emplace( + std::move(just_ran_sequence), next_task_sequenced_time, observer); + } + + if (can_schedule_sequence && + !preemption_state_[priority_index].preempted_sequences.empty()) { + sequence_to_schedule = + GetPreemptedSequenceToScheduleLockRequired(task_priority); + } + } + + // |sequence_to_schedule.sequence| may be null if there was no preempted + // sequence. + if (sequence_to_schedule.sequence) + SchedulePreemptedSequence(std::move(sequence_to_schedule)); + + return nullptr; +} + void TaskTracker::CallFlushCallbackForTesting() { OnceClosure flush_callback; {
diff --git a/base/task/task_scheduler/task_tracker.h b/base/task/task_scheduler/task_tracker.h index 2ce7f95..8dd9fe4 100644 --- a/base/task/task_scheduler/task_tracker.h +++ b/base/task/task_scheduler/task_tracker.h
@@ -21,6 +21,7 @@ #include "base/strings/string_piece.h" #include "base/synchronization/waitable_event.h" #include "base/task/common/task_annotator.h" +#include "base/task/task_scheduler/can_schedule_sequence_observer.h" #include "base/task/task_scheduler/scheduler_lock.h" #include "base/task/task_scheduler/sequence.h" #include "base/task/task_scheduler/task.h" @@ -34,42 +35,85 @@ namespace internal { -// Determines which tasks are allowed to run. -enum class CanRunPolicy { - // All tasks are allowed to run. - kAll, - // Only USER_VISIBLE and USER_BLOCKING tasks are allowed to run. - kForegroundOnly, - // No tasks can run. - kNone, -}; - // TaskTracker enforces policies that determines whether: // - A task can be added to a sequence (WillPostTask). -// - Tasks for a given priority can run (CanRunPriority). +// - A sequence can be scheduled (WillScheduleSequence). // - The next task in a scheduled sequence can run (RunAndPopNextTask). // TaskTracker also sets up the environment to run a task (RunAndPopNextTask) // and records metrics and trace events. This class is thread-safe. +// +// Life of a sequence: +// (possible states: IDLE, PREEMPTED, SCHEDULED, RUNNING) +// +// Create a sequence +// | +// ------------------------> Sequence is IDLE +// | | +// | Add a task to the sequence +// | (allowed by TaskTracker::WillPostTask) +// | | +// | TaskTracker:WillScheduleSequence +// | _____________________|_____________________ +// | | | +// | Returns true Returns false +// | | | +// | | Sequence is PREEMPTED <---- +// | | | | +// | | Eventually, | +// | | CanScheduleSequenceObserver | +// | | is notified that the | +// | | sequence can be scheduled. | +// | |__________________________________________| | +// | | | +// | (*) Sequence is SCHEDULED | +// | | | +// | A thread is ready to run the next | +// | task in the sequence | +// | | | +// | TaskTracker::RunAndPopNextTask | +// | A task from the sequence is run | +// | Sequence is RUNNING | +// | | | +// | ______________________|____ | +// | | | | +// | Sequence is empty Sequence has more tasks | +// |_________| _____________|_______________ | +// | | | +// Sequence can be Sequence cannot be | +// scheduled scheduled at this | +// | moment | +// Go back to (*) |_________________| +// +// +// Note: A best-effort task is a task posted with TaskPriority::BEST_EFFORT. A +// foreground task is a task posted with TaskPriority::USER_VISIBLE or +// TaskPriority::USER_BLOCKING. +// +// TODO(fdoray): We want to allow disabling TaskPriority::BEST_EFFORT tasks in a +// scope (e.g. during startup or page load), but we don't need a dynamic maximum +// number of best-effort tasks. The code could probably be simplified if it +// didn't support that. https://crbug.com/831835 class BASE_EXPORT TaskTracker { public: // |histogram_label| is used as a suffix for histograms, it must not be empty. + // The first constructor sets the maximum number of TaskPriority::BEST_EFFORT + // sequences that can be scheduled concurrently to 0 if the + // --disable-best-effort-tasks flag is specified, max() otherwise. The second + // constructor sets it to |max_num_scheduled_best_effort_sequences|. TaskTracker(StringPiece histogram_label); + TaskTracker(StringPiece histogram_label, + int max_num_scheduled_best_effort_sequences); virtual ~TaskTracker(); - // Initiates shutdown. Once this is called, only BLOCK_SHUTDOWN tasks will - // start running (doesn't affect tasks that are already running). This can - // only be called once. - void StartShutdown(); - - // Synchronously completes shutdown. StartShutdown() must be called first. - // Returns when: + // Synchronously shuts down the scheduler. Once this is called, only tasks + // posted with the BLOCK_SHUTDOWN behavior will be run. Returns when: // - All SKIP_ON_SHUTDOWN tasks that were already running have completed their // execution. // - All posted BLOCK_SHUTDOWN tasks have completed their execution. // CONTINUE_ON_SHUTDOWN tasks still may be running after Shutdown returns. // This can only be called once. - void CompleteShutdown(); + void Shutdown(); // Waits until there are no incomplete undelayed tasks. May be called in tests // to validate that a condition is met after all undelayed tasks have run. @@ -85,34 +129,45 @@ // FlushAsyncForTesting() may be pending at any given time. void FlushAsyncForTesting(OnceClosure flush_callback); - // Sets the new CanRunPolicy policy, possibly affecting result of - // CanRunPriority(). The caller must wake up worker as appropriate so that - // tasks that are allowed to run by the new policy can be scheduled. - void SetCanRunPolicy(CanRunPolicy can_run_policy); - // Informs this TaskTracker that |task| from a |shutdown_behavior| sequence // is about to be posted. Returns true if this operation is allowed (|task| // should be posted if-and-only-if it is). This method may also modify // metadata on |task| if desired. bool WillPostTask(Task* task, TaskShutdownBehavior shutdown_behavior); - // Returns true if a task with |priority| can run under to the current policy. - bool CanRunPriority(TaskPriority priority) const; + // Informs this TaskTracker that the Sequence locked by |sequence_transaction| + // is about to be scheduled. If this returns true, it is expected that + // RunAndPopNextTask() will soon be called with the Sequence as argument. + // Otherwise, RunAndPopNextTask() must not be called with the Sequence as + // argument until |observer| is notified that the Sequence can be scheduled + // (the caller doesn't need to keep a pointer to the Sequence; it will be + // included in the notification to |observer|). WillPostTask() must have + // allowed the task in front of the Sequence to be posted before this is + // called. |observer| is only required if the priority of the Sequence is + // TaskPriority::BEST_EFFORT. + bool WillScheduleSequence(const Sequence::Transaction& sequence_transaction, + CanScheduleSequenceObserver* observer); // Runs the next task in |sequence| unless the current shutdown state prevents // that. Then, pops the task from |sequence| (even if it didn't run). Returns - // |sequence| if non-empty after popping a task from it (which indicates that - // it should be reenqueued). WillPostTask() must have allowed the task in - // front of |sequence| to be posted before this is called. - scoped_refptr<Sequence> RunAndPopNextTask(scoped_refptr<Sequence> sequence); + // |sequence| if it can be rescheduled immediately. If |sequence| is non-empty + // after popping a task from it but it can't be rescheduled immediately, it + // will be handed back to |observer| when it can be rescheduled. + // WillPostTask() must have allowed the task in front of |sequence| to be + // posted before this is called. Also, WillScheduleSequence(), + // RunAndPopNextTask() or CanScheduleSequenceObserver::OnCanScheduleSequence() + // must have allowed |sequence| to be (re)scheduled. + scoped_refptr<Sequence> RunAndPopNextTask( + scoped_refptr<Sequence> sequence, + CanScheduleSequenceObserver* observer); - // Returns true once shutdown has started (StartShutdown() was called). - // Note: sequential consistency with the thread calling StartShutdown() isn't - // guaranteed by this call. + // Returns true once shutdown has started (Shutdown() has been called but + // might not have returned). Note: sequential consistency with the thread + // calling Shutdown() (or SetHasShutdownStartedForTesting()) isn't guaranteed + // by this call. bool HasShutdownStarted() const; - // Returns true if shutdown has completed (StartShutdown() was called and - // no tasks are blocking shutdown). + // Returns true if shutdown has completed (Shutdown() has returned). bool IsShutdownComplete() const; enum class LatencyHistogramType { @@ -125,6 +180,11 @@ HEARTBEAT_LATENCY, }; + // Causes HasShutdownStarted() to return true. Unlike when Shutdown() returns, + // IsShutdownComplete() won't return true after this returns. Shutdown() + // cannot be called after this. + void SetHasShutdownStartedForTesting(); + // Records two histograms // 1. TaskScheduler.[label].HeartbeatLatencyMicroseconds.[suffix]: // Now() - posted_time @@ -145,6 +205,13 @@ return tracked_ref_factory_.GetTrackedRef(); } + // Enables/disables an execution fence. When the fence is released, + // reschedules the sequences that were preempted by the fence. + void SetExecutionFenceEnabled(bool execution_fence_enabled); + + // Returns the number of preempted sequences of a given priority. + size_t GetPreemptedSequenceCountForTesting(TaskPriority priority); + protected: // Runs and deletes |task| if |can_run_task| is true. Otherwise, just deletes // |task|. |task| is always deleted in the environment where it runs or would @@ -164,9 +231,62 @@ private: class State; + struct PreemptedSequence; + + struct PreemptionState { + PreemptionState(); + ~PreemptionState(); + + // A priority queue of sequences that are waiting to be scheduled. Use + // std::greater so that the sequence which contains the task that has been + // posted the earliest is on top of the priority queue. + std::priority_queue<PreemptedSequence, + std::vector<PreemptedSequence>, + std::greater<PreemptedSequence>> + preempted_sequences; + + // Maximum number of sequences that can that be scheduled concurrently. + int max_scheduled_sequences = std::numeric_limits<int>::max(); + + // Caches the |max_scheduled_sequences| before enabling the execution fence. + int max_scheduled_sequences_before_fence = 0; + + // Number of currently scheduled sequences. + int current_scheduled_sequences = 0; + + // Synchronizes accesses to other members. + // |max_scheduled_sequences| and |max_scheduled_sequences_before_fence| are + // only written from the main sequence within the scope of |lock|. Reads can + // happen on the main sequence without holding |lock|, or on any other + // sequence while holding |lock|. + SchedulerLock lock; + + private: + DISALLOW_COPY_AND_ASSIGN(PreemptionState); + }; void PerformShutdown(); + // Sets the maximum number of sequences of priority |priority| that can be + // scheduled concurrently to |max_scheduled_sequences|. + void SetMaxNumScheduledSequences(int max_scheduled_sequences, + TaskPriority priority); + + // Pops the next sequence in |preemption_state_[priority].preempted_sequences| + // and increments |preemption_state_[priority].current_scheduled_sequences|. + // Must only be called in the scope of |preemption_state_[priority].lock|, + // with |preemption_state_[priority].preempted_sequences| non-empty. The + // caller must forward the returned sequence to the associated + // CanScheduleSequenceObserver as soon as |preemption_state_[priority].lock| + // is released. + PreemptedSequence GetPreemptedSequenceToScheduleLockRequired( + TaskPriority priority); + + // Schedules |sequence_to_schedule.sequence| using + // |sequence_to_schedule.observer|. Does not verify that the sequence is + // allowed to be scheduled. + void SchedulePreemptedSequence(PreemptedSequence sequence_to_schedule); + // Called before WillPostTask() informs the tracing system that a task has // been posted. Updates |num_tasks_blocking_shutdown_| if necessary and // returns true if the current shutdown state allows the task to be posted. @@ -190,6 +310,24 @@ // if it reaches zero. void DecrementNumIncompleteUndelayedTasks(); + // To be called after running a task from |just_ran_sequence|. Performs the + // following actions: + // - If |just_ran_sequence| is non-null: + // - returns it if it should be rescheduled by the caller of + // RunAndPopNextTask(), i.e. its next task is set to run earlier than the + // earliest currently preempted sequence. + // - Otherwise |just_ran_sequence| is preempted and the next preempted + // sequence is scheduled (|observer| will be notified when + // |just_ran_sequence| should be scheduled again). + // - If |just_ran_sequence| is null (RunAndPopNextTask() just popped the last + // task from it): + // - the next preempeted sequence (if any) is scheduled. + // - In all cases: adjusts the number of scheduled sequences accordingly. + scoped_refptr<Sequence> ManageSequencesAfterRunningTask( + scoped_refptr<Sequence> just_ran_sequence, + CanScheduleSequenceObserver* observer, + TaskPriority task_priority); + // Calls |flush_callback_for_testing_| if one is available in a lock-safe // manner. void CallFlushCallbackForTesting(); @@ -222,9 +360,6 @@ // returns. subtle::Atomic32 num_incomplete_undelayed_tasks_ = 0; - // Global policy the determines result of CanRunPriority(). - std::atomic<CanRunPolicy> can_run_policy_; - // Lock associated with |flush_cv_|. Partially synchronizes access to // |num_incomplete_undelayed_tasks_|. Full synchronization isn't needed // because it's atomic, but synchronization is needed to coordinate waking and @@ -265,6 +400,19 @@ HistogramBase* const num_tasks_run_while_queuing_histograms_[kNumTaskPriorities][2]; + PreemptionState preemption_state_[kNumTaskPriorities]; + +#if DCHECK_IS_ON() + // Indicates whether to prevent tasks running. + bool execution_fence_enabled_ = false; +#endif + + // Enforces that |max_scheduled_sequences| and + // |max_scheduled_sequences_before_fence| in PreemptedState are only written + // on the main sequence (determined by the first call to + // SetMaxNumScheduledSequences or SetExecutionFenceEnabled). + SEQUENCE_CHECKER(sequence_checker_); + // Ensures all state (e.g. dangling cleaned up workers) is coalesced before // destroying the TaskTracker (e.g. in test environments). // Ref. https://crbug.com/827615.
diff --git a/base/task/task_scheduler/task_tracker_posix_unittest.cc b/base/task/task_scheduler/task_tracker_posix_unittest.cc index f0a49dd..8d35b08 100644 --- a/base/task/task_scheduler/task_tracker_posix_unittest.cc +++ b/base/task/task_scheduler/task_tracker_posix_unittest.cc
@@ -61,9 +61,11 @@ EXPECT_TRUE(tracker_.WillPostTask(&task, default_traits.shutdown_behavior())); auto sequence = test::CreateSequenceWithTask(std::move(task), default_traits); + EXPECT_TRUE( + tracker_.WillScheduleSequence(sequence->BeginTransaction(), nullptr)); // Expect RunAndPopNextTask to return nullptr since |sequence| is empty after // popping a task from it. - EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence)); + EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence, nullptr)); EXPECT_TRUE(did_run); } @@ -85,10 +87,12 @@ auto sequence = test::CreateSequenceWithTask( std::move(task), default_traits, MakeRefCounted<NullTaskRunner>(), TaskSourceExecutionMode::kSequenced); + EXPECT_TRUE( + tracker_.WillScheduleSequence(sequence->BeginTransaction(), nullptr)); // Expect RunAndPopNextTask to return nullptr since |sequence| is empty after // popping a task from it. - EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence)); + EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence, nullptr)); // Join the service thread to make sure that the read watch is registered and // unregistered before file descriptors are closed.
diff --git a/base/task/task_scheduler/task_tracker_unittest.cc b/base/task/task_scheduler/task_tracker_unittest.cc index a5ef426..798dd823 100644 --- a/base/task/task_scheduler/task_tracker_unittest.cc +++ b/base/task/task_scheduler/task_tracker_unittest.cc
@@ -48,6 +48,15 @@ constexpr size_t kLoadTestNumIterations = 75; +class MockCanScheduleSequenceObserver : public CanScheduleSequenceObserver { + public: + void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override { + MockOnCanScheduleSequence(sequence.get()); + } + + MOCK_METHOD1(MockOnCanScheduleSequence, void(Sequence*)); +}; + // Invokes a closure asynchronously. class CallbackThread : public SimpleThread { public: @@ -123,10 +132,16 @@ (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) { EXPECT_TRUE(owned_task_.task); + testing::StrictMock<MockCanScheduleSequenceObserver> + never_notified_observer; + auto sequence = + test::CreateSequenceWithTask(std::move(owned_task_), traits_); + ASSERT_TRUE(tracker_->WillScheduleSequence(sequence->BeginTransaction(), + &never_notified_observer)); // Expect RunAndPopNextTask to return nullptr since |sequence| is empty // after popping a task from it. - EXPECT_FALSE(tracker_->RunAndPopNextTask( - test::CreateSequenceWithTask(std::move(owned_task_), traits_))); + EXPECT_FALSE(tracker_->RunAndPopNextTask(std::move(sequence), + &never_notified_observer)); } } @@ -167,19 +182,22 @@ } void DispatchAndRunTaskWithTracker(Task task, const TaskTraits& traits) { - tracker_.RunAndPopNextTask( - test::CreateSequenceWithTask(std::move(task), traits)); + auto sequence = test::CreateSequenceWithTask(std::move(task), traits); + ASSERT_TRUE(tracker_.WillScheduleSequence(sequence->BeginTransaction(), + &never_notified_observer_)); + tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_); } - // Calls tracker_->CompleteShutdown() on a new thread and expects it to block. - void ExpectAsyncCompleteShutdownBlocks() { + // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown() + // method has been entered on the new thread, but it hasn't necessarily + // returned. + void CallShutdownAsync() { ASSERT_FALSE(thread_calling_shutdown_); - ASSERT_TRUE(tracker_.HasShutdownStarted()); - thread_calling_shutdown_ = std::make_unique<CallbackThread>( - Bind(&TaskTracker::CompleteShutdown, Unretained(&tracker_))); + thread_calling_shutdown_.reset(new CallbackThread( + Bind(&TaskTracker::Shutdown, Unretained(&tracker_)))); thread_calling_shutdown_->Start(); - PlatformThread::Sleep(TestTimeouts::tiny_timeout()); - VerifyAsyncShutdownInProgress(); + while (!tracker_.HasShutdownStarted()) + PlatformThread::YieldCurrentThread(); } void WaitForAsyncIsShutdownComplete() { @@ -221,6 +239,7 @@ } TaskTracker tracker_ = {"Test"}; + testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer_; private: void RunTaskCallback() { @@ -278,7 +297,7 @@ EXPECT_EQ(1U, NumTasksExecuted()); // Shutdown() shouldn't block. - test::ShutdownTaskTracker(&tracker_); + tracker_.Shutdown(); } TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { @@ -310,14 +329,14 @@ task_running.Wait(); // Initiate shutdown after the task has started to run. - tracker_.StartShutdown(); + CallShutdownAsync(); if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. - tracker_.CompleteShutdown(); + WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); } else { // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. - ExpectAsyncCompleteShutdownBlocks(); + VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); } // Unblock the task. @@ -340,9 +359,9 @@ EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task, TaskShutdownBehavior::BLOCK_SHUTDOWN)); - // Start shutdown and try to complete it asynchronously. - tracker_.StartShutdown(); - ExpectAsyncCompleteShutdownBlocks(); + // Call Shutdown() asynchronously. + CallShutdownAsync(); + VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it // should be discarded. @@ -365,13 +384,12 @@ Task task(CreateTask()); EXPECT_TRUE(tracker_.WillPostTask(&task, GetParam())); - // Start shutdown. - tracker_.StartShutdown(); + // Call Shutdown() asynchronously. + CallShutdownAsync(); EXPECT_EQ(0U, NumTasksExecuted()); if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { - // Verify that CompleteShutdown() blocks. - ExpectAsyncCompleteShutdownBlocks(); + VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); // Run the task to unblock shutdown. DispatchAndRunTaskWithTracker(std::move(task), GetParam()); @@ -382,7 +400,7 @@ // shutdown after shutdown because Shutdown() won't return if there are // pending BLOCK_SHUTDOWN tasks. } else { - tracker_.CompleteShutdown(); + WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); // The task shouldn't be allowed to run after shutdown. DispatchAndRunTaskWithTracker(std::move(task), GetParam()); @@ -397,8 +415,9 @@ EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task, TaskShutdownBehavior::BLOCK_SHUTDOWN)); - // Start shutdown. - tracker_.StartShutdown(); + // Call Shutdown() asynchronously. + CallShutdownAsync(); + VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. @@ -417,10 +436,8 @@ // Don't try to run the task, because it wasn't allowed to be posted. } - // Verify that CompleteShutdown() blocks. - ExpectAsyncCompleteShutdownBlocks(); - // Unblock shutdown by running |block_shutdown_task|. + VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); DispatchAndRunTaskWithTracker(std::move(block_shutdown_task), TaskShutdownBehavior::BLOCK_SHUTDOWN); EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, @@ -429,7 +446,7 @@ } TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { - test::ShutdownTaskTracker(&tracker_); + tracker_.Shutdown(); Task task(CreateTask()); @@ -509,10 +526,13 @@ EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); + testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; auto sequence = test::CreateSequenceWithTask( std::move(verify_task), traits, std::move(task_runner), execution_mode); - tracker->RunAndPopNextTask(std::move(sequence)); + ASSERT_TRUE(tracker->WillScheduleSequence(sequence->BeginTransaction(), + &never_notified_observer)); + tracker->RunAndPopNextTask(std::move(sequence), &never_notified_observer); // TaskRunnerHandle state is reset outside of task's scope. EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); @@ -752,7 +772,7 @@ // Shutdown() should return immediately since there are no pending // BLOCK_SHUTDOWN tasks. - test::ShutdownTaskTracker(&tracker_); + tracker_.Shutdown(); // FlushForTesting() should return immediately after shutdown, even if an // undelayed task hasn't run. @@ -769,7 +789,7 @@ // Shutdown() should return immediately since there are no pending // BLOCK_SHUTDOWN tasks. - test::ShutdownTaskTracker(&tracker_); + tracker_.Shutdown(); // FlushForTesting() should callback immediately after shutdown, even if an // undelayed task hasn't run. @@ -796,7 +816,7 @@ // Shutdown() should return immediately since there are no pending // BLOCK_SHUTDOWN tasks. - test::ShutdownTaskTracker(&tracker_); + tracker_.Shutdown(); // FlushForTesting() should now return, even if an undelayed task hasn't run. WAIT_FOR_ASYNC_FLUSH_RETURNED(); @@ -820,7 +840,7 @@ // Shutdown() should return immediately since there are no pending // BLOCK_SHUTDOWN tasks. - test::ShutdownTaskTracker(&tracker_); + tracker_.Shutdown(); // FlushAsyncForTesting() should now callback, even if an undelayed task // hasn't run. @@ -849,7 +869,7 @@ // Since the delayed task doesn't block shutdown, a call to Shutdown() should // not hang. - test::ShutdownTaskTracker(&tracker_); + tracker_.Shutdown(); } INSTANTIATE_TEST_SUITE_P( @@ -888,9 +908,11 @@ sequence_transaction.PushTask(std::move(task)); EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); + ASSERT_TRUE(tracker_.WillScheduleSequence(sequence_transaction, + &never_notified_observer_)); } - tracker_.RunAndPopNextTask(std::move(sequence)); + tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_); EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); } @@ -925,7 +947,7 @@ EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted()); // Should return immediately because no tasks are blocking shutdown. - test::ShutdownTaskTracker(&tracker_); + tracker_.Shutdown(); } TEST_F(TaskSchedulerTaskTrackerTest, @@ -968,9 +990,8 @@ for (const auto& thread : post_threads) thread->Join(); - // Start shutdown and try to complete shutdown asynchronously. - tracker_.StartShutdown(); - ExpectAsyncCompleteShutdownBlocks(); + // Call Shutdown() asynchronously. + CallShutdownAsync(); // Run tasks asynchronously. std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads; @@ -1009,9 +1030,8 @@ EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task, TaskShutdownBehavior::BLOCK_SHUTDOWN)); - // Start shutdown and try to complete it asynchronously. - tracker_.StartShutdown(); - ExpectAsyncCompleteShutdownBlocks(); + // Call Shutdown() asynchronously. + CallShutdownAsync(); // Post and run tasks asynchronously. std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; @@ -1067,8 +1087,335 @@ scoped_refptr<Sequence> sequence = test::CreateSequenceWithTask(std::move(task_1), default_traits); - sequence->BeginTransaction().PushTask(std::move(task_2)); - EXPECT_EQ(sequence, tracker_.RunAndPopNextTask(sequence)); + { + Sequence::Transaction sequence_transaction(sequence->BeginTransaction()); + sequence_transaction.PushTask(std::move(task_2)); + EXPECT_TRUE(tracker_.WillScheduleSequence(sequence_transaction, nullptr)); + } + + EXPECT_EQ(sequence, tracker_.RunAndPopNextTask(sequence, nullptr)); +} + +namespace { + +void TestWillScheduleBestEffortSequenceWithMaxBestEffortSequences( + int max_num_scheduled_best_effort_sequences, + TaskTracker& tracker) { + // Simulate posting |max_num_scheduled_best_effort_sequences| best-effort + // tasks and scheduling the associated sequences. This should succeed. + std::vector<scoped_refptr<Sequence>> scheduled_sequences; + testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; + TaskTraits best_effort_traits = TaskTraits(TaskPriority::BEST_EFFORT); + for (int i = 0; i < max_num_scheduled_best_effort_sequences; ++i) { + Task task(FROM_HERE, DoNothing(), TimeDelta()); + EXPECT_TRUE( + tracker.WillPostTask(&task, best_effort_traits.shutdown_behavior())); + scoped_refptr<Sequence> sequence = + test::CreateSequenceWithTask(std::move(task), best_effort_traits); + ASSERT_TRUE(tracker.WillScheduleSequence(sequence->BeginTransaction(), + &never_notified_observer)); + scheduled_sequences.push_back(std::move(sequence)); + } + + // Simulate posting extra best-effort tasks and scheduling the associated + // sequences. This should fail because the maximum number of best-effort + // sequences that can be scheduled concurrently is already reached. + std::vector<std::unique_ptr<bool>> extra_tasks_did_run; + std::vector< + std::unique_ptr<testing::StrictMock<MockCanScheduleSequenceObserver>>> + extra_observers; + std::vector<scoped_refptr<Sequence>> extra_sequences; + for (int i = 0; i < max_num_scheduled_best_effort_sequences; ++i) { + extra_tasks_did_run.push_back(std::make_unique<bool>()); + Task extra_task( + FROM_HERE, + BindOnce([](bool* extra_task_did_run) { *extra_task_did_run = true; }, + Unretained(extra_tasks_did_run.back().get())), + TimeDelta()); + EXPECT_TRUE(tracker.WillPostTask(&extra_task, + best_effort_traits.shutdown_behavior())); + extra_sequences.push_back(test::CreateSequenceWithTask( + std::move(extra_task), best_effort_traits)); + extra_observers.push_back( + std::make_unique< + testing::StrictMock<MockCanScheduleSequenceObserver>>()); + EXPECT_FALSE( + tracker.WillScheduleSequence(extra_sequences.back()->BeginTransaction(), + extra_observers.back().get())); + } + + // Run the sequences scheduled at the beginning of the test. Expect an + // observer from |extra_observer| to be notified every time a task finishes to + // run. + for (int i = 0; i < max_num_scheduled_best_effort_sequences; ++i) { + EXPECT_CALL(*extra_observers[i].get(), + MockOnCanScheduleSequence(extra_sequences[i].get())); + EXPECT_FALSE(tracker.RunAndPopNextTask(scheduled_sequences[i], + &never_notified_observer)); + testing::Mock::VerifyAndClear(extra_observers[i].get()); + } + + // Run the extra sequences. + for (int i = 0; i < max_num_scheduled_best_effort_sequences; ++i) { + EXPECT_FALSE(*extra_tasks_did_run[i]); + EXPECT_FALSE(tracker.RunAndPopNextTask(extra_sequences[i], + &never_notified_observer)); + EXPECT_TRUE(*extra_tasks_did_run[i]); + } +} + +} // namespace + +// Verify that WillScheduleSequence() returns nullptr when it receives a +// best-effort sequence and the maximum number of best-effort sequences that can +// be scheduled concurrently is reached. Verify that an observer is notified +// when a best-effort sequence can be scheduled (i.e. when one of the previously +// scheduled best-effort sequences has run). +TEST_F(TaskSchedulerTaskTrackerTest, + WillScheduleBestEffortSequenceWithMaxBestEffortSequences) { + constexpr int kMaxNumScheduledBestEffortSequences = 2; + TaskTracker tracker("Test", kMaxNumScheduledBestEffortSequences); + TestWillScheduleBestEffortSequenceWithMaxBestEffortSequences( + kMaxNumScheduledBestEffortSequences, tracker); +} + +// Verify that providing a cap for the number of BEST_EFFORT tasks to the +// constructor of TaskTracker is compatible with using an execution fence. +TEST_F(TaskSchedulerTaskTrackerTest, + WillScheduleBestEffortSequenceWithMaxBestEffortSequencesAndFence) { + constexpr int kMaxNumScheduledBestEffortSequences = 2; + TaskTracker tracker("Test", kMaxNumScheduledBestEffortSequences); + tracker.SetExecutionFenceEnabled(true); + tracker.SetExecutionFenceEnabled(false); + TestWillScheduleBestEffortSequenceWithMaxBestEffortSequences( + kMaxNumScheduledBestEffortSequences, tracker); +} + +namespace { + +void SetBool(bool* arg) { + ASSERT_TRUE(arg); + EXPECT_FALSE(*arg); + *arg = true; +} + +} // namespace + +// Verify that enabling the ScopedExecutionFence will prevent +// WillScheduleSequence() returning sequence. +TEST_F(TaskSchedulerTaskTrackerTest, + WillScheduleSequenceWithScopedExecutionFence) { + TaskTraits default_traits = {}; + Task task_a(FROM_HERE, DoNothing(), TimeDelta()); + EXPECT_TRUE( + tracker_.WillPostTask(&task_a, default_traits.shutdown_behavior())); + scoped_refptr<Sequence> sequence_a = + test::CreateSequenceWithTask(std::move(task_a), default_traits); + testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; + EXPECT_TRUE(tracker_.WillScheduleSequence(sequence_a->BeginTransaction(), + &never_notified_observer)); + + // Verify that WillScheduleSequence() returns nullptr for foreground sequence + // when the ScopedExecutionFence is enabled. + tracker_.SetExecutionFenceEnabled(true); + bool task_b_1_did_run = false; + Task task_b_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_1_did_run)), + TimeDelta()); + EXPECT_TRUE( + tracker_.WillPostTask(&task_b_1, default_traits.shutdown_behavior())); + scoped_refptr<Sequence> sequence_b = + test::CreateSequenceWithTask(std::move(task_b_1), default_traits); + testing::StrictMock<MockCanScheduleSequenceObserver> observer_b_1; + EXPECT_EQ(0u, tracker_.GetPreemptedSequenceCountForTesting( + TaskPriority::BEST_EFFORT)); + EXPECT_FALSE(tracker_.WillScheduleSequence(sequence_b->BeginTransaction(), + &observer_b_1)); + EXPECT_EQ(1u, tracker_.GetPreemptedSequenceCountForTesting( + TaskPriority::USER_VISIBLE)); + + bool task_b_2_did_run = false; + Task task_b_2(FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_2_did_run)), + TimeDelta()); + TaskTraits best_effort_traits = TaskTraits(TaskPriority::BEST_EFFORT); + EXPECT_TRUE( + tracker_.WillPostTask(&task_b_2, best_effort_traits.shutdown_behavior())); + sequence_b->BeginTransaction().PushTask(std::move(task_b_2)); + testing::StrictMock<MockCanScheduleSequenceObserver> observer_b_2; + EXPECT_FALSE(tracker_.WillScheduleSequence(sequence_b->BeginTransaction(), + &observer_b_2)); + // The TaskPriority of the Sequence is unchanged by posting new tasks to it. + EXPECT_EQ(2u, tracker_.GetPreemptedSequenceCountForTesting( + TaskPriority::USER_VISIBLE)); + + // Verify that WillScheduleSequence() returns nullptr for best-effort sequence + // when the ScopedExecutionFence is enabled. + bool task_c_did_run = false; + Task task_c(FROM_HERE, BindOnce(&SetBool, Unretained(&task_c_did_run)), + TimeDelta()); + EXPECT_TRUE( + tracker_.WillPostTask(&task_c, best_effort_traits.shutdown_behavior())); + scoped_refptr<Sequence> sequence_c = + test::CreateSequenceWithTask(std::move(task_c), best_effort_traits); + testing::StrictMock<MockCanScheduleSequenceObserver> observer_c; + EXPECT_FALSE(tracker_.WillScheduleSequence(sequence_c->BeginTransaction(), + &observer_c)); + EXPECT_EQ(1u, tracker_.GetPreemptedSequenceCountForTesting( + TaskPriority::BEST_EFFORT)); + + // Verifies that the sequences preempted when the fence is on are rescheduled + // right after the fence is released. + EXPECT_CALL(observer_b_1, MockOnCanScheduleSequence(sequence_b.get())); + EXPECT_CALL(observer_b_2, MockOnCanScheduleSequence(sequence_b.get())); + EXPECT_CALL(observer_c, MockOnCanScheduleSequence(sequence_c.get())); + tracker_.SetExecutionFenceEnabled(false); + testing::Mock::VerifyAndClear(&observer_b_1); + testing::Mock::VerifyAndClear(&observer_b_2); + testing::Mock::VerifyAndClear(&observer_c); + EXPECT_EQ(0u, tracker_.GetPreemptedSequenceCountForTesting( + TaskPriority::USER_VISIBLE)); + EXPECT_EQ(0u, tracker_.GetPreemptedSequenceCountForTesting( + TaskPriority::BEST_EFFORT)); + + // Runs the sequences and verifies the tasks are done. + EXPECT_FALSE( + tracker_.RunAndPopNextTask(sequence_a, &never_notified_observer)); + + EXPECT_FALSE(task_b_1_did_run); + EXPECT_EQ(sequence_b, tracker_.RunAndPopNextTask(sequence_b, &observer_b_1)); + EXPECT_TRUE(task_b_1_did_run); + + EXPECT_FALSE(task_b_2_did_run); + EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence_b, &observer_b_2)); + EXPECT_TRUE(task_b_2_did_run); + + EXPECT_FALSE(task_c_did_run); + EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence_c, &observer_c)); + EXPECT_TRUE(task_c_did_run); + + // Verify that WillScheduleSequence() returns the sequence when the + // ScopedExecutionFence isn't enabled. + Task task_d(FROM_HERE, DoNothing(), TimeDelta()); + EXPECT_TRUE( + tracker_.WillPostTask(&task_d, default_traits.shutdown_behavior())); + scoped_refptr<Sequence> sequence_d = + test::CreateSequenceWithTask(std::move(task_d), default_traits); + EXPECT_TRUE(tracker_.WillScheduleSequence(sequence_d->BeginTransaction(), + &never_notified_observer)); +} + +// Verify that RunAndPopNextTask() doesn't reschedule the best-effort sequence +// it was assigned if there is a preempted best-effort sequence with an earlier +// sequence time (compared to the next task in the sequence assigned to +// RunAndPopNextTask()). +TEST_F(TaskSchedulerTaskTrackerTest, + RunNextBestEffortTaskWithEarlierPendingBestEffortTask) { + constexpr int kMaxNumScheduledBestEffortSequences = 1; + TaskTracker tracker("Test", kMaxNumScheduledBestEffortSequences); + testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; + TaskTraits best_effort_traits = TaskTraits(TaskPriority::BEST_EFFORT); + + // Simulate posting a best-effort task and scheduling the associated sequence. + // This should succeed. + bool task_a_1_did_run = false; + Task task_a_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_1_did_run)), + TimeDelta()); + EXPECT_TRUE( + tracker.WillPostTask(&task_a_1, best_effort_traits.shutdown_behavior())); + scoped_refptr<Sequence> sequence_a = + test::CreateSequenceWithTask(std::move(task_a_1), best_effort_traits); + EXPECT_TRUE(tracker.WillScheduleSequence(sequence_a->BeginTransaction(), + &never_notified_observer)); + + // Simulate posting an extra best-effort task and scheduling the associated + // sequence. This should fail because the maximum number of best-effort + // sequences that can be scheduled concurrently is already reached. + bool task_b_1_did_run = false; + Task task_b_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_1_did_run)), + TimeDelta()); + EXPECT_TRUE( + tracker.WillPostTask(&task_b_1, best_effort_traits.shutdown_behavior())); + scoped_refptr<Sequence> sequence_b = + test::CreateSequenceWithTask(std::move(task_b_1), best_effort_traits); + testing::StrictMock<MockCanScheduleSequenceObserver> task_b_1_observer; + EXPECT_FALSE(tracker.WillScheduleSequence(sequence_b->BeginTransaction(), + &task_b_1_observer)); + + // Wait to be sure that the sequence time of |task_a_2| is after the sequenced + // time of |task_b_1|. + PlatformThread::Sleep(TestTimeouts::tiny_timeout()); + + // Post an extra best-effort task in |sequence_a|. + bool task_a_2_did_run = false; + Task task_a_2(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_2_did_run)), + TimeDelta()); + EXPECT_TRUE( + tracker.WillPostTask(&task_a_2, best_effort_traits.shutdown_behavior())); + sequence_a->BeginTransaction().PushTask(std::move(task_a_2)); + + // Run the first task in |sequence_a|. RunAndPopNextTask() should return + // nullptr since |sequence_a| can't be rescheduled immediately. + // |task_b_1_observer| should be notified that |sequence_b| can be scheduled. + testing::StrictMock<MockCanScheduleSequenceObserver> task_a_2_observer; + EXPECT_CALL(task_b_1_observer, MockOnCanScheduleSequence(sequence_b.get())); + EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &task_a_2_observer)); + testing::Mock::VerifyAndClear(&task_b_1_observer); + EXPECT_TRUE(task_a_1_did_run); + + // Run the first task in |sequence_b|. RunAndPopNextTask() should return + // nullptr since |sequence_b| is empty after popping a task from it. + // |task_a_2_observer| should be notified that |sequence_a| can be + // scheduled. + EXPECT_CALL(task_a_2_observer, MockOnCanScheduleSequence(sequence_a.get())); + EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_b, &never_notified_observer)); + testing::Mock::VerifyAndClear(&task_a_2_observer); + EXPECT_TRUE(task_b_1_did_run); + + // Run the first task in |sequence_a|. RunAndPopNextTask() should return + // nullptr since |sequence_b| is empty after popping a task from it. No + // observer should be notified. + EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &never_notified_observer)); + EXPECT_TRUE(task_a_2_did_run); +} + +// Verify that preempted best-effort sequences are scheduled when shutdown +// starts. +TEST_F(TaskSchedulerTaskTrackerTest, + SchedulePreemptedBestEffortSequencesOnShutdown) { + constexpr int kMaxNumScheduledBestEffortSequences = 0; + TaskTracker tracker("Test", kMaxNumScheduledBestEffortSequences); + testing::StrictMock<MockCanScheduleSequenceObserver> observer; + + // Simulate scheduling sequences. TaskTracker should prevent this. + std::vector<scoped_refptr<Sequence>> preempted_sequences; + for (int i = 0; i < 3; ++i) { + Task task(FROM_HERE, DoNothing(), + TimeDelta()); + EXPECT_TRUE( + tracker.WillPostTask(&task, TaskShutdownBehavior::BLOCK_SHUTDOWN)); + scoped_refptr<Sequence> sequence = test::CreateSequenceWithTask( + std::move(task), TaskTraits(TaskPriority::BEST_EFFORT, + TaskShutdownBehavior::BLOCK_SHUTDOWN)); + EXPECT_FALSE( + tracker.WillScheduleSequence(sequence->BeginTransaction(), &observer)); + preempted_sequences.push_back(std::move(sequence)); + + // Wait to be sure that tasks have different |sequenced_time|. + PlatformThread::Sleep(TestTimeouts::tiny_timeout()); + } + + // Perform shutdown. Expect |preempted_sequences| to be scheduled in posting + // order. + { + testing::InSequence in_sequence; + for (auto& preempted_sequence : preempted_sequences) { + EXPECT_CALL(observer, MockOnCanScheduleSequence(preempted_sequence.get())) + .WillOnce(testing::Invoke([&tracker](Sequence* sequence) { + // Run the task to unblock shutdown. + tracker.RunAndPopNextTask(sequence, nullptr); + })); + } + tracker.Shutdown(); + } } namespace { @@ -1092,10 +1439,15 @@ TaskTraits default_traits = {}; EXPECT_TRUE(task_tracker->WillPostTask(&task_without_sync_primitives, default_traits.shutdown_behavior())); + testing::StrictMock<MockCanScheduleSequenceObserver> + never_notified_observer; auto sequence_without_sync_primitives = test::CreateSequenceWithTask( std::move(task_without_sync_primitives), default_traits); - task_tracker->RunAndPopNextTask( - std::move(sequence_without_sync_primitives)); + ASSERT_TRUE(task_tracker->WillScheduleSequence( + sequence_without_sync_primitives->BeginTransaction(), + &never_notified_observer)); + task_tracker->RunAndPopNextTask(std::move(sequence_without_sync_primitives), + &never_notified_observer); // Disallow waiting. Expect TaskTracker to allow it before running a task // with the WithBaseSyncPrimitives() trait. @@ -1113,7 +1465,11 @@ traits_with_sync_primitives.shutdown_behavior())); auto sequence_with_sync_primitives = test::CreateSequenceWithTask( std::move(task_with_sync_primitives), traits_with_sync_primitives); - task_tracker->RunAndPopNextTask(std::move(sequence_with_sync_primitives)); + ASSERT_TRUE(task_tracker->WillScheduleSequence( + sequence_with_sync_primitives->BeginTransaction(), + &never_notified_observer)); + task_tracker->RunAndPopNextTask(std::move(sequence_with_sync_primitives), + &never_notified_observer); ScopedAllowBaseSyncPrimitivesForTesting allow_wait_in_task_tracker_destructor; @@ -1143,6 +1499,7 @@ auto statistics_recorder = StatisticsRecorder::CreateTemporaryForTesting(); TaskTracker tracker("Test"); + testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; struct { const TaskTraits traits; @@ -1182,8 +1539,10 @@ HistogramTester tester; - tracker.RunAndPopNextTask( - test::CreateSequenceWithTask(std::move(task), test.traits)); + auto sequence = test::CreateSequenceWithTask(std::move(task), test.traits); + ASSERT_TRUE(tracker.WillScheduleSequence(sequence->BeginTransaction(), + &never_notified_observer)); + tracker.RunAndPopNextTask(std::move(sequence), &never_notified_observer); tester.ExpectTotalCount(test.expected_histogram, 1); } }
diff --git a/base/task/task_scheduler/test_utils.cc b/base/task/task_scheduler/test_utils.cc index f7f04bd..c9e2e57 100644 --- a/base/task/task_scheduler/test_utils.cc +++ b/base/task/task_scheduler/test_utils.cc
@@ -58,8 +58,9 @@ scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode( test::ExecutionMode execution_mode, - MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate, - const TaskTraits& traits) { + MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate) { + // Allow tasks posted to the returned TaskRunner to wait on a WaitableEvent. + const TaskTraits traits = {WithBaseSyncPrimitives()}; switch (execution_mode) { case test::ExecutionMode::PARALLEL: return CreateTaskRunnerWithTraits(traits, @@ -162,11 +163,6 @@ worker_pool_ = worker_pool; } -void ShutdownTaskTracker(TaskTracker* task_tracker) { - task_tracker->StartShutdown(); - task_tracker->CompleteShutdown(); -} - } // namespace test } // namespace internal } // namespace base
diff --git a/base/task/task_scheduler/test_utils.h b/base/task/task_scheduler/test_utils.h index 97b80c3..bd82a22 100644 --- a/base/task/task_scheduler/test_utils.h +++ b/base/task/task_scheduler/test_utils.h
@@ -98,8 +98,7 @@ // Caveat: this does not support ExecutionMode::SINGLE_THREADED. scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode( test::ExecutionMode execution_mode, - MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate, - const TaskTraits& traits = TaskTraits()); + MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate); scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits( const TaskTraits& traits, @@ -111,9 +110,6 @@ void WaitWithoutBlockingObserver(WaitableEvent* event); -// Calls StartShutdown() and CompleteShutdown() on |task_tracker|. -void ShutdownTaskTracker(TaskTracker* task_tracker); - } // namespace test } // namespace internal } // namespace base
diff --git a/base/test/task_scheduler_test_helpers_android.cc b/base/test/task_scheduler_test_helpers_android.cc index 2e935a0..99471fda25 100644 --- a/base/test/task_scheduler_test_helpers_android.cc +++ b/base/test/task_scheduler_test_helpers_android.cc
@@ -19,7 +19,8 @@ // static void TaskSchedulerTestHelpers::SetTaskSchedulerExecutionFenceEnabledForTesting( bool execution_fence_enabled) { - TaskScheduler::GetInstance()->SetCanRun(!execution_fence_enabled); + TaskScheduler::GetInstance()->SetExecutionFenceEnabled( + execution_fence_enabled); } } // namespace base
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index c4393ff..b4c72e2 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8916765319702380096 \ No newline at end of file +8916737669163559168 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 5a0d165..5a44181d 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8916772086441183392 \ No newline at end of file +8916742152396029840 \ No newline at end of file
diff --git a/build/util/android_chrome_version.py b/build/util/android_chrome_version.py index f183441..5628f1a 100644 --- a/build/util/android_chrome_version.py +++ b/build/util/android_chrome_version.py
@@ -113,11 +113,11 @@ """ ARCH64_APK_VARIANTS = { '64_32': { - 'PACKAGES': frozenset(['MONOCHROME']), + 'PACKAGES': frozenset(['MONOCHROME', 'TRICHROME']), 'MODIFIER': 10 }, '64': { - 'PACKAGES': frozenset(['MONOCHROME']), + 'PACKAGES': frozenset(['MONOCHROME', 'TRICHROME']), 'MODIFIER': 20 } }
diff --git a/build/util/android_chrome_version_test.py b/build/util/android_chrome_version_test.py index ad3c5ca1..5e743d3 100644 --- a/build/util/android_chrome_version_test.py +++ b/build/util/android_chrome_version_test.py
@@ -172,9 +172,13 @@ self.EXAMPLE_VERSION_VALUES, arch='arm64', is_next_build=False) arch_monochrome_64_32_version_code = output['MONOCHROME_64_32_VERSION_CODE'] arch_monochrome_64_version_code = output['MONOCHROME_64_VERSION_CODE'] + arch_trichrome_64_32_version_code = output['TRICHROME_64_32_VERSION_CODE'] + arch_trichrome_64_version_code = output['TRICHROME_64_VERSION_CODE'] self.assertEqual(arch_monochrome_64_32_version_code, '372000042') self.assertEqual(arch_monochrome_64_version_code, '372000052') + self.assertEqual(arch_trichrome_64_32_version_code, '372000043') + self.assertEqual(arch_trichrome_64_version_code, '372000053') def testGenerateVersionCodesAndroidArchX64(self): """Assert it handles different architectures correctly. @@ -200,9 +204,13 @@ self.EXAMPLE_VERSION_VALUES, arch='x64', is_next_build=False) arch_monochrome_64_32_version_code = output['MONOCHROME_64_32_VERSION_CODE'] arch_monochrome_64_version_code = output['MONOCHROME_64_VERSION_CODE'] + arch_trichrome_64_32_version_code = output['TRICHROME_64_32_VERSION_CODE'] + arch_trichrome_64_version_code = output['TRICHROME_64_VERSION_CODE'] self.assertEqual(arch_monochrome_64_32_version_code, '372000072') self.assertEqual(arch_monochrome_64_version_code, '372000082') + self.assertEqual(arch_trichrome_64_32_version_code, '372000073') + self.assertEqual(arch_trichrome_64_version_code, '372000083') def testGenerateVersionCodesAndroidArchOrderArm(self): """Assert it handles different architectures correctly.
diff --git a/build/util/version.gni b/build/util/version.gni index 0bcae72..a28f2e46 100644 --- a/build/util/version.gni +++ b/build/util/version.gni
@@ -51,7 +51,9 @@ if (target_cpu == "arm64" || target_cpu == "x64") { _version_dictionary_template += "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" " + - "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" " + "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" " + + "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" " + + "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" " } _script_arguments += [ @@ -96,16 +98,18 @@ } else if (target_os == "android") { forward_variables_from(_result, [ - "chrome_version_code", "chrome_modern_version_code", - "monochrome_version_code", - "trichrome_version_code", - "notouch_chrome_version_code", - "webview_stable_version_code", - "webview_beta_version_code", - "webview_dev_version_code", + "chrome_version_code", "monochrome_64_32_version_code", "monochrome_64_version_code", + "monochrome_version_code", + "notouch_chrome_version_code", + "trichrome_64_32_version_code", + "trichrome_64_version_code", + "trichrome_version_code", + "webview_beta_version_code", + "webview_dev_version_code", + "webview_stable_version_code", ]) chrome_version_name = chrome_version_full @@ -126,6 +130,8 @@ lines_to_write += [ "Monochrome_64_32=$monochrome_64_32_version_code", "Monochrome_64=$monochrome_64_version_code", + "TrichromeChrome_64_32=$trichrome_64_32_version_code", + "TrichromeChrome_64=$trichrome_64_version_code", ] }
diff --git a/build/util/version_test.py b/build/util/version_test.py index 290d026..2a65ddc7 100644 --- a/build/util/version_test.py +++ b/build/util/version_test.py
@@ -120,7 +120,9 @@ new_template = ( self._EXAMPLE_ANDROID_TEMPLATE + "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" " - "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" ") + "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" " + "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" " + "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" ") args_with_template = _ReplaceArgs(self._EXAMPLE_ANDROID_ARGS, ['-t', new_template]) new_args = _ReplaceArgs(args_with_template, ['-a', 'arm64']) @@ -131,13 +133,19 @@ r'\bmonochrome_64_32_version_code = "\d+"\s') self.assertRegexpMatches(contents, r'\bmonochrome_64_version_code = "\d+"\s') + self.assertRegexpMatches(contents, + r'\btrichrome_64_32_version_code = "\d+"\s') + self.assertRegexpMatches(contents, + r'\btrichrome_64_version_code = "\d+"\s') def testBuildOutputAndroidArchVariantsX64(self): """Assert 64-bit-specific version codes""" new_template = ( self._EXAMPLE_ANDROID_TEMPLATE + "monochrome_64_32_version_code = \"@MONOCHROME_64_32_VERSION_CODE@\" " - "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" ") + "monochrome_64_version_code = \"@MONOCHROME_64_VERSION_CODE@\" " + "trichrome_64_32_version_code = \"@TRICHROME_64_32_VERSION_CODE@\" " + "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" ") args_with_template = _ReplaceArgs(self._EXAMPLE_ANDROID_ARGS, ['-t', new_template]) new_args = _ReplaceArgs(args_with_template, ['-a', 'x64']) @@ -148,6 +156,10 @@ r'\bmonochrome_64_32_version_code = "\d+"\s') self.assertRegexpMatches(contents, r'\bmonochrome_64_version_code = "\d+"\s') + self.assertRegexpMatches(contents, + r'\btrichrome_64_32_version_code = "\d+"\s') + self.assertRegexpMatches(contents, + r'\btrichrome_64_version_code = "\d+"\s') def testBuildOutputAndroidChromeArchInput(self): """Assert it raises an exception when using an invalid architecture input"""
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 70f0024..54907fe 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -47,7 +47,7 @@ opacity(1.f), blend_mode(SkBlendMode::kSrcOver), is_root_for_isolated_group(false), - hit_testable_without_draws_content(false), + hit_testable(false), contents_opaque(false), is_drawable(false), double_sided(true), @@ -741,15 +741,19 @@ SetNeedsCommit(); } -void Layer::SetHitTestableWithoutDrawsContent(bool should_hit_test) { +void Layer::SetHitTestable(bool should_hit_test) { DCHECK(IsPropertyChangeAllowed()); - if (inputs_.hit_testable_without_draws_content == should_hit_test) + if (inputs_.hit_testable == should_hit_test) return; - inputs_.hit_testable_without_draws_content = should_hit_test; + inputs_.hit_testable = should_hit_test; SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } +bool Layer::HitTestable() const { + return inputs_.hit_testable; +} + void Layer::SetContentsOpaque(bool opaque) { DCHECK(IsPropertyChangeAllowed()); if (inputs_.contents_opaque == opaque) @@ -1423,8 +1427,7 @@ layer->SetScrollTreeIndex(scroll_tree_index()); layer->SetOffsetToTransformParent(offset_to_transform_parent_); layer->SetDrawsContent(DrawsContent()); - layer->SetHitTestableWithoutDrawsContent( - hit_testable_without_draws_content()); + layer->SetHitTestable(HitTestable()); // subtree_property_changed_ is propagated to all descendants while building // property trees. So, it is enough to check it only for the current layer. if (subtree_property_changed_)
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 826ba6f..8fca418 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -336,15 +336,9 @@ void SetContentsOpaque(bool opaque); bool contents_opaque() const { return inputs_.contents_opaque; } - // Set or get whether this layer should be a hit test target even if not - // visible. Normally if DrawsContent() is false, making the layer not - // contribute to the final composited output, the layer will not be eligable - // for hit testing since it is invisible. Set this to true to allow the layer - // to be hit tested regardless. - void SetHitTestableWithoutDrawsContent(bool should_hit_test); - bool hit_testable_without_draws_content() const { - return inputs_.hit_testable_without_draws_content; - } + // Set or get whether this layer should be a hit test target + void SetHitTestable(bool should_hit_test); + bool HitTestable() const; // Set or gets if this layer is a container for fixed position layers in its // subtree. Such layers will be positioned and transformed relative to this @@ -936,10 +930,8 @@ bool is_root_for_isolated_group : 1; - // Hit testing depends on draws_content (see: |LayerImpl::should_hit_test|) - // and this bit can be set to cause the LayerImpl to be hit testable without - // draws_content. - bool hit_testable_without_draws_content : 1; + // Hit testing depends on this bit. + bool hit_testable : 1; bool contents_opaque : 1;
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 0d9d4fb..36a262b3 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -63,7 +63,7 @@ should_check_backface_visibility_(false), draws_content_(false), contributes_to_drawn_render_surface_(false), - hit_testable_without_draws_content_(false), + hit_testable_(false), is_resized_by_browser_controls_(false), viewport_layer_type_(NOT_VIEWPORT_LAYER), background_color_(0), @@ -324,8 +324,7 @@ layer->use_parent_backface_visibility_ = use_parent_backface_visibility_; layer->should_check_backface_visibility_ = should_check_backface_visibility_; layer->draws_content_ = draws_content_; - layer->hit_testable_without_draws_content_ = - hit_testable_without_draws_content_; + layer->hit_testable_ = hit_testable_; layer->non_fast_scrollable_region_ = non_fast_scrollable_region_; layer->touch_action_region_ = touch_action_region_; layer->wheel_event_handler_region_ = wheel_event_handler_region_; @@ -413,8 +412,7 @@ result->Set("Transform", std::move(list)); result->SetBoolean("DrawsContent", draws_content_); - result->SetBoolean("HitTestableWithoutDrawsContent", - hit_testable_without_draws_content_); + result->SetBoolean("HitTestable", hit_testable_); result->SetBoolean("Is3dSorted", Is3dSorted()); result->SetDouble("Opacity", Opacity()); result->SetBoolean("ContentsOpaque", contents_opaque_); @@ -607,20 +605,25 @@ NoteLayerPropertyChanged(); } -void LayerImpl::SetHitTestableWithoutDrawsContent(bool should_hit_test) { - if (hit_testable_without_draws_content_ == should_hit_test) +void LayerImpl::SetHitTestable(bool should_hit_test) { + if (hit_testable_ == should_hit_test) return; - hit_testable_without_draws_content_ = should_hit_test; + hit_testable_ = should_hit_test; NoteLayerPropertyChanged(); } -bool LayerImpl::ShouldHitTest() const { - bool should_hit_test = draws_content_; - if (GetEffectTree().Node(effect_tree_index())) - should_hit_test &= - !GetEffectTree().Node(effect_tree_index())->subtree_hidden; - should_hit_test |= hit_testable_without_draws_content_; +bool LayerImpl::HitTestable() const { + EffectTree& effect_tree = GetEffectTree(); + bool should_hit_test = hit_testable_; + // TODO(sunxd): remove or refactor SetHideLayerAndSubtree, or move this logic + // to subclasses of Layer. See https://crbug.com/595843 and + // https://crbug.com/931865. + // The bit |subtree_hidden| can only be true for ui::Layers. Other layers are + // not supposed to set this bit. + if (effect_tree.Node(effect_tree_index())) { + should_hit_test &= !effect_tree.Node(effect_tree_index())->subtree_hidden; + } return should_hit_test; }
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 8e6dd6c7..b98cfd6 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -165,15 +165,9 @@ void SetDrawsContent(bool draws_content); bool DrawsContent() const { return draws_content_; } - // Make the layer hit test (see: |should_hit_test|) even if !draws_content_. - void SetHitTestableWithoutDrawsContent(bool should_hit_test); - bool hit_testable_without_draws_content() const { - return hit_testable_without_draws_content_; - } - - // True if either the layer draws content or has been marked as hit testable - // without draws_content. - bool ShouldHitTest() const; + // Make the layer hit testable. + void SetHitTestable(bool should_hit_test); + bool HitTestable() const; LayerImplTestProperties* test_properties() { if (!test_properties_) @@ -536,10 +530,8 @@ bool draws_content_ : 1; bool contributes_to_drawn_render_surface_ : 1; - // Hit testing depends on draws_content (see: |LayerImpl::should_hit_test|) - // and this bit can be set to cause the layer to be hit testable without - // draws_content. - bool hit_testable_without_draws_content_ : 1; + // Tracks if this layer should participate in hit testing. + bool hit_testable_ : 1; bool is_resized_by_browser_controls_ : 1; // TODO(bokan): This can likely be removed after blink-gen-property-trees
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index f207739..9a6e3342 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc
@@ -1420,30 +1420,29 @@ LayerImpl::Create(host_impl_.active_tree(), 1); EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, layer_tree_host_->SetRootLayer(root_layer)); - EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(3); + EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(5); // A layer that draws content should be hit testable. root_layer->SetIsDrawable(true); + root_layer->SetHitTestable(true); root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_TRUE(impl_layer->DrawsContent()); - EXPECT_FALSE(impl_layer->hit_testable_without_draws_content()); - EXPECT_TRUE(impl_layer->ShouldHitTest()); + EXPECT_TRUE(impl_layer->HitTestable()); // A layer that does not draw content and does not hit test without drawing // content should not be hit testable. root_layer->SetIsDrawable(false); + root_layer->SetHitTestable(false); root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_FALSE(impl_layer->DrawsContent()); - EXPECT_FALSE(impl_layer->hit_testable_without_draws_content()); - EXPECT_FALSE(impl_layer->ShouldHitTest()); + EXPECT_FALSE(impl_layer->HitTestable()); // |SetHitTestableWithoutDrawsContent| should cause a layer to become hit // testable even though it does not draw content. - root_layer->SetHitTestableWithoutDrawsContent(true); + root_layer->SetHitTestable(true); root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_FALSE(impl_layer->DrawsContent()); - EXPECT_TRUE(impl_layer->hit_testable_without_draws_content()); - EXPECT_TRUE(impl_layer->ShouldHitTest()); + EXPECT_TRUE(impl_layer->HitTestable()); } void ReceiveCopyOutputResult(int* result_count,
diff --git a/cc/test/layer_tree_json_parser.cc b/cc/test/layer_tree_json_parser.cc index 8d600d5..a7819bc 100644 --- a/cc/test/layer_tree_json_parser.cc +++ b/cc/test/layer_tree_json_parser.cc
@@ -35,6 +35,14 @@ bool draws_content; success &= dict->GetBoolean("DrawsContent", &draws_content); + bool hit_testable; + // If we cannot load hit_testable, we may try loading the old version, since + // we do not record |hit_testable_without_draws_content| in the past, we use + // |draws_content| as the value of |hit_testable|. + if (!dict->GetBoolean("HitTestable", &hit_testable)) { + hit_testable = draws_content; + } + scoped_refptr<Layer> new_layer; if (layer_type == "SolidColorLayer") { new_layer = SolidColorLayer::Create(); @@ -84,6 +92,7 @@ } new_layer->SetBounds(gfx::Size(width, height)); new_layer->SetIsDrawable(draws_content); + new_layer->SetHitTestable(hit_testable); double opacity; if (dict->GetDouble("Opacity", &opacity))
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index 8526bd0..08818c80 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc
@@ -159,6 +159,7 @@ const gfx::Rect& rect, SkColor color) { scoped_refptr<SolidColorLayer> layer = SolidColorLayer::Create(); layer->SetIsDrawable(true); + layer->SetHitTestable(true); layer->SetBounds(rect.size()); layer->SetPosition(gfx::PointF(rect.origin())); layer->SetOffsetToTransformParent(
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index d2a248a..a977f6b 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -158,9 +158,11 @@ inner_viewport_container_layer->SetBounds(inner_bounds); inner_viewport_scroll_layer->SetScrollable(inner_bounds); + inner_viewport_scroll_layer->SetHitTestable(true); inner_viewport_scroll_layer->SetBounds(outer_bounds); outer_viewport_container_layer->SetBounds(outer_bounds); outer_scroll_layer->SetScrollable(outer_bounds); + outer_scroll_layer->SetHitTestable(true); inner_viewport_scroll_layer->SetIsContainerForFixedPositionLayers(true); outer_scroll_layer->SetIsContainerForFixedPositionLayers(true); @@ -184,6 +186,7 @@ outer_viewport_scroll_layer->SetBounds(scroll_bounds); outer_viewport_scroll_layer->SetIsDrawable(true); + outer_viewport_scroll_layer->SetHitTestable(true); CreateVirtualViewportLayers(root_layer, outer_viewport_scroll_layer, inner_bounds, outer_bounds, host); } @@ -906,6 +909,7 @@ initial_device_scale_factor_, viz::LocalSurfaceIdAllocation()); layer_tree_host()->root_layer()->SetIsDrawable(true); + layer_tree_host()->root_layer()->SetHitTestable(true); layer_tree_host()->SetElementIdsForTesting(); }
diff --git a/cc/trees/effect_node.h b/cc/trees/effect_node.h index 7302bcee..f9ad9713 100644 --- a/cc/trees/effect_node.h +++ b/cc/trees/effect_node.h
@@ -79,9 +79,6 @@ bool has_masking_child : 1; // Whether this node has a mask. This bit is not used when using layer lists. bool is_masked : 1; - // Whether layers associated with this node have a mask or ancestor mask that - // could affect the layer's hit testable bit. - bool hit_test_may_be_affected_by_mask : 1; // Whether this node's effect has been changed since the last // frame. Needed in order to compute damage rect. bool effect_changed : 1;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 687ab1b..59c4845 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -883,9 +883,11 @@ if (inner_viewport_scroll_delta.IsZero() && info.page_scale_delta == 1.f && info.elastic_overscroll_delta.IsZero() && !info.top_controls_delta && !info.browser_controls_constraint_changed && - !info.scroll_gesture_did_end) { + !info.scroll_gesture_did_end && + info.is_pinch_gesture_active == is_pinch_gesture_active_from_impl_) { return; } + is_pinch_gesture_active_from_impl_ = info.is_pinch_gesture_active; // Preemptively apply the scroll offset and scale delta here before sending // it to the client. If the client comes back and sets it to the same @@ -1326,11 +1328,16 @@ this, [](Layer* layer) { layer->SetNeedsDisplay(); }); } -void LayerTreeHost::SetExternalPageScaleFactor(float page_scale_factor) { - if (external_page_scale_factor_ == page_scale_factor) +void LayerTreeHost::SetExternalPageScaleFactor( + float page_scale_factor, + bool is_external_pinch_gesture_active) { + if (external_page_scale_factor_ == page_scale_factor && + is_external_pinch_gesture_active_ == is_external_pinch_gesture_active) { return; + } external_page_scale_factor_ = page_scale_factor; + is_external_pinch_gesture_active_ = is_external_pinch_gesture_active; SetNeedsCommit(); } @@ -1651,6 +1658,7 @@ host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_); host_impl->SetContentHasSlowPaths(content_has_slow_paths_); host_impl->SetContentHasNonAAPaint(content_has_non_aa_paint_); + host_impl->set_pinch_gesture_active(is_external_pinch_gesture_active_); RecordGpuRasterizationHistogram(host_impl); host_impl->SetDebugState(debug_state_);
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 85c520d..cd2c6e69 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -471,7 +471,11 @@ // 'external_page_scale_factor', a value that affects raster scale in the // same way that page_scale_factor does, but doesn't affect any geometry // calculations. - void SetExternalPageScaleFactor(float page_scale_factor); + void SetExternalPageScaleFactor(float page_scale_factor, + bool is_external_pinch_gesture_active); + bool is_external_pinch_gesture_active_for_testing() { + return is_external_pinch_gesture_active_; + } // Requests that we force send RenderFrameMetadata with the next frame. void RequestForceSendMetadata() { force_send_metadata_request_ = true; } @@ -805,6 +809,9 @@ float min_page_scale_factor_ = 1.f; float max_page_scale_factor_ = 1.f; float external_page_scale_factor_ = 1.f; + bool is_external_pinch_gesture_active_ = false; + // Used to track the out-bound state for ApplyViewportChanges. + bool is_pinch_gesture_active_from_impl_ = false; int raster_color_space_id_ = -1; gfx::ColorSpace raster_color_space_;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 72dfe949..62add2c4 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -2631,7 +2631,13 @@ // a result we do async hit test on any surface layers that bool assume_overlap = false; for (const auto* layer : base::Reversed(*active_tree())) { - if (!layer->ShouldHitTest()) + // Viz hit test needs to collect information for pointer-events: none OOPIFs + // as well. Now Layer::HitTestable ignores pointer-events property, but this + // early out will not work correctly if we integrate has_pointer_events_none + // into Layer::HitTestable, so we make sure we don't skip surface layers + // that draws content but has pointer-events: none property. + if (!(layer->HitTestable() || + (layer->is_surface_layer() && layer->DrawsContent()))) continue; if (layer->is_surface_layer()) { @@ -2639,7 +2645,8 @@ // If a surface layer is created not by child frame compositor or the // frame owner has pointer-events: none property, the surface layer // becomes not hit testable. We should not generate data for it. - if (!surface_layer->surface_hit_testable()) { + if (!surface_layer->surface_hit_testable() || + !surface_layer->range().IsValid()) { // We collect any overlapped regions that does not have pointer-events: // none. if (!surface_layer->has_pointer_events_none() && !assume_overlap) {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 8e76053..c2d3791e 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -591,6 +591,15 @@ } bool pinch_gesture_active() const { return pinch_gesture_active_; } + // Used to set the pinch gesture active state when the pinch gesture is + // handled on another layer tree. In a page with OOPIFs, only the main + // frame's layer tree directly handles pinch events. But layer trees for + // sub-frames need to know when pinch gestures are active so they can + // throttle the re-rastering. This function allows setting this flag on + // OOPIF layer trees using information sent (initially) from the main-frame. + void set_pinch_gesture_active(bool external_pinch_gesture_active) { + pinch_gesture_active_ = external_pinch_gesture_active; + } void SetTreePriority(TreePriority priority); TreePriority GetTreePriority() const; @@ -1006,6 +1015,15 @@ bool did_scroll_x_for_scroll_gesture_; bool did_scroll_y_for_scroll_gesture_; + // This value is used to allow the compositor to throttle re-rastering during + // pinch gestures, when the page scale factor may be changing frequently. It + // is set in one of two ways: + // i) In a layer tree serving the root of the frame/compositor tree, it is + // directly set during processing of GesturePinch events on the impl thread + // (only the root layer tree has access to these). + // ii) In a layer tree serving a sub-frame in the frame/compositor tree, it + // is set from the main thread during the commit process, using information + // sent from the root layer tree via IPC messaging. bool pinch_gesture_active_ = false; bool pinch_gesture_end_should_clear_scrolling_node_ = false;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 26e4d88..795737f 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -394,6 +394,7 @@ LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); inner_scroll->SetScrollable(viewport_scroll_bounds); + inner_scroll->SetHitTestable(true); inner_scroll->SetElementId( LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(content_size); @@ -408,6 +409,7 @@ std::unique_ptr<LayerImpl> outer_scroll = LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); outer_scroll->SetScrollable(content_size); + outer_scroll->SetHitTestable(true); outer_scroll->SetElementId( LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->layer_tree_impl() @@ -465,6 +467,7 @@ std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -484,15 +487,17 @@ squash1->test_properties()->opacity = 0.0f; // The transparent layer should still participate in hit testing even // through it does not draw content. - squash1->SetHitTestableWithoutDrawsContent(true); + squash1->SetHitTestable(true); } else { squash1->SetDrawsContent(true); + squash1->SetHitTestable(true); } std::unique_ptr<LayerImpl> squash2 = LayerImpl::Create(layer_tree_impl, 6); squash2->SetBounds(gfx::Size(140, 300)); squash2->test_properties()->position = gfx::PointF(220, 300); squash2->SetDrawsContent(true); + squash2->SetHitTestable(true); scroll->test_properties()->AddChild(std::move(squash2)); root->test_properties()->AddChild(std::move(scroll)); @@ -540,6 +545,7 @@ content_layer->SetBounds(content_size); host_impl_->OuterViewportScrollLayer()->SetBounds(content_size); host_impl_->OuterViewportScrollLayer()->SetScrollable(viewport_size); + host_impl_->OuterViewportScrollLayer()->SetHitTestable(true); LayerImpl* outer_clip = host_impl_->OuterViewportScrollLayer()->test_properties()->parent; @@ -552,6 +558,7 @@ inner_clip_layer->SetBounds(viewport_size); host_impl_->InnerViewportScrollLayer()->SetBounds(viewport_size); host_impl_->InnerViewportScrollLayer()->SetScrollable(viewport_size); + host_impl_->InnerViewportScrollLayer()->SetHitTestable(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); @@ -571,6 +578,7 @@ gfx::Size scroll_container_bounds = gfx::Size(size.width() / 2, size.height() / 2); layer->SetScrollable(scroll_container_bounds); + layer->SetHitTestable(true); return layer; } @@ -710,6 +718,7 @@ LayerImpl* overflow = scroll_layer->test_properties()->children[0]; overflow->SetBounds(overflow_size); overflow->SetScrollable(gfx::Size(100, 100)); + overflow->SetHitTestable(true); overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id())); overflow->layer_tree_impl() ->property_trees() @@ -1035,6 +1044,7 @@ root->SetBounds(gfx::Size(110, 110)); root->SetScrollable(gfx::Size(10, 10)); + root->SetHitTestable(true); root->SetElementId(LayerIdToElementIdForTesting(root->id())); root->layer_tree_impl() ->property_trees() @@ -1334,8 +1344,10 @@ std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); + scroll->SetHitTestable(true); std::unique_ptr<SolidColorScrollbarLayerImpl> drawn_scrollbar = SolidColorScrollbarLayerImpl::Create(layer_tree_impl, 4, VERTICAL, 10, 0, @@ -1344,12 +1356,14 @@ drawn_scrollbar->test_properties()->position = gfx::PointF(345, 0); drawn_scrollbar->SetScrollElementId(scroll->element_id()); drawn_scrollbar->SetDrawsContent(true); + drawn_scrollbar->SetHitTestable(true); drawn_scrollbar->test_properties()->opacity = 1.f; std::unique_ptr<LayerImpl> squash = LayerImpl::Create(layer_tree_impl, 5); squash->SetBounds(gfx::Size(140, 300)); squash->test_properties()->position = gfx::PointF(220, 0); squash->SetDrawsContent(true); + squash->SetHitTestable(true); scroll->test_properties()->AddChild(std::move(drawn_scrollbar)); scroll->test_properties()->AddChild(std::move(squash)); @@ -1775,6 +1789,7 @@ LayerImpl* overflow = scroll_layer->test_properties()->children[0]; overflow->SetBounds(overflow_size); overflow->SetScrollable(gfx::Size(100, 100)); + overflow->SetHitTestable(true); overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id())); overflow->layer_tree_impl() ->property_trees() @@ -1944,6 +1959,7 @@ LayerImpl* overflow = scroll_layer->test_properties()->children[0]; overflow->SetBounds(overflow_size); overflow->SetScrollable(gfx::Size(100, 100)); + overflow->SetHitTestable(true); overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id())); overflow->layer_tree_impl() ->property_trees() @@ -2386,6 +2402,7 @@ // frame (outer viewport) such that it matches the width of the content, // preventing horizontal scrolling. Replicate that behavior here. host_impl_->OuterViewportScrollLayer()->SetScrollable(outer_viewport_size); + host_impl_->OuterViewportScrollLayer()->SetHitTestable(true); LayerImpl* outer_clip = host_impl_->OuterViewportScrollLayer()->test_properties()->parent; outer_clip->SetBounds(outer_viewport_size); @@ -3990,6 +4007,7 @@ scrollbar_1_ = scrollbar_1.get(); scrollbar_1->SetScrollElementId(root_scroll->element_id()); scrollbar_1->SetDrawsContent(true); + scrollbar_1->SetHitTestable(true); scrollbar_1->SetBounds(scrollbar_size_1); TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionNone, gfx::Rect(scrollbar_size_1)); @@ -4012,12 +4030,15 @@ child->test_properties()->position = gfx::PointF(50, 50); child->SetBounds(child_layer_size); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetScrollable(gfx::Size(100, 100)); + child->SetHitTestable(true); child->SetElementId(LayerIdToElementIdForTesting(child->id())); ElementId child_element_id = child->element_id(); scrollbar_2->SetScrollElementId(child_element_id); scrollbar_2->SetDrawsContent(true); + scrollbar_2->SetHitTestable(true); scrollbar_2->SetBounds(scrollbar_size_2); scrollbar_2->SetCurrentPos(0); scrollbar_2->test_properties()->position = gfx::PointF(0, 0); @@ -4338,6 +4359,7 @@ // Check scrollbar registration on a sublayer. child->SetScrollable(viewport_size); + child->SetHitTestable(true); child->SetElementId(LayerIdToElementIdForTesting(child->id())); ElementId child_scroll_element_id = child->element_id(); root_scroll->test_properties()->AddChild(std::move(child)); @@ -5920,6 +5942,7 @@ LayerImpl::Create(host_impl_->active_tree(), id + 2); child->SetScrollable(sub_content_layer_size); + child->SetHitTestable(true); child->SetElementId(LayerIdToElementIdForTesting(child->id())); child->SetBounds(sub_content_size); child->test_properties()->position = gfx::PointF(); @@ -6474,6 +6497,7 @@ std::unique_ptr<LayerImpl> scroll_layer = LayerImpl::Create(host_impl_->active_tree(), 12); scroll_layer->SetScrollable(surface_size); + scroll_layer->SetHitTestable(true); scroll_layer->SetElementId(LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(contents_size); scroll_layer->test_properties()->position = gfx::PointF(); @@ -7382,6 +7406,7 @@ gfx::Size(child->bounds().width(), child->bounds().height() / 2); clip_layer->SetBounds(scroll_container_bounds); child->SetScrollable(scroll_container_bounds); + child->SetHitTestable(true); // The rotation depends on the layer's transform origin, and the child layer // is a different size than the clip, so make sure the clip layer's origin // lines up over the child. @@ -7615,6 +7640,7 @@ scroll_layer->test_properties()->parent->test_properties()->parent; clip_layer->SetBounds(gfx::Size(10, 20)); scroll_layer->SetScrollable(gfx::Size(10, 20)); + scroll_layer->SetHitTestable(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->BindToClient(&scroll_watcher); @@ -7728,6 +7754,7 @@ scroll_layer->test_properties()->parent->test_properties()->parent; clip_layer->SetBounds(gfx::Size(10, 20)); scroll_layer->SetScrollable(gfx::Size(10, 20)); + scroll_layer->SetHitTestable(true); scroll_layer->SetDrawsContent(true); // Draw first frame to clear any pending draws and check scroll. @@ -8148,6 +8175,7 @@ clip_layer->SetBounds(gfx::Size(50, 50)); scroll_layer->SetScrollable(gfx::Size(50, 50)); + scroll_layer->SetHitTestable(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50)); @@ -8256,6 +8284,7 @@ std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -8377,6 +8406,7 @@ std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollable(viewport_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -8465,12 +8495,14 @@ std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 13); scroll2->SetBounds(gfx::Size(500, 500)); scroll2->SetScrollable(gfx::Size(300, 300)); + scroll2->SetHitTestable(true); scroll2->SetElementId(LayerIdToElementIdForTesting(scroll2->id())); scroll2->SetDrawsContent(true); @@ -8588,6 +8620,7 @@ std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(1200, 1200)); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -8599,6 +8632,7 @@ std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 15); scroll2->SetBounds(gfx::Size(1200, 1200)); scroll2->SetScrollable(gfx::Size(600, 600)); + scroll2->SetHitTestable(true); scroll2->SetElementId(LayerIdToElementIdForTesting(scroll2->id())); scroll2->SetDrawsContent(true); @@ -9842,6 +9876,7 @@ gfx::ScrollOffset scroll_offset(100000, 0); scrolling_layer->SetScrollable(content_layer_bounds); + scrolling_layer->SetHitTestable(true); scrolling_layer->SetElementId( LayerIdToElementIdForTesting(scrolling_layer->id())); host_impl_->pending_tree()->BuildPropertyTreesForTesting(); @@ -10346,6 +10381,7 @@ LayerImpl* scroll_layer = host_impl_->active_tree()->LayerById(scroll_layer_id); scroll_layer->SetDrawsContent(true); + scroll_layer->SetHitTestable(true); int page_scale_layer_id = 5; LayerImpl* page_scale_layer = @@ -10355,6 +10391,7 @@ std::unique_ptr<LayerImpl> occluder_layer = LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id); occluder_layer->SetDrawsContent(true); + occluder_layer->SetHitTestable(true); occluder_layer->SetBounds(content_size); occluder_layer->test_properties()->position = gfx::PointF(); @@ -10382,11 +10419,13 @@ LayerImpl* scroll_layer = host_impl_->active_tree()->LayerById(scroll_layer_id); scroll_layer->SetDrawsContent(true); + scroll_layer->SetHitTestable(true); int occluder_layer_id = 6; std::unique_ptr<LayerImpl> occluder_layer = LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id); occluder_layer->SetDrawsContent(true); + occluder_layer->SetHitTestable(true); occluder_layer->SetBounds(content_size); occluder_layer->test_properties()->position = gfx::PointF(-10.f, -10.f); @@ -11255,6 +11294,7 @@ std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(scroll_content_size); scroll->SetScrollable(root_layer_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -11323,6 +11363,7 @@ LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); inner_scroll->SetScrollable(inner_viewport); + inner_scroll->SetHitTestable(true); inner_scroll->SetElementId( LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(outer_viewport); @@ -11337,6 +11378,7 @@ std::unique_ptr<LayerImpl> outer_scroll = LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); outer_scroll->SetScrollable(outer_viewport); + outer_scroll->SetHitTestable(true); outer_scroll->SetElementId( LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->layer_tree_impl() @@ -13567,6 +13609,7 @@ child->SetBounds(child_layer_size); child->SetDrawsContent(true); child->SetScrollable(gfx::Size(100, 100)); + child->SetHitTestable(true); child->SetElementId(LayerIdToElementIdForTesting(child->id())); ElementId child_element_id = child->element_id(); @@ -14221,16 +14264,19 @@ rotate.Rotate(45); surface_child1->test_properties()->transform = rotate; surface_child1->SetDrawsContent(true); + surface_child1->SetHitTestable(true); surface_child1->SetSurfaceHitTestable(true); surface_child2->test_properties()->position = gfx::PointF(450, 300); surface_child2->SetBounds(gfx::Size(100, 100)); surface_child2->SetDrawsContent(true); + surface_child2->SetHitTestable(true); surface_child2->SetSurfaceHitTestable(true); overlapping_layer->test_properties()->position = gfx::PointF(500, 350); overlapping_layer->SetBounds(gfx::Size(200, 200)); overlapping_layer->SetDrawsContent(true); + overlapping_layer->SetHitTestable(true); viz::LocalSurfaceId child_local_surface_id(2, base::UnguessableToken::Create()); @@ -14327,12 +14373,14 @@ surface_child1->test_properties()->position = gfx::PointF(0, 0); surface_child1->SetBounds(gfx::Size(100, 100)); surface_child1->SetDrawsContent(true); + surface_child1->SetHitTestable(true); surface_child1->SetSurfaceHitTestable(true); surface_child1->SetHasPointerEventsNone(false); surface_child2->test_properties()->position = gfx::PointF(50, 50); surface_child2->SetBounds(gfx::Size(100, 100)); surface_child2->SetDrawsContent(true); + surface_child2->SetHitTestable(true); surface_child2->SetSurfaceHitTestable(false); surface_child2->SetHasPointerEventsNone(true); @@ -14405,6 +14453,7 @@ surface_child->test_properties()->position = gfx::PointF(0, 0); surface_child->SetBounds(gfx::Size(100, 100)); surface_child->SetDrawsContent(true); + surface_child->SetHitTestable(true); surface_child->SetSurfaceHitTestable(true); surface_child->SetHasPointerEventsNone(false); @@ -14430,6 +14479,7 @@ layer->test_properties()->position = gfx::PointF(110, 110); layer->SetBounds(gfx::Size(1, 1)); layer->SetDrawsContent(true); + layer->SetHitTestable(true); host_impl_->active_tree() ->root_layer_for_testing() ->test_properties() @@ -14469,6 +14519,93 @@ hit_test_region_list->regions[0].rect.ToString()); } +TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, InvalidFrameSinkId) { + // Setup surface layers in LayerTreeHostImpl. + host_impl_->CreatePendingTree(); + host_impl_->ActivateSyncTree(); + + // The structure of the layer tree: + // +-Root (1024x768) + // +---surface_child1 (0, 0), 100x100 + // +---surface_child2 (0, 0), 50x50, frame_sink_id = (0, 0) + std::unique_ptr<SurfaceLayerImpl> surface_child1 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 2); + + host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(1024, 768)); + + surface_child1->test_properties()->position = gfx::PointF(0, 0); + surface_child1->SetBounds(gfx::Size(100, 100)); + surface_child1->SetDrawsContent(true); + surface_child1->SetHitTestable(true); + surface_child1->SetSurfaceHitTestable(true); + surface_child1->SetHasPointerEventsNone(false); + + viz::LocalSurfaceId child_local_surface_id(2, + base::UnguessableToken::Create()); + viz::FrameSinkId frame_sink_id(2, 0); + viz::SurfaceId child_surface_id(frame_sink_id, child_local_surface_id); + surface_child1->SetRange(viz::SurfaceRange(base::nullopt, child_surface_id), + base::nullopt); + + std::unique_ptr<SurfaceLayerImpl> surface_child2 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 3); + + surface_child2->test_properties()->position = gfx::PointF(0, 0); + surface_child2->SetBounds(gfx::Size(50, 50)); + surface_child2->SetDrawsContent(true); + surface_child2->SetHitTestable(true); + surface_child2->SetSurfaceHitTestable(true); + surface_child2->SetHasPointerEventsNone(false); + + surface_child2->SetRange(viz::SurfaceRange(base::nullopt, viz::SurfaceId()), + base::nullopt); + + std::unique_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child1)); + + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child2)); + + constexpr gfx::Rect kFrameRect(0, 0, 1024, 768); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + host_impl_->active_tree()->UpdateDrawProperties(); + base::Optional<viz::HitTestRegionList> hit_test_region_list = + host_impl_->BuildHitTestData(); + // Generating HitTestRegionList should have been enabled for this test. + ASSERT_TRUE(hit_test_region_list); + + uint32_t expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestMine; + EXPECT_EQ(expected_flags, hit_test_region_list->flags); + EXPECT_EQ(kFrameRect, hit_test_region_list->bounds); + EXPECT_EQ(1u, hit_test_region_list->regions.size()); + + EXPECT_EQ(child_surface_id.frame_sink_id(), + hit_test_region_list->regions[0].frame_sink_id); + // We do not populate hit test region for a surface layer with invalid frame + // sink id to avoid deserialization failure. Instead we make the overlapping + // hit test region kHitTestAsk. + expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestChildSurface | + viz::HitTestRegionFlags::kHitTestAsk; + EXPECT_EQ(expected_flags, hit_test_region_list->regions[0].flags); + gfx::Transform child1_transform; + EXPECT_TRUE(child1_transform.ApproximatelyEqual( + hit_test_region_list->regions[0].transform)); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + hit_test_region_list->regions[0].rect.ToString()); +} + TEST_F(LayerTreeHostImplTest, ImplThreadPhaseUponImplSideInvalidation) { LayerTreeSettings settings = DefaultSettings(); CreateHostImpl(settings, CreateLayerTreeFrameSink());
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index 6a6f99b..667f67d 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -599,6 +599,7 @@ child_layer_->SetIsDrawable(true); child_layer_->SetScrollable(root_layer->bounds()); + child_layer_->SetHitTestable(true); child_layer_->SetElementId( LayerIdToElementIdForTesting(child_layer_->id())); child_layer_->SetBounds(root_scroll_layer_->bounds()); @@ -1130,6 +1131,7 @@ switch (layer_tree_host()->SourceFrameNumber()) { case 0: scroll_layer->SetScrollable(root->bounds()); + scroll_layer->SetHitTestable(true); // Set max_scroll_offset = (100, 100). scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 100, root->bounds().height() + 100)); @@ -1410,6 +1412,7 @@ scroll_layer->SetPosition(gfx::PointF()); scroll_layer->SetIsDrawable(true); scroll_layer->SetScrollable(parent->bounds()); + scroll_layer->SetHitTestable(true); scroll_layer->SetElementId( LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(gfx::Size(parent->bounds().width() + 100,
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 76d41d91..8202fa0 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -2133,10 +2133,7 @@ } struct HitTestVisibleScrollableOrTouchableFunctor { - bool operator()(LayerImpl* layer) const { - return layer->scrollable() || layer->ShouldHitTest() || - !layer->touch_action_region().region().IsEmpty(); - } + bool operator()(LayerImpl* layer) const { return layer->HitTestable(); } }; LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint(
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc index c752ebca..e703093 100644 --- a/cc/trees/layer_tree_impl_unittest.cc +++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -77,6 +77,7 @@ root->test_properties()->sorting_context_id = root_sorting_context; root->SetBounds(bounds); root->SetDrawsContent(true); + root->SetHitTestable(true); } { gfx::Transform translate_z; @@ -86,6 +87,7 @@ left_child_sorting_context; left_child->SetBounds(bounds); left_child->SetDrawsContent(true); + left_child->SetHitTestable(true); left_child->test_properties()->should_flatten_transform = false; } { @@ -96,6 +98,7 @@ right_child_sorting_context; right_child->SetBounds(bounds); right_child->SetDrawsContent(true); + right_child->SetHitTestable(true); } root->test_properties()->AddChild(std::move(left_child)); @@ -124,6 +127,7 @@ LayerImpl* root = root_layer(); root->SetBounds(bounds); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -163,6 +167,7 @@ LayerImpl* root = root_layer(); root->SetBounds(bounds); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -185,12 +190,14 @@ LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); // Create hud and add it as a child of root. std::unique_ptr<HeadsUpDisplayLayerImpl> hud = HeadsUpDisplayLayerImpl::Create(host_impl().active_tree(), 11111); hud->SetBounds(gfx::Size(200, 200)); hud->SetDrawsContent(true); + hud->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(hud->bounds()); host_impl().active_tree()->set_hud_layer(hud.get()); @@ -239,6 +246,7 @@ root->test_properties()->transform = uninvertible_transform; root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -295,6 +303,7 @@ test_layer->test_properties()->position = gfx::PointF(50.f, 50.f); test_layer->SetBounds(gfx::Size(100, 100)); test_layer->SetDrawsContent(true); + test_layer->SetHitTestable(true); root_layer()->test_properties()->AddChild(std::move(test_layer)); } @@ -343,6 +352,7 @@ root->test_properties()->transform = rotation45_degrees_about_center; root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -414,6 +424,7 @@ LayerImpl::Create(host_impl().active_tree(), 5); test->SetBounds(gfx::Size(100, 100)); test->SetDrawsContent(true); + test->SetHitTestable(true); clip->test_properties()->AddChild(std::move(test)); scale->test_properties()->AddChild(std::move(clip)); @@ -445,12 +456,14 @@ child1->SetBounds(gfx::Size(25, 25)); child1->SetMasksToBounds(true); child1->SetDrawsContent(true); + child1->SetHitTestable(true); std::unique_ptr<LayerImpl> child2 = LayerImpl::Create(host_impl().active_tree(), 3); child2->SetBounds(gfx::Size(75, 75)); child2->SetMasksToBounds(true); child2->SetDrawsContent(true); + child2->SetHitTestable(true); root->test_properties()->AddChild(std::move(child1)); root->test_properties()->AddChild(std::move(child2)); @@ -480,6 +493,7 @@ (perspective_projection_about_center * translation_by_z); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -535,6 +549,7 @@ child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); + child->SetHitTestable(true); clipping_layer->test_properties()->AddChild(std::move(child)); root->test_properties()->AddChild(std::move(clipping_layer)); } @@ -629,6 +644,7 @@ rotated_leaf->SetBounds(gfx::Size(100, 100)); rotated_leaf->test_properties()->transform = rotated_leaf_transform; rotated_leaf->SetDrawsContent(true); + rotated_leaf->SetHitTestable(true); grand_child->test_properties()->AddChild(std::move(rotated_leaf)); child->test_properties()->AddChild(std::move(grand_child)); @@ -712,6 +728,7 @@ gfx::PointF(60.f, 60.f); // 70, 70 in screen spae child->SetBounds(gfx::Size(20, 20)); child->SetDrawsContent(true); + child->SetHitTestable(true); intermediate_layer->test_properties()->AddChild(std::move(child)); root->test_properties()->AddChild(std::move(intermediate_layer)); } @@ -754,6 +771,7 @@ LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { // child 1 and child2 are initialized to overlap between x=50 and x=60. // grand_child is set to overlap both child1 and child2 between y=50 and @@ -771,10 +789,12 @@ child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); + child1->SetHitTestable(true); child2->test_properties()->position = gfx::PointF(50.f, 10.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); + child2->SetHitTestable(true); // Remember that grand_child is positioned with respect to its parent (i.e. // child1). In screen space, the intended position is (10, 50), with size @@ -782,6 +802,7 @@ grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); + grand_child1->SetHitTestable(true); child1->test_properties()->AddChild(std::move(grand_child1)); root->test_properties()->AddChild(std::move(child1)); @@ -898,6 +919,7 @@ LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); root->test_properties()->should_flatten_transform = false; root->test_properties()->sorting_context_id = 1; { @@ -917,6 +939,7 @@ child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); + child1->SetHitTestable(true); child1->test_properties()->should_flatten_transform = false; child1->test_properties()->sorting_context_id = 1; @@ -926,6 +949,7 @@ translate_z.Translate3d(0, 0, 10.f); child2->test_properties()->transform = translate_z; child2->SetDrawsContent(true); + child2->SetHitTestable(true); child2->test_properties()->should_flatten_transform = false; child2->test_properties()->sorting_context_id = 1; @@ -935,6 +959,7 @@ grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); + grand_child1->SetHitTestable(true); grand_child1->test_properties()->should_flatten_transform = false; child1->test_properties()->AddChild(std::move(grand_child1)); @@ -1008,6 +1033,7 @@ LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 2); @@ -1017,11 +1043,13 @@ child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetMasksToBounds(true); grand_child->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child->SetBounds(gfx::Size(100, 50)); grand_child->SetDrawsContent(true); + grand_child->SetHitTestable(true); grand_child->test_properties()->force_render_surface = true; // This should let |grand_child| "escape" |child|'s clip. @@ -1049,6 +1077,7 @@ LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 2); @@ -1060,10 +1089,12 @@ child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetMasksToBounds(true); scroll_child->SetBounds(gfx::Size(200, 200)); scroll_child->SetDrawsContent(true); + scroll_child->SetHitTestable(true); // This should cause scroll child and its descendants to be affected by // |child|'s clip. @@ -1071,6 +1102,7 @@ grand_child->SetBounds(gfx::Size(200, 200)); grand_child->SetDrawsContent(true); + grand_child->SetHitTestable(true); grand_child->test_properties()->force_render_surface = true; scroll_child->test_properties()->AddChild(std::move(grand_child)); @@ -1097,6 +1129,7 @@ LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { // child 1 and child2 are initialized to overlap between x=50 and x=60. // grand_child is set to overlap both child1 and child2 between y=50 and @@ -1114,11 +1147,13 @@ child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); + child1->SetHitTestable(true); child1->test_properties()->force_render_surface = true; child2->test_properties()->position = gfx::PointF(50.f, 10.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); + child2->SetHitTestable(true); child2->test_properties()->force_render_surface = true; // Remember that grand_child is positioned with respect to its parent (i.e. @@ -1127,6 +1162,7 @@ grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); + grand_child1->SetHitTestable(true); grand_child1->test_properties()->force_render_surface = true; child1->test_properties()->AddChild(std::move(grand_child1)); @@ -1218,6 +1254,7 @@ LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -1295,6 +1332,7 @@ root->test_properties()->transform = uninvertible_transform; root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); root->SetTouchActionRegion(touch_action_region); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); @@ -1365,6 +1403,7 @@ test_layer->test_properties()->position = gfx::PointF(50.f, 50.f); test_layer->SetBounds(gfx::Size(100, 100)); test_layer->SetDrawsContent(true); + test_layer->SetHitTestable(true); test_layer->SetTouchActionRegion(touch_action_region); root_layer()->test_properties()->AddChild(std::move(test_layer)); } @@ -1434,6 +1473,7 @@ test_layer->test_properties()->position = gfx::PointF(25.f, 25.f); test_layer->SetBounds(gfx::Size(50, 50)); test_layer->SetDrawsContent(true); + test_layer->SetHitTestable(true); test_layer->SetTouchActionRegion(touch_action_region); root->test_properties()->AddChild(std::move(test_layer)); } @@ -1579,6 +1619,7 @@ child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetTouchActionRegion(touch_action_region); clipping_layer->test_properties()->AddChild(std::move(child)); root->test_properties()->AddChild(std::move(clipping_layer)); @@ -1663,6 +1704,7 @@ child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetTouchActionRegion(touch_action_region); clipping_layer->test_properties()->AddChild(std::move(child)); surface->test_properties()->AddChild(std::move(clipping_layer)); @@ -1723,6 +1765,7 @@ // layer is located. touch_layer->SetBounds(gfx::Size(50, 50)); touch_layer->SetDrawsContent(true); + touch_layer->SetHitTestable(true); TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionNone, gfx::Rect(0, 0, 50, 50)); touch_layer->SetTouchActionRegion(touch_action_region); @@ -1737,6 +1780,7 @@ notouch_layer->test_properties()->position = gfx::PointF(0, 25); notouch_layer->SetBounds(gfx::Size(50, 50)); notouch_layer->SetDrawsContent(true); + notouch_layer->SetHitTestable(true); root->test_properties()->AddChild(std::move(notouch_layer)); } @@ -1789,6 +1833,7 @@ LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionNone, gfx::Rect(10, 10, 30, 30)); @@ -1796,6 +1841,7 @@ LayerImpl::Create(host_impl().active_tree(), 12345); test_layer->SetBounds(gfx::Size(50, 50)); test_layer->SetDrawsContent(false); + test_layer->SetHitTestable(false); test_layer->SetTouchActionRegion(touch_action_region); root->test_properties()->AddChild(std::move(test_layer)); } @@ -2259,6 +2305,7 @@ root->test_properties()->transform = translate_z; root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); } { gfx::Transform translate_z; @@ -2266,6 +2313,7 @@ left_child->test_properties()->transform = translate_z; left_child->SetBounds(gfx::Size(100, 100)); left_child->SetDrawsContent(true); + left_child->SetHitTestable(true); } { gfx::Transform translate_z;
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 0ed2742f..9801773 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -830,17 +830,9 @@ // Reset to false when a node is first met. We'll set the bit later // when we actually encounter a masking child. node->has_masking_child = false; - if (node->blend_mode == SkBlendMode::kDstIn) + if (node->blend_mode == SkBlendMode::kDstIn) { + DCHECK(parent_node->has_render_surface); parent_node->has_masking_child = true; -} - -void EffectTree::UpdateHitTestMayBeAffectedByMask(EffectNode* node, - EffectNode* parent_node) { - node->hit_test_may_be_affected_by_mask = - node->is_masked || node->has_masking_child; - if (parent_node) { - node->hit_test_may_be_affected_by_mask |= - parent_node->hit_test_may_be_affected_by_mask; } } @@ -920,7 +912,6 @@ UpdateEffectChanged(node, parent_node); UpdateBackfaceVisibility(node, parent_node); UpdateHasMaskingChild(node, parent_node); - UpdateHitTestMayBeAffectedByMask(node, parent_node); UpdateSurfaceContentsScale(node); } @@ -1201,8 +1192,11 @@ bool EffectTree::HitTestMayBeAffectedByMask(int effect_id) const { const EffectNode* effect_node = Node(effect_id); - if (effect_node) - return effect_node->hit_test_may_be_affected_by_mask; + for (; effect_node->id != kContentsRootNodeId; + effect_node = Node(effect_node->target_id)) { + if (effect_node->has_masking_child || effect_node->is_masked) + return true; + } return false; }
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 5fa178a..3296420 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -381,8 +381,6 @@ void UpdateIsDrawn(EffectNode* node, EffectNode* parent_node); void UpdateBackfaceVisibility(EffectNode* node, EffectNode* parent_node); void UpdateHasMaskingChild(EffectNode* node, EffectNode* parent_node); - void UpdateHitTestMayBeAffectedByMask(EffectNode* node, - EffectNode* parent_node); // Stores copy requests, keyed by node id. std::unordered_multimap<int, std::unique_ptr<viz::CopyOutputRequest>>
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index d6915c96..b278406 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -408,6 +408,7 @@ "//components/supervised_user_error_page:enums_srcjar", "//components/ui_metrics:ui_metrics_enums_java", "//chrome/browser/ui:tab_model_enums_java", + "//net:effective_connection_type_java", ":vr_build_config", ] @@ -2053,7 +2054,7 @@ } } -template("monochrome_public_bundle_tmpl") { +template("monochrome_or_trichrome_public_bundle_tmpl") { _base_module_target_name = "${invoker.target_name}__base_bundle_module" _is_trichrome = defined(invoker.use_trichrome_library) && invoker.use_trichrome_library @@ -2066,15 +2067,25 @@ } if (_is_trichrome) { - _version_code = trichrome_version_code - } else if (defined(invoker.is_64_bit_browser) && invoker.is_64_bit_browser) { - if (invoker.build_apk_secondary_abi && invoker.include_32_bit_webview) { - _version_code = monochrome_64_32_version_code + if (defined(invoker.is_64_bit_browser) && invoker.is_64_bit_browser) { + if (invoker.build_apk_secondary_abi && invoker.include_32_bit_webview) { + _version_code = trichrome_64_32_version_code + } else { + _version_code = trichrome_64_version_code + } } else { - _version_code = monochrome_64_version_code + _version_code = trichrome_version_code } } else { - _version_code = monochrome_version_code + if (defined(invoker.is_64_bit_browser) && invoker.is_64_bit_browser) { + if (invoker.build_apk_secondary_abi && invoker.include_32_bit_webview) { + _version_code = monochrome_64_32_version_code + } else { + _version_code = monochrome_64_version_code + } + } else { + _version_code = monochrome_version_code + } } _version_name = chrome_version_name @@ -2172,7 +2183,7 @@ } } -monochrome_public_bundle_tmpl("monochrome_public_bundle") { +monochrome_or_trichrome_public_bundle_tmpl("monochrome_public_bundle") { bundle_suffix = "" } @@ -2186,8 +2197,13 @@ } } +monochrome_or_trichrome_public_bundle_tmpl("trichrome_chrome_bundle") { + bundle_suffix = "" + use_trichrome_library = true +} + if (android_64bit_target_cpu) { - monochrome_public_bundle_tmpl("monochrome_64_public_bundle") { + monochrome_or_trichrome_public_bundle_tmpl("monochrome_64_public_bundle") { bundle_suffix = "64" is_64_bit_browser = true if (build_apk_secondary_abi) { @@ -2195,18 +2211,31 @@ } } - monochrome_public_bundle_tmpl("monochrome_64_32_public_bundle") { + monochrome_or_trichrome_public_bundle_tmpl("monochrome_64_32_public_bundle") { bundle_suffix = "6432" is_64_bit_browser = true if (build_apk_secondary_abi) { include_32_bit_webview = true } } -} -monochrome_public_bundle_tmpl("trichrome_chrome_bundle") { - bundle_suffix = "" - use_trichrome_library = true + monochrome_or_trichrome_public_bundle_tmpl("trichrome_64_chrome_bundle") { + bundle_suffix = "64" + is_64_bit_browser = true + use_trichrome_library = true + if (build_apk_secondary_abi) { + include_32_bit_webview = false + } + } + + monochrome_or_trichrome_public_bundle_tmpl("trichrome_64_32_chrome_bundle") { + bundle_suffix = "6432" + is_64_bit_browser = true + use_trichrome_library = true + if (build_apk_secondary_abi) { + include_32_bit_webview = true + } + } } generate_jni("chrome_jni_headers") { @@ -2363,6 +2392,7 @@ "java/src/org/chromium/chrome/browser/metrics/UmaUtils.java", "java/src/org/chromium/chrome/browser/metrics/VariationsSession.java", "java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java", + "java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProvider.java", "java/src/org/chromium/chrome/browser/net/spdyproxy/DataReductionProxySettings.java", "java/src/org/chromium/chrome/browser/notifications/ActionInfo.java", "java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 475f705..0f2aa90f 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -944,6 +944,8 @@ "java/src/org/chromium/chrome/browser/native_page/NativePageHost.java", "java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegate.java", "java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java", + "java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityObserver.java", + "java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProvider.java", "java/src/org/chromium/chrome/browser/net/spdyproxy/DataReductionProxySettings.java", "java/src/org/chromium/chrome/browser/nfc/BeamCallback.java", "java/src/org/chromium/chrome/browser/nfc/BeamController.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 3650ab8..17b1e3a2 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -114,6 +114,7 @@ "junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTitleUpdatedTest.java", "junit/src/org/chromium/chrome/browser/metrics/VariationsSessionTest.java", "junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java", + "junit/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProviderTest.java", "junit/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeUnitTest.java", "junit/src/org/chromium/chrome/browser/notifications/NotificationSystemStatusUtilUnitTest.java", "junit/src/org/chromium/chrome/browser/notifications/NotificationTriggerBackgroundTaskTest.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index a244711c..f8fa973 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -366,7 +366,9 @@ # depend on their respective versions of the shared library APK even # though they're functionally the same. native_lib_placeholders = [ "libdummy.so" ] - if (android_64bit_target_cpu && build_apk_secondary_abi) { + if (android_64bit_target_cpu && build_apk_secondary_abi && + (!defined(invoker.is_64_bit_browser) || !invoker.is_64_bit_browser || + invoker.include_32_bit_webview)) { secondary_native_lib_placeholders = [ "libdummy.so" ] } _pak_prefix = "trichrome_chrome"
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 07aa8ed9..77eaf16 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -132,6 +132,9 @@ android:largeHeap="false" android:manageSpaceActivity="@string/manage_space_activity" android:supportsRtl="true" + {% if (use_zygote|default(false) == 'true') %} + android:zygotePreloadName="org.chromium.content.app.ZygotePreload" + {% endif %} {% if backup_key is defined %} android:allowBackup="true" android:backupAgent="org.chromium.chrome.browser.ChromeBackupAgent" @@ -1169,6 +1172,9 @@ android:permission="{{ manifest_package }}.permission.CHILD_SERVICE" android:isolatedProcess="true" android:exported="{{sandboxed_service_exported|default(false)}}" + {% if (use_zygote|default(false) == 'true') %} + android:useAppZygote="true" + {% endif %} {% if (sandboxed_service_exported|default(false)) == 'true' %} android:externalService="true" tools:ignore="ExportedService"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java index fdb0d04..1d1c050 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -459,4 +459,9 @@ public @Nullable ImmersiveModeManager createImmersiveModeManager(View contentView) { return null; } + + /** + * Starts monitoring network quality. Must be called after native initialization is complete. + */ + public void startMonitoringNetworkQuality() {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index ed5dbc4..39b6d9e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1511,6 +1511,7 @@ !ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_BUTTON)); getComponent().resolveContextualSuggestionsCoordinator(); } + AppHooks.get().startMonitoringNetworkQuality(); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 43002e5..2ada68d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -284,6 +284,8 @@ "OmniboxUIExperimentHideSteadyStateUrlTrivialSubdomains"; public static final String OMNIBOX_NEW_ANSWER_LAYOUT = "OmniboxNewAnswerLayout"; public static final String OMNIBOX_RICH_ENTITY_SUGGESTIONS = "OmniboxRichEntitySuggestions"; + public static final String OMNIBOX_SHOW_SUGGESTION_FAVICONS = + "OmniboxUIExperimentShowSuggestionFavicons"; public static final String OMNIBOX_SPARE_RENDERER = "OmniboxSpareRenderer"; public static final String OVERSCROLL_HISTORY_NAVIGATION = "OverscrollHistoryNavigation"; public static final String PAY_WITH_GOOGLE_V1 = "PayWithGoogleV1";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java index dc0535f..cd3f330 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java
@@ -26,7 +26,9 @@ @Override public void onCreate() { super.onCreate(); - LibraryLoader.getInstance().setNativeLibraryPreloader(new MonochromeLibraryPreloader()); + if (!LibraryLoader.getInstance().isLoadedByZygote()) { + LibraryLoader.getInstance().setNativeLibraryPreloader(new MonochromeLibraryPreloader()); + } // ChildProcessCreationParams is only needed for browser process, though it is // created and set in all processes. We must set isExternalService to true for // Monochrome because Monochrome's renderer services are shared with WebView
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/CategoryCardAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/CategoryCardAdapter.java index f7a9556..0a0006d6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/CategoryCardAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/CategoryCardAdapter.java
@@ -52,7 +52,7 @@ private LinearLayoutManager mLayoutManager; private PropertyModel mCategoryModel; - public CategoryCardAdapter(PropertyModel model, LinearLayoutManager layoutManager, + CategoryCardAdapter(PropertyModel model, LinearLayoutManager layoutManager, RoundedIconGenerator iconGenerator, ContextMenuManager contextMenuManager, NativePageNavigationDelegate navDelegate, Profile profile) { mCategoryModel = model;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java index b8ea3699..4fbf792 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java
@@ -6,6 +6,7 @@ import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Rect; import android.util.AttributeSet; import android.view.ContextMenu; import android.view.LayoutInflater; @@ -50,11 +51,12 @@ private int mCategoryCardIndex; private class CategoryCardInteractionDelegate - implements ContextMenuManager.Delegate, OnClickListener, OnCreateContextMenuListener { + implements ContextMenuManager.Delegate, OnClickListener, OnCreateContextMenuListener, + OnFocusChangeListener { private String mSiteUrl; private int mTileIndex; - public CategoryCardInteractionDelegate(String siteUrl, int tileIndex) { + CategoryCardInteractionDelegate(String siteUrl, int tileIndex) { mSiteUrl = siteUrl; mTileIndex = tileIndex; } @@ -99,14 +101,19 @@ @Override public boolean isItemSupported(@ContextMenuManager.ContextMenuItemId int menuItemId) { - if (menuItemId == ContextMenuManager.ContextMenuItemId.LEARN_MORE) { - return false; - } - return true; + return menuItemId != ContextMenuManager.ContextMenuItemId.LEARN_MORE; } @Override - public void onContextMenuCreated(){}; + public void onContextMenuCreated() {} + + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + getParent().requestChildRectangleOnScreen( + ExploreSitesCategoryCardView.this, new Rect(), true); + } + } } // We use the MVC paradigm for the site tiles inside the category card. We don't use the MVC @@ -130,6 +137,7 @@ model.get(ExploreSitesSite.TILE_INDEX_KEY)); view.setOnClickListener(interactionDelegate); view.setOnCreateContextMenuListener(interactionDelegate); + view.setOnFocusChangeListener(interactionDelegate); } } } @@ -157,8 +165,8 @@ mCategoryCardIndex = categoryCardIndex; mCategory = category; - updateTitle(category.getTitle()); - updateTileViews(category); + updateTitle(mCategory.getTitle()); + updateTileViews(mCategory); } public void updateTitle(String categoryTitle) { @@ -232,8 +240,8 @@ /** * Records UMA data for how far down the EoS page the picked tile was. - * @param cardNumber The number card (zero based) of the tile that was picked. - * @param tileNumber The number of the tile within the card. + * @param cardIndex The number card (zero based) of the tile that was picked. + * @param tileIndex The number of the tile within the card. */ public static void recordTileIndexClick(int cardIndex, int tileIndex) { // TODO(petewil): Should I get the number of sites in this category from the model instead
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java index 05e30fc7..f8ca689 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
@@ -168,7 +168,7 @@ mHasFetchedNetworkCatalog = false; mModel = new PropertyModel.Builder(STATUS_KEY, SCROLL_TO_CATEGORY_KEY, CATEGORY_LIST_KEY) - .with(CATEGORY_LIST_KEY, new ListModel<ExploreSitesCategory>()) + .with(CATEGORY_LIST_KEY, new ListModel<>()) .with(STATUS_KEY, CatalogLoadingState.LOADING) .build(); @@ -194,7 +194,7 @@ CategoryCardAdapter adapterDelegate = new CategoryCardAdapter( mModel, mLayoutManager, iconGenerator, mContextMenuManager, navDelegate, mProfile); - mRecyclerView = (RecyclerView) mView.findViewById(R.id.explore_sites_category_recycler); + mRecyclerView = mView.findViewById(R.id.explore_sites_category_recycler); RecyclerViewAdapter<CategoryCardViewHolderFactory.CategoryCardViewHolder, Void> adapter = new RecyclerViewAdapter<>(adapterDelegate, new CategoryCardViewHolderFactory());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityObserver.java new file mode 100644 index 0000000..0cc4910 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityObserver.java
@@ -0,0 +1,32 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.net.nqe; + +import org.chromium.net.EffectiveConnectionType; + +/** + * Interface for observing changes to the current Network Quality Estimate. + */ +public interface NetworkQualityObserver { + /** + * Called when there is a change in the effective connection type. + * + * @param effectiveConnectionType the current effective connection type. + */ + default void onEffectiveConnectionTypeChanged( + @EffectiveConnectionType int effectiveConnectionType) {} + + /** + * Called when there is a substantial change in either HTTP RTT, transport RTT or downstream + * throughput estimate. + * + * @param httpRTTMillis estimate of the round trip time at the http layer. + * @param transportRTTMillis estimate of the round trip time at the transport layer. + * @param downstreamThroughputKbps estimate of the downstream throughput in Kbps (Kilobits per + * second). + */ + default void onRTTOrThroughputEstimatesComputed( + long httpRTTMillis, long transportRTTMillis, int downstreamThroughputKbps) {} +} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProvider.java new file mode 100644 index 0000000..669ce7ca --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProvider.java
@@ -0,0 +1,100 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.net.nqe; + +import org.chromium.base.ObserverList; +import org.chromium.base.ObserverList.RewindableIterator; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.library_loader.LibraryProcessType; +import org.chromium.content_public.browser.BrowserStartupController; +import org.chromium.net.EffectiveConnectionType; + +/** + * Provides Network Quality Estimates to observers. + */ +public class NetworkQualityProvider { + protected static NetworkQualityProvider sInstance; + + private final ObserverList<NetworkQualityObserver> mObservers = new ObserverList<>(); + + private final RewindableIterator<NetworkQualityObserver> mRewindableIterator; + + private boolean mInitializedRtt; + private long mHttpRttMillis; + private long mTransportRttMillis; + private int mDownstreamThroughputKbps; + private @EffectiveConnectionType Integer mEffectiveConnectionType; + + private long mNativeNetworkQualityProvider; + + /** + * @param observer The {@link NetworkQualityObserver} to be called when connection changes + * occur. This will trigger all observer callbacks for which data is already + * available. + */ + public static void addObserverAndMaybeTrigger(NetworkQualityObserver observer) { + NetworkQualityProvider provider = getInstance(); + provider.mObservers.addObserver(observer); + if (provider.mEffectiveConnectionType != null) { + observer.onEffectiveConnectionTypeChanged(provider.mEffectiveConnectionType); + } + if (provider.mInitializedRtt) { + observer.onRTTOrThroughputEstimatesComputed(provider.mHttpRttMillis, + provider.mTransportRttMillis, provider.mDownstreamThroughputKbps); + } + } + + /** + * @param observer The {@link NetworkQualityObserver} to remove. + */ + public static void removeObserver(NetworkQualityObserver observer) { + NetworkQualityProvider provider = getInstance(); + provider.mObservers.removeObserver(observer); + } + + private static NetworkQualityProvider getInstance() { + if (sInstance == null) sInstance = new NetworkQualityProvider(); + return sInstance; + } + + // Protected for testing. + protected NetworkQualityProvider() { + sInstance = this; + mRewindableIterator = mObservers.rewindableIterator(); + doNativeInit(); + } + + protected void doNativeInit() { + assert BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) + .isStartupSuccessfullyCompleted(); + mNativeNetworkQualityProvider = nativeInit(); + } + + @CalledByNative + public void onEffectiveConnectionTypeChanged( + @EffectiveConnectionType int effectiveConnectionType) { + mEffectiveConnectionType = effectiveConnectionType; + mRewindableIterator.rewind(); + while (mRewindableIterator.hasNext()) { + mRewindableIterator.next().onEffectiveConnectionTypeChanged(mEffectiveConnectionType); + } + } + + @CalledByNative + public void onRTTOrThroughputEstimatesComputed( + long httpRTTMillis, long transportRTTMillis, int downstreamThroughputKbps) { + mHttpRttMillis = httpRTTMillis; + mTransportRttMillis = transportRTTMillis; + mDownstreamThroughputKbps = downstreamThroughputKbps; + mInitializedRtt = true; + mRewindableIterator.rewind(); + while (mRewindableIterator.hasNext()) { + mRewindableIterator.next().onRTTOrThroughputEstimatesComputed( + mHttpRttMillis, mTransportRttMillis, mDownstreamThroughputKbps); + } + } + + private native long nativeInit(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/net/qualityprovider/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/net/nqe/OWNERS similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/net/qualityprovider/OWNERS rename to chrome/android/java/src/org/chromium/chrome/browser/net/nqe/OWNERS
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProviderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProviderTest.java new file mode 100644 index 0000000..5208c50 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProviderTest.java
@@ -0,0 +1,124 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.net.nqe; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.net.EffectiveConnectionType; + +/** + * JUnit tests for NetworkQualityProvider which run against Robolectric. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class NetworkQualityProviderTest { + private static final long HTTP_RTT = 1; + private static final long TRANSPORT_RTT = 2; + private static final int KBPS = 3; + private static final @EffectiveConnectionType int CONNECTION_TYPE = 4; + + private NetworkQualityProvider mProvider; + private TestNetworkQualityObserver mObserver; + + private static class NetworkQualityProviderForTesting extends NetworkQualityProvider { + @Override + protected void doNativeInit() {} + + public static void reset(NetworkQualityProvider provider) { + sInstance = provider; + } + } + + private static class TestNetworkQualityObserver implements NetworkQualityObserver { + private int mConnectionTypeCount; + private int mRTTCount; + + public int getConnectionTypeCount() { + return mConnectionTypeCount; + } + + public int getRTTCount() { + return mRTTCount; + } + + @Override + public void onEffectiveConnectionTypeChanged( + @EffectiveConnectionType int effectiveConnectionType) { + ++mConnectionTypeCount; + assertEquals(CONNECTION_TYPE, effectiveConnectionType); + } + + @Override + public void onRTTOrThroughputEstimatesComputed( + long httpRTTMillis, long transportRTTMillis, int downstreamThroughputKbps) { + ++mRTTCount; + assertEquals(HTTP_RTT, httpRTTMillis); + assertEquals(TRANSPORT_RTT, transportRTTMillis); + assertEquals(KBPS, downstreamThroughputKbps); + } + } + + @Before + public void setUp() throws Exception { + mProvider = new NetworkQualityProviderForTesting(); + NetworkQualityProviderForTesting.reset(mProvider); + mObserver = new TestNetworkQualityObserver(); + } + + @Test + public void testObserversGetNotified() throws Exception { + NetworkQualityProvider.addObserverAndMaybeTrigger(mObserver); + + assertEquals(0, mObserver.getConnectionTypeCount()); + assertEquals(0, mObserver.getRTTCount()); + + mProvider.onEffectiveConnectionTypeChanged(CONNECTION_TYPE); + assertEquals(1, mObserver.getConnectionTypeCount()); + assertEquals(0, mObserver.getRTTCount()); + + mProvider.onRTTOrThroughputEstimatesComputed(HTTP_RTT, TRANSPORT_RTT, KBPS); + assertEquals(1, mObserver.getConnectionTypeCount()); + assertEquals(1, mObserver.getRTTCount()); + } + + @Test + public void testRemovedObserversDontGetNotified() throws Exception { + NetworkQualityProvider.addObserverAndMaybeTrigger(mObserver); + NetworkQualityProvider.removeObserver(mObserver); + + mProvider.onEffectiveConnectionTypeChanged(CONNECTION_TYPE); + mProvider.onRTTOrThroughputEstimatesComputed(HTTP_RTT, TRANSPORT_RTT, KBPS); + assertEquals(0, mObserver.getConnectionTypeCount()); + assertEquals(0, mObserver.getRTTCount()); + } + + @Test + public void testObserversGetNotifiedWhenAdded() throws Exception { + mProvider.onEffectiveConnectionTypeChanged(CONNECTION_TYPE); + NetworkQualityProvider.addObserverAndMaybeTrigger(mObserver); + assertEquals(1, mObserver.getConnectionTypeCount()); + assertEquals(0, mObserver.getRTTCount()); + + NetworkQualityProvider.removeObserver(mObserver); + mProvider.onRTTOrThroughputEstimatesComputed(HTTP_RTT, TRANSPORT_RTT, KBPS); + NetworkQualityProvider.addObserverAndMaybeTrigger(mObserver); + assertEquals(2, mObserver.getConnectionTypeCount()); + assertEquals(1, mObserver.getRTTCount()); + NetworkQualityProvider.removeObserver(mObserver); + + mProvider = new NetworkQualityProviderForTesting(); + NetworkQualityProviderForTesting.reset(mProvider); + mProvider.onRTTOrThroughputEstimatesComputed(HTTP_RTT, TRANSPORT_RTT, KBPS); + NetworkQualityProvider.addObserverAndMaybeTrigger(mObserver); + assertEquals(2, mObserver.getConnectionTypeCount()); + assertEquals(2, mObserver.getRTTCount()); + } +} \ No newline at end of file
diff --git a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java index 7270a127..cc42488 100644 --- a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java +++ b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java
@@ -257,8 +257,7 @@ // the host browser to relaunch it again. { SharedPreferences.Editor editor = WebApkSharedPreferences.getPrefs(mAppContext).edit(); - editor.putLong( - WebApkSharedPreferences.SHARED_PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP, + editor.putLong(WebApkSharedPreferences.PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP, System.currentTimeMillis() - 1); editor.apply(); @@ -272,8 +271,7 @@ // the host browser to relaunch it. { SharedPreferences.Editor editor = WebApkSharedPreferences.getPrefs(mAppContext).edit(); - editor.putLong( - WebApkSharedPreferences.SHARED_PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP, 1); + editor.putLong(WebApkSharedPreferences.PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP, 1); editor.apply(); Robolectric.buildActivity(H2OMainActivity.class, launchIntent).create();
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkSharedPreferences.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkSharedPreferences.java index 4faf0b3..0ef7f74 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkSharedPreferences.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkSharedPreferences.java
@@ -28,7 +28,7 @@ "org.chromium.webapk.shell_apk.dex_version"; /** Timestamp of when the WebAPK asked the host browser to relaunch the WebAPK. */ - public static final String SHARED_PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP = + public static final String PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP = "org.chromium.webapk.shell_apk.request_host_browser_relaunch_timestamp"; public static SharedPreferences getPrefs(Context context) {
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/H2OLauncher.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/H2OLauncher.java index 821902a..b870432 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/H2OLauncher.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/H2OLauncher.java
@@ -42,7 +42,7 @@ SharedPreferences sharedPrefs = WebApkSharedPreferences.getPrefs(context); long now = System.currentTimeMillis(); long lastRequestTimestamp = sharedPrefs.getLong( - WebApkSharedPreferences.SHARED_PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP, -1); + WebApkSharedPreferences.PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP, -1); return (now - lastRequestTimestamp) <= deltaMs; } @@ -102,8 +102,8 @@ Context context, HostBrowserLauncherParams params) { long timestamp = System.currentTimeMillis(); SharedPreferences.Editor editor = WebApkSharedPreferences.getPrefs(context).edit(); - editor.putLong(WebApkSharedPreferences.SHARED_PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP, - timestamp); + editor.putLong( + WebApkSharedPreferences.PREF_REQUEST_HOST_BROWSER_RELAUNCH_TIMESTAMP, timestamp); editor.apply(); Bundle extraExtras = new Bundle();
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 1d60c07..4e1f4f0 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -9536,6 +9536,15 @@ <message name="IDS_WEBAUTHN_MISSING_USER_VERIFICATION_DESC" desc="The description on a dialog informing the user that the security key (an external physical device for user authentication) that they selected does not support any methods of identifying its owner, e.g. a fingerprint reader or a secret code (PIN)."> That security key does not support any method of personal identification (e.g. a fingerprint reader, or PIN entry), but that feature was requested. </message> + <message name="IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_TITLE" desc="Title of a dialog informing the user that the website wants to see information that identifies the user's Security Key, such as make and model number. The 'make' of a device is the brand name of the manufacturer, e.g. Yubikey is a make of Security Key. The 'model' of a device is the specific product, e.g. Yubikey Neo is a model of Security Key."> + Give permission to read your Security Key? + </message> + <message name="IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_DESC" desc="The description on a dialog informing the user that the website wants to see information that identifies the user's Security Key, such as make and model number. The 'make' of a device is the brand name of the manufacturer, e.g. Yubikey is a make of Security Key. The 'model' of a device is the specific product, e.g. Yubikey Neo is a model of Security Key."> + <ph name="WEBSITE"><ex>accounts.google.com</ex>$1</ph> wants to see the make and model of your security key + </message> + <message name="IDS_WEBAUTHN_ALLOW_ATTESTATION" desc="Label on button to allow a website to see information that identifies the user's Security Key, such as make and model number. The 'make' of a device is the brand name of the manufacturer, e.g. Yubikey is a make of Security Key. The 'model' of a device is the specific product, e.g. Yubikey Neo is a model of Security Key."> + Allow + </message> </if> <if expr="is_macosx"> <message name="IDS_WEBAUTHN_TOUCH_ID_TITLE" desc="Title of the dialog shown when the user tries to sign in with Touch ID." meaning="'Touch ID' is the fingerprint recognition feature in macOS. Try to refer Apple support documentation in the target language for the appropriate product name translation.">
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ALLOW_ATTESTATION.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ALLOW_ATTESTATION.png.sha1 new file mode 100644 index 0000000..646577a --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_ALLOW_ATTESTATION.png.sha1
@@ -0,0 +1 @@ +3975694e13a91a3ef1e4fd4276c7bd3c462b1bee \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_DESC.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_DESC.png.sha1 new file mode 100644 index 0000000..646577a --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_DESC.png.sha1
@@ -0,0 +1 @@ +3975694e13a91a3ef1e4fd4276c7bd3c462b1bee \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_TITLE.png.sha1 new file mode 100644 index 0000000..646577a --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_TITLE.png.sha1
@@ -0,0 +1 @@ +3975694e13a91a3ef1e4fd4276c7bd3c462b1bee \ No newline at end of file
diff --git a/chrome/app/vector_icons/google_chrome/google_g_logo.icon b/chrome/app/vector_icons/google_chrome/google_g_logo.icon deleted file mode 100644 index ba12830..0000000 --- a/chrome/app/vector_icons/google_chrome/google_g_logo.icon +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 32, -PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4, -MOVE_TO, 31.9f, 16.36f, -R_CUBIC_TO, 0, -1.13f, -0.1f, -2.22f, -0.3f, -3.27f, -H_LINE_TO, 16.27f, -R_V_LINE_TO, 6.15f, -R_H_LINE_TO, 8.76f, -R_CUBIC_TO, -0.38f, 2, -1.53f, 3.7f, -3.25f, 4.83f, -R_V_LINE_TO, 4, -R_H_LINE_TO, 5.26f, -R_CUBIC_TO, 3.08f, -2.77f, 4.85f, -6.87f, 4.85f, -11.75f, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0x34, 0xA8, 0x53, -MOVE_TO, 16.27f, 32, -R_CUBIC_TO, 4.4f, 0, 8.08f, -1.43f, 10.77f, -3.88f, -R_LINE_TO, -5.26f, -4, -R_CUBIC_TO, -1.46f, 0.95f, -3.32f, 1.52f, -5.5f, 1.52f, -R_CUBIC_TO, -4.25f, 0, -7.83f, -2.82f, -9.1f, -6.6f, -H_LINE_TO, 1.72f, -R_V_LINE_TO, 4.15f, -CUBIC_TO, 4.4f, 28.4f, 9.9f, 32, 16.27f, 32, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x05, -MOVE_TO, 7.17f, 19.04f, -R_CUBIC_TO, -0.33f, -0.96f, -0.5f, -2, -0.5f, -3.04f, -R_CUBIC_TO, 0, -1.05f, 0.17f, -2.08f, 0.5f, -3.04f, -V_LINE_TO, 8.8f, -H_LINE_TO, 1.73f, -CUBIC_TO, 0.63f, 10.98f, 0, 13.43f, 0, 16, -R_CUBIC_TO, 0, 2.57f, 0.63f, 5.03f, 1.73f, 7.2f, -R_LINE_TO, 5.44f, -4.16f, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xEA, 0x43, 0x35, -MOVE_TO, 16.27f, 6.36f, -R_CUBIC_TO, 2.4f, 0, 4.53f, 0.8f, 6.22f, 2.4f, -R_LINE_TO, 4.63f, -4.6f, -CUBIC_TO, 24.33f, 1.6f, 20.63f, 0, 16.23f, 0, -CUBIC_TO, 9.96f, 0, 4.46f, 3.6f, 1.78f, 8.8f, -R_LINE_TO, 5.43f, 4.16f, -R_CUBIC_TO, 1.27f, -3.78f, 4.85f, -6.6f, 9.1f, -6.6f, -CLOSE
diff --git a/chrome/app/vector_icons/google_chrome/google_pay_logo.icon b/chrome/app/vector_icons/google_chrome/google_pay_logo.icon deleted file mode 100644 index 03a38032..0000000 --- a/chrome/app/vector_icons/google_chrome/google_pay_logo.icon +++ /dev/null
@@ -1,116 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 40, - -// "Pay" text. Color is set by Chrome code at runtime depending on dark mode. -MOVE_TO, 18.92f, 7.82f, -R_V_LINE_TO, 4.64f, -H_LINE_TO, 17.44f, -V_LINE_TO, 1.01f, -R_H_LINE_TO, 3.92f, -R_ARC_TO, 3.55f, 3.55f, 0, 0, 1, 2.54f, 0.99f, -R_ARC_TO, 3.18f, 3.18f, 0, 0, 1, 1.06f, 2.42f, -R_ARC_TO, 3.17f, 3.17f, 0, 0, 1, -1.06f, 2.43f, -R_CUBIC_TO, -0.68f, 0.65f, -1.53f, 0.98f, -2.54f, 0.98f, -R_H_LINE_TO, -2.44f, -CLOSE, -R_MOVE_TO, 0, -5.41f, -R_V_LINE_TO, 4, -R_H_LINE_TO, 2.48f, -R_CUBIC_TO, 0.55f, 0.02f, 1.08f, -0.2f, 1.46f, -0.59f, -R_ARC_TO, 1.95f, 1.95f, 0, 0, 0, 0, -2.8f, -R_ARC_TO, 1.93f, 1.93f, 0, 0, 0, -1.46f, -0.61f, -R_H_LINE_TO, -2.48f, -CLOSE, -MOVE_TO, 28.36f, 4.37f, -R_CUBIC_TO, 1.09f, 0, 1.95f, 0.29f, 2.59f, 0.87f, -R_CUBIC_TO, 0.63f, 0.58f, 0.95f, 1.38f, 0.95f, 2.39f, -R_V_LINE_TO, 4.83f, -R_H_LINE_TO, -1.41f, -R_V_LINE_TO, -1.09f, -R_H_LINE_TO, -0.06f, -R_CUBIC_TO, -0.61f, 0.9f, -1.42f, 1.34f, -2.44f, 1.34f, -R_CUBIC_TO, -0.87f, 0, -1.59f, -0.26f, -2.18f, -0.77f, -R_ARC_TO, 2.45f, 2.45f, 0, 0, 1, -0.87f, -1.92f, -R_CUBIC_TO, 0, -0.81f, 0.31f, -1.46f, 0.92f, -1.93f, -R_CUBIC_TO, 0.62f, -0.48f, 1.44f, -0.72f, 2.46f, -0.72f, -R_CUBIC_TO, 0.88f, 0, 1.6f, 0.16f, 2.17f, 0.48f, -V_LINE_TO, 7.52f, -R_ARC_TO, 1.67f, 1.67f, 0, 0, 0, -0.61f, -1.3f, -R_CUBIC_TO, -0.39f, -0.35f, -0.9f, -0.54f, -1.43f, -0.54f, -R_CUBIC_TO, -0.82f, 0, -1.48f, 0.35f, -1.96f, 1.04f, -R_LINE_TO, -1.3f, -0.82f, -R_CUBIC_TO, 0.72f, -1.02f, 1.77f, -1.54f, 3.18f, -1.54f, -CLOSE, -R_MOVE_TO, -1.91f, 5.7f, -R_CUBIC_TO, 0, 0.38f, 0.18f, 0.74f, 0.49f, 0.96f, -R_CUBIC_TO, 0.33f, 0.26f, 0.73f, 0.39f, 1.15f, 0.38f, -R_ARC_TO, 2.36f, 2.36f, 0, 0, 0, 1.66f, -0.69f, -R_CUBIC_TO, 0.49f, -0.46f, 0.73f, -1, 0.73f, -1.62f, -R_CUBIC_TO, -0.46f, -0.36f, -1.1f, -0.55f, -1.93f, -0.55f, -R_CUBIC_TO, -0.6f, 0, -1.1f, 0.14f, -1.5f, 0.43f, -R_CUBIC_TO, -0.4f, 0.29f, -0.61f, 0.65f, -0.61f, 1.08f, -CLOSE, -MOVE_TO, 40, 4.62f, -LINE_TO, 35.07f, 15.92f, -R_H_LINE_TO, -1.52f, -R_LINE_TO, 1.83f, -3.95f, -R_LINE_TO, -3.24f, -7.34f, -R_H_LINE_TO, 1.61f, -R_LINE_TO, 2.34f, 5.63f, -R_H_LINE_TO, 0.03f, -R_LINE_TO, 2.28f, -5.63f, -CLOSE, - -// Blue part of the G. -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4, -MOVE_TO, 12.95f, 6.82f, -R_CUBIC_TO, 0, -0.45f, -0.04f, -0.9f, -0.11f, -1.34f, -R_H_LINE_TO, -6.23f, -V_LINE_TO, 8.02f, -R_H_LINE_TO, 3.57f, -R_ARC_TO, 3.05f, 3.05f, 0, 0, 1, -1.32f, 2, -R_V_LINE_TO, 1.65f, -R_H_LINE_TO, 2.13f, -R_CUBIC_TO, 1.25f, -1.14f, 1.97f, -2.84f, 1.97f, -4.84f, -CLOSE, - -// Green part of the G. -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0x34, 0xA8, 0x53, -MOVE_TO, 6.61f, 13.26f, -R_CUBIC_TO, 1.78f, 0, 3.28f, -0.58f, 4.38f, -1.59f, -R_LINE_TO, -2.13f, -1.65f, -R_CUBIC_TO, -0.59f, 0.4f, -1.36f, 0.63f, -2.25f, 0.63f, -R_CUBIC_TO, -1.72f, 0, -3.19f, -1.16f, -3.71f, -2.72f, -H_LINE_TO, 0.7f, -V_LINE_TO, 9.63f, -R_ARC_TO, 6.61f, 6.61f, 0, 0, 0, 5.9f, 3.63f, -CLOSE, - -// Yellow part of the G. -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x05, -MOVE_TO, 2.9f, 7.93f, -R_ARC_TO, 3.93f, 3.93f, 0, 0, 1, 0, -2.52f, -V_LINE_TO, 3.72f, -H_LINE_TO, 0.7f, -R_ARC_TO, 6.56f, 6.56f, 0, 0, 0, 0, 5.91f, -R_LINE_TO, 2.19f, -1.7f, -CLOSE, - -// Red part of the G. -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xEA, 0x43, 0x35, -MOVE_TO, 6.61f, 2.7f, -R_ARC_TO, 3.59f, 3.59f, 0, 0, 1, 2.53f, 0.99f, -R_LINE_TO, 1.89f, -1.88f, -ARC_TO, 6.36f, 6.36f, 0, 0, 0, 6.61f, 0.09f, -ARC_TO, 6.61f, 6.61f, 0, 0, 0, 0.71f, 3.72f, -R_LINE_TO, 2.19f, 1.7f, -R_CUBIC_TO, 0.52f, -1.56f, 1.99f, -2.72f, 3.71f, -2.72f, -CLOSE -
diff --git a/chrome/app/vector_icons/google_chrome/product.icon b/chrome/app/vector_icons/google_chrome/product.icon deleted file mode 100644 index 8f98f16..0000000 --- a/chrome/app/vector_icons/google_chrome/product.icon +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 24, -// Red -PATH_COLOR_ARGB, 0xFF, 0xDB, 0x44, 0x37, -MOVE_TO, 12, 7.5f, -R_H_LINE_TO, 8.9f, -CUBIC_TO, 19.3f, 4.2f, 15.9f, 2, 12, 2, -CUBIC_TO, 8.9f, 2, 6.1f, 3.4f, 4.3f, 5.6f, -R_LINE_TO, 3.3f, 5.7f, -R_CUBIC_TO, 0.3f, -2.1f, 2.2f, -3.8f, 4.4f, -3.8f, -CLOSE, -NEW_PATH, -// Green -PATH_COLOR_ARGB, 0xFF, 0x0F, 0x9D, 0x58, -// R_MOVE_TO, 0, 9, -MOVE_TO, 12, 16.5f, -R_CUBIC_TO, -1.7f, 0, -3.1f, -0.9f, -3.9f, -2.3f, -LINE_TO, 3.6f, 6.5f, -CUBIC_TO, 2.6f, 8.1f, 2, 10, 2, 12, -R_CUBIC_TO, 0, 5, 3.6f, 9.1f, 8.4f, 9.9f, -R_LINE_TO, 3.3f, -5.7f, -R_CUBIC_TO, -0.6f, 0.2f, -1.1f, 0.3f, -1.7f, 0.3f, -CLOSE, -NEW_PATH, -// Yellow -PATH_COLOR_ARGB, 0xFF, 0xFF, 0xCD, 0x40, -MOVE_TO, 16.5f, 12, -R_CUBIC_TO, 0, 0.8f, -0.2f, 1.6f, -0.6f, 2.2f, -LINE_TO, 11.4f, 22, -R_H_LINE_TO, 0.6f, -R_CUBIC_TO, 5.5f, 0, 10, -4.5f, 10, -10, -R_CUBIC_TO, 0, -1.2f, -0.2f, -2.4f, -0.6f, -3.5f, -R_H_LINE_TO, -6.6f, -R_CUBIC_TO, 1, 0.8f, 1.7f, 2.1f, 1.7f, 3.5f, -CLOSE, -NEW_PATH, -// Blue -PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4, -CIRCLE, 12, 12, 3.5
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 9d15290..3ecd7e9 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1060,8 +1060,6 @@ "performance_manager/graph/frame_node_impl.h", "performance_manager/graph/graph.cc", "performance_manager/graph/graph.h", - "performance_manager/graph/graph_introspector_impl.cc", - "performance_manager/graph/graph_introspector_impl.h", "performance_manager/graph/node_attached_data.cc", "performance_manager/graph/node_attached_data.h", "performance_manager/graph/node_attached_data_impl.h", @@ -2404,6 +2402,8 @@ "android/metrics/variations_session.cc", "android/mojo/chrome_interface_registrar_android.cc", "android/mojo/chrome_interface_registrar_android.h", + "android/net/nqe/network_quality_provider.cc", + "android/net/nqe/network_quality_provider.h", "android/ntp/android_content_suggestions_notifier.cc", "android/ntp/android_content_suggestions_notifier.h", "android/ntp/content_suggestions_notifier.cc", @@ -5342,6 +5342,8 @@ "chromeos/policy/fake_device_cloud_policy_manager.h", "chromeos/settings/device_settings_test_helper.cc", "chromeos/settings/device_settings_test_helper.h", + "ui/ash/ash_test_util.cc", + "ui/ash/ash_test_util.h", "ui/ash/tablet_mode_client_test_util.cc", "ui/ash/tablet_mode_client_test_util.h", ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 7aa9dae..b9e8a06e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2723,7 +2723,8 @@ {"omnibox-ui-show-suggestion-favicons", flag_descriptions::kOmniboxUIShowSuggestionFaviconsName, - flag_descriptions::kOmniboxUIShowSuggestionFaviconsDescription, kOsDesktop, + flag_descriptions::kOmniboxUIShowSuggestionFaviconsDescription, + kOsDesktop | kOsAndroid, FEATURE_VALUE_TYPE(omnibox::kUIExperimentShowSuggestionFavicons)}, {"omnibox-ui-swap-title-and-url", @@ -4030,6 +4031,11 @@ FEATURE_VALUE_TYPE(features::kInSessionPasswordChange)}, #endif // OS_CHROMEOS + {"autofill-off-no-server-data", + flag_descriptions::kAutofillOffNoServerDataName, + flag_descriptions::kAutofillOffNoServerDataDescription, kOsAll, + FEATURE_VALUE_TYPE(autofill::features::kAutofillOffNoServerData)}, + {"enable-portals", flag_descriptions::kEnablePortalsName, flag_descriptions::kEnablePortalsDescription, kOsAll, FEATURE_VALUE_TYPE(blink::features::kPortals)},
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index 77af698c..42264272 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -200,6 +200,7 @@ &omnibox::kOmniboxNewAnswerLayout, &omnibox::kOmniboxRichEntitySuggestions, &omnibox::kQueryInOmnibox, + &omnibox::kUIExperimentShowSuggestionFavicons, &password_manager::features::kGooglePasswordManager, &password_manager::features::kPasswordsKeyboardAccessory, &previews::features::kDataSaverLiteModeRebranding,
diff --git a/chrome/browser/android/net/nqe/network_quality_provider.cc b/chrome/browser/android/net/nqe/network_quality_provider.cc new file mode 100644 index 0000000..4ceffda --- /dev/null +++ b/chrome/browser/android/net/nqe/network_quality_provider.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 "chrome/browser/android/net/nqe/network_quality_provider.h" + +#include "base/android/jni_android.h" +#include "chrome/browser/browser_process.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_quality_observer_factory.h" +#include "jni/NetworkQualityProvider_jni.h" + +using base::android::JavaParamRef; +using base::android::ScopedJavaLocalRef; + +NetworkQualityProvider::NetworkQualityProvider(JNIEnv* env, + const JavaParamRef<jobject>& obj) + : j_obj_(env, obj) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + DCHECK(g_browser_process); + g_browser_process->network_quality_tracker() + ->AddRTTAndThroughputEstimatesObserver(this); + g_browser_process->network_quality_tracker() + ->AddEffectiveConnectionTypeObserver(this); +} + +NetworkQualityProvider::~NetworkQualityProvider() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + g_browser_process->network_quality_tracker() + ->RemoveRTTAndThroughputEstimatesObserver(this); + g_browser_process->network_quality_tracker() + ->RemoveEffectiveConnectionTypeObserver(this); +} + +void NetworkQualityProvider::OnEffectiveConnectionTypeChanged( + net::EffectiveConnectionType type) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + JNIEnv* env = base::android::AttachCurrentThread(); + Java_NetworkQualityProvider_onEffectiveConnectionTypeChanged( + env, j_obj_, static_cast<int>(type)); +} + +void NetworkQualityProvider::OnRTTOrThroughputEstimatesComputed( + base::TimeDelta http_rtt, + base::TimeDelta transport_rtt, + int32_t downstream_throughput_kbps) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + JNIEnv* env = base::android::AttachCurrentThread(); + Java_NetworkQualityProvider_onRTTOrThroughputEstimatesComputed( + env, j_obj_, http_rtt.InMilliseconds(), transport_rtt.InMilliseconds(), + downstream_throughput_kbps); +} + +// ---------------------------------------------------------------------------- +// Native JNI methods +// ---------------------------------------------------------------------------- + +static jlong JNI_NetworkQualityProvider_Init(JNIEnv* env, + const JavaParamRef<jobject>& obj) { + return reinterpret_cast<intptr_t>(new NetworkQualityProvider(env, obj)); +}
diff --git a/chrome/browser/android/net/nqe/network_quality_provider.h b/chrome/browser/android/net/nqe/network_quality_provider.h new file mode 100644 index 0000000..e2c781d --- /dev/null +++ b/chrome/browser/android/net/nqe/network_quality_provider.h
@@ -0,0 +1,47 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_NET_NQE_NETWORK_QUALITY_PROVIDER_H_ +#define CHROME_BROWSER_ANDROID_NET_NQE_NETWORK_QUALITY_PROVIDER_H_ + +#include "base/android/scoped_java_ref.h" +#include "base/macros.h" +#include "base/threading/thread_checker.h" +#include "base/time/time.h" +#include "net/nqe/effective_connection_type.h" +#include "net/nqe/network_quality.h" +#include "services/network/public/cpp/network_quality_tracker.h" + +// The native instance of the NetworkQualityProvider. This class is not +// threadsafe and must only be used on the UI thread. +class NetworkQualityProvider + : public network::NetworkQualityTracker::EffectiveConnectionTypeObserver, + public network::NetworkQualityTracker::RTTAndThroughputEstimatesObserver { + public: + NetworkQualityProvider(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); + + private: + // Note that this destructor is currently dead code. This destructor is never + // called as this object is owned by a java singleton that never goes away. + ~NetworkQualityProvider() override; + + // net::EffectiveConnectionTypeObserver implementation: + void OnEffectiveConnectionTypeChanged( + net::EffectiveConnectionType type) override; + + // net::RTTAndThroughputEstimatesObserver implementation: + void OnRTTOrThroughputEstimatesComputed( + base::TimeDelta http_rtt, + base::TimeDelta transport_rtt, + int32_t downstream_throughput_kbps) override; + + base::android::ScopedJavaGlobalRef<jobject> j_obj_; + + THREAD_CHECKER(thread_checker_); + + DISALLOW_COPY_AND_ASSIGN(NetworkQualityProvider); +}; + +#endif // CHROME_BROWSER_ANDROID_NET_NQE_NETWORK_QUALITY_PROVIDER_H_
diff --git a/chrome/browser/chrome_browser_main_browsertest.cc b/chrome/browser/chrome_browser_main_browsertest.cc deleted file mode 100644 index 3fa3a8bf..0000000 --- a/chrome/browser/chrome_browser_main_browsertest.cc +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chrome_browser_main.h" - -#include <stddef.h> - -#include "base/command_line.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_browser_main_extra_parts.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "components/variations/service/variations_service.h" -#include "components/variations/variations_switches.h" -#include "content/public/test/network_connection_change_simulator.h" - -// Friend of ChromeBrowserMainPartsTestApi to poke at internal state. -class ChromeBrowserMainPartsTestApi { - public: - explicit ChromeBrowserMainPartsTestApi(ChromeBrowserMainParts* main_parts) - : main_parts_(main_parts) {} - ~ChromeBrowserMainPartsTestApi() = default; - - void EnableVariationsServiceInit() { - main_parts_ - ->should_call_pre_main_loop_start_startup_on_variations_service_ = true; - } - - private: - ChromeBrowserMainParts* main_parts_; - DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainPartsTestApi); -}; - -namespace { - -class ChromeBrowserMainBrowserTest : public InProcessBrowserTest { - public: - ChromeBrowserMainBrowserTest() { - net::NetworkChangeNotifier::SetTestNotificationsOnly(true); - // Since the test currently performs an actual request to localhost (which - // is expected to fail since no variations server is running), retries are - // disabled to prevent race conditions from causing flakiness in tests. - scoped_feature_list_.InitAndDisableFeature(variations::kHttpRetryFeature); - } - - protected: - // InProcessBrowserTest: - void SetUpCommandLine(base::CommandLine* command_line) override { - // Without this (and EnableFetchForTesting() below) VariationsService won't - // do requests in non-branded builds. - command_line->AppendSwitchASCII(variations::switches::kVariationsServerURL, - "http://localhost"); - } - - void CreatedBrowserMainParts( - content::BrowserMainParts* browser_main_parts) override { - variations::VariationsService::EnableFetchForTesting(); - ChromeBrowserMainParts* chrome_browser_main_parts = - static_cast<ChromeBrowserMainParts*>(browser_main_parts); - ChromeBrowserMainPartsTestApi(chrome_browser_main_parts) - .EnableVariationsServiceInit(); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; - - DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainBrowserTest); -}; - -// Verifies VariationsService does a request when network status changes from -// none to connected. This is a regression test for https://crbug.com/826930. -// TODO(crbug.com/905714): This test should use a mock variations server -// instead of performing an actual request. -#if defined(OS_CHROMEOS) -#define MAYBE_VariationsServiceStartsRequestOnNetworkChange \ - DISABLED_VariationsServiceStartsRequestOnNetworkChange -#else -#define MAYBE_VariationsServiceStartsRequestOnNetworkChange \ - VariationsServiceStartsRequestOnNetworkChange -#endif -IN_PROC_BROWSER_TEST_F(ChromeBrowserMainBrowserTest, - MAYBE_VariationsServiceStartsRequestOnNetworkChange) { - variations::VariationsService* variations_service = - g_browser_process->variations_service(); - variations_service->CancelCurrentRequestForTesting(); - - content::NetworkConnectionChangeSimulator network_change_simulator; - network_change_simulator.SetConnectionType( - network::mojom::ConnectionType::CONNECTION_NONE); - const int initial_request_count = variations_service->request_count(); - - // The variations service will only send a request the first time the - // connection goes online, or after the 30min delay. Tell it that it hasn't - // sent a request yet to make sure the next time we go online a request will - // be sent. - variations_service->GetResourceRequestAllowedNotifierForTesting() - ->SetObserverRequestedForTesting(true); - - network_change_simulator.SetConnectionType( - network::mojom::ConnectionType::CONNECTION_WIFI); - // NotifyObserversOfNetworkChangeForTests uses PostTask, so run the loop until - // idle to ensure VariationsService processes the network change. - base::RunLoop().RunUntilIdle(); - const int final_request_count = variations_service->request_count(); - EXPECT_EQ(initial_request_count + 1, final_request_count); -} - -} // namespace
diff --git a/chrome/browser/chromeos/kiosk_next_home/app_controller_service.cc b/chrome/browser/chromeos/kiosk_next_home/app_controller_service.cc index 617a994..8f995abfe 100644 --- a/chrome/browser/chromeos/kiosk_next_home/app_controller_service.cc +++ b/chrome/browser/chromeos/kiosk_next_home/app_controller_service.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/kiosk_next_home/app_controller_service.h" +#include <sstream> #include <string> #include <utility> #include <vector> @@ -13,7 +14,6 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/optional.h" -#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "chrome/browser/apps/app_service/app_icon_source.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" @@ -100,9 +100,9 @@ [](mojom::AppController::GetArcAndroidIdCallback callback, bool success, int64_t raw_android_id) { // The bridge expects the Android id as a hex string. - std::string android_id = base::NumberToString(raw_android_id); - std::move(callback).Run( - success, base::HexEncode(android_id.data(), android_id.size())); + std::stringstream android_id_stream; + android_id_stream << std::hex << raw_android_id; + std::move(callback).Run(success, android_id_stream.str()); }, std::move(callback))); }
diff --git a/chrome/browser/chromeos/kiosk_next_home/app_controller_service_unittest.cc b/chrome/browser/chromeos/kiosk_next_home/app_controller_service_unittest.cc index 8a0d5c9..0a3e4c8 100644 --- a/chrome/browser/chromeos/kiosk_next_home/app_controller_service_unittest.cc +++ b/chrome/browser/chromeos/kiosk_next_home/app_controller_service_unittest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/kiosk_next_home/app_controller_service.h" +#include <limits> #include <map> #include <memory> #include <utility> @@ -69,6 +70,12 @@ arc_test_.app_instance()->SendAppAdded(app_info); } + void SetAndroidId(int64_t android_id) { + arc_test_.app_instance()->set_android_id(android_id); + } + + void StopArc() { arc_test_.StopArcInstance(); } + void AddAppDeltaToAppService(apps::mojom::AppPtr delta) { std::vector<apps::mojom::AppPtr> deltas; deltas.push_back(std::move(delta)); @@ -121,6 +128,21 @@ } } + void ExpectArcAndroidIdResponse(bool success, const std::string& android_id) { + bool returned_success; + std::string returned_android_id; + + app_controller_service_->GetArcAndroidId(base::BindLambdaForTesting( + [&returned_success, &returned_android_id]( + bool success, const std::string& android_id) { + returned_success = success; + returned_android_id = android_id; + })); + + EXPECT_EQ(returned_success, success); + EXPECT_EQ(returned_android_id, android_id); + } + private: content::TestBrowserThreadBundle test_browser_thread_bundle_; std::unique_ptr<TestingProfile> profile_; @@ -326,5 +348,21 @@ ExpectApps({allowed_app}); } +TEST_F(AppControllerServiceTest, GetArcAndroidIdReturnsItWhenItHasIt) { + SetAndroidId(123456789L); + ExpectArcAndroidIdResponse(true, "75bcd15"); // 75bcd15 is 123456789 in hex. + + // Make sure the returned Android ID doesn't get clipped when it's too large. + SetAndroidId(std::numeric_limits<int64_t>::max()); + ExpectArcAndroidIdResponse(true, "7fffffffffffffff"); +} + +TEST_F(AppControllerServiceTest, GetArcAndroidIdFailureIsPropagated) { + // Stop the ARC instance to simulate a failure. + StopArc(); + + ExpectArcAndroidIdResponse(false, "0"); +} + } // namespace kiosk_next_home } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc index 4b02da0b..4e60bf85 100644 --- a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc +++ b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h" #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h" #include "chrome/browser/chromeos/login/startup_utils.h" +#include "chrome/browser/chromeos/login/test/enrollment_ui_mixin.h" #include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h" #include "chrome/browser/chromeos/login/test/js_checker.h" #include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h" @@ -18,12 +19,14 @@ #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/policy/test/local_policy_test_server.h" +#include "chrome/grit/generated_resources.h" #include "chromeos/attestation/mock_attestation_flow.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/cryptohome/async_method_caller.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "components/policy/core/common/policy_switches.h" +#include "components/strings/grit/components_strings.h" namespace chromeos { @@ -54,6 +57,7 @@ fake_gaia_.SetupFakeGaiaForLogin(FakeGaiaMixin::kFakeUserEmail, FakeGaiaMixin::kFakeUserGaiaId, FakeGaiaMixin::kFakeRefreshToken); + policy_server_.SetUpdateDeviceAttributesPermission(false); OobeBaseTest::SetUpOnMainThread(); } @@ -81,7 +85,17 @@ return auto_enrollment_screen; } - LocalPolicyTestServerMixin local_policy_mixin_{&mixin_host_}; + void TriggerEnrollmentAndSignInSuccessfully() { + host()->StartWizard(OobeScreen::SCREEN_OOBE_ENROLLMENT); + OobeScreenWaiter(OobeScreen::SCREEN_OOBE_ENROLLMENT).Wait(); + + ASSERT_FALSE(StartupUtils::IsDeviceRegistered()); + enrollment_screen()->OnLoginDone(FakeGaiaMixin::kFakeUserEmail, + FakeGaiaMixin::kFakeAuthCode); + } + + LocalPolicyTestServerMixin policy_server_{&mixin_host_}; + test::EnrollmentUIMixin enrollment_ui_{&mixin_host_}; FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()}; private: @@ -127,18 +141,190 @@ // Simple manual enrollment. IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, ManualEnrollment) { - host()->StartWizard(OobeScreen::SCREEN_OOBE_ENROLLMENT); - OobeScreenWaiter(OobeScreen::SCREEN_OOBE_ENROLLMENT).Wait(); + TriggerEnrollmentAndSignInSuccessfully(); - ASSERT_FALSE(StartupUtils::IsDeviceRegistered()); - enrollment_screen()->OnLoginDone(FakeGaiaMixin::kFakeUserEmail, - FakeGaiaMixin::kFakeAuthCode); - - OobeBaseTest::WaitForEnrollmentSuccess(); - // TODO(rsorokin): Interact with attribute prompt step. + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); } +// Simple manual enrollment with device attributes prompt. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + ManualEnrollmentWithDeviceAttributes) { + policy_server_.SetUpdateDeviceAttributesPermission(true); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepDeviceAttributes); + enrollment_ui_.SubmitDeviceAttributes(test::values::kAssetId, + test::values::kLocation); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); + EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); +} + +// Simple manual enrollment with only license type available. +// Client should automatically select the only available license type, +// so no license selection UI should be displayed. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + ManualEnrollmentWithSingleLicense) { + policy_server_.ExpectAvailableLicenseCount(5 /* perpetual */, 0 /* annual */, + 0 /* kiosk */); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); + EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); +} + +// Simple manual enrollment with license selection. +// Enrollment selection UI should be displayed during enrollment. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + ManualEnrollmentWithMultipleLicenses) { + policy_server_.ExpectAvailableLicenseCount(5 /* perpetual */, 5 /* annual */, + 5 /* kiosk */); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepLicenses); + enrollment_ui_.SelectEnrollmentLicense(test::values::kLicenseTypeAnnual); + enrollment_ui_.UseSelectedLicense(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); + EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); +} + +// Negative scenarios: see different HTTP error codes in +// device_management_service.cc + +// Error during enrollment : 402 - missing licenses. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorNoLicenses) { + policy_server_.SetExpectedDeviceEnrollmentError(402); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + enrollment_ui_.ExpectErrorMessage( + IDS_ENTERPRISE_ENROLLMENT_MISSING_LICENSES_ERROR, /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +// Error during enrollment : 403 - management not allowed. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorManagementNotAllowed) { + policy_server_.SetExpectedDeviceEnrollmentError(403); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + enrollment_ui_.ExpectErrorMessage( + IDS_ENTERPRISE_ENROLLMENT_AUTH_ACCOUNT_ERROR, /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +// Error during enrollment : 405 - invalid device serial. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorInvalidDeviceSerial) { + policy_server_.SetExpectedDeviceEnrollmentError(405); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + // TODO (antrim, rsorokin): find out why it makes sense to retry here? + enrollment_ui_.ExpectErrorMessage( + IDS_POLICY_DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER, + /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +// Error during enrollment : 406 - domain mismatch +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorDomainMismatch) { + policy_server_.SetExpectedDeviceEnrollmentError(406); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + enrollment_ui_.ExpectErrorMessage( + IDS_ENTERPRISE_ENROLLMENT_DOMAIN_MISMATCH_ERROR, /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +// Error during enrollment : 409 - Device ID is already in use +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorDeviceIDConflict) { + policy_server_.SetExpectedDeviceEnrollmentError(409); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + // TODO (antrim, rsorokin): find out why it makes sense to retry here? + enrollment_ui_.ExpectErrorMessage( + IDS_POLICY_DM_STATUS_SERVICE_DEVICE_ID_CONFLICT, /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +// Error during enrollment : 412 - Activation is pending +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorActivationIsPending) { + policy_server_.SetExpectedDeviceEnrollmentError(412); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + enrollment_ui_.ExpectErrorMessage( + IDS_POLICY_DM_STATUS_SERVICE_ACTIVATION_PENDING, /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +// Error during enrollment : 417 - Consumer account with packaged license. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorConsumerAccountWithPackagedLicense) { + policy_server_.SetExpectedDeviceEnrollmentError(417); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + enrollment_ui_.ExpectErrorMessage( + IDS_ENTERPRISE_ENROLLMENT_CONSUMER_ACCOUNT_WITH_PACKAGED_LICENSE, + /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +// Error during enrollment : 500 - Consumer account with packaged license. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorServerError) { + policy_server_.SetExpectedDeviceEnrollmentError(500); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + enrollment_ui_.ExpectErrorMessage(IDS_POLICY_DM_STATUS_TEMPORARY_UNAVAILABLE, + /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +// Error during enrollment : Strange HTTP response from server. +IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, + EnrollmentErrorServerIsDrunk) { + policy_server_.SetExpectedDeviceEnrollmentError(12345); + + TriggerEnrollmentAndSignInSuccessfully(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); + enrollment_ui_.ExpectErrorMessage(IDS_POLICY_DM_STATUS_HTTP_STATUS_ERROR, + /* can retry */ true); + enrollment_ui_.RetryAfterError(); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + // No state keys on the server. Auto enrollment check should proceed to login. IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, AutoEnrollmentCheck) { host()->StartWizard(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK); @@ -147,7 +333,7 @@ // State keys are present but restore mode is not requested. IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, ReenrollmentNone) { - EXPECT_TRUE(local_policy_mixin_.SetDeviceStateRetrievalResponse( + EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse( state_keys_broker(), enterprise_management::DeviceStateRetrievalResponse::RESTORE_MODE_NONE, kTestDomain)); @@ -157,7 +343,7 @@ // Reenrollment requested. User can skip. IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, ReenrollmentRequested) { - EXPECT_TRUE(local_policy_mixin_.SetDeviceStateRetrievalResponse( + EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse( state_keys_broker(), enterprise_management::DeviceStateRetrievalResponse:: RESTORE_MODE_REENROLLMENT_REQUESTED, @@ -170,7 +356,7 @@ // Reenrollment forced. User can not skip. IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, ReenrollmentForced) { - EXPECT_TRUE(local_policy_mixin_.SetDeviceStateRetrievalResponse( + EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse( state_keys_broker(), enterprise_management::DeviceStateRetrievalResponse:: RESTORE_MODE_REENROLLMENT_ENFORCED, @@ -186,7 +372,7 @@ // Device is disabled. IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, DeviceDisabled) { - EXPECT_TRUE(local_policy_mixin_.SetDeviceStateRetrievalResponse( + EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse( state_keys_broker(), enterprise_management::DeviceStateRetrievalResponse:: RESTORE_MODE_DISABLED, @@ -198,14 +384,14 @@ // Attestation enrollment. IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, Attestation) { SetFakeAttestationFlow(); - EXPECT_TRUE(local_policy_mixin_.SetDeviceStateRetrievalResponse( + EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse( state_keys_broker(), enterprise_management::DeviceStateRetrievalResponse:: RESTORE_MODE_REENROLLMENT_ZERO_TOUCH, kTestDomain)); host()->StartWizard(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK); - OobeBaseTest::WaitForEnrollmentSuccess(); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); }
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc index 1d59e886..1b2db68 100644 --- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc +++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/login/login_manager_test.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/test/enrollment_helper_mixin.h" +#include "chrome/browser/chromeos/login/test/enrollment_ui_mixin.h" #include "chrome/browser/chromeos/login/test/js_checker.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" @@ -147,13 +148,6 @@ ExecutePendingJavaScript(); } - // Fills out the UI with device attribute information and submits it. - void SubmitAttributePromptUpdate() { - // Fill out the attribute prompt info and submit it. - test::OobeJS().TypeIntoPath("asset_id", {"oauth-enroll-asset-id"}); - test::OobeJS().TypeIntoPath("location", {"oauth-enroll-location"}); - test::OobeJS().TapOn("enroll-attributes-submit-button"); - } // Completes the enrollment process. void CompleteEnrollment() { @@ -170,23 +164,6 @@ // and the test code. void ExecutePendingJavaScript() { test::OobeJS().Evaluate(";"); } - // Returns true if there are any DOM elements with the given class. - bool IsStepDisplayed(const std::string& step) { - const std::string js = - "document.getElementsByClassName('oauth-enroll-state-" + step + - "').length"; - int count = test::OobeJS().GetInt(js); - return count > 0; - } - - // Waits until specific enrollment step is displayed. - void WaitForStep(const std::string& step) { - const std::string js = - "document.getElementsByClassName('oauth-enroll-state-" + step + - "').length > 0"; - test::OobeJS().CreateWaiter(js)->Wait(); - } - // Setup the enrollment screen. void ShowEnrollmentScreen() { LoginDisplayHost* host = LoginDisplayHost::default_host(); @@ -205,6 +182,7 @@ } protected: + test::EnrollmentUIMixin enrollment_ui_{&mixin_host_}; test::EnrollmentHelperMixin enrollment_helper_{&mixin_host_}; private: @@ -240,7 +218,8 @@ } void CheckActiveDirectoryCredentialsShown() { - EXPECT_TRUE(IsStepDisplayed("ad-join")); + EXPECT_TRUE( + enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); test::OobeJS().ExpectVisiblePath({kAdDialog, kAdCredentialsStep}); test::OobeJS().ExpectHiddenPath({kAdDialog, kAdUnlockConfigurationStep}); } @@ -253,7 +232,8 @@ } void CheckActiveDirectoryUnlockConfigurationShown() { - EXPECT_TRUE(IsStepDisplayed("ad-join")); + EXPECT_TRUE( + enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); test::OobeJS().ExpectHiddenPath({kAdDialog, kAdCredentialsStep}); test::OobeJS().ExpectVisiblePath({kAdDialog, kAdUnlockConfigurationStep}); } @@ -456,8 +436,7 @@ ExecutePendingJavaScript(); // Verify that the error page is displayed. - WaitForStep("error"); - EXPECT_FALSE(IsStepDisplayed("success")); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepError); } // Shows the enrollment screen and simulates a successful enrollment. Verifies @@ -472,8 +451,7 @@ SubmitEnrollmentCredentials(); // Verify that the success page is displayed. - WaitForStep("success"); - EXPECT_FALSE(IsStepDisplayed("error")); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); } // Shows the enrollment screen and mocks the enrollment helper to request an @@ -485,19 +463,17 @@ ShowEnrollmentScreen(); enrollment_helper_.ExpectEnrollmentMode( policy::EnrollmentConfig::MODE_MANUAL); - enrollment_helper_.ExpectAttributePromptUpdate("asset_id", "location"); + enrollment_helper_.ExpectAttributePromptUpdate(test::values::kAssetId, + test::values::kLocation); enrollment_helper_.ExpectSuccessfulOAuthEnrollment(); SubmitEnrollmentCredentials(); // Make sure the attribute-prompt view is open. + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepDeviceAttributes); - WaitForStep("attribute-prompt"); - EXPECT_TRUE(IsStepDisplayed("attribute-prompt")); - EXPECT_FALSE(IsStepDisplayed("success")); - EXPECT_FALSE(IsStepDisplayed("error")); - - SubmitAttributePromptUpdate(); - WaitForStep("success"); + enrollment_ui_.SubmitDeviceAttributes(test::values::kAssetId, + test::values::kLocation); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); } // Shows the enrollment screen and mocks the enrollment helper to show license @@ -517,16 +493,14 @@ SubmitEnrollmentCredentials(); // Make sure the license selection screen is open. - WaitForStep("license"); - // Click on third option. - test::OobeJS().SelectRadioPath( - {"oauth-enroll-license-ui", "license-option-kiosk"}); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepLicenses); + // Click on Kiosk option. + enrollment_ui_.SelectEnrollmentLicense(test::values::kLicenseTypeKiosk); // Click on second option. As there is 0 annual licenses, it should not be // selected. - test::OobeJS().SelectRadioPath( - {"oauth-enroll-license-ui", "license-option-annual"}); - test::OobeJS().TapOnPath({"oauth-enroll-license-ui", "next"}); - WaitForStep("success"); + enrollment_ui_.SelectEnrollmentLicense(test::values::kLicenseTypeAnnual); + enrollment_ui_.UseSelectedLicense(); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); } // Shows the enrollment screen and mocks the enrollment helper to show Active @@ -553,12 +527,11 @@ SubmitActiveDirectoryCredentials("machine_name", "" /* machine_dn */, "all", kAdTestUser, "password"); WaitForMessage(&message_queue, "\"ShowSpinnerScreen\""); - EXPECT_FALSE(IsStepDisplayed("ad-join")); + EXPECT_FALSE(enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); CompleteEnrollment(); // Verify that the success page is displayed. - WaitForStep("success"); - EXPECT_FALSE(IsStepDisplayed("error")); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); } // Verifies that the distinguished name specified on the Active Directory join @@ -587,12 +560,11 @@ "" /* encryption_types */, kAdTestUser, "password"); WaitForMessage(&message_queue, "\"ShowSpinnerScreen\""); - EXPECT_FALSE(IsStepDisplayed("ad-join")); + EXPECT_FALSE(enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); CompleteEnrollment(); // Verify that the success page is displayed. - WaitForStep("success"); - EXPECT_FALSE(IsStepDisplayed("error")); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); } // Shows the enrollment screen and mocks the enrollment helper to show Active @@ -616,7 +588,7 @@ SubmitActiveDirectoryCredentials("too_long_machine_name", "" /* machine_dn */, "" /* encryption_types */, kAdTestUser, "" /* password */); - EXPECT_TRUE(IsStepDisplayed("ad-join")); + EXPECT_TRUE(enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); ExpectElementValid(kAdMachineNameInput, true); ExpectElementValid(kAdUsernameInput, true); ExpectElementValid(kAdPasswordInput, false); @@ -626,7 +598,7 @@ "" /* encryption_types */, kAdTestUser, "password"); WaitForMessage(&message_queue, "\"ShowJoinDomainError\""); - EXPECT_TRUE(IsStepDisplayed("ad-join")); + EXPECT_TRUE(enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); ExpectElementValid(kAdMachineNameInput, false); ExpectElementValid(kAdUsernameInput, true); ExpectElementValid(kAdPasswordInput, true); @@ -636,7 +608,7 @@ "" /* encryption_types */, "test_user", "password"); WaitForMessage(&message_queue, "\"ShowJoinDomainError\""); - EXPECT_TRUE(IsStepDisplayed("ad-join")); + EXPECT_TRUE(enrollment_ui_.IsStepDisplayed(test::ui::kEnrollmentStepADJoin)); ExpectElementValid(kAdMachineNameInput, true); ExpectElementValid(kAdUsernameInput, false); ExpectElementValid(kAdPasswordInput, true); @@ -659,9 +631,9 @@ SubmitActiveDirectoryCredentials("machine_name", "" /* machine_dn */, "legacy", kAdTestUser, "password"); WaitForMessage(&message_queue, "\"ShowADJoinError\""); - WaitForStep("active-directory-join-error"); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepADJoinError); test::OobeJS().TapOnPath({kAdErrorCard, kSubmitButton}); - WaitForStep("ad-join"); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepADJoin); } // Check that configuration for the streamline Active Directory domain join
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index 0196cbf..b6ce972 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -31,6 +31,7 @@ #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/screens/gaia_view.h" #include "chrome/browser/chromeos/login/startup_utils.h" +#include "chrome/browser/chromeos/login/test/enrollment_ui_mixin.h" #include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h" #include "chrome/browser/chromeos/login/test/https_forwarder.h" #include "chrome/browser/chromeos/login/test/js_checker.h" @@ -794,11 +795,13 @@ guest_view::TestGuestViewManager* GetGuestViewManager(); content::WebContents* GetEnrollmentContents(); - private: + protected: LocalPolicyTestServerMixin local_policy_mixin_{&mixin_host_}; + test::EnrollmentUIMixin enrollment_ui_{&mixin_host_}; guest_view::TestGuestViewManagerFactory guest_view_manager_factory_; + private: DISALLOW_COPY_AND_ASSIGN(SAMLEnrollmentTest); }; @@ -860,7 +863,8 @@ SigninFrameJS().TypeIntoPath("fake_user", {"Email"}); SigninFrameJS().TypeIntoPath("fake_password", {"Password"}); SigninFrameJS().TapOn("Submit"); - OobeBaseTest::WaitForEnrollmentSuccess(); + + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepDeviceAttributes); } IN_PROC_BROWSER_TEST_F(SAMLEnrollmentTest, WithCredentialsPassingAPI) { @@ -873,7 +877,7 @@ SigninFrameJS().TypeIntoPath("fake_password", {"Password"}); SigninFrameJS().TapOn("Submit"); - OobeBaseTest::WaitForEnrollmentSuccess(); + enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepDeviceAttributes); } class SAMLPolicyTest : public SamlTest {
diff --git a/chrome/browser/chromeos/login/test/enrollment_ui_mixin.cc b/chrome/browser/chromeos/login/test/enrollment_ui_mixin.cc new file mode 100644 index 0000000..5f9c6d6 --- /dev/null +++ b/chrome/browser/chromeos/login/test/enrollment_ui_mixin.cc
@@ -0,0 +1,113 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/test/enrollment_ui_mixin.h" + +#include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h" +#include "chrome/browser/chromeos/login/test/js_checker.h" +#include "chrome/browser/chromeos/login/test/test_predicate_waiter.h" +#include "ui/base/l10n/l10n_util.h" + +namespace chromeos { +namespace test { + +namespace ui { + +const char kEnrollmentStepSignin[] = "signin"; +const char kEnrollmentStepWorking[] = "working"; +const char kEnrollmentStepSuccess[] = "success"; +const char kEnrollmentStepError[] = "error"; +const char kEnrollmentStepLicenses[] = "license"; +const char kEnrollmentStepDeviceAttributes[] = "attribute-prompt"; +const char kEnrollmentStepADJoin[] = "ad-join"; +const char kEnrollmentStepADJoinError[] = "active-directory-join-error"; + +} // namespace ui + +namespace values { + +const char kLicenseTypePerpetual[] = "perpetual"; +const char kLicenseTypeAnnual[] = "annual"; +const char kLicenseTypeKiosk[] = "kiosk"; + +const char kAssetId[] = "asset_id"; +const char kLocation[] = "location"; + +} // namespace values + +namespace { + +const char* const kAllSteps[] = { + ui::kEnrollmentStepSignin, ui::kEnrollmentStepWorking, + ui::kEnrollmentStepLicenses, ui::kEnrollmentStepDeviceAttributes, + ui::kEnrollmentStepSuccess, ui::kEnrollmentStepADJoin, + ui::kEnrollmentStepError, ui::kEnrollmentStepADJoinError}; + +std::string StepVisibleExpression(const std::string& step) { + return "document.getElementsByClassName('oauth-enroll-state-" + step + + "').length > 0"; +} + +const std::initializer_list<base::StringPiece> kEnrollmentErrorRetryButtonPath = + {"oauth-enroll-error-card", "submitButton"}; + +} // namespace + +EnrollmentUIMixin::EnrollmentUIMixin(InProcessBrowserTestMixinHost* host) + : InProcessBrowserTestMixin(host) {} + +EnrollmentUIMixin::~EnrollmentUIMixin() = default; + +// Waits until specific enrollment step is displayed. +void EnrollmentUIMixin::WaitForStep(const std::string& step) { + OobeJS().CreateWaiter(StepVisibleExpression(step))->Wait(); + for (const char* other : kAllSteps) { + if (other != step) { + ASSERT_FALSE(IsStepDisplayed(other)); + } + } +} +// Returns true if there are any DOM elements with the given class. +bool EnrollmentUIMixin::IsStepDisplayed(const std::string& step) { + return OobeJS().GetBool(StepVisibleExpression(step)); +} + +void EnrollmentUIMixin::SelectEnrollmentLicense( + const std::string& license_type) { + OobeJS().SelectRadioPath( + {"oauth-enroll-license-ui", "license-option-" + license_type}); +} + +void EnrollmentUIMixin::UseSelectedLicense() { + OobeJS().TapOnPath({"oauth-enroll-license-ui", "next"}); +} + +void EnrollmentUIMixin::ExpectErrorMessage(int error_message_id, + bool can_retry) { + const std::string element_path = + GetOobeElementPath({"oauth-enroll-error-card"}); + const std::string message = OobeJS().GetString(element_path + ".textContent"); + ASSERT_TRUE(std::string::npos != + message.find(l10n_util::GetStringUTF8(error_message_id))); + if (can_retry) { + OobeJS().ExpectVisiblePath(kEnrollmentErrorRetryButtonPath); + } else { + OobeJS().ExpectHiddenPath(kEnrollmentErrorRetryButtonPath); + } +} + +void EnrollmentUIMixin::RetryAfterError() { + OobeJS().TapOnPath(kEnrollmentErrorRetryButtonPath); + WaitForStep(ui::kEnrollmentStepSignin); +} + +void EnrollmentUIMixin::SubmitDeviceAttributes(const std::string& asset_id, + const std::string& location) { + OobeJS().TypeIntoPath(asset_id, {"oauth-enroll-asset-id"}); + OobeJS().TypeIntoPath(location, {"oauth-enroll-location"}); + OobeJS().TapOn("enroll-attributes-submit-button"); +} + +} // namespace test +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/enrollment_ui_mixin.h b/chrome/browser/chromeos/login/test/enrollment_ui_mixin.h new file mode 100644 index 0000000..37407de --- /dev/null +++ b/chrome/browser/chromeos/login/test/enrollment_ui_mixin.h
@@ -0,0 +1,74 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_TEST_ENROLLMENT_UI_MIXIN_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_ENROLLMENT_UI_MIXIN_H_ + +#include <string> + +#include "base/macros.h" +#include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h" + +namespace chromeos { +namespace test { + +namespace ui { + +// WaitForStep(...) constants. + +extern const char kEnrollmentStepLicenses[]; +extern const char kEnrollmentStepDeviceAttributes[]; +extern const char kEnrollmentStepSuccess[]; +extern const char kEnrollmentStepADJoin[]; +extern const char kEnrollmentStepError[]; +extern const char kEnrollmentStepADJoinError[]; + +} // namespace ui + +namespace values { + +// SelectEnrollmentLicense(...) constants. + +extern const char kLicenseTypePerpetual[]; +extern const char kLicenseTypeKiosk[]; +extern const char kLicenseTypeAnnual[]; + +// SubmitDeviceAttributes common values. + +extern const char kAssetId[]; +extern const char kLocation[]; + +} // namespace values + +// This test mixin covers enrollment-specific OOBE UI interactions. +class EnrollmentUIMixin : public InProcessBrowserTestMixin { + public: + explicit EnrollmentUIMixin(InProcessBrowserTestMixinHost* host); + ~EnrollmentUIMixin() override; + + // Waits until specific enrollment step is displayed. + void WaitForStep(const std::string& step); + bool IsStepDisplayed(const std::string& step); + + void ExpectErrorMessage(int error_message_id, bool can_retry); + void RetryAfterError(); + + // Fills out the UI with device attribute information and submits it. + void SubmitDeviceAttributes(const std::string& asset_id, + const std::string& location); + + // Selects enrollment license. + void SelectEnrollmentLicense(const std::string& license_type); + + // Proceeds with selected license. + void UseSelectedLicense(); + + private: + DISALLOW_COPY_AND_ASSIGN(EnrollmentUIMixin); +}; + +} // namespace test +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_ENROLLMENT_UI_MIXIN_H_
diff --git a/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.cc b/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.cc index 481199be..c7b7b08 100644 --- a/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.cc +++ b/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.cc
@@ -58,6 +58,38 @@ policy_test_server_->GetServiceURL().spec()); } +void LocalPolicyTestServerMixin::ExpectAvailableLicenseCount(int perpetual, + int annual, + int kiosk) { + base::Value licenses(base::Value::Type::DICTIONARY); + if (perpetual >= 0) { + licenses.SetKey("perpetual", base::Value(perpetual)); + } + if (annual >= 0) { + licenses.SetKey("annual", base::Value(annual)); + } + if (kiosk >= 0) { + licenses.SetKey("kiosk", base::Value(kiosk)); + } + DCHECK(licenses.DictSize() > 0); + + server_config_.SetKey("available_licenses", std::move(licenses)); + policy_test_server_->SetConfig(server_config_); +} + +void LocalPolicyTestServerMixin::SetUpdateDeviceAttributesPermission( + bool allowed) { + server_config_.SetKey("allow_set_device_attributes", base::Value(allowed)); + policy_test_server_->SetConfig(server_config_); +} + +void LocalPolicyTestServerMixin::SetExpectedDeviceEnrollmentError( + int net_error_code) { + server_config_.SetKey("device_register_http_error", + base::Value(net_error_code)); + policy_test_server_->SetConfig(server_config_); +} + bool LocalPolicyTestServerMixin::UpdateDevicePolicy( const enterprise_management::ChromeDeviceSettingsProto& policy) { DCHECK(policy_test_server_);
diff --git a/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h b/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h index cc65c82c..7db656f 100644 --- a/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h +++ b/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h
@@ -34,6 +34,18 @@ bool UpdateDevicePolicy( const enterprise_management::ChromeDeviceSettingsProto& policy); + // Configures and sets expectations for enrollment flow with license + // selection. Non-negative values indicate number of available licenses. + // There should be at least one license type. + void ExpectAvailableLicenseCount(int perpetual, int annual, int kiosk); + + void SetUpdateDeviceAttributesPermission(bool allowed); + + // Configures server to respond with particular error code during device + // registration. + // |net_error_code| - error code from device_management_service.cc. + void SetExpectedDeviceEnrollmentError(int net_error_code); + // Set response for DeviceStateRetrievalRequest. Returns that if finds state // key passed in the request. State keys could be set by RegisterClient call // on policy test server.
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc index 29e90ab8..74d4484 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.cc +++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -173,14 +173,6 @@ } while (message != "\"Done\""); } -void OobeBaseTest::WaitForEnrollmentSuccess() { - test::OobeJS() - .CreateWaiter( - "document.getElementsByClassName('oauth-enroll-state-attribute-" - "prompt').length > 0") - ->Wait(); -} - void OobeBaseTest::WaitForSigninScreen() { WizardController* wizard_controller = WizardController::default_controller(); if (wizard_controller)
diff --git a/chrome/browser/conflicts/module_inspector_win.cc b/chrome/browser/conflicts/module_inspector_win.cc index b8077f6..969efba 100644 --- a/chrome/browser/conflicts/module_inspector_win.cc +++ b/chrome/browser/conflicts/module_inspector_win.cc
@@ -39,14 +39,6 @@ base::UmaHistogramBoolean("Windows.InspectModule.ConnectionError", value); } -base::FilePath GetInspectionResultsCachePath() { - base::FilePath user_data_dir; - if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) - return base::FilePath(); - - return user_data_dir.Append(L"Module Info Cache"); -} - // Reads the inspection results cache and records the result in UMA. InspectionResultsCache ReadInspectionResultsCacheOnBackgroundSequence( const base::FilePath& file_path) { @@ -80,6 +72,9 @@ // static constexpr base::Feature ModuleInspector::kWinOOPInspectModuleFeature; +// static +constexpr base::TimeDelta ModuleInspector::kFlushInspectionResultsTimerTimeout; + ModuleInspector::ModuleInspector( const OnModuleInspectedCallback& on_module_inspected_callback) : on_module_inspected_callback_(on_module_inspected_callback), @@ -90,8 +85,15 @@ path_mapping_(GetPathMapping()), cache_task_runner_(base::CreateSequencedTaskRunnerWithTraits( {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), inspection_results_cache_read_(false), + flush_inspection_results_timer_( + FROM_HERE, + kFlushInspectionResultsTimerTimeout, + base::BindRepeating( + &ModuleInspector::MaybeUpdateInspectionResultsCache, + base::Unretained(this))), + has_new_inspection_results_(false), connection_error_retry_count_(kConnectionErrorRetryCount), background_inspection_disabled_( base::FeatureList::IsEnabled(kDisableBackgroundModuleInspection)), @@ -144,11 +146,23 @@ } void ModuleInspector::OnModuleDatabaseIdle() { - // Serialize cache. - cache_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&WriteInspectionResultCacheOnBackgroundSequence, - GetInspectionResultsCachePath(), - inspection_results_cache_)); + MaybeUpdateInspectionResultsCache(); +} + +// static +base::FilePath ModuleInspector::GetInspectionResultsCachePath() { + base::FilePath user_data_dir; + if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) + return base::FilePath(); + + return user_data_dir.Append(L"Module Info Cache"); +} + +void ModuleInspector::SetModuleInspectionResultForTesting( + const ModuleInfoKey& module_key, + ModuleInspectionResult inspection_result) { + AddInspectionResultToCache(module_key, inspection_result, + &inspection_results_cache_); } void ModuleInspector::EnsureUtilWinServiceBound() { @@ -285,6 +299,9 @@ // easily comparable. CollapseMatchingPrefixInPath(path_mapping_, &inspection_result.location); + has_new_inspection_results_ = true; + if (!flush_inspection_results_timer_.IsRunning()) + flush_inspection_results_timer_.Reset(); AddInspectionResultToCache(module_key, inspection_result, &inspection_results_cache_); @@ -313,3 +330,16 @@ if (!queue_.empty()) StartInspectingModule(); } + +void ModuleInspector::MaybeUpdateInspectionResultsCache() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (!has_new_inspection_results_) + return; + + has_new_inspection_results_ = false; + cache_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&WriteInspectionResultCacheOnBackgroundSequence, + GetInspectionResultsCachePath(), + inspection_results_cache_)); +}
diff --git a/chrome/browser/conflicts/module_inspector_win.h b/chrome/browser/conflicts/module_inspector_win.h index 81a6e38..5a414f5f 100644 --- a/chrome/browser/conflicts/module_inspector_win.h +++ b/chrome/browser/conflicts/module_inspector_win.h
@@ -15,6 +15,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/task/task_traits.h" +#include "base/timer/timer.h" #include "chrome/browser/conflicts/inspection_results_cache_win.h" #include "chrome/browser/conflicts/module_database_observer_win.h" #include "chrome/browser/conflicts/module_info_win.h" @@ -51,6 +52,11 @@ static constexpr base::Feature kWinOOPInspectModuleFeature = { "WinOOPInspectModule", base::FEATURE_DISABLED_BY_DEFAULT}; + // The amount of time before the |inspection_results_cache_| is flushed to + // disk while the ModuleDatabase is not idle. + static constexpr base::TimeDelta kFlushInspectionResultsTimerTimeout = + base::TimeDelta::FromMinutes(5); + using OnModuleInspectedCallback = base::Callback<void(const ModuleInfoKey& module_key, ModuleInspectionResult inspection_result)>; @@ -76,6 +82,12 @@ test_connector_ = connector; } + static base::FilePath GetInspectionResultsCachePath(); + + void SetModuleInspectionResultForTesting( + const ModuleInfoKey& module_key, + ModuleInspectionResult inspection_result); + private: // Ensures the |util_win_ptr_| instance is bound to the UtilWin service. This // may result in an unbounded pointer if Chrome is currently shutting down. @@ -107,6 +119,10 @@ void OnInspectionFinished(const ModuleInfoKey& module_key, ModuleInspectionResult inspection_result); + // Sends a task on a blocking background sequence to serialize + // |inspection_results_cache_|, should it be needed. + void MaybeUpdateInspectionResultsCache(); + OnModuleInspectedCallback on_module_inspected_callback_; // The modules are put in queue until they are sent for inspection. @@ -141,6 +157,14 @@ // more than once between restarts. InspectionResultsCache inspection_results_cache_; + // Ensures that newly inspected modules are flushed to the disk after at most + // 5 minutes to avoid losing too much of the work done if the browser is + // closed before all modules are inspected. + base::RetainingOneShotTimer flush_inspection_results_timer_; + + // Indicates if a module was newly inspected and the cache must be updated. + bool has_new_inspection_results_; + // The number of time this class will try to restart the UtilWin service if a // connection error occurs. This is to prevent the degenerate case where the // service always fails to start and the restart cycle happens infinitely.
diff --git a/chrome/browser/conflicts/module_inspector_win_unittest.cc b/chrome/browser/conflicts/module_inspector_win_unittest.cc index c5e76bb..a6a402d 100644 --- a/chrome/browser/conflicts/module_inspector_win_unittest.cc +++ b/chrome/browser/conflicts/module_inspector_win_unittest.cc
@@ -12,8 +12,11 @@ #include "base/bind.h" #include "base/environment.h" #include "base/files/file_path.h" +#include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_path_override.h" +#include "chrome/common/chrome_paths.h" #include "chrome/services/util_win/public/mojom/constants.mojom.h" #include "chrome/services/util_win/util_win_service.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -33,9 +36,25 @@ return path; } +bool CreateInspectionResultsCacheWithEntry( + const ModuleInfoKey& module_key, + const ModuleInspectionResult& inspection_result) { + // First create a cache with bogus data and create the cache file. + InspectionResultsCache inspection_results_cache; + + AddInspectionResultToCache(module_key, inspection_result, + &inspection_results_cache); + + return WriteInspectionResultsCache( + ModuleInspector::GetInspectionResultsCachePath(), + inspection_results_cache); +} + class ModuleInspectorTest : public testing::Test { public: - ModuleInspectorTest() = default; + ModuleInspectorTest() + : test_browser_thread_bundle_( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {} // Callback for ModuleInspector. void OnModuleInspected(const ModuleInfoKey& module_key, @@ -44,11 +63,18 @@ } void RunUntilIdle() { test_browser_thread_bundle_.RunUntilIdle(); } + void FastForwardToIdleTimer() { + test_browser_thread_bundle_.FastForwardBy( + ModuleInspector::kFlushInspectionResultsTimerTimeout); + test_browser_thread_bundle_.RunUntilIdle(); + } const std::vector<ModuleInspectionResult>& inspected_modules() { return inspected_modules_; } + void ClearInspectedModules() { inspected_modules_.clear(); } + // A TestBrowserThreadBundle is required instead of a ScopedTaskEnvironment // because of AfterStartupTaskUtils (DCHECK for BrowserThread::UI). // @@ -146,3 +172,114 @@ RunUntilIdle(); EXPECT_EQ(2u, inspected_modules().size()); } + +TEST_F(ModuleInspectorTest, InspectionResultsCache) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(kInspectionResultsCache); + + base::ScopedTempDir scoped_temp_dir; + ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + + base::ScopedPathOverride scoped_user_data_dir_override( + chrome::DIR_USER_DATA, scoped_temp_dir.GetPath()); + + // First create a cache with bogus data and create the cache file. + ModuleInfoKey module_key(GetKernel32DllFilePath(), 0, 0); + ModuleInspectionResult inspection_result; + inspection_result.location = L"BogusLocation"; + inspection_result.basename = L"BogusBasename"; + + ASSERT_TRUE( + CreateInspectionResultsCacheWithEntry(module_key, inspection_result)); + + ModuleInspector module_inspector(base::Bind( + &ModuleInspectorTest::OnModuleInspected, base::Unretained(this))); + + module_inspector.AddModule(module_key); + + RunUntilIdle(); + + ASSERT_EQ(1u, inspected_modules().size()); + + // The following comparisons can only succeed if the module was truly read + // from the cache. + ASSERT_EQ(inspected_modules()[0].location, inspection_result.location); + ASSERT_EQ(inspected_modules()[0].basename, inspection_result.basename); +} + +// Tests that when OnModuleDatabaseIdle() notificate is received, the cache is +// flushed to disk. +TEST_F(ModuleInspectorTest, InspectionResultsCache_OnModuleDatabaseIdle) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(kInspectionResultsCache); + + base::ScopedTempDir scoped_temp_dir; + ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + + base::ScopedPathOverride scoped_user_data_dir_override( + chrome::DIR_USER_DATA, scoped_temp_dir.GetPath()); + + ModuleInspector module_inspector(base::Bind( + &ModuleInspectorTest::OnModuleInspected, base::Unretained(this))); + + ModuleInfoKey module_key(GetKernel32DllFilePath(), 0, 0); + module_inspector.AddModule(module_key); + + RunUntilIdle(); + + ASSERT_EQ(1u, inspected_modules().size()); + + module_inspector.OnModuleDatabaseIdle(); + RunUntilIdle(); + + // If the cache was written to disk, it should contain the one entry for + // Kernel32.dll. + InspectionResultsCache inspection_results_cache; + EXPECT_EQ(ReadInspectionResultsCache( + ModuleInspector::GetInspectionResultsCachePath(), 0, + &inspection_results_cache), + ReadCacheResult::kSuccess); + + EXPECT_EQ(inspection_results_cache.size(), 1u); + auto inspection_result = + GetInspectionResultFromCache(module_key, &inspection_results_cache); + EXPECT_TRUE(inspection_result); +} + +// Tests that when the timer expires before the OnModuleDatabaseIdle() +// notification, the cache is flushed to disk. +TEST_F(ModuleInspectorTest, InspectionResultsCache_TimerExpired) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(kInspectionResultsCache); + + base::ScopedTempDir scoped_temp_dir; + ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + + base::ScopedPathOverride scoped_user_data_dir_override( + chrome::DIR_USER_DATA, scoped_temp_dir.GetPath()); + + ModuleInspector module_inspector(base::Bind( + &ModuleInspectorTest::OnModuleInspected, base::Unretained(this))); + + ModuleInfoKey module_key(GetKernel32DllFilePath(), 0, 0); + module_inspector.AddModule(module_key); + + RunUntilIdle(); + + ASSERT_EQ(1u, inspected_modules().size()); + + // Fast forwarding until the timer is fired. + FastForwardToIdleTimer(); + + // If the cache was flushed, it should contain the one entry for Kernel32.dll. + InspectionResultsCache inspection_results_cache; + EXPECT_EQ(ReadInspectionResultsCache( + ModuleInspector::GetInspectionResultsCachePath(), 0, + &inspection_results_cache), + ReadCacheResult::kSuccess); + + EXPECT_EQ(inspection_results_cache.size(), 1u); + auto inspection_result = + GetInspectionResultFromCache(module_key, &inspection_results_cache); + EXPECT_TRUE(inspection_result); +}
diff --git a/chrome/browser/extensions/extension_bindings_apitest.cc b/chrome/browser/extensions/extension_bindings_apitest.cc index 26e77d4..1d7a9f06 100644 --- a/chrome/browser/extensions/extension_bindings_apitest.cc +++ b/chrome/browser/extensions/extension_bindings_apitest.cc
@@ -915,6 +915,57 @@ EXPECT_EQ("success", result); } +// Tests the aliasing of chrome.extension methods to their chrome.runtime +// equivalents. +IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest, + ChromeExtensionIsAliasedToChromeRuntime) { + constexpr char kManifest[] = + R"({ + "name": "Test", + "version": "0.1", + "manifest_version": 2, + "background": { "scripts": ["background.js"] } + })"; + constexpr char kBackground[] = + R"(chrome.test.runTests([ + function chromeExtensionIsAliased() { + // Sanity check: chrome.extension is directly aliased to + // chrome.runtime. + chrome.test.assertTrue(!!chrome.runtime); + chrome.test.assertTrue(!!chrome.runtime.sendMessage); + chrome.test.assertEq(chrome.runtime.sendMessage, + chrome.extension.sendMessage); + chrome.test.succeed(); + }, + function testOverridingFailsGracefully() { + let intercepted = false; + // Modify the chrome.runtime object, which is the source for the + // chrome.extension API, to throw an error when sendMessage is + // accessed. Nothing should blow up. + // Regression test for https://crbug.com/949170. + Object.defineProperty( + chrome.runtime, + 'sendMessage', + { + get() { + intercepted = true; + throw new Error('Mwahaha'); + } + }); + chrome.extension.sendMessage; + chrome.test.assertTrue(intercepted); + chrome.test.succeed(); + } + ]);)"; + + TestExtensionDir extension_dir; + extension_dir.WriteManifest(kManifest); + extension_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kBackground); + ResultCatcher catcher; + ASSERT_TRUE(LoadExtension(extension_dir.UnpackedPath())); + EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); +} + INSTANTIATE_TEST_SUITE_P(, ExtensionBindingsUserGestureTest, ::testing::Values(kUserActivationV1,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index c04bfc8..4f212af1 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -918,6 +918,11 @@ "expiry_milestone": 77 }, { + "name": "autofill-off-no-server-data", + "owners": [ "seblalancette" ], + "expiry_milestone": 79 + }, + { "name": "enable-autoplay-ignore-web-audio", "owners": [ "beccahughes", "mlamouri", "media-dev" ], "expiry_milestone": 73
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 41771ef4..073657a 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -139,6 +139,11 @@ "When enabled, no local copy of server card will be saved when credit card " "upload succeeds."; +const char kAutofillOffNoServerDataName[] = "Autofill Off No Server Data"; +const char kAutofillOffNoServerDataDescription[] = + "Disables Autofill for fields with autocomplete off that have no " + "crowd-sourced evidence that Autofill would be helpful."; + const char kAutofillProfileClientValidationName[] = "Autofill Validates Profiles By Client"; const char kAutofillProfileClientValidationDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 10dde3a..b7c07d4 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -113,6 +113,9 @@ extern const char kAutofillNoLocalSaveOnUploadSuccessName[]; extern const char kAutofillNoLocalSaveOnUploadSuccessDescription[]; +extern const char kAutofillOffNoServerDataName[]; +extern const char kAutofillOffNoServerDataDescription[]; + extern const char kAutofillProfileClientValidationName[]; extern const char kAutofillProfileClientValidationDescription[];
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc index 809942b..f055953 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/metrics/process_memory_metrics_emitter.h" +#include <set> + #include "base/bind.h" #include "base/compiler_specific.h" #include "base/metrics/histogram_functions.h" @@ -12,6 +14,10 @@ #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/metrics/tab_footprint_aggregator.h" +#include "chrome/browser/performance_manager/graph/frame_node_impl.h" +#include "chrome/browser/performance_manager/graph/graph.h" +#include "chrome/browser/performance_manager/graph/page_node_impl.h" +#include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "chrome/browser/performance_manager/performance_manager.h" #include "chrome/browser/profiles/profile_manager.h" #include "content/public/browser/audio_service_info.h" @@ -398,14 +404,13 @@ void EmitRendererMemoryMetrics( const GlobalMemoryDump::ProcessDump& pmd, - const resource_coordinator::mojom::PageInfoPtr& page_info, + const ProcessMemoryMetricsEmitter::PageInfo* page_info, ukm::UkmRecorder* ukm_recorder, int number_of_extensions, const base::Optional<base::TimeDelta>& uptime, bool record_uma) { - ukm::SourceId ukm_source_id = page_info.is_null() - ? ukm::UkmRecorder::GetNewSourceID() - : page_info->ukm_source_id; + ukm::SourceId ukm_source_id = + page_info ? page_info->ukm_source_id : ukm::UkmRecorder::GetNewSourceID(); Memory_Experimental builder(ukm_source_id); builder.SetProcessType(static_cast<int64_t>( memory_instrumentation::mojom::ProcessType::RENDERER)); @@ -414,7 +419,7 @@ const char* process = number_of_extensions == 0 ? "Renderer" : "Extension"; EmitProcessUmaAndUkm(pmd, process, uptime, record_uma, &builder); - if (!page_info.is_null()) { + if (page_info) { builder.SetIsVisible(page_info->is_visible); builder.SetTimeSinceLastVisibilityChange( page_info->time_since_last_visibility_change.InSeconds()); @@ -494,10 +499,12 @@ // The callback keeps this object alive until the callback is invoked. performance_manager::PerformanceManager* performance_manager = performance_manager::PerformanceManager::GetInstance(); - performance_manager->BindInterface(mojo::MakeRequest(&introspector_)); auto callback2 = - base::Bind(&ProcessMemoryMetricsEmitter::ReceivedProcessInfos, this); - introspector_->GetProcessToURLMap(callback2); + base::BindOnce(&ProcessMemoryMetricsEmitter::ReceivedProcessInfos, this); + performance_manager->CallOnGraph( + FROM_HERE, + base::BindOnce(&ProcessMemoryMetricsEmitter::GetProcessToPageInfoMap, + std::move(callback2))); } void ProcessMemoryMetricsEmitter::MarkServiceRequestsInProgress() { @@ -518,15 +525,14 @@ } void ProcessMemoryMetricsEmitter::ReceivedProcessInfos( - std::vector<resource_coordinator::mojom::ProcessInfoPtr> process_infos) { + std::vector<ProcessInfo> process_infos) { get_process_urls_in_progress_ = false; process_infos_.clear(); process_infos_.reserve(process_infos.size()); // If there are duplicate pids, keep the latest ProcessInfoPtr. - for (resource_coordinator::mojom::ProcessInfoPtr& process_info : - process_infos) { - base::ProcessId pid = process_info->pid; + for (ProcessInfo& process_info : process_infos) { + base::ProcessId pid = process_info.pid; process_infos_[pid] = std::move(process_info); } CollateResults(); @@ -582,8 +588,8 @@ base::ProcessId pid) { auto process_info = process_infos_.find(pid); if (process_info != process_infos_.end()) { - if (process_info->second->launch_time) - return now - process_info->second->launch_time.value(); + if (!process_info->second.launch_time.is_null()) + return now - process_info->second.launch_time; } return base::Optional<base::TimeDelta>(); } @@ -621,24 +627,22 @@ } case memory_instrumentation::mojom::ProcessType::RENDERER: { renderer_private_footprint_total_kb += process_pmf_kb; - resource_coordinator::mojom::PageInfoPtr single_page_info; + const PageInfo* single_page_info = nullptr; auto iter = process_infos_.find(pmd.pid()); if (iter != process_infos_.end()) { - const resource_coordinator::mojom::ProcessInfoPtr& process_info = - iter->second; + const ProcessInfo& process_info = iter->second; if (emit_metrics_for_all_processes) { // Renderer metrics-by-tab only make sense if we're visiting all // render processes. - for (const resource_coordinator::mojom::PageInfoPtr& page_info : - process_info->page_infos) { - if (page_info->hosts_main_frame) { - per_tab_metrics.AssociateMainFrame(page_info->ukm_source_id, - pmd.pid(), page_info->tab_id, + for (const PageInfo& page_info : process_info.page_infos) { + if (page_info.hosts_main_frame) { + per_tab_metrics.AssociateMainFrame(page_info.ukm_source_id, + pmd.pid(), page_info.tab_id, process_pmf_kb); } else { - per_tab_metrics.AssociateSubFrame(page_info->ukm_source_id, - pmd.pid(), page_info->tab_id, + per_tab_metrics.AssociateSubFrame(page_info.ukm_source_id, + pmd.pid(), page_info.tab_id, process_pmf_kb); } } @@ -648,8 +652,8 @@ // emit any per-renderer URLs. This is not ideal, but UKM does not // support multiple-URLs per entry, and we must have one entry per // process. - if (process_info->page_infos.size() == 1) { - single_page_info = std::move(process_info->page_infos[0]); + if (process_info.page_infos.size() == 1) { + single_page_info = &process_info.page_infos[0]; } } @@ -728,3 +732,67 @@ per_tab_metrics.RecordPmfs(GetUkmRecorder()); } } + +namespace { + +// Returns true iff the given |process| is responsible for hosting the +// main-frame of the given |page|. +bool HostsMainFrame(performance_manager::ProcessNodeImpl* process, + performance_manager::PageNodeImpl* page) { + performance_manager::FrameNodeImpl* main_frame = page->GetMainFrameNode(); + if (main_frame == nullptr) { + // |process| can't host a frame that doesn't exist. + return false; + } + + return main_frame->process_node() == process; +} + +} // namespace + +void ProcessMemoryMetricsEmitter::GetProcessToPageInfoMap( + GetProcessToPageInfoMapCallback callback, + performance_manager::Graph* graph) { + std::vector<ProcessInfo> process_infos; + std::vector<performance_manager::ProcessNodeImpl*> process_nodes = + graph->GetAllProcessNodes(); + for (auto* process_node : process_nodes) { + if (process_node->process_id() == base::kNullProcessId) + continue; + + ProcessInfo process_info; + process_info.pid = process_node->process_id(); + process_info.launch_time = process_node->launch_time(); + + std::set<performance_manager::PageNodeImpl*> page_nodes = + process_node->GetAssociatedPageCoordinationUnits(); + for (performance_manager::PageNodeImpl* page_node : page_nodes) { + if (page_node->ukm_source_id() == ukm::kInvalidSourceId) + continue; + + PageInfo page_info; + page_info.ukm_source_id = page_node->ukm_source_id(); + page_info.tab_id = page_node->id().id; + page_info.hosts_main_frame = HostsMainFrame(process_node, page_node); + page_info.is_visible = page_node->is_visible(); + page_info.time_since_last_visibility_change = + page_node->TimeSinceLastVisibilityChange(); + page_info.time_since_last_navigation = + page_node->TimeSinceLastNavigation(); + process_info.page_infos.push_back(std::move(page_info)); + } + process_infos.push_back(std::move(process_info)); + } + std::move(callback).Run(std::move(process_infos)); +} + +ProcessMemoryMetricsEmitter::ProcessInfo::ProcessInfo() = default; + +ProcessMemoryMetricsEmitter::ProcessInfo::ProcessInfo(ProcessInfo&& other) = + default; + +ProcessMemoryMetricsEmitter::ProcessInfo::~ProcessInfo() = default; + +ProcessMemoryMetricsEmitter::ProcessInfo& +ProcessMemoryMetricsEmitter::ProcessInfo::operator=(const ProcessInfo& other) = + default;
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.h b/chrome/browser/metrics/process_memory_metrics_emitter.h index 0a2cfb7..0cc330a 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter.h +++ b/chrome/browser/metrics/process_memory_metrics_emitter.h
@@ -5,20 +5,25 @@ #ifndef CHROME_BROWSER_METRICS_PROCESS_MEMORY_METRICS_EMITTER_H_ #define CHROME_BROWSER_METRICS_PROCESS_MEMORY_METRICS_EMITTER_H_ -#include <unordered_map> #include <vector> +#include "base/callback.h" +#include "base/containers/flat_map.h" #include "base/memory/ref_counted.h" #include "base/optional.h" #include "base/process/process_handle.h" #include "base/time/time.h" +#include "services/metrics/public/cpp/ukm_source_id.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h" -#include "services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom.h" namespace ukm { class UkmRecorder; } +namespace performance_manager { +class Graph; +} + // This class asynchronously fetches memory metrics for each process, and then // emits UMA metrics from those metrics. // Each instance is self-owned, and will delete itself once it has finished @@ -29,6 +34,9 @@ class ProcessMemoryMetricsEmitter : public base::RefCountedThreadSafe<ProcessMemoryMetricsEmitter> { public: + struct PageInfo; + struct ProcessInfo; + // Use this constructor to emit UKM and UMA from all processes, i.e. // browser process, gpu process, and all renderers. ProcessMemoryMetricsEmitter(); @@ -50,10 +58,9 @@ bool success, std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump); - // Virtual for testing. Callback invoked when resource_coordinator service + // Virtual for testing. Callback invoked when the performance_manager // returns info for each process. - virtual void ReceivedProcessInfos( - std::vector<resource_coordinator::mojom::ProcessInfoPtr> process_infos); + virtual void ReceivedProcessInfos(std::vector<ProcessInfo> process_infos); // Virtual for testing. virtual ukm::UkmRecorder* GetUkmRecorder(); @@ -75,7 +82,10 @@ // be collated. void CollateResults(); - resource_coordinator::mojom::CoordinationUnitIntrospectorPtr introspector_; + using GetProcessToPageInfoMapCallback = + base::OnceCallback<void(std::vector<ProcessInfo>)>; + static void GetProcessToPageInfoMap(GetProcessToPageInfoMapCallback callback, + performance_manager::Graph* graph); // The results of each request are cached. When both requests are finished, // the results are collated. @@ -83,9 +93,8 @@ std::unique_ptr<memory_instrumentation::GlobalMemoryDump> global_dump_; bool get_process_urls_in_progress_ = false; - // The key is ProcessInfoPtr::pid. - std::unordered_map<int64_t, resource_coordinator::mojom::ProcessInfoPtr> - process_infos_; + // The key is ProcessInfo::pid. + base::flat_map<base::ProcessId, ProcessInfo> process_infos_; // Specify this pid_scope_ to only record the memory metrics of the specific // process. @@ -94,4 +103,29 @@ DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitter); }; +// A |PageInfo| describes some metrics about a particular page with respect to +// a given process. +struct ProcessMemoryMetricsEmitter::PageInfo { + // Identifier to distinguish which UMK Source this |PageInfo| corresponds to. + ukm::SourceId ukm_source_id; + // Identifier to distinguish which tab this |PageInfo| corresponds to. + uint64_t tab_id; + // True iff the process for this |PageInfo| hosts the main frame of the page. + bool hosts_main_frame; + bool is_visible; + base::TimeDelta time_since_last_navigation; + base::TimeDelta time_since_last_visibility_change; +}; + +struct ProcessMemoryMetricsEmitter::ProcessInfo { + ProcessInfo(); + ProcessInfo(ProcessInfo&& other); + ~ProcessInfo(); + ProcessInfo& operator=(const ProcessInfo& other); + + base::ProcessId pid; + std::vector<PageInfo> page_infos; + base::Time launch_time; +}; + #endif // CHROME_BROWSER_METRICS_PROCESS_MEMORY_METRICS_EMITTER_H_
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc index e94a07f..f685672d 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
@@ -105,9 +105,7 @@ QuitIfFinished(); } - void ReceivedProcessInfos( - std::vector<resource_coordinator::mojom::ProcessInfoPtr> process_infos) - override { + void ReceivedProcessInfos(std::vector<ProcessInfo> process_infos) override { ProcessMemoryMetricsEmitter::ReceivedProcessInfos(std::move(process_infos)); finished_process_info_ = true; QuitIfFinished();
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc index 2d422db..8923d92 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc
@@ -21,10 +21,10 @@ using ProcessMemoryDumpPtr = memory_instrumentation::mojom::ProcessMemoryDumpPtr; using OSMemDumpPtr = memory_instrumentation::mojom::OSMemDumpPtr; -using PageInfoPtr = resource_coordinator::mojom::PageInfoPtr; +using PageInfo = ProcessMemoryMetricsEmitter::PageInfo; using ProcessType = memory_instrumentation::mojom::ProcessType; -using ProcessInfoPtr = resource_coordinator::mojom::ProcessInfoPtr; -using ProcessInfoVector = std::vector<ProcessInfoPtr>; +using ProcessInfo = ProcessMemoryMetricsEmitter::ProcessInfo; +using ProcessInfoVector = std::vector<ProcessInfo>; namespace { @@ -501,60 +501,57 @@ // Process 200 always has no URLs. { - ProcessInfoPtr process_info( - resource_coordinator::mojom::ProcessInfo::New()); - process_info->pid = 200; + ProcessInfo process_info; + process_info.pid = 200; process_infos.push_back(std::move(process_info)); } // Process kTestRendererPid201 always has 1 URL { - ProcessInfoPtr process_info( - resource_coordinator::mojom::ProcessInfo::New()); - process_info->pid = kTestRendererPid201; + ProcessInfo process_info; + process_info.pid = kTestRendererPid201; ukm::SourceId first_source_id = ukm::UkmRecorder::GetNewSourceID(); ukm_recorder.UpdateSourceURL(first_source_id, GURL("http://www.url201.com/")); - PageInfoPtr page_info(resource_coordinator::mojom::PageInfo::New()); + PageInfo page_info; - page_info->ukm_source_id = first_source_id; - page_info->tab_id = 201; - page_info->hosts_main_frame = true; - page_info->is_visible = true; - page_info->time_since_last_visibility_change = + page_info.ukm_source_id = first_source_id; + page_info.tab_id = 201; + page_info.hosts_main_frame = true; + page_info.is_visible = true; + page_info.time_since_last_visibility_change = base::TimeDelta::FromSeconds(15); - page_info->time_since_last_navigation = base::TimeDelta::FromSeconds(20); - process_info->page_infos.push_back(std::move(page_info)); + page_info.time_since_last_navigation = base::TimeDelta::FromSeconds(20); + process_info.page_infos.push_back(page_info); process_infos.push_back(std::move(process_info)); } // Process kTestRendererPid202 always has 2 URL { - ProcessInfoPtr process_info( - resource_coordinator::mojom::ProcessInfo::New()); - process_info->pid = kTestRendererPid202; + ProcessInfo process_info; + process_info.pid = kTestRendererPid202; ukm::SourceId first_source_id = ukm::UkmRecorder::GetNewSourceID(); ukm::SourceId second_source_id = ukm::UkmRecorder::GetNewSourceID(); ukm_recorder.UpdateSourceURL(first_source_id, GURL("http://www.url2021.com/")); ukm_recorder.UpdateSourceURL(second_source_id, GURL("http://www.url2022.com/")); - PageInfoPtr page_info1(resource_coordinator::mojom::PageInfo::New()); - page_info1->ukm_source_id = first_source_id; - page_info1->tab_id = 2021; - page_info1->hosts_main_frame = true; - page_info1->time_since_last_visibility_change = + PageInfo page_info1; + page_info1.ukm_source_id = first_source_id; + page_info1.tab_id = 2021; + page_info1.hosts_main_frame = true; + page_info1.time_since_last_visibility_change = base::TimeDelta::FromSeconds(11); - page_info1->time_since_last_navigation = base::TimeDelta::FromSeconds(21); - PageInfoPtr page_info2(resource_coordinator::mojom::PageInfo::New()); - page_info2->ukm_source_id = second_source_id; - page_info2->tab_id = 2022; - page_info2->hosts_main_frame = true; - page_info2->time_since_last_visibility_change = + page_info1.time_since_last_navigation = base::TimeDelta::FromSeconds(21); + PageInfo page_info2; + page_info2.ukm_source_id = second_source_id; + page_info2.tab_id = 2022; + page_info2.hosts_main_frame = true; + page_info2.time_since_last_visibility_change = base::TimeDelta::FromSeconds(12); - page_info2->time_since_last_navigation = base::TimeDelta::FromSeconds(22); - process_info->page_infos.push_back(std::move(page_info1)); - process_info->page_infos.push_back(std::move(page_info2)); + page_info2.time_since_last_navigation = base::TimeDelta::FromSeconds(22); + process_info.page_infos.push_back(std::move(page_info1)); + process_info.page_infos.push_back(std::move(page_info2)); process_infos.push_back(std::move(process_info)); }
diff --git a/chrome/browser/performance_manager/graph/graph_introspector_impl.cc b/chrome/browser/performance_manager/graph/graph_introspector_impl.cc deleted file mode 100644 index 5e0ac80..0000000 --- a/chrome/browser/performance_manager/graph/graph_introspector_impl.cc +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/performance_manager/graph/graph_introspector_impl.h" - -#include <set> -#include <utility> -#include <vector> - -#include "base/process/process_handle.h" -#include "base/time/time.h" -#include "chrome/browser/performance_manager/graph/frame_node_impl.h" -#include "chrome/browser/performance_manager/graph/graph.h" -#include "chrome/browser/performance_manager/graph/page_node_impl.h" -#include "chrome/browser/performance_manager/graph/process_node_impl.h" -#include "services/service_manager/public/cpp/bind_source_info.h" - -namespace { - -using performance_manager::FrameNodeImpl; -using performance_manager::PageNodeImpl; -using performance_manager::ProcessNodeImpl; - -// Returns true iff the given |process| is responsible for hosting the -// main-frame of the given |page|. -bool HostsMainFrame(ProcessNodeImpl* process, PageNodeImpl* page) { - FrameNodeImpl* main_frame = page->GetMainFrameNode(); - if (main_frame == nullptr) { - // |process| can't host a frame that doesn't exist. - return false; - } - - return main_frame->process_node() == process; -} - -} // namespace - -namespace performance_manager { - -CoordinationUnitIntrospectorImpl::CoordinationUnitIntrospectorImpl(Graph* graph) - : graph_(graph) {} - -CoordinationUnitIntrospectorImpl::~CoordinationUnitIntrospectorImpl() = default; - -void CoordinationUnitIntrospectorImpl::GetProcessToURLMap( - GetProcessToURLMapCallback callback) { - std::vector<resource_coordinator::mojom::ProcessInfoPtr> process_infos; - std::vector<ProcessNodeImpl*> process_nodes = graph_->GetAllProcessNodes(); - for (auto* process_node : process_nodes) { - if (process_node->process_id() == base::kNullProcessId) - continue; - - resource_coordinator::mojom::ProcessInfoPtr process_info( - resource_coordinator::mojom::ProcessInfo::New()); - process_info->pid = process_node->process_id(); - process_info->launch_time = process_node->launch_time(); - - std::set<PageNodeImpl*> page_nodes = - process_node->GetAssociatedPageCoordinationUnits(); - for (PageNodeImpl* page_node : page_nodes) { - if (page_node->ukm_source_id() == ukm::kInvalidSourceId) - continue; - - resource_coordinator::mojom::PageInfoPtr page_info( - resource_coordinator::mojom::PageInfo::New()); - page_info->ukm_source_id = page_node->ukm_source_id(); - page_info->tab_id = page_node->id().id; - page_info->hosts_main_frame = HostsMainFrame(process_node, page_node); - page_info->is_visible = page_node->is_visible(); - page_info->time_since_last_visibility_change = - page_node->TimeSinceLastVisibilityChange(); - page_info->time_since_last_navigation = - page_node->TimeSinceLastNavigation(); - process_info->page_infos.push_back(std::move(page_info)); - } - process_infos.push_back(std::move(process_info)); - } - std::move(callback).Run(std::move(process_infos)); -} - -void CoordinationUnitIntrospectorImpl::BindToInterface( - resource_coordinator::mojom::CoordinationUnitIntrospectorRequest request, - const service_manager::BindSourceInfo& source_info) { - bindings_.AddBinding(this, std::move(request)); -} - -} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/graph_introspector_impl.h b/chrome/browser/performance_manager/graph/graph_introspector_impl.h deleted file mode 100644 index 6a2d22e..0000000 --- a/chrome/browser/performance_manager/graph/graph_introspector_impl.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_GRAPH_INTROSPECTOR_IMPL_H_ -#define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_GRAPH_INTROSPECTOR_IMPL_H_ - -#include "mojo/public/cpp/bindings/binding_set.h" -#include "services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom.h" -#include "services/service_manager/public/cpp/bind_source_info.h" - -namespace service_manager { -struct BindSourceInfo; -} // namespace service_manager - -namespace performance_manager { - -class Graph; - -class CoordinationUnitIntrospectorImpl - : public resource_coordinator::mojom::CoordinationUnitIntrospector { - public: - explicit CoordinationUnitIntrospectorImpl(Graph* graph); - ~CoordinationUnitIntrospectorImpl() override; - - void BindToInterface( - resource_coordinator::mojom::CoordinationUnitIntrospectorRequest request, - const service_manager::BindSourceInfo& source_info); - - // Overridden from resource_coordinator::mojom::CoordinationUnitIntrospector: - void GetProcessToURLMap(GetProcessToURLMapCallback callback) override; - - private: - Graph* const graph_; - mojo::BindingSet<resource_coordinator::mojom::CoordinationUnitIntrospector> - bindings_; - - DISALLOW_COPY_AND_ASSIGN(CoordinationUnitIntrospectorImpl); -}; - -} // namespace performance_manager - -#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_GRAPH_INTROSPECTOR_IMPL_H_
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc index 57a6713..3adea9f 100644 --- a/chrome/browser/performance_manager/performance_manager.cc +++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -41,8 +41,7 @@ return g_performance_manager; } -PerformanceManager::PerformanceManager() - : task_runner_(CreateTaskRunner()), introspector_(&graph_) { +PerformanceManager::PerformanceManager() : task_runner_(CreateTaskRunner()) { DETACH_FROM_SEQUENCE(sequence_checker_); } @@ -252,10 +251,6 @@ std::unique_ptr<service_manager::Connector> connector) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - interface_registry_.AddInterface( - base::BindRepeating(&CoordinationUnitIntrospectorImpl::BindToInterface, - base::Unretained(&introspector_))); - // Register new |GraphObserver| implementations here. auto page_signal_generator_impl = std::make_unique<PageSignalGeneratorImpl>(); interface_registry_.AddInterface(
diff --git a/chrome/browser/performance_manager/performance_manager.h b/chrome/browser/performance_manager/performance_manager.h index 8d8c30b..6b3a157 100644 --- a/chrome/browser/performance_manager/performance_manager.h +++ b/chrome/browser/performance_manager/performance_manager.h
@@ -15,7 +15,6 @@ #include "base/sequence_checker.h" #include "base/sequenced_task_runner.h" #include "chrome/browser/performance_manager/graph/graph.h" -#include "chrome/browser/performance_manager/graph/graph_introspector_impl.h" #include "chrome/browser/performance_manager/performance_manager.h" #include "chrome/browser/performance_manager/webui_graph_dump_impl.h" #include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h" @@ -136,8 +135,6 @@ // The registered graph observers. std::vector<std::unique_ptr<GraphObserver>> observers_; - CoordinationUnitIntrospectorImpl introspector_; - // Provided to |graph_|. // TODO(siggi): This no longer needs to go through mojo. std::unique_ptr<ukm::MojoUkmRecorder> ukm_recorder_;
diff --git a/chrome/browser/policy/test/policy_testserver.py b/chrome/browser/policy/test/policy_testserver.py index 5a16814f..6be5bb6 100644 --- a/chrome/browser/policy/test/policy_testserver.py +++ b/chrome/browser/policy/test/policy_testserver.py
@@ -58,6 +58,8 @@ "token": "abcd-ef01-123123123", "username": "admin@example.com" }, + "device_register_http_error" : 902, + "allow_set_device_attributes" : false, } """ @@ -427,6 +429,9 @@ if not auth: return (403, 'No authorization') + if 'device_register_http_error' in policy: + return (policy['device_register_http_error'], 'Preconfigured error') + if ('managed_users' not in policy): return (500, 'Error in config - no managed users') username = self.server.ResolveUser(auth) @@ -716,8 +721,15 @@ A tuple of HTTP status code and response data to send to the client. """ response = dm.DeviceManagementResponse() + policy = self.server.GetPolicies() + update_allowed = True + if ('allow_set_device_attributes' in policy): + update_allowed = policy['allow_set_device_attributes'] + response.device_attribute_update_permission_response.result = ( - dm.DeviceAttributeUpdatePermissionResponse.ATTRIBUTE_UPDATE_ALLOWED) + dm.DeviceAttributeUpdatePermissionResponse.ATTRIBUTE_UPDATE_ALLOWED + if update_allowed else + dm.DeviceAttributeUpdatePermissionResponse.ATTRIBUTE_UPDATE_DISALLOWED) return (200, response)
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js index e9893ba..22854d3 100644 --- a/chrome/browser/resources/print_preview/data/destination.js +++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -201,8 +201,8 @@ */ print_preview.PinModeRestriction = { NONE: 0, - SECURE: 1, - UNSECURE: 2 + PIN: 1, + NO_PIN: 2 }; /**
diff --git a/chrome/browser/resources/print_preview/new/model.js b/chrome/browser/resources/print_preview/new/model.js index d425c53f..19c144f 100644 --- a/chrome/browser/resources/print_preview/new/model.js +++ b/chrome/browser/resources/print_preview/new/model.js
@@ -1002,7 +1002,7 @@ !!duplexPolicy && setDuplexTypeByPolicy); const pinPolicy = this.destination.pinPolicy; - if (pinPolicy == print_preview.PinModeRestriction.UNSECURE) { + if (pinPolicy == print_preview.PinModeRestriction.NO_PIN) { this.set('settings.pin.available', false); this.set('settings.pinValue.available', false); } @@ -1010,7 +1010,7 @@ if (pinValue) { this.set( 'settings.pin.value', - pinValue == print_preview.PinModeRestriction.SECURE); + pinValue == print_preview.PinModeRestriction.PIN); } this.set('settings.pin.setByPolicy', !!pinPolicy);
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc index 368ecc1..5c59e12 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc
@@ -321,7 +321,10 @@ EXPECT_TRUE(last_request_headers().GetHeader(signin::kChromeConnectedHeader, &header_value)); // mode = PROFILE_MODE_DEFAULT - EXPECT_EQ("mode=0,enable_account_consistency=false", header_value); + EXPECT_EQ( + "mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false", + header_value); #else // On not Chrome OS, the X-Chrome-Connected header must not be present. EXPECT_FALSE( @@ -356,7 +359,10 @@ EXPECT_TRUE(last_request_headers().GetHeader(signin::kChromeConnectedHeader, &header_value)); // mode = PROFILE_MODE_INCOGNITO_DISABLED | PROFILE_MODE_ADD_ACCOUNT_DISABLED - EXPECT_EQ("mode=3,enable_account_consistency=true", header_value); + EXPECT_EQ( + "mode=3,enable_account_consistency=true," + "consistency_enabled_by_default=false", + header_value); #else // This is not a valid case (mirror account consistency can only be required // on Chrome OS). This ensures in this case nothing happens.
diff --git a/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc b/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc index 183a883d..65c7bb9 100644 --- a/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc +++ b/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc
@@ -139,7 +139,8 @@ ASSERT_EQ(3, signin::PROFILE_MODE_INCOGNITO_DISABLED | signin::PROFILE_MODE_ADD_ACCOUNT_DISABLED); TestMirrorRequestForProfile(test_server_.get(), profile, - "mode=3,enable_account_consistency=true"); + "mode=3,enable_account_consistency=true," + "consistency_enabled_by_default=false"); } class ChromeOsMirrorAccountConsistencyTestWithAccountManagerEnabled @@ -185,5 +186,6 @@ EXPECT_TRUE( AccountConsistencyModeManager::IsMirrorEnabledForProfile(profile)); TestMirrorRequestForProfile(test_server_.get(), profile, - "mode=0,enable_account_consistency=true"); + "mode=0,enable_account_consistency=true," + "consistency_enabled_by_default=false"); }
diff --git a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc index 14e9db2..29ed8b5 100644 --- a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
@@ -14,6 +14,8 @@ #include "components/sync/driver/profile_sync_service.h" #include "components/sync/driver/sync_driver_switches.h" +namespace { + using passwords_helper::AddLogin; using passwords_helper::CreateTestPasswordForm; using passwords_helper::GetPasswordCount; @@ -24,6 +26,9 @@ using autofill::PasswordForm; +using testing::ElementsAre; +using testing::IsEmpty; + class SingleClientPasswordsSyncTest : public FeatureToggler, public SyncTest { public: SingleClientPasswordsSyncTest() @@ -199,3 +204,58 @@ INSTANTIATE_TEST_SUITE_P(USS, SingleClientPasswordsSyncTest, ::testing::Values(false, true)); + +class SingleClientPasswordsSyncUssMigratorTest : public SyncTest { + public: + SingleClientPasswordsSyncUssMigratorTest() : SyncTest(SINGLE_CLIENT) {} + ~SingleClientPasswordsSyncUssMigratorTest() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(SingleClientPasswordsSyncUssMigratorTest); +}; + +// Creates and syncs two passwords before USS being enabled. +IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncUssMigratorTest, + PRE_ExerciseUssMigrator) { + base::test::ScopedFeatureList override_features; + override_features.InitAndDisableFeature(switches::kSyncUSSPasswords); + + ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + AddLogin(GetPasswordStore(0), CreateTestPasswordForm(0)); + AddLogin(GetPasswordStore(0), CreateTestPasswordForm(1)); + ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait()); + ASSERT_EQ(2, GetPasswordCount(0)); +} + +// Now that local passwords, the local sync directory and the sever are +// populated with two passwords, USS is enabled for passwords. +IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncUssMigratorTest, + ExerciseUssMigrator) { + base::test::ScopedFeatureList override_features; + override_features.InitAndEnableFeature(switches::kSyncUSSPasswords); + + base::HistogramTester histogram_tester; + ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + ASSERT_EQ(2, GetPasswordCount(0)); +#if defined(CHROMEOS) + // identity::SetRefreshTokenForPrimaryAccount() is needed on ChromeOS in order + // to get a non-empty refresh token on startup. + GetClient(0)->SignInPrimaryAccount(); +#endif // defined(CHROMEOS) + ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion()); + ASSERT_EQ(2, GetPasswordCount(0)); + + EXPECT_EQ(1, histogram_tester.GetBucketCount( + "Sync.USSMigrationSuccess", + syncer::ModelTypeToHistogramInt(syncer::PASSWORDS))); + EXPECT_THAT( + histogram_tester.GetAllSamples("Sync.USSMigrationEntityCount.PASSWORD"), + ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); + EXPECT_THAT(histogram_tester.GetAllSamples("Sync.DataTypeStartFailures2"), + IsEmpty()); + EXPECT_EQ( + 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.PASSWORD", + /*REMOTE_INITIAL_UPDATE=*/5)); +} + +} // namespace
diff --git a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc index 94618a0..4b1be45 100644 --- a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
@@ -304,19 +304,4 @@ EXPECT_TRUE(ExpectUserEvents({test_event1})); } -IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, FieldTrial) { - const std::string trial_name = "TrialName"; - const std::string group_name = "GroupName"; - - ASSERT_TRUE(SetupSync()); - variations::AssociateGoogleVariationID(variations::CHROME_SYNC_EVENT_LOGGER, - trial_name, group_name, 123); - base::FieldTrialList::CreateFieldTrial(trial_name, group_name); - base::FieldTrialList::FindFullName(trial_name); - - UserEventCaseChecker(GetSyncService(0), GetFakeServer(), - {UserEventSpecifics::kFieldTrialEvent}) - .Wait(); -} - } // namespace
diff --git a/chrome/browser/ui/ash/ash_test_util.cc b/chrome/browser/ui/ash/ash_test_util.cc new file mode 100644 index 0000000..47aeaa7 --- /dev/null +++ b/chrome/browser/ui/ash/ash_test_util.cc
@@ -0,0 +1,37 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/ash_test_util.h" + +#include "ash/public/interfaces/constants.mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" +#include "base/run_loop.h" +#include "content/public/common/service_manager_connection.h" +#include "services/service_manager/public/cpp/connector.h" +#include "ui/aura/test/mus/change_completion_waiter.h" + +namespace test { + +ash::mojom::ShellTestApiPtr GetShellTestApi() { + ash::mojom::ShellTestApiPtr shell_test_api; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &shell_test_api); + + return shell_test_api; +} + +void WaitForNoPointerHoldLock(bool wait_for_changes) { + ash::mojom::ShellTestApiPtr shell_test_api = GetShellTestApi(); + + // Allow nestable tasks because this is called within a move loop. + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + shell_test_api->WaitForNoPointerHoldLock(run_loop.QuitClosure()); + run_loop.Run(); + + if (wait_for_changes) + aura::test::WaitForAllChangesToComplete(); +} + +} // namespace test
diff --git a/chrome/browser/ui/ash/ash_test_util.h b/chrome/browser/ui/ash/ash_test_util.h new file mode 100644 index 0000000..0fb0ded --- /dev/null +++ b/chrome/browser/ui/ash/ash_test_util.h
@@ -0,0 +1,23 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_ASH_ASH_TEST_UTIL_H_ +#define CHROME_BROWSER_UI_ASH_ASH_TEST_UTIL_H_ + +#include "ash/public/interfaces/shell_test_api.test-mojom-test-utils.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" + +namespace test { + +// Binds to ash service and returns a ShellTestApiPtr. +ash::mojom::ShellTestApiPtr GetShellTestApi(); + +// Waits until WindowTreeHost no longer holding pointer events. +// If |wait_for_all_changes| is true, this also runs +// aura::test::WaitForAllChangesToComplete(). +void WaitForNoPointerHoldLock(bool wait_for_changes = true); + +} // namespace test + +#endif // CHROME_BROWSER_UI_ASH_ASH_TEST_UTIL_H_
diff --git a/chrome/browser/ui/ash/drag_to_overview_interactive_uitest.cc b/chrome/browser/ui/ash/drag_to_overview_interactive_uitest.cc new file mode 100644 index 0000000..cad041f --- /dev/null +++ b/chrome/browser/ui/ash/drag_to_overview_interactive_uitest.cc
@@ -0,0 +1,215 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/public/cpp/ash_switches.h" +#include "base/bind.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/task/post_task.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/ui/ash/ash_test_util.h" +#include "chrome/browser/ui/ash/tablet_mode_client_test_util.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/tabs/tab_drag_controller.h" +#include "chrome/browser/ui/views/tabs/tab_strip.h" +#include "chrome/test/base/interactive_test_utils.h" +#include "chrome/test/base/perf/performance_test.h" +#include "content/public/browser/notification_service.h" +#include "content/public/test/test_utils.h" +#include "services/service_manager/public/cpp/connector.h" +#include "ui/aura/window.h" +#include "ui/base/test/ui_controls.h" +#include "ui/compositor/compositor.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/gfx/geometry/vector2d.h" +#include "ui/views/widget/widget.h" + +namespace { + +bool IsOverviewSelecting() { + ash::mojom::ShellTestApiPtr shell_test_api = test::GetShellTestApi(); + ash::mojom::ShellTestApiAsyncWaiter waiter(shell_test_api.get()); + bool is_selecting = false; + waiter.IsOverviewSelecting(&is_selecting); + return is_selecting; +} + +int GetDetachY(TabStrip* tab_strip) { + return std::max(TabDragController::kTouchVerticalDetachMagnetism, + TabDragController::kVerticalDetachMagnetism) + + tab_strip->height() + 1; +} + +// Waits for the primary display to present a frame after the object is +// constructed. +class NextFrameWaiter { + public: + NextFrameWaiter() : shell_test_api_(test::GetShellTestApi()) { + shell_test_api_->WaitForNextFrame(base::BindOnce( + &NextFrameWaiter::OnFramePresented, base::Unretained(this))); + // Flush to ensure the call has gone through. + shell_test_api_.FlushForTesting(); + } + ~NextFrameWaiter() { EXPECT_TRUE(frame_presented_); } + + void WaitForDisplay() { + if (!frame_presented_) { + run_loop_ = std::make_unique<base::RunLoop>( + base::RunLoop::Type::kNestableTasksAllowed); + run_loop_->Run(); + EXPECT_TRUE(frame_presented_); + } + } + + private: + void OnFramePresented() { + frame_presented_ = true; + if (run_loop_) + run_loop_->Quit(); + } + + ash::mojom::ShellTestApiPtr shell_test_api_; + bool frame_presented_ = false; + std::unique_ptr<base::RunLoop> run_loop_; + + DISALLOW_COPY_AND_ASSIGN(NextFrameWaiter); +}; + +} // namespace + +class DragToOverviewTest : public UIPerformanceTest { + public: + DragToOverviewTest() = default; + ~DragToOverviewTest() override = default; + + // UIPerformanceTest: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(ash::switches::kAshEnableTabletMode); + } + void SetUpOnMainThread() override { + test::SetAndWaitForTabletMode(true); + + if (base::SysInfo::IsRunningOnChromeOS()) { + base::RunLoop run_loop; + base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), + base::TimeDelta::FromSeconds(5)); + run_loop.Run(); + } + } + std::vector<std::string> GetUMAHistogramNames() const override { + return { + "Ash.SwipeDownDrag.Window.PresentationTime.TabletMode", + "Ash.SwipeDownDrag.Window.PresentationTime.MaxLatency.TabletMode", + "Ash.SwipeDownDrag.Tab.PresentationTime.TabletMode", + "Ash.SwipeDownDrag.Tab.PresentationTime.MaxLatency.TabletMode", + }; + } + + // Continue a drag by perform |count| steps mouse dragging with each step move + // |delta|, then moue up. + void ContinueDrag(const gfx::Point& start_position, + const gfx::Vector2d& delta, + int count) { + gfx::Point drag_position = start_position; + for (int i = 0; i < count; ++i) { + drag_position += delta; + + test::WaitForNoPointerHoldLock(/*wait_for_changes=*/false); + NextFrameWaiter waiter; + ASSERT_TRUE( + ui_controls::SendMouseMove(drag_position.x(), drag_position.y())); + waiter.WaitForDisplay(); + } + + { + NextFrameWaiter waiter; + ASSERT_TRUE( + ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP)); + waiter.WaitForDisplay(); + } + } + + void VerifyTabDetachedAndContinueDrag(const gfx::Point& start_position, + const gfx::Vector2d delta, + int count) { + // Tab should be detached to create a new browser window. + EXPECT_EQ(2u, BrowserList::GetInstance()->size()); + EXPECT_TRUE(TabDragController::IsActive()); + + ContinueDrag(start_position, delta, count); + } + + private: + DISALLOW_COPY_AND_ASSIGN(DragToOverviewTest); +}; + +IN_PROC_BROWSER_TEST_F(DragToOverviewTest, DragWindow) { + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); + aura::Window* browser_window = browser_view->GetWidget()->GetNativeWindow(); + gfx::Rect browser_screen_bounds = browser_window->GetBoundsInScreen(); + + const gfx::Point start_position( + browser_screen_bounds.CenterPoint().x(), + browser_screen_bounds.y() + browser_view->GetTabStripHeight() / 2); + + test::WaitForNoPointerHoldLock(); + ASSERT_TRUE( + ui_test_utils::SendMouseMoveSync(start_position) && + ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::DOWN)); + + // One more mouse move to start drag. + ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(start_position)); + + // Drag 25% of the work area height. + const int drag_length = display::Screen::GetScreen() + ->GetDisplayNearestWindow(browser_window) + .work_area_size() + .height() / + 4; + constexpr int kSteps = 20; + gfx::Vector2d delta(0, drag_length / kSteps); + ContinueDrag(start_position, delta, kSteps); + EXPECT_TRUE(IsOverviewSelecting()); +} + +IN_PROC_BROWSER_TEST_F(DragToOverviewTest, DragTab) { + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); + aura::Window* browser_window = browser_view->GetWidget()->GetNativeWindow(); + + AddBlankTabAndShow(browser()); + browser_view->tabstrip()->StopAnimating(true); + + gfx::Point drag_position(ui_test_utils::GetCenterInScreenCoordinates( + browser_view->tabstrip()->tab_at(0))); + + test::WaitForNoPointerHoldLock(); + ASSERT_TRUE( + ui_test_utils::SendMouseMoveSync(drag_position) && + ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::DOWN)); + + // Drag 25% of the work area height. + const int drag_length = display::Screen::GetScreen() + ->GetDisplayNearestWindow(browser_window) + .work_area_size() + .height() / + 4; + constexpr int kSteps = 20; + gfx::Vector2d delta(0, drag_length / kSteps); + + // Drag tab far enough to detach. + drag_position.Offset(0, GetDetachY(browser_view->tabstrip())); + ui_controls::SendMouseMoveNotifyWhenDone( + drag_position.x(), drag_position.y(), + base::BindOnce(&DragToOverviewTest::VerifyTabDetachedAndContinueDrag, + base::Unretained(this), drag_position, delta, kSteps)); + + // Wait for the drag to finish. + content::WindowedNotificationObserver( + chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, + content::NotificationService::AllSources()) + .Wait(); +}
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc index f314c433..18aabb9d 100644 --- a/chrome/browser/ui/ash/session_controller_client.cc +++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -26,6 +26,8 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/policy/profile_policy_connector.h" +#include "chrome/browser/policy/profile_policy_connector_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profiles_state.h" @@ -100,6 +102,18 @@ session->user_info->is_ephemeral = UserManager::Get()->IsUserNonCryptohomeDataEphemeral(user.GetAccountId()); session->user_info->has_gaia_account = user.has_gaia_account(); + if (user.GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT || + user.GetType() == user_manager::USER_TYPE_KIOSK_APP || + user.GetType() == user_manager::USER_TYPE_ARC_KIOSK_APP) { + session->user_info->is_managed = true; + } else { + session->user_info->is_managed = + (profile && + policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile) != + nullptr && + policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile) + ->IsManaged()); + } const AccountId& owner_id = UserManager::Get()->GetOwnerAccountId(); session->user_info->is_device_owner = owner_id.is_valid() && owner_id == user.GetAccountId();
diff --git a/chrome/browser/ui/ash/split_view_interactive_uitest.cc b/chrome/browser/ui/ash/split_view_interactive_uitest.cc index 0b215b9..311581b 100644 --- a/chrome/browser/ui/ash/split_view_interactive_uitest.cc +++ b/chrome/browser/ui/ash/split_view_interactive_uitest.cc
@@ -3,9 +3,6 @@ // found in the LICENSE file. #include "ash/public/cpp/ash_switches.h" -#include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shell_test_api.test-mojom-test-utils.h" -#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "ash/shell.h" // mash-ok #include "ash/wm/splitview/split_view_controller.h" // mash-ok #include "base/macros.h" @@ -13,17 +10,15 @@ #include "base/system/sys_info.h" #include "base/task/post_task.h" #include "base/test/bind_test_util.h" +#include "chrome/browser/ui/ash/ash_test_util.h" #include "chrome/browser/ui/ash/tablet_mode_client_test_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/perf/performance_test.h" -#include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" -#include "services/service_manager/public/cpp/connector.h" #include "ui/aura/mus/window_mus.h" -#include "ui/aura/test/mus/change_completion_waiter.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/base/ui_base_features.h" @@ -48,11 +43,8 @@ SplitViewTest() = default; ~SplitViewTest() override = default; - // InProcessBrowserTest: + // UIPerformanceTest: void SetUpCommandLine(base::CommandLine* command_line) override { - // Make sure the test actually draws to screen and uses the real gpu. - command_line->AppendSwitch(switches::kEnablePixelOutputInTests); - command_line->AppendSwitch(switches::kUseGpuInTests); command_line->AppendSwitch(ash::switches::kAshEnableTabletMode); } @@ -64,16 +56,6 @@ DISALLOW_COPY_AND_ASSIGN(SplitViewTest); }; -void WaitForNoPointerHoldLock() { - ash::mojom::ShellTestApiPtr shell_test_api; - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(ash::mojom::kServiceName, &shell_test_api); - ash::mojom::ShellTestApiAsyncWaiter waiter(shell_test_api.get()); - waiter.WaitForNoPointerHoldLock(); - aura::test::WaitForAllChangesToComplete(); -} - // Used to wait for a window resize to show up on screen. class WidgetResizeWaiter : public views::WidgetObserver { public: @@ -87,12 +69,14 @@ } void WaitForDisplay() { - if (waiting_for_frame_) { - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - EXPECT_FALSE(waiting_for_frame_); - } - WaitForNoPointerHoldLock(); + do { + if (waiting_for_frame_) { + run_loop_ = std::make_unique<base::RunLoop>(); + run_loop_->Run(); + EXPECT_FALSE(waiting_for_frame_); + } + test::WaitForNoPointerHoldLock(); + } while (waiting_for_frame_); } private: @@ -150,10 +134,7 @@ views::Widget* browser2_widget = BrowserView::GetBrowserViewForBrowser(browser2)->GetWidget(); if (features::IsUsingWindowService()) { - ash::mojom::ShellTestApiPtr shell_test_api; - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(ash::mojom::kServiceName, &shell_test_api); + ash::mojom::ShellTestApiPtr shell_test_api = test::GetShellTestApi(); { base::RunLoop run_loop; @@ -180,7 +161,7 @@ shell->split_view_controller()->FlushForTesting(); } - WaitForNoPointerHoldLock(); + test::WaitForNoPointerHoldLock(); const gfx::Size display_size = display::Screen::GetScreen()->GetPrimaryDisplay().bounds().size();
diff --git a/chrome/browser/ui/views/payments/payment_request_item_list.cc b/chrome/browser/ui/views/payments/payment_request_item_list.cc index b42e692..c0db5bf2c 100644 --- a/chrome/browser/ui/views/payments/payment_request_item_list.cc +++ b/chrome/browser/ui/views/payments/payment_request_item_list.cc
@@ -124,14 +124,11 @@ void PaymentRequestItemList::Item::SetSelected(bool selected, bool notify) { selected_ = selected; - (void)std::find_if( - children().cbegin(), children().cend(), [selected](views::View* child) { - bool found = - child->id() == static_cast<int>(DialogViewID::CHECKMARK_VIEW); - if (found) - child->SetVisible(selected); - return found; - }); + for (views::View* child : children()) + if (child->id() == static_cast<int>(DialogViewID::CHECKMARK_VIEW)) { + child->SetVisible(selected); + break; + } UpdateAccessibleName();
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc index a3bc4c2..16f94cff 100644 --- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc +++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -171,6 +171,11 @@ sheet_view = std::make_unique<AuthenticatorSelectAccountSheetView>( std::make_unique<AuthenticatorSelectAccountSheetModel>(dialog_model)); break; + case Step::kAttestationPermissionRequest: + sheet_view = std::make_unique<AuthenticatorRequestSheetView>( + std::make_unique<AttestationPermissionRequestSheetModel>( + dialog_model)); + break; case Step::kNotStarted: case Step::kClosed: sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc index eafef88..4ecd52e 100644 --- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc +++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
@@ -145,6 +145,8 @@ model->SelectAccount( std::move(responses), base::Bind([](device::AuthenticatorGetAssertionResponse) {})); + } else if (name == "request_attestation_permission") { + model->RequestAttestationPermission(base::DoNothing()); } ShowAuthenticatorRequestDialog( @@ -279,3 +281,8 @@ IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_account_select) { ShowAndVerifyUi(); } + +IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, + InvokeUi_request_attestation_permission) { + ShowAndVerifyUi(); +}
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc index c7561620..e4b377b 100644 --- a/chrome/browser/ui/webauthn/sheet_models.cc +++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -1030,3 +1030,54 @@ void AuthenticatorSelectAccountSheetModel::SetObserver( ui::TableModelObserver* observer) {} + +// AttestationPermissionRequestSheetModel ------------------------------------- + +AttestationPermissionRequestSheetModel::AttestationPermissionRequestSheetModel( + AuthenticatorRequestDialogModel* dialog_model) + : AuthenticatorSheetModelBase(dialog_model) {} + +AttestationPermissionRequestSheetModel:: + ~AttestationPermissionRequestSheetModel() = default; + +void AttestationPermissionRequestSheetModel::OnAccept() { + dialog_model()->OnAttestationPermissionResponse(true); +} + +void AttestationPermissionRequestSheetModel::OnCancel() { + dialog_model()->OnAttestationPermissionResponse(false); +} + +gfx::ImageSkia* AttestationPermissionRequestSheetModel::GetStepIllustration() + const { + return GetImage(IDR_WEBAUTHN_ILLUSTRATION_PERMISSION); +} + +base::string16 AttestationPermissionRequestSheetModel::GetStepTitle() const { + return l10n_util::GetStringUTF16( + IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_TITLE); +} + +base::string16 AttestationPermissionRequestSheetModel::GetStepDescription() + const { + return l10n_util::GetStringFUTF16( + IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_DESC, + GetRelyingPartyIdString()); +} + +bool AttestationPermissionRequestSheetModel::IsAcceptButtonVisible() const { + return true; +} + +bool AttestationPermissionRequestSheetModel::IsAcceptButtonEnabled() const { + return true; +} + +base::string16 AttestationPermissionRequestSheetModel::GetAcceptButtonLabel() + const { + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ALLOW_ATTESTATION); +} + +bool AttestationPermissionRequestSheetModel::IsCancelButtonVisible() const { + return true; +}
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h index 7eae1cb..b1419e4 100644 --- a/chrome/browser/ui/webauthn/sheet_models.h +++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -486,4 +486,25 @@ size_t selected_ = 0; }; +class AttestationPermissionRequestSheetModel + : public AuthenticatorSheetModelBase { + public: + explicit AttestationPermissionRequestSheetModel( + AuthenticatorRequestDialogModel* dialog_model); + ~AttestationPermissionRequestSheetModel() override; + + // AuthenticatorSheetModelBase: + void OnAccept() override; + void OnCancel() override; + + private: + // AuthenticatorSheetModelBase: + gfx::ImageSkia* GetStepIllustration() const override; + base::string16 GetStepTitle() const override; + base::string16 GetStepDescription() const override; + bool IsAcceptButtonVisible() const override; + bool IsAcceptButtonEnabled() const override; + base::string16 GetAcceptButtonLabel() const override; + bool IsCancelButtonVisible() const override; +}; #endif // CHROME_BROWSER_UI_WEBAUTHN_SHEET_MODELS_H_
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc index b7e652cf..3f5b7c97 100644 --- a/chrome/browser/ui/webui/sync_internals_message_handler.cc +++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/command_line.h" -#include "base/feature_list.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "chrome/browser/profiles/profile.h" @@ -263,9 +262,10 @@ const base::ListValue* args) { DCHECK(args->empty()); AllowJavascript(); - CallJavascriptFunction( - syncer::sync_ui_util::kUserEventsVisibilityCallback, - Value(base::FeatureList::IsEnabled(switches::kSyncUserEvents))); + // TODO(crbug.com/934333): Get rid of this callback now that user events are + // always enabled. + CallJavascriptFunction(syncer::sync_ui_util::kUserEventsVisibilityCallback, + Value(true)); } void SyncInternalsMessageHandler::HandleSetIncludeSpecifics(
diff --git a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc index ff0156f..aa7be133 100644 --- a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc +++ b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc
@@ -12,6 +12,7 @@ #include "base/values.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/web_applications/bookmark_apps/test_web_app_provider.h" +#include "chrome/browser/web_applications/components/install_options.h" #include "chrome/browser/web_applications/components/pending_app_manager.h" #include "chrome/browser/web_applications/components/policy/web_app_policy_constants.h" #include "chrome/browser/web_applications/components/test_pending_app_manager.h" @@ -35,9 +36,9 @@ namespace { -const char kWindowedUrl[] = "https://windowed.example"; -const char kTabbedUrl[] = "https://tabbed.example"; -const char kNoContainerUrl[] = "https://no-container.example"; +const char kWindowedUrl[] = "https://windowed.example/"; +const char kTabbedUrl[] = "https://tabbed.example/"; +const char kNoContainerUrl[] = "https://no-container.example/"; base::Value GetWindowedItem() { base::Value item(base::Value::Type::DICTIONARY); @@ -161,7 +162,7 @@ return provider; } - std::string GenerateFakeExtensionId(GURL& url) { + std::string GenerateFakeExtensionId(const GURL& url) { return crx_file::id_util::GenerateId("fake_app_id_for:" + url.spec()); } @@ -383,4 +384,52 @@ pending_app_manager()->uninstall_requests()); } +// Tests that we correctly reinstall a placeholder app. +TEST_F(WebAppPolicyManagerTest, ReinstallPlaceholderApp) { + base::Value list(base::Value::Type::LIST); + list.GetList().push_back(GetWindowedItem()); + profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list)); + + policy_manager()->Start(); + base::RunLoop().RunUntilIdle(); + + std::vector<InstallOptions> expected_options_list; + expected_options_list.push_back(GetWindowedInstallOptions()); + + const auto& install_options_list = pending_app_manager()->install_requests(); + EXPECT_EQ(expected_options_list, install_options_list); + + policy_manager()->ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(expected_options_list, install_options_list); + + const auto& reinstall_options_list = + pending_app_manager()->reinstall_requests(); + EXPECT_EQ(expected_options_list, reinstall_options_list); +} + +TEST_F(WebAppPolicyManagerTest, TryToInexistentPlaceholderApp) { + base::Value list(base::Value::Type::LIST); + list.GetList().push_back(GetWindowedItem()); + profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list)); + + policy_manager()->Start(); + base::RunLoop().RunUntilIdle(); + + std::vector<InstallOptions> expected_options_list; + expected_options_list.push_back(GetWindowedInstallOptions()); + + const auto& install_options_list = pending_app_manager()->install_requests(); + EXPECT_EQ(expected_options_list, install_options_list); + EXPECT_TRUE(pending_app_manager()->reinstall_requests().empty()); + + // Try to reinstall for app not installed by policy. + policy_manager()->ReinstallPlaceholderAppIfNecessary(GURL(kTabbedUrl)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(expected_options_list, install_options_list); + EXPECT_TRUE(pending_app_manager()->reinstall_requests().empty()); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/components/pending_app_manager.h b/chrome/browser/web_applications/components/pending_app_manager.h index f423a3a..1b4c158a 100644 --- a/chrome/browser/web_applications/components/pending_app_manager.h +++ b/chrome/browser/web_applications/components/pending_app_manager.h
@@ -74,6 +74,14 @@ virtual void UninstallApps(std::vector<GURL> uninstall_urls, const UninstallCallback& callback) = 0; + // If there is a placeholder app for |install_options.url| removes that app + // and tries to install the app again. + // TODO(ortuno): Temporarily use the same callback as Install. We should + // figure out if we want a separate enum for reinstall results or just re-use + // the InstallResult enum for both methods. + virtual void ReinstallPlaceholderApp(InstallOptions install_options, + OnceInstallCallback callback) = 0; + // Returns the URLs of those apps installed from |install_source|. virtual std::vector<GURL> GetInstalledAppUrls( InstallSource install_source) const = 0;
diff --git a/chrome/browser/web_applications/components/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/components/policy/web_app_policy_manager.cc index 09df440c..77100ad 100644 --- a/chrome/browser/web_applications/components/policy/web_app_policy_manager.cc +++ b/chrome/browser/web_applications/components/policy/web_app_policy_manager.cc
@@ -4,13 +4,16 @@ #include "chrome/browser/web_applications/components/policy/web_app_policy_manager.h" +#include <algorithm> #include <utility> #include <vector> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/task/post_task.h" #include "base/values.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/components/install_options.h" #include "chrome/browser/web_applications/components/policy/web_app_policy_constants.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/common/pref_names.h" @@ -21,6 +24,51 @@ namespace web_app { +namespace { + +InstallOptions GetInstallOptionsForPolicyEntry(const base::Value& entry) { + const base::Value& url = *entry.FindKey(kUrlKey); + const base::Value* default_launch_container = + entry.FindKey(kDefaultLaunchContainerKey); + const base::Value* create_desktop_shortcut = + entry.FindKey(kCreateDesktopShorcutKey); + + DCHECK(!default_launch_container || + default_launch_container->GetString() == + kDefaultLaunchContainerWindowValue || + default_launch_container->GetString() == + kDefaultLaunchContainerTabValue); + + LaunchContainer launch_container; + if (!default_launch_container) { + launch_container = LaunchContainer::kTab; + } else if (default_launch_container->GetString() == + kDefaultLaunchContainerTabValue) { + launch_container = LaunchContainer::kTab; + } else { + launch_container = LaunchContainer::kWindow; + } + + InstallOptions install_options(GURL(url.GetString()), launch_container, + web_app::InstallSource::kExternalPolicy); + + bool create_shortcut = false; + if (create_desktop_shortcut) + create_shortcut = create_desktop_shortcut->GetBool(); + + install_options.add_to_applications_menu = create_shortcut; + install_options.add_to_desktop = create_shortcut; + + // It's not yet clear how pinning to shelf will work for policy installed + // Web Apps, but for now never pin them. See crbug.com/880125. + install_options.add_to_quick_launch_bar = false; + + install_options.install_placeholder = true; + + return install_options; +} + +} // namespace WebAppPolicyManager::WebAppPolicyManager(Profile* profile, PendingAppManager* pending_app_manager) : profile_(profile), @@ -39,6 +87,26 @@ weak_ptr_factory_.GetWeakPtr())); } +void WebAppPolicyManager::ReinstallPlaceholderAppIfNecessary(const GURL& url) { + const base::Value* web_apps = + pref_service_->GetList(prefs::kWebAppInstallForceList); + const auto& web_apps_list = web_apps->GetList(); + + const auto it = + std::find_if(web_apps_list.begin(), web_apps_list.end(), + [&url](const base::Value& entry) { + return entry.FindKey(kUrlKey)->GetString() == url.spec(); + }); + + if (it == web_apps_list.end()) + return; + + // If the app is not a placeholder app, PendingAppManager will ignore the + // request. + pending_app_manager_->ReinstallPlaceholderApp( + GetInstallOptionsForPolicyEntry(*it), base::DoNothing()); +} + // static void WebAppPolicyManager::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { @@ -62,46 +130,8 @@ // No need to validate the types or values of the policy members because we // are using a SimpleSchemaValidatingPolicyHandler which should validate them // for us. - for (const base::Value& info : web_apps->GetList()) { - const base::Value& url = *info.FindKey(kUrlKey); - const base::Value* default_launch_container = - info.FindKey(kDefaultLaunchContainerKey); - const base::Value* create_desktop_shortcut = - info.FindKey(kCreateDesktopShorcutKey); - - DCHECK(!default_launch_container || - default_launch_container->GetString() == - kDefaultLaunchContainerWindowValue || - default_launch_container->GetString() == - kDefaultLaunchContainerTabValue); - - LaunchContainer launch_container; - if (!default_launch_container) - launch_container = LaunchContainer::kTab; - else if (default_launch_container->GetString() == - kDefaultLaunchContainerTabValue) - launch_container = LaunchContainer::kTab; - else - launch_container = LaunchContainer::kWindow; - - InstallOptions install_options(GURL(std::move(url.GetString())), - launch_container, - web_app::InstallSource::kExternalPolicy); - - bool create_shortcut = false; - if (create_desktop_shortcut) - create_shortcut = create_desktop_shortcut->GetBool(); - - install_options.add_to_applications_menu = create_shortcut; - install_options.add_to_desktop = create_shortcut; - - // It's not yet clear how pinning to shelf will work for policy installed - // Web Apps, but for now never pin them. See crbug.com/880125. - install_options.add_to_quick_launch_bar = false; - - install_options.install_placeholder = true; - - install_options_list.push_back(std::move(install_options)); + for (const base::Value& entry : web_apps->GetList()) { + install_options_list.push_back(GetInstallOptionsForPolicyEntry(entry)); } pending_app_manager_->SynchronizeInstalledApps(
diff --git a/chrome/browser/web_applications/components/policy/web_app_policy_manager.h b/chrome/browser/web_applications/components/policy/web_app_policy_manager.h index c931296..5bb4cfd 100644 --- a/chrome/browser/web_applications/components/policy/web_app_policy_manager.h +++ b/chrome/browser/web_applications/components/policy/web_app_policy_manager.h
@@ -35,6 +35,8 @@ void Start(); + void ReinstallPlaceholderAppIfNecessary(const GURL& url); + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); private:
diff --git a/chrome/browser/web_applications/components/test_pending_app_manager.cc b/chrome/browser/web_applications/components/test_pending_app_manager.cc index 17e348c8..b05481c 100644 --- a/chrome/browser/web_applications/components/test_pending_app_manager.cc +++ b/chrome/browser/web_applications/components/test_pending_app_manager.cc
@@ -72,6 +72,14 @@ } } +void TestPendingAppManager::ReinstallPlaceholderApp( + InstallOptions install_options, + OnceInstallCallback callback) { + reinstall_requests_.push_back(std::move(install_options)); + std::move(callback).Run(reinstall_requests_.back().url, + InstallResultCode::kSuccess); +} + std::vector<GURL> TestPendingAppManager::GetInstalledAppUrls( InstallSource install_source) const { std::vector<GURL> urls;
diff --git a/chrome/browser/web_applications/components/test_pending_app_manager.h b/chrome/browser/web_applications/components/test_pending_app_manager.h index 2501df37..69ebab7 100644 --- a/chrome/browser/web_applications/components/test_pending_app_manager.h +++ b/chrome/browser/web_applications/components/test_pending_app_manager.h
@@ -30,6 +30,9 @@ const std::vector<GURL>& uninstall_requests() const { return uninstall_requests_; } + const std::vector<InstallOptions>& reinstall_requests() const { + return reinstall_requests_; + } int deduped_install_count() const { return deduped_install_count_; } int deduped_uninstall_count() const { return deduped_uninstall_count_; } @@ -49,6 +52,8 @@ const RepeatingInstallCallback& callback) override; void UninstallApps(std::vector<GURL> uninstall_urls, const UninstallCallback& callback) override; + void ReinstallPlaceholderApp(InstallOptions install_options, + OnceInstallCallback callback) override; std::vector<GURL> GetInstalledAppUrls( InstallSource install_source) const override; base::Optional<std::string> LookupAppId(const GURL& url) const override; @@ -57,6 +62,7 @@ void DoInstall(InstallOptions install_options, OnceInstallCallback callback); std::vector<InstallOptions> install_requests_; std::vector<GURL> uninstall_requests_; + std::vector<InstallOptions> reinstall_requests_; int deduped_install_count_; int deduped_uninstall_count_;
diff --git a/chrome/browser/web_applications/components/web_app_tab_helper_base.cc b/chrome/browser/web_applications/components/web_app_tab_helper_base.cc index 23a6f57..6b471583 100644 --- a/chrome/browser/web_applications/components/web_app_tab_helper_base.cc +++ b/chrome/browser/web_applications/components/web_app_tab_helper_base.cc
@@ -5,7 +5,10 @@ #include "chrome/browser/web_applications/components/web_app_tab_helper_base.h" #include "base/unguessable_token.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/components/policy/web_app_policy_manager.h" #include "chrome/browser/web_applications/components/web_app_audio_focus_id_map.h" +#include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "content/public/browser/media_session.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/site_instance.h" @@ -48,6 +51,8 @@ const AppId app_id = FindAppIdInScopeOfUrl(navigation_handle->GetURL()); SetAppId(app_id); + + ReinstallPlaceholderAppIfNecessary(navigation_handle->GetURL()); } void WebAppTabHelperBase::DidCloneToNewWebContents( @@ -98,4 +103,16 @@ ->SetAudioFocusGroupId(audio_focus_group_id_); } +void WebAppTabHelperBase::ReinstallPlaceholderAppIfNecessary(const GURL& url) { + auto* provider = web_app::WebAppProviderBase::GetProviderBase( + Profile::FromBrowserContext(web_contents()->GetBrowserContext())); + DCHECK(provider); + + // WebAppPolicyManager might be nullptr in the non-extensions implementation. + if (!provider->policy_manager()) + return; + + provider->policy_manager()->ReinstallPlaceholderAppIfNecessary(url); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_tab_helper_base.h b/chrome/browser/web_applications/components/web_app_tab_helper_base.h index 088ae80..124b4c76 100644 --- a/chrome/browser/web_applications/components/web_app_tab_helper_base.h +++ b/chrome/browser/web_applications/components/web_app_tab_helper_base.h
@@ -87,6 +87,9 @@ // Updates the audio focus group id based on the current web app. void UpdateAudioFocusGroupId(); + // Triggers a reinstall of a placeholder app for |url|. + void ReinstallPlaceholderAppIfNecessary(const GURL& url); + // WebApp associated with this tab. Empty string if no app associated. AppId app_id_;
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc index 011f099..4480c40 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
@@ -93,6 +93,38 @@ } } +void PendingBookmarkAppManager::ReinstallPlaceholderApp( + web_app::InstallOptions install_options, + OnceInstallCallback callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PendingBookmarkAppManager::StartReinstallTask, + weak_ptr_factory_.GetWeakPtr(), std::move(install_options), + std::move(callback))); +} + +void PendingBookmarkAppManager::StartReinstallTask( + web_app::InstallOptions install_options, + OnceInstallCallback callback) { + base::Optional<std::string> extension_id = + extension_ids_map_.LookupPlaceholderAppId(install_options.url); + + bool uninstall_succeeded = true; + if (extension_id.has_value() && + registrar_->IsInstalled(extension_id.value())) { + uninstall_succeeded = uninstaller_->UninstallApp(install_options.url); + } + + if (!uninstall_succeeded) { + LOG(WARNING) << "Could not uninstall Web App for : " << install_options.url; + std::move(callback).Run(install_options.url, + web_app::InstallResultCode::kFailedUnknownReason); + return; + } + + Install(std::move(install_options), std::move(callback)); +} + std::vector<GURL> PendingBookmarkAppManager::GetInstalledAppUrls( web_app::InstallSource install_source) const { return web_app::ExtensionIdsMap::GetInstalledAppUrls(profile_,
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h index 614309f..f9637e08 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
@@ -63,6 +63,8 @@ const RepeatingInstallCallback& callback) override; void UninstallApps(std::vector<GURL> uninstall_urls, const UninstallCallback& callback) override; + void ReinstallPlaceholderApp(web_app::InstallOptions install_options, + OnceInstallCallback callback) override; std::vector<GURL> GetInstalledAppUrls( web_app::InstallSource install_source) const override; base::Optional<std::string> LookupAppId(const GURL& url) const override; @@ -80,6 +82,9 @@ void StartInstallationTask(std::unique_ptr<TaskAndCallback> task); + void StartReinstallTask(web_app::InstallOptions install_options, + OnceInstallCallback callback); + void CreateWebContentsIfNecessary(); void OnUrlLoaded(web_app::WebAppUrlLoader::Result result);
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc index cbaf4a1..01093db9 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
@@ -105,7 +105,7 @@ BookmarkAppInstallationTask::ResultCallback callback) override { std::move(on_install_placeholder_called_).Run(); if (succeeds_) { - std::move(callback).Run(SimulateInstallingApp()); + std::move(callback).Run(SimulateInstallingApp(true /* is_placeholder */)); } else { std::move(callback).Run(BookmarkAppInstallationTask::Result( web_app::InstallResultCode::kFailedUnknownReason, std::string())); @@ -122,10 +122,12 @@ } private: - BookmarkAppInstallationTask::Result SimulateInstallingApp() { + BookmarkAppInstallationTask::Result SimulateInstallingApp( + bool is_placeholder = false) { std::string app_id = GenerateFakeAppId(install_options().url); extension_ids_map_.Insert(install_options().url, app_id, install_options().install_source); + extension_ids_map_.SetIsPlaceholder(install_options().url, is_placeholder); registrar_->AddAsInstalled(app_id); return {web_app::InstallResultCode::kSuccess, app_id}; } @@ -143,8 +145,9 @@ class TestBookmarkAppUninstaller : public BookmarkAppUninstaller { public: - TestBookmarkAppUninstaller(Profile* profile, web_app::AppRegistrar* registrar) - : BookmarkAppUninstaller(profile, registrar) {} + TestBookmarkAppUninstaller(Profile* profile, + web_app::TestAppRegistrar* registrar) + : BookmarkAppUninstaller(profile, registrar), registrar_(registrar) {} ~TestBookmarkAppUninstaller() override = default; @@ -170,11 +173,16 @@ bool result = next_result_map_[app_url]; next_result_map_.erase(app_url); + + if (result) + registrar_->RemoveAsInstalled(GenerateFakeAppId(app_url)); + return result; } private: std::map<GURL, bool> next_result_map_; + web_app::TestAppRegistrar* registrar_; size_t uninstall_call_count_ = 0; std::vector<GURL> uninstalled_app_urls_; @@ -269,6 +277,28 @@ return {url.value(), code.value()}; } + std::pair<GURL, web_app::InstallResultCode> ReinstallPlaceholderAppAndWait( + web_app::PendingAppManager* pending_app_manager, + web_app::InstallOptions install_options) { + base::RunLoop run_loop; + + base::Optional<GURL> url; + base::Optional<web_app::InstallResultCode> code; + + pending_app_manager->ReinstallPlaceholderApp( + std::move(install_options), + base::BindLambdaForTesting( + [&](const GURL& app_url, + web_app::InstallResultCode install_result_code) { + url = app_url; + code = install_result_code; + run_loop.Quit(); + })); + run_loop.Run(); + + return {url.value(), code.value()}; + } + std::vector<std::pair<GURL, web_app::InstallResultCode>> InstallAppsAndWait( web_app::PendingAppManager* pending_app_manager, std::vector<web_app::InstallOptions> apps_to_install) { @@ -1100,6 +1130,7 @@ TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Succeeds) { auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories(); + registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kFooWebAppUrl))); uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true); UninstallAppsResults results = UninstallAppsAndWait( @@ -1125,6 +1156,8 @@ TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Multiple) { auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories(); + registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kFooWebAppUrl))); + registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kBarWebAppUrl))); uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true); uninstaller()->SetNextResultForTesting(GURL(kBarWebAppUrl), true); @@ -1164,4 +1197,133 @@ run_loop.Run(); } +TEST_F(PendingBookmarkAppManagerTest, ReinstallPlaceholderApp_Success) { + auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories(); + + // Install a placeholder app + auto install_options = GetFooInstallOptions(); + install_options.install_placeholder = true; + + { + url_loader()->SetNextLoadUrlResult( + GURL(kFooWebAppUrl), + web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded); + base::Optional<GURL> url; + base::Optional<web_app::InstallResultCode> code; + std::tie(url, code) = + InstallAndWait(pending_app_manager.get(), install_options); + ASSERT_EQ(web_app::InstallResultCode::kSuccess, code.value()); + EXPECT_EQ(0u, install_run_count()); + EXPECT_EQ(1u, install_placeholder_run_count()); + } + + // Reinstall placeholder + { + url_loader()->SetNextLoadUrlResult( + GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded); + uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true); + + base::Optional<GURL> url; + base::Optional<web_app::InstallResultCode> code; + std::tie(url, code) = ReinstallPlaceholderAppAndWait( + pending_app_manager.get(), install_options); + + EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value()); + EXPECT_EQ(GURL(kFooWebAppUrl), url.value()); + + EXPECT_EQ(1u, uninstall_call_count()); + EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url()); + + EXPECT_EQ(1u, install_run_count()); + EXPECT_EQ(1u, install_placeholder_run_count()); + } +} + +TEST_F(PendingBookmarkAppManagerTest, + ReinstallPlaceholderApp_FailsToUninstall) { + auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories(); + + // Install a placeholder app + auto install_options = GetFooInstallOptions(); + install_options.install_placeholder = true; + + { + url_loader()->SetNextLoadUrlResult( + GURL(kFooWebAppUrl), + web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded); + base::Optional<GURL> url; + base::Optional<web_app::InstallResultCode> code; + std::tie(url, code) = + InstallAndWait(pending_app_manager.get(), install_options); + ASSERT_EQ(web_app::InstallResultCode::kSuccess, code.value()); + EXPECT_EQ(0u, install_run_count()); + EXPECT_EQ(1u, install_placeholder_run_count()); + } + + // Reinstall placeholder + { + url_loader()->SetNextLoadUrlResult( + GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded); + uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), false); + + base::Optional<GURL> url; + base::Optional<web_app::InstallResultCode> code; + std::tie(url, code) = ReinstallPlaceholderAppAndWait( + pending_app_manager.get(), install_options); + + EXPECT_EQ(web_app::InstallResultCode::kFailedUnknownReason, code.value()); + EXPECT_EQ(GURL(kFooWebAppUrl), url.value()); + + EXPECT_EQ(1u, uninstall_call_count()); + EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url()); + + EXPECT_EQ(0u, install_run_count()); + EXPECT_EQ(1u, install_placeholder_run_count()); + } +} + +TEST_F(PendingBookmarkAppManagerTest, + ReinstallPlaceholderApp_ReinstallNotPossible) { + auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories(); + + // Install a placeholder app + auto install_options = GetFooInstallOptions(); + install_options.install_placeholder = true; + + { + url_loader()->SetNextLoadUrlResult( + GURL(kFooWebAppUrl), + web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded); + base::Optional<GURL> url; + base::Optional<web_app::InstallResultCode> code; + std::tie(url, code) = + InstallAndWait(pending_app_manager.get(), install_options); + ASSERT_EQ(web_app::InstallResultCode::kSuccess, code.value()); + EXPECT_EQ(0u, install_run_count()); + EXPECT_EQ(1u, install_placeholder_run_count()); + } + + // Reinstall placeholder + { + url_loader()->SetNextLoadUrlResult( + GURL(kFooWebAppUrl), + web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded); + uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true); + + base::Optional<GURL> url; + base::Optional<web_app::InstallResultCode> code; + std::tie(url, code) = ReinstallPlaceholderAppAndWait( + pending_app_manager.get(), install_options); + + EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value()); + EXPECT_EQ(GURL(kFooWebAppUrl), url.value()); + + EXPECT_EQ(1u, uninstall_call_count()); + EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url()); + + EXPECT_EQ(0u, install_run_count()); + EXPECT_EQ(2u, install_placeholder_run_count()); + } +} + } // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_ids_map.cc b/chrome/browser/web_applications/extensions/web_app_extension_ids_map.cc index 97a42897..b76ab0b 100644 --- a/chrome/browser/web_applications/extensions/web_app_extension_ids_map.cc +++ b/chrome/browser/web_applications/extensions/web_app_extension_ids_map.cc
@@ -178,6 +178,23 @@ return base::nullopt; } +base::Optional<std::string> ExtensionIdsMap::LookupPlaceholderAppId( + const GURL& url) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + const base::Value* entry = + pref_service_->GetDictionary(prefs::kWebAppsExtensionIDs) + ->FindKey(url.spec()); + if (!entry) + return base::nullopt; + + base::Optional<bool> is_placeholder = entry->FindBoolKey(kIsPlaceholder); + if (!is_placeholder.has_value() || !is_placeholder.value()) + return base::nullopt; + + return *entry->FindStringKey(kExtensionId); +} + void ExtensionIdsMap::SetIsPlaceholder(const GURL& url, bool is_placeholder) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_ids_map.h b/chrome/browser/web_applications/extensions/web_app_extension_ids_map.h index f83c847..3f1f7632 100644 --- a/chrome/browser/web_applications/extensions/web_app_extension_ids_map.h +++ b/chrome/browser/web_applications/extensions/web_app_extension_ids_map.h
@@ -50,6 +50,11 @@ const std::string& extension_id, InstallSource install_source); base::Optional<std::string> LookupExtensionId(const GURL& url) const; + + // Returns an id if there is a placeholder app for |url|. Note that nullopt + // does not mean that there is no app for |url| just that there is no + // *placeholder app*. + base::Optional<std::string> LookupPlaceholderAppId(const GURL& url) const; void SetIsPlaceholder(const GURL& url, bool is_placeholder); private:
diff --git a/chrome/browser/webauth_interactive_uitest.cc b/chrome/browser/webauth_interactive_uitest.cc index 9334b3c..60b77ab 100644 --- a/chrome/browser/webauth_interactive_uitest.cc +++ b/chrome/browser/webauth_interactive_uitest.cc
@@ -3,14 +3,15 @@ // found in the LICENSE file. #include "base/bind.h" +#include "base/test/bind_test_util.h" #include "build/build_config.h" #include "chrome/browser/devtools/devtools_window_testing.h" -#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/webauthn/authenticator_request_scheduler.h" +#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" -#include "chrome/test/base/ui_test_utils.h" #include "components/network_session_configurator/common/network_switches.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_service_manager_context.h" @@ -22,9 +23,11 @@ namespace { class WebAuthFocusTest : public InProcessBrowserTest, - public PermissionRequestManager::Observer { + public AuthenticatorRequestDialogModel::Observer { protected: - WebAuthFocusTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} + WebAuthFocusTest() + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS), + permission_requested_(false) {} void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); @@ -37,50 +40,33 @@ return https_server_.GetURL(hostname, relative_url); } - // PermissionRequestManager::Observer implementation - void OnBubbleAdded() override { - // If this object is registered as a PermissionRequestManager observer then - // it'll attempt to complete all permissions bubbles by sending keystrokes. - // Note, however, that macOS rejects the permission bubble while other - // platforms accept it, because there's no key sequence for accepting a - // bubble on macOS. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - [](Browser* browser) { - for (const auto& key : std::vector<ui::KeyboardCode> { -#if defined(OS_WIN) || defined(OS_CHROMEOS) - // Press tab (to select the "Allow" button of the - // permissions prompt) and then enter to activate it. - ui::KeyboardCode::VKEY_TAB, ui::KeyboardCode::VKEY_RETURN, -#elif defined(OS_MACOSX) - // There is no way to allow the bubble, we have to - // press escape to reject it. - ui::KeyboardCode::VKEY_ESCAPE, -#else - // Press tab twice (to select the "Allow" button of the - // permissions prompt) and then enter to activate it. - ui::KeyboardCode::VKEY_TAB, - ui::KeyboardCode::VKEY_TAB, - ui::KeyboardCode::VKEY_RETURN, -#endif - }) { - ASSERT_TRUE(ui_test_utils::SendKeyPressSync( - browser, key, - /*control=*/false, /*shift=*/false, /*alt=*/false, - /*command=*/false)); - } - }, - browser())); - } + bool permission_requested() { return permission_requested_; } + + AuthenticatorRequestDialogModel* dialog_model_; private: void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitch(switches::kIgnoreCertificateErrors); } + // AuthenticatorRequestDialogModel::Observer: + void OnStepTransition() override { + if (dialog_model_->current_step() != + AuthenticatorRequestDialogModel::Step::kAttestationPermissionRequest) + return; + + // Simulate accepting the permission request. + dialog_model_->OnAttestationPermissionResponse(true); + permission_requested_ = true; + } + + void OnModelDestroyed() override {} + net::EmbeddedTestServer https_server_; + // Set to true when the permission sheet is triggered. + bool permission_requested_; + DISALLOW_COPY_AND_ASSIGN(WebAuthFocusTest); }; @@ -182,26 +168,23 @@ EXPECT_EQ(result, "OK"); // Requesting "direct" attestation will trigger a permissions prompt. + virtual_device.mutable_state()->simulate_press_callback = + base::BindLambdaForTesting([&]() { + dialog_model_ = + AuthenticatorRequestScheduler::GetRequestDelegateForTest( + initial_web_contents) + ->WeakDialogModelForTesting(); + dialog_model_->AddObserver(this); + }); + const std::string get_assertion_with_attestation_script = base::ReplaceStringPlaceholders( kRegisterTemplate, std::vector<std::string>{"direct"}, nullptr); - - PermissionRequestManager* const permission_request_manager = - PermissionRequestManager::FromWebContents(initial_web_contents); - // The observer callback will trigger the permissions prompt. - permission_request_manager->AddObserver(this); ASSERT_TRUE(content::ExecuteScriptAndExtractString( initial_web_contents, get_assertion_with_attestation_script, &result)); -#if defined(OS_MACOSX) - // The permissions bubble has to be rejected on macOS because there's no key - // sequence to accept it. Therefore a NotAllowedError is expected. This is not - // ideal as a timeout causes the same result, but it is distinct from a focus - // error. - EXPECT_THAT(result, ::testing::HasSubstr("NotAllowedError: ")); -#else + + EXPECT_TRUE(permission_requested()); EXPECT_EQ(result, "OK"); -#endif - permission_request_manager->RemoveObserver(this); } } // anonymous namespace
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index e7a063fa..0268dea8 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -473,6 +473,14 @@ has_attempted_pin_entry_ = true; } +void AuthenticatorRequestDialogModel::OnAttestationPermissionResponse( + bool attestation_permission_granted) { + if (!attestation_callback_) { + return; + } + std::move(attestation_callback_).Run(attestation_permission_granted); +} + void AuthenticatorRequestDialogModel::AddAuthenticator( const device::FidoAuthenticator& authenticator) { if (!authenticator.AuthenticatorTransport()) { @@ -568,3 +576,9 @@ SetCurrentStep(Step::kClientPinSetup); } } + +void AuthenticatorRequestDialogModel::RequestAttestationPermission( + base::OnceCallback<void(bool)> callback) { + attestation_callback_ = std::move(callback); + SetCurrentStep(Step::kAttestationPermissionRequest); +}
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h index fc04162..789864b 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -97,6 +97,9 @@ // Account selection, kSelectAccount, + + // Attestation permission request. + kAttestationPermissionRequest, }; // Implemented by the dialog to observe this model and show the UI panels @@ -323,6 +326,10 @@ // OnHavePIN is called when the user enters a PIN in the UI. void OnHavePIN(const std::string& pin); + // OnAttestationPermissionResponse is called when the user either allows or + // disallows an attestation permission request. + void OnAttestationPermissionResponse(bool attestation_permission_granted); + void UpdateAuthenticatorReferenceId(base::StringPiece old_authenticator_id, std::string new_authenticator_id); void AddAuthenticator(const device::FidoAuthenticator& authenticator); @@ -358,6 +365,8 @@ bool has_attempted_pin_entry() const { return has_attempted_pin_entry_; } base::Optional<int> pin_attempts() const { return pin_attempts_; } + void RequestAttestationPermission(base::OnceCallback<void(bool)> callback); + const std::vector<device::AuthenticatorGetAssertionResponse>& responses() { return responses_; } @@ -414,6 +423,8 @@ bool has_attempted_pin_entry_ = false; base::Optional<int> pin_attempts_; + base::OnceCallback<void(bool)> attestation_callback_; + // responses_ contains possible accounts to select between. std::vector<device::AuthenticatorGetAssertionResponse> responses_; base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
diff --git a/chrome/browser/webauthn/authenticator_request_scheduler.cc b/chrome/browser/webauthn/authenticator_request_scheduler.cc index 9a28341..fb49996 100644 --- a/chrome/browser/webauthn/authenticator_request_scheduler.cc +++ b/chrome/browser/webauthn/authenticator_request_scheduler.cc
@@ -58,3 +58,12 @@ active_request_holder->request() = request->AsWeakPtr(); return request; } + +// static +ChromeAuthenticatorRequestDelegate* +AuthenticatorRequestScheduler::GetRequestDelegateForTest( + content::WebContents* web_contents) { + return ActiveRequestWeakHolder::EnsureForWebContents(web_contents) + ->request() + .get(); +}
diff --git a/chrome/browser/webauthn/authenticator_request_scheduler.h b/chrome/browser/webauthn/authenticator_request_scheduler.h index 4e0163e..f70ed3e 100644 --- a/chrome/browser/webauthn/authenticator_request_scheduler.h +++ b/chrome/browser/webauthn/authenticator_request_scheduler.h
@@ -13,6 +13,7 @@ namespace content { class RenderFrameHost; +class WebContents; } // Responsible for scheduling simultaneous Web Authentication API requests @@ -31,6 +32,11 @@ static std::unique_ptr<ChromeAuthenticatorRequestDelegate> CreateRequestDelegate(content::RenderFrameHost* render_frame_host); + // Returns the current request delegate associated to the |web_contents| or + // nullptr if there is none. + static ChromeAuthenticatorRequestDelegate* GetRequestDelegateForTest( + content::WebContents* web_contents); + private: DISALLOW_COPY_AND_ASSIGN(AuthenticatorRequestScheduler); };
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc index 16b5d6e..401433f 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -14,11 +14,8 @@ #include "base/feature_list.h" #include "base/location.h" #include "base/stl_util.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "build/build_config.h" -#include "chrome/browser/permissions/attestation_permission_request.h" -#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" @@ -112,6 +109,11 @@ return weak_ptr_factory_.GetWeakPtr(); } +AuthenticatorRequestDialogModel* +ChromeAuthenticatorRequestDelegate::WeakDialogModelForTesting() const { + return weak_dialog_model_; +} + content::BrowserContext* ChromeAuthenticatorRequestDelegate::browser_context() const { return content::WebContents::FromRenderFrameHost(render_frame_host()) @@ -204,29 +206,13 @@ return; } - // This does not use content::PermissionControllerDelegate because that only - // works with content settings, while this permission is a non-persisted, - // per-attested- registration consent. - auto* permission_request_manager = PermissionRequestManager::FromWebContents( - content::WebContents::FromRenderFrameHost(render_frame_host())); - if (!permission_request_manager) { - std::move(callback).Run(false); - return; + if (!IsWebAuthnUIEnabled()) { + // Enable the UI to show the user the permission dialog. + ShowAuthenticatorRequestDialog( + content::WebContents::FromRenderFrameHost(render_frame_host()), + std::move(transient_dialog_model_holder_)); } - - // The created AttestationPermissionRequest deletes itself once complete. - // - // |callback| is called via the |MessageLoop| because otherwise the - // permissions bubble will have focus and |AuthenticatorImpl| checks that the - // frame still has focus before returning any results. - permission_request_manager->AddRequest(NewAttestationPermissionRequest( - render_frame_host()->GetLastCommittedOrigin(), - base::BindOnce( - [](base::OnceCallback<void(bool)> callback, bool result) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), result)); - }, - std::move(callback)))); + weak_dialog_model_->RequestAttestationPermission(std::move(callback)); #endif }
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h index 68d3e98..95d7b362 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
@@ -57,6 +57,8 @@ base::WeakPtr<ChromeAuthenticatorRequestDelegate> AsWeakPtr(); + AuthenticatorRequestDialogModel* WeakDialogModelForTesting() const; + private: FRIEND_TEST_ALL_PREFIXES(ChromeAuthenticatorRequestDelegateTest, TestTransportPrefType);
diff --git a/chrome/renderer/extensions/extension_hooks_delegate.cc b/chrome/renderer/extensions/extension_hooks_delegate.cc index 3f0513a..bbd7271b 100644 --- a/chrome/renderer/extensions/extension_hooks_delegate.cc +++ b/chrome/renderer/extensions/extension_hooks_delegate.cc
@@ -77,8 +77,13 @@ if (!has_property.IsJust() || !has_property.FromJust()) return; - info.GetReturnValue().Set( - runtime_obj->Get(context, property_name).ToLocalChecked()); + v8::Local<v8::Value> property_value; + // Try and grab the chrome.runtime version. It's possible this has been + // tampered with, so early-out if an exception is thrown. + if (!runtime_obj->Get(context, property_name).ToLocal(&property_value)) + return; + + info.GetReturnValue().Set(property_value); } // A helper method to throw a deprecation error on access.
diff --git a/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc b/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc index ad7f5d0..be0703f 100644 --- a/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc +++ b/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc
@@ -212,4 +212,29 @@ messaging_service()->HasPortForTesting(script_context(), port_id)); } +// Tests that overriding the runtime equivalents of chrome.extension methods +// with accessors that throw does not cause a crash on access. Regression test +// for https://crbug.com/949170. +TEST_F(ExtensionHooksDelegateTest, RuntimeAliasesCorrupted) { + v8::HandleScope handle_scope(isolate()); + v8::Local<v8::Context> context = MainContext(); + + // Set a trap on chrome.runtime.sendMessage. + constexpr char kMutateChromeRuntime[] = + R"((function() { + Object.defineProperty( + chrome.runtime, 'sendMessage', + { get() { throw new Error('haha'); } }); + }))"; + RunFunctionOnGlobal(FunctionFromString(context, kMutateChromeRuntime), + context, 0, nullptr); + + // Touch chrome.extension.sendMessage, which is aliased to the runtime + // version. Though an error is thrown, we shouldn't crash. + constexpr char kTouchExtensionSendMessage[] = + "(function() { chrome.extension.sendMessage; })"; + RunFunctionOnGlobal(FunctionFromString(context, kTouchExtensionSendMessage), + context, 0, nullptr); +} + } // namespace extensions
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index aee2876..843e48e 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -629,7 +629,6 @@ "../browser/browsing_data/counters/passwords_counter_browsertest.cc", "../browser/browsing_data/counters/sync_aware_counter_browsertest.cc", "../browser/browsing_data/navigation_entry_remover_browsertest.cc", - "../browser/chrome_browser_main_browsertest.cc", "../browser/chrome_content_browser_client_browsertest.cc", "../browser/chrome_content_browser_client_browsertest_chromeos.cc", "../browser/chrome_do_not_track_browsertest.cc", @@ -1884,6 +1883,8 @@ "../browser/chromeos/login/signin/oauth2_browsertest.cc", "../browser/chromeos/login/test/enrollment_helper_mixin.cc", "../browser/chromeos/login/test/enrollment_helper_mixin.h", + "../browser/chromeos/login/test/enrollment_ui_mixin.cc", + "../browser/chromeos/login/test/enrollment_ui_mixin.h", "../browser/chromeos/login/test/fake_gaia_mixin.cc", "../browser/chromeos/login/test/fake_gaia_mixin.h", "../browser/chromeos/login/test/hid_controller_mixin.cc", @@ -5219,7 +5220,10 @@ # Use only the _chromeos version on Ash / Chrome OS. "../browser/ui/views/test/view_event_test_platform_part_default.cc", ] - sources += [ "../browser/ui/ash/split_view_interactive_uitest.cc" ] + sources += [ + "../browser/ui/ash/drag_to_overview_interactive_uitest.cc", + "../browser/ui/ash/split_view_interactive_uitest.cc", + ] } else { # ! is_chromeos # Non-ChromeOS notifications tests. sources += [
diff --git a/chrome/test/data/extensions/api_test/enterprise_platform_keys.crx b/chrome/test/data/extensions/api_test/enterprise_platform_keys.crx index 3e4b41fc..ef3c032 100644 --- a/chrome/test/data/extensions/api_test/enterprise_platform_keys.crx +++ b/chrome/test/data/extensions/api_test/enterprise_platform_keys.crx Binary files differ
diff --git a/chrome/test/data/extensions/api_test/webstore_private/bundle/bmfoocgfinpmkmlbjhcbofejhkhlbchk.crx b/chrome/test/data/extensions/api_test/webstore_private/bundle/bmfoocgfinpmkmlbjhcbofejhkhlbchk.crx index 99ce36a4..fccc178 100644 --- a/chrome/test/data/extensions/api_test/webstore_private/bundle/bmfoocgfinpmkmlbjhcbofejhkhlbchk.crx +++ b/chrome/test/data/extensions/api_test/webstore_private/bundle/bmfoocgfinpmkmlbjhcbofejhkhlbchk.crx Binary files differ
diff --git a/chrome/test/data/extensions/api_test/webstore_private/bundle/mpneghmdnmaolkljkipbhaienajcflfe.crx b/chrome/test/data/extensions/api_test/webstore_private/bundle/mpneghmdnmaolkljkipbhaienajcflfe.crx index e20ff4d..2ee96b7e 100644 --- a/chrome/test/data/extensions/api_test/webstore_private/bundle/mpneghmdnmaolkljkipbhaienajcflfe.crx +++ b/chrome/test/data/extensions/api_test/webstore_private/bundle/mpneghmdnmaolkljkipbhaienajcflfe.crx Binary files differ
diff --git a/chrome/test/data/extensions/api_test/webstore_private/bundle/pkapffpjmiilhlhbibjhamlmdhfneidj.crx b/chrome/test/data/extensions/api_test/webstore_private/bundle/pkapffpjmiilhlhbibjhamlmdhfneidj.crx index 9ad13fa..bbde66d 100644 --- a/chrome/test/data/extensions/api_test/webstore_private/bundle/pkapffpjmiilhlhbibjhamlmdhfneidj.crx +++ b/chrome/test/data/extensions/api_test/webstore_private/bundle/pkapffpjmiilhlhbibjhamlmdhfneidj.crx Binary files differ
diff --git a/chrome/test/data/extensions/platform_apps/extension_view/skeleton.crx b/chrome/test/data/extensions/platform_apps/extension_view/skeleton.crx index 99912d1..ee5070c0 100644 --- a/chrome/test/data/extensions/platform_apps/extension_view/skeleton.crx +++ b/chrome/test/data/extensions/platform_apps/extension_view/skeleton.crx Binary files differ
diff --git a/chrome/test/data/extensions/platform_apps/extension_view/skeleton_two.crx b/chrome/test/data/extensions/platform_apps/extension_view/skeleton_two.crx index 507e9eb63e9..73eb8a0 100644 --- a/chrome/test/data/extensions/platform_apps/extension_view/skeleton_two.crx +++ b/chrome/test/data/extensions/platform_apps/extension_view/skeleton_two.crx Binary files differ
diff --git a/chrome/test/data/extensions/signin_screen_manual_test_app/app_signed_by_webstore.crx b/chrome/test/data/extensions/signin_screen_manual_test_app/app_signed_by_webstore.crx index deb82fa..9e9d462e 100644 --- a/chrome/test/data/extensions/signin_screen_manual_test_app/app_signed_by_webstore.crx +++ b/chrome/test/data/extensions/signin_screen_manual_test_app/app_signed_by_webstore.crx Binary files differ
diff --git a/chrome/test/data/extensions/trivial_extension/extension.crx b/chrome/test/data/extensions/trivial_extension/extension.crx index cc8c54d..c899595 100644 --- a/chrome/test/data/extensions/trivial_extension/extension.crx +++ b/chrome/test/data/extensions/trivial_extension/extension.crx Binary files differ
diff --git a/chrome/test/data/extensions/trivial_platform_app/app.crx b/chrome/test/data/extensions/trivial_platform_app/app.crx index 80f24f6..6c45322 100644 --- a/chrome/test/data/extensions/trivial_platform_app/app.crx +++ b/chrome/test/data/extensions/trivial_platform_app/app.crx Binary files differ
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 4ece725..1a8204ad 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -329,7 +329,7 @@ "PrintingAllowedPinModes": { "os": ["chromeos"], - "test_policy": { "PrintingAllowedPinModes": "secure" }, + "test_policy": { "PrintingAllowedPinModes": "pin" }, "pref_mappings": [ { "pref": "printing.allowed_pin_modes" } ] @@ -361,7 +361,7 @@ "PrintingPinDefault": { "os": ["chromeos"], - "test_policy": { "PrintingPinDefault": "secure" }, + "test_policy": { "PrintingPinDefault": "pin" }, "pref_mappings": [ { "pref": "printing.pin_default" } ]
diff --git a/chrome/test/data/webui/print_preview/model_settings_policy_test.js b/chrome/test/data/webui/print_preview/model_settings_policy_test.js index 8a2cf851..f7c10061 100644 --- a/chrome/test/data/webui/print_preview/model_settings_policy_test.js +++ b/chrome/test/data/webui/print_preview/model_settings_policy_test.js
@@ -257,8 +257,8 @@ { // Policy has no effect, setting unavailable. pinCap: {}, - pinPolicy: print_preview.PinModeRestriction.SECURE, - pinDefault: print_preview.PinModeRestriction.SECURE, + pinPolicy: print_preview.PinModeRestriction.PIN, + pinDefault: print_preview.PinModeRestriction.PIN, expectedValue: false, expectedAvailable: false, expectedManaged: false, @@ -268,7 +268,7 @@ // Policy has no effect, setting is not supported. pinCap: {supported: false}, pinPolicy: print_preview.PinModeRestriction.NONE, - pinDefault: print_preview.PinModeRestriction.SECURE, + pinDefault: print_preview.PinModeRestriction.PIN, expectedValue: false, expectedAvailable: false, expectedManaged: false, @@ -277,7 +277,7 @@ { // Policy is UNSECURE, setting is not available. pinCap: {supported: true}, - pinPolicy: print_preview.PinModeRestriction.UNSECURE, + pinPolicy: print_preview.PinModeRestriction.NO_PIN, expectedValue: false, expectedAvailable: false, expectedManaged: false, @@ -287,7 +287,7 @@ // No restriction policy, setting is modifiable. pinCap: {supported: true}, pinPolicy: print_preview.PinModeRestriction.NONE, - pinDefault: print_preview.PinModeRestriction.UNSECURE, + pinDefault: print_preview.PinModeRestriction.NO_PIN, expectedValue: false, expectedAvailable: true, expectedManaged: false, @@ -296,9 +296,9 @@ { // Policy overrides default. pinCap: {supported: true}, - pinPolicy: print_preview.PinModeRestriction.SECURE, + pinPolicy: print_preview.PinModeRestriction.PIN, // Default mismatches restriction and is ignored. - pinDefault: print_preview.PinModeRestriction.UNSECURE, + pinDefault: print_preview.PinModeRestriction.NO_PIN, expectedValue: true, expectedAvailable: true, expectedManaged: true, @@ -307,7 +307,7 @@ { // Default defined by policy but setting is modifiable. pinCap: {supported: true}, - pinDefault: print_preview.PinModeRestriction.SECURE, + pinDefault: print_preview.PinModeRestriction.PIN, expectedValue: true, expectedAvailable: true, expectedManaged: false,
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc index bd76b7e..b3b6d3d 100644 --- a/chromecast/browser/url_request_context_factory.cc +++ b/chromecast/browser/url_request_context_factory.cc
@@ -32,6 +32,7 @@ #include "net/cert_net/nss_ocsp.h" #include "net/cookies/cookie_store.h" #include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_manager.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_layer.h" #include "net/http/http_server_properties_impl.h" @@ -233,9 +234,8 @@ if (system_dependencies_initialized_) return; - // TODO(crbug.com/934402): Use a shared HostResolverManager instead of a - // global HostResolver. - host_resolver_ = net::HostResolver::CreateStandaloneResolver(nullptr); + host_resolver_manager_ = std::make_unique<net::HostResolverManager>( + net::HostResolver::Options(), nullptr); cert_verifier_ = net::CertVerifier::CreateDefault(); ssl_config_service_.reset(new net::SSLConfigServiceDefaults); transport_security_state_.reset(new net::TransportSecurityState()); @@ -252,6 +252,10 @@ proxy_resolution_service_ = net::ProxyResolutionService::CreateUsingSystemProxyResolver( std::move(proxy_config_service_), nullptr); + + system_host_resolver_ = + net::HostResolver::CreateResolver(host_resolver_manager_.get()); + system_dependencies_initialized_ = true; } @@ -300,15 +304,18 @@ main_job_factory_ = std::move(top_job_factory); + main_host_resolver_ = + net::HostResolver::CreateResolver(host_resolver_manager_.get()); + main_dependencies_initialized_ = true; } -void URLRequestContextFactory::InitializeMediaContextDependencies( - net::HttpTransactionFactory* transaction_factory) { +void URLRequestContextFactory::InitializeMediaContextDependencies() { if (media_dependencies_initialized_) return; - media_transaction_factory_.reset(transaction_factory); + media_host_resolver_ = + net::HostResolver::CreateResolver(host_resolver_manager_.get()); media_dependencies_initialized_ = true; } @@ -338,6 +345,18 @@ << session_params->disable_idle_sockets_close_on_memory_pressure; } +std::unique_ptr<net::HttpNetworkSession> +URLRequestContextFactory::CreateNetworkSession( + const net::URLRequestContext* context) { + net::HttpNetworkSession::Params session_params; + net::HttpNetworkSession::Context session_context; + PopulateNetworkSessionParams(IgnoreCertificateErrors(), &session_params); + net::URLRequestContextBuilder::SetHttpNetworkSessionComponents( + context, &session_context); + return std::make_unique<net::HttpNetworkSession>(session_params, + session_context); +} + net::URLRequestContext* URLRequestContextFactory::CreateSystemRequestContext() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); InitializeSystemContextDependencies(); @@ -347,15 +366,12 @@ net::URLRequestContext* system_context = new net::URLRequestContext(); ConfigureURLRequestContext(system_context, system_job_factory_, - system_cookie_store_, system_network_delegate_); + system_cookie_store_, system_network_delegate_, + system_host_resolver_); - net::HttpNetworkSession::Params session_params; - net::HttpNetworkSession::Context session_context; - PopulateNetworkSessionParams(IgnoreCertificateErrors(), &session_params); - net::URLRequestContextBuilder::SetHttpNetworkSessionComponents( - system_context, &session_context); - system_transaction_factory_.reset(new net::HttpNetworkLayer( - new net::HttpNetworkSession(session_params, session_context))); + system_network_session_ = CreateNetworkSession(system_context); + system_transaction_factory_ = + std::make_unique<net::HttpNetworkLayer>(system_network_session_.get()); system_context->set_http_transaction_factory( system_transaction_factory_.get()); @@ -366,18 +382,20 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(main_getter_.get()) << "Getting MediaRequestContext before MainRequestContext"; - net::URLRequestContext* main_context = main_getter_->GetURLRequestContext(); - // Set non caching backend. - net::HttpNetworkSession* main_session = - main_transaction_factory_->GetSession(); - InitializeMediaContextDependencies( - new net::HttpNetworkLayer(main_session)); + InitializeMediaContextDependencies(); + // Reuse main context dependencies except HostResolver and + // HttpTransactionFactory. net::URLRequestContext* media_context = new net::URLRequestContext(); - media_context->CopyFrom(main_context); - media_context->set_http_transaction_factory( - media_transaction_factory_.get()); + ConfigureURLRequestContext(media_context, main_job_factory_, + main_cookie_store_, app_network_delegate_, + media_host_resolver_); + + media_network_session_ = CreateNetworkSession(media_context); + media_transaction_factory_ = + std::make_unique<net::HttpNetworkLayer>(media_network_session_.get()); + media_context->set_http_transaction_factory(media_transaction_factory_.get()); return media_context; } @@ -396,15 +414,12 @@ net::URLRequestContext* main_context = new net::URLRequestContext(); ConfigureURLRequestContext(main_context, main_job_factory_, - main_cookie_store_, app_network_delegate_); + main_cookie_store_, app_network_delegate_, + main_host_resolver_); - net::HttpNetworkSession::Params session_params; - net::HttpNetworkSession::Context session_context; - PopulateNetworkSessionParams(IgnoreCertificateErrors(), &session_params); - net::URLRequestContextBuilder::SetHttpNetworkSessionComponents( - main_context, &session_context); - main_transaction_factory_.reset(new net::HttpNetworkLayer( - new net::HttpNetworkSession(session_params, session_context))); + main_network_session_ = CreateNetworkSession(main_context); + main_transaction_factory_ = + std::make_unique<net::HttpNetworkLayer>(main_network_session_.get()); main_context->set_http_transaction_factory(main_transaction_factory_.get()); return main_context; @@ -414,9 +429,9 @@ net::URLRequestContext* context, const std::unique_ptr<net::URLRequestJobFactory>& job_factory, const std::unique_ptr<net::CookieStore>& cookie_store, - const std::unique_ptr<CastNetworkDelegate>& network_delegate) { + const std::unique_ptr<CastNetworkDelegate>& network_delegate, + const std::unique_ptr<net::HostResolver>& host_resolver) { // common settings - context->set_host_resolver(host_resolver_.get()); context->set_channel_id_service(channel_id_service_.get()); context->set_cert_verifier(cert_verifier_.get()); context->set_cert_transparency_verifier(cert_transparency_verifier_.get()); @@ -433,6 +448,9 @@ context->set_job_factory(job_factory.get()); context->set_cookie_store(cookie_store.get()); context->set_network_delegate(network_delegate.get()); + context->set_host_resolver(host_resolver.get()); + + host_resolver->SetRequestContext(context); } void URLRequestContextFactory::InitializeNetworkDelegates() {
diff --git a/chromecast/browser/url_request_context_factory.h b/chromecast/browser/url_request_context_factory.h index 9864eb8..3337110 100644 --- a/chromecast/browser/url_request_context_factory.h +++ b/chromecast/browser/url_request_context_factory.h
@@ -20,6 +20,8 @@ namespace net { class ChannelIDService; class CookieStore; +class HostResolver; +class HostResolverManager; class HttpTransactionFactory; class HttpUserAgentSettings; class NetLog; @@ -60,10 +62,6 @@ return app_network_delegate_.get(); } - net::HostResolver* host_resolver() const { - return host_resolver_.get(); - } - // Initialize the CastNetworkDelegate objects. This needs to be done // after the CastService is created, but before any URL requests are made. void InitializeNetworkDelegates(); @@ -78,11 +76,13 @@ void InitializeMainContextDependencies( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors); - void InitializeMediaContextDependencies(net::HttpTransactionFactory* factory); + void InitializeMediaContextDependencies(); void PopulateNetworkSessionParams( bool ignore_certificate_errors, net::HttpNetworkSession::Params* session_params); + std::unique_ptr<net::HttpNetworkSession> CreateNetworkSession( + const net::URLRequestContext* context); // These are called by the RequestContextGetters to create each // RequestContext. @@ -99,7 +99,8 @@ net::URLRequestContext* context, const std::unique_ptr<net::URLRequestJobFactory>& job_factory, const std::unique_ptr<net::CookieStore>& cookie_store, - const std::unique_ptr<CastNetworkDelegate>& network_delegate); + const std::unique_ptr<CastNetworkDelegate>& network_delegate, + const std::unique_ptr<net::HostResolver>& host_resolver); scoped_refptr<net::URLRequestContextGetter> system_getter_; scoped_refptr<net::URLRequestContextGetter> media_getter_; @@ -113,7 +114,7 @@ // The URLRequestContextStorage class manages dependent resources for a single // instance of URLRequestContext only. bool system_dependencies_initialized_; - std::unique_ptr<net::HostResolver> host_resolver_; + std::unique_ptr<net::HostResolverManager> host_resolver_manager_; std::unique_ptr<net::ChannelIDService> channel_id_service_; std::unique_ptr<net::CertVerifier> cert_verifier_; std::unique_ptr<net::SSLConfigService> ssl_config_service_; @@ -125,17 +126,23 @@ std::unique_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory_; std::unique_ptr<net::HttpServerProperties> http_server_properties_; std::unique_ptr<net::HttpUserAgentSettings> http_user_agent_settings_; + std::unique_ptr<net::HttpNetworkSession> system_network_session_; std::unique_ptr<net::HttpTransactionFactory> system_transaction_factory_; std::unique_ptr<net::CookieStore> system_cookie_store_; std::unique_ptr<net::URLRequestJobFactory> system_job_factory_; + std::unique_ptr<net::HostResolver> system_host_resolver_; bool main_dependencies_initialized_; + std::unique_ptr<net::HttpNetworkSession> main_network_session_; std::unique_ptr<net::HttpTransactionFactory> main_transaction_factory_; std::unique_ptr<net::CookieStore> main_cookie_store_; std::unique_ptr<net::URLRequestJobFactory> main_job_factory_; + std::unique_ptr<net::HostResolver> main_host_resolver_; bool media_dependencies_initialized_; + std::unique_ptr<net::HttpNetworkSession> media_network_session_; std::unique_ptr<net::HttpTransactionFactory> media_transaction_factory_; + std::unique_ptr<net::HostResolver> media_host_resolver_; std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_impl_;
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn index 9a62e07..cd8e95b 100644 --- a/chromeos/dbus/BUILD.gn +++ b/chromeos/dbus/BUILD.gn
@@ -13,6 +13,7 @@ public_deps = [ ":common", "//chromeos/dbus/constants", + "//chromeos/dbus/shill", "//dbus", ] deps = [ @@ -134,48 +135,6 @@ "runtime_probe_client.h", "seneschal_client.cc", "seneschal_client.h", - "shill/fake_gsm_sms_client.cc", - "shill/fake_gsm_sms_client.h", - "shill/fake_modem_messaging_client.cc", - "shill/fake_modem_messaging_client.h", - "shill/fake_shill_device_client.cc", - "shill/fake_shill_device_client.h", - "shill/fake_shill_ipconfig_client.cc", - "shill/fake_shill_ipconfig_client.h", - "shill/fake_shill_manager_client.cc", - "shill/fake_shill_manager_client.h", - "shill/fake_shill_profile_client.cc", - "shill/fake_shill_profile_client.h", - "shill/fake_shill_service_client.cc", - "shill/fake_shill_service_client.h", - "shill/fake_shill_third_party_vpn_driver_client.cc", - "shill/fake_shill_third_party_vpn_driver_client.h", - "shill/fake_sms_client.cc", - "shill/fake_sms_client.h", - "shill/gsm_sms_client.cc", - "shill/gsm_sms_client.h", - "shill/modem_messaging_client.cc", - "shill/modem_messaging_client.h", - "shill/shill_client_helper.cc", - "shill/shill_client_helper.h", - "shill/shill_clients.cc", - "shill/shill_clients.h", - "shill/shill_device_client.cc", - "shill/shill_device_client.h", - "shill/shill_ipconfig_client.cc", - "shill/shill_ipconfig_client.h", - "shill/shill_manager_client.cc", - "shill/shill_manager_client.h", - "shill/shill_profile_client.cc", - "shill/shill_profile_client.h", - "shill/shill_property_changed_observer.h", - "shill/shill_service_client.cc", - "shill/shill_service_client.h", - "shill/shill_third_party_vpn_driver_client.cc", - "shill/shill_third_party_vpn_driver_client.h", - "shill/shill_third_party_vpn_observer.h", - "shill/sms_client.cc", - "shill/sms_client.h", "smb_provider_client.cc", "smb_provider_client.h", "update_engine_client.cc", @@ -244,6 +203,7 @@ "//chromeos/dbus/cryptohome", "//chromeos/dbus/cryptohome:attestation_proto", "//chromeos/dbus/session_manager", + "//chromeos/dbus/shill:test_support", "//components/account_id", "//dbus", "//dbus:test_support", @@ -268,16 +228,6 @@ "power/fake_power_manager_client_unittest.cc", "power/power_manager_client_unittest.cc", "power/power_policy_controller_unittest.cc", - "shill/gsm_sms_client_unittest.cc", - "shill/modem_messaging_client_unittest.cc", - "shill/shill_client_unittest_base.cc", - "shill/shill_client_unittest_base.h", - "shill/shill_device_client_unittest.cc", - "shill/shill_ipconfig_client_unittest.cc", - "shill/shill_manager_client_unittest.cc", - "shill/shill_profile_client_unittest.cc", - "shill/shill_service_client_unittest.cc", - "shill/shill_third_party_vpn_driver_client_unittest.cc", "update_engine_client_unittest.cc", "util/version_loader_unittest.cc", ]
diff --git a/chromeos/dbus/shill/BUILD.gn b/chromeos/dbus/shill/BUILD.gn new file mode 100644 index 0000000..021cc42 --- /dev/null +++ b/chromeos/dbus/shill/BUILD.gn
@@ -0,0 +1,91 @@ +# 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. + +assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos") + +component("shill") { + defines = [ "IS_SHILL_CLIENT_IMPL" ] + + deps = [ + "//base", + "//chromeos/dbus:common", + "//chromeos/dbus/constants", + "//components/device_event_log", + "//dbus", + "//net", + ] + + sources = [ + "fake_gsm_sms_client.cc", + "fake_gsm_sms_client.h", + "fake_modem_messaging_client.cc", + "fake_modem_messaging_client.h", + "fake_shill_device_client.cc", + "fake_shill_device_client.h", + "fake_shill_ipconfig_client.cc", + "fake_shill_ipconfig_client.h", + "fake_shill_manager_client.cc", + "fake_shill_manager_client.h", + "fake_shill_profile_client.cc", + "fake_shill_profile_client.h", + "fake_shill_service_client.cc", + "fake_shill_service_client.h", + "fake_shill_third_party_vpn_driver_client.cc", + "fake_shill_third_party_vpn_driver_client.h", + "fake_sms_client.cc", + "fake_sms_client.h", + "gsm_sms_client.cc", + "gsm_sms_client.h", + "modem_messaging_client.cc", + "modem_messaging_client.h", + "shill_client_helper.cc", + "shill_client_helper.h", + "shill_clients.cc", + "shill_clients.h", + "shill_device_client.cc", + "shill_device_client.h", + "shill_ipconfig_client.cc", + "shill_ipconfig_client.h", + "shill_manager_client.cc", + "shill_manager_client.h", + "shill_profile_client.cc", + "shill_profile_client.h", + "shill_property_changed_observer.h", + "shill_service_client.cc", + "shill_service_client.h", + "shill_third_party_vpn_driver_client.cc", + "shill_third_party_vpn_driver_client.h", + "shill_third_party_vpn_observer.h", + "sms_client.cc", + "sms_client.h", + ] +} + +source_set("test_support") { + testonly = true + public_deps = [ + ":shill", + ] + deps = [ + "//base", + "//base/test:test_support", + "//chromeos/dbus:common", + "//dbus:test_support", + "//testing/gmock", + "//testing/gtest", + ] + + sources = [ + "gsm_sms_client_unittest.cc", + "modem_messaging_client_unittest.cc", + "shill_client_unittest_base.cc", + "shill_client_unittest_base.h", + "shill_device_client_unittest.cc", + "shill_ipconfig_client_unittest.cc", + "shill_manager_client_unittest.cc", + "shill_profile_client_unittest.cc", + "shill_service_client_unittest.cc", + "shill_third_party_vpn_driver_client_unittest.cc", + ] +}
diff --git a/chromeos/dbus/shill/fake_gsm_sms_client.h b/chromeos/dbus/shill/fake_gsm_sms_client.h index 7d86470..12873c1 100644 --- a/chromeos/dbus/shill/fake_gsm_sms_client.h +++ b/chromeos/dbus/shill/fake_gsm_sms_client.h
@@ -19,7 +19,7 @@ namespace chromeos { // A fake implementation of GsmSMSClient used for tests. -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeGsmSMSClient : public GsmSMSClient { +class COMPONENT_EXPORT(SHILL_CLIENT) FakeGsmSMSClient : public GsmSMSClient { public: FakeGsmSMSClient(); ~FakeGsmSMSClient() override;
diff --git a/chromeos/dbus/shill/fake_modem_messaging_client.h b/chromeos/dbus/shill/fake_modem_messaging_client.h index 9cb26299..316763c0 100644 --- a/chromeos/dbus/shill/fake_modem_messaging_client.h +++ b/chromeos/dbus/shill/fake_modem_messaging_client.h
@@ -15,7 +15,7 @@ namespace chromeos { -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeModemMessagingClient +class COMPONENT_EXPORT(SHILL_CLIENT) FakeModemMessagingClient : public ModemMessagingClient { public: FakeModemMessagingClient();
diff --git a/chromeos/dbus/shill/fake_shill_device_client.h b/chromeos/dbus/shill/fake_shill_device_client.h index f2ee1670..b598755b 100644 --- a/chromeos/dbus/shill/fake_shill_device_client.h +++ b/chromeos/dbus/shill/fake_shill_device_client.h
@@ -19,7 +19,7 @@ // A fake implementation of ShillDeviceClient. // Implemented: Stub cellular device for SMS testing. -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeShillDeviceClient +class COMPONENT_EXPORT(SHILL_CLIENT) FakeShillDeviceClient : public ShillDeviceClient, public ShillDeviceClient::TestInterface { public:
diff --git a/chromeos/dbus/shill/fake_shill_ipconfig_client.h b/chromeos/dbus/shill/fake_shill_ipconfig_client.h index 7d332bb..0640142 100644 --- a/chromeos/dbus/shill/fake_shill_ipconfig_client.h +++ b/chromeos/dbus/shill/fake_shill_ipconfig_client.h
@@ -14,7 +14,7 @@ namespace chromeos { // A fake implementation of ShillIPConfigClient. -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeShillIPConfigClient +class COMPONENT_EXPORT(SHILL_CLIENT) FakeShillIPConfigClient : public ShillIPConfigClient, public ShillIPConfigClient::TestInterface { public:
diff --git a/chromeos/dbus/shill/fake_shill_manager_client.h b/chromeos/dbus/shill/fake_shill_manager_client.h index 703b1da..a5df436 100644 --- a/chromeos/dbus/shill/fake_shill_manager_client.h +++ b/chromeos/dbus/shill/fake_shill_manager_client.h
@@ -20,7 +20,7 @@ // A fake implementation of ShillManagerClient. This works in close coordination // with FakeShillServiceClient. FakeShillDeviceClient, and // FakeShillProfileClient, and is not intended to be used independently. -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeShillManagerClient +class COMPONENT_EXPORT(SHILL_CLIENT) FakeShillManagerClient : public ShillManagerClient, public ShillManagerClient::TestInterface { public:
diff --git a/chromeos/dbus/shill/fake_shill_profile_client.h b/chromeos/dbus/shill/fake_shill_profile_client.h index 71400f7..8567f7d 100644 --- a/chromeos/dbus/shill/fake_shill_profile_client.h +++ b/chromeos/dbus/shill/fake_shill_profile_client.h
@@ -17,7 +17,7 @@ namespace chromeos { // A stub implementation of ShillProfileClient. -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeShillProfileClient +class COMPONENT_EXPORT(SHILL_CLIENT) FakeShillProfileClient : public ShillProfileClient, public ShillProfileClient::TestInterface { public:
diff --git a/chromeos/dbus/shill/fake_shill_service_client.cc b/chromeos/dbus/shill/fake_shill_service_client.cc index 4fc8536..e24cfc51 100644 --- a/chromeos/dbus/shill/fake_shill_service_client.cc +++ b/chromeos/dbus/shill/fake_shill_service_client.cc
@@ -16,7 +16,6 @@ #include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/dbus/shill/shill_profile_client.h"
diff --git a/chromeos/dbus/shill/fake_shill_service_client.h b/chromeos/dbus/shill/fake_shill_service_client.h index 084d487..50549c6 100644 --- a/chromeos/dbus/shill/fake_shill_service_client.h +++ b/chromeos/dbus/shill/fake_shill_service_client.h
@@ -20,7 +20,7 @@ // A fake implementation of ShillServiceClient. This works in close coordination // with FakeShillManagerClient and is not intended to be used independently. -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeShillServiceClient +class COMPONENT_EXPORT(SHILL_CLIENT) FakeShillServiceClient : public ShillServiceClient, public ShillServiceClient::TestInterface { public:
diff --git a/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h index a70730f..0a8d041 100644 --- a/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h +++ b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h
@@ -21,7 +21,7 @@ // The client can generate fake DBus signals when // ShillThirdPartyVpnDriverClient::TestInterface methods are called. The // DBus methods are nops that only acknowledge the caller. -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeShillThirdPartyVpnDriverClient +class COMPONENT_EXPORT(SHILL_CLIENT) FakeShillThirdPartyVpnDriverClient : public ShillThirdPartyVpnDriverClient, public ShillThirdPartyVpnDriverClient::TestInterface { public:
diff --git a/chromeos/dbus/shill/gsm_sms_client.h b/chromeos/dbus/shill/gsm_sms_client.h index 05aee39..5d65a2a 100644 --- a/chromeos/dbus/shill/gsm_sms_client.h +++ b/chromeos/dbus/shill/gsm_sms_client.h
@@ -30,7 +30,7 @@ // org.freedesktop.ModemManager.Modem.Gsm.SMS service. // All methods should be called from the origin thread (UI thread) which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) GsmSMSClient { +class COMPONENT_EXPORT(SHILL_CLIENT) GsmSMSClient { public: typedef base::Callback<void(uint32_t index, bool complete)> SmsReceivedHandler;
diff --git a/chromeos/dbus/shill/modem_messaging_client.h b/chromeos/dbus/shill/modem_messaging_client.h index b089be41..4f1073a 100644 --- a/chromeos/dbus/shill/modem_messaging_client.h +++ b/chromeos/dbus/shill/modem_messaging_client.h
@@ -11,7 +11,6 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/dbus_method_call_status.h" namespace dbus { @@ -25,7 +24,7 @@ // org.freedesktop.ModemManager1.Modem.Messaging service. All methods // should be called from the origin thread (UI thread) which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ModemMessagingClient { +class COMPONENT_EXPORT(SHILL_CLIENT) ModemMessagingClient { public: typedef base::Callback<void(const dbus::ObjectPath& message_path, bool complete)>
diff --git a/chromeos/dbus/shill/shill_clients.h b/chromeos/dbus/shill/shill_clients.h index aca7564..edba68f 100644 --- a/chromeos/dbus/shill/shill_clients.h +++ b/chromeos/dbus/shill/shill_clients.h
@@ -15,13 +15,13 @@ namespace shill_clients { // Initialize Shill and modemmanager related dbus clients. -COMPONENT_EXPORT(CHROMEOS_DBUS) void Initialize(dbus::Bus* system_bus); +COMPONENT_EXPORT(SHILL_CLIENT) void Initialize(dbus::Bus* system_bus); // Initialize fake Shill and modemmanager related dbus clients. -COMPONENT_EXPORT(CHROMEOS_DBUS) void InitializeFakes(); +COMPONENT_EXPORT(SHILL_CLIENT) void InitializeFakes(); // Shut down Shill and modemmanager related dbus clients. -COMPONENT_EXPORT(CHROMEOS_DBUS) void Shutdown(); +COMPONENT_EXPORT(SHILL_CLIENT) void Shutdown(); } // namespace shill_clients } // namespace chromeos
diff --git a/chromeos/dbus/shill/shill_device_client.h b/chromeos/dbus/shill/shill_device_client.h index c4f1b03d..d3e97eb5 100644 --- a/chromeos/dbus/shill/shill_device_client.h +++ b/chromeos/dbus/shill/shill_device_client.h
@@ -33,7 +33,7 @@ // ShillDeviceClient is used to communicate with the Shill Device service. // All methods should be called from the origin thread which initializes the // DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillDeviceClient { +class COMPONENT_EXPORT(SHILL_CLIENT) ShillDeviceClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback;
diff --git a/chromeos/dbus/shill/shill_ipconfig_client.h b/chromeos/dbus/shill/shill_ipconfig_client.h index 272545d..2dd805b 100644 --- a/chromeos/dbus/shill/shill_ipconfig_client.h +++ b/chromeos/dbus/shill/shill_ipconfig_client.h
@@ -29,7 +29,7 @@ // ShillIPConfigClient is used to communicate with the Shill IPConfig // service. All methods should be called from the origin thread which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillIPConfigClient { +class COMPONENT_EXPORT(SHILL_CLIENT) ShillIPConfigClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback;
diff --git a/chromeos/dbus/shill/shill_manager_client.h b/chromeos/dbus/shill/shill_manager_client.h index 02900c0..92042eb 100644 --- a/chromeos/dbus/shill/shill_manager_client.h +++ b/chromeos/dbus/shill/shill_manager_client.h
@@ -24,7 +24,7 @@ // ShillManagerClient is used to communicate with the Shill Manager // service. All methods should be called from the origin thread which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillManagerClient { +class COMPONENT_EXPORT(SHILL_CLIENT) ShillManagerClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback;
diff --git a/chromeos/dbus/shill/shill_profile_client.cc b/chromeos/dbus/shill/shill_profile_client.cc index 170c422..0782411 100644 --- a/chromeos/dbus/shill/shill_profile_client.cc +++ b/chromeos/dbus/shill/shill_profile_client.cc
@@ -11,7 +11,6 @@ #include "base/bind.h" #include "base/macros.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/fake_shill_profile_client.h" #include "chromeos/dbus/shill/shill_property_changed_observer.h" #include "dbus/bus.h"
diff --git a/chromeos/dbus/shill/shill_profile_client.h b/chromeos/dbus/shill/shill_profile_client.h index b75a452..8c1ca92 100644 --- a/chromeos/dbus/shill/shill_profile_client.h +++ b/chromeos/dbus/shill/shill_profile_client.h
@@ -29,7 +29,7 @@ // ShillProfileClient is used to communicate with the Shill Profile // service. All methods should be called from the origin thread which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillProfileClient { +class COMPONENT_EXPORT(SHILL_CLIENT) ShillProfileClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallbackWithoutStatus
diff --git a/chromeos/dbus/shill/shill_service_client.h b/chromeos/dbus/shill/shill_service_client.h index c3a4658..84f271ec 100644 --- a/chromeos/dbus/shill/shill_service_client.h +++ b/chromeos/dbus/shill/shill_service_client.h
@@ -29,7 +29,7 @@ // service. // All methods should be called from the origin thread which initializes the // DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillServiceClient { +class COMPONENT_EXPORT(SHILL_CLIENT) ShillServiceClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback;
diff --git a/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h index 89814686..4ec6abde 100644 --- a/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h +++ b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h
@@ -30,7 +30,7 @@ // ThirdPartyVpnDriver service. // All methods should be called from the origin thread which initializes the // DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillThirdPartyVpnDriverClient { +class COMPONENT_EXPORT(SHILL_CLIENT) ShillThirdPartyVpnDriverClient { public: class TestInterface { public:
diff --git a/chromeos/dbus/shill/sms_client.h b/chromeos/dbus/shill/sms_client.h index de50158..89a6673e 100644 --- a/chromeos/dbus/shill/sms_client.h +++ b/chromeos/dbus/shill/sms_client.h
@@ -10,7 +10,6 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" namespace base { class Bus; @@ -18,6 +17,7 @@ } // namespace base namespace dbus { +class Bus; class ObjectPath; } @@ -27,7 +27,7 @@ // org.freedesktop.ModemManager1.SMS service. All methods should be // called from the origin thread (UI thread) which initializes the // DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) SMSClient { +class COMPONENT_EXPORT(SHILL_CLIENT) SMSClient { public: using GetAllCallback = base::OnceCallback<void(const base::DictionaryValue& sms)>;
diff --git a/chromeos/geolocation/BUILD.gn b/chromeos/geolocation/BUILD.gn index 525c819..4bc2e9df 100644 --- a/chromeos/geolocation/BUILD.gn +++ b/chromeos/geolocation/BUILD.gn
@@ -32,7 +32,7 @@ deps = [ ":geolocation", "//base", - "//chromeos/dbus", + "//chromeos/dbus/shill", "//chromeos/network:test_support", "//net", "//services/network:test_support",
diff --git a/chromeos/network/BUILD.gn b/chromeos/network/BUILD.gn index 5dda140..99fb26a 100644 --- a/chromeos/network/BUILD.gn +++ b/chromeos/network/BUILD.gn
@@ -14,8 +14,9 @@ "//base", "//base:i18n", "//chromeos/constants", - "//chromeos/dbus", + "//chromeos/dbus:common", "//chromeos/dbus/permission_broker", + "//chromeos/dbus/shill", "//chromeos/login/login_state", "//components/account_id", "//components/certificate_matching",
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc index 3acbc8c..6a15e0b 100644 --- a/components/autofill/core/browser/autofill_profile.cc +++ b/components/autofill/core/browser/autofill_profile.cc
@@ -444,12 +444,6 @@ return 0; } -bool AutofillProfile::EqualsSansOrigin(const AutofillProfile& profile) const { - return guid() == profile.guid() && - language_code() == profile.language_code() && - Compare(profile) == 0; -} - bool AutofillProfile::EqualsForSyncPurposes(const AutofillProfile& profile) const { return use_count() == profile.use_count() && @@ -665,16 +659,6 @@ } // static -bool AutofillProfile::SupportsMultiValue(ServerFieldType type) { - FieldTypeGroup group = AutofillType(type).group(); - return group == NAME || - group == NAME_BILLING || - group == EMAIL || - group == PHONE_HOME || - group == PHONE_BILLING; -} - -// static void AutofillProfile::CreateDifferentiatingLabels( const std::vector<AutofillProfile*>& profiles, const std::string& app_locale,
diff --git a/components/autofill/core/browser/autofill_profile.h b/components/autofill/core/browser/autofill_profile.h index 716f726e..59b8bf12 100644 --- a/components/autofill/core/browser/autofill_profile.h +++ b/components/autofill/core/browser/autofill_profile.h
@@ -100,9 +100,6 @@ // themselves. int Compare(const AutofillProfile& profile) const; - // Same as operator==, but ignores differences in origin. - bool EqualsSansOrigin(const AutofillProfile& profile) const; - // Same as operator==, but ignores differences in guid and cares about // differences in usage stats. bool EqualsForSyncPurposes(const AutofillProfile& profile) const; @@ -149,9 +146,6 @@ bool SaveAdditionalInfo(const AutofillProfile& profile, const std::string& app_locale); - // Returns |true| if |type| accepts multi-values. - static bool SupportsMultiValue(ServerFieldType type); - // Creates a differentiating label for each of the |profiles|. // Labels consist of the minimal differentiating combination of: // 1. Full name.
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index ffab385a..816aa8d 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -337,12 +337,6 @@ return profile; } -AutofillProfile GetVerifiedProfile2() { - AutofillProfile profile(GetFullProfile2()); - profile.set_origin(kSettingsOrigin); - return profile; -} - AutofillProfile GetServerProfile() { AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "id1"); // Note: server profiles don't have email addresses and only have full names.
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h index 02eb584..9b74aab 100644 --- a/components/autofill/core/browser/autofill_test_utils.h +++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -112,9 +112,6 @@ // Returns a verified profile full of dummy info. AutofillProfile GetVerifiedProfile(); -// Returns a verified profile full of dummy info, different to the above. -AutofillProfile GetVerifiedProfile2(); - // Returns a server profile full of dummy info. AutofillProfile GetServerProfile(); @@ -127,12 +124,6 @@ // Returns a credit card full of dummy info, different to the above. CreditCard GetCreditCard2(); -// Returns a verified credit card full of dummy info. -CreditCard GetVerifiedCreditCard(); - -// Returns a verified credit card full of dummy info, different to the above. -CreditCard GetVerifiedCreditCard2(); - // Returns a masked server card full of dummy info. CreditCard GetMaskedServerCard(); CreditCard GetMaskedServerCardAmex();
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index cdfc2f3..08281b2 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -1230,24 +1230,6 @@ return values; } -base::string16 FormStructure::GetUniqueValue(HtmlFieldType type) const { - base::string16 value; - for (const auto& field : fields_) { - if (field->html_type() != type) - continue; - - // More than one value found; abort rather than choosing one arbitrarily. - if (!value.empty() && !field->value.empty()) { - value.clear(); - break; - } - - value = field->value; - } - - return value; -} - const AutofillField* FormStructure::field(size_t index) const { if (index >= fields_.size()) { NOTREACHED(); @@ -1728,7 +1710,14 @@ void FormStructure::RationalizeFieldTypePredictions() { RationalizeCreditCardFieldPredictions(); for (const auto& field : fields_) { - field->SetTypeTo(field->Type()); + if (base::FeatureList::IsEnabled(features::kAutofillOffNoServerData) && + !field->should_autocomplete && field->server_type() == NO_SERVER_DATA) { + // When the field has autocomplete off, and the server returned no + // prediction, then assume Autofill is not useful for the current field. + field->SetTypeTo(AutofillType(UNKNOWN_TYPE)); + } else { + field->SetTypeTo(field->Type()); + } } }
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index 8f7fdaa..102920d9 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -194,10 +194,6 @@ // All returned values are standardized to upper case. std::set<base::string16> PossibleValues(ServerFieldType type); - // Gets the form's current value for |type|. For example, it may return - // the contents of a text input or the currently selected <option>. - base::string16 GetUniqueValue(HtmlFieldType type) const; - // Rationalize phone number fields in a given section, that is only fill // the fields that are considered composing a first complete phone number. void RationalizePhoneNumbersInSection(std::string section);
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc index cdc3cd5..b20f3c9 100644 --- a/components/autofill/core/browser/form_structure_unittest.cc +++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -143,6 +143,10 @@ scoped_refptr<base::FieldTrial> field_trial_; }; +class ParameterizedFormStructureTest + : public FormStructureTest, + public testing::WithParamInterface<bool> {}; + TEST_F(FormStructureTest, FieldCount) { std::unique_ptr<FormStructure> form_structure; FormData form; @@ -6584,6 +6588,81 @@ EXPECT_EQ(ADDRESS_HOME_STATE, forms[0]->field(5)->Type().GetStorableType()); } +INSTANTIATE_TEST_SUITE_P(, + ParameterizedFormStructureTest, + testing::Values(true, false)); + +// Tests that, when the flag is off, we will not set the predicted type to +// unknown for fields that have no server data and autocomplete off, and when +// the flag is ON, we will overwrite the predicted type. +TEST_P(ParameterizedFormStructureTest, + NoServerData_AutocompleteOff_FlagDisabled_NoOverwrite) { + base::test::ScopedFeatureList scoped_features; + + bool flag_enabled = GetParam(); + scoped_features.InitWithFeatureState(features::kAutofillOffNoServerData, + flag_enabled); + + FormData form; + form.origin = GURL("http://foo.com"); + FormFieldData field; + field.form_control_type = "text"; + field.max_length = 10000; + field.should_autocomplete = false; + + // Autocomplete Off, with server data. + field.label = ASCIIToUTF16("First Name"); + field.name = ASCIIToUTF16("firstName"); + form.fields.push_back(field); + + // Autocomplete Off, without server data. + field.label = ASCIIToUTF16("Last Name"); + field.name = ASCIIToUTF16("lastName"); + form.fields.push_back(field); + + // Autocomplete On, with server data. + field.should_autocomplete = true; + field.label = ASCIIToUTF16("Address"); + field.name = ASCIIToUTF16("address"); + form.fields.push_back(field); + + // Autocomplete On, without server data. + field.label = ASCIIToUTF16("Country"); + field.name = ASCIIToUTF16("country"); + form.fields.push_back(field); + + AutofillQueryResponseContents response; + response.add_field()->set_overall_type_prediction(NAME_FIRST); + response.add_field()->set_overall_type_prediction(NO_SERVER_DATA); + response.add_field()->set_overall_type_prediction(NO_SERVER_DATA); + response.add_field()->set_overall_type_prediction(NO_SERVER_DATA); + + std::string response_string; + ASSERT_TRUE(response.SerializeToString(&response_string)); + + FormStructure form_structure(form); + + // Will identify the sections based on the heuristics types. + form_structure.DetermineHeuristicTypes(); + + std::vector<FormStructure*> forms; + forms.push_back(&form_structure); + + // Will call RationalizeFieldTypePredictions + FormStructure::ParseQueryResponse(response_string, forms, nullptr); + + ASSERT_EQ(1U, forms.size()); + ASSERT_EQ(4U, forms[0]->field_count()); + + // Only NAME_LAST should be affected by the flag. + EXPECT_EQ(flag_enabled ? UNKNOWN_TYPE : NAME_LAST, + forms[0]->field(1)->Type().GetStorableType()); + + EXPECT_EQ(NAME_FIRST, forms[0]->field(0)->Type().GetStorableType()); + EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(2)->Type().GetStorableType()); + EXPECT_EQ(ADDRESS_HOME_COUNTRY, forms[0]->field(3)->Type().GetStorableType()); +} + TEST_F(FormStructureTest, AllowBigForms) { FormData form; form.origin = GURL("http://foo.com");
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 0a175f96..634a03d 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -70,6 +70,9 @@ const base::Feature kAutofillEnableCompanyName{ "AutofillEnableCompanyName", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kAutofillOffNoServerData{"AutofillOffNoServerData", + base::FEATURE_DISABLED_BY_DEFAULT}; + // When enabled, autofill server will override field types with rater // consensus data before returning to client. const base::Feature kAutofillOverrideWithRaterConsensus{
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index a148569..fbf0e97 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -40,6 +40,7 @@ extern const base::Feature kAutofillManualFallback; extern const base::Feature kAutofillManualFallbackPhaseTwo; extern const base::Feature kAutofillMetadataUploads; +extern const base::Feature kAutofillOffNoServerData; extern const base::Feature kAutofillOverrideWithRaterConsensus; extern const base::Feature kAutofillPreferServerNamePredictions; extern const base::Feature kAutofillProfileServerValidation;
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc index 53961dc..5de561a 100644 --- a/components/browser_sync/profile_sync_components_factory_impl.cc +++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -396,8 +396,7 @@ syncer::READING_LIST)); } - if (!disabled_types.Has(syncer::USER_EVENTS) && - FeatureList::IsEnabled(switches::kSyncUserEvents)) { + if (!disabled_types.Has(syncer::USER_EVENTS)) { controllers.push_back(CreateModelTypeControllerForModelRunningOnUIThread( syncer::USER_EVENTS)); }
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index 94e73a7..087b448 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -55,12 +55,6 @@ srcjar_deps = [ ":cronet_jni_registration" ] } -java_cpp_enum("effective_connection_type_java") { - sources = [ - "//net/nqe/effective_connection_type.h", - ] -} - java_cpp_enum("rtt_throughput_values_java") { sources = [ "//net/nqe/network_quality.h", @@ -260,11 +254,11 @@ } cronet_impl_common_java_srcjar_deps = [ - ":effective_connection_type_java", ":http_cache_type_java", ":integrated_mode_state", ":load_states_list", ":rtt_throughput_values_java", + "//net:effective_connection_type_java", ] cronet_impl_common_java_deps_to_package =
diff --git a/components/domain_reliability/bake_in_configs.py b/components/domain_reliability/bake_in_configs.py index d3d5f6e6..cf2e8b4 100755 --- a/components/domain_reliability/bake_in_configs.py +++ b/components/domain_reliability/bake_in_configs.py
@@ -8,6 +8,7 @@ encodes their contents as an array of C strings that gets compiled in to Chrome and loaded at runtime.""" +from __future__ import print_function import ast import json @@ -532,13 +533,13 @@ opts, args = parser.parse_args() if not opts.output: - print >> sys.stderr, "--output argument required" + print("--output argument required", file=sys.stderr) return 1 if opts.gypi_file: # .gypi-style input. if not opts.gypi_relative_to: - print >> sys.stderr, "--gypi-relative-to is required with --gypi-file" + print("--gypi-relative-to is required with --gypi-file", file=sys.stderr) return 1 json_files = read_json_files_from_gypi(opts.gypi_file) json_files = [ os.path.join(opts.gypi_relative_to, f) for f in json_files ] @@ -547,7 +548,7 @@ # Regular file list input. json_files = read_json_files_from_file(opts.file_list) else: - print >> sys.stderr, "Either --file-list or --gypi-file is required." + print("Either --file-list or --gypi-file is required.", file=sys.stderr) return 1 cpp_code = CC_HEADER @@ -558,18 +559,19 @@ json_text = f.read() try: config = json.loads(json_text) - except ValueError, e: - print >> sys.stderr, "%s: error parsing JSON: %s" % (json_file, e) + except ValueError as e: + print("%s: error parsing JSON: %s" % (json_file, e), file=sys.stderr) found_invalid_config = True continue if 'origin' not in config: - print >> sys.stderr, '%s: no origin found' % json_file + print('%s: no origin found' % json_file, file=sys.stderr) found_invalid_config = True continue origin = config['origin'] if not origin_is_whitelisted(origin): - print >> sys.stderr, ('%s: origin "%s" not in whitelist' % - (json_file, origin)) + print( + '%s: origin "%s" not in whitelist' % (json_file, origin), + file=sys.stderr) found_invalid_config = True continue @@ -585,7 +587,7 @@ if found_invalid_config: return 1 - with open(opts.output, 'wb') as f: + with open(opts.output, 'w') as f: f.write(cpp_code) return 0
diff --git a/components/metrics/file_metrics_provider.cc b/components/metrics/file_metrics_provider.cc index ae677948..938cc89 100644 --- a/components/metrics/file_metrics_provider.cc +++ b/components/metrics/file_metrics_provider.cc
@@ -636,13 +636,10 @@ SystemProfileProto* system_profile_proto, base::HistogramSnapshotManager* snapshot_manager) { RecordEmbeddedProfileResult(EMBEDDED_PROFILE_ATTEMPT); - base::Time start_time = base::Time::Now(); if (PersistentSystemProfile::GetSystemProfile( *source->allocator->memory_allocator(), system_profile_proto)) { system_profile_proto->mutable_stability()->set_from_previous_run(true); RecordHistogramSnapshotsFromSource(snapshot_manager, source); - UMA_HISTOGRAM_TIMES("UMA.FileMetricsProvider.EmbeddedProfile.RecordTime", - base::Time::Now() - start_time); RecordEmbeddedProfileResult(EMBEDDED_PROFILE_FOUND); if (system_profile_proto->hardware().has_cpu()) {
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index 9486d34..1d927bd 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -171,8 +171,13 @@ // Feature used for showing the URL suggestion favicons as a UI experiment, // currently only used on desktop platforms. const base::Feature kUIExperimentShowSuggestionFavicons{ - "OmniboxUIExperimentShowSuggestionFavicons", - base::FEATURE_ENABLED_BY_DEFAULT}; + "OmniboxUIExperimentShowSuggestionFavicons", +#if defined(OS_ANDROID) + base::FEATURE_DISABLED_BY_DEFAULT +#else + base::FEATURE_ENABLED_BY_DEFAULT +#endif +}; // Feature used to always swap the title and URL. const base::Feature kUIExperimentSwapTitleAndUrl{
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index f4bed0c..65423ae1 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -1981,8 +1981,8 @@ 'type': 'string', 'enum': [ 'any', - 'secure', - 'unsecure', + 'pin', + 'no_pin', ], }, 'items': [ @@ -1992,24 +1992,24 @@ 'caption': '''Allow printing both with and without PIN''', }, { - 'name': 'secure', - 'value': 'secure', + 'name': 'pin', + 'value': 'pin', 'caption': '''Allow printing only with PIN''', }, { - 'name': 'unsecure', - 'value': 'unsecure', + 'name': 'no_pin', + 'value': 'no_pin', 'caption': '''Allow printing only without PIN''', }, ], - 'supported_on': ['chrome_os:74-'], + 'supported_on': ['chrome_os:75-'], 'future': True, 'features': { 'can_be_recommended': False, 'dynamic_refresh': True, 'per_profile': True, }, - 'example_value': 'secure', + 'example_value': 'pin', 'id': 525, 'caption': '''Restrict PIN printing mode''', 'tags': [], @@ -2128,30 +2128,30 @@ 'schema': { 'type': 'string', 'enum': [ - 'secure', - 'unsecure', + 'pin', + 'no_pin', ], }, 'items': [ { - 'name': 'secure', - 'value': 'secure', + 'name': 'pin', + 'value': 'pin', 'caption': '''Enable PIN printing by default''', }, { - 'name': 'unsecure', - 'value': 'unsecure', + 'name': 'no_pin', + 'value': 'no_pin', 'caption': '''Disable PIN printing by default''', }, ], - 'supported_on': ['chrome_os:74-'], + 'supported_on': ['chrome_os:75-'], 'future': True, 'features': { 'can_be_recommended': False, 'dynamic_refresh': True, 'per_profile': True, }, - 'example_value': 'secure', + 'example_value': 'pin', 'id': 526, 'caption': '''Default PIN printing mode''', 'tags': [], @@ -15085,6 +15085,7 @@ 'dynamic_refresh': False, 'per_profile': True, }, + 'default_for_enterprise_users': True, 'example_value': False, 'id': 533, 'caption': '''Allows a page to show popups during its unloading''',
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index f0e785d..eb717d8d 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -789,8 +789,7 @@ blink::WebTreeScopeType scope, const blink::WebString& name, const blink::WebString& fallback_name, - blink::WebSandboxFlags sandbox_flags, - const blink::ParsedFeaturePolicy& container_policy, + const blink::FramePolicy& frame_policy, const blink::WebFrameOwnerProperties& frame_owner_properties, blink::FrameOwnerElementType owner_type) override; void FrameDetached(DetachType detach_type) override; @@ -970,8 +969,7 @@ blink::WebTreeScopeType scope, const blink::WebString& name, const blink::WebString& fallback_name, - blink::WebSandboxFlags sandbox_flags, - const blink::ParsedFeaturePolicy& container_policy, + const blink::FramePolicy& frame_policy, const blink::WebFrameOwnerProperties& frame_owner_properties, blink::FrameOwnerElementType frame_owner_type) { // This is called when printing a selection and when this selection contains
diff --git a/components/search_engines/prepopulated_engines.json b/components/search_engines/prepopulated_engines.json index 9d7af2b..877048a 100644 --- a/components/search_engines/prepopulated_engines.json +++ b/components/search_engines/prepopulated_engines.json
@@ -28,7 +28,7 @@ // Increment this if you change the data in ways that mean users with // existing data should get a new version. Otherwise, existing data may // continue to be used and updates made here will not always appear. - "kCurrentDataVersion": 111 + "kCurrentDataVersion": 112 }, // The following engines are included in country lists and are added to the @@ -101,6 +101,7 @@ "favicon_url": "https://duckduckgo.com/favicon.ico", "search_url": "https://duckduckgo.com/?q={searchTerms}", "suggest_url": "https://duckduckgo.com/ac/?q={searchTerms}&type=list", + "new_tab_url": "https://duckduckgo.com/chrome_newtab", "type": "SEARCH_ENGINE_DUCKDUCKGO", "id": 92 },
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc index fa9c1b3..142c31b 100644 --- a/components/signin/core/browser/chrome_connected_header_helper.cc +++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -22,6 +22,8 @@ namespace { +const char kConsistencyEnabledByDefaultAttrName[] = + "consistency_enabled_by_default"; const char kContinueUrlAttrName[] = "continue_url"; const char kEmailAttrName[] = "email"; const char kEnableAccountConsistencyAttrName[] = "enable_account_consistency"; @@ -167,20 +169,23 @@ const GURL& url, const std::string& account_id, int profile_mode_mask) { -// If we are on mobile, an empty |account_id| corresponds to the user not signed -// into Sync. Do not enforce account consistency, unless Mice is enabled on -// Android. +#if defined(OS_ANDROID) + bool is_mice_enabled = base::FeatureList::IsEnabled(kMiceFeature); +#else + bool is_mice_enabled = false; +#endif + +// If we are on mobile or desktop, an empty |account_id| corresponds to the user +// not signed into Sync. Do not enforce account consistency, unless Mice is +// enabled on Android. // On Chrome OS, an empty |account_id| corresponds to Public Sessions, Guest // Sessions and Active Directory logins. Guest Sessions have already been // filtered upstream and we want to enforce account consistency in Public // Sessions and Active Directory logins. -#if defined(OS_ANDROID) - if (account_id.empty() && !base::FeatureList::IsEnabled(kMiceFeature)) +#if !defined(OS_CHROMEOS) + if (account_id.empty() && !is_mice_enabled) return std::string(); -#elif !defined(OS_CHROMEOS) - if (account_id.empty()) - return std::string(); -#endif +#endif // !defined(OS_CHROMEOS) std::vector<std::string> parts; if (!account_id.empty() && @@ -196,6 +201,9 @@ account_consistency_ == AccountConsistencyMethod::kMirror; parts.push_back(base::StringPrintf("%s=%s", kEnableAccountConsistencyAttrName, is_mirror_enabled ? "true" : "false")); + parts.push_back(base::StringPrintf("%s=%s", + kConsistencyEnabledByDefaultAttrName, + is_mice_enabled ? "true" : "false")); return base::JoinString(parts, is_header_request ? "," : ":"); }
diff --git a/components/signin/core/browser/signin_error_controller.cc b/components/signin/core/browser/signin_error_controller.cc index 21c5c29f..9b2e0b9 100644 --- a/components/signin/core/browser/signin_error_controller.cc +++ b/components/signin/core/browser/signin_error_controller.cc
@@ -26,21 +26,68 @@ } void SigninErrorController::Update() { - GoogleServiceAuthError::State prev_state = auth_error_.state(); - std::string prev_account_id = error_account_id_; + const GoogleServiceAuthError::State prev_error_state = auth_error_.state(); + const std::string prev_account_id = error_account_id_; bool error_changed = false; + const std::string& primary_account_id = + identity_manager_->GetPrimaryAccountId(); + + if (identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState( + primary_account_id)) { + // Prioritize Primary Account errors over everything else. + auth_error_ = identity_manager_->GetErrorStateOfRefreshTokenForAccount( + primary_account_id); + DCHECK(auth_error_.IsPersistentError()); + error_account_id_ = primary_account_id; + error_changed = true; + } else if (account_mode_ != AccountMode::PRIMARY_ACCOUNT) { + // Additionally, check for Secondary Account errors, if we are not in + // |AccountMode::PRIMARY_ACCOUNT| mode. + error_changed = UpdateSecondaryAccountErrors( + primary_account_id, prev_account_id, prev_error_state); + } + + if (!error_changed && prev_error_state != GoogleServiceAuthError::NONE) { + // No provider reported an error, so clear the error we have now. + auth_error_ = GoogleServiceAuthError::AuthErrorNone(); + error_account_id_.clear(); + error_changed = true; + } + + if (!error_changed) + return; + + if (auth_error_.state() == prev_error_state && + error_account_id_ == prev_account_id) { + // Only fire notification if the auth error state or account were updated. + return; + } + + signin_metrics::LogAuthError(auth_error_); + for (auto& observer : observer_list_) + observer.OnErrorChanged(); +} + +bool SigninErrorController::UpdateSecondaryAccountErrors( + const std::string& primary_account_id, + const std::string& prev_account_id, + const GoogleServiceAuthError::State& prev_error_state) { + // This method should not have been called if we are in + // |AccountMode::PRIMARY_ACCOUNT|. + DCHECK_NE(AccountMode::PRIMARY_ACCOUNT, account_mode_); + // Find an error among the status providers. If |auth_error_| has an // actionable error state and some provider exposes a similar error and // account id, use that error. Otherwise, just take the first actionable // error we find. + bool error_changed = false; for (const AccountInfo& account_info : identity_manager_->GetAccountsWithRefreshTokens()) { std::string account_id = account_info.account_id; - // In PRIMARY_ACCOUNT mode, ignore all secondary accounts. - if (account_mode_ == AccountMode::PRIMARY_ACCOUNT && - (account_id != identity_manager_->GetPrimaryAccountId())) { + // Ignore the Primary Account. We are only interested in Secondary Accounts. + if (account_id == primary_account_id) { continue; } @@ -55,12 +102,12 @@ DCHECK(error.IsPersistentError()); // Prioritize this error if it matches the previous |auth_error_|. - if (error.state() == prev_state && account_id == prev_account_id) { + if (error.state() == prev_error_state && account_id == prev_account_id) { // The previous error for the previous account still exists. This error is // preferred to avoid UI churn, so |auth_error_| and |error_account_id_| // must be updated to match the previous state. This is needed in case - // |auth_error_| and |error_account_id_| were updated to other values in - // a previous iteration via the if statement below. + // |auth_error_| and |error_account_id_| were updated to other values in a + // previous iteration via the if statement below. auth_error_ = error; error_account_id_ = account_id; error_changed = true; @@ -76,25 +123,7 @@ } } - if (!error_changed && prev_state != GoogleServiceAuthError::NONE) { - // No provider reported an error, so clear the error we have now. - auth_error_ = GoogleServiceAuthError::AuthErrorNone(); - error_account_id_.clear(); - error_changed = true; - } - - if (!error_changed) - return; - - if (auth_error_.state() == prev_state && - error_account_id_ == prev_account_id) { - // Only fire notification if the auth error state or account were updated. - return; - } - - signin_metrics::LogAuthError(auth_error_); - for (auto& observer : observer_list_) - observer.OnErrorChanged(); + return error_changed; } bool SigninErrorController::HasError() const {
diff --git a/components/signin/core/browser/signin_error_controller.h b/components/signin/core/browser/signin_error_controller.h index 6edab303..3111119 100644 --- a/components/signin/core/browser/signin_error_controller.h +++ b/components/signin/core/browser/signin_error_controller.h
@@ -64,6 +64,17 @@ // Invoked when the auth status has changed. void Update(); + // Checks for Secondary Account errors and updates |auth_error_| and + // |error_account_id_| accordingly. Does not do anything if no Secondary + // Account has any error. Returns true if an error was found in a Secondary + // Account, false otherwise. + // Note: This function must not be called if |account_mode_| is + // |AccountMode::PRIMARY_ACCOUNT|. + bool UpdateSecondaryAccountErrors( + const std::string& primary_account_id, + const std::string& prev_account_id, + const GoogleServiceAuthError::State& prev_error_state); + // identity::IdentityManager::Observer: void OnEndBatchOfRefreshTokenStateChanges() override; void OnErrorStateOfRefreshTokenUpdatedForAccount(
diff --git a/components/signin/core/browser/signin_error_controller_unittest.cc b/components/signin/core/browser/signin_error_controller_unittest.cc index 2b88b04cf..90b3539 100644 --- a/components/signin/core/browser/signin_error_controller_unittest.cc +++ b/components/signin/core/browser/signin_error_controller_unittest.cc
@@ -19,8 +19,9 @@ namespace { -static const char kTestEmail[] = "me@test.com"; -static const char kOtherTestEmail[] = "you@test.com"; +constexpr char kPrimaryAccountEmail[] = "primary@example.com"; +constexpr char kTestEmail[] = "me@test.com"; +constexpr char kOtherTestEmail[] = "you@test.com"; class MockSigninErrorControllerObserver : public SigninErrorController::Observer { @@ -285,3 +286,99 @@ test_account_id, GoogleServiceAuthError(GoogleServiceAuthError::NONE)); ASSERT_FALSE(error_controller.HasError()); } + +TEST(SigninErrorControllerTest, + PrimaryAccountErrorsArePreferredToSecondaryAccountErrors) { + base::test::ScopedTaskEnvironment task_environment; + identity::IdentityTestEnvironment identity_test_env; + + AccountInfo primary_account_info = + identity_test_env.MakePrimaryAccountAvailable(kPrimaryAccountEmail); + std::string secondary_account_id = + identity_test_env.MakeAccountAvailable(kTestEmail).account_id; + SigninErrorController error_controller( + SigninErrorController::AccountMode::ANY_ACCOUNT, + identity_test_env.identity_manager()); + ASSERT_FALSE(error_controller.HasError()); + + // Set an error for the Secondary Account. + identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount( + secondary_account_id, + GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, + error_controller.auth_error().state()); + ASSERT_EQ(secondary_account_id, error_controller.error_account_id()); + + // Set an error for the Primary Account. This should override the previous + // error. + identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount( + primary_account_info.account_id, + GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, + error_controller.auth_error().state()); + ASSERT_EQ(primary_account_info.account_id, + error_controller.error_account_id()); + + // Clear the Primary Account error. This should cause the Secondary Account + // error to be returned again. + identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount( + primary_account_info.account_id, + GoogleServiceAuthError(GoogleServiceAuthError::NONE)); + ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, + error_controller.auth_error().state()); + ASSERT_EQ(secondary_account_id, error_controller.error_account_id()); + + // Clear the Secondary Account error too. All errors should be gone now. + identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount( + secondary_account_id, + GoogleServiceAuthError(GoogleServiceAuthError::NONE)); + ASSERT_FALSE(error_controller.HasError()); +} + +TEST(SigninErrorControllerTest, PrimaryAccountErrorsAreSticky) { + base::test::ScopedTaskEnvironment task_environment; + identity::IdentityTestEnvironment identity_test_env; + + AccountInfo primary_account_info = + identity_test_env.MakePrimaryAccountAvailable(kPrimaryAccountEmail); + std::string secondary_account_id = + identity_test_env.MakeAccountAvailable(kTestEmail).account_id; + SigninErrorController error_controller( + SigninErrorController::AccountMode::ANY_ACCOUNT, + identity_test_env.identity_manager()); + ASSERT_FALSE(error_controller.HasError()); + + // Set an error for the Primary Account. + identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount( + primary_account_info.account_id, + GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, + error_controller.auth_error().state()); + ASSERT_EQ(primary_account_info.account_id, + error_controller.error_account_id()); + + // Set an error for the Secondary Account. The Primary Account error should + // stick. + identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount( + secondary_account_id, + GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, + error_controller.auth_error().state()); + ASSERT_EQ(primary_account_info.account_id, + error_controller.error_account_id()); + + // Clear the Primary Account error. This should cause the Secondary Account + // error to be returned again. + identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount( + primary_account_info.account_id, + GoogleServiceAuthError(GoogleServiceAuthError::NONE)); + ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, + error_controller.auth_error().state()); + ASSERT_EQ(secondary_account_id, error_controller.error_account_id()); + + // Clear the Secondary Account error too. All errors should be gone now. + identity_test_env.UpdatePersistentErrorOfRefreshTokenForAccount( + secondary_account_id, + GoogleServiceAuthError(GoogleServiceAuthError::NONE)); + ASSERT_FALSE(error_controller.HasError()); +}
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc index ac7493a..a8935aa 100644 --- a/components/signin/core/browser/signin_header_helper_unittest.cc +++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -133,9 +133,11 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestNoAccountIdChromeOS) { account_consistency_ = AccountConsistencyMethod::kMirror; CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "", - "mode=0,enable_account_consistency=true"); + "mode=0,enable_account_consistency=true," + "consistency_enabled_by_default=false"); CheckMirrorCookieRequest(GURL("https://docs.google.com"), "", - "mode=0:enable_account_consistency=true"); + "mode=0:enable_account_consistency=true:" + "consistency_enabled_by_default=false"); } #else // !defined(OS_CHROMEOS) // Tests that no Mirror request is returned when the user is not signed in (no @@ -158,9 +160,11 @@ scoped_feature_list.InitAndEnableFeature(kMiceFeature); account_consistency_ = AccountConsistencyMethod::kMirror; CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "", - "mode=0,enable_account_consistency=true"); + "mode=0,enable_account_consistency=true," + "consistency_enabled_by_default=true"); CheckMirrorCookieRequest(GURL("https://docs.google.com"), "", - "mode=0:enable_account_consistency=true"); + "mode=0:enable_account_consistency=true:" + "consistency_enabled_by_default=true"); } #endif @@ -185,9 +189,11 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleTLD) { account_consistency_ = AccountConsistencyMethod::kMirror; CheckMirrorHeaderRequest(GURL("https://google.fr"), "0123456789", - "mode=0,enable_account_consistency=true"); + "mode=0,enable_account_consistency=true," + "consistency_enabled_by_default=false"); CheckMirrorCookieRequest(GURL("https://google.de"), "0123456789", - "mode=0:enable_account_consistency=true"); + "mode=0:enable_account_consistency=true:" + "consistency_enabled_by_default=false"); } // Tests that the Mirror request is returned when the target is the domain @@ -195,10 +201,12 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleCom) { account_consistency_ = AccountConsistencyMethod::kMirror; CheckMirrorHeaderRequest(GURL("https://www.google.com"), "0123456789", - "mode=0,enable_account_consistency=true"); + "mode=0,enable_account_consistency=true," + "consistency_enabled_by_default=false"); CheckMirrorCookieRequest( GURL("https://www.google.com"), "0123456789", - "id=0123456789:mode=0:enable_account_consistency=true"); + "id=0123456789:mode=0:enable_account_consistency=true:" + "consistency_enabled_by_default=false"); } // Tests that no header sent when mirror account consistency is nor requested. @@ -226,9 +234,10 @@ AppendOrRemoveMirrorRequestHeader( &request_adapter, GURL(), "0123456789", account_consistency_, cookie_settings_.get(), PROFILE_MODE_DEFAULT); - CheckAccountConsistencyHeaderRequest( - url_request.get(), kChromeConnectedHeader, - "mode=0,enable_account_consistency=true"); + CheckAccountConsistencyHeaderRequest(url_request.get(), + kChromeConnectedHeader, + "mode=0,enable_account_consistency=true," + "consistency_enabled_by_default=false"); } // Mirror is always enabled on Android and iOS, so these tests are only relevant @@ -239,10 +248,12 @@ // if account consistency is disabled. TEST_F(SigninHeaderHelperTest, TestMirrorRequestGaiaURL) { CheckMirrorHeaderRequest(GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false"); + "mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false"); CheckMirrorCookieRequest( GURL("https://accounts.google.com"), "0123456789", - "id=0123456789:mode=0:enable_account_consistency=false"); + "id=0123456789:mode=0:enable_account_consistency=false:" + "consistency_enabled_by_default=false"); } // Tests Dice requests. @@ -251,7 +262,9 @@ // ChromeConnected but no Dice for Docs URLs. CheckDiceHeaderRequest( GURL("https://docs.google.com"), "0123456789", - "id=0123456789,mode=0,enable_account_consistency=false", ""); + "id=0123456789,mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false", + ""); // ChromeConnected and Dice for Gaia URLs. // Sync disabled. @@ -259,7 +272,8 @@ ASSERT_FALSE(client_id.empty()); CheckDiceHeaderRequest( GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", + "mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false", base::StringPrintf( "version=%s,client_id=%s,device_id=DeviceID,signin_mode=all_accounts," "signout_mode=show_confirmation", @@ -269,7 +283,8 @@ sync_enabled_ = true; CheckDiceHeaderRequest( GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", + "mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false", base::StringPrintf("version=%s,client_id=%s,device_id=DeviceID," "sync_account_id=0123456789,signin_mode=all_accounts," "signout_mode=show_confirmation", @@ -299,7 +314,9 @@ TEST_F(SigninHeaderHelperTest, TestNoDiceRequestWhenDisabled) { account_consistency_ = AccountConsistencyMethod::kMirror; CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=true", ""); + "mode=0,enable_account_consistency=true," + "consistency_enabled_by_default=false", + ""); } TEST_F(SigninHeaderHelperTest, TestDiceEmptyDeviceID) { @@ -311,7 +328,8 @@ CheckDiceHeaderRequest( GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", + "mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false", base::StringPrintf("version=%s,client_id=%s,signin_mode=all_accounts," "signout_mode=no_confirmation", kDiceProtocolVersion, client_id.c_str())); @@ -327,7 +345,8 @@ // No signout confirmation by default. CheckDiceHeaderRequest( GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", + "mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false", base::StringPrintf( "version=%s,client_id=%s,device_id=DeviceID,signin_mode=all_accounts," "signout_mode=no_confirmation", @@ -337,7 +356,8 @@ account_consistency_ = AccountConsistencyMethod::kDice; CheckDiceHeaderRequest( GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", + "mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false", base::StringPrintf( "version=%s,client_id=%s,device_id=DeviceID,signin_mode=all_accounts," "signout_mode=show_confirmation", @@ -349,19 +369,23 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) { CheckMirrorHeaderRequest( GURL("https://docs.google.com/document"), "0123456789", - "id=0123456789,mode=0,enable_account_consistency=false"); + "id=0123456789,mode=0,enable_account_consistency=false," + "consistency_enabled_by_default=false"); CheckMirrorCookieRequest( GURL("https://drive.google.com/drive"), "0123456789", - "id=0123456789:mode=0:enable_account_consistency=false"); + "id=0123456789:mode=0:enable_account_consistency=false:" + "consistency_enabled_by_default=false"); // Enable Account Consistency will override the disable. account_consistency_ = AccountConsistencyMethod::kMirror; CheckMirrorHeaderRequest( GURL("https://docs.google.com/document"), "0123456789", - "id=0123456789,mode=0,enable_account_consistency=true"); + "id=0123456789,mode=0,enable_account_consistency=true," + "consistency_enabled_by_default=false"); CheckMirrorCookieRequest( GURL("https://drive.google.com/drive"), "0123456789", - "id=0123456789:mode=0:enable_account_consistency=true"); + "id=0123456789:mode=0:enable_account_consistency=true:" + "consistency_enabled_by_default=false"); } TEST_F(SigninHeaderHelperTest, TestDiceInvalidResponseParams) {
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn index 000c7425..0f22c20 100644 --- a/components/sync/BUILD.gn +++ b/components/sync/BUILD.gn
@@ -563,8 +563,6 @@ "user_events/fake_user_event_service.h", "user_events/no_op_user_event_service.cc", "user_events/no_op_user_event_service.h", - "user_events/trial_recorder.cc", - "user_events/trial_recorder.h", "user_events/user_event_service.h", "user_events/user_event_service_impl.cc", "user_events/user_event_service_impl.h", @@ -961,7 +959,6 @@ "syncable/syncable_enum_conversions_unittest.cc", "syncable/syncable_id_unittest.cc", "syncable/syncable_unittest.cc", - "user_events/trial_recorder_unittest.cc", "user_events/user_event_service_impl_unittest.cc", "user_events/user_event_sync_bridge_unittest.cc", ]
diff --git a/components/sync/driver/glue/sync_engine_impl.cc b/components/sync/driver/glue/sync_engine_impl.cc index 71922ec..6798351 100644 --- a/components/sync/driver/glue/sync_engine_impl.cc +++ b/components/sync/driver/glue/sync_engine_impl.cc
@@ -65,6 +65,10 @@ std::move(params))); } +bool SyncEngineImpl::IsInitialized() const { + return initialized_; +} + void SyncEngineImpl::TriggerRefresh(const ModelTypeSet& types) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); sync_task_runner_->PostTask( @@ -215,13 +219,13 @@ } SyncEngineImpl::Status SyncEngineImpl::GetDetailedStatus() { - DCHECK(initialized()); + DCHECK(IsInitialized()); return core_->sync_manager()->GetDetailedStatus(); } void SyncEngineImpl::HasUnsyncedItemsForTest( base::OnceCallback<void(bool)> cb) const { - DCHECK(initialized()); + DCHECK(IsInitialized()); base::PostTaskAndReplyWithResult( sync_task_runner_.get(), FROM_HERE, base::BindOnce(&SyncBackendHostCore::HasUnsyncedItemsForTest, core_), @@ -229,7 +233,7 @@ } void SyncEngineImpl::GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) const { - if (initialized()) { + if (IsInitialized()) { registrar_->GetModelSafeRoutingInfo(out); } else { NOTREACHED(); @@ -237,7 +241,7 @@ } void SyncEngineImpl::FlushDirectory() const { - DCHECK(initialized()); + DCHECK(IsInitialized()); sync_task_runner_->PostTask( FROM_HERE, base::BindOnce(&SyncBackendHostCore::SaveChanges, core_)); } @@ -258,7 +262,7 @@ } void SyncEngineImpl::EnableDirectoryTypeDebugInfoForwarding() { - DCHECK(initialized()); + DCHECK(IsInitialized()); sync_task_runner_->PostTask( FROM_HERE, base::BindOnce( @@ -266,7 +270,7 @@ } void SyncEngineImpl::DisableDirectoryTypeDebugInfoForwarding() { - DCHECK(initialized()); + DCHECK(IsInitialized()); sync_task_runner_->PostTask( FROM_HERE, base::BindOnce( @@ -347,7 +351,7 @@ // Process any changes to the datatypes we're syncing. // TODO(sync): add support for removing types. - if (initialized()) { + if (IsInitialized()) { host_->OnSyncCycleCompleted(snapshot); } }
diff --git a/components/sync/driver/glue/sync_engine_impl.h b/components/sync/driver/glue/sync_engine_impl.h index 8bbde17e..bc0e0b6f 100644 --- a/components/sync/driver/glue/sync_engine_impl.h +++ b/components/sync/driver/glue/sync_engine_impl.h
@@ -56,6 +56,7 @@ // SyncEngine implementation. void Initialize(InitParams params) override; + bool IsInitialized() const override; void TriggerRefresh(const ModelTypeSet& types) override; void UpdateCredentials(const SyncCredentials& credentials) override; void InvalidateCredentials() override; @@ -171,9 +172,6 @@ void HandleSyncCycleCompletedOnFrontendLoop( const SyncCycleSnapshot& snapshot); - // For convenience, checks if initialization state is INITIALIZED. - bool initialized() const { return initialized_; } - // Let the front end handle the actionable error event. void HandleActionableErrorEventOnFrontendLoop( const SyncProtocolError& sync_error);
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index 9395e0a8..08e89954 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -159,7 +159,6 @@ url_loader_factory_(std::move(init_params.url_loader_factory)), network_connection_tracker_(init_params.network_connection_tracker), is_first_time_sync_configure_(false), - engine_initialized_(false), sync_disabled_by_admin_(false), unrecoverable_error_reason_(ERROR_REASON_UNSET), expect_sync_configuration_aborted_(false), @@ -219,7 +218,7 @@ identity_manager_->RemoveObserver(this); sync_prefs_.RemoveSyncPrefObserver(this); // Shutdown() should have been called before destruction. - DCHECK(!engine_initialized_); + DCHECK(!engine_); } void ProfileSyncService::Initialize() { @@ -618,7 +617,6 @@ // Clear various state. crypto_.Reset(); expect_sync_configuration_aborted_ = false; - engine_initialized_ = false; last_snapshot_ = SyncCycleSnapshot(); auth_manager_->ConnectionClosed(); @@ -698,7 +696,7 @@ return TransportState::DISABLED; } - if (!engine_initialized_) { + if (!engine_ || !engine_->IsInitialized()) { switch (startup_controller_->GetState()) { // TODO(crbug.com/935523): If the engine is allowed to start, then we // should generally have kicked off the startup process already, so @@ -810,14 +808,14 @@ void ProfileSyncService::ReenableDatatype(ModelType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!engine_initialized_ || !data_type_manager_) + if (!engine_ || !engine_->IsInitialized() || !data_type_manager_) return; data_type_manager_->ReenableType(type); } void ProfileSyncService::ReadyForStartChanged(ModelType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!engine_initialized_ || !data_type_manager_) + if (!engine_ || !engine_->IsInitialized() || !data_type_manager_) return; data_type_manager_->ReadyForStartChanged(type); } @@ -871,8 +869,6 @@ return; } - engine_initialized_ = true; - sync_js_controller_.AttachJsBackend(js_backend); // Initialize local device info. @@ -971,7 +967,8 @@ void ProfileSyncService::OnMigrationNeededForTypes(ModelTypeSet types) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(engine_initialized_); + DCHECK(engine_); + DCHECK(engine_->IsInitialized()); DCHECK(data_type_manager_); // Migrator must be valid, because we don't sync until it is created and this @@ -1153,7 +1150,7 @@ bool ProfileSyncService::QueryDetailedSyncStatusForDebugging( SyncStatus* result) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (engine_ && engine_initialized_) { + if (engine_ && engine_->IsInitialized()) { *result = engine_->GetDetailedStatus(); return true; } @@ -1204,8 +1201,9 @@ void ProfileSyncService::TriggerRefresh(const ModelTypeSet& types) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (engine_initialized_) + if (engine_ && engine_->IsInitialized()) { engine_->TriggerRefresh(types); + } } bool ProfileSyncService::IsSignedIn() const { @@ -1397,7 +1395,7 @@ UserShare* ProfileSyncService::GetUserShare() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (engine_ && engine_initialized_) { + if (engine_ && engine_->IsInitialized()) { return engine_->GetUserShare(); } NOTREACHED(); @@ -1418,7 +1416,7 @@ base::OnceCallback<void(bool)> cb) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(engine_); - DCHECK(engine_initialized_); + DCHECK(engine_->IsInitialized()); engine_->HasUnsyncedItemsForTest(std::move(cb)); } @@ -1432,7 +1430,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto result = std::make_unique<base::ListValue>(); - if (!engine_ || !engine_initialized_) { + if (!engine_ || !engine_->IsInitialized()) { return std::move(result); } @@ -1527,7 +1525,7 @@ void ProfileSyncService::OnFirstSetupCompletePrefChange( bool is_first_setup_complete) { - if (engine_initialized_) { + if (engine_ && engine_->IsInitialized()) { ReconfigureDatatypeManager(/*bypass_setup_in_progress_check=*/false); } } @@ -1536,7 +1534,7 @@ if (is_sync_requested) { // If the Sync engine was already initialized (probably running in transport // mode), just reconfigure. - if (engine_initialized_) { + if (engine_ && engine_->IsInitialized()) { ReconfigureDatatypeManager(/*bypass_setup_in_progress_check=*/false); } else { // Otherwise try to start up. Note that there might still be other disable @@ -1573,7 +1571,7 @@ const std::vector<gaia::ListedAccount>& signed_in_accounts, const base::Closure& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!engine_initialized_) + if (!engine_ || !engine_->IsInitialized()) return; bool cookie_jar_mismatch = HasCookieJarMismatch(signed_in_accounts); @@ -1617,8 +1615,8 @@ TypeDebugInfoObserver* type_debug_info_observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); type_debug_info_observers_.AddObserver(type_debug_info_observer); - if (type_debug_info_observers_.might_have_observers() && - engine_initialized_) { + if (type_debug_info_observers_.might_have_observers() && engine_ && + engine_->IsInitialized()) { engine_->EnableDirectoryTypeDebugInfoForwarding(); } } @@ -1627,8 +1625,8 @@ TypeDebugInfoObserver* type_debug_info_observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); type_debug_info_observers_.RemoveObserver(type_debug_info_observer); - if (!type_debug_info_observers_.might_have_observers() && - engine_initialized_) { + if (!type_debug_info_observers_.might_have_observers() && engine_ && + engine_->IsInitialized()) { engine_->DisableDirectoryTypeDebugInfoForwarding(); } } @@ -1701,7 +1699,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // If the engine isn't initialized yet, then there are no nodes to return. - if (!engine_initialized_) { + if (!engine_ || !engine_->IsInitialized()) { callback.Run(std::make_unique<base::ListValue>()); return; } @@ -1747,8 +1745,9 @@ void ProfileSyncService::SetInvalidationsForSessionsEnabled(bool enabled) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (engine_initialized_) + if (engine_ && engine_->IsInitialized()) { engine_->SetInvalidationsForSessionsEnabled(enabled); + } } base::WeakPtr<JsController> ProfileSyncService::GetJsController() { @@ -1784,7 +1783,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // If we haven't initialized yet, don't configure the DTM as it could cause // association to start before a Directory has even been created. - if (engine_initialized_) { + if (engine_ && engine_->IsInitialized()) { DCHECK(engine_); // Don't configure datatypes if the setup UI is still on the screen - this // is to help multi-screen setting UIs (like iOS) where they don't want to @@ -1857,10 +1856,9 @@ void ProfileSyncService::FlushDirectory() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // engine_initialized_ implies engine_ isn't null and the manager exists. - // If sync is not initialized yet, we fail silently. - if (engine_initialized_) + if (engine_ && engine_->IsInitialized()) { engine_->FlushDirectory(); + } } bool ProfileSyncService::IsPassphrasePrompted() const { @@ -1883,8 +1881,9 @@ } void ProfileSyncService::RemoveClientFromServer() const { - if (!engine_initialized_) + if (!engine_ || !engine_->IsInitialized()) { return; + } const std::string cache_guid = sync_prefs_.GetCacheGuid(); DCHECK(!cache_guid.empty()); std::string birthday; @@ -1961,7 +1960,7 @@ --outstanding_setup_in_progress_handles_; - if (engine_initialized_) { + if (engine_ && engine_->IsInitialized()) { // The user closed a setup UI, and will expect their changes to actually // take effect now. So we reconfigure here even if another setup UI happens // to be open right now.
diff --git a/components/sync/driver/profile_sync_service.h b/components/sync/driver/profile_sync_service.h index 08ca40e..b978189 100644 --- a/components/sync/driver/profile_sync_service.h +++ b/components/sync/driver/profile_sync_service.h
@@ -433,9 +433,6 @@ // is decremented back to zero, Sync setup is marked no longer in progress. int outstanding_setup_in_progress_handles_ = 0; - // Whether the SyncEngine has been initialized. - bool engine_initialized_; - // Set when sync receives STOP_SYNC_FOR_DISABLED_ACCOUNT error from server. // Prevents ProfileSyncService from starting engine till browser restarted // or user signed out.
diff --git a/components/sync/driver/profile_sync_service_startup_unittest.cc b/components/sync/driver/profile_sync_service_startup_unittest.cc index c03af92..b3f1b85 100644 --- a/components/sync/driver/profile_sync_service_startup_unittest.cc +++ b/components/sync/driver/profile_sync_service_startup_unittest.cc
@@ -629,6 +629,7 @@ // Once the engine calls back and says it's initialized, we're just waiting // for the user to finish the initial configuration (choosing data types etc.) // before actually syncing data. + ON_CALL(*sync_engine, IsInitialized()).WillByDefault(Return(true)); sync_service()->OnEngineInitialized(ModelTypeSet(), WeakHandle<JsBackend>(), WeakHandle<DataTypeDebugInfoListener>(), "test-guid", "test-session-name", @@ -708,6 +709,7 @@ // Once the engine calls back and says it's initialized, the DataTypeManager // will get configured, since initial setup is already done. EXPECT_CALL(*data_type_manager, Configure(_, _)); + ON_CALL(*sync_engine, IsInitialized()).WillByDefault(Return(true)); sync_service()->OnEngineInitialized(ModelTypeSet(), WeakHandle<JsBackend>(), WeakHandle<DataTypeDebugInfoListener>(), "test-guid", "test-session-name",
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc index a9eb7b7..23399d5d 100644 --- a/components/sync/driver/sync_driver_switches.cc +++ b/components/sync/driver/sync_driver_switches.cc
@@ -92,15 +92,6 @@ const base::Feature kSyncSupportSecondaryAccount{ "SyncSupportSecondaryAccount", base::FEATURE_DISABLED_BY_DEFAULT}; -// Gates registration and construction of user events machinery. Enabled by -// default as each use case should have their own gating feature as well. -const base::Feature kSyncUserEvents{"SyncUserEvents", - base::FEATURE_ENABLED_BY_DEFAULT}; - -// Gates emission of FieldTrial events. -const base::Feature kSyncUserFieldTrialEvents{"SyncUserFieldTrialEvents", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Gates registration for user language detection events. const base::Feature kSyncUserLanguageDetectionEvents{ "SyncUserLanguageDetectionEvents", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/sync/driver/sync_driver_switches.h b/components/sync/driver/sync_driver_switches.h index 425e5c2..48d2df3 100644 --- a/components/sync/driver/sync_driver_switches.h +++ b/components/sync/driver/sync_driver_switches.h
@@ -44,8 +44,6 @@ extern const base::Feature kSyncPseudoUSSThemes; extern const base::Feature kSyncSendTabToSelf; extern const base::Feature kSyncSupportSecondaryAccount; -extern const base::Feature kSyncUserEvents; -extern const base::Feature kSyncUserFieldTrialEvents; extern const base::Feature kSyncUserLanguageDetectionEvents; extern const base::Feature kSyncUserTranslationEvents; extern const base::Feature kSyncUSSBookmarks;
diff --git a/components/sync/engine/fake_sync_engine.cc b/components/sync/engine/fake_sync_engine.cc index 0ae2598..9124c2a 100644 --- a/components/sync/engine/fake_sync_engine.cc +++ b/components/sync/engine/fake_sync_engine.cc
@@ -17,14 +17,20 @@ } // namespace -FakeSyncEngine::FakeSyncEngine() : fail_initial_download_(false) {} +FakeSyncEngine::FakeSyncEngine() {} FakeSyncEngine::~FakeSyncEngine() {} void FakeSyncEngine::Initialize(InitParams params) { - params.host->OnEngineInitialized( - ModelTypeSet(), WeakHandle<JsBackend>(), - WeakHandle<DataTypeDebugInfoListener>(), kTestCacheGuid, kTestSessionName, - kTestBirthday, /*bag_of_chips=*/"", !fail_initial_download_); + bool success = !fail_initial_download_; + initialized_ = success; + params.host->OnEngineInitialized(ModelTypeSet(), WeakHandle<JsBackend>(), + WeakHandle<DataTypeDebugInfoListener>(), + kTestCacheGuid, kTestSessionName, + kTestBirthday, /*bag_of_chips=*/"", success); +} + +bool FakeSyncEngine::IsInitialized() const { + return initialized_; } void FakeSyncEngine::TriggerRefresh(const ModelTypeSet& types) {}
diff --git a/components/sync/engine/fake_sync_engine.h b/components/sync/engine/fake_sync_engine.h index 74ce1f1..5564a465 100644 --- a/components/sync/engine/fake_sync_engine.h +++ b/components/sync/engine/fake_sync_engine.h
@@ -29,6 +29,8 @@ // Immediately calls params.host->OnEngineInitialized. void Initialize(InitParams params) override; + bool IsInitialized() const override; + void TriggerRefresh(const ModelTypeSet& types) override; void UpdateCredentials(const SyncCredentials& credentials) override; @@ -93,7 +95,8 @@ void set_fail_initial_download(bool should_fail); private: - bool fail_initial_download_; + bool fail_initial_download_ = false; + bool initialized_ = false; }; } // namespace syncer
diff --git a/components/sync/engine/mock_sync_engine.h b/components/sync/engine/mock_sync_engine.h index db413c0..e8ac6d66 100644 --- a/components/sync/engine/mock_sync_engine.h +++ b/components/sync/engine/mock_sync_engine.h
@@ -37,6 +37,7 @@ // SyncEngine: MOCK_METHOD1(Initialize, void(InitParams)); + MOCK_CONST_METHOD0(IsInitialized, bool()); MOCK_METHOD1(TriggerRefresh, void(const ModelTypeSet&)); MOCK_METHOD1(UpdateCredentials, void(const SyncCredentials&)); MOCK_METHOD0(InvalidateCredentials, void());
diff --git a/components/sync/engine/sync_engine.h b/components/sync/engine/sync_engine.h index dbd2153e..b7867a4 100644 --- a/components/sync/engine/sync_engine.h +++ b/components/sync/engine/sync_engine.h
@@ -101,6 +101,9 @@ // engine instance. May be null. virtual void Initialize(InitParams params) = 0; + // Returns whether the asynchronous initialization process has finished. + virtual bool IsInitialized() const = 0; + // Inform the engine to trigger a sync cycle for |types|. virtual void TriggerRefresh(const ModelTypeSet& types) = 0;
diff --git a/components/sync/engine_impl/loopback_server/loopback_connection_manager.cc b/components/sync/engine_impl/loopback_server/loopback_connection_manager.cc index adb88f38..1ed07ed 100644 --- a/components/sync/engine_impl/loopback_server/loopback_connection_manager.cc +++ b/components/sync/engine_impl/loopback_server/loopback_connection_manager.cc
@@ -19,7 +19,7 @@ bool LoopbackConnectionManager::PostBufferToPath( PostBufferParams* params, const std::string& path, - const std::string& auth_token) { + const std::string& access_token) { params->response.http_status_code = loopback_server_.HandleCommand(params->buffer_in, ¶ms->buffer_out); DCHECK_GE(params->response.http_status_code, 0);
diff --git a/components/sync/engine_impl/loopback_server/loopback_connection_manager.h b/components/sync/engine_impl/loopback_server/loopback_connection_manager.h index 6c8b7fa..edccb010 100644 --- a/components/sync/engine_impl/loopback_server/loopback_connection_manager.h +++ b/components/sync/engine_impl/loopback_server/loopback_connection_manager.h
@@ -26,7 +26,7 @@ // Overridden ServerConnectionManager functions. bool PostBufferToPath(PostBufferParams* params, const std::string& path, - const std::string& auth_token) override; + const std::string& access_token) override; // The loopback server that will handle the requests locally. LoopbackServer loopback_server_;
diff --git a/components/sync/engine_impl/net/server_connection_manager.cc b/components/sync/engine_impl/net/server_connection_manager.cc index 8deaf2f..c056d25 100644 --- a/components/sync/engine_impl/net/server_connection_manager.cc +++ b/components/sync/engine_impl/net/server_connection_manager.cc
@@ -152,17 +152,17 @@ return MakeConnection(); } -bool ServerConnectionManager::SetAuthToken(const std::string& auth_token) { +bool ServerConnectionManager::SetAccessToken(const std::string& access_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!auth_token.empty()) { - auth_token_.assign(auth_token); + if (!access_token.empty()) { + access_token_.assign(access_token); return true; } - auth_token_.clear(); + access_token_.clear(); - // The auth token could be non-empty in cases like server outage/bug. E.g. + // The access token could be non-empty in cases like server outage/bug. E.g. // token returned by first request is considered invalid by sync server and // because of token server's caching policy, etc, same token is returned on // second request. Need to notify sync frontend again to request new token, @@ -172,8 +172,8 @@ return false; } -void ServerConnectionManager::ClearAuthToken() { - auth_token_.clear(); +void ServerConnectionManager::ClearAccessToken() { + access_token_.clear(); } void ServerConnectionManager::SetServerStatus( @@ -199,7 +199,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); string path = MakeSyncServerPath(proto_sync_path(), MakeSyncQueryString(client_id_)); - bool result = PostBufferToPath(params, path, auth_token()); + bool result = PostBufferToPath(params, path, access_token_); SetServerStatus(params->response.server_status); net_error_code_ = params->response.net_error_code; return result; @@ -207,14 +207,14 @@ bool ServerConnectionManager::PostBufferToPath(PostBufferParams* params, const string& path, - const string& auth_token) { + const string& access_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (auth_token.empty()) { + if (access_token.empty()) { params->response.server_status = HttpResponse::SYNC_AUTH_ERROR; // Print a log to distinguish this "known failure" from others. DVLOG(1) << "ServerConnectionManager forcing SYNC_AUTH_ERROR due to missing" - " auth token"; + " access token"; return false; } @@ -226,11 +226,11 @@ // Note that |post| may be aborted by now, which will just cause Init to fail // with CONNECTION_UNAVAILABLE. - bool ok = connection->Init(path.c_str(), auth_token, params->buffer_in, + bool ok = connection->Init(path.c_str(), access_token, params->buffer_in, ¶ms->response); if (params->response.server_status == HttpResponse::SYNC_AUTH_ERROR) { - auth_token_.clear(); + access_token_.clear(); } if (!ok || net::HTTP_OK != params->response.http_status_code)
diff --git a/components/sync/engine_impl/net/server_connection_manager.h b/components/sync/engine_impl/net/server_connection_manager.h index 18b4905..b56a72c 100644 --- a/components/sync/engine_impl/net/server_connection_manager.h +++ b/components/sync/engine_impl/net/server_connection_manager.h
@@ -111,7 +111,7 @@ // Called to initialize and perform an HTTP POST. virtual bool Init(const char* path, - const std::string& auth_token, + const std::string& access_token, const std::string& payload, HttpResponse* response) = 0; @@ -149,7 +149,7 @@ virtual ~ServerConnectionManager(); // POSTS buffer_in and reads a response into buffer_out. Uses our currently - // set auth token in our headers. + // set access token in our headers. // // Returns true if executed successfully. virtual bool PostBufferWithCachedAuth(PostBufferParams* params); @@ -179,17 +179,12 @@ client_id_.assign(client_id); } - // Sets a new auth token. If |auth_token| is empty, the current token is + // Sets a new access token. If |access_token| is empty, the current token is // invalidated and cleared. Returns false if the server is in authentication // error state. - bool SetAuthToken(const std::string& auth_token); + bool SetAccessToken(const std::string& access_token); - bool HasInvalidAuthToken() { return auth_token_.empty(); } - - const std::string auth_token() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return auth_token_; - } + bool HasInvalidAccessToken() { return access_token_.empty(); } protected: inline std::string proto_sync_path() const { return proto_sync_path_; } @@ -202,9 +197,9 @@ // Internal PostBuffer base function. virtual bool PostBufferToPath(PostBufferParams*, const std::string& path, - const std::string& auth_token); + const std::string& access_token); - void ClearAuthToken(); + void ClearAccessToken(); // Helper to check terminated flags and build a Connection object. If this // ServerConnectionManager has been terminated, this will return null. @@ -228,8 +223,8 @@ // The paths we post to. std::string proto_sync_path_; - // The auth token to use in authenticated requests. - std::string auth_token_; + // The access token to use in authenticated requests. + std::string access_token_; base::ObserverList<ServerConnectionEventListener>::Unchecked listeners_;
diff --git a/components/sync/engine_impl/net/sync_server_connection_manager.cc b/components/sync/engine_impl/net/sync_server_connection_manager.cc index 07fe6b7..64fceb64 100644 --- a/components/sync/engine_impl/net/sync_server_connection_manager.cc +++ b/components/sync/engine_impl/net/sync_server_connection_manager.cc
@@ -33,7 +33,7 @@ } bool SyncBridgedConnection::Init(const char* path, - const std::string& auth_token, + const std::string& access_token, const std::string& payload, HttpResponse* response) { std::string sync_server; @@ -45,9 +45,9 @@ HttpPostProviderInterface* http = post_provider_; http->SetURL(connection_url.c_str(), sync_server_port); - if (!auth_token.empty()) { + if (!access_token.empty()) { std::string headers; - headers = "Authorization: Bearer " + auth_token; + headers = "Authorization: Bearer " + access_token; http->SetExtraRequestHeaders(headers.c_str()); }
diff --git a/components/sync/engine_impl/net/sync_server_connection_manager.h b/components/sync/engine_impl/net/sync_server_connection_manager.h index 1848b67..07cbdce 100644 --- a/components/sync/engine_impl/net/sync_server_connection_manager.h +++ b/components/sync/engine_impl/net/sync_server_connection_manager.h
@@ -30,7 +30,7 @@ ~SyncBridgedConnection() override; bool Init(const char* path, - const std::string& auth_token, + const std::string& access_token, const std::string& payload, HttpResponse* response) override;
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc index 174b8f19..6649ffb 100644 --- a/components/sync/engine_impl/sync_manager_impl.cc +++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -464,10 +464,6 @@ return scheduler_.get(); } -bool SyncManagerImpl::GetHasInvalidAuthTokenForTest() const { - return connection_manager_->HasInvalidAuthToken(); -} - bool SyncManagerImpl::OpenDirectory(const InitArgs* args) { DCHECK(!initialized_) << "Should only happen once"; @@ -538,7 +534,7 @@ cycle_context_->set_account_name(credentials.email); observing_network_connectivity_changes_ = true; - if (!connection_manager_->SetAuthToken(credentials.access_token)) + if (!connection_manager_->SetAccessToken(credentials.access_token)) return; // Auth token is known to be invalid, so exit early. scheduler_->OnCredentialsUpdated(); @@ -548,7 +544,7 @@ void SyncManagerImpl::InvalidateCredentials() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - connection_manager_->SetAuthToken(std::string()); + connection_manager_->SetAccessToken(std::string()); } void SyncManagerImpl::AddObserver(SyncManager::Observer* observer) {
diff --git a/components/sync/engine_impl/sync_manager_impl.h b/components/sync/engine_impl/sync_manager_impl.h index 5462d2c6..10c1a95 100644 --- a/components/sync/engine_impl/sync_manager_impl.h +++ b/components/sync/engine_impl/sync_manager_impl.h
@@ -173,8 +173,6 @@ const SyncScheduler* scheduler() const; - bool GetHasInvalidAuthTokenForTest() const; - protected: // Helper functions. Virtual for testing. virtual void NotifyInitializationSuccess();
diff --git a/components/sync/engine_impl/sync_scheduler_impl.cc b/components/sync/engine_impl/sync_scheduler_impl.cc index 856cf4be..ec9b987 100644 --- a/components/sync/engine_impl/sync_scheduler_impl.cc +++ b/components/sync/engine_impl/sync_scheduler_impl.cc
@@ -155,7 +155,7 @@ // // 1. We're in exponential backoff. // 2. We're silenced / throttled. - // 3. A nudge was saved previously due to not having a valid auth token. + // 3. A nudge was saved previously due to not having a valid access token. // 4. A nudge was scheduled + saved while in configuration mode. // // In all cases except (2), we want to retry contacting the server. We @@ -288,8 +288,8 @@ } if (!ignore_auth_credentials_ && - cycle_context_->connection_manager()->HasInvalidAuthToken()) { - SDVLOG(1) << "Unable to run a job because we have no valid auth token."; + cycle_context_->connection_manager()->HasInvalidAccessToken()) { + SDVLOG(1) << "Unable to run a job because we have no valid access token."; return false; } @@ -689,7 +689,7 @@ // We must be in an error state. Transitioning out of each of these // error states should trigger a canary job. DCHECK(IsGlobalThrottle() || IsGlobalBackoff() || - cycle_context_->connection_manager()->HasInvalidAuthToken()); + cycle_context_->connection_manager()->HasInvalidAccessToken()); } RestartWaiting();
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc index ccb16ce..bf64b2cd 100644 --- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc +++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -514,12 +514,12 @@ ASSERT_EQ(0, ready_counter.times_called()); } -// Verify that in the absence of valid auth token the command will fail. -TEST_F(SyncSchedulerImplTest, ConfigNoAuthToken) { +// Verify that in the absence of valid access token the command will fail. +TEST_F(SyncSchedulerImplTest, ConfigNoAccessToken) { SyncShareTimes times; const ModelTypeSet model_types(THEMES); - connection()->ResetAuthToken(); + connection()->ResetAccessToken(); StartSyncConfiguration(); @@ -532,14 +532,14 @@ ASSERT_EQ(0, ready_counter.times_called()); } -// Verify that in the absence of valid auth token the command will pass if local -// sync backend is used. -TEST_F(SyncSchedulerImplTest, ConfigNoAuthTokenLocalSync) { +// Verify that in the absence of valid access token the command will pass if +// local sync backend is used. +TEST_F(SyncSchedulerImplTest, ConfigNoAccessTokenLocalSync) { SyncShareTimes times; const ModelTypeSet model_types(THEMES); NewSchedulerForLocalBackend(); - connection()->ResetAuthToken(); + connection()->ResetAccessToken(); EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _)) .WillOnce(DoAll(Invoke(test_util::SimulateConfigureSuccess),
diff --git a/components/sync/engine_impl/uss_migrator.cc b/components/sync/engine_impl/uss_migrator.cc index 1032285..fe8c856 100644 --- a/components/sync/engine_impl/uss_migrator.cc +++ b/components/sync/engine_impl/uss_migrator.cc
@@ -64,8 +64,6 @@ DCHECK_NE(BOOKMARKS, type); } - // It looks like there are fancy other ways to get e.g. passwords specifics - // out of Entry. Do we need to special-case them when we ship those types? entity->mutable_specifics()->CopyFrom(entry.GetServerSpecifics()); return true; }
diff --git a/components/sync/test/engine/mock_connection_manager.cc b/components/sync/test/engine/mock_connection_manager.cc index 298ac7c..f65915a 100644 --- a/components/sync/test/engine/mock_connection_manager.cc +++ b/components/sync/test/engine/mock_connection_manager.cc
@@ -27,7 +27,7 @@ namespace syncer { -static char kValidAuthToken[] = "AuthToken"; +static char kValidAccessToken[] = "AccessToken"; static char kCacheGuid[] = "kqyg7097kro6GSUod+GSg=="; MockConnectionManager::MockConnectionManager(syncable::Directory* directory, @@ -49,7 +49,7 @@ next_position_in_parent_(2), num_get_updates_requests_(0) { SetNewTimestamp(0); - SetAuthToken(kValidAuthToken); + SetAccessToken(kValidAccessToken); } MockConnectionManager::~MockConnectionManager() { @@ -72,7 +72,7 @@ bool MockConnectionManager::PostBufferToPath(PostBufferParams* params, const string& path, - const string& auth_token) { + const string& access_token) { ClientToServerMessage post; if (!post.ParseFromString(params->buffer_in)) { ADD_FAILURE(); @@ -108,15 +108,15 @@ syncable::WriteTransaction wt(FROM_HERE, syncable::UNITTEST, directory_); } - if (auth_token.empty()) { + if (access_token.empty()) { params->response.server_status = HttpResponse::SYNC_AUTH_ERROR; return false; } - if (auth_token != kValidAuthToken) { + if (access_token != kValidAccessToken) { // Simulate server-side auth failure. params->response.server_status = HttpResponse::SYNC_AUTH_ERROR; - ClearAuthToken(); + ClearAccessToken(); } if (--countdown_to_postbuffer_fail_ == 0) {
diff --git a/components/sync/test/engine/mock_connection_manager.h b/components/sync/test/engine/mock_connection_manager.h index 2ac6bbb8..6eb29b6c 100644 --- a/components/sync/test/engine/mock_connection_manager.h +++ b/components/sync/test/engine/mock_connection_manager.h
@@ -45,7 +45,7 @@ // Overridden ServerConnectionManager functions. bool PostBufferToPath(PostBufferParams*, const std::string& path, - const std::string& auth_token) override; + const std::string& access_token) override; // Control of commit response. // NOTE: Commit callback is invoked only once then reset. @@ -268,7 +268,7 @@ // Adds a new progress marker to the last update. sync_pb::DataTypeProgressMarker* AddUpdateProgressMarker(); - void ResetAuthToken() { ClearAuthToken(); } + void ResetAccessToken() { ClearAccessToken(); } private: sync_pb::SyncEntity* AddUpdateFull(syncable::Id id, @@ -375,7 +375,7 @@ // The AUTHENTICATE response we'll return for auth requests. sync_pb::AuthenticateResponse auth_response_; // What we use to determine if we should return SUCCESS or BAD_AUTH_TOKEN. - std::string valid_auth_token_; + std::string valid_access_token_; // Whether we are faking a server mandating clients to throttle requests. // Protected by |response_code_override_lock_|.
diff --git a/components/sync/user_events/trial_recorder.cc b/components/sync/user_events/trial_recorder.cc deleted file mode 100644 index e2580ff8..0000000 --- a/components/sync/user_events/trial_recorder.cc +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/sync/user_events/trial_recorder.h" - -#include <memory> -#include <set> -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/feature_list.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/field_trial_params.h" -#include "base/stl_util.h" -#include "base/time/time.h" -#include "components/sync/driver/sync_driver_switches.h" -#include "components/variations/active_field_trials.h" - -using sync_pb::UserEventSpecifics; - -namespace syncer { - -namespace { - -// A FieldTrial is recorded periodically, using this delay. Although upon chance -// an event is immediately recorded and we reset to using this delay for the -// next time. -base::TimeDelta GetFieldTrialDelay() { - return base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt( - switches::kSyncUserFieldTrialEvents, "field_trial_delay_seconds", - base::TimeDelta::FromDays(1).InSeconds())); -} - -} // namespace - -TrialRecorder::TrialRecorder(UserEventService* user_event_service) - : user_event_service_(user_event_service), - variations_(variations::CHROME_SYNC_EVENT_LOGGER, - base::BindRepeating(&TrialRecorder::OnNewVariationId, - base::Unretained(this))) { - DCHECK(user_event_service_); - RecordFieldTrials(); -} - -TrialRecorder::~TrialRecorder() {} - -void TrialRecorder::RecordFieldTrials() { - if (!base::FeatureList::IsEnabled(switches::kSyncUserFieldTrialEvents)) { - return; - } - - std::set<variations::VariationID> ids = variations_.GetIds(); - if (!ids.empty()) { - auto specifics = std::make_unique<UserEventSpecifics>(); - specifics->set_event_time_usec( - (base::Time::Now() - base::Time()).InMicroseconds()); - - for (variations::VariationID id : ids) { - DCHECK_NE(variations::EMPTY_ID, id); - specifics->mutable_field_trial_event()->add_variation_ids(id); - } - user_event_service_->RecordUserEvent(std::move(specifics)); - } - - field_trial_timer_.Start( - FROM_HERE, GetFieldTrialDelay(), - base::BindRepeating(&TrialRecorder::RecordFieldTrials, - base::Unretained(this))); -} - -void TrialRecorder::OnNewVariationId(variations::VariationID id) { - RecordFieldTrials(); -} - -} // namespace syncer
diff --git a/components/sync/user_events/trial_recorder.h b/components/sync/user_events/trial_recorder.h deleted file mode 100644 index 7461a92..0000000 --- a/components/sync/user_events/trial_recorder.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_SYNC_USER_EVENTS_TRIAL_RECORDER_H_ -#define COMPONENTS_SYNC_USER_EVENTS_TRIAL_RECORDER_H_ - -#include "base/macros.h" -#include "base/timer/timer.h" -#include "components/sync/protocol/user_event_specifics.pb.h" -#include "components/sync/user_events/user_event_service.h" -#include "components/variations/variations_associated_data.h" -#include "components/variations/variations_id_collection.h" - -namespace syncer { - -// Watches finalization of trails and records FieldTrial events through its -// UserEventService on construction, on change, and every so often. -class TrialRecorder { - public: - explicit TrialRecorder(UserEventService* user_event_service); - ~TrialRecorder(); - - private: - // Construct and record a field trial event if applicable. - void RecordFieldTrials(); - - // Simply drops the |id| param and calls RecordFieldTrials(). - void OnNewVariationId(variations::VariationID id); - - // Non-owning pointer to interface of how events are actually recorded. - UserEventService* user_event_service_; - - // Tracks all the variation ids that we we care about. - variations::VariationsIdCollection variations_; - - // Timer used to record a field trial event every given interval. - base::OneShotTimer field_trial_timer_; - - DISALLOW_COPY_AND_ASSIGN(TrialRecorder); -}; - -} // namespace syncer - -#endif // COMPONENTS_SYNC_USER_EVENTS_TRIAL_RECORDER_H_
diff --git a/components/sync/user_events/trial_recorder_unittest.cc b/components/sync/user_events/trial_recorder_unittest.cc deleted file mode 100644 index c8735ec..0000000 --- a/components/sync/user_events/trial_recorder_unittest.cc +++ /dev/null
@@ -1,162 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/sync/user_events/trial_recorder.h" - -#include <memory> -#include <set> -#include <string> - -#include "base/metrics/field_trial.h" -#include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/scoped_task_environment.h" -#include "components/sync/driver/sync_driver_switches.h" -#include "components/sync/protocol/sync.pb.h" -#include "components/sync/user_events/fake_user_event_service.h" -#include "components/variations/variations_associated_data.h" -#include "testing/gtest/include/gtest/gtest.h" - -using sync_pb::UserEventSpecifics; - -namespace syncer { - -namespace { - -const char kTrial1[] = "TrialNameOne"; -const char kTrial2[] = "TrialNameTwo"; -const char kGroup[] = "GroupName"; -const variations::VariationID kVariation1 = 111; -const variations::VariationID kVariation2 = 222; - -void VerifyEvent(std::set<variations::VariationID> expected_variations, - const UserEventSpecifics& actual) { - ASSERT_EQ( - expected_variations.size(), - static_cast<size_t>(actual.field_trial_event().variation_ids_size())); - for (int actaul_variation : actual.field_trial_event().variation_ids()) { - auto iter = expected_variations.find(actaul_variation); - if (iter == expected_variations.end()) { - FAIL() << actaul_variation; - } else { - // Remove to make sure the event doesn't contain duplicates. - expected_variations.erase(iter); - } - } -} - -void SetupAndFinalizeTrial(const std::string& trial_name, - variations::VariationID id) { - variations::AssociateGoogleVariationID(variations::CHROME_SYNC_EVENT_LOGGER, - trial_name, kGroup, id); - base::FieldTrialList::CreateFieldTrial(trial_name, kGroup); - base::FieldTrialList::FindFullName(trial_name); - base::RunLoop().RunUntilIdle(); -} - -class TrialRecorderTest : public testing::Test { - public: - TrialRecorderTest() : field_trial_list_(nullptr) {} - - ~TrialRecorderTest() override { variations::testing::ClearAllVariationIDs(); } - - FakeUserEventService* service() { return &service_; } - TrialRecorder* recorder() { return recorder_.get(); } - - void VerifyLastEvent(std::set<variations::VariationID> expected_variations) { - ASSERT_LE(1u, service()->GetRecordedUserEvents().size()); - VerifyEvent(expected_variations, - *service()->GetRecordedUserEvents().rbegin()); - } - - void InitRecorder() { - recorder_ = std::make_unique<TrialRecorder>(&service_); - } - - private: - base::test::ScopedTaskEnvironment task_environment_; - base::FieldTrialList field_trial_list_; - FakeUserEventService service_; - std::unique_ptr<TrialRecorder> recorder_; -}; - -TEST_F(TrialRecorderTest, FinalizedBeforeInit) { - SetupAndFinalizeTrial(kTrial1, kVariation1); - SetupAndFinalizeTrial(kTrial2, kVariation2); - // Should check on initialization to see if there are any trails to record. - InitRecorder(); - VerifyLastEvent({kVariation1, kVariation2}); -} - -TEST_F(TrialRecorderTest, FinalizedAfterInit) { - InitRecorder(); - SetupAndFinalizeTrial(kTrial1, kVariation1); - SetupAndFinalizeTrial(kTrial2, kVariation2); - VerifyLastEvent({kVariation1, kVariation2}); -} - -TEST_F(TrialRecorderTest, FinalizedMix) { - SetupAndFinalizeTrial(kTrial1, kVariation1); - InitRecorder(); - VerifyLastEvent({kVariation1}); - - SetupAndFinalizeTrial(kTrial2, kVariation2); - VerifyLastEvent({kVariation1, kVariation2}); -} - -TEST_F(TrialRecorderTest, WrongVariationKey) { - InitRecorder(); - variations::AssociateGoogleVariationID(variations::GOOGLE_WEB_PROPERTIES, - kTrial1, kGroup, kVariation1); - base::FieldTrialList::CreateFieldTrial(kTrial1, kGroup); - base::FieldTrialList::FindFullName(kTrial1); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(0u, service()->GetRecordedUserEvents().size()); -} - -TEST_F(TrialRecorderTest, NoVariation) { - InitRecorder(); - base::FieldTrialList::CreateFieldTrial(kTrial1, kGroup); - base::FieldTrialList::FindFullName(kTrial1); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(0u, service()->GetRecordedUserEvents().size()); -} - -TEST_F(TrialRecorderTest, FieldTrialFeatureDisabled) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature( - switches::kSyncUserFieldTrialEvents); - InitRecorder(); - SetupAndFinalizeTrial(kTrial1, kVariation1); - - EXPECT_EQ(0u, service()->GetRecordedUserEvents().size()); -} - -TEST_F(TrialRecorderTest, FieldTrialTimer) { - SetupAndFinalizeTrial(kTrial2, kVariation2); - - { - // Start with 0 delay, which should mean we post immediately to record. - // Need to be not call any methods that might invoke RunUntilIdle() while we - // have a delay of 0, like SetupAndFinalizeTrial(). - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - switches::kSyncUserFieldTrialEvents, - {{"field_trial_delay_seconds", "0"}}); - InitRecorder(); - EXPECT_EQ(1u, service()->GetRecordedUserEvents().size()); - } - - // Now that |scoped_feature_list| is gone, we should reset to default, - // otherwise our RunUntilIdle() would infinitively loop with a delay of 0. - base::RunLoop().RunUntilIdle(); - // Should have picked up exactly one more event. - EXPECT_EQ(2u, service()->GetRecordedUserEvents().size()); -} - -} // namespace - -} // namespace syncer
diff --git a/components/sync/user_events/user_event_service_impl.cc b/components/sync/user_events/user_event_service_impl.cc index be026b2..db28eeb 100644 --- a/components/sync/user_events/user_event_service_impl.cc +++ b/components/sync/user_events/user_event_service_impl.cc
@@ -6,7 +6,6 @@ #include <utility> -#include "base/feature_list.h" #include "base/rand_util.h" #include "base/stl_util.h" #include "base/time/time.h" @@ -66,8 +65,7 @@ std::unique_ptr<UserEventSyncBridge> bridge) : sync_service_(sync_service), bridge_(std::move(bridge)), - session_id_(base::RandUint64()), - trial_recorder_(this) { + session_id_(base::RandUint64()) { DCHECK(bridge_); DCHECK(sync_service_); } @@ -97,8 +95,7 @@ // static bool UserEventServiceImpl::MightRecordEvents(bool off_the_record, SyncService* sync_service) { - return !off_the_record && sync_service && - base::FeatureList::IsEnabled(switches::kSyncUserEvents); + return !off_the_record && sync_service; } bool UserEventServiceImpl::CanRecordHistory() {
diff --git a/components/sync/user_events/user_event_service_impl.h b/components/sync/user_events/user_event_service_impl.h index a1aa9e1..8c421c846 100644 --- a/components/sync/user_events/user_event_service_impl.h +++ b/components/sync/user_events/user_event_service_impl.h
@@ -12,7 +12,6 @@ #include "base/memory/weak_ptr.h" #include "components/keyed_service/core/keyed_service.h" #include "components/sync/protocol/user_event_specifics.pb.h" -#include "components/sync/user_events/trial_recorder.h" #include "components/sync/user_events/user_event_service.h" namespace syncer { @@ -57,9 +56,6 @@ // which events came from the same session. uint64_t session_id_; - // Tracks and records field trails when appropriate. - TrialRecorder trial_recorder_; - DISALLOW_COPY_AND_ASSIGN(UserEventServiceImpl); };
diff --git a/components/sync/user_events/user_event_service_impl_unittest.cc b/components/sync/user_events/user_event_service_impl_unittest.cc index b78f650a99..7b86abd 100644 --- a/components/sync/user_events/user_event_service_impl_unittest.cc +++ b/components/sync/user_events/user_event_service_impl_unittest.cc
@@ -7,8 +7,6 @@ #include <utility> #include <vector> -#include "base/metrics/field_trial.h" -#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "components/sync/base/model_type.h" #include "components/sync/driver/sync_driver_switches.h" @@ -20,7 +18,6 @@ #include "components/variations/variations_associated_data.h" #include "testing/gtest/include/gtest/gtest.h" -using base::test::ScopedFeatureList; using sync_pb::UserEventSpecifics; using testing::_; @@ -57,13 +54,6 @@ return specifics; } -MATCHER_P(HasFieldTrialVariationIds, expected_variation_id, "") { - const UserEventSpecifics& specifics = arg->specifics.user_event(); - return specifics.field_trial_event().variation_ids_size() == 1 && - specifics.field_trial_event().variation_ids(0) == - expected_variation_id; -} - class TestGlobalIdMapper : public GlobalIdMapper { void AddGlobalIdChangeObserver(GlobalIdChange callback) override {} int64_t GetLatestGlobalId(int64_t global_id) override { return global_id; } @@ -71,7 +61,7 @@ class UserEventServiceImplTest : public testing::Test { protected: - UserEventServiceImplTest() : field_trial_list_(nullptr) { + UserEventServiceImplTest() { sync_service_.SetPreferredDataTypes( {HISTORY_DELETE_DIRECTIVES, USER_EVENTS}); ON_CALL(mock_processor_, IsTrackingMetadata()) @@ -91,15 +81,12 @@ private: base::test::ScopedTaskEnvironment task_environment_; - base::FieldTrialList field_trial_list_; syncer::TestSyncService sync_service_; testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_; TestGlobalIdMapper mapper_; - - base::test::ScopedFeatureList feature_list_; }; -TEST_F(UserEventServiceImplTest, MightRecordEventsFeatureEnabled) { +TEST_F(UserEventServiceImplTest, MightRecordEvents) { // All conditions are met, might record. EXPECT_TRUE(UserEventServiceImpl::MightRecordEvents(false, sync_service())); // No sync service, will not record. @@ -108,13 +95,6 @@ EXPECT_FALSE(UserEventServiceImpl::MightRecordEvents(true, sync_service())); } -TEST_F(UserEventServiceImplTest, MightRecordEventsFeatureDisabled) { - // Will not record because the default on feature is overridden. - ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature(switches::kSyncUserEvents); - EXPECT_FALSE(UserEventServiceImpl::MightRecordEvents(false, sync_service())); -} - TEST_F(UserEventServiceImplTest, ShouldRecord) { UserEventServiceImpl service(sync_service(), MakeBridge()); EXPECT_CALL(*mock_processor(), Put(_, _, _)); @@ -205,16 +185,6 @@ EXPECT_NE(put_session_ids[0], put_session_ids[1]); } -TEST_F(UserEventServiceImplTest, FieldTrial) { - variations::AssociateGoogleVariationID(variations::CHROME_SYNC_EVENT_LOGGER, - "trial", "group", 123); - base::FieldTrialList::CreateFieldTrial("trial", "group"); - base::FieldTrialList::FindFullName("trial"); - - EXPECT_CALL(*mock_processor(), Put(_, HasFieldTrialVariationIds(123u), _)); - UserEventServiceImpl service(sync_service(), MakeBridge()); -} - TEST_F(UserEventServiceImplTest, ShouldNotRecordWhenEventsDatatypeIsDisabled) { sync_service()->SetPreferredDataTypes({HISTORY_DELETE_DIRECTIVES}); UserEventServiceImpl service(sync_service(), MakeBridge());
diff --git a/components/translate/translate_internals/translate_internals.html b/components/translate/translate_internals/translate_internals.html index e4d4ceab..061cbcd 100644 --- a/components/translate/translate_internals/translate_internals.html +++ b/components/translate/translate_internals/translate_internals.html
@@ -11,6 +11,10 @@ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> <link rel="stylesheet" href="chrome://resources/css/tabs.css"> <link rel="stylesheet" href="./translate_internals.css"> +<if expr="is_ios"> + <!-- TODO(crbug.com/487000): Remove this once injected by web. --> + <script src="chrome://resources/js/ios/web_ui.js"></script> +</if> <script src="chrome://resources/js/util.js"></script> <script src="chrome://resources/js/cr.js"></script> <script src="chrome://resources/js/cr/event_target.js"></script>
diff --git a/components/update_client/protocol_parser_json.cc b/components/update_client/protocol_parser_json.cc index 09dd08f..eb022e43 100644 --- a/components/update_client/protocol_parser_json.cc +++ b/components/update_client/protocol_parser_json.cc
@@ -299,12 +299,13 @@ return false; } const auto* protocol = response_node->FindKey("protocol"); - if (!protocol || !protocol->is_string() || - protocol->GetString() != kProtocolVersion) { - ParseError( - "Missing/incorrect protocol." - "(expected '%s', found '%s')", - kProtocolVersion, protocol->GetString().c_str()); + if (!protocol || !protocol->is_string()) { + ParseError("Missing/non-string protocol."); + return false; + } + if (protocol->GetString() != kProtocolVersion) { + ParseError("Incorrect protocol. (expected '%s', found '%s')", + kProtocolVersion, protocol->GetString().c_str()); return false; }
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc index 7eb2180f..c2807a85 100644 --- a/components/variations/service/variations_service.cc +++ b/components/variations/service/variations_service.cc
@@ -924,6 +924,11 @@ pending_seed_request_.reset(); } +void VariationsService::StartRepeatedVariationsSeedFetchForTesting() { + InitResourceRequestedAllowedNotifier(); + return StartRepeatedVariationsSeedFetch(); +} + std::string VariationsService::GetStoredPermanentCountry() { const base::ListValue* list_value = local_state_->GetList(prefs::kVariationsPermanentConsistencyCountry);
diff --git a/components/variations/service/variations_service.h b/components/variations/service/variations_service.h index bc5fd826b..ebe1a83 100644 --- a/components/variations/service/variations_service.h +++ b/components/variations/service/variations_service.h
@@ -198,6 +198,9 @@ // Cancels the currently pending fetch request. void CancelCurrentRequestForTesting(); + // Exposes StartRepeatedVariationsSeedFetch for testing. + void StartRepeatedVariationsSeedFetchForTesting(); + protected: // Starts the fetching process once, where |OnURLFetchComplete| is called with // the response. This calls DoFetchToURL with the set url.
diff --git a/components/variations/service/variations_service_unittest.cc b/components/variations/service/variations_service_unittest.cc index 0eb1a64..b7cc43fa 100644 --- a/components/variations/service/variations_service_unittest.cc +++ b/components/variations/service/variations_service_unittest.cc
@@ -1040,6 +1040,38 @@ net::ERR_FAILED, 1); } +TEST_F(VariationsServiceTest, + VariationsServiceStartsRequestOnNetworkChange) { + // Verifies VariationsService does a request when network status changes from + // none to connected. This is a regression test for https://crbug.com/826930. + VariationsService::EnableFetchForTesting(); + network_tracker_->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); + TestVariationsService service( + std::make_unique<web_resource::TestRequestAllowedNotifier>( + &prefs_, network_tracker_), + &prefs_, GetMetricsStateManager(), true); + service.set_intercepts_fetch(false); + service.CancelCurrentRequestForTesting(); + base::RunLoop().RunUntilIdle(); + // Simulate starting Chrome browser. + service.StartRepeatedVariationsSeedFetchForTesting(); + const int initial_request_count = service.request_count(); + // The variations seed can not be fetched if disconnected. So even we start + // repeated variations seed fetch (on Chrome start), no requests will be made. + EXPECT_EQ(0, initial_request_count); + + service.GetResourceRequestAllowedNotifierForTesting() + ->SetObserverRequestedForTesting(true); + network_tracker_->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_WIFI); + base::RunLoop().RunUntilIdle(); + + const int final_request_count = service.request_count(); + // The request will be made once Chrome gets online. + EXPECT_EQ(initial_request_count + 1, final_request_count); +} + // TODO(isherman): Add an integration test for saving and loading a safe seed, // once the loading functionality is implemented on the seed store.
diff --git a/components/viz/common/quads/frame_deadline.cc b/components/viz/common/quads/frame_deadline.cc index a332727..4af2eb08 100644 --- a/components/viz/common/quads/frame_deadline.cc +++ b/components/viz/common/quads/frame_deadline.cc
@@ -27,6 +27,10 @@ return frame_start_time_ + deadline_in_frames * frame_interval_; } +bool FrameDeadline::IsZero() const { + return deadline_in_frames_ == 0 && !use_default_lower_bound_deadline_; +} + std::string FrameDeadline::ToString() const { const base::TimeDelta start_time_delta = frame_start_time_ - base::TimeTicks();
diff --git a/components/viz/common/quads/frame_deadline.h b/components/viz/common/quads/frame_deadline.h index be7a80a..e980980 100644 --- a/components/viz/common/quads/frame_deadline.h +++ b/components/viz/common/quads/frame_deadline.h
@@ -68,6 +68,8 @@ return use_default_lower_bound_deadline_; } + bool IsZero() const; + std::string ToString() const; private:
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc index cd0e3c1..89cbf1a 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -141,6 +141,7 @@ } if (format_changed) { + frame_pool_.ClearFrameMarking(); RefreshEntireSourceSoon(); } } @@ -297,7 +298,7 @@ void FrameSinkVideoCapturerImpl::RefreshEntireSourceSoon() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - dirty_rect_ = kMaxRect; + InvalidateEntireSource(); RefreshSoon(); } @@ -327,11 +328,11 @@ } if (source_size != oracle_->source_size()) { oracle_->SetSourceSize(source_size); - dirty_rect_ = kMaxRect; + InvalidateEntireSource(); } - MaybeCaptureFrame(VideoCaptureOracle::kRefreshRequest, - gfx::Rect(oracle_->source_size()), clock_->NowTicks(), + MaybeCaptureFrame(VideoCaptureOracle::kRefreshRequest, gfx::Rect(), + clock_->NowTicks(), *resolved_target_->GetLastActivatedFrameMetadata()); } @@ -350,7 +351,7 @@ InvalidateRect(damage_rect); } else { oracle_->SetSourceSize(frame_size); - dirty_rect_ = kMaxRect; + InvalidateEntireSource(); } MaybeCaptureFrame(VideoCaptureOracle::kCompositorUpdate, damage_rect, @@ -369,6 +370,14 @@ gfx::Rect positive_rect = rect; positive_rect.Intersect(kMaxRect); dirty_rect_.Union(positive_rect); + content_version_++; +} + +void FrameSinkVideoCapturerImpl::InvalidateEntireSource() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + dirty_rect_ = kMaxRect; + content_version_++; } void FrameSinkVideoCapturerImpl::OnOverlayConnectionLost( @@ -431,27 +440,19 @@ return; } - // Reserve a buffer from the pool for the next frame. Optimization: If there - // are no changes in the source that need to be captured AND there are no - // captures currently in-flight, attempt to resurrect the last frame from the - // pool (and there is no need to capture anything new into the frame). + // Reserve a buffer from the pool for the next frame. const OracleFrameNumber oracle_frame_number = oracle_->next_frame_number(); const gfx::Size capture_size = AdjustSizeForPixelFormat(oracle_->capture_size()); + const bool can_resurrect_content = + content_version_in_marked_frame_ == content_version_ && + frame_pool_.HasMarkedFrameWithSize(capture_size); scoped_refptr<VideoFrame> frame; - bool using_resurrected_frame = - dirty_rect_.IsEmpty() && - next_capture_frame_number_ == next_delivery_frame_number_; - if (using_resurrected_frame) { - frame = frame_pool_.ResurrectLastVideoFrame(pixel_format_, capture_size); - // If the resurrection failed, promote to a full frame capture. - if (!frame) { - TRACE_EVENT_INSTANT0("gpu.capture", "ResurrectionFailed", - TRACE_EVENT_SCOPE_THREAD); - using_resurrected_frame = false; - frame = frame_pool_.ReserveVideoFrame(pixel_format_, capture_size); - } + if (can_resurrect_content) { + TRACE_EVENT_INSTANT0("gpu.capture", "UsingResurrectedFrame", + TRACE_EVENT_SCOPE_THREAD); + frame = frame_pool_.ResurrectOrDuplicateContentFromMarkedFrame(); } else { frame = frame_pool_.ReserveVideoFrame(pixel_format_, capture_size); } @@ -564,16 +565,16 @@ frame->set_color_space(gfx::ColorSpace::CreateSRGB()); } dirty_rect_ = gfx::Rect(); - DidCaptureFrame(capture_frame_number, oracle_frame_number, gfx::Rect(), - std::move(frame)); + OnFrameReadyForDelivery(capture_frame_number, oracle_frame_number, + gfx::Rect(), std::move(frame)); return; } // If the frame is a resurrected one, just deliver it since it already // contains the most up-to-date capture of the source content. - if (using_resurrected_frame) { - DidCaptureFrame(capture_frame_number, oracle_frame_number, content_rect, - std::move(frame)); + if (can_resurrect_content) { + OnFrameReadyForDelivery(capture_frame_number, oracle_frame_number, + content_rect, std::move(frame)); return; } @@ -584,7 +585,7 @@ : CopyOutputRequest::ResultFormat::RGBA_BITMAP, base::BindOnce(&FrameSinkVideoCapturerImpl::DidCopyFrame, capture_weak_factory_.GetWeakPtr(), capture_frame_number, - oracle_frame_number, content_rect, + oracle_frame_number, content_version_, content_rect, VideoCaptureOverlay::MakeCombinedRenderer( GetOverlaysInOrder(), content_rect, frame->format()), std::move(frame)))); @@ -599,16 +600,7 @@ request->set_result_selection(gfx::Rect(content_rect.size())); // Clear the |dirty_rect_|, to indicate all changes at the source are now - // being captured. This will also enable the "frame resurrection" optimization - // in future calls to this method. In other words, while the source content - // remains unchanged, there is no need to make any more CopyOutputRequests. - // - // Note that some optimistic assumptions are being made here: 1) that this - // |request| will succeed and it's image data successfully transferred to the - // VideoFrame; and 2) that delivery of the VideoFrame to the consumer will - // succeed. If, later in the pipeline, either of these assumptions is - // violated, the |dirty_rect_| will be changed to indicate that there might - // still be source changes requiring capture. See MaybeDeliverFrame(). + // being captured. dirty_rect_ = gfx::Rect(); resolved_target_->RequestCopyOfOutput(LocalSurfaceId(), std::move(request)); @@ -617,6 +609,7 @@ void FrameSinkVideoCapturerImpl::DidCopyFrame( int64_t capture_frame_number, OracleFrameNumber oracle_frame_number, + int64_t content_version, const gfx::Rect& content_rect, VideoCaptureOverlay::OnceRenderer overlay_renderer, scoped_refptr<VideoFrame> frame, @@ -680,13 +673,18 @@ media::LetterboxVideoFrame( frame.get(), gfx::Rect(content_rect.origin(), AdjustSizeForPixelFormat(result->size()))); + + if (content_version > content_version_in_marked_frame_) { + frame_pool_.MarkFrame(*frame); + content_version_in_marked_frame_ = content_version; + } } - DidCaptureFrame(capture_frame_number, oracle_frame_number, content_rect, - std::move(frame)); + OnFrameReadyForDelivery(capture_frame_number, oracle_frame_number, + content_rect, std::move(frame)); } -void FrameSinkVideoCapturerImpl::DidCaptureFrame( +void FrameSinkVideoCapturerImpl::OnFrameReadyForDelivery( int64_t capture_frame_number, OracleFrameNumber oracle_frame_number, const gfx::Rect& content_rect, @@ -733,12 +731,6 @@ TRACE_EVENT_ASYNC_END1("gpu.capture", "Capture", oracle_frame_number, "success", false); - // Mark the whole source as dirty, since this frame may have contained - // updated content that will not be delivered. See the comment at the end of - // MaybeCaptureFrame() regarding "optimistic assumptions" for further - // discussion. - dirty_rect_ = kMaxRect; - ScheduleRefreshFrame(); return; }
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h index 3c5ddc07..b35bf1e 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -174,6 +174,8 @@ void InvalidateRect(const gfx::Rect& rect) final; void OnOverlayConnectionLost(VideoCaptureOverlay* overlay) final; + void InvalidateEntireSource(); + // Returns a list of the overlays in rendering order. std::vector<VideoCaptureOverlay*> GetOverlaysInOrder() const; @@ -189,6 +191,7 @@ // |content_rect| region of a [possibly letterboxed] video |frame|. void DidCopyFrame(int64_t capture_frame_number, OracleFrameNumber oracle_frame_number, + int64_t content_version, const gfx::Rect& content_rect, VideoCaptureOverlay::OnceRenderer overlay_renderer, scoped_refptr<media::VideoFrame> frame, @@ -197,10 +200,10 @@ // Places the frame in the |delivery_queue_| and calls MaybeDeliverFrame(), // one frame at a time, in-order. |frame| may be null to indicate a // completed, but unsuccessful capture. - void DidCaptureFrame(int64_t capture_frame_number, - OracleFrameNumber oracle_frame_number, - const gfx::Rect& content_rect, - scoped_refptr<media::VideoFrame> frame); + void OnFrameReadyForDelivery(int64_t capture_frame_number, + OracleFrameNumber oracle_frame_number, + const gfx::Rect& content_rect, + scoped_refptr<media::VideoFrame> frame); // Delivers a |frame| to the consumer, if the VideoCaptureOracle allows // it. |frame| can be null to indicate a completed, but unsuccessful capture. @@ -281,6 +284,12 @@ // frames in-flight at any one time. InterprocessFramePool frame_pool_; + // Increased every time the source content changes or a forced refresh is + // requested. + int64_t content_version_ = 0; + + int64_t content_version_in_marked_frame_ = -1; + // A queue of captured frames pending delivery. This queue is used to re-order // frames, if they should happen to be captured out-of-order. struct CapturedFrame {
diff --git a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc index d13824dd..2ca164c 100644 --- a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc +++ b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc
@@ -30,10 +30,6 @@ const gfx::Size& size) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Calling this method is a signal that there is no intention of resurrecting - // the last frame. - resurrectable_buffer_memory_ = nullptr; - const size_t bytes_required = VideoFrame::AllocationSize(format, size); // Look for an available buffer that's large enough. If one is found, wrap it @@ -56,6 +52,8 @@ [](const PooledBuffer& a, const PooledBuffer& b) { return a.mapping.size() < b.mapping.size(); }); + if (it->mapping.memory() == marked_frame_buffer_) + marked_frame_buffer_ = nullptr; available_buffers_.erase(it.base() - 1); // Release before allocating more. PooledBuffer reallocated = mojo::CreateReadOnlySharedMemoryRegion(bytes_required); @@ -82,33 +80,78 @@ return WrapBuffer(std::move(additional), format, size); } -scoped_refptr<VideoFrame> InterprocessFramePool::ResurrectLastVideoFrame( - VideoPixelFormat expected_format, - const gfx::Size& expected_size) { +void InterprocessFramePool::MarkFrame(const media::VideoFrame& frame) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + marked_frame_buffer_ = frame.data(0); + marked_frame_size_ = frame.coded_size(); + marked_frame_color_space_ = frame.ColorSpace(); + marked_frame_pixel_format_ = frame.format(); +} + +void InterprocessFramePool::ClearFrameMarking() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + marked_frame_buffer_ = nullptr; +} + +bool InterprocessFramePool::HasMarkedFrameWithSize( + const gfx::Size& size) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return marked_frame_buffer_ != nullptr && marked_frame_size_ == size; +} + +scoped_refptr<VideoFrame> +InterprocessFramePool::ResurrectOrDuplicateContentFromMarkedFrame() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Find the tracking entry for the resurrectable buffer. If it is still being - // used, or is not of the expected format and size, punt. - if (resurrectable_buffer_memory_ == nullptr || - last_delivered_format_ != expected_format || - last_delivered_size_ != expected_size) { + if (!marked_frame_buffer_) return nullptr; - } - const auto it = std::find_if( - available_buffers_.rbegin(), available_buffers_.rend(), - [this](const PooledBuffer& candidate) { - return candidate.mapping.memory() == resurrectable_buffer_memory_; - }); - if (it == available_buffers_.rend()) { - return nullptr; + + const auto it = + std::find_if(available_buffers_.rbegin(), available_buffers_.rend(), + [this](const PooledBuffer& candidate) { + return candidate.mapping.memory() == marked_frame_buffer_; + }); + + // If the buffer is available, use it directly. + if (it != available_buffers_.rend()) { + // Wrap the buffer in a VideoFrame and return it. + PooledBuffer resurrected = std::move(*it); + available_buffers_.erase(it.base() - 1); + auto frame = WrapBuffer(std::move(resurrected), marked_frame_pixel_format_, + marked_frame_size_); + frame->set_color_space(marked_frame_color_space_); + return frame; } - // Wrap the buffer in a VideoFrame and return it. - PooledBuffer resurrected = std::move(*it); - available_buffers_.erase(it.base() - 1); + // Buffer is currently in use. Reserve a new buffer and copy the contents + // over. auto frame = - WrapBuffer(std::move(resurrected), expected_format, expected_size); - frame->set_color_space(last_delivered_color_space_); + ReserveVideoFrame(marked_frame_pixel_format_, marked_frame_size_); + // The call to ReserverVideoFrame should not have cleared + // |marked_frame_buffer_|, because that buffer is currently in use. + DCHECK(marked_frame_buffer_); + if (!frame) + return nullptr; +#if DCHECK_IS_ON() + // Sanity check that |marked_frame_buffer_| indeed corresponds to a buffer in + // |utilized_buffers_|. If MarkFrame() was erroneously called with a frame + // that did not belong to this pool or was otherwise tampered with, this might + // not be the case. + const auto source_it = std::find_if( + utilized_buffers_.rbegin(), utilized_buffers_.rend(), + [this](const std::pair<const media::VideoFrame*, + base::ReadOnlySharedMemoryRegion>& candidate) { + return candidate.first->data(0) == marked_frame_buffer_; + }); + DCHECK(source_it != utilized_buffers_.rend()); +#endif // DCHECK_IS_ON() + + // Copy the contents over. + const size_t num_bytes_to_copy = VideoFrame::AllocationSize( + marked_frame_pixel_format_, marked_frame_size_); + memcpy(frame->data(0), marked_frame_buffer_, num_bytes_to_copy); + + frame->set_color_space(marked_frame_color_space_); return frame; } @@ -116,16 +159,8 @@ const VideoFrame* frame) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Record that this frame is the last-delivered one, for possible future calls - // to ResurrectLastVideoFrame(). const auto it = utilized_buffers_.find(frame); DCHECK(it != utilized_buffers_.end()); - // Assumption: The first image plane's memory pointer should be the start of - // the writable mapped memory. WrapBuffer() sanity-checks this. - resurrectable_buffer_memory_ = frame->data(0); - last_delivered_format_ = frame->format(); - last_delivered_size_ = frame->coded_size(); - last_delivered_color_space_ = frame->ColorSpace(); return it->second.Duplicate(); } @@ -161,7 +196,7 @@ static_cast<uint8_t*>(pooled_buffer.mapping.memory()), pooled_buffer.mapping.size(), base::TimeDelta()); DCHECK(frame); - // Sanity-check the assumption being made in CloneHandleForDelivery(): + // Sanity-check the assumption being made for SetMarkedBuffer(): DCHECK_EQ(frame->data(0), pooled_buffer.mapping.memory()); utilized_buffers_.emplace(frame.get(), std::move(pooled_buffer.region)); frame->AddDestructionObserver(
diff --git a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h index 9337f72..f4ffc14e 100644 --- a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h +++ b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h
@@ -42,14 +42,20 @@ media::VideoPixelFormat format, const gfx::Size& size); - // Finds the last VideoFrame delivered, and if it has been returned back to - // this pool already, re-materializes it. Otherwise, null is returned. This is - // used when the client knows the content of the video frame has not changed - // and is trying to avoid having to re-populate a new VideoFrame with the same - // content. - scoped_refptr<media::VideoFrame> ResurrectLastVideoFrame( - media::VideoPixelFormat expected_format, - const gfx::Size& expected_size); + // Clients may call this using a frame previously returned by + // ReserveVideoFrame() to mark it (or its contents) for later resurrection via + // ResurrectOrDuplicateContentFromMarkedFrame(). Note that only one frame can + // be marked at a time. MarkFrame() will overwrite any existing mark. + void MarkFrame(const media::VideoFrame& frame); + void ClearFrameMarking(); + bool HasMarkedFrameWithSize(const gfx::Size& size) const; + + // If no frame is marked, returns nullptr. Otherwise, if the marked frame is + // not currently in use, returns the marked frame. If the marked frame is in + // use, reserves a new frame and copies the contents of the marked frame to + // the newly reserved one. That last case may still return nullptr if the pool + // is fully utilized. + scoped_refptr<media::VideoFrame> ResurrectOrDuplicateContentFromMarkedFrame(); // Returns a cloned handle to the shared memory backing |frame| and its size // in bytes. Note that the client should not allow the ref-count of the @@ -99,13 +105,12 @@ base::flat_map<const media::VideoFrame*, base::ReadOnlySharedMemoryRegion> utilized_buffers_; - // The pointer to the mapped memory of the buffer that was last delivered, - // along with its format and size. ResurrectLastVideoFrame() uses this - // information to locate and confirm that a prior frame can be resurrected. - const void* resurrectable_buffer_memory_ = nullptr; - media::VideoPixelFormat last_delivered_format_ = media::PIXEL_FORMAT_UNKNOWN; - gfx::Size last_delivered_size_; - gfx::ColorSpace last_delivered_color_space_; + // The pointer to the mapped memory of the buffer that was set as "marked" + // via a call to SetMarkedBuffer(). + const void* marked_frame_buffer_ = nullptr; + gfx::Size marked_frame_size_; + gfx::ColorSpace marked_frame_color_space_; + media::VideoPixelFormat marked_frame_pixel_format_; // The time at which the last shared memory allocation or mapping failed. base::TimeTicks last_fail_log_time_;
diff --git a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc index 29e2fee..86233d74 100644 --- a/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc
@@ -143,70 +143,154 @@ return true; } -TEST(InterprocessFramePoolTest, ResurrectsDeliveredFramesOnly) { +TEST(InterprocessFramePoolTest, ResurrectFrameThatIsNotInUse) { InterprocessFramePool pool(2); + const gfx::ColorSpace kArbitraryColorSpace = gfx::ColorSpace::CreateREC709(); - // Reserve a frame, populate it, but release it before delivery. + // Reserve a frame, populate it, mark it, and release it. scoped_refptr<media::VideoFrame> frame = pool.ReserveVideoFrame(kFormat, kSize); ASSERT_TRUE(frame); - media::FillYUV(frame.get(), 0x11, 0x22, 0x33); - frame = nullptr; // Returns frame to pool. - - // The pool should fail to resurrect the last frame because it was never - // delivered. - frame = pool.ResurrectLastVideoFrame(kFormat, kSize); - ASSERT_FALSE(frame); - - // Reserve a frame and populate it with different color values; only this - // time, signal that it will be delivered before releasing it. - frame = pool.ReserveVideoFrame(kFormat, kSize); - ASSERT_TRUE(frame); - const uint8_t kValues[3] = {0x44, 0x55, 0x66}; + const uint8_t kValues[3] = {0x11, 0x22, 0x33}; media::FillYUV(frame.get(), kValues[0], kValues[1], kValues[2]); - { - auto handle = pool.CloneHandleForDelivery(frame.get()); - ExpectValidHandleForDelivery(handle); - } + frame->set_color_space(kArbitraryColorSpace); + pool.MarkFrame(*frame); frame = nullptr; // Returns frame to pool. - // Confirm that the last frame can be resurrected repeatedly. + ASSERT_TRUE(pool.HasMarkedFrameWithSize(kSize)); + const gfx::Size kDifferentSize(kSize.width() - 2, kSize.height() + 2); + ASSERT_FALSE(pool.HasMarkedFrameWithSize(kDifferentSize)); + + // Resurrect the frame and expect it to still have the same content, size, + // format, and color space. Release and repeat that a few times. for (int i = 0; i < 3; ++i) { - frame = pool.ResurrectLastVideoFrame(kFormat, kSize); + frame = pool.ResurrectOrDuplicateContentFromMarkedFrame(); ASSERT_TRUE(frame); + ASSERT_EQ(kFormat, frame->format()); + ASSERT_EQ(kSize, frame->coded_size()); + ASSERT_EQ(kSize, frame->visible_rect().size()); + ASSERT_EQ(kSize, frame->natural_size()); + ASSERT_EQ(kArbitraryColorSpace, frame->ColorSpace()); ASSERT_TRUE(PlanesAreFilledWithValues(*frame, kValues)); - frame = nullptr; // Returns frame to pool. + frame = nullptr; } +} - // A frame that is being delivered cannot be resurrected. - for (int i = 0; i < 2; ++i) { - if (i == 0) { // Test this for a resurrected frame. - frame = pool.ResurrectLastVideoFrame(kFormat, kSize); - ASSERT_TRUE(frame); - ASSERT_TRUE(PlanesAreFilledWithValues(*frame, kValues)); - } else { // Test this for a normal frame. - frame = pool.ReserveVideoFrame(kFormat, kSize); - ASSERT_TRUE(frame); - media::FillYUV(frame.get(), 0x77, 0x88, 0x99); - } - { - auto handle = pool.CloneHandleForDelivery(frame.get()); - ExpectValidHandleForDelivery(handle); - } - scoped_refptr<media::VideoFrame> should_be_null = - pool.ResurrectLastVideoFrame(kFormat, kSize); - ASSERT_FALSE(should_be_null); - frame = nullptr; // Returns frame to pool. - } +TEST(InterprocessFramePoolTest, ResurrectContentFromFrameThatIsStillInUse) { + InterprocessFramePool pool(2); + const gfx::ColorSpace kArbitraryColorSpace = gfx::ColorSpace::CreateREC709(); - // Finally, reserve a frame, populate it, and don't deliver it. Expect that, - // still, undelivered frames cannot be resurrected. - frame = pool.ReserveVideoFrame(kFormat, kSize); + // Reserve a frame, populate it, mark it, and hold on to it. + scoped_refptr<media::VideoFrame> frame = + pool.ReserveVideoFrame(kFormat, kSize); ASSERT_TRUE(frame); - media::FillYUV(frame.get(), 0xaa, 0xbb, 0xcc); - frame = nullptr; // Returns frame to pool. - frame = pool.ResurrectLastVideoFrame(kFormat, kSize); + const uint8_t kValues[3] = {0x11, 0x22, 0x33}; + media::FillYUV(frame.get(), kValues[0], kValues[1], kValues[2]); + frame->set_color_space(kArbitraryColorSpace); + pool.MarkFrame(*frame); + + ASSERT_TRUE(pool.HasMarkedFrameWithSize(kSize)); + const gfx::Size kDifferentSize(kSize.width() - 2, kSize.height() + 2); + ASSERT_FALSE(pool.HasMarkedFrameWithSize(kDifferentSize)); + + scoped_refptr<media::VideoFrame> frame2 = + pool.ResurrectOrDuplicateContentFromMarkedFrame(); + ASSERT_TRUE(frame2); + ASSERT_NE(frame, frame2); + ASSERT_NE(frame->data(0), frame2->data(0)); + ASSERT_EQ(kFormat, frame2->format()); + ASSERT_EQ(kSize, frame2->coded_size()); + ASSERT_EQ(kSize, frame2->visible_rect().size()); + ASSERT_EQ(kSize, frame2->natural_size()); + ASSERT_EQ(kArbitraryColorSpace, frame2->ColorSpace()); + ASSERT_TRUE(PlanesAreFilledWithValues(*frame2, kValues)); +} + +TEST(InterprocessFramePoolTest, ResurrectWhenAtCapacity) { + InterprocessFramePool pool(2); + const gfx::ColorSpace kArbitraryColorSpace = gfx::ColorSpace::CreateREC709(); + + // Reserve two frames and hold on to them + scoped_refptr<media::VideoFrame> frame1 = + pool.ReserveVideoFrame(kFormat, kSize); + scoped_refptr<media::VideoFrame> frame2 = + pool.ReserveVideoFrame(kFormat, kSize); + ASSERT_TRUE(frame1); + ASSERT_TRUE(frame2); + // Fill and mark one of them + const uint8_t kValues[3] = {0x11, 0x22, 0x33}; + media::FillYUV(frame1.get(), kValues[0], kValues[1], kValues[2]); + frame1->set_color_space(kArbitraryColorSpace); + pool.MarkFrame(*frame1); + + // Attempt to resurrect. This should fail, because the pool is already at + // capacity. + scoped_refptr<media::VideoFrame> frame3 = + pool.ResurrectOrDuplicateContentFromMarkedFrame(); + ASSERT_FALSE(frame3); + + // Release the first frame + frame1 = nullptr; + + // Now, resurrecting should work again. + frame3 = pool.ResurrectOrDuplicateContentFromMarkedFrame(); + ASSERT_TRUE(frame3); + ASSERT_EQ(kFormat, frame3->format()); + ASSERT_EQ(kSize, frame3->coded_size()); + ASSERT_EQ(kArbitraryColorSpace, frame3->ColorSpace()); + ASSERT_TRUE(PlanesAreFilledWithValues(*frame3, kValues)); +} + +TEST(InterprocessFramePoolTest, ResurrectWhenNoFrameMarked) { + InterprocessFramePool pool(2); + + // Attempt to resurrect before any frame was ever reserved. + scoped_refptr<media::VideoFrame> frame = + pool.ResurrectOrDuplicateContentFromMarkedFrame(); ASSERT_FALSE(frame); + + // Reserve a frame and release it without marking it. + scoped_refptr<media::VideoFrame> frame2 = + pool.ReserveVideoFrame(kFormat, kSize); + ASSERT_TRUE(frame2); + frame2 = nullptr; // Returns frame to pool. + + // Attempt to resurrect. This should fail, because no frame was marked. + scoped_refptr<media::VideoFrame> frame3 = + pool.ResurrectOrDuplicateContentFromMarkedFrame(); + ASSERT_FALSE(frame3); +} + +TEST(InterprocessFramePoolTest, FrameMarkingIsLostWhenBufferIsReallocated) { + InterprocessFramePool pool(2); + + // Reserve enough frames to hit capacity. + scoped_refptr<media::VideoFrame> frame1 = + pool.ReserveVideoFrame(kFormat, kSize); + scoped_refptr<media::VideoFrame> frame2 = + pool.ReserveVideoFrame(kFormat, kSize); + ASSERT_TRUE(frame1); + ASSERT_TRUE(frame2); + + // Mark one of them + pool.MarkFrame(*frame1); + ASSERT_TRUE(pool.HasMarkedFrameWithSize(kSize)); + + // Release all frames + frame1 = nullptr; + frame2 = nullptr; + + // Reserve all frames again but this time request a bigger size. + // This should lead to all buffers being reallocated and the marking being + // lost. + gfx::Size kBiggerSize(kSize.width() + 2, kSize.height() + 2); + frame1 = pool.ReserveVideoFrame(kFormat, kBiggerSize); + frame2 = pool.ReserveVideoFrame(kFormat, kBiggerSize); + ASSERT_TRUE(frame1); + ASSERT_TRUE(frame2); + + ASSERT_FALSE(pool.HasMarkedFrameWithSize(kSize)); + ASSERT_FALSE(pool.HasMarkedFrameWithSize(kBiggerSize)); } TEST(InterprocessFramePoolTest, ReportsCorrectUtilization) { @@ -219,7 +303,7 @@ // Reserve the frame and expect 1/2 the pool to be utilized. scoped_refptr<media::VideoFrame> frame = (i == 0) ? pool.ReserveVideoFrame(kFormat, kSize) - : pool.ResurrectLastVideoFrame(kFormat, kSize); + : pool.ResurrectOrDuplicateContentFromMarkedFrame(); ASSERT_TRUE(frame); ASSERT_EQ(0.5f, pool.GetUtilization()); @@ -231,6 +315,9 @@ } ASSERT_EQ(0.5f, pool.GetUtilization()); + // Mark the frame for later resurrection. + pool.MarkFrame(*frame); + // Finally, release the frame to indicate it has been delivered and is no // longer in-use by downstream consumers. This should cause the utilization // to go back down to zero.
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc index 01a6440..a31c903 100644 --- a/components/viz/service/surfaces/surface.cc +++ b/components/viz/service/surfaces/surface.cc
@@ -521,6 +521,14 @@ blocking_allocation_groups_.clear(); activation_dependencies_.clear(); + // If the client has specified a deadline of zero and we don't need to block + // on the parent, there is no need to figure out the activation dependencies, + // since the frame will activate immediately. + bool block_activation = + block_activation_on_parent_ && !seen_first_surface_dependency_; + if (!block_activation && current_frame.metadata.deadline.IsZero()) + return; + std::vector<SurfaceAllocationGroup*> new_blocking_allocation_groups; std::vector<SurfaceId> new_activation_dependencies; for (const SurfaceId& surface_id :
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 4d147306..d4ab24d 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -39,6 +39,8 @@ #include "content/browser/android/background_sync_network_observer_android.h" #endif +using blink::mojom::BackgroundSyncType; + namespace content { namespace { @@ -192,10 +194,27 @@ std::move(task).Run(std::move(callback)); } -blink::mojom::BackgroundSyncType GetBackgroundSyncType( +BackgroundSyncType GetBackgroundSyncType( const blink::mojom::SyncRegistrationOptions& options) { - return options.min_interval >= 0 ? blink::mojom::BackgroundSyncType::PERIODIC - : blink::mojom::BackgroundSyncType::ONE_SHOT; + return options.min_interval >= 0 ? BackgroundSyncType::PERIODIC + : BackgroundSyncType::ONE_SHOT; +} + +std::string GetEventStatusString(blink::ServiceWorkerStatusCode status_code) { + // The |status_code| is derived from blink::mojom::ServiceWorkerEventStatus. + switch (status_code) { + case blink::ServiceWorkerStatusCode::kOk: + return "succeeded"; + case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected: + return "waitUntil rejected"; + case blink::ServiceWorkerStatusCode::kErrorAbort: + return "aborted"; + case blink::ServiceWorkerStatusCode::kErrorTimeout: + return "timeout"; + default: + NOTREACHED(); + return "unknown error"; + } } } // namespace @@ -450,10 +469,10 @@ for (const auto& registration_proto : registrations_proto.registration()) { - blink::mojom::BackgroundSyncType sync_type = + BackgroundSyncType sync_type = registration_proto.has_periodic_sync_options() - ? blink::mojom::BackgroundSyncType::PERIODIC - : blink::mojom::BackgroundSyncType::ONE_SHOT; + ? BackgroundSyncType::PERIODIC + : BackgroundSyncType::ONE_SHOT; BackgroundSyncRegistration* registration = ®istrations ->registration_map[{registration_proto.tag(), sync_type}]; @@ -461,7 +480,7 @@ blink::mojom::SyncRegistrationOptions* options = registration->options(); options->tag = registration_proto.tag(); - if (sync_type == blink::mojom::BackgroundSyncType::PERIODIC) { + if (sync_type == BackgroundSyncType::PERIODIC) { options->min_interval = registration_proto.periodic_sync_options().min_interval(); if (options->min_interval < 0) { @@ -617,8 +636,7 @@ *new_registration.options() = std::move(options); - if (new_registration.sync_type() == - blink::mojom::BackgroundSyncType::PERIODIC) { + if (new_registration.sync_type() == BackgroundSyncType::PERIODIC) { base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {BrowserThread::UI}, base::BindOnce( @@ -643,8 +661,7 @@ // For one-shot registrations, we let the delay_until be in the past, so that // an event is fired at the soonest opportune moment. - if (new_registration.sync_type() == - blink::mojom::BackgroundSyncType::PERIODIC) { + if (new_registration.sync_type() == BackgroundSyncType::PERIODIC) { new_registration.set_delay_until(clock_->Now() + delay); } @@ -858,13 +875,12 @@ &active_registrations_[sw_registration_id]; registrations->origin = origin; - blink::mojom::BackgroundSyncType sync_type = sync_registration.sync_type(); + BackgroundSyncType sync_type = sync_registration.sync_type(); registrations ->registration_map[{sync_registration.options()->tag, sync_type}] = sync_registration; - if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC) && - sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT) { + if (ShouldLogToDevTools(sync_type)) { devtools_context_->LogBackgroundServiceEvent( sw_registration_id, origin, devtools::proto::BACKGROUND_SYNC, /* event_name= */ "registered sync", @@ -1010,7 +1026,7 @@ } base::TimeDelta BackgroundSyncManager::GetSoonestWakeupDelta( - blink::mojom::BackgroundSyncType sync_type) { + BackgroundSyncType sync_type) { DCHECK_CURRENTLY_ON(BrowserThread::IO); base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max(); for (const auto& sw_reg_id_and_registrations : active_registrations_) { @@ -1036,7 +1052,7 @@ // If the browser is closed while firing events, the browser needs a task to // wake it back up and try again. - if (sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT && + if (sync_type == BackgroundSyncType::ONE_SHOT && num_firing_registrations_ > 0 && soonest_wakeup_delta > parameters_->min_sync_recovery_time) { soonest_wakeup_delta = parameters_->min_sync_recovery_time; @@ -1048,9 +1064,9 @@ void BackgroundSyncManager::RunInBackgroundIfNecessary() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - base::TimeDelta soonest_wakeup_delta = std::min( - GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::ONE_SHOT), - GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC)); + base::TimeDelta soonest_wakeup_delta = + std::min(GetSoonestWakeupDelta(BackgroundSyncType::ONE_SHOT), + GetSoonestWakeupDelta(BackgroundSyncType::PERIODIC)); // Try firing again after the wakeup delta. if (!soonest_wakeup_delta.is_max() && !soonest_wakeup_delta.is_zero()) { @@ -1180,8 +1196,8 @@ // Don't dispatch a sync event if the sync is periodic. // TODO(crbug.com/925297): Remove this code when we've added the logic to // dispatch periodic sync events. - if (registration && registration_info->sync_type == - blink::mojom::BackgroundSyncType::PERIODIC) { + if (registration && + registration_info->sync_type == BackgroundSyncType::PERIODIC) { RemoveActiveRegistration(*registration_info); StoreRegistrations(registration_info->service_worker_registration_id, base::DoNothing()); @@ -1291,8 +1307,7 @@ // It's important to update |num_attempts| before we update |delay_until|. registration->set_num_attempts(registration->num_attempts() + 1); - if ((registration->sync_type() == - blink::mojom::BackgroundSyncType::PERIODIC && + if ((registration->sync_type() == BackgroundSyncType::PERIODIC && registration->num_attempts() == parameters_->max_sync_attempts) || (registration->sync_state() == blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING)) { @@ -1301,7 +1316,7 @@ // If |delay_until| needs to be updated, get updated delay. bool succeeded = status_code == blink::ServiceWorkerStatusCode::kOk; - if (registration->sync_type() == blink::mojom::BackgroundSyncType::PERIODIC || + if (registration->sync_type() == BackgroundSyncType::PERIODIC || (!succeeded && registration->num_attempts() < parameters_->max_sync_attempts)) { base::PostTaskWithTraitsAndReplyWithResult( @@ -1311,18 +1326,18 @@ std::make_unique<BackgroundSyncParameters>(*parameters_)), base::BindOnce(&BackgroundSyncManager::EventCompleteDidGetDelay, weak_ptr_factory_.GetWeakPtr(), - std::move(registration_info), succeeded, origin, + std::move(registration_info), status_code, origin, std::move(callback))); return; } - EventCompleteDidGetDelay(std::move(registration_info), succeeded, origin, + EventCompleteDidGetDelay(std::move(registration_info), status_code, origin, std::move(callback), base::TimeDelta::Max()); } void BackgroundSyncManager::EventCompleteDidGetDelay( blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info, - bool succeeded, + blink::ServiceWorkerStatusCode status_code, const url::Origin& origin, base::OnceClosure callback, base::TimeDelta delay) { @@ -1336,51 +1351,59 @@ return; } + bool succeeded = status_code == blink::ServiceWorkerStatusCode::kOk; bool can_retry = registration->num_attempts() < parameters_->max_sync_attempts; - if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC) && - registration_info->sync_type == - blink::mojom::BackgroundSyncType::ONE_SHOT) { - if (succeeded) { - devtools_context_->LogBackgroundServiceEvent( - registration_info->service_worker_registration_id, origin, - devtools::proto::BACKGROUND_SYNC, - /* event_name= */ "sync event failed", - /* instance_id= */ registration_info->tag, - /* event_metadata= */ - {{"can_retry", can_retry ? "yes" : "no"}, - {"next attempt delay (ms)", - delay.is_max() ? "infinite" - : base::NumberToString(delay.InMilliseconds())}}); - } else { - devtools_context_->LogBackgroundServiceEvent( - registration_info->service_worker_registration_id, origin, - devtools::proto::BACKGROUND_SYNC, - /* event_name= */ "sync complete", - /* instance_id= */ registration_info->tag, - /* event_metadata= */ - {{"succeeded", succeeded ? "yes" : "no"}}); - } - } - bool registration_completed = true; - if (registration->sync_state() == blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING) { registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING); registration->set_num_attempts(0); registration_completed = false; - } else if (registration->sync_type() == - blink::mojom::BackgroundSyncType::PERIODIC || - (!succeeded && can_retry)) { + if (ShouldLogToDevTools(registration->sync_type())) { + devtools_context_->LogBackgroundServiceEvent( + registration_info->service_worker_registration_id, origin, + devtools::proto::BACKGROUND_SYNC, + /* event_name= */ "sync event reregistered", + /* instance_id= */ registration_info->tag, + /* event_metadata= */ {}); + } + } else if ((!succeeded && can_retry) || + registration->sync_type() == BackgroundSyncType::PERIODIC) { registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING); registration_completed = false; registration->set_delay_until(clock_->Now() + delay); + + if (ShouldLogToDevTools(registration->sync_type())) { + std::string delay_ms = delay.is_max() + ? "infinite" + : base::NumberToString(delay.InMilliseconds()); + devtools_context_->LogBackgroundServiceEvent( + registration_info->service_worker_registration_id, origin, + devtools::proto::BACKGROUND_SYNC, + /* event_name= */ "sync event failed", + /* instance_id= */ registration_info->tag, + {{"next attempt delay (ms)", delay_ms}, + {"failure reason", GetEventStatusString(status_code)}}); + } } - if (registration_completed) + if (registration_completed) { + BackgroundSyncMetrics::RecordRegistrationComplete( + succeeded, registration->num_attempts()); + + if (ShouldLogToDevTools(registration->sync_type())) { + devtools_context_->LogBackgroundServiceEvent( + registration_info->service_worker_registration_id, origin, + devtools::proto::BACKGROUND_SYNC, + /* event_name= */ "sync complete", + /* instance_id= */ registration_info->tag, + {{"status", GetEventStatusString(status_code)}}); + } + RemoveActiveRegistration(*registration_info); + } StoreRegistrations( registration_info->service_worker_registration_id, @@ -1465,13 +1488,18 @@ blink::ServiceWorkerStatusCode BackgroundSyncManager::CanEmulateSyncEvent( scoped_refptr<ServiceWorkerVersion> active_version) { if (!active_version) - return blink::ServiceWorkerStatusCode::kErrorFailed; + return blink::ServiceWorkerStatusCode::kErrorAbort; if (!network_observer_->NetworkSufficient()) - return blink::ServiceWorkerStatusCode::kErrorNetwork; + return blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected; int64_t registration_id = active_version->registration_id(); if (base::ContainsKey(emulated_offline_sw_, registration_id)) - return blink::ServiceWorkerStatusCode::kErrorNetwork; + return blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected; return blink::ServiceWorkerStatusCode::kOk; } +bool BackgroundSyncManager::ShouldLogToDevTools(BackgroundSyncType sync_type) { + return sync_type == BackgroundSyncType::ONE_SHOT && + devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC); +} + } // namespace content
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h index 11723924..8ca76b85 100644 --- a/content/browser/background_sync/background_sync_manager.h +++ b/content/browser/background_sync/background_sync_manager.h
@@ -287,7 +287,7 @@ base::OnceClosure callback); void EventCompleteDidGetDelay( blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info, - bool succeeded, + blink::ServiceWorkerStatusCode status_code, const url::Origin& origin, base::OnceClosure callback, base::TimeDelta delay); @@ -312,6 +312,9 @@ void SetMaxSyncAttemptsImpl(int max_sync_attempts, base::OnceClosure callback); + // Whether an event should be logged for debuggability. + bool ShouldLogToDevTools(blink::mojom::BackgroundSyncType sync_type); + base::OnceClosure MakeEmptyCompletion(); blink::ServiceWorkerStatusCode CanEmulateSyncEvent(
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc index 5a0034b..6b7a73f 100644 --- a/content/browser/background_sync/background_sync_manager_unittest.cc +++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -402,7 +402,8 @@ void InitFailedSyncEventTest() { SetupForSyncEvent(base::BindRepeating( &BackgroundSyncManagerTest::DispatchSyncStatusCallback, - base::Unretained(this), blink::ServiceWorkerStatusCode::kErrorFailed)); + base::Unretained(this), + blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected)); } void DispatchSyncDelayedCallback( @@ -913,7 +914,7 @@ // The first sync attempt fails. ASSERT_TRUE(sync_fired_callback_); std::move(sync_fired_callback_) - .Run(blink::ServiceWorkerStatusCode::kErrorFailed); + .Run(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected); base::RunLoop().RunUntilIdle(); // It should fire again since it was reregistered mid-sync. @@ -1547,7 +1548,7 @@ InitSyncEventTest(); bool was_called = false; blink::ServiceWorkerStatusCode code = - blink::ServiceWorkerStatusCode::kErrorFailed; + blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected; background_sync_manager_->EmulateDispatchSyncEvent( "emulated_tag", sw_registration_1_->active_version(), false, base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code)); @@ -1566,7 +1567,7 @@ base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(was_called); - EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNetwork, code); + EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, code); background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_, false); @@ -1579,7 +1580,7 @@ base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(was_called); - EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNetwork, code); + EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, code); SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI); was_called = false; @@ -1633,4 +1634,45 @@ } } +TEST_F(BackgroundSyncManagerTest, UkmRecordedAtCompletion) { + InitSyncEventTest(); + { + base::HistogramTester histogram_tester; + + EXPECT_TRUE(Register(sync_options_1_)); + + test_background_sync_manager_->RunDelayedTask(); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(GetRegistration(sync_options_1_)); + + histogram_tester.ExpectBucketCount( + "BackgroundSync.Registration.OneShot.EventSucceededAtCompletion", true, + 1); + histogram_tester.ExpectBucketCount( + "BackgroundSync.Registration.OneShot.NumAttemptsForSuccessfulEvent", 1, + 1); + } + + SetMaxSyncAttemptsAndRestartManager(1); + InitFailedSyncEventTest(); + { + base::HistogramTester histogram_tester; + + EXPECT_TRUE(Register(sync_options_2_)); + + test_background_sync_manager_->RunDelayedTask(); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(GetRegistration(sync_options_2_)); + + histogram_tester.ExpectBucketCount( + "BackgroundSync.Registration.OneShot.EventSucceededAtCompletion", false, + 1); + histogram_tester.ExpectBucketCount( + "BackgroundSync.Registration.OneShot.NumAttemptsForSuccessfulEvent", 1, + 0); + } +} + } // namespace content
diff --git a/content/browser/child_process_launcher_helper.cc b/content/browser/child_process_launcher_helper.cc index 8cbede7e..956df48 100644 --- a/content/browser/child_process_launcher_helper.cc +++ b/content/browser/child_process_launcher_helper.cc
@@ -227,13 +227,22 @@ launcher_task_runner( android::LauncherThread::GetMessageLoop()->task_runner()); return (*launcher_task_runner).get(); -#else // defined(OS_ANDROID) +#else // defined(OS_ANDROID) + constexpr base::TaskShutdownBehavior shutdown_behavior = +#if defined(OS_WIN) + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN; +#else + // Linux could use CONTINUE_ON_SHUTDOWN if ZygoteHostImpl was leaked on + // shutdown. Mac could use CONTINUE_ON_SHUTDOWN if PluginServiceImpl was + // leaked on shutdown. + base::TaskShutdownBehavior::BLOCK_SHUTDOWN; +#endif // defined(OS_WIN) // TODO(http://crbug.com/820200): Investigate whether we could use // SequencedTaskRunner on platforms other than Windows. static base::LazySingleThreadTaskRunner launcher_task_runner = LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER( base::TaskTraits({base::MayBlock(), base::TaskPriority::USER_BLOCKING, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN}), + shutdown_behavior}), base::SingleThreadTaskRunnerThreadMode::DEDICATED); return launcher_task_runner.Get().get(); #endif // defined(OS_ANDROID)
diff --git a/content/browser/image_capture/OWNERS b/content/browser/image_capture/OWNERS index c261502..cc7f7bb 100644 --- a/content/browser/image_capture/OWNERS +++ b/content/browser/image_capture/OWNERS
@@ -1,5 +1,7 @@ -mcasas@chromium.org miu@chromium.org +# Original (legacy) owner. +mcasas@chromium.org + # COMPONENT: Blink>ImageCapture -# TEAM: media-dev@chromium.org +# TEAM: webrtc-dev@chromium.org
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc index 37f294f..07cdd163a 100644 --- a/content/browser/portal/portal_browsertest.cc +++ b/content/browser/portal/portal_browsertest.cc
@@ -4,6 +4,7 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/test/bind_test_util.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "content/browser/frame_host/render_frame_host_impl.h" @@ -426,4 +427,59 @@ EXPECT_EQ(false, EvalJs(portal_frame, "clicked")); } +// Tests that async hit testing does not target portals. +IN_PROC_BROWSER_TEST_F(PortalBrowserTest, AsyncEventTargetingIgnoresPortals) { + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("portal.test", "/title1.html"))); + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame(); + + // Create portal and wait for navigation. + PortalCreatedObserver portal_created_observer(main_frame); + GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html")); + EXPECT_TRUE(ExecJs(main_frame, + JsReplace("var portal = document.createElement('portal');" + "portal.src = $1;" + "document.body.appendChild(portal);", + a_url))); + Portal* portal = portal_created_observer.WaitUntilPortalCreated(); + WebContentsImpl* portal_contents = portal->GetPortalContents(); + RenderFrameHostImpl* portal_frame = portal_contents->GetMainFrame(); + ASSERT_TRUE(static_cast<RenderWidgetHostViewBase*>(portal_frame->GetView()) + ->IsRenderWidgetHostViewChildFrame()); + RenderWidgetHostViewChildFrame* portal_view = + static_cast<RenderWidgetHostViewChildFrame*>(portal_frame->GetView()); + TestNavigationObserver navigation_observer(portal_contents); + navigation_observer.Wait(); + WaitForHitTestDataOrChildSurfaceReady(portal_frame); + + viz::mojom::InputTargetClient* target_client = + main_frame->GetRenderWidgetHost()->input_target_client(); + ASSERT_TRUE(target_client); + + gfx::PointF root_location = + portal_view->TransformPointToRootCoordSpaceF(gfx::PointF(5, 5)); + + // Query the renderer for the target widget. The root should claim the point + // for itself, not the portal. + base::RunLoop run_loop; + base::OnceClosure quit_closure = run_loop.QuitClosure(); + viz::FrameSinkId received_frame_sink_id; + target_client->FrameSinkIdAt( + root_location, 0, + base::BindLambdaForTesting( + [&](const viz::FrameSinkId& id, const gfx::PointF& point) { + received_frame_sink_id = id; + std::move(quit_closure).Run(); + })); + run_loop.Run(); + + viz::FrameSinkId root_frame_sink_id = + static_cast<RenderWidgetHostViewBase*>(main_frame->GetView()) + ->GetFrameSinkId(); + EXPECT_EQ(root_frame_sink_id, received_frame_sink_id) + << "Note: The portal's FrameSinkId is " << portal_view->GetFrameSinkId(); +} + } // namespace content
diff --git a/content/browser/renderer_host/frame_connector_delegate.cc b/content/browser/renderer_host/frame_connector_delegate.cc index 39f910a..c0d82a9 100644 --- a/content/browser/renderer_host/frame_connector_delegate.cc +++ b/content/browser/renderer_host/frame_connector_delegate.cc
@@ -48,7 +48,9 @@ render_widget_host->SetAutoResize(visual_properties.auto_resize_enabled, visual_properties.min_size_for_auto_resize, visual_properties.max_size_for_auto_resize); - render_widget_host->SetPageScaleFactor(visual_properties.page_scale_factor); + render_widget_host->SetPageScaleState( + visual_properties.page_scale_factor, + visual_properties.is_pinch_gesture_active); render_widget_host->SynchronizeVisualProperties(); }
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index 8ffc145..09fddbc 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -57,16 +57,13 @@ std::unique_ptr<InputEvent> ScaleEvent(const WebInputEvent& event, double scale, - const ui::LatencyInfo latency_info) { + const ui::LatencyInfo& latency_info) { std::unique_ptr<blink::WebInputEvent> event_in_viewport = ui::ScaleWebInputEvent(event, scale); if (event_in_viewport) { - ui::LatencyInfo scaled_latency_info(latency_info); - scaled_latency_info.set_scroll_update_delta( - latency_info.scroll_update_delta() * scale); return std::make_unique<InputEvent>( ui::WebScopedInputEvent(event_in_viewport.release()), - scaled_latency_info); + latency_info.ScaledBy(scale)); } return std::make_unique<InputEvent>(ui::WebInputEventTraits::Clone(event),
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc index e9b9352..ec4452bc 100644 --- a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc +++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
@@ -174,6 +174,8 @@ has_seen_first_gesture_scroll_update_ = true; latency->set_scroll_update_delta( static_cast<const WebGestureEvent&>(event).data.scroll_update.delta_y); + latency->set_predicted_scroll_update_delta( + static_cast<const WebGestureEvent&>(event).data.scroll_update.delta_y); } }
diff --git a/content/browser/renderer_host/media/OWNERS b/content/browser/renderer_host/media/OWNERS index 68a9bdc..107a4d64 100644 --- a/content/browser/renderer_host/media/OWNERS +++ b/content/browser/renderer_host/media/OWNERS
@@ -7,8 +7,10 @@ olka@chromium.org maxmorin@chromium.org -per-file *video*=mcasas@chromium.org per-file *video*=chfremer@chromium.org -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# Original (legacy) owner. +per-file *video*=mcasas@chromium.org + # COMPONENT: Blink>GetUserMedia +# TEAM: webrtc-dev@chromium.org
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index c9a555e7..edfc500c 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -422,6 +422,7 @@ visual_properties_ack_pending_(false), auto_resize_enabled_(false), page_scale_factor_(1.f), + is_pinch_gesture_active_(false), waiting_for_screen_rects_ack_(false), is_unresponsive_(false), in_flight_event_count_(0), @@ -898,6 +899,7 @@ visual_properties->max_size_for_auto_resize = max_size_for_auto_resize_; visual_properties->page_scale_factor = page_scale_factor_; + visual_properties->is_pinch_gesture_active = is_pinch_gesture_active_; if (view_) { visual_properties->new_size = view_->GetRequestedRendererSize(); @@ -984,7 +986,9 @@ old_visual_properties_->capture_sequence_number != visual_properties->capture_sequence_number || old_visual_properties_->page_scale_factor != - visual_properties->page_scale_factor; + visual_properties->page_scale_factor || + old_visual_properties_->is_pinch_gesture_active != + visual_properties->is_pinch_gesture_active; // We should throttle sending updated VisualProperties to the renderer to // the rate of commit. This ensures we don't overwhelm the renderer with @@ -2165,8 +2169,10 @@ max_size_for_auto_resize_ = max_size; } -void RenderWidgetHostImpl::SetPageScaleFactor(float page_scale_factor) { +void RenderWidgetHostImpl::SetPageScaleState(float page_scale_factor, + bool is_pinch_gesture_active) { page_scale_factor_ = page_scale_factor; + is_pinch_gesture_active_ = is_pinch_gesture_active; } void RenderWidgetHostImpl::Destroy(bool also_delete) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 5264464..cb0b14ec 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -562,8 +562,8 @@ const gfx::Size& min_size, const gfx::Size& max_size); - // Allows the main frame's page scale factor to be tracked. - void SetPageScaleFactor(float page_scale_factor); + // Allows the main frame's page scale state to be tracked. + void SetPageScaleState(float page_scale_factor, bool is_pinch_gesture_active); // Fills in the |visual_properties| struct. // Returns |false| if the update is redundant, |true| otherwise. @@ -789,6 +789,8 @@ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, AutoResizeWithScale); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, AutoResizeWithBrowserInitiatedResize); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, + ChildAllocationAcceptedInParentWhileHidden); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, Resize); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewChildFrameTest, ChildFrameAutoResizeUpdate); @@ -1018,6 +1020,8 @@ // The page-scale factor of the main-frame. float page_scale_factor_; + // True when the renderer is currently undergoing a pinch-zoom gesture. + bool is_pinch_gesture_active_; bool waiting_for_screen_rects_ack_; gfx::Rect last_view_screen_rect_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 5e1a20e..edba25d 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2214,8 +2214,19 @@ host(), metadata.top_controls_shown_ratio); } - SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(), - metadata.local_surface_id_allocation); + if (host()->is_hidden()) { + // When an embedded child responds, we want to accept its changes to the + // viz::LocalSurfaceId. However we do not want to embed surfaces while + // hidden. Nor do we want to embed invalid ids when we are evicted. Becoming + // visible will generate a new id, if necessary, and begin embedding. + // TODO(ejoe): Change the LocalSurfaceIdAllocation so that it can pause the + // elpased time for surface embedding. crbug/949967. + window_->UpdateLocalSurfaceIdFromEmbeddedClient( + metadata.local_surface_id_allocation); + } else { + SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(), + metadata.local_surface_id_allocation); + } } ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 067e2c7..5895441 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -2831,6 +2831,46 @@ EXPECT_EQ(local_surface_id_allocation2, local_surface_id_allocation3); } +// This test verifies that if the parent is hidden when the child sends a +// child-allocated viz::LocalSurfaceId, the parent will store it and it will +// not send a WidgetMsg_SynchronizeVisualProperties back to the child. +TEST_F(RenderWidgetHostViewAuraTest, + ChildAllocationAcceptedInParentWhileHidden) { + view_->InitAsChild(nullptr); + aura::client::ParentWindowWithContext( + view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(), + gfx::Rect()); + sink_->ClearMessages(); + viz::LocalSurfaceIdAllocation local_surface_id_allocation1( + view_->GetLocalSurfaceIdAllocation()); + EXPECT_TRUE(local_surface_id_allocation1.IsValid()); + + widget_host_->SetAutoResize(true, gfx::Size(50, 50), gfx::Size(100, 100)); + viz::ChildLocalSurfaceIdAllocator child_allocator; + child_allocator.UpdateFromParent(local_surface_id_allocation1); + child_allocator.GenerateId(); + viz::LocalSurfaceIdAllocation local_surface_id_allocation2 = + child_allocator.GetCurrentLocalSurfaceIdAllocation(); + + view_->WasOccluded(); + EXPECT_TRUE(widget_host_->is_hidden()); + + { + cc::RenderFrameMetadata metadata; + metadata.viewport_size_in_pixels = gfx::Size(75, 75); + metadata.local_surface_id_allocation = local_surface_id_allocation2; + widget_host_->DidUpdateVisualProperties(metadata); + } + + viz::LocalSurfaceIdAllocation local_surface_id_allocation3( + view_->GetLocalSurfaceIdAllocation()); + EXPECT_NE(local_surface_id_allocation1, local_surface_id_allocation3); + EXPECT_EQ(local_surface_id_allocation2, local_surface_id_allocation3); + + EXPECT_FALSE(sink_->GetUniqueMessageMatching( + WidgetMsg_SynchronizeVisualProperties::ID)); +} + // This test verifies that when the child and parent both allocate their own // viz::LocalSurfaceId the resulting conflict is resolved. TEST_F(RenderWidgetHostViewAuraTest, ConflictingAllocationsResolve) {
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index e870f17..bbc5c8d 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -10880,6 +10880,17 @@ RenderFrameSubmissionObserver observer_c(child_c); RenderFrameSubmissionObserver observer_d(child_d); + // Monitor visual sync messages coming from the mainframe to make sure + // |is_pinch_gesture_active| goes true during the pinch gesture. + scoped_refptr<SynchronizeVisualPropertiesMessageFilter> filter_mainframe = + new SynchronizeVisualPropertiesMessageFilter(); + root->current_frame_host()->GetProcess()->AddFilter(filter_mainframe.get()); + // Monitor frame sync messages coming from child_b as it will need to + // relay them to child_d. + scoped_refptr<SynchronizeVisualPropertiesMessageFilter> filter_child_b = + new SynchronizeVisualPropertiesMessageFilter(); + child_b->current_frame_host()->GetProcess()->AddFilter(filter_child_b.get()); + // We need to observe a root frame submission to pick up the initial page // scale factor. observer_a.WaitForAnyFrameSubmission(); @@ -10923,6 +10934,17 @@ observer_b.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); observer_c.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); observer_d.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); + + // The change in |is_pinch_gesture_active| that signals the end of the pinch + // gesture will occur sometime after the ack for GesturePinchEnd, so we need + // to wait for it from each renderer. If it's never seen, the test fails by + // timing out. + filter_mainframe->WaitForPinchGestureEnd(); + EXPECT_TRUE(filter_mainframe->pinch_gesture_active_set()); + EXPECT_TRUE(filter_mainframe->pinch_gesture_active_cleared()); + filter_child_b->WaitForPinchGestureEnd(); + EXPECT_TRUE(filter_child_b->pinch_gesture_active_set()); + EXPECT_TRUE(filter_child_b->pinch_gesture_active_cleared()); } // Verify that sandbox flags specified by a CSP header are properly inherited by
diff --git a/content/browser/webrtc/OWNERS b/content/browser/webrtc/OWNERS index 4002051..106f113a 100644 --- a/content/browser/webrtc/OWNERS +++ b/content/browser/webrtc/OWNERS
@@ -1,9 +1,12 @@ chfremer@chromium.org emircan@chromium.org guidou@chromium.org -mcasas@chromium.org tommi@chromium.org per-file *test*=phoglund@chromium.org +# Original (legacy) owner. +mcasas@chromium.org + # COMPONENT: Blink>WebRTC +# TEAM: webrtc-dev@chromium.org
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 4784e99..48b2fe1 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -265,6 +265,7 @@ IPC_STRUCT_TRAITS_MEMBER(capture_sequence_number) IPC_STRUCT_TRAITS_MEMBER(zoom_level) IPC_STRUCT_TRAITS_MEMBER(page_scale_factor) + IPC_STRUCT_TRAITS_MEMBER(is_pinch_gesture_active) IPC_STRUCT_TRAITS_MEMBER(local_surface_id_allocation) IPC_STRUCT_TRAITS_END()
diff --git a/content/common/frame_visual_properties.h b/content/common/frame_visual_properties.h index b93180d..c897b9b 100644 --- a/content/common/frame_visual_properties.h +++ b/content/common/frame_visual_properties.h
@@ -44,7 +44,10 @@ // (0 is the default value which results in 1.0 zoom factor.) double zoom_level = 0; + // Tracks the page-scale factor and whether the frame is currently in an + // active pinch-zoom gesture. float page_scale_factor = 1.f; + bool is_pinch_gesture_active = false; // The time at which the viz::LocalSurfaceId used to submit this was // allocated.
diff --git a/content/common/visual_properties.h b/content/common/visual_properties.h index ed6f914..dcccf0b 100644 --- a/content/common/visual_properties.h +++ b/content/common/visual_properties.h
@@ -83,6 +83,10 @@ // This represents the page's scale factor, which changes during pinch zoom. // It needs to be shared with subframes. float page_scale_factor = 1.f; + + // Indicates whether a pinch gesture is currently active. Originates in the + // main frame's renderer, and needs to be shared with subframes. + bool is_pinch_gesture_active = false; }; } // namespace content
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h index 84f6662a..fcda7ced 100644 --- a/content/common/widget_messages.h +++ b/content/common/widget_messages.h
@@ -63,6 +63,7 @@ IPC_STRUCT_TRAITS_MEMBER(capture_sequence_number) IPC_STRUCT_TRAITS_MEMBER(zoom_level) IPC_STRUCT_TRAITS_MEMBER(page_scale_factor) + IPC_STRUCT_TRAITS_MEMBER(is_pinch_gesture_active) IPC_STRUCT_TRAITS_END() // Traits for WebDeviceEmulationParams.
diff --git a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java index 08bd28d..b34a26de 100644 --- a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java +++ b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
@@ -12,7 +12,6 @@ import android.util.SparseArray; import android.view.Surface; -import org.chromium.base.CommandLine; import org.chromium.base.JNIUtils; import org.chromium.base.Log; import org.chromium.base.UnguessableToken; @@ -31,7 +30,6 @@ import org.chromium.content.common.SurfaceWrapper; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.common.ContentProcessInfo; -import org.chromium.content_public.common.ContentSwitches; import java.util.List; @@ -83,7 +81,7 @@ mCpuFeatures = connectionBundle.getLong(ContentChildProcessConstants.EXTRA_CPU_FEATURES); assert mCpuCount > 0; - if (LibraryLoader.useCrazyLinker()) { + if (LibraryLoader.useCrazyLinker() && !LibraryLoader.getInstance().isLoadedByZygote()) { Bundle sharedRelros = connectionBundle.getBundle(Linker.EXTRA_LINKER_SHARED_RELROS); if (sharedRelros != null) { getLinker().useSharedRelros(sharedRelros); @@ -101,13 +99,12 @@ @Override public boolean loadNativeLibrary(Context hostContext) { - String processType = - CommandLine.getInstance().getSwitchValue(ContentSwitches.SWITCH_PROCESS_TYPE); - // Enable selective JNI registration when the process is not the browser process. - if (processType != null) { - JNIUtils.enableSelectiveJniRegistration(); + if (LibraryLoader.getInstance().isLoadedByZygote()) { + return initializeLibrary(); } + JNIUtils.enableSelectiveJniRegistration(); + Linker linker = null; boolean requestedSharedRelro = false; if (LibraryLoader.useCrazyLinker()) { @@ -149,6 +146,11 @@ } LibraryLoader.getInstance().registerRendererProcessHistogram( requestedSharedRelro, loadAtFixedAddressFailed); + + return initializeLibrary(); + } + + private boolean initializeLibrary() { try { LibraryLoader.getInstance().initialize(mLibraryProcessType); } catch (ProcessInitException e) {
diff --git a/content/public/browser/gpu_utils.cc b/content/public/browser/gpu_utils.cc index c4b61f9..8502b82 100644 --- a/content/public/browser/gpu_utils.cc +++ b/content/public/browser/gpu_utils.cc
@@ -115,6 +115,9 @@ gpu_preferences.enable_vulkan = command_line->HasSwitch(switches::kEnableVulkan); + gpu_preferences.disable_vulkan_fallback_to_gl_for_testing = + command_line->HasSwitch(switches::kDisableVulkanFallbackToGLForTesting); + gpu_preferences.enable_gpu_benchmarking_extension = command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking);
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 74a2c98..fc8424e 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -3110,7 +3110,10 @@ : content::BrowserMessageFilter(kMessageClassesToFilter, base::size(kMessageClassesToFilter)), screen_space_rect_run_loop_(std::make_unique<base::RunLoop>()), - screen_space_rect_received_(false) {} + screen_space_rect_received_(false), + pinch_gesture_active_set_(false), + pinch_gesture_active_cleared_(false), + last_pinch_gesture_active_(false) {} void SynchronizeVisualPropertiesMessageFilter::WaitForRect() { screen_space_rect_run_loop_->Run(); @@ -3155,6 +3158,20 @@ void SynchronizeVisualPropertiesMessageFilter::OnSynchronizeVisualProperties( const viz::FrameSinkId& frame_sink_id, const FrameVisualProperties& visual_properties) { + // Monitor |is_pinch_gesture_active| to determine when pinch gestures begin + // and end. + if (visual_properties.is_pinch_gesture_active && + !last_pinch_gesture_active_) { + pinch_gesture_active_set_ = true; + } + if (!visual_properties.is_pinch_gesture_active && + last_pinch_gesture_active_) { + pinch_gesture_active_cleared_ = true; + if (pinch_end_run_loop_) + pinch_end_run_loop_->Quit(); + } + last_pinch_gesture_active_ = visual_properties.is_pinch_gesture_active; + gfx::Rect screen_space_rect_in_dip = visual_properties.screen_space_rect; if (IsUseZoomForDSFEnabled()) { screen_space_rect_in_dip = @@ -3236,6 +3253,14 @@ return false; } +void SynchronizeVisualPropertiesMessageFilter::WaitForPinchGestureEnd() { + if (pinch_gesture_active_cleared_) + return; + DCHECK(!pinch_end_run_loop_); + pinch_end_run_loop_ = std::make_unique<base::RunLoop>(); + pinch_end_run_loop_->Run(); +} + RenderWidgetHostMouseEventMonitor::RenderWidgetHostMouseEventMonitor( RenderWidgetHost* host) : host_(host), event_received_(false) {
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 7c11f9c..69c48d8 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -1574,6 +1574,7 @@ // BrowserPluginHostMsg_SynchronizeVisualProperties messages. This allows the // message to continue to the target child so that processing can be verified by // tests. +// It also monitors for GesturePinchBegin/End events. class SynchronizeVisualPropertiesMessageFilter : public content::BrowserMessageFilter { public: @@ -1592,6 +1593,11 @@ // Waits for the next viz::LocalSurfaceId be received and returns it. viz::LocalSurfaceId WaitForSurfaceId(); + bool pinch_gesture_active_set() { return pinch_gesture_active_set_; } + bool pinch_gesture_active_cleared() { return pinch_gesture_active_cleared_; } + + void WaitForPinchGestureEnd(); + protected: ~SynchronizeVisualPropertiesMessageFilter() override; @@ -1623,6 +1629,11 @@ viz::LocalSurfaceId last_surface_id_; std::unique_ptr<base::RunLoop> surface_id_run_loop_; + bool pinch_gesture_active_set_; + bool pinch_gesture_active_cleared_; + bool last_pinch_gesture_active_; + std::unique_ptr<base::RunLoop> pinch_end_run_loop_; + DISALLOW_COPY_AND_ASSIGN(SynchronizeVisualPropertiesMessageFilter); };
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 56819fa5..9512126 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -73,9 +73,6 @@ "crash_helpers.h", "cursor_utils.cc", "cursor_utils.h", - "devtools/render_widget_screen_metrics_emulator.cc", - "devtools/render_widget_screen_metrics_emulator.h", - "devtools/render_widget_screen_metrics_emulator_delegate.h", "dom_automation_controller.cc", "dom_automation_controller.h", "dom_storage/dom_storage_cached_area.cc", @@ -468,6 +465,9 @@ "render_widget_delegate.h", "render_widget_mouse_lock_dispatcher.cc", "render_widget_mouse_lock_dispatcher.h", + "render_widget_screen_metrics_emulator.cc", + "render_widget_screen_metrics_emulator.h", + "render_widget_screen_metrics_emulator_delegate.h", "renderer_blink_platform_impl.cc", "renderer_blink_platform_impl.h", "renderer_main.cc",
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc index fda424e7..9c016e3 100644 --- a/content/renderer/child_frame_compositing_helper.cc +++ b/content/renderer/child_frame_compositing_helper.cc
@@ -78,8 +78,10 @@ void ChildFrameCompositingHelper::UpdateVisibility(bool visible) { cc::Layer* layer = child_frame_compositor_->GetLayer(); - if (layer) + if (layer) { layer->SetIsDrawable(visible); + layer->SetHitTestable(visible); + } } gfx::Rect ChildFrameCompositingHelper::PaintableRegion() {
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc index 5f163f8..6d7e1f34 100644 --- a/content/renderer/compositor/layer_tree_view.cc +++ b/content/renderer/compositor/layer_tree_view.cc
@@ -425,8 +425,11 @@ layer_tree_host_->SetRasterColorSpace(color_space); } -void LayerTreeView::SetExternalPageScaleFactor(float page_scale_factor) { - layer_tree_host_->SetExternalPageScaleFactor(page_scale_factor); +void LayerTreeView::SetExternalPageScaleFactor( + float page_scale_factor, + bool is_external_pinch_gesture_active) { + layer_tree_host_->SetExternalPageScaleFactor( + page_scale_factor, is_external_pinch_gesture_active); } void LayerTreeView::ClearCachesOnNextCommit() {
diff --git a/content/renderer/compositor/layer_tree_view.h b/content/renderer/compositor/layer_tree_view.h index 7b0aac53..a477847 100644 --- a/content/renderer/compositor/layer_tree_view.h +++ b/content/renderer/compositor/layer_tree_view.h
@@ -107,7 +107,8 @@ bool SendMessageToMicroBenchmark(int id, std::unique_ptr<base::Value> value); void SetFrameSinkId(const viz::FrameSinkId& frame_sink_id); void SetRasterColorSpace(const gfx::ColorSpace& color_space); - void SetExternalPageScaleFactor(float page_scale_factor); + void SetExternalPageScaleFactor(float page_scale_factor, + bool is_external_pinch_gesture_active); void ClearCachesOnNextCommit(); void SetContentSourceId(uint32_t source_id); void SetViewportSizeAndScale(
diff --git a/content/renderer/devtools/OWNERS b/content/renderer/devtools/OWNERS deleted file mode 100644 index a0d7d1d59..0000000 --- a/content/renderer/devtools/OWNERS +++ /dev/null
@@ -1,4 +0,0 @@ -alph@chromium.org -dgozman@chromium.org - -# COMPONENT: Platform>DevTools
diff --git a/content/renderer/image_capture/OWNERS b/content/renderer/image_capture/OWNERS index 57aa41f..ab8e7ba 100644 --- a/content/renderer/image_capture/OWNERS +++ b/content/renderer/image_capture/OWNERS
@@ -1,5 +1,7 @@ -mcasas@chromium.org reillyg@chromium.org +# Original (legacy) owner. +mcasas@chromium.org + # COMPONENT: Blink>ImageCapture -# TEAM: media-dev@chromium.org +# TEAM: webrtc-dev@chromium.org
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc index 0c76af8..e192902 100644 --- a/content/renderer/input/render_widget_input_handler.cc +++ b/content/renderer/input/render_widget_input_handler.cc
@@ -192,8 +192,11 @@ viz::FrameSinkId GetRemoteFrameSinkId(const blink::WebNode& node) { blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(node); if (result_frame && result_frame->IsWebRemoteFrame()) { - return RenderFrameProxy::FromWebFrame(result_frame->ToWebRemoteFrame()) - ->frame_sink_id(); + blink::WebRemoteFrame* remote_frame = result_frame->ToWebRemoteFrame(); + if (remote_frame->IsIgnoredForHitTest()) + return viz::FrameSinkId(); + + return RenderFrameProxy::FromWebFrame(remote_frame)->frame_sink_id(); } auto* plugin = BrowserPlugin::GetFromNode(node); return plugin ? plugin->frame_sink_id() : viz::FrameSinkId();
diff --git a/content/renderer/media/stream/OWNERS b/content/renderer/media/stream/OWNERS index c205d4f9..32889cc 100644 --- a/content/renderer/media/stream/OWNERS +++ b/content/renderer/media/stream/OWNERS
@@ -2,5 +2,5 @@ per-file media_stream_audio_processor*=aluebs@chromium.org -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>GetUserMedia
diff --git a/content/renderer/media/webrtc/mock_data_channel_impl.cc b/content/renderer/media/webrtc/mock_data_channel_impl.cc index 5cdf70cc..6f4e886c1 100644 --- a/content/renderer/media/webrtc/mock_data_channel_impl.cc +++ b/content/renderer/media/webrtc/mock_data_channel_impl.cc
@@ -35,11 +35,15 @@ bool MockDataChannel::ordered() const { return config_.ordered; } uint16_t MockDataChannel::maxRetransmitTime() const { - return config_.maxRetransmitTime; + // TODO(https://bugs.chromium.org/854385): Restore when change landed. + // return config_.maxRetransmitTime; + return -1; } uint16_t MockDataChannel::maxRetransmits() const { - return config_.maxRetransmits; + // TODO(https://bugs.chromium.org/854385): Restore when change landed. + // return config_.maxRetransmits; + return -1; } std::string MockDataChannel::protocol() const { return config_.protocol; }
diff --git a/content/renderer/media_capture_from_element/OWNERS b/content/renderer/media_capture_from_element/OWNERS index 446f8fb0..d176cccc 100644 --- a/content/renderer/media_capture_from_element/OWNERS +++ b/content/renderer/media_capture_from_element/OWNERS
@@ -1,4 +1,7 @@ emircan@chromium.org + +# Original (legacy) owner. mcasas@chromium.org # COMPONENT: Blink>MediaStream>CaptureFromElement +# TEAM: webrtc-dev@chromium.org
diff --git a/content/renderer/media_recorder/OWNERS b/content/renderer/media_recorder/OWNERS index 6675929..c6eb0c4 100644 --- a/content/renderer/media_recorder/OWNERS +++ b/content/renderer/media_recorder/OWNERS
@@ -1,5 +1,7 @@ emircan@chromium.org + +# Original (legacy) owner. mcasas@chromium.org # COMPONENT: Blink>MediaRecording -# TEAM: media-dev@chromium.org +# TEAM: webrtc-dev@chromium.org
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 75479724..c6418073 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1454,11 +1454,10 @@ replicated_state.unique_name); web_frame = parent_web_frame->CreateLocalChild( replicated_state.scope, WebString::FromUTF8(replicated_state.name), - replicated_state.frame_policy.sandbox_flags, render_frame, + replicated_state.frame_policy, render_frame, render_frame->blink_interface_registry_.get(), document_interface_broker_blink.PassInterface().PassHandle(), previous_sibling_web_frame, - replicated_state.frame_policy.container_policy, ConvertFrameOwnerPropertiesToWebFrameOwnerProperties( frame_owner_properties), replicated_state.frame_owner_element_type, @@ -1494,8 +1493,7 @@ web_frame = blink::WebLocalFrame::CreateProvisional( render_frame, render_frame->blink_interface_registry_.get(), document_interface_broker_blink.PassInterface().PassHandle(), - proxy->web_frame(), replicated_state.frame_policy.sandbox_flags, - replicated_state.frame_policy.container_policy); + proxy->web_frame(), replicated_state.frame_policy); // The new |web_frame| is a main frame iff the proxy's frame was. DCHECK_EQ(proxy_is_main_frame, !web_frame->Parent()); } @@ -2697,8 +2695,7 @@ void RenderFrameImpl::OnDidUpdateFramePolicy( const blink::FramePolicy& frame_policy) { - frame_->SetFrameOwnerPolicy(frame_policy.sandbox_flags, - frame_policy.container_policy); + frame_->SetFrameOwnerPolicy(frame_policy); } void RenderFrameImpl::OnSetFrameOwnerProperties( @@ -4193,8 +4190,7 @@ blink::WebTreeScopeType scope, const blink::WebString& name, const blink::WebString& fallback_name, - blink::WebSandboxFlags sandbox_flags, - const blink::ParsedFeaturePolicy& container_policy, + const blink::FramePolicy& frame_policy, const blink::WebFrameOwnerProperties& frame_owner_properties, blink::FrameOwnerElementType frame_owner_element_type) { DCHECK_EQ(frame_, parent); @@ -4227,7 +4223,7 @@ params.frame_unique_name = unique_name_helper_.GenerateNameForNewChildFrame( params.frame_name.empty() ? fallback_name.Utf8() : params.frame_name, params.is_created_by_script); - params.frame_policy = {sandbox_flags, container_policy}; + params.frame_policy = frame_policy; params.frame_owner_properties = ConvertWebFrameOwnerPropertiesToFrameOwnerProperties( frame_owner_properties); @@ -4437,11 +4433,10 @@ void RenderFrameImpl::DidChangeFramePolicy( blink::WebFrame* child_frame, - blink::WebSandboxFlags flags, - const blink::ParsedFeaturePolicy& container_policy) { + const blink::FramePolicy& frame_policy) { Send(new FrameHostMsg_DidChangeFramePolicy( routing_id_, RenderFrame::GetRoutingIdForWebFrame(child_frame), - {flags, container_policy})); + frame_policy)); } void RenderFrameImpl::DidSetFramePolicyHeaders(
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 1f6e37c..a12dfe6 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -695,8 +695,7 @@ blink::WebTreeScopeType scope, const blink::WebString& name, const blink::WebString& fallback_name, - blink::WebSandboxFlags sandbox_flags, - const blink::ParsedFeaturePolicy& container_policy, + const blink::FramePolicy& frame_policy, const blink::WebFrameOwnerProperties& frame_owner_properties, blink::FrameOwnerElementType frame_owner_element_type) override; std::pair<blink::WebRemoteFrame*, base::UnguessableToken> CreatePortal( @@ -712,10 +711,8 @@ blink::WebInsecureRequestPolicy policy) override; void DidEnforceInsecureNavigationsSet( const std::vector<uint32_t>& set) override; - void DidChangeFramePolicy( - blink::WebFrame* child_frame, - blink::WebSandboxFlags flags, - const blink::ParsedFeaturePolicy& container_policy) override; + void DidChangeFramePolicy(blink::WebFrame* child_frame, + const blink::FramePolicy& frame_policy) override; void DidSetFramePolicyHeaders( blink::WebSandboxFlags flags, const blink::ParsedFeaturePolicy& parsed_header) override;
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index d4e8c3f0..ea8f000 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -154,8 +154,7 @@ web_frame = parent->web_frame()->CreateRemoteChild( replicated_state.scope, blink::WebString::FromUTF8(replicated_state.name), - replicated_state.frame_policy.sandbox_flags, - replicated_state.frame_policy.container_policy, + replicated_state.frame_policy, replicated_state.frame_owner_element_type, proxy.get(), opener); proxy->unique_name_ = replicated_state.unique_name; render_view = parent->render_view(); @@ -311,8 +310,10 @@ SynchronizeVisualProperties(); } -void RenderFrameProxy::OnPageScaleFactorChanged(float page_scale_factor) { +void RenderFrameProxy::OnPageScaleFactorChanged(float page_scale_factor, + bool is_pinch_gesture_active) { pending_visual_properties_.page_scale_factor = page_scale_factor; + pending_visual_properties_.is_pinch_gesture_active = is_pinch_gesture_active; SynchronizeVisualProperties(); } @@ -382,8 +383,7 @@ void RenderFrameProxy::OnDidUpdateFramePolicy( const blink::FramePolicy& frame_policy) { DCHECK(web_frame()->Parent()); - web_frame_->SetFrameOwnerPolicy(frame_policy.sandbox_flags, - frame_policy.container_policy); + web_frame_->SetFrameOwnerPolicy(frame_policy); } // Update the proxy's SecurityContext with new sandbox flags or feature policy @@ -687,6 +687,8 @@ pending_visual_properties_.zoom_level || sent_visual_properties_->page_scale_factor != pending_visual_properties_.page_scale_factor || + sent_visual_properties_->is_pinch_gesture_active != + pending_visual_properties_.is_pinch_gesture_active || capture_sequence_number_changed; if (synchronized_props_changed) {
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index 947c70a..bebf7d1 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -145,8 +145,9 @@ void OnZoomLevelChanged(double zoom_level); // Out-of-process child frames receive a signal from RenderWidget when the - // page scale factor has changed. - void OnPageScaleFactorChanged(float page_scale_factor); + // page scale factor has changed, and/or a pinch-zoom gesture starts/ends. + void OnPageScaleFactorChanged(float page_scale_factor, + bool is_pinch_gesture_active); // Invoked by RenderWidget when a new capture sequence number was set, // indicating that surfaces should be synchronized. @@ -229,6 +230,10 @@ void WasEvicted(); + bool is_pinch_gesture_active_for_testing() { + return pending_visual_properties_.is_pinch_gesture_active; + } + private: RenderFrameProxy(int routing_id);
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 0ff9552..3bb88dc9 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -548,6 +548,54 @@ } }; +TEST_F(RenderViewImplTest, IsPinchGestureActivePropagatesToProxies) { + LoadHTML( + "<body style='min-height:1000px;'>" + " <iframe src='data:text/html,frame 1'></iframe>" + " <iframe src='data:text/html,frame 2'></iframe>" + "</body>"); + + // Verify child's proxy doesn't think we're pinching. + blink::WebFrame* root_web_frame = frame()->GetWebFrame(); + ASSERT_TRUE(root_web_frame->FirstChild()->IsWebLocalFrame()); + TestRenderFrame* child_frame_1 = + static_cast<TestRenderFrame*>(RenderFrame::FromWebFrame( + root_web_frame->FirstChild()->ToWebLocalFrame())); + ASSERT_TRUE(child_frame_1); + TestRenderFrame* child_frame_2 = + static_cast<TestRenderFrame*>(RenderFrame::FromWebFrame( + root_web_frame->FirstChild()->NextSibling()->ToWebLocalFrame())); + ASSERT_TRUE(child_frame_2); + child_frame_1->SwapOut(kProxyRoutingId, true, + ReconstructReplicationStateForTesting(child_frame_1)); + EXPECT_TRUE(root_web_frame->FirstChild()->IsWebRemoteFrame()); + RenderFrameProxy* child_proxy_1 = RenderFrameProxy::FromWebFrame( + root_web_frame->FirstChild()->ToWebRemoteFrame()); + ASSERT_TRUE(child_proxy_1); + EXPECT_FALSE(child_proxy_1->is_pinch_gesture_active_for_testing()); + + // Set the |is_pinch_gesture_active| flag. + view()->PageScaleFactorChanged(1.f, true); + EXPECT_TRUE(child_proxy_1->is_pinch_gesture_active_for_testing()); + + // Create a new remote child, and get its proxy. Swapping out will force + // creation and registering of a new RenderFrameProxy, which should pick up + // the existing setting. + child_frame_2->SwapOut(kProxyRoutingId + 1, true, + ReconstructReplicationStateForTesting(child_frame_2)); + EXPECT_TRUE(root_web_frame->FirstChild()->NextSibling()->IsWebRemoteFrame()); + RenderFrameProxy* child_proxy_2 = RenderFrameProxy::FromWebFrame( + root_web_frame->FirstChild()->NextSibling()->ToWebRemoteFrame()); + + // Verify new child has the flag too. + EXPECT_TRUE(child_proxy_2->is_pinch_gesture_active_for_testing()); + + // Reset the flag, make sure both children respond. + view()->PageScaleFactorChanged(1.f, false); + EXPECT_FALSE(child_proxy_1->is_pinch_gesture_active_for_testing()); + EXPECT_FALSE(child_proxy_2->is_pinch_gesture_active_for_testing()); +} + // Test that we get form state change notifications when input fields change. TEST_F(RenderViewImplTest, OnNavStateChanged) { view()->set_send_content_state_immediately(true);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 9fb5ae6..4d3da78 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -57,7 +57,6 @@ #include "content/renderer/browser_plugin/browser_plugin.h" #include "content/renderer/compositor/layer_tree_view.h" #include "content/renderer/cursor_utils.h" -#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h" #include "content/renderer/drop_data_builder.h" #include "content/renderer/external_popup_menu.h" #include "content/renderer/frame_swap_message_queue.h" @@ -72,6 +71,7 @@ #include "content/renderer/render_process.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" +#include "content/renderer/render_widget_screen_metrics_emulator.h" #include "content/renderer/renderer_blink_platform_impl.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "ipc/ipc_message_start.h" @@ -860,10 +860,18 @@ // the visual properties here. While blink doesn't need to know this // page scale factor outside the main frame, the compositor does in // order to produce its output at the correct scale. - layer_tree_view_->SetExternalPageScaleFactor(params.page_scale_factor); + layer_tree_view_->SetExternalPageScaleFactor( + params.page_scale_factor, params.is_pinch_gesture_active); // Store the value to give to any new RenderFrameProxy that is // registered. page_scale_factor_from_mainframe_ = params.page_scale_factor; + // Similarly, only the main frame knows when a pinch gesture is active, + // but this information is needed in subframes so they can throttle + // re-rastering in the same manner as the main frame. + // |is_pinch_gesture_active| follows the same path to the subframe + // compositor(s) as |page_scale_factor|. + is_pinch_gesture_active_from_mainframe_ = + params.is_pinch_gesture_active; // Push the page scale factor down to any child RenderWidgets via our // child proxy frames. // TODO(danakj): This ends up setting the page scale factor in the @@ -872,8 +880,10 @@ // global value per-page, we could instead store it once in the browser // (such as in RenderViewHost) and distribute it to each frame-hosted // RenderWidget from there. - for (auto& child_proxy : render_frame_proxies_) - child_proxy.OnPageScaleFactorChanged(params.page_scale_factor); + for (auto& child_proxy : render_frame_proxies_) { + child_proxy.OnPageScaleFactorChanged(params.page_scale_factor, + params.is_pinch_gesture_active); + } } gfx::Size old_visible_viewport_size = visible_viewport_size_; @@ -3440,7 +3450,8 @@ // frame trees). A new RenderFrameProxy means there is a new child // RenderWidget in another frame tree. In order for it to hear about // the page scale factor we pass along the last seen value here. - proxy->OnPageScaleFactorChanged(page_scale_factor_from_mainframe_); + proxy->OnPageScaleFactorChanged(page_scale_factor_from_mainframe_, + is_pinch_gesture_active_from_mainframe_); } void RenderWidget::UnregisterRenderFrameProxy(RenderFrameProxy* proxy) { @@ -3587,21 +3598,16 @@ // of which will be via proxy child frame). These will each in turn forward // the message to their child RenderWidgets (through their proxy child // frames). - // TODO(crbug.com/924336): This value is continuously propagated during a - // pinch-zoom, causing the child RenderWidgets to re-raster, while the main - // frame is able to throttle re-raster to powers of 2. We could find some way - // to throttle child RenderWidgets also, perhaps by informing them when the - // pinch-zoom gesture is started and stopped. DCHECK(!is_frozen_); DCHECK(delegate()); - // TODO(wjmaclean): In the next CL, plumb |is_pinch_gesture_active| into the - // observer via observer.OnPageScaleFactorChanged() and allow it to trigger - // SynchronizeVisualProperties if needed. - for (auto& observer : render_frame_proxies_) - observer.OnPageScaleFactorChanged(page_scale_factor); + for (auto& observer : render_frame_proxies_) { + observer.OnPageScaleFactorChanged(page_scale_factor, + is_pinch_gesture_active); + } // Store the value to give to any new RenderFrameProxy that is registered. page_scale_factor_from_mainframe_ = page_scale_factor; + is_pinch_gesture_active_from_mainframe_ = is_pinch_gesture_active; } void RenderWidget::UseSynchronousResizeModeForTesting(bool enable) {
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index d0fd4036..34ce2a6 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -39,13 +39,13 @@ #include "content/public/common/drop_data.h" #include "content/public/common/screen_info.h" #include "content/renderer/compositor/layer_tree_view_delegate.h" -#include "content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h" #include "content/renderer/input/main_thread_event_queue.h" #include "content/renderer/input/render_widget_input_handler.h" #include "content/renderer/input/render_widget_input_handler_delegate.h" #include "content/renderer/mouse_lock_dispatcher.h" #include "content/renderer/render_widget_delegate.h" #include "content/renderer/render_widget_mouse_lock_dispatcher.h" +#include "content/renderer/render_widget_screen_metrics_emulator_delegate.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" #include "ipc/ipc_sender.h" @@ -1136,10 +1136,11 @@ // The height of the browser bottom controls. float bottom_controls_height_ = 0.f; - // The last seen page scale factor, which comes from the main frame and is - // propagated through the RenderWidget tree. This value is passed to any new + // The last seen page scale state, which comes from the main frame and is + // propagated through the RenderWidget tree. This state is passed to any new // child RenderWidget. float page_scale_factor_from_mainframe_ = 1.f; + bool is_pinch_gesture_active_from_mainframe_ = false; // This is initialized to zero and is incremented on each non-same-page // navigation commit by RenderFrameImpl. At that time it is sent to the
diff --git a/content/renderer/render_widget_delegate.h b/content/renderer/render_widget_delegate.h index 4052e67..1252e15 100644 --- a/content/renderer/render_widget_delegate.h +++ b/content/renderer/render_widget_delegate.h
@@ -11,6 +11,7 @@ class WebMouseEvent; class WebWidget; class WebWidgetClient; +struct WebDeviceEmulationParams; } // namespace blink namespace content {
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc index d24067e..ebcba1e 100644 --- a/content/renderer/render_widget_fullscreen_pepper.cc +++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -345,6 +345,7 @@ } UpdateLayerBounds(); layer_->SetIsDrawable(true); + layer_->SetHitTestable(true); layer_tree_view()->SetNonBlinkManagedRootLayer(layer_); }
diff --git a/content/renderer/devtools/render_widget_screen_metrics_emulator.cc b/content/renderer/render_widget_screen_metrics_emulator.cc similarity index 97% rename from content/renderer/devtools/render_widget_screen_metrics_emulator.cc rename to content/renderer/render_widget_screen_metrics_emulator.cc index 6c60733..29d798d 100644 --- a/content/renderer/devtools/render_widget_screen_metrics_emulator.cc +++ b/content/renderer/render_widget_screen_metrics_emulator.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h" +#include "content/renderer/render_widget_screen_metrics_emulator.h" #include "content/common/visual_properties.h" #include "content/public/common/context_menu_params.h" -#include "content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h" +#include "content/renderer/render_widget_screen_metrics_emulator_delegate.h" namespace content {
diff --git a/content/renderer/devtools/render_widget_screen_metrics_emulator.h b/content/renderer/render_widget_screen_metrics_emulator.h similarity index 92% rename from content/renderer/devtools/render_widget_screen_metrics_emulator.h rename to content/renderer/render_widget_screen_metrics_emulator.h index 287ccbc2..4a98f3e 100644 --- a/content/renderer/devtools/render_widget_screen_metrics_emulator.h +++ b/content/renderer/render_widget_screen_metrics_emulator.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 CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_ -#define CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_ +#ifndef CONTENT_RENDERER_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_ +#define CONTENT_RENDERER_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_ #include <memory> @@ -83,4 +83,4 @@ } // namespace content -#endif // CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_ +#endif // CONTENT_RENDERER_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_
diff --git a/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h b/content/renderer/render_widget_screen_metrics_emulator_delegate.h similarity index 82% rename from content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h rename to content/renderer/render_widget_screen_metrics_emulator_delegate.h index fdaadb8..6d94586c 100644 --- a/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h +++ b/content/renderer/render_widget_screen_metrics_emulator_delegate.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 CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_ -#define CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_ +#ifndef CONTENT_RENDERER_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_ +#define CONTENT_RENDERER_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_ #include "content/common/content_export.h" @@ -39,4 +39,4 @@ } // namespace content -#endif // CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_ +#endif // CONTENT_RENDERER_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index 023f4ede..2454bc48 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -15,11 +15,13 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" +#include "base/unguessable_token.h" #include "build/build_config.h" #include "cc/layers/solid_color_layer.h" #include "cc/trees/layer_tree_host.h" #include "components/viz/common/features.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "content/common/frame_replication_state.h" #include "content/common/input/input_handler.mojom.h" #include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/input_messages.h" @@ -29,9 +31,10 @@ #include "content/public/common/content_features.h" #include "content/public/test/mock_render_thread.h" #include "content/renderer/compositor/layer_tree_view.h" -#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h" #include "content/renderer/input/widget_input_handler_manager.h" +#include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_widget_delegate.h" +#include "content/renderer/render_widget_screen_metrics_emulator.h" #include "content/test/fake_compositor_dependencies.h" #include "content/test/mock_render_process.h" #include "ipc/ipc_test_sink.h" @@ -551,6 +554,41 @@ const blink::WebDeviceEmulationParams& params) override {} }; +// Tests that the value of VisualProperties::is_pinch_gesture_active is +// propagated to the LayerTreeHost when properties are synced, but only for +// subframe widgets. +TEST_F(RenderWidgetUnittest, ActivePinchGestureUpdatesLayerTreeHost) { + auto* layer_tree_host = widget()->layer_tree_view()->layer_tree_host(); + EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing()); + content::VisualProperties visual_properties; + + // Sync visual properties on a child RenderWidget. + visual_properties.is_pinch_gesture_active = true; + widget()->OnSynchronizeVisualProperties(visual_properties); + // We expect the |is_pinch_gesture_active| value to propagate to the + // LayerTreeHost for sub-frames. Since GesturePinch events are handled + // directly in the main-frame's layer tree (and only there), information about + // whether or not we're in a pinch gesture must be communicated separately to + // sub-frame layer trees, via SynchronizeVisualProperties. This information + // is required to allow sub-frame compositors to throttle rastering while + // pinch gestures are active. + EXPECT_TRUE(layer_tree_host->is_external_pinch_gesture_active_for_testing()); + visual_properties.is_pinch_gesture_active = false; + widget()->OnSynchronizeVisualProperties(visual_properties); + EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing()); + + // Repeat with a 'mainframe' widget. + widget()->set_delegate(std::make_unique<StubRenderWidgetDelegate>()); + visual_properties.is_pinch_gesture_active = true; + widget()->OnSynchronizeVisualProperties(visual_properties); + // We do not expect the |is_pinch_gesture_active| value to propagate to the + // LayerTreeHost for the main-frame. Since GesturePinch events are handled + // directly by the layer tree for the main frame, it already knows whether or + // not a pinch gesture is active, and so we shouldn't propagate this + // information to the layer tree for a main-frame's widget. + EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing()); +} + TEST_F(RenderWidgetPopupUnittest, EmulatingPopupRect) { blink::WebRect popup_screen_rect(200, 250, 100, 400); widget()->SetWindowRect(popup_screen_rect);
diff --git a/content/shell/test_runner/web_ax_object_proxy.cc b/content/shell/test_runner/web_ax_object_proxy.cc index 8cebe74..5298659f 100644 --- a/content/shell/test_runner/web_ax_object_proxy.cc +++ b/content/shell/test_runner/web_ax_object_proxy.cc
@@ -742,7 +742,6 @@ &WebAXObjectProxy::AriaFlowToElementAtIndex) .SetMethod("ariaOwnsElementAtIndex", &WebAXObjectProxy::AriaOwnsElementAtIndex) - .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex) .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange) .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex) .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint) @@ -1486,17 +1485,6 @@ return collector.attributes(); } -int WebAXObjectProxy::LineForIndex(int index) { - accessibility_object_.UpdateLayoutAndCheckValidity(); - blink::WebVector<int> line_breaks; - accessibility_object_.LineBreaks(line_breaks); - int line = 0; - int vector_size = static_cast<int>(line_breaks.size()); - while (line < vector_size && line_breaks[line] <= index) - line++; - return line; -} - std::string WebAXObjectProxy::BoundsForRange(int start, int end) { accessibility_object_.UpdateLayoutAndCheckValidity(); if (accessibility_object_.Role() != ax::mojom::Role::kStaticText)
diff --git a/content/shell/test_runner/web_ax_object_proxy.h b/content/shell/test_runner/web_ax_object_proxy.h index dfa1494..da30a01b 100644 --- a/content/shell/test_runner/web_ax_object_proxy.h +++ b/content/shell/test_runner/web_ax_object_proxy.h
@@ -158,7 +158,6 @@ v8::Local<v8::Object> AriaOwnsElementAtIndex(unsigned index); std::string AllAttributes(); std::string AttributesOfChildren(); - int LineForIndex(int index); std::string BoundsForRange(int start, int end); v8::Local<v8::Object> ChildAtIndex(int index); v8::Local<v8::Object> ElementAtPoint(int x, int y);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 3eb36ce..eb8cce8c 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -394,7 +394,6 @@ "//third_party/webrtc/api:rtc_stats_api", "//third_party/webrtc/api:scoped_refptr", "//third_party/webrtc/media:rtc_media_base", - "//third_party/webrtc/modules/video_capture", "//third_party/webrtc/pc:libjingle_peerconnection", "//third_party/webrtc/rtc_base:rtc_base_approved", "//third_party/webrtc/stats:rtc_stats", @@ -2018,7 +2017,6 @@ "//third_party/webrtc/media:rtc_media", "//third_party/webrtc/media:rtc_vp9_profile", "//third_party/webrtc/modules/desktop_capture:primitives", - "//third_party/webrtc/modules/video_capture", "//third_party/webrtc/modules/video_coding:video_codec_interface", "//third_party/webrtc/pc:libjingle_peerconnection", "//third_party/webrtc/rtc_base:ip_address",
diff --git a/content/test/data/frame_tree/page_with_ancestor_masked_iframe.html b/content/test/data/frame_tree/page_with_ancestor_masked_iframe.html index 6331a6f..d9faa98 100644 --- a/content/test/data/frame_tree/page_with_ancestor_masked_iframe.html +++ b/content/test/data/frame_tree/page_with_ancestor_masked_iframe.html
@@ -20,6 +20,7 @@ width: 200px; height: 200px; border: none; + opacity: 0.5; } </style> </head>
diff --git a/docs/gpu/gpu_testing_bot_details.md b/docs/gpu/gpu_testing_bot_details.md index b2b5317..853cf6c 100644 --- a/docs/gpu/gpu_testing_bot_details.md +++ b/docs/gpu/gpu_testing_bot_details.md
@@ -535,63 +535,55 @@ [go/chromecals]: http://go/chromecals -### How to add a new "optional" try bot +### How to add a new try bot that runs a subset of tests or extra tests -TODO(kbr): the naming of the "optional" try bots is confusing and -unfortunate. They should probably be renamed to something like "extratests" or -"extra_tests", so perhaps a new naming convention of "gpu_win_extratests_rel" or -"win_gpu_extratests_rel". Unfortunately making this change at this point -requires touching tons of files across many workspaces and is unlikely to happen -unless someone highly motivated wants to pick up the task. +Several projects (ANGLE, Dawn) run custom tests using the Chromium recipes. They +use try bot bot configs that run subsets of Chromium or additional slower tests +that can't be run on the main CQ. -The "optional" GPU try bots are a concession to the reality that there are some -long-running GPU test suites that simply can not run against every Chromium CL. -They run some additional tests that are usually run only on the -chromium.gpu.fyi waterfall. Some of these tests, like the WebGL 2.0 conformance -suite, are intended to be run on the normal try bots once hardware capacity is -available. Some are not intended to ever run on the normal try bots. +These try bots are a little different because they mirror waterfall bots that +don't actually exist. The waterfall bots' specifications exist only to tell +these try bots which tests to run. -The optional try bots are a little different because they mirror waterfall bots -that don't actually exist. The waterfall bots' specifications exist only to -tell the optional try bots which tests to run. +Let's say that you intended to add a new such custom try bot on Windows. Call it +`win-myproject-rel` for example. You will need to add a "fake" mirror bot for +each GPU family the tests you will need to run. For a GPU type of +"CoolNewGPUType" in this example you could add a "fake" bot named "MyProject GPU +Win10 Release (CoolNewGPUType)". -Let's say that you intended to add a new such optional try bot on Windows. Call -it `win_new_optional_tests_rel` for example. Now, if you wanted to just add -this GPU type to the existing `win_optional_gpu_tests_rel` try bot, you'd -just follow the instructions above -([How to start running tests on a new GPU type on an existing try bot](#How-to-start-running-tests-on-a-new-GPU-type-on-an-existing-try-bot)). The steps below describe how to spin up -an entire new optional try bot. - +1. Allocate new virtual machines for the bots as described in [How to set up + new virtual machine + instances](#How-to-set-up-new-virtual-machine-instances). 1. Make sure that you have some swarming capacity for the new GPU type. Since it's not running against all Chromium CLs you don't need the recommended 30 minimum bots, though ~10 would be good. -1. Create a CL in the Chromium workspace: - 1. Add your new bot (for example, "Optional Win7 Release +1. Create a CL in the Chromium workspace the does the following. Here's an + [example CL](https://crrev.com/c/1554296). + 1. Add your new bot (for example, "MyProject GPU Win10 Release (CoolNewGPUType)") to the chromium.gpu.fyi waterfall in - [waterfalls.pyl]. (Note, this is a bad example: the - "optional" bots have special semantics in this script. You'd probably - want to define some new category of bot if you didn't intend to add - this to `win_optional_gpu_tests_rel`.) - 1. Re-run the script to regenerate the JSON files. -1. Land the above CL. -1. Create a CL in the tools/build workspace: - 1. Modify `masters/master.tryserver.chromium.win`'s [master.cfg] and - [slaves.cfg] to add the new tryserver. Follow the pattern for the - existing `win_optional_gpu_tests_rel` tryserver. Namely, add the new - entry to master.cfg, and add the new tryserver to the - `optional_builders` list in `slaves.cfg`. - 1. Modify [`chromium_gpu_fyi.py`][chromium_gpu_fyi.py] to add the new - "Optional Win7 Release (CoolNewGPUType)" entry. - 1. Modify [`trybots.py`][trybots.py] to add - the new `win_new_optional_tests_rel` try bot, mirroring "Optional - Win7 Release (CoolNewGPUType)". -1. Land the above CL and request an off-hours restart of the - tryserver.chromium.win waterfall. -1. Now you can send CLs to the new bot with: - `git cl try -m tryserver.chromium.win -b win_new_optional_tests_rel` - -[master.cfg]: https://chromium.googlesource.com/chromium/tools/build/+/master/masters/master.tryserver.chromium.win/master.cfg -[slaves.cfg]: https://chromium.googlesource.com/chromium/tools/build/+/master/masters/master.tryserver.chromium.win/slaves.cfg + [waterfalls.pyl]. + 1. Re-run [`src/testing/buildbot/generate_buildbot_json.py`][generate_buildbot_json.py] to regenerate the JSON files. + 1. Update [`cr-buildbucket.cfg`][cr-buildbucket.cfg] to add `win-myproject-rel`. + 1. Update [`luci-milo.cfg`][luci-milo.cfg] to include `win-myproject-rel`. + 1. Update [`luci-scheduler.cfg`][luci-scheduler.cfg] to include "MyProject GPU Win10 Release + (CoolNewGPUType)". + 1. Update [`src/tools/mb/mb_config.pyl`][mb_config.pyl] to include `win-myproject-rel`. + 1. Also add your fake bot to [`src/testing/buildbot/generate_buildbot_json.py`][generate_buildbot_json.py] in the list of `get_bots_that_do_not_actually_exist` section. +1. *After* the Chromium-side CL lands and the bot is on the console, create a CL + in the [`tools/build`][tools/build] workspace which does the + following. Here's an [example CL](https://crrev.com/c/1554272). + 1. Adds "MyProject GPU Win10 Release + (CoolNewGPUType)" to [`chromium_gpu_fyi.py`][chromium_gpu_fyi.py] in + `scripts/slave/recipe_modules/chromium_tests/`. You can copy a similar + step. + 1. Adds `win-myproject-rel` to [`trybots.py`][trybots.py] in the same folder. + This is where you associate "MyProject GPU Win10 Release + (CoolNewGPUType)" with `win-myproject-rel`. See the sample CL for an example. + 1. Get this reviewed and landed. This step tells the Chromium recipe about + the newly-deployed waterfall bot, so it knows which JSON file to load + out of src/testing/buildbot and which entry to look at. +1. After your CLs land you should be able to find and run `win-myproject-rel` on CLs + using Choose Trybots in Gerrit. ### How to test and deploy a driver update
diff --git a/docs/vscode.md b/docs/vscode.md index b9d8ead2..ef87c75 100644 --- a/docs/vscode.md +++ b/docs/vscode.md
@@ -154,24 +154,12 @@ If you do not plan to use VSCode for debugging, vscode-clangd is a great alternative to C/C++ IntelliSense. It knows about how to compile Chromium, enabling it to provide smarter autocomplete than C/C++ IntelliSense as well - as allowing you to jump from functions to their definitions. To set it up: + as allowing you to jump from functions to their definitions. See + [clangd.md](clangd.md) for details. - 1. Install vscode-clangd - 2. Disable C/C++ IntelliSense - 3. Generate compilation database, from chromium/src: - - ``` - $ ninja -C out/Default -t compdb cc cxx objc objcxx > compile_commands.json - ``` - - 4. Re-run the above command each time you gclient sync to stay updated. - - If you need to debug, disable the vscode-clangd plugin, enable C/C++ + If you need to debug, disable the vscode-clangd extension, enable C/C++ Intellisense, and restart VSCode. - Read more about [clangd with VSCode](https://clang.llvm.org/extra/clangd/Installation.html#editor-plugins). - If you are a Googler, also see [go/clangd-chromium](go/clangd-chromium). - Also be sure to take a look at the [VS Code marketplace](https://marketplace.visualstudio.com/VSCode) to check out other
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index 2a02a01..cd01681 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc
@@ -1869,7 +1869,7 @@ true); registry->RegisterIntegerPref(kCorruptedDisableCount, 0); registry->RegisterBooleanPref(pref_names::kInsecureExtensionUpdatesEnabled, - true); + false); #if !defined(OS_MACOSX) registry->RegisterBooleanPref(pref_names::kAppFullscreenAllowed, true);
diff --git a/gpu/command_buffer/service/gpu_switches.cc b/gpu/command_buffer/service/gpu_switches.cc index e1aedf5..ff0f8ae 100644 --- a/gpu/command_buffer/service/gpu_switches.cc +++ b/gpu/command_buffer/service/gpu_switches.cc
@@ -83,4 +83,9 @@ // used for present render result on screen. const char kDisableVulkanSurface[] = "disable-vulkan-surface"; +// Disables falling back to GL based hardware rendering if initializing Vulkan +// fails. This is to allow tests to catch regressions in Vulkan. +const char kDisableVulkanFallbackToGLForTesting[] = + "disable-vulkan-fallback-to-gl-for-testing"; + } // namespace switches
diff --git a/gpu/command_buffer/service/gpu_switches.h b/gpu/command_buffer/service/gpu_switches.h index 3f87de21..60b6a5ed 100644 --- a/gpu/command_buffer/service/gpu_switches.h +++ b/gpu/command_buffer/service/gpu_switches.h
@@ -39,6 +39,7 @@ GPU_EXPORT extern const char kEnableRasterToSkImage[]; GPU_EXPORT extern const char kEnableVulkan[]; GPU_EXPORT extern const char kDisableVulkanSurface[]; +GPU_EXPORT extern const char kDisableVulkanFallbackToGLForTesting[]; } // namespace switches
diff --git a/gpu/config/gpu_preferences.h b/gpu/config/gpu_preferences.h index 5719fec..b866fbf 100644 --- a/gpu/config/gpu_preferences.h +++ b/gpu/config/gpu_preferences.h
@@ -201,12 +201,18 @@ // send a background/suspend signal. bool watchdog_starts_backgrounded = false; + // =================================== + // Settings from //gpu/command_buffer/service/gpu_switches.h // Use Vulkan for rasterization and display compositing. bool enable_vulkan = false; // Use vulkan VK_KHR_surface for presenting. bool disable_vulkan_surface = false; + // If Vulkan initialization has failed, do not fallback to GL. This is for + // testing in order to detect regressions which crash Vulkan. + bool disable_vulkan_fallback_to_gl_for_testing = false; + // =================================== // Settings from //cc/base/switches.h // Enable the GPU benchmarking extension; used by tests only.
diff --git a/gpu/ipc/common/gpu_preferences.mojom b/gpu/ipc/common/gpu_preferences.mojom index 3dd1f66..04b1901 100644 --- a/gpu/ipc/common/gpu_preferences.mojom +++ b/gpu/ipc/common/gpu_preferences.mojom
@@ -66,6 +66,7 @@ bool watchdog_starts_backgrounded; bool enable_vulkan; bool disable_vulkan_surface; + bool disable_vulkan_fallback_to_gl_for_testing; bool enable_gpu_benchmarking_extension; bool enable_webgpu; };
diff --git a/gpu/ipc/common/gpu_preferences_struct_traits.h b/gpu/ipc/common/gpu_preferences_struct_traits.h index 9baa25c..107ba37 100644 --- a/gpu/ipc/common/gpu_preferences_struct_traits.h +++ b/gpu/ipc/common/gpu_preferences_struct_traits.h
@@ -123,6 +123,8 @@ out->watchdog_starts_backgrounded = prefs.watchdog_starts_backgrounded(); out->enable_vulkan = prefs.enable_vulkan(); out->disable_vulkan_surface = prefs.disable_vulkan_surface(); + out->disable_vulkan_fallback_to_gl_for_testing = + prefs.disable_vulkan_fallback_to_gl_for_testing(); out->enable_gpu_benchmarking_extension = prefs.enable_gpu_benchmarking_extension(); out->enable_webgpu = prefs.enable_webgpu(); @@ -271,6 +273,10 @@ static bool disable_vulkan_surface(const gpu::GpuPreferences& prefs) { return prefs.disable_vulkan_surface; } + static bool disable_vulkan_fallback_to_gl_for_testing( + const gpu::GpuPreferences& prefs) { + return prefs.disable_vulkan_fallback_to_gl_for_testing; + } static bool enable_gpu_benchmarking_extension( const gpu::GpuPreferences& prefs) { return prefs.enable_gpu_benchmarking_extension;
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc index a138814..d0d64e8 100644 --- a/gpu/ipc/service/gpu_init.cc +++ b/gpu/ipc/service/gpu_init.cc
@@ -235,6 +235,7 @@ !gpu_preferences_.disable_vulkan_surface)) { DLOG(WARNING) << "Failed to create and initialize Vulkan implementation."; vulkan_implementation_ = nullptr; + CHECK(!gpu_preferences_.disable_vulkan_fallback_to_gl_for_testing); } gpu_preferences_.enable_vulkan = !!vulkan_implementation_; }
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg index c42f673..3345a58 100644 --- a/infra/config/cr-buildbucket.cfg +++ b/infra/config/cr-buildbucket.cfg
@@ -3506,6 +3506,7 @@ name: "gpu-manual-try-linux-nvidia-tsn" } builders { mixins: "linux-try" name: "leak_detection_linux" } + builders { mixins: "linux-angle-try" name: "linux-angle-rel" } builders { mixins: "linux-angle-try" name: "linux_angle_compile_dbg_ng" } builders { mixins: "linux-angle-try" name: "linux_angle_dbg_ng" } builders { mixins: "linux-angle-try" name: "linux_angle_deqp_rel_ng" } @@ -3625,6 +3626,7 @@ builders { mixins: "ios-try" name: "ios-simulator-eg" } builders { mixins: "ios-try" name: "ios-simulator-xcode-clang" } builders { mixins: "ios-try" name: "ios-slimnav" } + builders { mixins: "mac-angle-try" name: "mac-angle-rel" } builders { mixins: "mac-angle-try" name: "mac_angle_compile_dbg_ng" } builders { mixins: "mac-angle-try" name: "mac_angle_dbg_ng" } builders { mixins: "mac-angle-try" name: "mac_angle_rel_ng" }
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg index ba67371..79a77ad 100644 --- a/infra/config/luci-milo.cfg +++ b/infra/config/luci-milo.cfg
@@ -4478,6 +4478,9 @@ name: "buildbucket/luci.chromium.try/android_angle_vk64_rel_ng" } builders { + name: "buildbucket/luci.chromium.try/linux-angle-rel" + } + builders { name: "buildbucket/luci.chromium.try/linux_angle_dbg_ng" } builders { @@ -4490,6 +4493,9 @@ name: "buildbucket/luci.chromium.try/linux_angle_rel_ng" } builders { + name: "buildbucket/luci.chromium.try/mac-angle-rel" + } + builders { name: "buildbucket/luci.chromium.try/mac_angle_dbg_ng" } builders { @@ -4719,6 +4725,9 @@ name: "buildbucket/luci.chromium.try/gpu-manual-try-win10-nvidia-rel" } builders { + name: "buildbucket/luci.chromium.try/linux-angle-rel" + } + builders { name: "buildbucket/luci.chromium.try/linux-blink-heap-concurrent-marking-tsan-rel" } builders { @@ -4858,6 +4867,9 @@ name: "buildbucket/luci.chromium.try/ios12-sdk-simulator" } builders { + name: "buildbucket/luci.chromium.try/mac-angle-rel" + } + builders { name: "buildbucket/luci.chromium.try/mac-jumbo-rel" } builders {
diff --git a/infra/config/luci-scheduler.cfg b/infra/config/luci-scheduler.cfg index 5c6d9817..e456176 100644 --- a/infra/config/luci-scheduler.cfg +++ b/infra/config/luci-scheduler.cfg
@@ -1312,6 +1312,22 @@ ################################################################################ job { + id: "ANGLE GPU Linux Release (Intel HD 630)" + # Triggered by "GPU FYI Linux Builder". + acl_sets: "triggered-by-parent-builders" + # This bot doesn't actually exist, so it's noop'ed out. crbug.com/819899 + noop: {} +} + +job { + id: "ANGLE GPU Linux Release (NVIDIA)" + # Triggered by "GPU FYI Linux Builder". + acl_sets: "triggered-by-parent-builders" + # This bot doesn't actually exist, so it's noop'ed out. crbug.com/819899 + noop: {} +} + +job { id: "Cast Audio Linux" acl_sets: "default" buildbucket: { @@ -1985,6 +2001,30 @@ ################################################################################ job { + id: "ANGLE GPU Mac Release (Intel)" + # Triggered by "GPU FYI Mac Builder". + acl_sets: "triggered-by-parent-builders" + # This bot doesn't actually exist, so it's noop'ed out. crbug.com/819899 + noop: {} +} + +job { + id: "ANGLE GPU Mac Retina Release (NVIDIA)" + # Triggered by "GPU FYI Mac Builder". + acl_sets: "triggered-by-parent-builders" + # This bot doesn't actually exist, so it's noop'ed out. crbug.com/819899 + noop: {} +} + +job { + id: "ANGLE GPU Mac Retina Release (AMD)" + # Triggered by "GPU FYI Mac Builder". + acl_sets: "triggered-by-parent-builders" + # This bot doesn't actually exist, so it's noop'ed out. crbug.com/819899 + noop: {} +} + +job { id: "Dawn GPU Mac Release (Intel)" # Triggered by "GPU FYI Mac Builder". acl_sets: "triggered-by-parent-builders"
diff --git a/ios/chrome/app/resources/ios_resources.grd b/ios/chrome/app/resources/ios_resources.grd index 1aa2035..69df3a0 100644 --- a/ios/chrome/app/resources/ios_resources.grd +++ b/ios/chrome/app/resources/ios_resources.grd
@@ -14,6 +14,8 @@ <include name="IDR_IOS_OMAHA_JS" file="omaha/omaha.js" type="BINDATA" compress="gzip" /> <include name="IDR_IOS_UKM_INTERNALS_HTML" file="../../../../components/ukm/debug/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" /> <include name="IDR_IOS_UKM_INTERNALS_JS" file="../../../../components/ukm/debug/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" /> + <include name="IDR_IOS_TRANSLATE_INTERNALS_HTML" file="../../../../components/translate/translate_internals/translate_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" /> + <include name="IDR_IOS_TRANSLATE_INTERNALS_JS" file="../../../../components/translate/translate_internals/translate_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" /> </includes> </release> </grit>
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index e90b9876..56c7157 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -87,8 +87,7 @@ "+components/sync_sessions", "+components/sync_preferences", "+components/task_scheduler_util", - "+components/translate/core", - "+components/translate/ios", + "+components/translate", "+components/ui_metrics", "+components/ukm", "+components/undo",
diff --git a/ios/chrome/browser/chrome_url_constants.cc b/ios/chrome/browser/chrome_url_constants.cc index 2576ec4..bcb79ab6 100644 --- a/ios/chrome/browser/chrome_url_constants.cc +++ b/ios/chrome/browser/chrome_url_constants.cc
@@ -47,6 +47,7 @@ const char kChromeUISuggestionsHost[] = "suggestions"; const char kChromeUISyncInternalsHost[] = "sync-internals"; const char kChromeUITermsHost[] = "terms"; +const char kChromeUITranslateInternalsHost[] = "translate-internals"; const char kChromeUIURLKeyedMetricsHost[] = "ukm"; const char kChromeUIUserActionsHost[] = "user-actions"; const char kChromeUIVersionHost[] = "version";
diff --git a/ios/chrome/browser/chrome_url_constants.h b/ios/chrome/browser/chrome_url_constants.h index 57af229a..96a19ca4 100644 --- a/ios/chrome/browser/chrome_url_constants.h +++ b/ios/chrome/browser/chrome_url_constants.h
@@ -59,6 +59,7 @@ extern const char kChromeUISuggestionsHost[]; extern const char kChromeUISyncInternalsHost[]; extern const char kChromeUITermsHost[]; +extern const char kChromeUITranslateInternalsHost[]; extern const char kChromeUIURLKeyedMetricsHost[]; extern const char kChromeUIUserActionsHost[]; extern const char kChromeUIVersionHost[];
diff --git a/ios/chrome/browser/ui/autofill/cells/BUILD.gn b/ios/chrome/browser/ui/autofill/cells/BUILD.gn index c981086..23fee9c 100644 --- a/ios/chrome/browser/ui/autofill/cells/BUILD.gn +++ b/ios/chrome/browser/ui/autofill/cells/BUILD.gn
@@ -15,7 +15,6 @@ ] deps = [ - "resources:autofill_edit_item_icon", "//components/resources", "//components/strings", "//ios/chrome/app/strings", @@ -42,7 +41,6 @@ source_set("unit_tests") { testonly = true sources = [ - "autofill_edit_item_unittest.mm", "cvc_item_unittest.mm", "legacy_autofill_edit_item_unittest.mm", "status_item_unittest.mm",
diff --git a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h index 5e175cb..4da8a62 100644 --- a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h +++ b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h
@@ -8,60 +8,14 @@ #import <UIKit/UIKit.h> #import "ios/chrome/browser/ui/autofill/autofill_ui_type.h" -#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h" -// Item to represent and configure an AutofillEditItem. It features a label and -// a text field. -@interface AutofillEditItem : TableViewItem - -// The name of the text field. -@property(nonatomic, copy) NSString* textFieldName; - -// The value of the text field. -@property(nonatomic, copy) NSString* textFieldValue; - -// An icon identifying the text field or its current value, if any. -@property(nonatomic, copy) UIImage* identifyingIcon; +// Item to represent and configure an AutofillEditItem. +@interface AutofillEditItem : TableViewTextEditItem // The field type this item is describing. @property(nonatomic, assign) AutofillUIType autofillUIType; -// Whether this field is required. If YES, an "*" is appended to the name of the -// text field to indicate that the field is required. It is also used for -// validation purposes. -@property(nonatomic, getter=isRequired) BOOL required; - -// Whether the text field is enabled for editing. -@property(nonatomic, getter=isTextFieldEnabled) BOOL textFieldEnabled; - -// Controls the display of the return key when the keyboard is displaying. -@property(nonatomic, assign) UIReturnKeyType returnKeyType; - -// Keyboard type to be displayed when the text field becomes first responder. -@property(nonatomic, assign) UIKeyboardType keyboardType; - -// Controls autocapitalization behavior of the text field. -@property(nonatomic, assign) - UITextAutocapitalizationType autoCapitalizationType; - -@end - -// AutofillEditCell implements an TableViewCell subclass containing a label -// and a text field. -@interface AutofillEditCell : TableViewCell - -// Label at the leading edge of the cell. It displays the item's textFieldName. -@property(nonatomic, strong) UILabel* textLabel; - -// Text field at the trailing edge of the cell. It displays the item's -// |textFieldValue|. -@property(nonatomic, readonly, strong) UITextField* textField; - -// Whether the icon showing that the cell is editable should be displayed. -@property(nonatomic, assign) BOOL editIconDisplayed; - -- (void)setIdentifyingIcon:(UIImage*)icon; - @end #endif // IOS_CHROME_BROWSER_UI_AUTOFILL_CELLS_AUTOFILL_EDIT_ITEM_H_
diff --git a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm index 38c1f49..91de3674 100644 --- a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm +++ b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm
@@ -4,321 +4,20 @@ #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" -#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" -#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" -#import "ios/chrome/browser/ui/util/rtl_geometry.h" -#import "ios/chrome/browser/ui/util/uikit_ui_util.h" -#import "ios/chrome/common/ui_util/constraints_ui_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -namespace { -// Minimum gap between the label and the text field. -const CGFloat kLabelAndFieldGap = 5; -// Height/width of the edit icon. -const CGFloat kEditIconLength = 18; -} // namespace - @implementation AutofillEditItem - (instancetype)initWithType:(NSInteger)type { self = [super initWithType:type]; if (self) { - self.cellClass = [AutofillEditCell class]; - _returnKeyType = UIReturnKeyNext; - _keyboardType = UIKeyboardTypeDefault; - _autoCapitalizationType = UITextAutocapitalizationTypeWords; + self.hideEditIcon = !base::FeatureList::IsEnabled(kSettingsRefresh); } return self; } -#pragma mark TableViewItem - -- (void)configureCell:(AutofillEditCell*)cell - withStyler:(ChromeTableViewStyler*)styler { - [super configureCell:cell withStyler:styler]; - - NSString* textLabelFormat = self.required ? @"%@*" : @"%@"; - cell.textLabel.text = - [NSString stringWithFormat:textLabelFormat, self.textFieldName]; - cell.textField.text = self.textFieldValue; - if (self.textFieldName.length) { - cell.textField.accessibilityIdentifier = - [NSString stringWithFormat:@"%@_textField", self.textFieldName]; - } - if (styler.cellBackgroundColor) { - cell.textLabel.backgroundColor = styler.cellBackgroundColor; - cell.textField.backgroundColor = styler.cellBackgroundColor; - } else { - cell.textLabel.backgroundColor = styler.tableViewBackgroundColor; - cell.textField.backgroundColor = styler.tableViewBackgroundColor; - } - cell.textField.enabled = self.textFieldEnabled; - if (base::FeatureList::IsEnabled(kSettingsRefresh)) { - cell.textField.textColor = - UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); - cell.editIconDisplayed = self.textFieldEnabled; - } else { - cell.textField.textColor = - self.textFieldEnabled - ? UIColorFromRGB(kTableViewTextLabelColorBlue) - : UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); - } - [cell.textField addTarget:self - action:@selector(textFieldChanged:) - forControlEvents:UIControlEventEditingChanged]; - cell.textField.returnKeyType = self.returnKeyType; - cell.textField.keyboardType = self.keyboardType; - cell.textField.autocapitalizationType = self.autoCapitalizationType; - [cell setIdentifyingIcon:self.identifyingIcon]; -} - -#pragma mark Actions - -- (void)textFieldChanged:(UITextField*)textField { - self.textFieldValue = textField.text; -} - -@end - -#pragma mark - AutofillEditCell - -@interface AutofillEditCell () - -@property(nonatomic, strong) NSLayoutConstraint* iconHeightConstraint; -@property(nonatomic, strong) NSLayoutConstraint* iconWidthConstraint; -@property(nonatomic, strong) NSLayoutConstraint* textFieldTrailingConstraint; -@property(nonatomic, strong) NSLayoutConstraint* textLabelTrailingConstraint; - -@property(nonatomic, strong) NSLayoutConstraint* editIconHeightConstraint; -@property(nonatomic, strong) NSLayoutConstraint* iconTrailingConstraint; - -// When they are activated, the label and the text field are on one line. -// They conflict with the |accessibilityConstraints|. -@property(nonatomic, strong) NSArray<NSLayoutConstraint*>* standardConstraints; -// When they are activated, the label is on one line, the text field is on -// another line. They conflict with the |standardConstraints|. -@property(nonatomic, strong) - NSArray<NSLayoutConstraint*>* accessibilityConstraints; - -// UIImageView containing the icon identifying |textField| or its current value. -@property(nonatomic, readonly, strong) UIImageView* identifyingIconView; - -// UIImageView containing the icon indicating that |textField| is editable. -@property(nonatomic, strong) UIImageView* editIconView; - -@end - -@implementation AutofillEditCell - -@synthesize textLabel = _textLabel; - -- (instancetype)initWithStyle:(UITableViewCellStyle)style - reuseIdentifier:(NSString*)reuseIdentifier { - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self) { - self.isAccessibilityElement = YES; - UIView* contentView = self.contentView; - - _textLabel = [[UILabel alloc] init]; - _textLabel.translatesAutoresizingMaskIntoConstraints = NO; - [_textLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh - forAxis:UILayoutConstraintAxisHorizontal]; - _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - _textLabel.adjustsFontForContentSizeCategory = YES; - [contentView addSubview:_textLabel]; - - _textField = [[UITextField alloc] init]; - _textField.translatesAutoresizingMaskIntoConstraints = NO; - _textField.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - _textField.adjustsFontForContentSizeCategory = YES; - [_textField - setContentCompressionResistancePriority:UILayoutPriorityDefaultLow - forAxis: - UILayoutConstraintAxisHorizontal]; - [contentView addSubview:_textField]; - - _textField.autocorrectionType = UITextAutocorrectionTypeNo; - _textField.clearButtonMode = UITextFieldViewModeWhileEditing; - _textField.contentVerticalAlignment = - UIControlContentVerticalAlignmentCenter; - - // Card type icon. - _identifyingIconView = [[UIImageView alloc] initWithFrame:CGRectZero]; - _identifyingIconView.translatesAutoresizingMaskIntoConstraints = NO; - [contentView addSubview:_identifyingIconView]; - - // Edit icon. - UIImage* editImage = [[UIImage imageNamed:@"autofill_edit_item_icon"] - imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - _editIconView = [[UIImageView alloc] initWithImage:editImage]; - _editIconView.tintColor = - UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); - _editIconView.translatesAutoresizingMaskIntoConstraints = NO; - [contentView addSubview:_editIconView]; - - // Set up the icons size constraints. They are activated here and updated in - // layoutSubviews. - _iconHeightConstraint = - [_identifyingIconView.heightAnchor constraintEqualToConstant:0]; - _iconWidthConstraint = - [_identifyingIconView.widthAnchor constraintEqualToConstant:0]; - _editIconHeightConstraint = - [_editIconView.heightAnchor constraintEqualToConstant:0]; - - _textFieldTrailingConstraint = [_textField.trailingAnchor - constraintEqualToAnchor:_editIconView.leadingAnchor]; - _textLabelTrailingConstraint = [_textLabel.trailingAnchor - constraintEqualToAnchor:_editIconView.leadingAnchor]; - _iconTrailingConstraint = [_editIconView.trailingAnchor - constraintEqualToAnchor:_identifyingIconView.leadingAnchor]; - - _standardConstraints = @[ - [_textField.firstBaselineAnchor - constraintEqualToAnchor:_textLabel.firstBaselineAnchor], - [_textField.leadingAnchor - constraintEqualToAnchor:_textLabel.trailingAnchor - constant:kLabelAndFieldGap], - ]; - - _accessibilityConstraints = @[ - [_textField.topAnchor constraintEqualToAnchor:_textLabel.bottomAnchor - constant:kTableViewVerticalSpacing], - [_textField.leadingAnchor - constraintEqualToAnchor:contentView.leadingAnchor - constant:kTableViewHorizontalSpacing], - _textLabelTrailingConstraint, - ]; - - // Set up the constraints. - [NSLayoutConstraint activateConstraints:@[ - [_textLabel.leadingAnchor - constraintEqualToAnchor:contentView.leadingAnchor - constant:kTableViewHorizontalSpacing], - _textFieldTrailingConstraint, - [_identifyingIconView.trailingAnchor - constraintEqualToAnchor:contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], - [_identifyingIconView.centerYAnchor - constraintEqualToAnchor:contentView.centerYAnchor], - [_editIconView.centerYAnchor - constraintEqualToAnchor:contentView.centerYAnchor], - _iconHeightConstraint, - _iconWidthConstraint, - _iconTrailingConstraint, - _editIconHeightConstraint, - [_editIconView.widthAnchor - constraintEqualToAnchor:_editIconView.heightAnchor], - ]]; - AddOptionalVerticalPadding(contentView, _textLabel, - kTableViewOneLabelCellVerticalSpacing); - AddOptionalVerticalPadding(contentView, _textField, - kTableViewOneLabelCellVerticalSpacing); - - [self updateForAccessibilityContentSizeCategory: - UIContentSizeCategoryIsAccessibilityCategory( - self.traitCollection.preferredContentSizeCategory)]; - } - return self; -} - -#pragma mark Public - -- (void)setEditIconDisplayed:(BOOL)editIconDisplayed { - if (editIconDisplayed == _editIconDisplayed) - return; - - _editIconDisplayed = editIconDisplayed; - self.editIconView.hidden = !editIconDisplayed; - if (editIconDisplayed) { - self.textFieldTrailingConstraint.constant = -kLabelAndFieldGap; - self.textLabelTrailingConstraint.constant = -kLabelAndFieldGap; - - _editIconHeightConstraint.constant = kEditIconLength; - } else { - self.textFieldTrailingConstraint.constant = 0; - self.textLabelTrailingConstraint.constant = 0; - - _editIconHeightConstraint.constant = 0; - } -} - -- (void)setIdentifyingIcon:(UIImage*)icon { - self.identifyingIconView.image = icon; - if (icon) { - self.iconTrailingConstraint.constant = -kLabelAndFieldGap; - - // Set the size constraints of the icon view to the dimensions of the image. - self.iconHeightConstraint.constant = icon.size.height; - self.iconWidthConstraint.constant = icon.size.width; - } else { - self.iconTrailingConstraint.constant = 0; - self.iconHeightConstraint.constant = 0; - self.iconWidthConstraint.constant = 0; - } -} - -- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { - [super traitCollectionDidChange:previousTraitCollection]; - BOOL isCurrentCategoryAccessibility = - UIContentSizeCategoryIsAccessibilityCategory( - self.traitCollection.preferredContentSizeCategory); - if (isCurrentCategoryAccessibility != - UIContentSizeCategoryIsAccessibilityCategory( - previousTraitCollection.preferredContentSizeCategory)) { - [self updateForAccessibilityContentSizeCategory: - isCurrentCategoryAccessibility]; - } -} - -#pragma mark - UITableViewCell - -- (void)prepareForReuse { - [super prepareForReuse]; - self.textLabel.text = nil; - self.textField.text = nil; - self.textField.returnKeyType = UIReturnKeyNext; - self.textField.keyboardType = UIKeyboardTypeDefault; - self.textField.autocapitalizationType = UITextAutocapitalizationTypeWords; - self.textField.autocorrectionType = UITextAutocorrectionTypeNo; - self.textField.clearButtonMode = UITextFieldViewModeWhileEditing; - self.textField.accessibilityIdentifier = nil; - self.textField.enabled = NO; - self.textField.delegate = nil; - [self.textField removeTarget:nil - action:nil - forControlEvents:UIControlEventAllEvents]; - self.identifyingIconView.image = nil; -} - -#pragma mark Accessibility - -- (NSString*)accessibilityLabel { - return [NSString - stringWithFormat:@"%@, %@", self.textLabel.text, self.textField.text]; -} - -#pragma mark Private - -// Updates the cell such as it is layouted correctly with regard to the -// preferred content size category, if it is an -// |accessibilityContentSizeCategory| or not. -- (void)updateForAccessibilityContentSizeCategory: - (BOOL)accessibilityContentSizeCategory { - if (accessibilityContentSizeCategory) { - [NSLayoutConstraint deactivateConstraints:_standardConstraints]; - [NSLayoutConstraint activateConstraints:_accessibilityConstraints]; - _textField.textAlignment = - UseRTLLayout() ? NSTextAlignmentRight : NSTextAlignmentLeft; - } else { - [NSLayoutConstraint deactivateConstraints:_accessibilityConstraints]; - [NSLayoutConstraint activateConstraints:_standardConstraints]; - _textField.textAlignment = - UseRTLLayout() ? NSTextAlignmentLeft : NSTextAlignmentRight; - } -} - @end
diff --git a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item_unittest.mm b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item_unittest.mm deleted file mode 100644 index b6529c33..0000000 --- a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item_unittest.mm +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" - -#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" -#include "testing/gtest/include/gtest/gtest.h" -#import "testing/gtest_mac.h" -#include "testing/platform_test.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -using AutofillEditItemTest = PlatformTest; - -// Tests that the label and text field are set properly after a call to -// |configureCell:|. -TEST_F(AutofillEditItemTest, ConfigureCell) { - AutofillEditItem* item = [[AutofillEditItem alloc] initWithType:0]; - NSString* name = @"Name"; - NSString* value = @"Value"; - BOOL enabled = NO; - - item.textFieldName = name; - item.textFieldValue = value; - item.textFieldEnabled = enabled; - - id cell = [[[item cellClass] alloc] init]; - ASSERT_TRUE([cell isMemberOfClass:[AutofillEditCell class]]); - - AutofillEditCell* autofillEditCell = cell; - EXPECT_EQ(0U, autofillEditCell.textLabel.text.length); - EXPECT_EQ(0U, autofillEditCell.textField.text.length); - EXPECT_TRUE(autofillEditCell.textField.enabled); - - [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; - EXPECT_NSEQ(name, autofillEditCell.textLabel.text); - EXPECT_NSEQ(value, autofillEditCell.textField.text); - EXPECT_FALSE(autofillEditCell.textField.enabled); -}
diff --git a/ios/chrome/browser/ui/autofill/cells/resources/BUILD.gn b/ios/chrome/browser/ui/autofill/cells/resources/BUILD.gn deleted file mode 100644 index 5695705..0000000 --- a/ios/chrome/browser/ui/autofill/cells/resources/BUILD.gn +++ /dev/null
@@ -1,13 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/ios/asset_catalog.gni") - -imageset("autofill_edit_item_icon") { - sources = [ - "autofill_edit_item_icon.imageset/Contents.json", - "autofill_edit_item_icon.imageset/autofill_edit_item_icon@2x.png", - "autofill_edit_item_icon.imageset/autofill_edit_item_icon@3x.png", - ] -}
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index c50247b..f2fe346 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -125,6 +125,7 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state:browser_state_impl", "//ios/chrome/browser/browsing_data", + "//ios/chrome/browser/browsing_data:feature_flags", "//ios/chrome/browser/content_settings", "//ios/chrome/browser/favicon", "//ios/chrome/browser/feature_engagement",
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_edit_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_edit_table_view_controller.mm index ba5eaf3f..542e14b 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_edit_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_edit_table_view_controller.mm
@@ -260,7 +260,8 @@ cell.selectionStyle = UITableViewCellSelectionStyleNone; NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath]; - AutofillEditCell* editCell = base::mac::ObjCCast<AutofillEditCell>(cell); + TableViewTextEditCell* editCell = + base::mac::ObjCCast<TableViewTextEditCell>(cell); editCell.textField.delegate = self; switch (itemType) { case ItemTypeCardholderName: @@ -296,8 +297,8 @@ didSelectRowAtIndexPath:(NSIndexPath*)indexPath { if (self.tableView.editing) { UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath]; - AutofillEditCell* textFieldCell = - base::mac::ObjCCastStrict<AutofillEditCell>(cell); + TableViewTextEditCell* textFieldCell = + base::mac::ObjCCastStrict<TableViewTextEditCell>(cell); [textFieldCell.textField becomeFirstResponder]; } }
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.mm index 3a0ee7b..7409f5a 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.mm
@@ -15,7 +15,7 @@ #endif @interface AutofillEditTableViewController () <AutofillEditAccessoryDelegate> { - AutofillEditCell* _currentEditingCell; + TableViewTextEditCell* _currentEditingCell; AutofillEditAccessoryView* _accessoryView; } @end @@ -70,14 +70,14 @@ #pragma mark - UITextFieldDelegate - (void)textFieldDidBeginEditing:(UITextField*)textField { - AutofillEditCell* cell = [self autofillEditCellForTextField:textField]; + TableViewTextEditCell* cell = [self autofillEditCellForTextField:textField]; _currentEditingCell = cell; [textField setInputAccessoryView:_accessoryView]; [self updateAccessoryViewButtonState]; } - (void)textFieldDidEndEditing:(UITextField*)textField { - AutofillEditCell* cell = [self autofillEditCellForTextField:textField]; + TableViewTextEditCell* cell = [self autofillEditCellForTextField:textField]; DCHECK(_currentEditingCell == cell); [textField setInputAccessoryView:nil]; _currentEditingCell = nil; @@ -106,10 +106,11 @@ #pragma mark - Helper methods // Returns the cell containing |textField|. -- (AutofillEditCell*)autofillEditCellForTextField:(UITextField*)textField { - AutofillEditCell* settingsCell = nil; +- (TableViewTextEditCell*)autofillEditCellForTextField:(UITextField*)textField { + TableViewTextEditCell* settingsCell = nil; for (UIView* view = textField; view; view = [view superview]) { - AutofillEditCell* cell = base::mac::ObjCCast<AutofillEditCell>(view); + TableViewTextEditCell* cell = + base::mac::ObjCCast<TableViewTextEditCell>(view); if (cell) { settingsCell = cell; break; @@ -155,8 +156,9 @@ if (!nextCellPath) { [[_currentEditingCell textField] resignFirstResponder]; } else { - AutofillEditCell* nextCell = base::mac::ObjCCastStrict<AutofillEditCell>( - [self.tableView cellForRowAtIndexPath:nextCellPath]); + TableViewTextEditCell* nextCell = + base::mac::ObjCCastStrict<TableViewTextEditCell>( + [self.tableView cellForRowAtIndexPath:nextCellPath]); [nextCell.textField becomeFirstResponder]; } }
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_profile_edit_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_profile_edit_table_view_controller.mm index 30b98159..4d2364b 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_profile_edit_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_profile_edit_table_view_controller.mm
@@ -220,8 +220,8 @@ cell.selectionStyle = UITableViewCellSelectionStyleNone; - AutofillEditCell* textFieldCell = - base::mac::ObjCCastStrict<AutofillEditCell>(cell); + TableViewTextEditCell* textFieldCell = + base::mac::ObjCCastStrict<TableViewTextEditCell>(cell); textFieldCell.accessibilityIdentifier = textFieldCell.textLabel.text; textFieldCell.textField.delegate = self; return textFieldCell; @@ -231,8 +231,8 @@ didSelectRowAtIndexPath:(NSIndexPath*)indexPath { if (self.tableView.editing) { UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath]; - AutofillEditCell* textFieldCell = - base::mac::ObjCCastStrict<AutofillEditCell>(cell); + TableViewTextEditCell* textFieldCell = + base::mac::ObjCCastStrict<TableViewTextEditCell>(cell); [textFieldCell.textField becomeFirstResponder]; } }
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm index c947fe5a..1c721cb9 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm
@@ -138,7 +138,7 @@ // Align cell separators with text label leading margin. [self.tableView setSeparatorInset:UIEdgeInsetsMake(0, kTableViewHorizontalSpacing, 0, 0)]; - + self.tableView.allowsMultipleSelection = YES; // Navigation controller configuration. self.title = l10n_util::GetNSString(IDS_IOS_CLEAR_BROWSING_DATA_TITLE); // Adds the "Done" button and hooks it up to |dismiss|. @@ -160,7 +160,22 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.dataManager restartCounters:BrowsingDataRemoveMask::REMOVE_ALL]; + if (IsNewClearBrowsingDataUIEnabled()) { + // Select those cells correspond to a checked item. + NSArray* dataTypeItems = [self.tableViewModel + itemsInSectionWithIdentifier:SectionIdentifierDataTypes]; + for (TableViewClearBrowsingDataItem* dataTypeItem in dataTypeItems) { + DCHECK( + [dataTypeItem isKindOfClass:[TableViewClearBrowsingDataItem class]]); + if (dataTypeItem.checked) { + [self.tableView selectRowAtIndexPath:[self.tableViewModel + indexPathForItem:dataTypeItem] + animated:NO + scrollPosition:UITableViewScrollPositionNone]; + } + } + // Showing toolbar here because parent class hides toolbar in // viewWillDisappear:. self.navigationController.toolbarHidden = NO; @@ -237,18 +252,41 @@ - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { + if (!IsNewClearBrowsingDataUIEnabled()) { + [self tableView:tableView legacyDidSelectRowAtIndexPath:indexPath]; + } else { + TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath]; + DCHECK(item); + switch (item.type) { + case ItemTypeTimeRange: { + UIViewController* controller = + [[TimeRangeSelectorTableViewController alloc] + initWithPrefs:self.browserState->GetPrefs() + delegate:self.dataManager]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + [self.navigationController pushViewController:controller animated:YES]; + break; + } + case ItemTypeDataTypeBrowsingHistory: + case ItemTypeDataTypeCookiesSiteData: + case ItemTypeDataTypeCache: + case ItemTypeDataTypeSavedPasswords: + case ItemTypeDataTypeAutofill: { + [self updateItemAndReconfigureCellFor:item setChecked:YES]; + break; + } + default: + break; + } + } +} + +- (void)tableView:(UITableView*)tableView + legacyDidSelectRowAtIndexPath:(NSIndexPath*)indexPath { [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath]; DCHECK(item); switch (item.type) { - case ItemTypeTimeRange: { - UIViewController* controller = - [[TimeRangeSelectorTableViewController alloc] - initWithPrefs:self.browserState->GetPrefs() - delegate:self.dataManager]; - [self.navigationController pushViewController:controller animated:YES]; - break; - } case ItemTypeDataTypeBrowsingHistory: case ItemTypeDataTypeCookiesSiteData: case ItemTypeDataTypeCache: @@ -262,11 +300,27 @@ [self reconfigureCellsForItems:@[ clearBrowsingDataItem ]]; break; } - case ItemTypeClearBrowsingDataButton: - case ItemTypeFooterGoogleAccount: - case ItemTypeFooterGoogleAccountAndMyActivity: - case ItemTypeFooterSavedSiteData: - case ItemTypeFooterClearSyncAndSavedSiteData: + default: + break; + } +} + +- (void)tableView:(UITableView*)tableView + didDeselectRowAtIndexPath:(NSIndexPath*)indexPath { + if (!IsNewClearBrowsingDataUIEnabled()) { + return; + } + TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath]; + DCHECK(item); + switch (item.type) { + case ItemTypeDataTypeBrowsingHistory: + case ItemTypeDataTypeCookiesSiteData: + case ItemTypeDataTypeCache: + case ItemTypeDataTypeSavedPasswords: + case ItemTypeDataTypeAutofill: { + [self updateItemAndReconfigureCellFor:item setChecked:NO]; + break; + } default: break; } @@ -296,6 +350,20 @@ // thus the cell height needs to adapt accordingly. [self reloadCellsForItems:@[ item ] withRowAnimation:UITableViewRowAnimationAutomatic]; + + // Restore a cell's seleted state potentially cleared by the above reload + // method. + if (IsNewClearBrowsingDataUIEnabled() && + [item isKindOfClass:[TableViewClearBrowsingDataItem class]]) { + TableViewClearBrowsingDataItem* dataTypeItem = + base::mac::ObjCCastStrict<TableViewClearBrowsingDataItem>(item); + if (dataTypeItem.checked) { + [self.tableView selectRowAtIndexPath:[self.tableViewModel + indexPathForItem:dataTypeItem] + animated:NO + scrollPosition:UITableViewScrollPositionNone]; + } + } } - (void)removeBrowsingDataForBrowserState:(ios::ChromeBrowserState*)browserState @@ -404,4 +472,21 @@ [self.actionSheetCoordinator start]; } +// Helper of |tableView:didSelectRowAtIndexPath:| and +// |tableView:didDeselectRowAtIndexPath:| for browsing data items. +// Sets |item|'s |checked| to |flag|, which depends on whether it's a selection +// or a deselection, then performs updates accordingly. +- (void)updateItemAndReconfigureCellFor:(TableViewItem*)item + setChecked:(BOOL)flag { + if (![item isKindOfClass:[TableViewClearBrowsingDataItem class]]) { + return; + } + TableViewClearBrowsingDataItem* clearBrowsingDataItem = + base::mac::ObjCCastStrict<TableViewClearBrowsingDataItem>(item); + clearBrowsingDataItem.checked = flag; + self.browserState->GetPrefs()->SetBoolean(clearBrowsingDataItem.prefName, + clearBrowsingDataItem.checked); + [self reconfigureCellsForItems:@[ clearBrowsingDataItem ]]; +} + @end
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm b/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm index 9bb1833..097f7b7 100644 --- a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm
@@ -20,6 +20,7 @@ #include "components/unified_consent/feature.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/browsing_data/browsing_data_features.h" #include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/system_flags.h" @@ -383,7 +384,7 @@ } break; case ItemTypeClearBrowsingDataClear: - if (base::FeatureList::IsEnabled(kSettingsRefresh)) { + if (IsNewClearBrowsingDataUIEnabled()) { ClearBrowsingDataTableViewController* clearBrowsingDataViewController = [[ClearBrowsingDataTableViewController alloc] initWithBrowserState:_browserState];
diff --git a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm index 4ab6324..a4e93cb 100644 --- a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm +++ b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
@@ -54,6 +54,7 @@ ItemTypeURLNoMetadata, ItemTypeTextAccessoryImage, ItemTypeTextAccessoryNoImage, + ItemTypeTextEditItem, ItemTypeURLWithTimestamp, ItemTypeURLWithSize, ItemTypeURLWithSupplementalText, @@ -66,7 +67,6 @@ ItemTypeSettingsSwitch2, ItemTypeSyncSwitch, ItemTypeSettingsSyncError, - ItemTypeAutofillEditItem, ItemTypeAutofillData, ItemTypeAccount, }; @@ -204,6 +204,32 @@ [model addItem:detailIconItemBothLong toSectionWithIdentifier:SectionIdentifierText]; + TableViewTextEditItem* textEditItem = + [[TableViewTextEditItem alloc] initWithType:ItemTypeTextEditItem]; + textEditItem.textFieldName = @"Edit Text Item"; + textEditItem.textFieldValue = @" with no icons"; + textEditItem.hideEditIcon = YES; + textEditItem.textFieldEnabled = YES; + [model addItem:textEditItem toSectionWithIdentifier:SectionIdentifierText]; + + TableViewTextEditItem* textEditItemEditIcon = + [[TableViewTextEditItem alloc] initWithType:ItemTypeTextEditItem]; + textEditItemEditIcon.textFieldName = @"Edit Text Item"; + textEditItemEditIcon.textFieldValue = @" with edit icon"; + textEditItemEditIcon.textFieldEnabled = YES; + [model addItem:textEditItemEditIcon + toSectionWithIdentifier:SectionIdentifierText]; + + TableViewTextEditItem* textEditItemBothIcons = + [[TableViewTextEditItem alloc] initWithType:ItemTypeTextEditItem]; + textEditItemBothIcons.textFieldName = @"Edit Text Item"; + textEditItemBothIcons.textFieldValue = @" with edit and custom icons"; + textEditItemBothIcons.identifyingIcon = + [UIImage imageNamed:@"table_view_cell_check_mark"]; + textEditItemBothIcons.textFieldEnabled = YES; + [model addItem:textEditItemBothIcons + toSectionWithIdentifier:SectionIdentifierText]; + // SectionIdentifierSettings. TableViewTextHeaderFooterItem* settingsHeader = [[TableViewTextHeaderFooterItem alloc] initWithType:ItemTypeTextHeader]; @@ -265,15 +291,6 @@ [model setHeader:autofillHeader forSectionWithIdentifier:SectionIdentifierAutofill]; - AutofillEditItem* autofillEditItem = - [[AutofillEditItem alloc] initWithType:ItemTypeAutofillEditItem]; - autofillEditItem.textFieldName = @"Autofill field"; - autofillEditItem.textFieldValue = @" with a value"; - autofillEditItem.identifyingIcon = - [UIImage imageNamed:@"table_view_cell_check_mark"]; - [model addItem:autofillEditItem - toSectionWithIdentifier:SectionIdentifierAutofill]; - AutofillDataItem* autofillItemWithMainLeading = [[AutofillDataItem alloc] initWithType:ItemTypeAutofillData]; autofillItemWithMainLeading.text = @"Main Text";
diff --git a/ios/chrome/browser/ui/table_view/cells/BUILD.gn b/ios/chrome/browser/ui/table_view/cells/BUILD.gn index a7f463a..a559b47 100644 --- a/ios/chrome/browser/ui/table_view/cells/BUILD.gn +++ b/ios/chrome/browser/ui/table_view/cells/BUILD.gn
@@ -26,6 +26,8 @@ "table_view_link_header_footer_item.mm", "table_view_text_button_item.h", "table_view_text_button_item.mm", + "table_view_text_edit_item.h", + "table_view_text_edit_item.mm", "table_view_text_header_footer_item.h", "table_view_text_header_footer_item.mm", "table_view_text_item.h", @@ -40,6 +42,7 @@ deps = [ "resources:table_view_cell_chevron", + "resources:table_view_cell_edit_icon", "resources:table_view_cell_favicon_background", "//base", "//base:i18n", @@ -68,6 +71,7 @@ "table_view_image_item_unittest.mm", "table_view_item_unittest.mm", "table_view_text_button_item_unittest.mm", + "table_view_text_edit_item_unittest.mm", "table_view_text_header_footer_item_unittest.mm", "table_view_text_item_unittest.mm", "table_view_url_item_unittest.mm",
diff --git a/ios/chrome/browser/ui/table_view/cells/resources/BUILD.gn b/ios/chrome/browser/ui/table_view/cells/resources/BUILD.gn index 55294924..b98df7d1 100644 --- a/ios/chrome/browser/ui/table_view/cells/resources/BUILD.gn +++ b/ios/chrome/browser/ui/table_view/cells/resources/BUILD.gn
@@ -30,3 +30,11 @@ "table_view_cell_favicon_background.imageset/table_view_cell_favicon_background@3x.png", ] } + +imageset("table_view_cell_edit_icon") { + sources = [ + "table_view_cell_edit_icon.imageset/Contents.json", + "table_view_cell_edit_icon.imageset/table_view_cell_edit_icon@2x.png", + "table_view_cell_edit_icon.imageset/table_view_cell_edit_icon@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/autofill/cells/resources/autofill_edit_item_icon.imageset/Contents.json b/ios/chrome/browser/ui/table_view/cells/resources/table_view_cell_edit_icon.imageset/Contents.json similarity index 74% rename from ios/chrome/browser/ui/autofill/cells/resources/autofill_edit_item_icon.imageset/Contents.json rename to ios/chrome/browser/ui/table_view/cells/resources/table_view_cell_edit_icon.imageset/Contents.json index d275f8b..894124ae 100644 --- a/ios/chrome/browser/ui/autofill/cells/resources/autofill_edit_item_icon.imageset/Contents.json +++ b/ios/chrome/browser/ui/table_view/cells/resources/table_view_cell_edit_icon.imageset/Contents.json
@@ -7,12 +7,12 @@ { "idiom": "universal", "scale": "2x", - "filename": "autofill_edit_item_icon@2x.png" + "filename": "table_view_cell_edit_icon@2x.png" }, { "idiom": "universal", "scale": "3x", - "filename": "autofill_edit_item_icon@3x.png" + "filename": "table_view_cell_edit_icon@3x.png" } ], "info": {
diff --git a/ios/chrome/browser/ui/autofill/cells/resources/autofill_edit_item_icon.imageset/autofill_edit_item_icon@2x.png b/ios/chrome/browser/ui/table_view/cells/resources/table_view_cell_edit_icon.imageset/table_view_cell_edit_icon@2x.png similarity index 100% rename from ios/chrome/browser/ui/autofill/cells/resources/autofill_edit_item_icon.imageset/autofill_edit_item_icon@2x.png rename to ios/chrome/browser/ui/table_view/cells/resources/table_view_cell_edit_icon.imageset/table_view_cell_edit_icon@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/autofill/cells/resources/autofill_edit_item_icon.imageset/autofill_edit_item_icon@3x.png b/ios/chrome/browser/ui/table_view/cells/resources/table_view_cell_edit_icon.imageset/table_view_cell_edit_icon@3x.png similarity index 100% rename from ios/chrome/browser/ui/autofill/cells/resources/autofill_edit_item_icon.imageset/autofill_edit_item_icon@3x.png rename to ios/chrome/browser/ui/table_view/cells/resources/table_view_cell_edit_icon.imageset/table_view_cell_edit_icon@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h new file mode 100644 index 0000000..c4a06e5 --- /dev/null +++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h
@@ -0,0 +1,66 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TABLE_VIEW_CELLS_TABLE_VIEW_TEXT_EDIT_ITEM_H_ +#define IOS_CHROME_BROWSER_UI_TABLE_VIEW_CELLS_TABLE_VIEW_TEXT_EDIT_ITEM_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" + +// Item to represent and configure an TableViewTextEditItem. It features a label +// and a text field. +@interface TableViewTextEditItem : TableViewItem + +// The name of the text field. +@property(nonatomic, copy) NSString* textFieldName; + +// The value of the text field. +@property(nonatomic, copy) NSString* textFieldValue; + +// An icon identifying the text field or its current value, if any. +@property(nonatomic, copy) UIImage* identifyingIcon; + +// Whether to hide or display the trailing edit icon. +@property(nonatomic, assign) BOOL hideEditIcon; + +// Whether this field is required. If YES, an "*" is appended to the name of the +// text field to indicate that the field is required. It is also used for +// validation purposes. +@property(nonatomic, getter=isRequired) BOOL required; + +// Whether the text field is enabled for editing. +@property(nonatomic, getter=isTextFieldEnabled) BOOL textFieldEnabled; + +// Controls the display of the return key when the keyboard is displaying. +@property(nonatomic, assign) UIReturnKeyType returnKeyType; + +// Keyboard type to be displayed when the text field becomes first responder. +@property(nonatomic, assign) UIKeyboardType keyboardType; + +// Controls autocapitalization behavior of the text field. +@property(nonatomic, assign) + UITextAutocapitalizationType autoCapitalizationType; + +@end + +// TableViewTextEditCell implements an TableViewCell subclass containing a label +// and a text field. +@interface TableViewTextEditCell : TableViewCell + +// Label at the leading edge of the cell. It displays the item's textFieldName. +@property(nonatomic, strong) UILabel* textLabel; + +// Text field at the trailing edge of the cell. It displays the item's +// |textFieldValue|. +@property(nonatomic, readonly, strong) UITextField* textField; + +// Whether the icon showing that the cell is editable should be displayed. +@property(nonatomic, assign) BOOL editIconDisplayed; + +- (void)setIdentifyingIcon:(UIImage*)icon; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TABLE_VIEW_CELLS_TABLE_VIEW_TEXT_EDIT_ITEM_H_
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.mm new file mode 100644 index 0000000..b600056 --- /dev/null +++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.mm
@@ -0,0 +1,323 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h" + +#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" +#import "ios/chrome/browser/ui/util/rtl_geometry.h" +#import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/ui_util/constraints_ui_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// Minimum gap between the label and the text field. +const CGFloat kLabelAndFieldGap = 5; +// Height/width of the edit icon. +const CGFloat kEditIconLength = 18; +} // namespace + +@implementation TableViewTextEditItem + +- (instancetype)initWithType:(NSInteger)type { + self = [super initWithType:type]; + if (self) { + self.cellClass = [TableViewTextEditCell class]; + _returnKeyType = UIReturnKeyNext; + _keyboardType = UIKeyboardTypeDefault; + _autoCapitalizationType = UITextAutocapitalizationTypeWords; + } + return self; +} + +#pragma mark TableViewItem + +- (void)configureCell:(TableViewTextEditCell*)cell + withStyler:(ChromeTableViewStyler*)styler { + [super configureCell:cell withStyler:styler]; + + NSString* textLabelFormat = self.required ? @"%@*" : @"%@"; + cell.textLabel.text = + [NSString stringWithFormat:textLabelFormat, self.textFieldName]; + cell.textField.text = self.textFieldValue; + if (self.textFieldName.length) { + cell.textField.accessibilityIdentifier = + [NSString stringWithFormat:@"%@_textField", self.textFieldName]; + } + if (styler.cellBackgroundColor) { + cell.textLabel.backgroundColor = styler.cellBackgroundColor; + cell.textField.backgroundColor = styler.cellBackgroundColor; + } else { + cell.textLabel.backgroundColor = styler.tableViewBackgroundColor; + cell.textField.backgroundColor = styler.tableViewBackgroundColor; + } + cell.textField.enabled = self.textFieldEnabled; + if (self.hideEditIcon) { + cell.textField.textColor = + self.textFieldEnabled + ? UIColorFromRGB(kTableViewTextLabelColorBlue) + : UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); + } else { + cell.textField.textColor = + UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); + cell.editIconDisplayed = self.textFieldEnabled; + } + [cell.textField addTarget:self + action:@selector(textFieldChanged:) + forControlEvents:UIControlEventEditingChanged]; + cell.textField.returnKeyType = self.returnKeyType; + cell.textField.keyboardType = self.keyboardType; + cell.textField.autocapitalizationType = self.autoCapitalizationType; + [cell setIdentifyingIcon:self.identifyingIcon]; +} + +#pragma mark Actions + +- (void)textFieldChanged:(UITextField*)textField { + self.textFieldValue = textField.text; +} + +@end + +#pragma mark - TableViewTextEditCell + +@interface TableViewTextEditCell () + +@property(nonatomic, strong) NSLayoutConstraint* iconHeightConstraint; +@property(nonatomic, strong) NSLayoutConstraint* iconWidthConstraint; +@property(nonatomic, strong) NSLayoutConstraint* textFieldTrailingConstraint; +@property(nonatomic, strong) NSLayoutConstraint* textLabelTrailingConstraint; + +@property(nonatomic, strong) NSLayoutConstraint* editIconHeightConstraint; +@property(nonatomic, strong) NSLayoutConstraint* iconTrailingConstraint; + +// When they are activated, the label and the text field are on one line. +// They conflict with the |accessibilityConstraints|. +@property(nonatomic, strong) NSArray<NSLayoutConstraint*>* standardConstraints; +// When they are activated, the label is on one line, the text field is on +// another line. They conflict with the |standardConstraints|. +@property(nonatomic, strong) + NSArray<NSLayoutConstraint*>* accessibilityConstraints; + +// UIImageView containing the icon identifying |textField| or its current value. +@property(nonatomic, readonly, strong) UIImageView* identifyingIconView; + +// UIImageView containing the icon indicating that |textField| is editable. +@property(nonatomic, strong) UIImageView* editIconView; + +@end + +@implementation TableViewTextEditCell + +@synthesize textLabel = _textLabel; + +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString*)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + self.isAccessibilityElement = YES; + UIView* contentView = self.contentView; + + _textLabel = [[UILabel alloc] init]; + _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + [_textLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh + forAxis:UILayoutConstraintAxisHorizontal]; + _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + _textLabel.adjustsFontForContentSizeCategory = YES; + [contentView addSubview:_textLabel]; + + _textField = [[UITextField alloc] init]; + _textField.translatesAutoresizingMaskIntoConstraints = NO; + _textField.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + _textField.adjustsFontForContentSizeCategory = YES; + [_textField + setContentCompressionResistancePriority:UILayoutPriorityDefaultLow + forAxis: + UILayoutConstraintAxisHorizontal]; + [contentView addSubview:_textField]; + + _textField.autocorrectionType = UITextAutocorrectionTypeNo; + _textField.clearButtonMode = UITextFieldViewModeWhileEditing; + _textField.contentVerticalAlignment = + UIControlContentVerticalAlignmentCenter; + + // Trailing con. + _identifyingIconView = [[UIImageView alloc] initWithFrame:CGRectZero]; + _identifyingIconView.translatesAutoresizingMaskIntoConstraints = NO; + [contentView addSubview:_identifyingIconView]; + + // Edit icon. + UIImage* editImage = [[UIImage imageNamed:@"table_view_cell_edit_icon"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + _editIconView = [[UIImageView alloc] initWithImage:editImage]; + _editIconView.tintColor = + UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); + _editIconView.translatesAutoresizingMaskIntoConstraints = NO; + [contentView addSubview:_editIconView]; + + // Set up the icons size constraints. They are activated here and updated in + // layoutSubviews. + _iconHeightConstraint = + [_identifyingIconView.heightAnchor constraintEqualToConstant:0]; + _iconWidthConstraint = + [_identifyingIconView.widthAnchor constraintEqualToConstant:0]; + _editIconHeightConstraint = + [_editIconView.heightAnchor constraintEqualToConstant:0]; + + _textFieldTrailingConstraint = [_textField.trailingAnchor + constraintEqualToAnchor:_editIconView.leadingAnchor]; + _textLabelTrailingConstraint = [_textLabel.trailingAnchor + constraintEqualToAnchor:_editIconView.leadingAnchor]; + _iconTrailingConstraint = [_editIconView.trailingAnchor + constraintEqualToAnchor:_identifyingIconView.leadingAnchor]; + + _standardConstraints = @[ + [_textField.firstBaselineAnchor + constraintEqualToAnchor:_textLabel.firstBaselineAnchor], + [_textField.leadingAnchor + constraintEqualToAnchor:_textLabel.trailingAnchor + constant:kLabelAndFieldGap], + ]; + + _accessibilityConstraints = @[ + [_textField.topAnchor constraintEqualToAnchor:_textLabel.bottomAnchor + constant:kTableViewVerticalSpacing], + [_textField.leadingAnchor + constraintEqualToAnchor:contentView.leadingAnchor + constant:kTableViewHorizontalSpacing], + _textLabelTrailingConstraint, + ]; + + // Set up the constraints. + [NSLayoutConstraint activateConstraints:@[ + [_textLabel.leadingAnchor + constraintEqualToAnchor:contentView.leadingAnchor + constant:kTableViewHorizontalSpacing], + _textFieldTrailingConstraint, + [_identifyingIconView.trailingAnchor + constraintEqualToAnchor:contentView.trailingAnchor + constant:-kTableViewHorizontalSpacing], + [_identifyingIconView.centerYAnchor + constraintEqualToAnchor:contentView.centerYAnchor], + [_editIconView.centerYAnchor + constraintEqualToAnchor:contentView.centerYAnchor], + _iconHeightConstraint, + _iconWidthConstraint, + _iconTrailingConstraint, + _editIconHeightConstraint, + [_editIconView.widthAnchor + constraintEqualToAnchor:_editIconView.heightAnchor], + ]]; + AddOptionalVerticalPadding(contentView, _textLabel, + kTableViewOneLabelCellVerticalSpacing); + AddOptionalVerticalPadding(contentView, _textField, + kTableViewOneLabelCellVerticalSpacing); + + [self updateForAccessibilityContentSizeCategory: + UIContentSizeCategoryIsAccessibilityCategory( + self.traitCollection.preferredContentSizeCategory)]; + } + return self; +} + +#pragma mark Public + +- (void)setEditIconDisplayed:(BOOL)editIconDisplayed { + if (editIconDisplayed == _editIconDisplayed) + return; + + _editIconDisplayed = editIconDisplayed; + self.editIconView.hidden = !editIconDisplayed; + if (editIconDisplayed) { + self.textFieldTrailingConstraint.constant = -kLabelAndFieldGap; + self.textLabelTrailingConstraint.constant = -kLabelAndFieldGap; + + _editIconHeightConstraint.constant = kEditIconLength; + } else { + self.textFieldTrailingConstraint.constant = 0; + self.textLabelTrailingConstraint.constant = 0; + + _editIconHeightConstraint.constant = 0; + } +} + +- (void)setIdentifyingIcon:(UIImage*)icon { + self.identifyingIconView.image = icon; + if (icon) { + self.iconTrailingConstraint.constant = -kLabelAndFieldGap; + + // Set the size constraints of the icon view to the dimensions of the image. + self.iconHeightConstraint.constant = icon.size.height; + self.iconWidthConstraint.constant = icon.size.width; + } else { + self.iconTrailingConstraint.constant = 0; + self.iconHeightConstraint.constant = 0; + self.iconWidthConstraint.constant = 0; + } +} + +- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + BOOL isCurrentCategoryAccessibility = + UIContentSizeCategoryIsAccessibilityCategory( + self.traitCollection.preferredContentSizeCategory); + if (isCurrentCategoryAccessibility != + UIContentSizeCategoryIsAccessibilityCategory( + previousTraitCollection.preferredContentSizeCategory)) { + [self updateForAccessibilityContentSizeCategory: + isCurrentCategoryAccessibility]; + } +} + +#pragma mark - UITableViewCell + +- (void)prepareForReuse { + [super prepareForReuse]; + self.textLabel.text = nil; + self.textField.text = nil; + self.textField.returnKeyType = UIReturnKeyNext; + self.textField.keyboardType = UIKeyboardTypeDefault; + self.textField.autocapitalizationType = UITextAutocapitalizationTypeWords; + self.textField.autocorrectionType = UITextAutocorrectionTypeNo; + self.textField.clearButtonMode = UITextFieldViewModeWhileEditing; + self.textField.accessibilityIdentifier = nil; + self.textField.enabled = NO; + self.textField.delegate = nil; + [self.textField removeTarget:nil + action:nil + forControlEvents:UIControlEventAllEvents]; + self.identifyingIconView.image = nil; +} + +#pragma mark Accessibility + +- (NSString*)accessibilityLabel { + return [NSString + stringWithFormat:@"%@, %@", self.textLabel.text, self.textField.text]; +} + +#pragma mark Private + +// Updates the cell such as it is layouted correctly with regard to the +// preferred content size category, if it is an +// |accessibilityContentSizeCategory| or not. +- (void)updateForAccessibilityContentSizeCategory: + (BOOL)accessibilityContentSizeCategory { + if (accessibilityContentSizeCategory) { + [NSLayoutConstraint deactivateConstraints:_standardConstraints]; + [NSLayoutConstraint activateConstraints:_accessibilityConstraints]; + _textField.textAlignment = + UseRTLLayout() ? NSTextAlignmentRight : NSTextAlignmentLeft; + } else { + [NSLayoutConstraint deactivateConstraints:_accessibilityConstraints]; + [NSLayoutConstraint activateConstraints:_standardConstraints]; + _textField.textAlignment = + UseRTLLayout() ? NSTextAlignmentLeft : NSTextAlignmentRight; + } +} + +@end
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item_unittest.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item_unittest.mm new file mode 100644 index 0000000..384cfe0a --- /dev/null +++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item_unittest.mm
@@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h" + +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" +#include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using TableViewTextEditItemTest = PlatformTest; + +// Tests that the label and text field are set properly after a call to +// |configureCell:|. +TEST_F(TableViewTextEditItemTest, ConfigureCell) { + TableViewTextEditItem* item = [[TableViewTextEditItem alloc] initWithType:0]; + NSString* name = @"Name"; + NSString* value = @"Value"; + BOOL enabled = NO; + + item.textFieldName = name; + item.textFieldValue = value; + item.textFieldEnabled = enabled; + + id cell = [[[item cellClass] alloc] init]; + ASSERT_TRUE([cell isMemberOfClass:[TableViewTextEditCell class]]); + + TableViewTextEditCell* textEditCell = cell; + EXPECT_EQ(0U, textEditCell.textLabel.text.length); + EXPECT_EQ(0U, textEditCell.textField.text.length); + EXPECT_TRUE(textEditCell.textField.enabled); + + [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; + EXPECT_NSEQ(name, textEditCell.textLabel.text); + EXPECT_NSEQ(value, textEditCell.textField.text); + EXPECT_FALSE(textEditCell.textField.enabled); +}
diff --git a/ios/chrome/browser/ui/webui/BUILD.gn b/ios/chrome/browser/ui/webui/BUILD.gn index 02a25b712..188f0f4 100644 --- a/ios/chrome/browser/ui/webui/BUILD.gn +++ b/ios/chrome/browser/ui/webui/BUILD.gn
@@ -100,6 +100,7 @@ "//ios/chrome/browser/ui/webui/gcm", "//ios/chrome/browser/ui/webui/net_export", "//ios/chrome/browser/ui/webui/sync_internals", + "//ios/chrome/browser/ui/webui/translate_internals", "//ios/web", "//services/identity/public/cpp", "//url",
diff --git a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm index 303ee10..5a4e552 100644 --- a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm +++ b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
@@ -23,6 +23,7 @@ #include "ios/chrome/browser/ui/webui/suggestions_ui.h" #include "ios/chrome/browser/ui/webui/sync_internals/sync_internals_ui.h" #include "ios/chrome/browser/ui/webui/terms_ui.h" +#include "ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.h" #include "ios/chrome/browser/ui/webui/ukm_internals_ui.h" #include "ios/chrome/browser/ui/webui/user_actions_ui.h" #include "ios/chrome/browser/ui/webui/version_ui.h" @@ -89,6 +90,8 @@ return &NewWebUIIOS<SignInInternalsUIIOS>; if (url.host_piece() == kChromeUISuggestionsHost) return &NewWebUIIOS<suggestions::SuggestionsUI>; + if (url.host_piece() == kChromeUITranslateInternalsHost) + return &NewWebUIIOS<TranslateInternalsUI>; if (url_host == kChromeUIURLKeyedMetricsHost) return &NewWebUIIOS<UkmInternalsUI>; if (url_host == kChromeUIUserActionsHost)
diff --git a/ios/chrome/browser/ui/webui/translate_internals/BUILD.gn b/ios/chrome/browser/ui/webui/translate_internals/BUILD.gn new file mode 100644 index 0000000..0771ed4 --- /dev/null +++ b/ios/chrome/browser/ui/webui/translate_internals/BUILD.gn
@@ -0,0 +1,25 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("translate_internals") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "ios_translate_internals_handler.h", + "ios_translate_internals_handler.mm", + "translate_internals_ui.h", + "translate_internals_ui.mm", + ] + deps = [ + "//components/language/ios/browser", + "//components/translate/core/common", + "//components/translate/translate_internals", + "//ios/chrome/app/resources:ios_resources", + "//ios/chrome/browser", + "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/tabs", + "//ios/chrome/browser/translate", + "//ios/chrome/browser/web_state_list", + "//ios/web/public", + ] +}
diff --git a/ios/chrome/browser/ui/webui/translate_internals/ios_translate_internals_handler.h b/ios/chrome/browser/ui/webui/translate_internals/ios_translate_internals_handler.h new file mode 100644 index 0000000..27dffad --- /dev/null +++ b/ios/chrome/browser/ui/webui/translate_internals/ios_translate_internals_handler.h
@@ -0,0 +1,80 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_WEBUI_TRANSLATE_INTERNALS_IOS_TRANSLATE_INTERNALS_HANDLER_H_ +#define IOS_CHROME_BROWSER_UI_WEBUI_TRANSLATE_INTERNALS_IOS_TRANSLATE_INTERNALS_HANDLER_H_ + +#include <string> + +#include "base/macros.h" +#include "base/scoped_observer.h" +#include "components/language/ios/browser/ios_language_detection_tab_helper.h" +#include "components/translate/translate_internals/translate_internals_handler.h" +#import "ios/chrome/browser/web_state_list/web_state_list_observer.h" +#include "ios/web/public/webui/web_ui_ios_message_handler.h" + +namespace web { +class WebState; +} // namespace web + +// The handler for JavaScript messages for chrome://translate-internals. +class IOSTranslateInternalsHandler + : public translate::TranslateInternalsHandler, + public web::WebUIIOSMessageHandler, + public WebStateListObserver, + public language::IOSLanguageDetectionTabHelper::Observer { + public: + IOSTranslateInternalsHandler(); + ~IOSTranslateInternalsHandler() override; + + // translate::TranslateInternalsHandler. + translate::TranslateClient* GetTranslateClient() override; + variations::VariationsService* GetVariationsService() override; + void RegisterMessageCallback(const std::string& message, + const MessageCallback& callback) override; + void CallJavascriptFunction( + const std::string& function_name, + const std::vector<const base::Value*>& args) override; + + // web::WebUIIOSMessageHandler. + void RegisterMessages() override; + + // WebStateListObserver. + void WebStateInsertedAt(WebStateList* web_state_list, + web::WebState* web_state, + int index, + bool activating) override; + void WebStateReplacedAt(WebStateList* web_state_list, + web::WebState* old_web_state, + web::WebState* new_web_state, + int index) override; + void WebStateDetachedAt(WebStateList* web_state_list, + web::WebState* web_state, + int index) override; + + // language::IOSLanguageDetectionTabHelper::Observer + void OnLanguageDetermined( + const translate::LanguageDetectionDetails& details) override; + void IOSLanguageDetectionTabHelperWasDestroyed( + language::IOSLanguageDetectionTabHelper* tab_helper) override; + + private: + // Adds this instance as an observer of the IOSLanguageDetectionTabHelper + // associated with |web_state|. + void AddLanguageDetectionObserverForWebState(web::WebState* web_state); + // Removes this instance as an observer of the IOSLanguageDetectionTabHelper + // associated with |web_state|. + void RemoveLanguageDetectionObserverForWebState(web::WebState* web_state); + + std::unique_ptr<ScopedObserver<WebStateList, WebStateListObserver>> + scoped_web_state_list_observer_; + std::unique_ptr< + ScopedObserver<language::IOSLanguageDetectionTabHelper, + language::IOSLanguageDetectionTabHelper::Observer>> + scoped_tab_helper_observer_; + + DISALLOW_COPY_AND_ASSIGN(IOSTranslateInternalsHandler); +}; + +#endif // IOS_CHROME_BROWSER_UI_WEBUI_TRANSLATE_INTERNALS_IOS_TRANSLATE_INTERNALS_HANDLER_H_
diff --git a/ios/chrome/browser/ui/webui/translate_internals/ios_translate_internals_handler.mm b/ios/chrome/browser/ui/webui/translate_internals/ios_translate_internals_handler.mm new file mode 100644 index 0000000..98b6694 --- /dev/null +++ b/ios/chrome/browser/ui/webui/translate_internals/ios_translate_internals_handler.mm
@@ -0,0 +1,126 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/webui/translate_internals/ios_translate_internals_handler.h" + +#include "components/translate/core/common/language_detection_details.h" +#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/tabs/tab_model.h" +#import "ios/chrome/browser/tabs/tab_model_list.h" +#include "ios/chrome/browser/translate/chrome_ios_translate_client.h" +#include "ios/chrome/browser/translate/translate_service_ios.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" +#include "ios/web/public/web_state/web_state.h" +#include "ios/web/public/webui/web_ui_ios.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +IOSTranslateInternalsHandler::IOSTranslateInternalsHandler() + : scoped_web_state_list_observer_( + std::make_unique<ScopedObserver<WebStateList, WebStateListObserver>>( + this)), + scoped_tab_helper_observer_( + std::make_unique<ScopedObserver< + language::IOSLanguageDetectionTabHelper, + language::IOSLanguageDetectionTabHelper::Observer>>(this)) {} + +IOSTranslateInternalsHandler::~IOSTranslateInternalsHandler() {} + +translate::TranslateClient* IOSTranslateInternalsHandler::GetTranslateClient() { + return ChromeIOSTranslateClient::FromWebState(web_ui()->GetWebState()); +} + +variations::VariationsService* +IOSTranslateInternalsHandler::GetVariationsService() { + return GetApplicationContext()->GetVariationsService(); +} + +void IOSTranslateInternalsHandler::RegisterMessageCallback( + const std::string& message, + const MessageCallback& callback) { + web_ui()->RegisterMessageCallback(message, callback); +} + +void IOSTranslateInternalsHandler::CallJavascriptFunction( + const std::string& function_name, + const std::vector<const base::Value*>& args) { + web_ui()->CallJavascriptFunction(function_name, args); +} + +void IOSTranslateInternalsHandler::RegisterMessages() { + web::BrowserState* browser_state = web_ui()->GetWebState()->GetBrowserState(); + ios::ChromeBrowserState* chrome_browser_state = + ios::ChromeBrowserState::FromBrowserState(browser_state) + ->GetOriginalChromeBrowserState(); + NSArray<TabModel*>* tab_models = + TabModelList::GetTabModelsForChromeBrowserState(chrome_browser_state); + for (TabModel* tab_model in tab_models) { + scoped_web_state_list_observer_->Add(tab_model.webStateList); + for (int i = 0; i < tab_model.webStateList->count(); i++) { + AddLanguageDetectionObserverForWebState( + tab_model.webStateList->GetWebStateAt(i)); + } + } + + RegisterMessageCallbacks(); +} + +void IOSTranslateInternalsHandler::WebStateInsertedAt( + WebStateList* web_state_list, + web::WebState* web_state, + int index, + bool activating) { + AddLanguageDetectionObserverForWebState(web_state); +} + +void IOSTranslateInternalsHandler::WebStateReplacedAt( + WebStateList* web_state_list, + web::WebState* old_web_state, + web::WebState* new_web_state, + int index) { + RemoveLanguageDetectionObserverForWebState(old_web_state); + AddLanguageDetectionObserverForWebState(new_web_state); +} + +void IOSTranslateInternalsHandler::WebStateDetachedAt( + WebStateList* web_state_list, + web::WebState* web_state, + int index) { + RemoveLanguageDetectionObserverForWebState(web_state); +} + +void IOSTranslateInternalsHandler::OnLanguageDetermined( + const translate::LanguageDetectionDetails& details) { + if (web_ui()->GetWebState()->GetBrowserState()->IsOffTheRecord() || + !GetTranslateClient()->IsTranslatableURL(details.url)) { + return; + } + + AddLanguageDetectionDetails(details); +} + +void IOSTranslateInternalsHandler::IOSLanguageDetectionTabHelperWasDestroyed( + language::IOSLanguageDetectionTabHelper* tab_helper) { + // No-op. The IOSLanguageDetectionTabHelper is stopped being observed in + // WebStateListObserver callbacks. +} + +void IOSTranslateInternalsHandler::AddLanguageDetectionObserverForWebState( + web::WebState* web_state) { + language::IOSLanguageDetectionTabHelper* tab_helper = + language::IOSLanguageDetectionTabHelper::FromWebState(web_state); + if (!scoped_tab_helper_observer_->IsObserving(tab_helper)) { + scoped_tab_helper_observer_->Add(tab_helper); + } +} + +void IOSTranslateInternalsHandler::RemoveLanguageDetectionObserverForWebState( + web::WebState* web_state) { + language::IOSLanguageDetectionTabHelper* tab_helper = + language::IOSLanguageDetectionTabHelper::FromWebState(web_state); + scoped_tab_helper_observer_->Remove(tab_helper); +}
diff --git a/ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.h b/ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.h new file mode 100644 index 0000000..dac50a5 --- /dev/null +++ b/ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.h
@@ -0,0 +1,25 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_WEBUI_TRANSLATE_INTERNALS_TRANSLATE_INTERNALS_UI_H_ +#define IOS_CHROME_BROWSER_UI_WEBUI_TRANSLATE_INTERNALS_TRANSLATE_INTERNALS_UI_H_ + +#include "base/macros.h" +#include "ios/web/public/webui/web_ui_ios_controller.h" + +namespace web { +class WebUIIOS; +} + +// The WebUI controller for chrome://translate-internals. +class TranslateInternalsUI : public web::WebUIIOSController { + public: + explicit TranslateInternalsUI(web::WebUIIOS* web_ui); + ~TranslateInternalsUI() override; + + private: + DISALLOW_COPY_AND_ASSIGN(TranslateInternalsUI); +}; + +#endif // IOS_CHROME_BROWSER_UI_WEBUI_TRANSLATE_INTERNALS_TRANSLATE_INTERNALS_UI_H_
diff --git a/ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.mm b/ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.mm new file mode 100644 index 0000000..a3cf78cf --- /dev/null +++ b/ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.mm
@@ -0,0 +1,59 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.h" + +#include <string> + +#import "components/translate/translate_internals/translate_internals_handler.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/ui/webui/translate_internals/ios_translate_internals_handler.h" +#include "ios/chrome/grit/ios_resources.h" +#include "ios/web/public/web_ui_ios_data_source.h" +#include "ios/web/public/webui/web_ui_ios.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +// Creates a WebUI data source for chrome://translate-internals page. +// Changes to this should be in sync with its non-iOS equivalent +// chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc +web::WebUIIOSDataSource* CreateTranslateInternalsHTMLSource() { + web::WebUIIOSDataSource* source = + web::WebUIIOSDataSource::Create(kChromeUITranslateInternalsHost); + + source->SetDefaultResource(IDR_IOS_TRANSLATE_INTERNALS_HTML); + source->SetJsonPath("strings.js"); + source->AddResourcePath("translate_internals.js", + IDR_IOS_TRANSLATE_INTERNALS_JS); + source->UseGzip(); + + base::DictionaryValue langs; + translate::TranslateInternalsHandler::GetLanguages(&langs); + for (base::DictionaryValue::Iterator it(langs); !it.IsAtEnd(); it.Advance()) { + std::string key = "language-" + it.key(); + std::string value; + it.value().GetAsString(&value); + source->AddString(key, value); + } + + source->AddString("cld-version", "3"); + + return source; +} + +} // namespace + +TranslateInternalsUI::TranslateInternalsUI(web::WebUIIOS* web_ui) + : web::WebUIIOSController(web_ui) { + web_ui->AddMessageHandler(std::make_unique<IOSTranslateInternalsHandler>()); + web::WebUIIOSDataSource::Add(ios::ChromeBrowserState::FromWebUIIOS(web_ui), + CreateTranslateInternalsHTMLSource()); +} + +TranslateInternalsUI::~TranslateInternalsUI() {}
diff --git a/ios/web/shell/test/BUILD.gn b/ios/web/shell/test/BUILD.gn index eb07f38..6cb8818 100644 --- a/ios/web/shell/test/BUILD.gn +++ b/ios/web/shell/test/BUILD.gn
@@ -79,6 +79,8 @@ "earl_grey/shell_actions.mm", "earl_grey/shell_earl_grey.h", "earl_grey/shell_earl_grey.mm", + "earl_grey/shell_earl_grey_app_interface.h", + "earl_grey/shell_earl_grey_app_interface.mm", "earl_grey/shell_matchers.h", "earl_grey/shell_matchers.mm", "earl_grey/shell_matchers_shorthand.h",
diff --git a/ios/web/shell/test/context_menu_egtest.mm b/ios/web/shell/test/context_menu_egtest.mm index 091170452..8d050cd 100644 --- a/ios/web/shell/test/context_menu_egtest.mm +++ b/ios/web/shell/test/context_menu_egtest.mm
@@ -54,10 +54,10 @@ const char linkText[] = "normal-link-text"; const GURL pageURL = _server.GetURL(kHtmlFile); - bool success = [ShellEarlGrey loadURL:pageURL]; + bool success = shell_test_util::LoadUrl(pageURL); GREYAssert(success, @"Page did not complete loading."); - success = [ShellEarlGrey waitForWebViewContainingText:linkText]; + success = shell_test_util::WaitForWebViewContainingText(linkText); GREYAssert(success, @"Failed waiting for web view containing '%s'", linkText); [[EarlGrey selectElementWithMatcher:web::WebView()] @@ -85,9 +85,9 @@ const char linkText[] = "no-webkit-link-text"; const GURL pageURL = _server.GetURL(kHtmlFile); - bool success = [ShellEarlGrey loadURL:pageURL]; + bool success = shell_test_util::LoadUrl(pageURL); GREYAssert(success, @"Page did not complete loading."); - success = [ShellEarlGrey waitForWebViewContainingText:linkText]; + success = shell_test_util::WaitForWebViewContainingText(linkText); GREYAssert(success, @"Failed waiting for web view containing '%s'", linkText); [[EarlGrey selectElementWithMatcher:web::WebView()]
diff --git a/ios/web/shell/test/earl_grey/shell_earl_grey.h b/ios/web/shell/test/earl_grey/shell_earl_grey.h index 66a0e88..b19ae4f 100644 --- a/ios/web/shell/test/earl_grey/shell_earl_grey.h +++ b/ios/web/shell/test/earl_grey/shell_earl_grey.h
@@ -13,18 +13,18 @@ // Test methods that perform actions on Web Shell. These methods may read or // alter Web Shell's internal state programmatically or via the UI, but in both // cases will properly synchronize the UI for Earl Grey tests. -@interface ShellEarlGrey : NSObject +namespace shell_test_util { // Loads |URL| in the current WebState with transition of type // ui::PAGE_TRANSITION_TYPED, and waits for the page to complete loading, or // a timeout. Returns false if the page doesn't finish loading, true if it // does. -+ (bool)loadURL:(const GURL&)URL WARN_UNUSED_RESULT; +bool LoadUrl(const GURL& url) WARN_UNUSED_RESULT; // Waits for the current web view to contain |text|. If the condition is not met // within a timeout, it returns false, otherwise, true. -+ (bool)waitForWebViewContainingText:(const std::string)text WARN_UNUSED_RESULT; +bool WaitForWebViewContainingText(const std::string& text) WARN_UNUSED_RESULT; -@end +} // namespace shell_test_util #endif // IOS_WEB_SHELL_TEST_EARL_GREY_SHELL_EARL_GREY_H_
diff --git a/ios/web/shell/test/earl_grey/shell_earl_grey.mm b/ios/web/shell/test/earl_grey/shell_earl_grey.mm index 4878039..bf23f64 100644 --- a/ios/web/shell/test/earl_grey/shell_earl_grey.mm +++ b/ios/web/shell/test/earl_grey/shell_earl_grey.mm
@@ -6,15 +6,11 @@ #import <EarlGrey/EarlGrey.h> +#import "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" -#import "ios/web/public/test/earl_grey/js_test_util.h" -#include "ios/web/public/test/element_selector.h" -#import "ios/web/public/test/navigation_test_util.h" -#import "ios/web/public/test/web_view_content_test_util.h" -#import "ios/web/public/test/web_view_interaction_test_util.h" -#include "ios/web/shell/test/app/navigation_test_util.h" -#import "ios/web/shell/test/app/web_shell_test_util.h" +#import "ios/web/shell/test/earl_grey/shell_earl_grey_app_interface.h" +using base::test::ios::kWaitForPageLoadTimeout; using base::test::ios::kWaitForUIElementTimeout; using base::test::ios::WaitUntilConditionOrTimeout; @@ -22,19 +18,22 @@ #error "This file requires ARC support." #endif -@implementation ShellEarlGrey +namespace shell_test_util { -+ (bool)loadURL:(const GURL&)URL { - web::shell_test_util::LoadUrl(URL); - web::WebState* webState = web::shell_test_util::GetCurrentWebState(); +bool LoadUrl(const GURL& url) { + [ShellEarlGreyAppInterface loadURL:base::SysUTF8ToNSString(url.spec())]; - if (!web::test::WaitForPageToFinishLoading(webState)) + bool load_success = WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{ + return ![ShellEarlGreyAppInterface isCurrentWebStateLoading]; + }); + if (!load_success) { return false; + } - if (webState->ContentIsHTML()) { - if (!web::WaitUntilWindowIdInjected(webState)) { - return false; - } + bool injection_success = + [ShellEarlGreyAppInterface waitForWindowIDInjectedInCurrentWebState]; + if (!injection_success) { + return false; } // Ensure any UI elements handled by EarlGrey become idle for any subsequent @@ -43,11 +42,11 @@ return true; } -+ (bool)waitForWebViewContainingText:(std::string)text { +bool WaitForWebViewContainingText(const std::string& text) { return WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^bool { - return web::test::IsWebViewContainingText( - web::shell_test_util::GetCurrentWebState(), text); + return [ShellEarlGreyAppInterface + currentWebStateContainsText:base::SysUTF8ToNSString(text)]; }); } -@end +} // namespace shell_test_util
diff --git a/ios/web/shell/test/earl_grey/shell_earl_grey_app_interface.h b/ios/web/shell/test/earl_grey/shell_earl_grey_app_interface.h new file mode 100644 index 0000000..03eb265 --- /dev/null +++ b/ios/web/shell/test/earl_grey/shell_earl_grey_app_interface.h
@@ -0,0 +1,34 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_SHELL_TEST_EARL_GREY_SHELL_EARL_GREY_APP_INTERFACE_H_ +#define IOS_WEB_SHELL_TEST_EARL_GREY_SHELL_EARL_GREY_APP_INTERFACE_H_ + +#import <Foundation/Foundation.h> + +#include "base/compiler_specific.h" + +// Test methods that perform actions on Web Shell. These methods may read or +// alter Web Shell's internal state programmatically or via the UI, but in both +// cases will properly synchronize the UI for Earl Grey tests. +@interface ShellEarlGreyAppInterface : NSObject + +// Loads |URL| in the current WebState with transition of type +// ui::PAGE_TRANSITION_TYPED and returns without waiting for the page to load. ++ (void)loadURL:(NSString*)spec; + +// Returns YES if the current WebState is loading. ++ (BOOL)isCurrentWebStateLoading WARN_UNUSED_RESULT; + +// Returns YES if the windowID has been injected into the current web state. If +// the WebState contains content that does not require windowID injection, +// returns YES immediately. ++ (BOOL)waitForWindowIDInjectedInCurrentWebState WARN_UNUSED_RESULT; + +// Returns YES if the current WebState contains the given |text|. ++ (BOOL)currentWebStateContainsText:(NSString*)text WARN_UNUSED_RESULT; + +@end + +#endif // IOS_WEB_SHELL_TEST_EARL_GREY_SHELL_EARL_GREY_APP_INTERFACE_H_
diff --git a/ios/web/shell/test/earl_grey/shell_earl_grey_app_interface.mm b/ios/web/shell/test/earl_grey/shell_earl_grey_app_interface.mm new file mode 100644 index 0000000..e751576 --- /dev/null +++ b/ios/web/shell/test/earl_grey/shell_earl_grey_app_interface.mm
@@ -0,0 +1,42 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/shell/test/earl_grey/shell_earl_grey_app_interface.h" + +#import <EarlGrey/EarlGrey.h> + +#import "base/strings/sys_string_conversions.h" +#import "base/test/ios/wait_util.h" +#import "ios/web/public/test/earl_grey/js_test_util.h" +#import "ios/web/public/test/navigation_test_util.h" +#import "ios/web/public/test/web_view_content_test_util.h" +#import "ios/web/public/web_state/web_state.h" +#import "ios/web/shell/test/app/web_shell_test_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using web::shell_test_util::GetCurrentWebState; + +@implementation ShellEarlGreyAppInterface + ++ (void)loadURL:(NSString*)spec { + web::test::LoadUrl(GetCurrentWebState(), GURL(base::SysNSStringToUTF8(spec))); +} + ++ (BOOL)isCurrentWebStateLoading { + return GetCurrentWebState()->IsLoading(); +} + ++ (BOOL)waitForWindowIDInjectedInCurrentWebState { + return web::WaitUntilWindowIdInjected(GetCurrentWebState()); +} + ++ (BOOL)currentWebStateContainsText:(NSString*)text { + return web::test::IsWebViewContainingText(GetCurrentWebState(), + base::SysNSStringToUTF8(text)); +} + +@end
diff --git a/ios/web/shell/test/page_state_egtest.mm b/ios/web/shell/test/page_state_egtest.mm index b7edc1a..f240bcdf 100644 --- a/ios/web/shell/test/page_state_egtest.mm +++ b/ios/web/shell/test/page_state_egtest.mm
@@ -55,7 +55,7 @@ // be {0, 0} before returning. void ScrollLongPageToTop(const GURL& url) { // Load the page and swipe down. - bool success = [ShellEarlGrey loadURL:url]; + bool success = shell_test_util::LoadUrl(url); GREYAssert(success, @"Page did not complete loading."); [[EarlGrey selectElementWithMatcher:web::WebViewScrollView()] performAction:grey_scrollToContentEdge(kGREYContentEdgeTop)]; @@ -113,7 +113,7 @@ - (void)testZeroContentOffsetAfterLoad { // Set up the file-based server to load the tall page. const GURL baseURL = _server.GetURL(kLongPage1); - bool success = [ShellEarlGrey loadURL:baseURL]; + bool success = shell_test_util::LoadUrl(baseURL); GREYAssert(success, @"Page did not complete loading."); // Scroll the page and load again to verify that the new page's scroll offset @@ -127,8 +127,9 @@ // Add a query parameter so the next load creates another NavigationItem. GURL::Replacements replacements; replacements.SetQueryStr(base::NumberToString(i)); - GREYAssert([ShellEarlGrey loadURL:baseURL.ReplaceComponents(replacements)], - @"Page did not complete loading."); + bool success = + shell_test_util::LoadUrl(baseURL.ReplaceComponents(replacements)); + GREYAssert(success, @"Page did not complete loading."); // Wait for the content offset to be set to {0, 0}. WaitForOffset(0.0); }
diff --git a/ios/web/web_state/js/resources/message.js b/ios/web/web_state/js/resources/message.js index 3a75562..b723725 100644 --- a/ios/web/web_state/js/resources/message.js +++ b/ios/web/web_state/js/resources/message.js
@@ -273,8 +273,7 @@ getFrameSymmetricKey_(function(frameKey) { window.crypto.subtle.decrypt(algorithm, frameKey, encryptedFunctionArray) .then(function(decrypted) { - var callJSON = - String.fromCharCode.apply(null, new Uint8Array(decrypted)); + var callJSON = new TextDecoder().decode(new Uint8Array(decrypted)); var callDict = JSON.parse(callJSON); // Verify that message id is valid.
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index 3433ba1..912ae0edb 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -2034,13 +2034,7 @@ } // Tests failed load after the navigation is sucessfully finished. -// TODO(crbug.com/845879): test is flaky (probably since crrev.com/1056203). -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_FailedLoad FailedLoad -#else -#define MAYBE_FailedLoad FLAKY_FailedLoad -#endif -TEST_P(WebStateObserverTest, FLAKY_FailedLoad) { +TEST_P(WebStateObserverTest, FailedLoad) { GURL url = test_server_->GetURL("/exabyte_response"); NavigationContext* context = nullptr;
diff --git a/media/capture/video/OWNERS b/media/capture/video/OWNERS index ea5ac3b3..8b3d667 100644 --- a/media/capture/video/OWNERS +++ b/media/capture/video/OWNERS
@@ -1,7 +1,9 @@ emircan@chromium.org chfremer@chromium.org -mcasas@chromium.org tommi@chromium.org -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# Original (legacy) owner. +mcasas@chromium.org + # COMPONENT: Blink>GetUserMedia>WebCam +# TEAM: webrtc-dev@chromium.org
diff --git a/media/capture/video/android/java/src/org/chromium/media/OWNERS b/media/capture/video/android/java/src/org/chromium/media/OWNERS index e34b150738..939f3d261 100644 --- a/media/capture/video/android/java/src/org/chromium/media/OWNERS +++ b/media/capture/video/android/java/src/org/chromium/media/OWNERS
@@ -1,5 +1,7 @@ -mcasas@chromium.org qinmin@chromium.org -# media-capture-and-streams@grotations.appspotmail.com +# Original (legacy) owner. +mcasas@chromium.org + # COMPONENT: Blink>GetUserMedia>WebCam +# TEAM: webrtc-dev@chromium.org
diff --git a/media/muxers/OWNERS b/media/muxers/OWNERS index 2198557..92570f5 100644 --- a/media/muxers/OWNERS +++ b/media/muxers/OWNERS
@@ -1,4 +1,7 @@ -mcasas@chromium.org miu@chromium.org +# Original (legacy) owner. +mcasas@chromium.org + # COMPONENT: Blink>MediaRecording +# TEAM: webrtc-dev@chromium.org
diff --git a/net/BUILD.gn b/net/BUILD.gn index f2b371d..efc93fa8 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -2329,6 +2329,14 @@ } } +if (is_android) { + java_cpp_enum("effective_connection_type_java") { + sources = [ + "//net/nqe/effective_connection_type.h", + ] + } +} + grit("net_resources") { source = "base/net_resources.grd" outputs = [
diff --git a/net/disk_cache/blockfile/entry_impl.cc b/net/disk_cache/blockfile/entry_impl.cc index 9bc513c..7323333 100644 --- a/net/disk_cache/blockfile/entry_impl.cc +++ b/net/disk_cache/blockfile/entry_impl.cc
@@ -183,6 +183,12 @@ DCHECK_GE(offset, 0); DCHECK_GE(len, 0); DCHECK_GE(offset + len, 0); + + // 0-length writes that don't extend can just be ignored here, and are safe + // even if they're are before offset_, as truncates are handled elsewhere. + if (len == 0 && offset < End()) + return; + DCHECK_GE(offset, offset_); DVLOG(3) << "Buffer write at " << offset << " current " << offset_;
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc index 2fe639b8..0611436a 100644 --- a/net/disk_cache/entry_unittest.cc +++ b/net/disk_cache/entry_unittest.cc
@@ -94,6 +94,7 @@ void CloseSparseAfterBackendDestruction(); void LastUsedTimePersists(); void TruncateBackwards(); + void ZeroWriteBackwards(); }; // This part of the test runs on the background thread. @@ -5155,6 +5156,56 @@ TruncateBackwards(); } +void DiskCacheEntryTest::ZeroWriteBackwards() { + const char kKey[] = "a key"; + + disk_cache::Entry* entry = nullptr; + ASSERT_THAT(CreateEntry(kKey, &entry), IsOk()); + ASSERT_TRUE(entry != nullptr); + + const int kSize = 1024; + scoped_refptr<net::IOBuffer> buffer = + base::MakeRefCounted<net::IOBuffer>(kSize); + CacheTestFillBuffer(buffer->data(), kSize, false); + + // Offset here needs to be > blockfile's kMaxBlockSize to hit + // https://crbug.com/946538, as writes close to beginning are handled + // specially. + EXPECT_EQ(0, WriteData(entry, /* stream_index = */ 0, + /* offset = */ 17000, buffer.get(), + /* size = */ 0, /* truncate = */ true)); + + EXPECT_EQ(0, WriteData(entry, /* stream_index = */ 0, + /* offset = */ 0, buffer.get(), + /* size = */ 0, /* truncate = */ false)); + + EXPECT_EQ(kSize, ReadData(entry, /* stream_index = */ 0, + /* offset = */ 0, buffer.get(), + /* size = */ kSize)); + for (int i = 0; i < kSize; ++i) { + EXPECT_EQ(0, buffer->data()[i]) << i; + } + entry->Close(); +} + +TEST_F(DiskCacheEntryTest, ZeroWriteBackwards) { + // https://crbug.com/946538/ + InitCache(); + ZeroWriteBackwards(); +} + +TEST_F(DiskCacheEntryTest, SimpleZeroWriteBackwards) { + SetSimpleCacheMode(); + InitCache(); + ZeroWriteBackwards(); +} + +TEST_F(DiskCacheEntryTest, MemoryOnlyZeroWriteBackwards) { + SetMemoryOnlyMode(); + InitCache(); + ZeroWriteBackwards(); +} + TEST_F(DiskCacheEntryTest, SimpleCacheCloseResurrection) { const int kSize = 10; scoped_refptr<net::IOBuffer> buffer =
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn index f4da496..d6fb54bd 100644 --- a/net/dns/BUILD.gn +++ b/net/dns/BUILD.gn
@@ -213,6 +213,10 @@ # Whitelist-only access so we can keep track of all usage external to the # network stack and network service. friend = [ + # chromecast/browser/url_request_context_factory.cc + # URLRequestContext creation for chromecast. + "//chromecast/browser", + # Network stack/service. "//net/*", "//services/network/*", @@ -352,6 +356,7 @@ source_set("tests") { testonly = true sources = [ + "context_host_resolver_unittest.cc", "dns_config_service_unittest.cc", "dns_config_service_win_unittest.cc", "dns_hosts_unittest.cc",
diff --git a/net/dns/context_host_resolver.cc b/net/dns/context_host_resolver.cc index 5fd0b3a..31a6d7e 100644 --- a/net/dns/context_host_resolver.cc +++ b/net/dns/context_host_resolver.cc
@@ -4,6 +4,7 @@ #include "net/dns/context_host_resolver.h" +#include <string> #include <utility> #include "base/logging.h" @@ -17,6 +18,67 @@ namespace net { +// Wrapper of ResolveHostRequests that on destruction will remove itself from +// |ContextHostResolver::active_requests_|. +class ContextHostResolver::WrappedRequest + : public HostResolver::ResolveHostRequest { + public: + WrappedRequest( + std::unique_ptr<HostResolverManager::CancellableRequest> inner_request, + ContextHostResolver* resolver) + : inner_request_(std::move(inner_request)), resolver_(resolver) {} + + ~WrappedRequest() override { Cancel(); } + + void Cancel() { + // Cannot destroy |inner_request_| because it is still allowed to call + // Get...Results() methods if the request was already complete. + inner_request_->Cancel(); + + if (resolver_) { + resolver_->active_requests_.erase(this); + resolver_ = nullptr; + } + } + + int Start(CompletionOnceCallback callback) override { + DCHECK(resolver_); + return inner_request_->Start(std::move(callback)); + } + + const base::Optional<AddressList>& GetAddressResults() const override { + return inner_request_->GetAddressResults(); + } + + const base::Optional<std::vector<std::string>>& GetTextResults() + const override { + return inner_request_->GetTextResults(); + } + + const base::Optional<std::vector<HostPortPair>>& GetHostnameResults() + const override { + return inner_request_->GetHostnameResults(); + } + + const base::Optional<HostCache::EntryStaleness>& GetStaleInfo() + const override { + return inner_request_->GetStaleInfo(); + } + + void ChangeRequestPriority(RequestPriority priority) override { + inner_request_->ChangeRequestPriority(priority); + } + + private: + std::unique_ptr<HostResolverManager::CancellableRequest> inner_request_; + + // Resolver is expected to call Cancel() on destruction, clearing the pointer + // before it becomes invalid. + ContextHostResolver* resolver_; + + DISALLOW_COPY_AND_ASSIGN(WrappedRequest); +}; + ContextHostResolver::ContextHostResolver(HostResolverManager* manager) : manager_(manager) { DCHECK(manager_); @@ -31,6 +93,10 @@ ContextHostResolver::~ContextHostResolver() { if (owned_manager_) DCHECK_EQ(owned_manager_.get(), manager_); + + // Silently cancel all requests associated with this resolver. + while (!active_requests_.empty()) + (*active_requests_.begin())->Cancel(); } std::unique_ptr<HostResolver::ResolveHostRequest> @@ -39,7 +105,10 @@ const NetLogWithSource& source_net_log, const base::Optional<ResolveHostParameters>& optional_parameters) { // TODO(crbug.com/934402): DHCECK |context_| once universally set. - return manager_->CreateRequest(host, source_net_log, optional_parameters); + auto request = std::make_unique<WrappedRequest>( + manager_->CreateRequest(host, source_net_log, optional_parameters), this); + active_requests_.insert(request.get()); + return request; } std::unique_ptr<HostResolver::MdnsListener>
diff --git a/net/dns/context_host_resolver.h b/net/dns/context_host_resolver.h index 76382ee..0f8f5be9 100644 --- a/net/dns/context_host_resolver.h +++ b/net/dns/context_host_resolver.h
@@ -6,6 +6,7 @@ #define NET_DNS_CONTEXT_HOST_RESOLVER_H_ #include <memory> +#include <unordered_set> #include <vector> #include "base/macros.h" @@ -75,10 +76,20 @@ void SetBaseDnsConfigForTesting(const DnsConfig& base_config); void SetTickClockForTesting(const base::TickClock* tick_clock); + size_t GetNumActiveRequestsForTesting() const { + return active_requests_.size(); + } + private: + class WrappedRequest; + HostResolverManager* const manager_; std::unique_ptr<HostResolverManager> owned_manager_; + // Requests are expected to clear themselves from this set on destruction or + // cancellation. + std::unordered_set<WrappedRequest*> active_requests_; + URLRequestContext* context_ = nullptr; DISALLOW_COPY_AND_ASSIGN(ContextHostResolver);
diff --git a/net/dns/context_host_resolver_unittest.cc b/net/dns/context_host_resolver_unittest.cc new file mode 100644 index 0000000..7ff08ad --- /dev/null +++ b/net/dns/context_host_resolver_unittest.cc
@@ -0,0 +1,251 @@ +// 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 "net/dns/context_host_resolver.h" + +#include <utility> + +#include "base/bind.h" +#include "base/optional.h" +#include "base/run_loop.h" +#include "net/base/host_port_pair.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_errors.h" +#include "net/base/network_change_notifier.h" +#include "net/base/test_completion_callback.h" +#include "net/dns/dns_config.h" +#include "net/dns/dns_test_util.h" +#include "net/dns/dns_util.h" +#include "net/dns/host_resolver_manager.h" +#include "net/dns/mock_host_resolver.h" +#include "net/dns/public/dns_protocol.h" +#include "net/log/net_log_with_source.h" +#include "net/test/gtest_util.h" +#include "net/test/test_with_scoped_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { +const IPEndPoint kEndpoint(IPAddress(1, 2, 3, 4), 100); +} + +class ContextHostResolverTest : public TestWithScopedTaskEnvironment { + protected: + void SetUp() override { + manager_ = + std::make_unique<HostResolverManager>(HostResolver::Options(), nullptr); + } + + void SetMockDnsRules(MockDnsClientRuleList rules) { + // HostResolver expects DnsConfig to get set after setting DnsClient, so + // create first with an empty config and then update the config. + auto dns_client = + std::make_unique<MockDnsClient>(DnsConfig(), std::move(rules)); + dns_client_ = dns_client.get(); + manager_->SetDnsClient(std::move(dns_client)); + + scoped_refptr<HostResolverProc> proc = CreateCatchAllHostResolverProc(); + manager_->set_proc_params_for_test(ProcTaskParams(proc.get(), 1u)); + + IPAddress dns_ip(192, 168, 1, 0); + DnsConfig config; + config.nameservers.push_back( + IPEndPoint(dns_ip, dns_protocol::kDefaultPort)); + EXPECT_TRUE(config.IsValid()); + manager_->SetBaseDnsConfigForTesting(config); + } + + MockDnsClient* dns_client_; + std::unique_ptr<HostResolverManager> manager_; +}; + +TEST_F(ContextHostResolverTest, Resolve) { + MockDnsClientRuleList rules; + rules.emplace_back("example.com", dns_protocol::kTypeA, + SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(BuildTestDnsResponse( + "example.com", kEndpoint.address())), + false /* delay */); + rules.emplace_back( + "example.com", dns_protocol::kTypeAAAA, SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); + SetMockDnsRules(std::move(rules)); + + auto resolver = std::make_unique<ContextHostResolver>(manager_.get()); + std::unique_ptr<HostResolver::ResolveHostRequest> request = + resolver->CreateRequest(HostPortPair("example.com", 100), + NetLogWithSource(), base::nullopt); + + TestCompletionCallback callback; + int rv = request->Start(callback.callback()); + EXPECT_THAT(callback.GetResult(rv), test::IsOk()); + EXPECT_THAT(request->GetAddressResults().value().endpoints(), + testing::ElementsAre(kEndpoint)); +} + +// Test that destroying a request silently cancels that request. +TEST_F(ContextHostResolverTest, DestroyRequest) { + // Setup delayed results for "example.com". + MockDnsClientRuleList rules; + rules.emplace_back("example.com", dns_protocol::kTypeA, + SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(BuildTestDnsResponse( + "example.com", IPAddress(1, 2, 3, 4))), + true /* delay */); + rules.emplace_back( + "example.com", dns_protocol::kTypeAAAA, SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); + SetMockDnsRules(std::move(rules)); + + auto resolver = std::make_unique<ContextHostResolver>(manager_.get()); + std::unique_ptr<HostResolver::ResolveHostRequest> request = + resolver->CreateRequest(HostPortPair("example.com", 100), + NetLogWithSource(), base::nullopt); + EXPECT_EQ(1u, resolver->GetNumActiveRequestsForTesting()); + + TestCompletionCallback callback; + int rv = request->Start(callback.callback()); + + // Cancel |request| before allowing delayed result to complete. + request = nullptr; + dns_client_->CompleteDelayedTransactions(); + + // Ensure |request| never completes. + base::RunLoop().RunUntilIdle(); + EXPECT_THAT(rv, test::IsError(ERR_IO_PENDING)); + EXPECT_FALSE(callback.have_result()); + EXPECT_EQ(0u, resolver->GetNumActiveRequestsForTesting()); +} + +// Test that cancelling a resolver cancels its (and only its) requests. +TEST_F(ContextHostResolverTest, DestroyResolver) { + // Setup delayed results for "example.com" and "google.com". + MockDnsClientRuleList rules; + rules.emplace_back("example.com", dns_protocol::kTypeA, + SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(BuildTestDnsResponse( + "example.com", IPAddress(2, 3, 4, 5))), + true /* delay */); + rules.emplace_back( + "example.com", dns_protocol::kTypeAAAA, SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); + rules.emplace_back("google.com", dns_protocol::kTypeA, + SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(BuildTestDnsResponse( + "google.com", kEndpoint.address())), + true /* delay */); + rules.emplace_back( + "google.com", dns_protocol::kTypeAAAA, SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); + SetMockDnsRules(std::move(rules)); + + auto resolver1 = std::make_unique<ContextHostResolver>(manager_.get()); + std::unique_ptr<HostResolver::ResolveHostRequest> request1 = + resolver1->CreateRequest(HostPortPair("example.com", 100), + NetLogWithSource(), base::nullopt); + auto resolver2 = std::make_unique<ContextHostResolver>(manager_.get()); + std::unique_ptr<HostResolver::ResolveHostRequest> request2 = + resolver2->CreateRequest(HostPortPair("google.com", 100), + NetLogWithSource(), base::nullopt); + + TestCompletionCallback callback1; + int rv1 = request1->Start(callback1.callback()); + TestCompletionCallback callback2; + int rv2 = request2->Start(callback2.callback()); + + EXPECT_EQ(2u, manager_->num_jobs_for_testing()); + + // Cancel |resolver1| before allowing delayed requests to complete. + resolver1 = nullptr; + dns_client_->CompleteDelayedTransactions(); + + EXPECT_THAT(callback2.GetResult(rv2), test::IsOk()); + EXPECT_THAT(request2->GetAddressResults().value().endpoints(), + testing::ElementsAre(kEndpoint)); + + // Ensure |request1| never completes. + base::RunLoop().RunUntilIdle(); + EXPECT_THAT(rv1, test::IsError(ERR_IO_PENDING)); + EXPECT_FALSE(callback1.have_result()); +} + +// Test that cancelling a resolver cancels its (and only its) requests, even if +// those requests shared a job (same query) with another resolver's requests. +TEST_F(ContextHostResolverTest, DestroyResolver_RemainingRequests) { + // Setup delayed results for "example.com". + MockDnsClientRuleList rules; + rules.emplace_back("example.com", dns_protocol::kTypeA, + SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(BuildTestDnsResponse( + "example.com", kEndpoint.address())), + true /* delay */); + rules.emplace_back( + "example.com", dns_protocol::kTypeAAAA, SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); + SetMockDnsRules(std::move(rules)); + + // Make ResolveHostRequests the same hostname for both resolvers. + auto resolver1 = std::make_unique<ContextHostResolver>(manager_.get()); + std::unique_ptr<HostResolver::ResolveHostRequest> request1 = + resolver1->CreateRequest(HostPortPair("example.com", 100), + NetLogWithSource(), base::nullopt); + auto resolver2 = std::make_unique<ContextHostResolver>(manager_.get()); + std::unique_ptr<HostResolver::ResolveHostRequest> request2 = + resolver2->CreateRequest(HostPortPair("example.com", 100), + NetLogWithSource(), base::nullopt); + + TestCompletionCallback callback1; + int rv1 = request1->Start(callback1.callback()); + TestCompletionCallback callback2; + int rv2 = request2->Start(callback2.callback()); + + // Test relies on assumption that requests share jobs, so assert just 1. + ASSERT_EQ(1u, manager_->num_jobs_for_testing()); + + // Cancel |resolver1| before allowing delayed requests to complete. + resolver1 = nullptr; + dns_client_->CompleteDelayedTransactions(); + + EXPECT_THAT(callback2.GetResult(rv2), test::IsOk()); + EXPECT_THAT(request2->GetAddressResults().value().endpoints(), + testing::ElementsAre(kEndpoint)); + + // Ensure |request1| never completes. + base::RunLoop().RunUntilIdle(); + EXPECT_THAT(rv1, test::IsError(ERR_IO_PENDING)); + EXPECT_FALSE(callback1.have_result()); +} + +TEST_F(ContextHostResolverTest, DestroyResolver_CompletedRequests) { + MockDnsClientRuleList rules; + rules.emplace_back("example.com", dns_protocol::kTypeA, + SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(BuildTestDnsResponse( + "example.com", kEndpoint.address())), + false /* delay */); + rules.emplace_back( + "example.com", dns_protocol::kTypeAAAA, SecureDnsMode::AUTOMATIC, + MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */); + SetMockDnsRules(std::move(rules)); + + auto resolver = std::make_unique<ContextHostResolver>(manager_.get()); + std::unique_ptr<HostResolver::ResolveHostRequest> request = + resolver->CreateRequest(HostPortPair("example.com", 100), + NetLogWithSource(), base::nullopt); + + // Complete request and then destroy the resolver. + TestCompletionCallback callback; + int rv = request->Start(callback.callback()); + ASSERT_THAT(callback.GetResult(rv), test::IsOk()); + resolver = nullptr; + + // Expect completed results are still available. + EXPECT_THAT(request->GetAddressResults().value().endpoints(), + testing::ElementsAre(kEndpoint)); +} + +} // namespace net
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index cc6365a..e740cffb 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -490,7 +490,7 @@ // cancellation is initiated by the Job (OnJobCancelled) vs by the end user // (~RequestImpl). class HostResolverManager::RequestImpl - : public HostResolver::ResolveHostRequest, + : public CancellableRequest, public base::LinkNode<HostResolverManager::RequestImpl> { public: RequestImpl(const NetLogWithSource& source_net_log, @@ -508,7 +508,12 @@ resolver_(resolver), complete_(false) {} - ~RequestImpl() override; + ~RequestImpl() override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + Cancel(); + } + + void Cancel() override; int Start(CompletionOnceCallback callback) override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -2252,7 +2257,7 @@ UpdateModeForHistogram(dns_config); } -std::unique_ptr<HostResolver::ResolveHostRequest> +std::unique_ptr<HostResolverManager::CancellableRequest> HostResolverManager::CreateRequest( const HostPortPair& host, const NetLogWithSource& net_log, @@ -3133,10 +3138,14 @@ } } -HostResolverManager::RequestImpl::~RequestImpl() { +void HostResolverManager::RequestImpl::Cancel() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (job_) - job_->CancelRequest(this); + if (!job_) + return; + + job_->CancelRequest(this); + job_ = nullptr; + callback_.Reset(); } void HostResolverManager::RequestImpl::ChangeRequestPriority(
diff --git a/net/dns/host_resolver_manager.h b/net/dns/host_resolver_manager.h index 0dadfafd..e87c15f5 100644 --- a/net/dns/host_resolver_manager.h +++ b/net/dns/host_resolver_manager.h
@@ -87,6 +87,14 @@ using ResolveHostRequest = HostResolver::ResolveHostRequest; using ResolveHostParameters = HostResolver::ResolveHostParameters; + class CancellableRequest : public ResolveHostRequest { + public: + // If running asynchronously, silently cancels the request as if destroyed. + // Callbacks will never be invoked. Noop if request is already complete or + // never started. + virtual void Cancel() = 0; + }; + // Creates a HostResolver as specified by |options|. Blocking tasks are run in // TaskScheduler. // @@ -111,8 +119,7 @@ // NetworkChangeNotifier. void SetDnsClient(std::unique_ptr<DnsClient> dns_client); - // HostResolver methods: - std::unique_ptr<ResolveHostRequest> CreateRequest( + std::unique_ptr<CancellableRequest> CreateRequest( const HostPortPair& host, const NetLogWithSource& net_log, const base::Optional<ResolveHostParameters>& optional_parameters); @@ -159,6 +166,15 @@ void SetBaseDnsConfigForTesting(const DnsConfig& base_config); + // Allows the tests to catch slots leaking out of the dispatcher. One + // HostResolverManager::Job could occupy multiple PrioritizedDispatcher job + // slots. + size_t num_running_dispatcher_jobs_for_tests() const { + return dispatcher_->num_running_jobs(); + } + + size_t num_jobs_for_testing() const { return jobs_.size(); } + protected: // Callback from HaveOnlyLoopbackAddresses probe. void SetHaveOnlyLoopbackAddresses(bool result); @@ -332,13 +348,6 @@ int GetOrCreateMdnsClient(MDnsClient** out_client); - // Allows the tests to catch slots leaking out of the dispatcher. One - // HostResolverManager::Job could occupy multiple PrioritizedDispatcher job - // slots. - size_t num_running_dispatcher_jobs_for_tests() const { - return dispatcher_->num_running_jobs(); - } - // Update |mode_for_histogram_|. Called when DNS config changes. |dns_config| // is the current DNS config and is only used if !HaveDnsConfig(). void UpdateModeForHistogram(const DnsConfig& dns_config);
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index 2a82cf3a..bde8668 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -244,13 +244,13 @@ ResolveHostResponseHelper() {} explicit ResolveHostResponseHelper( - std::unique_ptr<HostResolver::ResolveHostRequest> request) + std::unique_ptr<HostResolverManager::CancellableRequest> request) : request_(std::move(request)) { result_error_ = request_->Start(base::BindOnce( &ResolveHostResponseHelper::OnComplete, base::Unretained(this))); } ResolveHostResponseHelper( - std::unique_ptr<HostResolver::ResolveHostRequest> request, + std::unique_ptr<HostResolverManager::CancellableRequest> request, Callback custom_callback) : request_(std::move(request)) { result_error_ = request_->Start( @@ -265,7 +265,7 @@ return result_error_; } - HostResolver::ResolveHostRequest* request() { return request_.get(); } + HostResolverManager::CancellableRequest* request() { return request_.get(); } void CancelRequest() { DCHECK(request_); @@ -291,7 +291,7 @@ DCHECK(complete()); } - std::unique_ptr<HostResolver::ResolveHostRequest> request_; + std::unique_ptr<HostResolverManager::CancellableRequest> request_; int result_error_ = ERR_IO_PENDING; base::RunLoop run_loop_; @@ -3993,6 +3993,57 @@ } } +TEST_F(HostResolverManagerDnsTest, DeleteWithCompletedRequests) { + ChangeDnsConfig(CreateValidDnsConfig()); + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair("ok", 80), NetLogWithSource(), base::nullopt)); + + EXPECT_THAT(response.result_error(), IsOk()); + EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 80), + CreateExpected("::1", 80))); + + resolver_.reset(); + + // Completed requests should be unaffected by manager destruction. + EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 80), + CreateExpected("::1", 80))); +} + +TEST_F(HostResolverManagerDnsTest, ExplicitCancel) { + ChangeDnsConfig(CreateValidDnsConfig()); + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair("4slow_4ok", 80), NetLogWithSource(), base::nullopt)); + + response.request()->Cancel(); + dns_client_->CompleteDelayedTransactions(); + + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(response.complete()); +} + +TEST_F(HostResolverManagerDnsTest, ExplicitCancel_Completed) { + ChangeDnsConfig(CreateValidDnsConfig()); + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair("ok", 80), NetLogWithSource(), base::nullopt)); + + EXPECT_THAT(response.result_error(), IsOk()); + EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 80), + CreateExpected("::1", 80))); + + response.request()->Cancel(); + + // Completed requests should be unaffected by cancellation. + EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 80), + CreateExpected("::1", 80))); +} + // Cancel a request with only the IPv6 transaction active. TEST_F(HostResolverManagerDnsTest, CancelWithIPv6TransactionActive) { ChangeDnsConfig(CreateValidDnsConfig());
diff --git a/net/http/http_basic_state.cc b/net/http/http_basic_state.cc index 3c1eb58..a9efbe1 100644 --- a/net/http/http_basic_state.cc +++ b/net/http/http_basic_state.cc
@@ -24,7 +24,6 @@ : read_buf_(base::MakeRefCounted<GrowableIOBuffer>()), connection_(std::move(connection)), using_proxy_(using_proxy), - can_send_early_(false), http_09_on_non_default_ports_enabled_( http_09_on_non_default_ports_enabled) { CHECK(connection_) << "ClientSocketHandle passed to HttpBasicState must " @@ -34,7 +33,6 @@ HttpBasicState::~HttpBasicState() = default; void HttpBasicState::Initialize(const HttpRequestInfo* request_info, - bool can_send_early, RequestPriority priority, const NetLogWithSource& net_log) { DCHECK(!parser_.get()); @@ -46,7 +44,6 @@ read_buf_.get(), net_log); parser_->set_http_09_on_non_default_ports_enabled( http_09_on_non_default_ports_enabled_); - can_send_early_ = can_send_early; } std::unique_ptr<ClientSocketHandle> HttpBasicState::ReleaseConnection() {
diff --git a/net/http/http_basic_state.h b/net/http/http_basic_state.h index 58c122ca..d811f9f 100644 --- a/net/http/http_basic_state.h +++ b/net/http/http_basic_state.h
@@ -35,7 +35,6 @@ // Initialize() must be called before using any of the other methods. void Initialize(const HttpRequestInfo* request_info, - bool can_send_early, RequestPriority priority, const NetLogWithSource& net_log); @@ -43,7 +42,6 @@ bool using_proxy() const { return using_proxy_; } - bool can_send_early() const { return can_send_early_; } bool http_09_on_non_default_ports_enabled() const { return http_09_on_non_default_ports_enabled_; } @@ -82,8 +80,6 @@ const bool using_proxy_; - bool can_send_early_; - const bool http_09_on_non_default_ports_enabled_; GURL url_;
diff --git a/net/http/http_basic_state_unittest.cc b/net/http/http_basic_state_unittest.cc index dd24b55..a811646 100644 --- a/net/http/http_basic_state_unittest.cc +++ b/net/http/http_basic_state_unittest.cc
@@ -46,7 +46,7 @@ TEST(HttpBasicStateTest, InitializeWorks) { HttpBasicState state(std::make_unique<ClientSocketHandle>(), false, false); const HttpRequestInfo request_info; - state.Initialize(&request_info, false, LOW, NetLogWithSource()); + state.Initialize(&request_info, LOW, NetLogWithSource()); EXPECT_TRUE(state.parser()); } @@ -55,7 +55,7 @@ HttpRequestInfo request_info; request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - state.Initialize(&request_info, false, LOW, NetLogWithSource()); + state.Initialize(&request_info, LOW, NetLogWithSource()); EXPECT_EQ(TRAFFIC_ANNOTATION_FOR_TESTS, NetworkTrafficAnnotationTag(state.traffic_annotation())); } @@ -63,7 +63,7 @@ TEST(HttpBasicStateTest, DeleteParser) { HttpBasicState state(std::make_unique<ClientSocketHandle>(), false, false); const HttpRequestInfo request_info; - state.Initialize(&request_info, false, LOW, NetLogWithSource()); + state.Initialize(&request_info, LOW, NetLogWithSource()); EXPECT_TRUE(state.parser()); state.DeleteParser(); EXPECT_EQ(NULL, state.parser()); @@ -76,7 +76,7 @@ HttpRequestInfo request_info; request_info.url = GURL("http://www.example.com/path?foo=bar#hoge"); request_info.method = "PUT"; - state.Initialize(&request_info, false, LOW, NetLogWithSource()); + state.Initialize(&request_info, LOW, NetLogWithSource()); EXPECT_EQ("PUT /path?foo=bar HTTP/1.1\r\n", state.GenerateRequestLine()); } @@ -87,7 +87,7 @@ HttpRequestInfo request_info; request_info.url = GURL("http://www.example.com/path?foo=bar#hoge"); request_info.method = "PUT"; - state.Initialize(&request_info, false, LOW, NetLogWithSource()); + state.Initialize(&request_info, LOW, NetLogWithSource()); EXPECT_EQ("PUT http://www.example.com/path?foo=bar HTTP/1.1\r\n", state.GenerateRequestLine()); }
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc index 9278d66..e516919 100644 --- a/net/http/http_basic_stream.cc +++ b/net/http/http_basic_stream.cc
@@ -31,8 +31,12 @@ const NetLogWithSource& net_log, CompletionOnceCallback callback) { DCHECK(request_info->traffic_annotation.is_valid()); - state_.Initialize(request_info, can_send_early, priority, net_log); - return OK; + state_.Initialize(request_info, priority, net_log); + int ret = OK; + if (!can_send_early) { + ret = parser()->ConfirmHandshake(std::move(callback)); + } + return ret; } int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 23775ab0..1c32ed9e 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -95,6 +95,7 @@ time_func(&base::TimeTicks::Now), enable_http2_alternative_service(false), enable_websocket_over_http2(false), + enable_early_data(false), enable_quic(false), enable_quic_proxies_for_https_urls(false), quic_max_packet_length(quic::kDefaultMaxPacketSize), @@ -438,6 +439,7 @@ GetAlpnProtos(&server_config->alpn_protos); server_config->ignore_certificate_errors = params_.ignore_certificate_errors; *proxy_config = *server_config; + server_config->early_data_enabled = params_.enable_early_data; } void HttpNetworkSession::DumpMemoryStats(
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 2a1a34d..5852772 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -127,6 +127,9 @@ // Whether to enable Websocket over HTTP/2. bool enable_websocket_over_http2; + // Enables 0-RTT support. + bool enable_early_data; + // Enables QUIC support. bool enable_quic;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 0ee8d86..50fb3e6e 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -19634,4 +19634,381 @@ #endif // BUILDFLAG(ENABLE_REPORTING) +TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) { + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n\r\n"), + }; + + // The proxy responds to the connect with a 407, using a persistent + // connection. + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 1\r\n\r\n"), + MockRead(SYNCHRONOUS, "1"), + }; + + StaticSocketDataProvider data(data_reads, data_writes); + session_deps_.socket_factory->AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + ssl.confirm = MockConfirm(SYNCHRONOUS, OK); + session_deps_.enable_early_data = true; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + TestCompletionCallback callback; + auto trans = + std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + + int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsOk()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ(200, response->headers->response_code()); + EXPECT_EQ(1, response->headers->GetContentLength()); + + // Check that ConfirmHandshake wasn't called. + ASSERT_FALSE(ssl.ConfirmDataConsumed()); + ASSERT_TRUE(ssl.WriteBeforeConfirm()); + + trans.reset(); + + session->CloseAllConnections(); +} + +TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) { + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite(SYNCHRONOUS, + "POST / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 0\r\n\r\n"), + }; + + // The proxy responds to the connect with a 407, using a persistent + // connection. + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 1\r\n\r\n"), + MockRead(SYNCHRONOUS, "1"), + }; + + StaticSocketDataProvider data(data_reads, data_writes); + session_deps_.socket_factory->AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + ssl.confirm = MockConfirm(SYNCHRONOUS, OK); + session_deps_.enable_early_data = true; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + TestCompletionCallback callback; + auto trans = + std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + + int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsOk()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ(200, response->headers->response_code()); + EXPECT_EQ(1, response->headers->GetContentLength()); + + // Check that the Write didn't get called before ConfirmHandshake completed. + ASSERT_FALSE(ssl.WriteBeforeConfirm()); + + trans.reset(); + + session->CloseAllConnections(); +} + +TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) { + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite(ASYNC, + "POST / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 0\r\n\r\n"), + }; + + // The proxy responds to the connect with a 407, using a persistent + // connection. + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 1\r\n\r\n"), + MockRead(SYNCHRONOUS, "1"), + }; + + StaticSocketDataProvider data(data_reads, data_writes); + session_deps_.socket_factory->AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + ssl.confirm = MockConfirm(SYNCHRONOUS, OK); + session_deps_.enable_early_data = true; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + TestCompletionCallback callback; + auto trans = + std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + + int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsOk()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ(200, response->headers->response_code()); + EXPECT_EQ(1, response->headers->GetContentLength()); + + // Check that the Write didn't get called before ConfirmHandshake completed. + ASSERT_FALSE(ssl.WriteBeforeConfirm()); + + trans.reset(); + + session->CloseAllConnections(); +} + +TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) { + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite(SYNCHRONOUS, + "POST / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 0\r\n\r\n"), + }; + + // The proxy responds to the connect with a 407, using a persistent + // connection. + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 1\r\n\r\n"), + MockRead(SYNCHRONOUS, "1"), + }; + + StaticSocketDataProvider data(data_reads, data_writes); + session_deps_.socket_factory->AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + ssl.confirm = MockConfirm(ASYNC, OK); + session_deps_.enable_early_data = true; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + TestCompletionCallback callback; + auto trans = + std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + + int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsOk()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ(200, response->headers->response_code()); + EXPECT_EQ(1, response->headers->GetContentLength()); + + // Check that the Write didn't get called before ConfirmHandshake completed. + ASSERT_FALSE(ssl.WriteBeforeConfirm()); + + trans.reset(); + + session->CloseAllConnections(); +} + +TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) { + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite(ASYNC, + "POST / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 0\r\n\r\n"), + }; + + // The proxy responds to the connect with a 407, using a persistent + // connection. + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 1\r\n\r\n"), + MockRead(SYNCHRONOUS, "1"), + }; + + StaticSocketDataProvider data(data_reads, data_writes); + session_deps_.socket_factory->AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + ssl.confirm = MockConfirm(ASYNC, OK); + session_deps_.enable_early_data = true; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + TestCompletionCallback callback; + auto trans = + std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + + int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsOk()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ(200, response->headers->response_code()); + EXPECT_EQ(1, response->headers->GetContentLength()); + + // Check that the Write didn't get called before ConfirmHandshake completed. + ASSERT_FALSE(ssl.WriteBeforeConfirm()); + + trans.reset(); + + session->CloseAllConnections(); +} + +TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) { + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite("POST / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 0\r\n\r\n"), + }; + + // The proxy responds to the connect with a 407, using a persistent + // connection. + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 1\r\n\r\n"), + MockRead(SYNCHRONOUS, "1"), + }; + + StaticSocketDataProvider data(data_reads, data_writes); + session_deps_.socket_factory->AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR); + session_deps_.enable_early_data = true; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + TestCompletionCallback callback; + auto trans = + std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + + int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR)); + + // Check that the Write didn't get called before ConfirmHandshake completed. + ASSERT_FALSE(ssl.WriteBeforeConfirm()); + + trans.reset(); + + session->CloseAllConnections(); +} + +TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) { + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite("POST / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 0\r\n\r\n"), + }; + + // The proxy responds to the connect with a 407, using a persistent + // connection. + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 1\r\n\r\n"), + MockRead(SYNCHRONOUS, "1"), + }; + + StaticSocketDataProvider data(data_reads, data_writes); + session_deps_.socket_factory->AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR); + session_deps_.enable_early_data = true; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + TestCompletionCallback callback; + auto trans = + std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + + int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR)); + + // Check that the Write didn't get called before ConfirmHandshake completed. + ASSERT_FALSE(ssl.WriteBeforeConfirm()); + + trans.reset(); + + session->CloseAllConnections(); +} + } // namespace net
diff --git a/net/http/http_proxy_connect_job.cc b/net/http/http_proxy_connect_job.cc index 5792433..a6dd03637 100644 --- a/net/http/http_proxy_connect_job.cc +++ b/net/http/http_proxy_connect_job.cc
@@ -623,8 +623,9 @@ spdy_stream_request_ = std::make_unique<SpdyStreamRequest>(); return spdy_stream_request_->StartRequest( SPDY_BIDIRECTIONAL_STREAM, spdy_session, - GURL("https://" + params_->endpoint().ToString()), kH2QuicTunnelPriority, - socket_tag(), spdy_session->net_log(), + GURL("https://" + params_->endpoint().ToString()), + false /* no early data */, kH2QuicTunnelPriority, socket_tag(), + spdy_session->net_log(), base::BindOnce(&HttpProxyConnectJob::OnIOComplete, base::Unretained(this)), params_->traffic_annotation());
diff --git a/net/http/http_proxy_connect_job_unittest.cc b/net/http/http_proxy_connect_job_unittest.cc index c4eb083..dc877737 100644 --- a/net/http/http_proxy_connect_job_unittest.cc +++ b/net/http/http_proxy_connect_job_unittest.cc
@@ -194,6 +194,8 @@ session_deps_.socket_factory->AddSocketDataProvider(data_.get()); if (GetParam() != HTTP) { + // Keep the old ssl_data in case there is a draining socket. + old_ssl_data_.swap(ssl_data_); ssl_data_ = std::make_unique<SSLSocketDataProvider>(connect_and_ssl_io_mode, OK); if (GetParam() == SPDY) { @@ -241,6 +243,7 @@ std::unique_ptr<TestProxyDelegate> proxy_delegate_; std::unique_ptr<SSLSocketDataProvider> ssl_data_; + std::unique_ptr<SSLSocketDataProvider> old_ssl_data_; std::unique_ptr<SequencedSocketData> data_; SpdySessionDependencies session_deps_;
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index 3db1d0e..35c7a4e 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc
@@ -320,6 +320,15 @@ return result > 0 ? OK : result; } +int HttpStreamParser::ConfirmHandshake(CompletionOnceCallback callback) { + int ret = stream_socket_->ConfirmHandshake( + base::BindOnce(&HttpStreamParser::RunConfirmHandshakeCallback, + weak_ptr_factory_.GetWeakPtr())); + if (ret == ERR_IO_PENDING) + confirm_handshake_callback_ = std::move(callback); + return ret; +} + int HttpStreamParser::ReadResponseHeaders(CompletionOnceCallback callback) { DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE); DCHECK(callback_.is_null()); @@ -932,6 +941,10 @@ return OK; } +void HttpStreamParser::RunConfirmHandshakeCallback(int rv) { + std::move(confirm_handshake_callback_).Run(rv); +} + int HttpStreamParser::FindAndParseResponseHeaders(int new_bytes) { DCHECK_GT(new_bytes, 0); DCHECK_EQ(0, read_buf_unused_offset_);
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h index c09a709..16d24e2 100644 --- a/net/http/http_stream_parser.h +++ b/net/http/http_stream_parser.h
@@ -73,6 +73,8 @@ HttpResponseInfo* response, CompletionOnceCallback callback); + int ConfirmHandshake(CompletionOnceCallback callback); + int ReadResponseHeaders(CompletionOnceCallback callback); int ReadResponseBody(IOBuffer* buf, @@ -183,6 +185,8 @@ // This handles most of the logic for DoReadHeadersComplete. int HandleReadHeaderResult(int result); + void RunConfirmHandshakeCallback(int rv); + // Examines |read_buf_| to find the start and end of the headers. If they are // found, parse them with DoParseResponseHeaders(). Return the offset for // the end of the headers, or -1 if the complete headers were not found, or @@ -266,6 +270,9 @@ scoped_refptr<IOBuffer> user_read_buf_; int user_read_buf_len_; + // The callback to notify a user that the handshake has been confirmed. + CompletionOnceCallback confirm_handshake_callback_; + // The callback to notify a user that their request or response is // complete or there was an error CompletionOnceCallback callback_;
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 3692ea4..7c949f5 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -157,6 +157,12 @@ MockConnect::~MockConnect() = default; +MockConfirm::MockConfirm() : mode(SYNCHRONOUS), result(OK) {} + +MockConfirm::MockConfirm(IoMode io_mode, int r) : mode(io_mode), result(r) {} + +MockConfirm::~MockConfirm() = default; + bool SocketDataProvider::IsIdle() const { return true; } @@ -1461,6 +1467,8 @@ int buf_len, CompletionOnceCallback callback, const NetworkTrafficAnnotationTag& traffic_annotation) { + if (!data_->is_confirm_data_consumed) + data_->write_called_before_confirm = true; return stream_socket_->Write(buf, buf_len, std::move(callback), traffic_annotation); } @@ -1486,6 +1494,28 @@ stream_socket_->Disconnect(); } +void MockSSLClientSocket::RunConfirmHandshakeCallback( + CompletionOnceCallback callback, + int result) { + data_->is_confirm_data_consumed = true; + std::move(callback).Run(result); +} + +int MockSSLClientSocket::ConfirmHandshake(CompletionOnceCallback callback) { + DCHECK(stream_socket_->IsConnected()); + if (data_->is_confirm_data_consumed) + return data_->confirm.result; + if (data_->confirm.mode == ASYNC) { + RunCallbackAsync( + base::BindOnce(&MockSSLClientSocket::RunConfirmHandshakeCallback, + base::Unretained(this), std::move(callback)), + data_->confirm.result); + return ERR_IO_PENDING; + } + data_->is_confirm_data_consumed = true; + return data_->confirm.result; +} + bool MockSSLClientSocket::IsConnected() const { return stream_socket_->IsConnected(); }
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 1b41630..44b8bf7 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -94,6 +94,18 @@ IPEndPoint peer_addr; }; +struct MockConfirm { + // Asynchronous confirm success. + // Creates a MockConfirm with |mode| ASYC and |result| OK. + MockConfirm(); + // Creates a MockConfirm with the specified mode and result. + MockConfirm(IoMode io_mode, int r); + ~MockConfirm(); + + IoMode mode; + int result; +}; + // MockRead and MockWrite shares the same interface and members, but we'd like // to have distinct types because we don't want to have them used // interchangably. To do this, a struct template is defined, and MockRead and @@ -441,9 +453,18 @@ // Returns whether MockConnect data has been consumed. bool ConnectDataConsumed() const { return is_connect_data_consumed; } + // Returns whether MockConfirm data has been consumed. + bool ConfirmDataConsumed() const { return is_confirm_data_consumed; } + + // Returns whether a Write occurred before ConfirmHandshake completed. + bool WriteBeforeConfirm() const { return write_called_before_confirm; } + // Result for Connect(). MockConnect connect; + // Result for Confirm(). + MockConfirm confirm; + // Result for GetNegotiatedProtocol(). NextProto next_proto; @@ -459,6 +480,8 @@ uint16_t expected_ssl_version_max; bool is_connect_data_consumed = false; + bool is_confirm_data_consumed = false; + bool write_called_before_confirm = false; }; // Uses the sequence_number field in the mock reads and writes to @@ -898,6 +921,7 @@ // StreamSocket implementation. int Connect(CompletionOnceCallback callback) override; void Disconnect() override; + int ConfirmHandshake(CompletionOnceCallback callback) override; bool IsConnected() const override; bool IsConnectedAndIdle() const override; bool WasEverUsed() const override; @@ -941,6 +965,8 @@ void RunCallbackAsync(CompletionOnceCallback callback, int result); void RunCallback(CompletionOnceCallback callback, int result); + void RunConfirmHandshakeCallback(CompletionOnceCallback callback, int result); + bool connected_ = false; NetLogWithSource net_log_; std::unique_ptr<StreamSocket> stream_socket_;
diff --git a/net/spdy/bidirectional_stream_spdy_impl.cc b/net/spdy/bidirectional_stream_spdy_impl.cc index f1281455..32d0999 100644 --- a/net/spdy/bidirectional_stream_spdy_impl.cc +++ b/net/spdy/bidirectional_stream_spdy_impl.cc
@@ -78,7 +78,8 @@ int rv = stream_request_.StartRequest( SPDY_BIDIRECTIONAL_STREAM, spdy_session_, request_info_->url, - request_info_->priority, request_info_->socket_tag, net_log, + false /* no early data */, request_info_->priority, + request_info_->socket_tag, net_log, base::Bind(&BidirectionalStreamSpdyImpl::OnStreamInitialized, weak_factory_.GetWeakPtr()), traffic_annotation);
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index 8d7ea84..63c692a 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc
@@ -156,8 +156,8 @@ } int rv = stream_request_.StartRequest( - SPDY_REQUEST_RESPONSE_STREAM, spdy_session_, request_info_->url, priority, - request_info_->socket_tag, stream_net_log, + SPDY_REQUEST_RESPONSE_STREAM, spdy_session_, request_info_->url, + can_send_early, priority, request_info_->socket_tag, stream_net_log, base::BindOnce(&SpdyHttpStream::OnStreamCreated, weak_factory_.GetWeakPtr(), std::move(callback)), NetworkTrafficAnnotationTag(request_info->traffic_annotation));
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index a17437d95..d95840d 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -8194,4 +8194,540 @@ #endif // BUILDFLAG(ENABLE_WEBSOCKETS) +TEST_F(SpdyNetworkTransactionTest, ZeroRTTDoesntConfirm) { + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + MockWrite writes[] = {CreateMockWrite(req, 0)}; + + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); + MockRead reads[] = { + CreateMockRead(resp, 1), CreateMockRead(body, 2), + MockRead(ASYNC, 0, 3) // EOF + }; + + SequencedSocketData data(reads, writes); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + // Configure |ssl_provider| to fail if ConfirmHandshake is called. The request + // should still succeed. + ssl_provider->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR); + helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider)); + TransactionHelperResult out = helper.output(); + EXPECT_THAT(out.rv, IsOk()); + EXPECT_EQ("HTTP/1.1 200", out.status_line); + EXPECT_EQ("hello!", out.response_data); +} + +// Run multiple concurrent streams that don't require handshake confirmation. +TEST_F(SpdyNetworkTransactionTest, ZeroRTTNoConfirmMultipleStreams) { + spdy::SpdySerializedFrame req1( + spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req2( + spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); + MockWrite writes1[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)}; + + spdy::SpdySerializedFrame resp1( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); + spdy::SpdySerializedFrame resp2( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); + MockRead reads1[] = { + CreateMockRead(resp1, 1), CreateMockRead(body1, 2), + CreateMockRead(resp2, 4), CreateMockRead(body2, 5), + MockRead(ASYNC, 0, 6) // EOF + }; + + SequencedSocketData data1(reads1, writes1); + SequencedSocketData data2({}, {}); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider1->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR); + auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider2->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR); + + helper.RunPreTestSetup(); + helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1)); + helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2)); + EXPECT_TRUE(helper.StartDefaultTest()); + + HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session()); + HttpRequestInfo request2; + request2.method = "GET"; + request2.url = GURL(kDefaultUrl); + request2.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + TestCompletionCallback callback2; + int rv = trans2.Start(&request2, callback2.callback(), log_); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + helper.FinishDefaultTest(); + EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk()); + helper.VerifyDataConsumed(); + + TransactionHelperResult out = helper.output(); + EXPECT_THAT(out.rv, IsOk()); + EXPECT_EQ("HTTP/1.1 200", out.status_line); + EXPECT_EQ("hello!", out.response_data); +} + +// Run multiple concurrent streams that require handshake confirmation. +TEST_F(SpdyNetworkTransactionTest, ZeroRTTConfirmMultipleStreams) { + spdy::SpdyHeaderBlock req_block1( + spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0)); + spdy::SpdySerializedFrame req1( + spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true)); + spdy::SpdyHeaderBlock req_block2( + spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0)); + spdy::SpdySerializedFrame req2( + spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true)); + MockWrite writes[] = { + CreateMockWrite(req1, 0), + CreateMockWrite(req2, 3), + }; + spdy::SpdySerializedFrame resp1( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); + spdy::SpdySerializedFrame resp2( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); + MockRead reads[] = { + CreateMockRead(resp1, 1), CreateMockRead(body1, 2), + CreateMockRead(resp2, 4), CreateMockRead(body2, 5), + MockRead(ASYNC, 0, 6) // EOF + }; + + SequencedSocketData data1(reads, writes); + SequencedSocketData data2({}, {}); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider1->confirm = MockConfirm(ASYNC, OK); + auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider2->confirm = MockConfirm(ASYNC, OK); + + helper.RunPreTestSetup(); + helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1)); + helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2)); + + HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session()); + HttpRequestInfo request1; + request1.method = "POST"; + request1.url = GURL(kDefaultUrl); + request1.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + TestCompletionCallback callback1; + int rv = trans1.Start(&request1, callback1.callback(), log_); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session()); + HttpRequestInfo request2; + request2.method = "POST"; + request2.url = GURL(kDefaultUrl); + request2.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + TestCompletionCallback callback2; + rv = trans2.Start(&request2, callback2.callback(), log_); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk()); + EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk()); + + const HttpResponseInfo* response1 = trans1.GetResponseInfo(); + ASSERT_TRUE(response1); + ASSERT_TRUE(response1->headers); + EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, + response1->connection_info); + EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine()); + std::string response_data; + ReadTransaction(&trans1, &response_data); + EXPECT_EQ("hello!", response_data); + + const HttpResponseInfo* response2 = trans2.GetResponseInfo(); + ASSERT_TRUE(response2); + ASSERT_TRUE(response2->headers); + EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, + response2->connection_info); + EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine()); + ReadTransaction(&trans2, &response_data); + EXPECT_EQ("hello!", response_data); + + helper.VerifyDataConsumed(); +} + +// Run multiple concurrent streams, the first require a confirmation and the +// second not requiring confirmation. +TEST_F(SpdyNetworkTransactionTest, ZeroRTTConfirmNoConfirmStreams) { + // This test orders the writes such that the GET (no confirmation) is written + // before the POST (confirmation required). + spdy::SpdyHeaderBlock req_block1( + spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); + spdy::SpdySerializedFrame req1( + spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true)); + spdy::SpdyHeaderBlock req_block2( + spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0)); + spdy::SpdySerializedFrame req2( + spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true)); + MockWrite writes[] = { + CreateMockWrite(req1, 0), + CreateMockWrite(req2, 3), + }; + spdy::SpdySerializedFrame resp1( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); + spdy::SpdySerializedFrame resp2( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); + MockRead reads[] = { + CreateMockRead(resp1, 1), CreateMockRead(body1, 2), + CreateMockRead(resp2, 4), CreateMockRead(body2, 5), + MockRead(ASYNC, 0, 6) // EOF + }; + + SequencedSocketData data1(reads, writes); + SequencedSocketData data2({}, {}); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider1->confirm = MockConfirm(ASYNC, OK); + auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider2->confirm = MockConfirm(ASYNC, OK); + + helper.RunPreTestSetup(); + helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1)); + helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2)); + + // TODO(https://crbug.com/949724): Explicitly verify the ordering of + // ConfirmHandshake and the second stream. + + HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session()); + HttpRequestInfo request1; + request1.method = "POST"; + request1.url = GURL(kDefaultUrl); + request1.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + TestCompletionCallback callback1; + int rv = trans1.Start(&request1, callback1.callback(), log_); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session()); + HttpRequestInfo request2; + request2.method = "GET"; + request2.url = GURL(kDefaultUrl); + request2.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + TestCompletionCallback callback2; + rv = trans2.Start(&request2, callback2.callback(), log_); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk()); + EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk()); + + const HttpResponseInfo* response1 = trans1.GetResponseInfo(); + ASSERT_TRUE(response1); + ASSERT_TRUE(response1->headers); + EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, + response1->connection_info); + EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine()); + std::string response_data; + ReadTransaction(&trans1, &response_data); + EXPECT_EQ("hello!", response_data); + + const HttpResponseInfo* response2 = trans2.GetResponseInfo(); + ASSERT_TRUE(response2); + ASSERT_TRUE(response2->headers); + EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, + response2->connection_info); + EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine()); + ReadTransaction(&trans2, &response_data); + EXPECT_EQ("hello!", response_data); + + helper.VerifyDataConsumed(); +} + +// Run multiple concurrent streams, the first not requiring confirmation and the +// second requiring confirmation. +TEST_F(SpdyNetworkTransactionTest, ZeroRTTNoConfirmConfirmStreams) { + // This test orders the writes such that the GET (no confirmation) is written + // before the POST (confirmation required). + spdy::SpdyHeaderBlock req_block1( + spdy_util_.ConstructGetHeaderBlock(kDefaultUrl)); + spdy::SpdySerializedFrame req1( + spdy_util_.ConstructSpdyHeaders(1, std::move(req_block1), LOWEST, true)); + spdy::SpdyHeaderBlock req_block2( + spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, 0)); + spdy::SpdySerializedFrame req2( + spdy_util_.ConstructSpdyHeaders(3, std::move(req_block2), LOWEST, true)); + MockWrite writes[] = { + CreateMockWrite(req1, 0), + CreateMockWrite(req2, 3), + }; + spdy::SpdySerializedFrame resp1( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); + spdy::SpdySerializedFrame resp2( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); + MockRead reads[] = { + CreateMockRead(resp1, 1), CreateMockRead(body1, 2), + CreateMockRead(resp2, 4), CreateMockRead(body2, 5), + MockRead(ASYNC, 0, 6) // EOF + }; + + SequencedSocketData data1(reads, writes); + SequencedSocketData data2({}, {}); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider1 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider1->confirm = MockConfirm(ASYNC, OK); + auto ssl_provider2 = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider2->confirm = MockConfirm(ASYNC, OK); + + helper.RunPreTestSetup(); + helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1)); + helper.AddDataWithSSLSocketDataProvider(&data2, std::move(ssl_provider2)); + + // TODO(https://crbug.com/949724): Explicitly verify the ordering of + // ConfirmHandshake and the second stream. + + HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session()); + HttpRequestInfo request1; + request1.method = "GET"; + request1.url = GURL(kDefaultUrl); + request1.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + TestCompletionCallback callback1; + int rv = trans1.Start(&request1, callback1.callback(), log_); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session()); + HttpRequestInfo request2; + request2.method = "POST"; + request2.url = GURL(kDefaultUrl); + request2.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + TestCompletionCallback callback2; + rv = trans2.Start(&request2, callback2.callback(), log_); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + EXPECT_THAT(callback1.GetResult(ERR_IO_PENDING), IsOk()); + EXPECT_THAT(callback2.GetResult(ERR_IO_PENDING), IsOk()); + + const HttpResponseInfo* response1 = trans1.GetResponseInfo(); + ASSERT_TRUE(response1); + ASSERT_TRUE(response1->headers); + EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, + response1->connection_info); + EXPECT_EQ("HTTP/1.1 200", response1->headers->GetStatusLine()); + std::string response_data; + ReadTransaction(&trans1, &response_data); + EXPECT_EQ("hello!", response_data); + + const HttpResponseInfo* response2 = trans2.GetResponseInfo(); + ASSERT_TRUE(response2); + ASSERT_TRUE(response2->headers); + EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP2, + response2->connection_info); + EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine()); + ReadTransaction(&trans2, &response_data); + EXPECT_EQ("hello!", response_data); + + helper.VerifyDataConsumed(); +} + +TEST_F(SpdyNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) { + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( + kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); + MockWrite writes[] = { + CreateMockWrite(req, 0, SYNCHRONOUS), + CreateMockWrite(body, 1), // POST upload frame + }; + + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + MockRead reads[] = { + CreateMockRead(resp, 2), CreateMockRead(body, 3), + MockRead(ASYNC, 0, 4) // EOF + }; + + SequencedSocketData data(reads, writes); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider->confirm = MockConfirm(SYNCHRONOUS, OK); + helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider)); + TransactionHelperResult out = helper.output(); + EXPECT_THAT(out.rv, IsOk()); + EXPECT_EQ("HTTP/1.1 200", out.status_line); + EXPECT_EQ("hello!", out.response_data); +} + +TEST_F(SpdyNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) { + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( + kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); + MockWrite writes[] = { + CreateMockWrite(req, 0, ASYNC), + CreateMockWrite(body, 1), // POST upload frame + }; + + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + MockRead reads[] = { + CreateMockRead(resp, 2), CreateMockRead(body, 3), + MockRead(ASYNC, 0, 4) // EOF + }; + + SequencedSocketData data(reads, writes); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider->confirm = MockConfirm(SYNCHRONOUS, OK); + helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider)); + TransactionHelperResult out = helper.output(); + EXPECT_THAT(out.rv, IsOk()); + EXPECT_EQ("HTTP/1.1 200", out.status_line); + EXPECT_EQ("hello!", out.response_data); +} + +TEST_F(SpdyNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) { + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( + kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); + MockWrite writes[] = { + CreateMockWrite(req, 0, SYNCHRONOUS), + CreateMockWrite(body, 1), // POST upload frame + }; + + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + MockRead reads[] = { + CreateMockRead(resp, 2), CreateMockRead(body, 3), + MockRead(ASYNC, 0, 4) // EOF + }; + + SequencedSocketData data(reads, writes); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider->confirm = MockConfirm(ASYNC, OK); + helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider)); + TransactionHelperResult out = helper.output(); + EXPECT_THAT(out.rv, IsOk()); + EXPECT_EQ("HTTP/1.1 200", out.status_line); + EXPECT_EQ("hello!", out.response_data); +} + +TEST_F(SpdyNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) { + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( + kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); + MockWrite writes[] = { + CreateMockWrite(req, 0, ASYNC), + CreateMockWrite(body, 1), // POST upload frame + }; + + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + MockRead reads[] = { + CreateMockRead(resp, 2), CreateMockRead(body, 3), + MockRead(ASYNC, 0, 4) // EOF + }; + + SequencedSocketData data(reads, writes); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider->confirm = MockConfirm(ASYNC, OK); + helper.RunToCompletionWithSSLData(&data, std::move(ssl_provider)); + TransactionHelperResult out = helper.output(); + EXPECT_THAT(out.rv, IsOk()); + EXPECT_EQ("HTTP/1.1 200", out.status_line); + EXPECT_EQ("hello!", out.response_data); +} + +TEST_F(SpdyNetworkTransactionTest, ZeroRTTConfirmErrorSync) { + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( + kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); + MockWrite writes[] = { + CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame + }; + + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + MockRead reads[] = { + CreateMockRead(resp, 2), CreateMockRead(body, 3), + MockRead(ASYNC, 0, 4) // EOF + }; + + SequencedSocketData data(reads, writes); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider->confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR); + helper.RunPreTestSetup(); + helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider)); + helper.RunDefaultTest(); + TransactionHelperResult out = helper.output(); + EXPECT_THAT(out.rv, IsError(ERR_SSL_PROTOCOL_ERROR)); +} + +TEST_F(SpdyNetworkTransactionTest, ZeroRTTConfirmErrorAsync) { + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( + kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); + MockWrite writes[] = { + CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame + }; + + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + MockRead reads[] = { + CreateMockRead(resp, 2), CreateMockRead(body, 3), + MockRead(ASYNC, 0, 4) // EOF + }; + + SequencedSocketData data(reads, writes); + UsePostRequest(); + auto session_deps = std::make_unique<SpdySessionDependencies>(); + session_deps->enable_early_data = true; + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, + std::move(session_deps)); + auto ssl_provider = std::make_unique<SSLSocketDataProvider>(ASYNC, OK); + ssl_provider->confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR); + helper.RunPreTestSetup(); + helper.AddDataWithSSLSocketDataProvider(&data, std::move(ssl_provider)); + helper.RunDefaultTest(); + TransactionHelperResult out = helper.output(); + EXPECT_THAT(out.rv, IsError(ERR_SSL_PROTOCOL_ERROR)); +} + } // namespace net
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index 1b09efe..329e2217e 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -199,6 +199,7 @@ ProxyServer proxy_; SpdySessionKey endpoint_spdy_session_key_; std::unique_ptr<CommonConnectJobParams> common_connect_job_params_; + SSLSocketDataProvider ssl_; DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest); }; @@ -215,7 +216,8 @@ proxy_, PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse, - SocketTag()) { + SocketTag()), + ssl_(SYNCHRONOUS, OK) { session_deps_.net_log = net_log_.bound().net_log(); } @@ -241,11 +243,10 @@ data_->set_connect_data(connect_data_); session_deps_.socket_factory->AddSocketDataProvider(data_.get()); - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - ssl.ssl_info.cert = + ssl_.ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); - ASSERT_TRUE(ssl.ssl_info.cert); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + ASSERT_TRUE(ssl_.ssl_info.cert); + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_); session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); common_connect_job_params_ = std::make_unique<CommonConnectJobParams>(
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index a88cca7..9b6ac6832 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -666,6 +666,7 @@ SpdyStreamType type, const base::WeakPtr<SpdySession>& session, const GURL& url, + bool can_send_early, RequestPriority priority, const SocketTag& socket_tag, const NetLogWithSource& net_log, @@ -680,18 +681,25 @@ type_ = type; session_ = session; url_ = SimplifyUrlForRequest(url); + can_send_early_ = can_send_early; priority_ = priority; socket_tag_ = socket_tag; net_log_ = net_log; callback_ = std::move(callback); traffic_annotation_ = MutableNetworkTrafficAnnotationTag(traffic_annotation); + next_state_ = STATE_WAIT_FOR_CONFIRMATION; + int rv = DoLoop(OK); + if (rv != OK) + return rv; + base::WeakPtr<SpdyStream> stream; - int rv = session->TryCreateStream(weak_ptr_factory_.GetWeakPtr(), &stream); - if (rv == OK) { - Reset(); - stream_ = stream; - } + rv = session->TryCreateStream(weak_ptr_factory_.GetWeakPtr(), &stream); + if (rv != OK) + return rv; + + Reset(); + stream_ = stream; return rv; } @@ -754,11 +762,74 @@ session_.reset(); stream_.reset(); url_ = GURL(); + can_send_early_ = false; priority_ = MINIMUM_PRIORITY; socket_tag_ = SocketTag(); net_log_ = NetLogWithSource(); callback_.Reset(); traffic_annotation_.reset(); + next_state_ = STATE_NONE; +} + +void SpdyStreamRequest::OnIOComplete(int rv) { + if (rv != OK) { + OnRequestCompleteFailure(rv); + } else { + DoLoop(rv); + } +} + +int SpdyStreamRequest::DoLoop(int rv) { + do { + State state = next_state_; + next_state_ = STATE_NONE; + switch (state) { + case STATE_WAIT_FOR_CONFIRMATION: + CHECK_EQ(OK, rv); + return DoWaitForConfirmation(); + break; + case STATE_REQUEST_STREAM: + CHECK_EQ(OK, rv); + return DoRequestStream(rv); + break; + default: + NOTREACHED() << "next_state_: " << next_state_; + break; + } + } while (next_state_ != STATE_NONE && next_state_ && rv != ERR_IO_PENDING); + return rv; +} + +int SpdyStreamRequest::DoWaitForConfirmation() { + if (can_send_early_) { + next_state_ = STATE_NONE; + return OK; + } + + int rv = session_->ConfirmHandshake(base::BindOnce( + &SpdyStreamRequest::OnIOComplete, weak_ptr_factory_.GetWeakPtr())); + // If ConfirmHandshake returned synchronously, exit the state machine early + // so StartRequest can call TryCreateStream synchronously. Otherwise, + // TryCreateStream will be called asynchronously as part of the confirmation + // state machine. + next_state_ = rv == ERR_IO_PENDING ? STATE_REQUEST_STREAM : STATE_NONE; + return rv; +} + +int SpdyStreamRequest::DoRequestStream(int rv) { + DCHECK_NE(ERR_IO_PENDING, rv); + next_state_ = STATE_NONE; + if (rv < 0) + return rv; + + base::WeakPtr<SpdyStream> stream; + rv = session_->TryCreateStream(weak_ptr_factory_.GetWeakPtr(), &stream); + if (rv == OK) { + OnRequestCompleteSuccess(stream); + } else if (rv != ERR_IO_PENDING) { + OnRequestCompleteFailure(rv); + } + return rv; } // static @@ -854,6 +925,7 @@ error_on_close_(OK), initial_settings_(initial_settings), greased_http2_frame_(greased_http2_frame), + in_confirm_handshake_(false), max_concurrent_streams_(kInitialMaxConcurrentStreams), max_concurrent_pushed_streams_( initial_settings.at(spdy::SETTINGS_MAX_CONCURRENT_STREAMS)), @@ -915,6 +987,8 @@ CHECK(!in_io_loop_); DcheckDraining(); + DCHECK(waiting_for_confirmation_callbacks_.empty()); + // TODO(akalin): Check connection->is_initialized(). DCHECK(socket_); // With SPDY we can't recycle sockets. @@ -1033,6 +1107,20 @@ stream->traffic_annotation()); } +int SpdySession::ConfirmHandshake(CompletionOnceCallback callback) { + int rv = ERR_IO_PENDING; + if (!in_confirm_handshake_) { + rv = socket_->ConfirmHandshake( + base::BindOnce(&SpdySession::NotifyRequestsOfConfirmation, + weak_factory_.GetWeakPtr())); + } + if (rv == ERR_IO_PENDING) { + in_confirm_handshake_ = true; + waiting_for_confirmation_callbacks_.push_back(std::move(callback)); + } + return rv; +} + std::unique_ptr<spdy::SpdySerializedFrame> SpdySession::CreateHeaders( spdy::SpdyStreamId stream_id, RequestPriority priority, @@ -2395,6 +2483,15 @@ return OK; } +void SpdySession::NotifyRequestsOfConfirmation(int rv) { + for (auto& callback : waiting_for_confirmation_callbacks_) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), rv)); + } + waiting_for_confirmation_callbacks_.clear(); + in_confirm_handshake_ = false; +} + void SpdySession::SendInitialData() { DCHECK(enable_sending_initial_data_); DCHECK(buffered_spdy_framer_.get()); @@ -2784,6 +2881,10 @@ } MakeUnavailable(); + // Notify any requests waiting for handshake confirmation that there is an + // error. + NotifyRequestsOfConfirmation(err); + // Mark host_port_pair requiring HTTP/1.1 for subsequent connections. if (err == ERR_HTTP_1_1_REQUIRED) { http_server_properties_->SetHTTP11Required(host_port_pair());
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 235c85a..827f1b8 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -203,6 +203,9 @@ // is not created, an error is returned, and ReleaseStream() may not // be called. // + // If |can_send_early| is true, this request is allowed to be sent over + // TLS 1.3 0RTT without confirming the handshake. + // // If OK is returned, must not be called again without // ReleaseStream() being called first. If ERR_IO_PENDING is // returned, must not be called again without CancelRequest() or @@ -211,6 +214,7 @@ int StartRequest(SpdyStreamType type, const base::WeakPtr<SpdySession>& session, const GURL& url, + bool can_send_early, RequestPriority priority, const SocketTag& socket_tag, const NetLogWithSource& net_log, @@ -241,6 +245,17 @@ private: friend class SpdySession; + enum State { + STATE_NONE, + STATE_WAIT_FOR_CONFIRMATION, + STATE_REQUEST_STREAM, + }; + + void OnIOComplete(int rv); + int DoLoop(int rv); + int DoWaitForConfirmation(); + int DoRequestStream(int rv); + // Called by |session_| when the stream attempt has finished // successfully. void OnRequestCompleteSuccess(const base::WeakPtr<SpdyStream>& stream); @@ -262,11 +277,13 @@ base::WeakPtr<SpdySession> session_; base::WeakPtr<SpdyStream> stream_; GURL url_; + bool can_send_early_; RequestPriority priority_; SocketTag socket_tag_; NetLogWithSource net_log_; CompletionOnceCallback callback_; MutableNetworkTrafficAnnotationTag traffic_annotation_; + State next_state_; base::WeakPtrFactory<SpdyStreamRequest> weak_ptr_factory_; @@ -382,6 +399,11 @@ spdy::SpdyFrameType frame_type, std::unique_ptr<SpdyBufferProducer> producer); + // Runs the handshake to completion to confirm the handshake with the server. + // If ERR_IO_PENDING is returned, then when the handshake is confirmed, + // |callback| will be called. + int ConfirmHandshake(CompletionOnceCallback callback); + // Creates and returns a HEADERS frame for |stream_id|. std::unique_ptr<spdy::SpdySerializedFrame> CreateHeaders( spdy::SpdyStreamId stream_id, @@ -704,6 +726,8 @@ int DoWrite(); int DoWriteComplete(int result); + void NotifyRequestsOfConfirmation(int rv); + // TODO(akalin): Rename the Send* and Write* functions below to // Enqueue*. @@ -1054,6 +1078,13 @@ // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00. const base::Optional<SpdySessionPool::GreasedHttp2Frame> greased_http2_frame_; + // The callbacks to notify a request that the handshake has been confirmed. + std::vector<CompletionOnceCallback> waiting_for_confirmation_callbacks_; + + // True if there is an ongoing handshake confirmation with outstanding + // requests. + bool in_confirm_handshake_; + // Limits size_t max_concurrent_streams_; size_t max_concurrent_pushed_streams_;
diff --git a/net/spdy/spdy_session_fuzzer.cc b/net/spdy/spdy_session_fuzzer.cc index 4b920299..417cd9a 100644 --- a/net/spdy/spdy_session_fuzzer.cc +++ b/net/spdy/spdy_session_fuzzer.cc
@@ -131,9 +131,9 @@ net::TestCompletionCallback wait_for_start; int rv = stream_request.StartRequest( net::SPDY_REQUEST_RESPONSE_STREAM, spdy_session, - GURL("http://www.example.invalid/"), net::DEFAULT_PRIORITY, - net::SocketTag(), bound_test_net_log.bound(), wait_for_start.callback(), - TRAFFIC_ANNOTATION_FOR_TESTS); + GURL("http://www.example.invalid/"), false /* no early data */, + net::DEFAULT_PRIORITY, net::SocketTag(), bound_test_net_log.bound(), + wait_for_start.callback(), TRAFFIC_ANNOTATION_FOR_TESTS); if (rv == net::ERR_IO_PENDING) { rv = wait_for_start.WaitForResult();
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index 05dd8a9..4ee2aee 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -444,7 +444,7 @@ StreamRequestDestroyingCallback callback1; ASSERT_EQ(ERR_IO_PENDING, request1.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, - test_url_, MEDIUM, SocketTag(), + test_url_, false, MEDIUM, SocketTag(), NetLogWithSource(), callback1.MakeCallback(), TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -452,7 +452,7 @@ TestCompletionCallback callback2; ASSERT_EQ(ERR_IO_PENDING, request2->StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, - test_url_, MEDIUM, SocketTag(), + test_url_, false, MEDIUM, SocketTag(), NetLogWithSource(), callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -879,8 +879,8 @@ SpdyStreamRequest stream_request; int rv = stream_request.StartRequest( - SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, SocketTag(), - NetLogWithSource(), CompletionOnceCallback(), + SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, false, MEDIUM, + SocketTag(), NetLogWithSource(), CompletionOnceCallback(), TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_THAT(rv, IsError(ERR_FAILED)); @@ -1305,7 +1305,7 @@ TestCompletionCallback callback4; EXPECT_EQ(ERR_IO_PENDING, request4.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, - test_url_, MEDIUM, SocketTag(), + test_url_, false, MEDIUM, SocketTag(), NetLogWithSource(), callback4.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -1411,9 +1411,10 @@ // Start request. SpdyStreamRequest request; TestCompletionCallback callback; - int rv = request.StartRequest( - SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, SocketTag(), - NetLogWithSource(), callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS); + int rv = + request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, + false, MEDIUM, SocketTag(), NetLogWithSource(), + callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Stream is stalled. @@ -1479,7 +1480,7 @@ TestCompletionCallback callback2; EXPECT_EQ(ERR_IO_PENDING, request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, - test_url_, MEDIUM, SocketTag(), + test_url_, false, MEDIUM, SocketTag(), NetLogWithSource(), callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -2000,12 +2001,11 @@ SpdyStreamRequest request; ASSERT_EQ(ERR_IO_PENDING, request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, - MEDIUM, SocketTag(), NetLogWithSource(), + false, MEDIUM, SocketTag(), NetLogWithSource(), stream_releaser.MakeCallback(&request), TRAFFIC_ANNOTATION_FOR_TESTS)); base::RunLoop().RunUntilIdle(); - EXPECT_THAT(stream_releaser.WaitForResult(), IsOk()); data.Resume(); @@ -2056,7 +2056,7 @@ SpdyStreamRequest request; ASSERT_THAT( request.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, test_url_, - MEDIUM, SocketTag(), NetLogWithSource(), + false, MEDIUM, SocketTag(), NetLogWithSource(), callback->callback(), TRAFFIC_ANNOTATION_FOR_TESTS), IsError(ERR_IO_PENDING)); @@ -2089,14 +2089,14 @@ TestCompletionCallback callback1; SpdyStreamRequest request1; ASSERT_EQ(OK, request1.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, - test_url_, LOWEST, SocketTag(), + test_url_, false, LOWEST, SocketTag(), NetLogWithSource(), callback1.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); TestCompletionCallback callback2; SpdyStreamRequest request2; ASSERT_EQ(ERR_IO_PENDING, request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, - test_url_, LOWEST, SocketTag(), + test_url_, false, LOWEST, SocketTag(), NetLogWithSource(), callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -2856,7 +2856,7 @@ SpdyStreamRequest request2; ASSERT_EQ(ERR_IO_PENDING, request2.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, - test_url_, LOWEST, SocketTag(), + test_url_, false, LOWEST, SocketTag(), NetLogWithSource(), callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -2864,7 +2864,7 @@ SpdyStreamRequest request3; ASSERT_EQ(ERR_IO_PENDING, request3.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, - test_url_, LOWEST, SocketTag(), + test_url_, false, LOWEST, SocketTag(), NetLogWithSource(), callback3.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -2969,7 +2969,7 @@ SpdyStreamRequest request2; ASSERT_EQ(ERR_IO_PENDING, request2.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, - test_url_, LOWEST, SocketTag(), + test_url_, false, LOWEST, SocketTag(), NetLogWithSource(), callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -2977,7 +2977,7 @@ SpdyStreamRequest request3; ASSERT_EQ(ERR_IO_PENDING, request3.StartRequest(SPDY_BIDIRECTIONAL_STREAM, session_, - test_url_, LOWEST, SocketTag(), + test_url_, false, LOWEST, SocketTag(), NetLogWithSource(), callback3.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 0a2d5007..988d82b 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -251,8 +251,9 @@ const NetLogWithSource& net_log) { SpdyStreamRequest stream_request; int rv = stream_request.StartRequest( - type, session, url, priority, SocketTag(), net_log, - CompletionOnceCallback(), TRAFFIC_ANNOTATION_FOR_TESTS); + type, session, url, false /* no early data */, priority, SocketTag(), + net_log, CompletionOnceCallback(), TRAFFIC_ANNOTATION_FOR_TESTS); + return (rv == OK) ? stream_request.ReleaseStream() : base::WeakPtr<SpdyStream>(); } @@ -342,7 +343,8 @@ enable_websocket_over_http2(false), net_log(nullptr), http_09_on_non_default_ports_enabled(false), - disable_idle_sockets_close_on_memory_pressure(false) { + disable_idle_sockets_close_on_memory_pressure(false), + enable_early_data(false) { http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = kDefaultInitialWindowSize; } @@ -395,6 +397,7 @@ session_deps->http_09_on_non_default_ports_enabled; params.disable_idle_sockets_close_on_memory_pressure = session_deps->disable_idle_sockets_close_on_memory_pressure; + params.enable_early_data = session_deps->enable_early_data; return params; }
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index def43e7..e0423d25 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h
@@ -235,6 +235,7 @@ NetLog* net_log; bool http_09_on_non_default_ports_enabled; bool disable_idle_sockets_close_on_memory_pressure; + bool enable_early_data; }; class SpdyURLRequestContext : public URLRequestContext {
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h index d263ebd6..1570b46 100644 --- a/net/url_request/url_request_context.h +++ b/net/url_request/url_request_context.h
@@ -35,12 +35,6 @@ } } -namespace chromecast { -namespace shell { -class URLRequestContextFactory; -} -} // namespace chromecast - namespace safe_browsing { class SafeBrowsingURLRequestContextGetter; } // namespace safe_browsing @@ -311,7 +305,6 @@ // Whitelist legacy usage of now-deprecated CopyFrom(). friend class ::ChromeBrowserStateImplIOData; friend class ::ProfileImplIOData; - friend class chromecast::shell::URLRequestContextFactory; friend class safe_browsing::SafeBrowsingURLRequestContextGetter; // Copies the state from |other| into this context.
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index a2cde27e..cd8e8de 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -12584,4 +12584,403 @@ } #endif +// Provides a response to the 0RTT request indicating whether it was received +// as early data. +class ZeroRTTResponse : public test_server::BasicHttpResponse { + public: + explicit ZeroRTTResponse(bool zero_rtt) : zero_rtt_(zero_rtt) {} + ~ZeroRTTResponse() override {} + + void SendResponse(const test_server::SendBytesCallback& send, + const test_server::SendCompleteCallback& done) override { + AddCustomHeader("Vary", "Early-Data"); + set_content_type("text/plain"); + AddCustomHeader("Cache-Control", "no-cache"); + if (zero_rtt_) { + set_content("1"); + } else { + set_content("0"); + } + + // Since the EmbeddedTestServer doesn't keep the socket open by default, + // it is explicitly kept alive to allow the remaining leg of the 0RTT + // handshake to be received after the early data. + send.Run(ToResponseString(), base::DoNothing()); + } + + private: + bool zero_rtt_; + + DISALLOW_COPY_AND_ASSIGN(ZeroRTTResponse); +}; + +std::unique_ptr<test_server::HttpResponse> HandleZeroRTTRequest( + const test_server::HttpRequest& request) { + if (request.GetURL().path() != "/zerortt") + return nullptr; + auto iter = request.headers.find("Early-Data"); + bool zero_rtt = iter != request.headers.end() && iter->second == "1"; + return std::make_unique<ZeroRTTResponse>(zero_rtt); +} + +class HTTPSEarlyDataTest : public TestWithScopedTaskEnvironment { + public: + HTTPSEarlyDataTest() + : context_(true), test_server_(net::EmbeddedTestServer::TYPE_HTTPS) { + auto params = std::make_unique<HttpNetworkSession::Params>(); + params->enable_early_data = true; + context_.set_http_network_session_params(std::move(params)); + + context_.set_network_delegate(&network_delegate_); + cert_verifier_.set_default_result(OK); + context_.set_cert_verifier(&cert_verifier_); + + ssl_config_service_ = std::make_unique<TestSSLConfigService>(); + ssl_config_service_->set_max_version(SSL_PROTOCOL_VERSION_TLS1_3); + context_.set_ssl_config_service(ssl_config_service_.get()); + + context_.Init(); + + ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_3; + ssl_config_.early_data_enabled = true; + test_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config_); + test_server_.AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + test_server_.RegisterRequestHandler( + base::BindRepeating(&HandleZeroRTTRequest)); + } + + ~HTTPSEarlyDataTest() override = default; + + void ResetSSLConfig(net::EmbeddedTestServer::ServerCertificate cert, + uint16_t version) { + ssl_config_.version_max = version; + test_server_.ResetSSLConfig(cert, ssl_config_); + } + + protected: + MockCertVerifier cert_verifier_; + TestNetworkDelegate network_delegate_; // Must outlive URLRequest. + std::unique_ptr<TestSSLConfigService> ssl_config_service_; + TestURLRequestContext context_; + + SSLServerConfig ssl_config_; + EmbeddedTestServer test_server_; +}; + +// TLSEarlyDataTest tests that we handle early data correctly. +TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTest) { + ASSERT_TRUE(test_server_.Start()); + context_.http_transaction_factory()->GetSession()->ClearSSLSessionCache(); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + + // The Early-Data header should be omitted in the initial request, and the + // handler should return "0". + EXPECT_EQ("0", d.data_received()); + } + + context_.http_transaction_factory()->GetSession()->CloseAllConnections(); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + + // The Early-Data header should be a single '1' in the resumed request, and + // the handler should return "1". + EXPECT_EQ("1", d.data_received()); + } +} + +// TLSEarlyDataTest tests that we handle early data correctly for POST. +TEST_F(HTTPSEarlyDataTest, TLSEarlyDataPOSTTest) { + ASSERT_TRUE(test_server_.Start()); + context_.http_transaction_factory()->GetSession()->ClearSSLSessionCache(); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + + // The Early-Data header should be omitted in the initial request, and the + // handler should return "0". + EXPECT_EQ("0", d.data_received()); + } + + context_.http_transaction_factory()->GetSession()->CloseAllConnections(); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + r->set_method("POST"); + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + + // The Early-Data header should be omitted in the request, since we don't + // send POSTs over early data, and the handler should return "0". + EXPECT_EQ("0", d.data_received()); + } +} + +std::unique_ptr<test_server::HttpResponse> HandleTooEarly( + bool* sent_425, + const test_server::HttpRequest& request) { + if (request.GetURL().path() != "/tooearly") + return nullptr; + std::unique_ptr<test_server::BasicHttpResponse> http_response( + new test_server::BasicHttpResponse); + http_response->set_content_type("text/html"); + if (request.headers.find("Early-Data") != request.headers.end()) { + EXPECT_EQ("1", request.headers.at("Early-Data")); + http_response->set_code(HTTP_TOO_EARLY); + http_response->set_content("1"); + *sent_425 = true; + } else { + http_response->set_content("None"); + } + return std::move(http_response); +} + +// Test that we handle 425 (Too Early) correctly. +TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTooEarlyTest) { + bool sent_425 = false; + test_server_.RegisterRequestHandler( + base::BindRepeating(&HandleTooEarly, base::Unretained(&sent_425))); + ASSERT_TRUE(test_server_.Start()); + context_.http_transaction_factory()->GetSession()->ClearSSLSessionCache(); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/tooearly"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + + // The Early-Data header should be omitted in the initial request, and the + // handler should return "None". + EXPECT_EQ("None", d.data_received()); + EXPECT_FALSE(sent_425); + } + + context_.http_transaction_factory()->GetSession()->CloseAllConnections(); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/tooearly"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + + // The resumption request will encounter a 425 error and retry without early + // data, and the handler should return "None". + EXPECT_EQ("None", d.data_received()); + EXPECT_TRUE(sent_425); + } +} + +// TLSEarlyDataRejectTest tests that we gracefully handle an early data reject +// and retry without early data. +TEST_F(HTTPSEarlyDataTest, TLSEarlyDataRejectTest) { + ASSERT_TRUE(test_server_.Start()); + context_.http_transaction_factory()->GetSession()->ClearSSLSessionCache(); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + + // The Early-Data header should be omitted in the initial request, and the + // handler should return "0". + EXPECT_EQ("0", d.data_received()); + } + + context_.http_transaction_factory()->GetSession()->CloseAllConnections(); + + // The certificate in the resumption is changed to confirm that the + // certificate change is observed. + scoped_refptr<X509Certificate> old_cert = test_server_.GetCertificate(); + ResetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED, + SSL_PROTOCOL_VERSION_TLS1_3); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + EXPECT_FALSE(old_cert->EqualsIncludingChain(r->ssl_info().cert.get())); + + // The Early-Data header should be omitted in the rejected request, and the + // handler should return "0". + EXPECT_EQ("0", d.data_received()); + } +} + +// TLSEarlyDataTLS12RejectTest tests that we gracefully handle an early data +// reject from a TLS 1.2 server and retry without early data. +TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTLS12RejectTest) { + ASSERT_TRUE(test_server_.Start()); + context_.http_transaction_factory()->GetSession()->ClearSSLSessionCache(); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + + // The Early-Data header should be omitted in the initial request, and the + // handler should return "0". + EXPECT_EQ("0", d.data_received()); + } + + context_.http_transaction_factory()->GetSession()->CloseAllConnections(); + + // The certificate in the resumption is changed to confirm that the + // certificate change is observed. + scoped_refptr<X509Certificate> old_cert = test_server_.GetCertificate(); + ResetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED, + SSL_PROTOCOL_VERSION_TLS1_2); + + { + TestDelegate d; + std::unique_ptr<URLRequest> r(context_.CreateRequest( + test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + + EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_2, + SSLConnectionStatusToVersion(r->ssl_info().connection_status)); + EXPECT_TRUE(r->ssl_info().unverified_cert.get()); + EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain( + r->ssl_info().cert.get())); + EXPECT_FALSE(old_cert->EqualsIncludingChain(r->ssl_info().cert.get())); + + // The Early-Data header should be omitted in the rejected request, and the + // handler should return "0". + EXPECT_EQ("0", d.data_received()); + } +} + } // namespace net
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc index 9ec81a6..65f63e0 100644 --- a/net/websockets/websocket_basic_handshake_stream.cc +++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -203,7 +203,17 @@ CompletionOnceCallback callback) { DCHECK(request_info->traffic_annotation.is_valid()); url_ = request_info->url; - state_.Initialize(request_info, can_send_early, priority, net_log); + // The WebSocket may receive a socket in the early data state from + // HttpNetworkTransaction, which means it must call ConfirmHandshake() for + // requests that need replay protection. However, the first request on any + // WebSocket stream is a GET with an idempotent request + // (https://tools.ietf.org/html/rfc6455#section-1.3), so there is no need to + // call ConfirmHandshake(). + // + // Data after the WebSockets handshake may not be replayable, but the + // handshake is guaranteed to be confirmed once the HTTP response is received. + DCHECK(can_send_early); + state_.Initialize(request_info, priority, net_log); return OK; }
diff --git a/net/websockets/websocket_http2_handshake_stream.cc b/net/websockets/websocket_http2_handshake_stream.cc index 343b4cd..7e38991 100644 --- a/net/websockets/websocket_http2_handshake_stream.cc +++ b/net/websockets/websocket_http2_handshake_stream.cc
@@ -121,8 +121,10 @@ callback_ = std::move(callback); spdy_stream_request_ = std::make_unique<SpdyStreamRequest>(); + // The initial request for the WebSocket is a CONNECT, so there is no need to + // call ConfirmHandshake(). int rv = spdy_stream_request_->StartRequest( - SPDY_BIDIRECTIONAL_STREAM, session_, request_info_->url, priority_, + SPDY_BIDIRECTIONAL_STREAM, session_, request_info_->url, true, priority_, request_info_->socket_tag, net_log_, base::BindOnce(&WebSocketHttp2HandshakeStream::StartRequestCallback, base::Unretained(this)),
diff --git a/printing/backend/printing_restrictions.cc b/printing/backend/printing_restrictions.cc index 1274926..038558e8 100644 --- a/printing/backend/printing_restrictions.cc +++ b/printing/backend/printing_restrictions.cc
@@ -68,11 +68,11 @@ base::Optional<PinModeRestriction> GetPinModeForName( const std::string& mode_name) { - if (mode_name == "secure") - return PinModeRestriction::kSecure; + if (mode_name == "pin") + return PinModeRestriction::kPin; - if (mode_name == "unsecure") - return PinModeRestriction::kUnsecure; + if (mode_name == "no_pin") + return PinModeRestriction::kNoPin; return base::nullopt; }
diff --git a/printing/backend/printing_restrictions.h b/printing/backend/printing_restrictions.h index 1aa80a18..16bb0236 100644 --- a/printing/backend/printing_restrictions.h +++ b/printing/backend/printing_restrictions.h
@@ -35,8 +35,8 @@ // This is used in pref file and should never change. enum class PinModeRestriction { kNone, - kSecure, - kUnsecure, + kPin, + kNoPin, }; struct PRINTING_EXPORT PrintingRestrictions {
diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn index ea8b7c7..49b2827 100644 --- a/services/device/geolocation/BUILD.gn +++ b/services/device/geolocation/BUILD.gn
@@ -110,7 +110,7 @@ } if (is_chromeos) { deps += [ - "//chromeos/dbus", + "//chromeos/dbus/shill", "//chromeos/network", ] }
diff --git a/services/device/geolocation/OWNERS b/services/device/geolocation/OWNERS index 2ce1e4a..2596b2d 100644 --- a/services/device/geolocation/OWNERS +++ b/services/device/geolocation/OWNERS
@@ -1,6 +1,8 @@ mattreynolds@chromium.org + +# Original (legacy) owners. mcasas@chromium.org timvolodine@chromium.org +# COMPONENT: Blink>Geolocation # TEAM: device-dev@chromium.org -# COMPONENT: Blink>Location
diff --git a/services/device/geolocation/geolocation_service_unittest.cc b/services/device/geolocation/geolocation_service_unittest.cc index 3d69c7a6..36f6ffe 100644 --- a/services/device/geolocation/geolocation_service_unittest.cc +++ b/services/device/geolocation/geolocation_service_unittest.cc
@@ -7,7 +7,7 @@ #include "base/test/bind_test_util.h" #include "build/build_config.h" #if defined(OS_CHROMEOS) -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/network/geolocation_handler.h" #endif #include "mojo/public/cpp/bindings/interface_ptr.h" @@ -40,7 +40,7 @@ protected: void SetUp() override { #if defined(OS_CHROMEOS) - chromeos::DBusThreadManager::Initialize(); + chromeos::shill_clients::InitializeFakes(); chromeos::NetworkHandler::Initialize(); #endif network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock()); @@ -60,7 +60,7 @@ #if defined(OS_CHROMEOS) chromeos::NetworkHandler::Shutdown(); - chromeos::DBusThreadManager::Shutdown(); + chromeos::shill_clients::Shutdown(); #endif // Let the GeolocationImpl destruct earlier than GeolocationProviderImpl to
diff --git a/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc b/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc index 757678a..a76e2bdd 100644 --- a/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc +++ b/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc
@@ -8,7 +8,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_task_environment.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/network/geolocation_handler.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,10 +23,9 @@ base::test::ScopedTaskEnvironment::MainThreadType::UI) {} void SetUp() override { - chromeos::DBusThreadManager::Initialize(); + chromeos::shill_clients::InitializeFakes(); chromeos::NetworkHandler::Initialize(); - manager_client_ = - chromeos::DBusThreadManager::Get()->GetShillManagerClient(); + manager_client_ = chromeos::ShillManagerClient::Get(); manager_test_ = manager_client_->GetTestInterface(); provider_ = new WifiDataProviderChromeOs(); base::RunLoop().RunUntilIdle(); @@ -35,7 +34,7 @@ void TearDown() override { provider_ = NULL; chromeos::NetworkHandler::Shutdown(); - chromeos::DBusThreadManager::Shutdown(); + chromeos::shill_clients::Shutdown(); } bool GetAccessPointData() { return provider_->GetAccessPointData(&ap_data_); }
diff --git a/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc b/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc index ecc955f..63081a2 100644 --- a/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc +++ b/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc
@@ -26,8 +26,7 @@ // static std::unique_ptr<TimeZoneMonitor> TimeZoneMonitor::Create( scoped_refptr<base::SequencedTaskRunner> file_task_runner) { - // TODO(fuchsia): Implement this. crbug.com/750934 - NOTIMPLEMENTED(); + // TODO(https://crbug.com/750934): Implement a real TimeZoneMonitor. return std::make_unique<TimeZoneMonitorFuchsia>(); }
diff --git a/services/resource_coordinator/public/mojom/BUILD.gn b/services/resource_coordinator/public/mojom/BUILD.gn index 2b2c4db..932c3d6 100644 --- a/services/resource_coordinator/public/mojom/BUILD.gn +++ b/services/resource_coordinator/public/mojom/BUILD.gn
@@ -10,7 +10,6 @@ sources = [ "coordination_unit.mojom", - "coordination_unit_introspector.mojom", "lifecycle.mojom", "memory_instrumentation/constants.mojom", "memory_instrumentation/memory_instrumentation.mojom",
diff --git a/services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom b/services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom deleted file mode 100644 index 22752bacb..0000000 --- a/services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module resource_coordinator.mojom; - -import "services/resource_coordinator/public/mojom/coordination_unit.mojom"; -import "mojo/public/mojom/base/process_id.mojom"; -import "mojo/public/mojom/base/time.mojom"; - -// A |PageInfo| describes some metrics about a particular page with respect to -// a given process. -struct PageInfo { - // Identifier to distinguish which URL this |PageInfo| corresponds to. - int64 ukm_source_id; - // Identifier to distinguish which tab this |PageInfo| corresponds to. - uint64 tab_id; - // True iff the process for this |PageInfo| hosts the main frame of the page. - bool hosts_main_frame; - bool is_visible; - mojo_base.mojom.TimeDelta time_since_last_navigation; - mojo_base.mojom.TimeDelta time_since_last_visibility_change; -}; - -struct ProcessInfo { - mojo_base.mojom.ProcessId pid; - array<PageInfo> page_infos; - mojo_base.mojom.Time? launch_time; -}; - -interface CoordinationUnitIntrospector { - // Returns an array that describes the current topology of Chrome, with - // respect to the relationship between processes and hosted frame URLs. - GetProcessToURLMap() => (array<ProcessInfo> process_infos); -};
diff --git a/services/service_manager/sandbox/win/sandbox_win.cc b/services/service_manager/sandbox/win/sandbox_win.cc index 2d994b72..78e0eb48 100644 --- a/services/service_manager/sandbox/win/sandbox_win.cc +++ b/services/service_manager/sandbox/win/sandbox_win.cc
@@ -862,13 +862,12 @@ options.handles_to_inherit = handles_to_inherit; BOOL in_job = true; // Prior to Windows 8 nested jobs aren't possible. - if (sandbox_type == SANDBOX_TYPE_NETWORK && - (base::win::GetVersion() >= base::win::VERSION_WIN8 || - (::IsProcessInJob(::GetCurrentProcess(), nullptr, &in_job) && - !in_job))) { - // Launch the process in a job to ensure that the network process doesn't - // outlive the browser. This could happen if there is a lot of I/O on - // process shutdown, in which case TerminateProcess would fail. + if (base::win::GetVersion() >= base::win::VERSION_WIN8 || + (::IsProcessInJob(::GetCurrentProcess(), nullptr, &in_job) && + !in_job)) { + // Launch the process in a job to ensure that it doesn't outlive the + // browser. This could happen if there is a lot of I/O on process + // shutdown, in which case TerminateProcess would fail. // https://crbug.com/820996 if (!g_job_object_handle) { sandbox::Job job_obj;
diff --git a/services/shape_detection/OWNERS b/services/shape_detection/OWNERS index 0e57d5f..7a97495 100644 --- a/services/shape_detection/OWNERS +++ b/services/shape_detection/OWNERS
@@ -1,5 +1,7 @@ -# COMPONENT: Blink>ImageCapture -# TEAM: media-dev@chromium.org - -mcasas@chromium.org reillyg@chromium.org + +# Original (legacy) owner. +mcasas@chromium.org + +# COMPONENT: Blink>ImageCapture +# TEAM: device-dev@chromium.org
diff --git a/services/video_capture/OWNERS b/services/video_capture/OWNERS index c3dbbd03..495d7a5 100644 --- a/services/video_capture/OWNERS +++ b/services/video_capture/OWNERS
@@ -1,6 +1,8 @@ -# TEAM: media-capture-and-streams@grotations.appspotmail.com -# COMPONENT: Blink>GetUserMedia - chfremer@chromium.org emircan@chromium.org -mcasas@chromium.org + +# Original (legacy) owner. +per-file *video*=mcasas@chromium.org + +# COMPONENT: Blink>GetUserMedia +# TEAM: webrtc-dev@chromium.org
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index c8ca2e8..a39ec10 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -1,6 +1,2630 @@ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, + "ANGLE GPU Linux Release (Intel HD 630)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "angle_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0", + "--no-xvfb" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "angle_unittests" + }, + { + "args": [ + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "angle_white_box_tests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*", + "--no-xvfb" + ], + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "browser_tests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter", + "--enable-features=VizDisplayCompositor,UseSkiaRenderer,UiGpuRasterization", + "--use-gl=any", + "--enable-oop-rasterization", + "--enable-vulkan", + "--enable-gpu-rasterization", + "--enable-raster-to-sk-image", + "--force-gpu-rasterization", + "--disable-software-compositing-fallback", + "--no-xvfb" + ], + "name": "vulkan_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "dawn_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=validating" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--no-xvfb" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_unittests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gles2_conform_test" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "swiftshader_unittests" + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "context_lost_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "depth_capture_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "gpu_process_launch_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "hardware_accelerated_feature_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--expected-vendor-id", + "8086", + "--expected-device-id", + "5912" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "info_collection_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "maps_pixel_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}", + "--use-skia-gold" + ], + "experiment_percentage": 100, + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_skia_gold_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage", + "--review-patch-issue", + "${patch_issue}", + "--review-patch-set", + "${patch_set}", + "--buildbucket-build-id", + "${buildbucket_build_id}" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "screenshot_sync_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "trace_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_gl_passthrough_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_gl_passthrough_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "intel-hd-630-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 2 + } + } + ] + }, + "ANGLE GPU Linux Release (NVIDIA)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "angle_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0", + "--no-xvfb" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "angle_unittests" + }, + { + "args": [ + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "angle_white_box_tests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*", + "--no-xvfb" + ], + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "browser_tests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter", + "--enable-features=VizDisplayCompositor,UseSkiaRenderer,UiGpuRasterization", + "--use-gl=any", + "--enable-oop-rasterization", + "--enable-vulkan", + "--enable-gpu-rasterization", + "--enable-raster-to-sk-image", + "--force-gpu-rasterization", + "--disable-software-compositing-fallback", + "--no-xvfb" + ], + "name": "vulkan_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "dawn_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=validating" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--no-xvfb" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_unittests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gles2_conform_test" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "swiftshader_unittests" + } + ], + "isolated_scripts": [ + { + "args": [ + "--gtest-benchmark-name=angle_perftests", + "-v", + "--one-frame-only" + ], + "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, + "name": "angle_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + } + }, + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "context_lost_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "depth_capture_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "gpu_process_launch_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "hardware_accelerated_feature_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--expected-vendor-id", + "10de", + "--expected-device-id", + "1cb3" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "info_collection_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "maps_pixel_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}", + "--use-skia-gold" + ], + "experiment_percentage": 100, + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_skia_gold_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage", + "--review-patch-issue", + "${patch_issue}", + "--review-patch-set", + "${patch_set}", + "--buildbucket-build-id", + "${buildbucket_build_id}" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "screenshot_sync_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "trace_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_gl_passthrough_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_gl_passthrough_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 2 + } + } + ] + }, + "ANGLE GPU Mac Release (Intel)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "shards": 4 + }, + "test": "angle_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "angle_unittests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" + ], + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "browser_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "shards": 4 + }, + "test": "dawn_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=validating" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "gl_tests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "gl_unittests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "gles2_conform_test" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "gpu_unittests" + }, + { + "args": [ + "--gtest_filter=*Detection*", + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "swiftshader_unittests" + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "context_lost_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "depth_capture_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "gpu_process_launch_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "hardware_accelerated_feature_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--expected-vendor-id", + "8086", + "--expected-device-id", + "0a2e" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "info_collection_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--os-type", + "mac", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "maps_pixel_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "mac", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "screenshot_sync_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "trace_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ], + "idempotent": false, + "shards": 2 + } + } + ] + }, + "ANGLE GPU Mac Retina Release (AMD)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "angle_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "angle_unittests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" + ], + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "browser_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "dawn_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=validating" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_tests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_unittests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gles2_conform_test" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gpu_unittests" + }, + { + "args": [ + "--gtest_filter=*Detection*", + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "swiftshader_unittests" + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "context_lost_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "depth_capture_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "gpu_process_launch_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "hardware_accelerated_feature_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--expected-vendor-id", + "1002", + "--expected-device-id", + "6821" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "info_collection_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--os-type", + "mac", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "maps_pixel_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "mac", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "screenshot_sync_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "trace_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 2 + } + } + ] + }, + "ANGLE GPU Mac Retina Release (NVIDIA)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "angle_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "angle_unittests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" + ], + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "browser_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "dawn_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=validating" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_tests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_unittests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gles2_conform_test" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gpu_unittests" + }, + { + "args": [ + "--gtest_filter=*Detection*", + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ] + }, + "test": "swiftshader_unittests" + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "context_lost_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "depth_capture_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "gpu_process_launch_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "hardware_accelerated_feature_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--expected-vendor-id", + "10de", + "--expected-device-id", + "0fe9" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "info_collection_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--os-type", + "mac", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "maps_pixel_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "mac", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "screenshot_sync_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "trace_test", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac-10.13.6", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 2 + } + } + ] + }, "ANGLE GPU Win10 Release (Intel HD 630)": { "gtest_tests": [ {
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index 3f8549bb..0167c8390 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -920,6 +920,11 @@ # are defined only to be mirrored into trybots, and don't actually # exist on any of the waterfalls or consoles. return [ + 'ANGLE GPU Linux Release (Intel HD 630)', + 'ANGLE GPU Linux Release (NVIDIA)', + 'ANGLE GPU Mac Release (Intel)', + 'ANGLE GPU Mac Retina Release (AMD)', + 'ANGLE GPU Mac Retina Release (NVIDIA)', 'ANGLE GPU Win10 Release (Intel HD 630)', 'ANGLE GPU Win10 Release (NVIDIA)', 'Dawn GPU Linux Release (Intel HD 630)',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 35e7987..ad46626 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -2070,6 +2070,67 @@ 'name': 'chromium.gpu.fyi', 'machines': { # BEGIN Fake builder used as mirror targets for ANGLE's GPU tryservers + 'ANGLE GPU Linux Release (Intel HD 630)': { + 'os_type': 'linux', + 'browser_config': 'release', + 'mixins': [ + 'linux_intel_hd_630', + ], + 'test_suites': { + # TODO(jmadill): Use custom test lists. crbug.com/822310 + 'gtest_tests': 'gpu_fyi_linux_release_gtests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', + }, + }, + 'ANGLE GPU Linux Release (NVIDIA)': { + 'os_type': 'linux', + 'browser_config': 'release', + 'mixins': [ + 'linux_nvidia_quadro_p400', + ], + 'test_suites': { + # TODO(jmadill): Use custom test lists. crbug.com/822310 + 'gtest_tests': 'gpu_fyi_linux_release_gtests', + 'isolated_scripts': 'gpu_angle_perftests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', + }, + }, + 'ANGLE GPU Mac Release (Intel)': { + 'os_type': 'mac', + 'browser_config': 'release', + 'mixins': [ + 'mac_mini_intel_gpu', + ], + 'test_suites': { + # TODO(jmadill): Use custom test lists. crbug.com/822310 + 'gtest_tests': 'gpu_fyi_mac_release_gtests', + 'gpu_telemetry_tests': 'gpu_fyi_mac_release_telemetry_tests', + }, + }, + 'ANGLE GPU Mac Retina Release (AMD)': { + 'os_type': 'mac', + 'browser_config': 'release', + 'mixins': [ + 'mac_retina_amd_gpu', + ], + 'test_suites': { + # TODO(jmadill): Use custom test lists. crbug.com/822310 + 'gtest_tests': 'gpu_fyi_mac_release_gtests', + 'gpu_telemetry_tests': 'gpu_fyi_mac_release_telemetry_tests', + }, + }, + 'ANGLE GPU Mac Retina Release (NVIDIA)': { + 'os_type': 'mac', + 'browser_config': 'release', + 'mixins': [ + 'mac_retina_nvidia_gpu', + ], + 'test_suites': { + # TODO(jmadill): Use custom test lists. crbug.com/822310 + 'gtest_tests': 'gpu_fyi_mac_release_gtests', + 'gpu_telemetry_tests': 'gpu_fyi_mac_release_telemetry_tests', + }, + }, 'ANGLE GPU Win10 Release (Intel HD 630)': { 'os_type': 'win', 'browser_config': 'release',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index f2cfeb1..6b34d2f 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -3014,9 +3014,9 @@ ], "experiments": [ { - "name": "Enabled_300_seconds_20190314", + "name": "Enabled_60_seconds_20190408", "params": { - "unused_idle_socket_timeout_seconds": "300" + "unused_idle_socket_timeout_seconds": "60" }, "enable_features": [ "NetUnusedIdleSocketTimeout"
diff --git a/third_party/blink/common/mediastream/OWNERS b/third_party/blink/common/mediastream/OWNERS index ed7be73..7f3f570 100644 --- a/third_party/blink/common/mediastream/OWNERS +++ b/third_party/blink/common/mediastream/OWNERS
@@ -4,5 +4,5 @@ per-file *_mojom_traits*.*=set noparent per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>GetUserMedia
diff --git a/third_party/blink/public/common/mediastream/OWNERS b/third_party/blink/public/common/mediastream/OWNERS index 155e1a8b..f247c7f 100644 --- a/third_party/blink/public/common/mediastream/OWNERS +++ b/third_party/blink/public/common/mediastream/OWNERS
@@ -6,5 +6,5 @@ per-file *.typemap=set noparent per-file *.typemap=file://ipc/SECURITY_OWNERS -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>GetUserMedia
diff --git a/third_party/blink/public/mojom/mediastream/OWNERS b/third_party/blink/public/mojom/mediastream/OWNERS index ff62c9c..1ec01e1 100644 --- a/third_party/blink/public/mojom/mediastream/OWNERS +++ b/third_party/blink/public/mojom/mediastream/OWNERS
@@ -4,5 +4,5 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>GetUserMedia
diff --git a/third_party/blink/public/platform/modules/mediastream/OWNERS b/third_party/blink/public/platform/modules/mediastream/OWNERS index c205d4f9..32889cc 100644 --- a/third_party/blink/public/platform/modules/mediastream/OWNERS +++ b/third_party/blink/public/platform/modules/mediastream/OWNERS
@@ -2,5 +2,5 @@ per-file media_stream_audio_processor*=aluebs@chromium.org -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>GetUserMedia
diff --git a/third_party/blink/public/web/modules/mediastream/OWNERS b/third_party/blink/public/web/modules/mediastream/OWNERS index 4d93338..9d70184 100644 --- a/third_party/blink/public/web/modules/mediastream/OWNERS +++ b/third_party/blink/public/web/modules/mediastream/OWNERS
@@ -1,4 +1,4 @@ file://third_party/blink/common/mediastream/OWNERS -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>GetUserMedia
diff --git a/third_party/blink/public/web/web_ax_object.h b/third_party/blink/public/web/web_ax_object.h index c6d5dc9c..9e401922 100644 --- a/third_party/blink/public/web/web_ax_object.h +++ b/third_party/blink/public/web/web_ax_object.h
@@ -272,7 +272,6 @@ BLINK_EXPORT bool HasComputedStyle() const; BLINK_EXPORT WebString ComputedStyleDisplay() const; BLINK_EXPORT bool AccessibilityIsIgnored() const; - BLINK_EXPORT bool LineBreaks(WebVector<int>&) const; BLINK_EXPORT void Markers(WebVector<ax::mojom::MarkerType>& types, WebVector<int>& starts, WebVector<int>& ends) const;
diff --git a/third_party/blink/public/web/web_frame.h b/third_party/blink/public/web/web_frame.h index 188e207..e5dd3db 100644 --- a/third_party/blink/public/web/web_frame.h +++ b/third_party/blink/public/web/web_frame.h
@@ -33,7 +33,6 @@ #include <memory> #include "cc/paint/paint_canvas.h" -#include "third_party/blink/public/common/feature_policy/feature_policy.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_insecure_request_policy.h" #include "third_party/blink/public/web/web_frame_load_type.h" @@ -52,6 +51,7 @@ class WebSecurityOrigin; class WebView; enum class WebSandboxFlags; +struct FramePolicy; struct WebFrameOwnerProperties; struct WebRect; @@ -104,7 +104,7 @@ // parent is in another process and it dynamically updates this frame's // sandbox flags or container policy. The new policy won't take effect until // the next navigation. - void SetFrameOwnerPolicy(WebSandboxFlags, const blink::ParsedFeaturePolicy&); + void SetFrameOwnerPolicy(const FramePolicy&); // The frame's insecure request policy. WebInsecureRequestPolicy GetInsecureRequestPolicy() const;
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index e1de94d8..dd216c89 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -112,8 +112,7 @@ blink::InterfaceRegistry*, mojo::ScopedMessagePipeHandle, WebFrame* previous_web_frame, - WebSandboxFlags, - ParsedFeaturePolicy); + const FramePolicy&); // Creates a new local child of this frame. Similar to the other methods that // create frames, the returned frame should be freed by calling Close() when
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h index 8ec78aa..3d3d4543 100644 --- a/third_party/blink/public/web/web_local_frame_client.h +++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -115,6 +115,7 @@ class WebURL; class WebURLResponse; class WebUserMediaClient; +struct FramePolicy; struct WebConsoleMessage; struct WebContextMenuData; struct WebFullscreenOptions; @@ -225,15 +226,13 @@ // to prevent the new child frame from being attached. Otherwise, embedders // should create a new WebLocalFrame, insert it into the frame tree, and // return the created frame. - virtual WebLocalFrame* CreateChildFrame( - WebLocalFrame* parent, - WebTreeScopeType, - const WebString& name, - const WebString& fallback_name, - WebSandboxFlags sandbox_flags, - const ParsedFeaturePolicy& container_policy, - const WebFrameOwnerProperties&, - FrameOwnerElementType) { + virtual WebLocalFrame* CreateChildFrame(WebLocalFrame* parent, + WebTreeScopeType, + const WebString& name, + const WebString& fallback_name, + const FramePolicy&, + const WebFrameOwnerProperties&, + FrameOwnerElementType) { return nullptr; } @@ -283,10 +282,8 @@ // The sandbox flags or container policy have changed for a child frame of // this frame. - virtual void DidChangeFramePolicy( - WebFrame* child_frame, - WebSandboxFlags flags, - const ParsedFeaturePolicy& container_policy) {} + virtual void DidChangeFramePolicy(WebFrame* child_frame, const FramePolicy&) { + } // Called when a Feature-Policy or Content-Security-Policy HTTP header (for // sandbox flags) is encountered while loading the frame's document.
diff --git a/third_party/blink/public/web/web_remote_frame.h b/third_party/blink/public/web/web_remote_frame.h index 6a6a04c..b140fc2 100644 --- a/third_party/blink/public/web/web_remote_frame.h +++ b/third_party/blink/public/web/web_remote_frame.h
@@ -52,20 +52,18 @@ // beginning. virtual WebLocalFrame* CreateLocalChild(WebTreeScopeType, const WebString& name, - WebSandboxFlags, + const FramePolicy&, WebLocalFrameClient*, blink::InterfaceRegistry*, mojo::ScopedMessagePipeHandle, WebFrame* previous_sibling, - const ParsedFeaturePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType, WebFrame* opener) = 0; virtual WebRemoteFrame* CreateRemoteChild(WebTreeScopeType, const WebString& name, - WebSandboxFlags, - const ParsedFeaturePolicy&, + const FramePolicy&, FrameOwnerElementType, WebRemoteFrameClient*, WebFrame* opener) = 0;
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc index a56856c..68d19bf 100644 --- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc +++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -57,6 +57,7 @@ #include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h" #include "third_party/blink/renderer/platform/bindings/v8_private_property.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/histogram.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" @@ -260,7 +261,7 @@ DidAttachGlobalObject(); #endif - script_state_ = ScriptState::Create(context, world_); + script_state_ = MakeGarbageCollected<ScriptState>(context, world_); DCHECK(lifecycle_ == Lifecycle::kContextIsUninitialized || lifecycle_ == Lifecycle::kGlobalObjectIsDetached);
diff --git a/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc b/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc index 4a92bd3..1e0faac 100644 --- a/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc +++ b/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
@@ -45,6 +45,7 @@ #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/wtf/casting.h" @@ -85,16 +86,19 @@ ScheduledAction::ScheduledAction(ScriptState* script_state, V8Function* function, const Vector<ScriptValue>& arguments) - : script_state_(ScriptStateProtectingContext::Create(script_state)), + : script_state_( + MakeGarbageCollected<ScriptStateProtectingContext>(script_state)), function_(function), arguments_(arguments) {} ScheduledAction::ScheduledAction(ScriptState* script_state, const String& code) - : script_state_(ScriptStateProtectingContext::Create(script_state)), + : script_state_( + MakeGarbageCollected<ScriptStateProtectingContext>(script_state)), code_(code) {} ScheduledAction::ScheduledAction(ScriptState* script_state) - : script_state_(ScriptStateProtectingContext::Create(script_state)) {} + : script_state_( + MakeGarbageCollected<ScriptStateProtectingContext>(script_state)) {} ScheduledAction::~ScheduledAction() { // Verify that owning DOMTimer has eagerly disposed.
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc index f44f349..251c4549 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
@@ -21,6 +21,7 @@ #include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "v8/include/v8.h" namespace blink { @@ -104,7 +105,7 @@ ScriptPromisePropertyTestBase() : page_(std::make_unique<DummyPageHolder>(IntSize(1, 1))) { v8::HandleScope handle_scope(GetIsolate()); - other_script_state_ = ScriptState::Create( + other_script_state_ = MakeGarbageCollected<ScriptState>( v8::Context::New(GetIsolate()), DOMWrapperWorld::EnsureIsolatedWorld(GetIsolate(), 1)); }
diff --git a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc index 611ea66..cfa7e4e 100644 --- a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc +++ b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
@@ -53,6 +53,7 @@ #include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h" #include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h" #include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/thread_state.h" #include "v8/include/v8.h" @@ -163,7 +164,7 @@ if (context.IsEmpty()) return false; - script_state_ = ScriptState::Create(context, world_); + script_state_ = MakeGarbageCollected<ScriptState>(context, world_); ScriptState::Scope scope(script_state_);
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index b561dfd..a899165 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -6216,7 +6216,7 @@ // If this frame is not the main frame, then get the container policy from its // owner. if (frame_ && frame_->Owner()) - return frame_->Owner()->ContainerPolicy(); + return frame_->Owner()->GetFramePolicy().container_policy; return ParsedFeaturePolicy(); }
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc index 3493baa..7975a1b 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -931,13 +931,11 @@ void LocalFrameClientImpl::DidChangeFramePolicy( Frame* child_frame, - SandboxFlags flags, - const ParsedFeaturePolicy& container_policy) { + const FramePolicy& frame_policy) { if (!web_frame_->Client()) return; - web_frame_->Client()->DidChangeFramePolicy( - WebFrame::FromFrame(child_frame), static_cast<WebSandboxFlags>(flags), - container_policy); + web_frame_->Client()->DidChangeFramePolicy(WebFrame::FromFrame(child_frame), + frame_policy); } void LocalFrameClientImpl::DidSetFramePolicyHeaders(
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h index 0419fbac..3dc160b 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -206,9 +206,7 @@ void DidChangeName(const String&) override; void DidEnforceInsecureRequestPolicy(WebInsecureRequestPolicy) override; void DidEnforceInsecureNavigationsSet(const std::vector<unsigned>&) override; - void DidChangeFramePolicy(Frame* child_frame, - SandboxFlags, - const ParsedFeaturePolicy&) override; + void DidChangeFramePolicy(Frame* child_frame, const FramePolicy&) override; void DidSetFramePolicyHeaders( SandboxFlags, const ParsedFeaturePolicy& parsed_header) override;
diff --git a/third_party/blink/renderer/core/exported/web_frame.cc b/third_party/blink/renderer/core/exported/web_frame.cc index 321368a..5e13338 100644 --- a/third_party/blink/renderer/core/exported/web_frame.cc +++ b/third_party/blink/renderer/core/exported/web_frame.cc
@@ -159,14 +159,11 @@ ToCoreFrame(*this)->GetSecurityContext()->GetSecurityOrigin()); } -void WebFrame::SetFrameOwnerPolicy( - WebSandboxFlags flags, - const blink::ParsedFeaturePolicy& container_policy) { +void WebFrame::SetFrameOwnerPolicy(const FramePolicy& frame_policy) { // At the moment, this is only used to replicate sandbox flags and container // policy for frames with a remote owner. - auto* owner = To<RemoteFrameOwner>(ToCoreFrame(*this)->Owner()); - owner->SetSandboxFlags(static_cast<SandboxFlags>(flags)); - owner->SetContainerPolicy(container_policy); + To<RemoteFrameOwner>(ToCoreFrame(*this)->Owner()) + ->SetFramePolicy(frame_policy); } WebInsecureRequestPolicy WebFrame::GetInsecureRequestPolicy() const {
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index a8fba24..da0a3200 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -4712,8 +4712,7 @@ WebTreeScopeType scope, const WebString& name, const WebString& fallback_name, - WebSandboxFlags sandbox_flags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType) override { return CreateLocalChild(*parent, scope, @@ -7453,8 +7452,7 @@ WebTreeScopeType scope, const WebString&, const WebString&, - WebSandboxFlags, - const ParsedFeaturePolicy&, + const FramePolicy&, const WebFrameOwnerProperties& frame_owner_properties, FrameOwnerElementType) override { auto child = std::make_unique<TestCachePolicyWebFrameClient>(); @@ -7775,8 +7773,7 @@ WebTreeScopeType scope, const WebString& name, const WebString& fallback_name, - WebSandboxFlags, - const ParsedFeaturePolicy&, + const FramePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType) override { return CreateLocalChild(*parent, scope, &child_client_); @@ -7917,8 +7914,7 @@ WebTreeScopeType scope, const WebString& name, const WebString& fallback_name, - WebSandboxFlags sandbox_flags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy&, const WebFrameOwnerProperties& frame_owner_properties, FrameOwnerElementType) override { ++call_count_; @@ -10806,8 +10802,7 @@ WebTreeScopeType scope, const WebString& name, const WebString& fallback_name, - WebSandboxFlags, - const ParsedFeaturePolicy&, + const FramePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType) override { return CreateLocalChild(*parent, scope, &child_client_); @@ -12324,8 +12319,7 @@ WebTreeScopeType scope, const WebString& name, const WebString& fallback_name, - WebSandboxFlags sandbox_flags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType) override { return CreateLocalChild(*parent, scope, &child_client_); @@ -12589,8 +12583,7 @@ WebTreeScopeType scope, const WebString&, const WebString&, - WebSandboxFlags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy&, const WebFrameOwnerProperties& frameOwnerProperties, FrameOwnerElementType) override { DCHECK(child_client_);
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc index 143562e2..2dd6a1c9 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc +++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
@@ -178,6 +178,7 @@ gfx::Vector2dF(frame_rect_.X(), frame_rect_.Y())); layer_->SetBounds(gfx::Size(frame_rect_.Size())); layer_->SetIsDrawable(true); + layer_->SetHitTestable(true); // When compositing is after paint, composited plugins should have their // layers inserted rather than invoking WebPlugin::paint. RecordForeignLayer(context, DisplayItem::kForeignLayerPlugin, layer_);
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_test.cc b/third_party/blink/renderer/core/exported/web_plugin_container_test.cc index ae580f0..425c1b7 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_test.cc +++ b/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
@@ -203,8 +203,7 @@ WebTreeScopeType scope, const WebString& name, const WebString& fallback_name, - WebSandboxFlags sandbox_flags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType owner_type) override { return CreateLocalChild(*parent, scope,
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc index d16ac271..4b57f17 100644 --- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc +++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
@@ -141,12 +141,11 @@ WebLocalFrame* WebRemoteFrameImpl::CreateLocalChild( WebTreeScopeType scope, const WebString& name, - WebSandboxFlags sandbox_flags, + const FramePolicy& frame_policy, WebLocalFrameClient* client, blink::InterfaceRegistry* interface_registry, mojo::ScopedMessagePipeHandle document_interface_broker_handle, WebFrame* previous_sibling, - const ParsedFeaturePolicy& container_policy, const WebFrameOwnerProperties& frame_owner_properties, FrameOwnerElementType frame_owner_element_type, WebFrame* opener) { @@ -155,8 +154,7 @@ std::move(document_interface_broker_handle), opener); InsertAfter(child, previous_sibling); auto* owner = MakeGarbageCollected<RemoteFrameOwner>( - static_cast<SandboxFlags>(sandbox_flags), container_policy, - frame_owner_properties, frame_owner_element_type); + frame_policy, frame_owner_properties, frame_owner_element_type); child->InitializeCoreFrame(*GetFrame()->GetPage(), owner, name); DCHECK(child->GetFrame()); return child; @@ -173,8 +171,7 @@ WebRemoteFrame* WebRemoteFrameImpl::CreateRemoteChild( WebTreeScopeType scope, const WebString& name, - WebSandboxFlags sandbox_flags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy& frame_policy, FrameOwnerElementType frame_owner_element_type, WebRemoteFrameClient* client, WebFrame* opener) { @@ -182,8 +179,7 @@ child->SetOpener(opener); AppendChild(child); auto* owner = MakeGarbageCollected<RemoteFrameOwner>( - static_cast<SandboxFlags>(sandbox_flags), container_policy, - WebFrameOwnerProperties(), frame_owner_element_type); + frame_policy, WebFrameOwnerProperties(), frame_owner_element_type); child->InitializeCoreFrame(*GetFrame()->GetPage(), owner, name); return child; } @@ -266,7 +262,7 @@ } ParsedFeaturePolicy container_policy; if (GetFrame()->Owner()) - container_policy = GetFrame()->Owner()->ContainerPolicy(); + container_policy = GetFrame()->Owner()->GetFramePolicy().container_policy; const FeaturePolicy::FeatureState& opener_feature_state = frame_->OpenerFeatureState(); GetFrame()->GetSecurityContext()->InitializeFeaturePolicy(
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.h b/third_party/blink/renderer/core/exported/web_remote_frame_impl.h index 9a469a3e0..694ea71 100644 --- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.h +++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
@@ -47,19 +47,17 @@ // WebRemoteFrame methods: WebLocalFrame* CreateLocalChild(WebTreeScopeType, const WebString& name, - WebSandboxFlags, + const FramePolicy&, WebLocalFrameClient*, blink::InterfaceRegistry*, mojo::ScopedMessagePipeHandle, WebFrame* previous_sibling, - const ParsedFeaturePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType, WebFrame* opener) override; WebRemoteFrame* CreateRemoteChild(WebTreeScopeType, const WebString& name, - WebSandboxFlags, - const ParsedFeaturePolicy&, + const FramePolicy&, FrameOwnerElementType, WebRemoteFrameClient*, WebFrame* opener) override;
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index 48ca3b4..68df7b3 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -3692,8 +3692,7 @@ WebTreeScopeType, const WebString& name, const WebString& fallback_name, - WebSandboxFlags, - const ParsedFeaturePolicy&, + const FramePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType) override; @@ -3708,14 +3707,13 @@ WebTreeScopeType scope, const WebString& name, const WebString& fallback_name, - WebSandboxFlags sandbox_flags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy& frame_policy, const WebFrameOwnerProperties& frame_owner_properties, FrameOwnerElementType frame_owner_element_type) { ++count_; return TestWebFrameClient::CreateChildFrame( - parent, scope, name, fallback_name, sandbox_flags, container_policy, - frame_owner_properties, frame_owner_element_type); + parent, scope, name, fallback_name, frame_policy, frame_owner_properties, + frame_owner_element_type); } TEST_F(WebViewTest, ChangeDisplayMode) {
diff --git a/third_party/blink/renderer/core/frame/frame_overlay.cc b/third_party/blink/renderer/core/frame/frame_overlay.cc index 68080a59..a4c344f7 100644 --- a/third_party/blink/renderer/core/frame/frame_overlay.cc +++ b/third_party/blink/renderer/core/frame/frame_overlay.cc
@@ -71,6 +71,7 @@ if (!layer_) { layer_ = std::make_unique<GraphicsLayer>(*this); layer_->SetDrawsContent(true); + layer_->SetHitTestable(true); if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { // This is required for contents of overlay to stay in sync with the page
diff --git a/third_party/blink/renderer/core/frame/frame_owner.h b/third_party/blink/renderer/core/frame/frame_owner.h index c31b88e..bd65ef0 100644 --- a/third_party/blink/renderer/core/frame/frame_owner.h +++ b/third_party/blink/renderer/core/frame/frame_owner.h
@@ -5,11 +5,11 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_OWNER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_OWNER_H_ -#include "third_party/blink/public/common/feature_policy/feature_policy.h" +#include "third_party/blink/public/common/frame/frame_policy.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/frame/sandbox_flags.h" #include "third_party/blink/renderer/core/scroll/scroll_types.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" namespace blink { @@ -32,8 +32,7 @@ virtual Frame* ContentFrame() const = 0; virtual void SetContentFrame(Frame&) = 0; virtual void ClearContentFrame() = 0; - - virtual SandboxFlags GetSandboxFlags() const = 0; + virtual const FramePolicy& GetFramePolicy() const = 0; // Note: there is a subtle ordering dependency here: if a page load needs to // report resource timing information, it *must* do so before calling // DispatchLoad(). @@ -71,7 +70,6 @@ virtual bool AllowPaymentRequest() const = 0; virtual bool IsDisplayNone() const = 0; virtual AtomicString RequiredCsp() const = 0; - virtual const ParsedFeaturePolicy& ContainerPolicy() const = 0; // Returns whether or not children of the owned frame should be lazily loaded. virtual bool ShouldLazyLoadChildren() const = 0; @@ -92,8 +90,9 @@ Frame* ContentFrame() const override { return nullptr; } void SetContentFrame(Frame&) override {} void ClearContentFrame() override {} - SandboxFlags GetSandboxFlags() const override { - return WebSandboxFlags::kNone; + const FramePolicy& GetFramePolicy() const override { + DEFINE_STATIC_LOCAL(FramePolicy, frame_policy, ()); + return frame_policy; } void AddResourceTiming(const ResourceTimingInfo&) override {} void DispatchLoad() override {} @@ -111,10 +110,6 @@ bool AllowPaymentRequest() const override { return false; } bool IsDisplayNone() const override { return false; } AtomicString RequiredCsp() const override { return g_null_atom; } - const ParsedFeaturePolicy& ContainerPolicy() const override { - DEFINE_STATIC_LOCAL(ParsedFeaturePolicy, container_policy, ()); - return container_policy; - } bool ShouldLazyLoadChildren() const override { return false; } private:
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 e8866c55..2d07afa8 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -36,6 +36,7 @@ #include "cc/test/test_ukm_recorder_factory.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_settings.h" +#include "third_party/blink/public/common/frame/frame_policy.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/public/platform/web_string.h" @@ -227,7 +228,7 @@ auto* frame = To<WebLocalFrameImpl>(WebLocalFrame::CreateProvisional( client, nullptr, mojo::MakeRequest(&document_interface_broker).PassMessagePipe(), - &old_frame, WebSandboxFlags::kNone, ParsedFeaturePolicy())); + &old_frame, FramePolicy())); client->Bind(frame, std::move(owned_client)); std::unique_ptr<TestWebWidgetClient> widget_client; // Create a local root, if necessary. @@ -269,10 +270,9 @@ client = CreateDefaultClientIfNeeded(client, owned_client); mojom::blink::DocumentInterfaceBrokerPtrInfo document_interface_broker; auto* frame = To<WebLocalFrameImpl>(parent.CreateLocalChild( - WebTreeScopeType::kDocument, name, WebSandboxFlags::kNone, client, - nullptr, mojo::MakeRequest(&document_interface_broker).PassMessagePipe(), - previous_sibling, ParsedFeaturePolicy(), properties, - FrameOwnerElementType::kIframe, nullptr)); + WebTreeScopeType::kDocument, name, FramePolicy(), client, nullptr, + mojo::MakeRequest(&document_interface_broker).PassMessagePipe(), + previous_sibling, properties, FrameOwnerElementType::kIframe, nullptr)); client->Bind(frame, std::move(owned_client)); std::unique_ptr<TestWebWidgetClient> owned_widget_client; @@ -299,8 +299,8 @@ std::unique_ptr<TestWebRemoteFrameClient> owned_client; client = CreateDefaultClientIfNeeded(client, owned_client); auto* frame = ToWebRemoteFrameImpl(parent.CreateRemoteChild( - WebTreeScopeType::kDocument, name, WebSandboxFlags::kNone, - ParsedFeaturePolicy(), FrameOwnerElementType::kIframe, client, nullptr)); + WebTreeScopeType::kDocument, name, FramePolicy(), + FrameOwnerElementType::kIframe, client, nullptr)); client->Bind(frame, std::move(owned_client)); if (!security_origin) security_origin = SecurityOrigin::CreateUniqueOpaque(); @@ -511,8 +511,7 @@ WebTreeScopeType scope, const WebString& name, const WebString& fallback_name, - WebSandboxFlags sandbox_flags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy&, const WebFrameOwnerProperties& frame_owner_properties, FrameOwnerElementType owner_type) { return CreateLocalChild(*parent, scope);
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 db540bd..8068ecb6 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.h +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -374,8 +374,7 @@ WebTreeScopeType, const WebString& name, const WebString& fallback_name, - WebSandboxFlags, - const ParsedFeaturePolicy&, + const FramePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType) override; void DidStartLoading() override;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 0cccfe4..693f35a9 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -342,9 +342,7 @@ virtual void DidEnforceInsecureRequestPolicy(WebInsecureRequestPolicy) {} virtual void DidEnforceInsecureNavigationsSet(const std::vector<unsigned>&) {} - virtual void DidChangeFramePolicy(Frame* child_frame, - SandboxFlags, - const ParsedFeaturePolicy&) {} + virtual void DidChangeFramePolicy(Frame* child_frame, const FramePolicy&) {} virtual void DidSetFramePolicyHeaders( SandboxFlags,
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 f0e2a6d..afe1f27 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2589,10 +2589,8 @@ // that don't for the purposes of hit testing. For example, an empty div // will not draw content but needs to create a layer to ensure scroll events // do not pass through it. - if (layer->PaintsContentOrHitTest() || - layer->GetHitTestableWithoutDrawsContent()) { + if (layer->PaintsContentOrHitTest() || layer->GetHitTestable()) RecordGraphicsLayerAsForeignLayer(context, layer); - } if (auto* contents_layer = layer->ContentsLayer()) { RecordForeignLayer(context, DisplayItem::kForeignLayerContentsWrapper,
diff --git a/third_party/blink/renderer/core/frame/remote_frame_owner.cc b/third_party/blink/renderer/core/frame/remote_frame_owner.cc index b35efa69..e3adcd17 100644 --- a/third_party/blink/renderer/core/frame/remote_frame_owner.cc +++ b/third_party/blink/renderer/core/frame/remote_frame_owner.cc
@@ -17,11 +17,10 @@ namespace blink { RemoteFrameOwner::RemoteFrameOwner( - SandboxFlags flags, - const ParsedFeaturePolicy& container_policy, + const FramePolicy& frame_policy, const WebFrameOwnerProperties& frame_owner_properties, FrameOwnerElementType frame_owner_element_type) - : sandbox_flags_(flags), + : frame_policy_(frame_policy), browsing_context_container_name_( static_cast<String>(frame_owner_properties.name)), scrolling_( @@ -33,7 +32,6 @@ is_display_none_(frame_owner_properties.is_display_none), needs_occlusion_tracking_(false), required_csp_(frame_owner_properties.required_csp), - container_policy_(container_policy), frame_owner_element_type_(frame_owner_element_type) {} void RemoteFrameOwner::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/frame/remote_frame_owner.h b/third_party/blink/renderer/core/frame/remote_frame_owner.h index 550622c..31afc440 100644 --- a/third_party/blink/renderer/core/frame/remote_frame_owner.h +++ b/third_party/blink/renderer/core/frame/remote_frame_owner.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_OWNER_H_ #include "third_party/blink/public/common/frame/frame_owner_element_type.h" +#include "third_party/blink/public/common/frame/frame_policy.h" #include "third_party/blink/public/web/web_frame_owner_properties.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/frame/frame_owner.h" @@ -25,8 +26,7 @@ USING_GARBAGE_COLLECTED_MIXIN(RemoteFrameOwner); public: - RemoteFrameOwner(SandboxFlags, - const ParsedFeaturePolicy&, + RemoteFrameOwner(const FramePolicy&, const WebFrameOwnerProperties&, FrameOwnerElementType frame_owner_element_type); @@ -34,8 +34,7 @@ Frame* ContentFrame() const override { return frame_.Get(); } void SetContentFrame(Frame&) override; void ClearContentFrame() override; - SandboxFlags GetSandboxFlags() const override { return sandbox_flags_; } - void SetSandboxFlags(SandboxFlags flags) { sandbox_flags_ = flags; } + const FramePolicy& GetFramePolicy() const override { return frame_policy_; } void AddResourceTiming(const ResourceTimingInfo&) override; void DispatchLoad() override; bool CanRenderFallbackContent() const override { @@ -55,11 +54,11 @@ bool AllowPaymentRequest() const override { return allow_payment_request_; } bool IsDisplayNone() const override { return is_display_none_; } AtomicString RequiredCsp() const override { return required_csp_; } - const ParsedFeaturePolicy& ContainerPolicy() const override { - return container_policy_; - } bool ShouldLazyLoadChildren() const final; + void SetFramePolicy(const FramePolicy& frame_policy) { + frame_policy_ = frame_policy; + } void SetBrowsingContextContainerName(const WebString& name) { browsing_context_container_name_ = name; } @@ -78,9 +77,6 @@ void SetRequiredCsp(const WebString& required_csp) { required_csp_ = required_csp; } - void SetContainerPolicy(const ParsedFeaturePolicy& container_policy) { - container_policy_ = container_policy; - } void Trace(blink::Visitor*) override; @@ -91,7 +87,7 @@ bool IsRemote() const override { return true; } Member<Frame> frame_; - SandboxFlags sandbox_flags_; + FramePolicy frame_policy_; AtomicString browsing_context_container_name_; ScrollbarMode scrolling_; int margin_width_; @@ -101,7 +97,6 @@ bool is_display_none_; bool needs_occlusion_tracking_; WebString required_csp_; - ParsedFeaturePolicy container_policy_; const FrameOwnerElementType frame_owner_element_type_; };
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.cc b/third_party/blink/renderer/core/frame/visual_viewport.cc index b0322c6f..0c0e308 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -700,6 +700,7 @@ scrollbar_layer_group->layer.get(), /*prevent_contents_opaque_changes=*/false); scrollbar_graphics_layer->SetDrawsContent(false); + scrollbar_graphics_layer->SetHitTestable(false); scrollbar_layer_group->scrollbar_layer->SetScrollElementId( inner_viewport_scroll_layer_->CcLayer()->element_id()); }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 8f45c37..5032acc 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1615,11 +1615,10 @@ InterfaceRegistry* interface_registry, mojo::ScopedMessagePipeHandle document_interface_broker_handle, WebFrame* previous_frame, - WebSandboxFlags flags, - ParsedFeaturePolicy container_policy) { + const FramePolicy& frame_policy) { return WebLocalFrameImpl::CreateProvisional( client, interface_registry, std::move(document_interface_broker_handle), - previous_frame, flags, container_policy); + previous_frame, frame_policy); } WebLocalFrameImpl* WebLocalFrameImpl::Create( @@ -1664,8 +1663,7 @@ blink::InterfaceRegistry* interface_registry, mojo::ScopedMessagePipeHandle document_interface_broker_handle, WebFrame* previous_web_frame, - WebSandboxFlags flags, - ParsedFeaturePolicy container_policy) { + const FramePolicy& frame_policy) { DCHECK(client); WebLocalFrameImpl* web_frame = MakeGarbageCollected<WebLocalFrameImpl>( previous_web_frame, client, interface_registry, @@ -1692,13 +1690,12 @@ new_frame->SetOwner(previous_frame->Owner()); if (auto* remote_frame_owner = DynamicTo<RemoteFrameOwner>(new_frame->Owner())) { - remote_frame_owner->SetSandboxFlags(static_cast<SandboxFlags>(flags)); - remote_frame_owner->SetContainerPolicy(container_policy); + remote_frame_owner->SetFramePolicy(frame_policy); } else if (!new_frame->Owner()) { // Provisional main frames need to force sandbox flags. This is necessary // to inherit sandbox flags when a sandboxed frame does a window.open() // which triggers a cross-process navigation. - new_frame->Loader().ForceSandboxFlags(static_cast<SandboxFlags>(flags)); + new_frame->Loader().ForceSandboxFlags(frame_policy.sandbox_flags); // If there is an opener (even disowned), the opener policies must be // inherited the same way as sandbox flag. new_frame->SetOpenerFeatureState(previous_frame->OpenerFeatureState()); @@ -1817,14 +1814,12 @@ // solution. subResourceAttributeName returns just one attribute name. The // element might not have the attribute, and there might be other attributes // which can identify the element. - WebLocalFrameImpl* webframe_child = - To<WebLocalFrameImpl>(client_->CreateChildFrame( - this, scope, name, - owner_element->getAttribute( - owner_element->SubResourceAttributeName()), - static_cast<WebSandboxFlags>(owner_element->GetSandboxFlags()), - owner_element->ContainerPolicy(), owner_properties, - owner_element->OwnerType())); + WebLocalFrameImpl* webframe_child = To<WebLocalFrameImpl>( + client_->CreateChildFrame(this, scope, name, + owner_element->getAttribute( + owner_element->SubResourceAttributeName()), + owner_element->GetFramePolicy(), + owner_properties, owner_element->OwnerType())); if (!webframe_child) return nullptr;
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index ef23363..ab46b26 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -359,8 +359,7 @@ InterfaceRegistry*, mojo::ScopedMessagePipeHandle, WebFrame*, - WebSandboxFlags, - ParsedFeaturePolicy); + const FramePolicy&); WebLocalFrameImpl(WebTreeScopeType, WebLocalFrameClient*,
diff --git a/third_party/blink/renderer/core/html/html_frame_element_base.cc b/third_party/blink/renderer/core/html/html_frame_element_base.cc index bcd8df0..7eb0252 100644 --- a/third_party/blink/renderer/core/html/html_frame_element_base.cc +++ b/third_party/blink/renderer/core/html/html_frame_element_base.cc
@@ -138,7 +138,8 @@ scoped_refptr<const SecurityOrigin> HTMLFrameElementBase::GetOriginForFeaturePolicy() const { // Sandboxed frames have a unique origin. - if ((GetSandboxFlags() & WebSandboxFlags::kOrigin) != WebSandboxFlags::kNone) + if ((GetFramePolicy().sandbox_flags & WebSandboxFlags::kOrigin) != + WebSandboxFlags::kNone) return SecurityOrigin::CreateUniqueOpaque(); // If the frame will inherit its origin from the owner, then use the owner's
diff --git a/third_party/blink/renderer/core/html/html_frame_element_test.cc b/third_party/blink/renderer/core/html/html_frame_element_test.cc index 2a9b23b..4be6b74 100644 --- a/third_party/blink/renderer/core/html/html_frame_element_test.cc +++ b/third_party/blink/renderer/core/html/html_frame_element_test.cc
@@ -26,7 +26,7 @@ frame_element->UpdateContainerPolicyForTests(); const ParsedFeaturePolicy& container_policy = - frame_element->ContainerPolicy(); + frame_element->GetFramePolicy().container_policy; EXPECT_EQ(1UL, container_policy.size()); // Fullscreen should be disabled in this frame EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen,
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 64eeea9..2e4b86d 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -145,7 +145,6 @@ : HTMLElement(tag_name, document), content_frame_(nullptr), embedded_content_view_(nullptr), - sandbox_flags_(WebSandboxFlags::kNone), should_lazy_load_children_(DoesParentAllowLazyLoadingChildren(document)) { } @@ -246,16 +245,16 @@ } void HTMLFrameOwnerElement::SetSandboxFlags(SandboxFlags flags) { - sandbox_flags_ = flags; + frame_policy_.sandbox_flags = flags; // Recalculate the container policy in case the allow-same-origin flag has // changed. - container_policy_ = ConstructContainerPolicy(nullptr); + frame_policy_.container_policy = ConstructContainerPolicy(nullptr); // Don't notify about updates if ContentFrame() is null, for example when // the subframe hasn't been created yet. if (ContentFrame()) { - GetDocument().GetFrame()->Client()->DidChangeFramePolicy( - ContentFrame(), sandbox_flags_, container_policy_); + GetDocument().GetFrame()->Client()->DidChangeFramePolicy(ContentFrame(), + frame_policy_); } } @@ -272,12 +271,12 @@ } void HTMLFrameOwnerElement::UpdateContainerPolicy(Vector<String>* messages) { - container_policy_ = ConstructContainerPolicy(messages); + frame_policy_.container_policy = ConstructContainerPolicy(messages); // Don't notify about updates if ContentFrame() is null, for example when // the subframe hasn't been created yet. if (ContentFrame()) { - GetDocument().GetFrame()->Client()->DidChangeFramePolicy( - ContentFrame(), sandbox_flags_, container_policy_); + GetDocument().GetFrame()->Client()->DidChangeFramePolicy(ContentFrame(), + frame_policy_); } } @@ -308,10 +307,6 @@ DispatchScopedEvent(*Event::Create(event_type_names::kLoad)); } -const ParsedFeaturePolicy& HTMLFrameOwnerElement::ContainerPolicy() const { - return container_policy_; -} - Document* HTMLFrameOwnerElement::getSVGDocument( ExceptionState& exception_state) const { Document* doc = contentDocument();
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h index b733a12..ca91bec 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.h +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -100,7 +100,7 @@ void ClearContentFrame() final; void AddResourceTiming(const ResourceTimingInfo&) final; void DispatchLoad() final; - SandboxFlags GetSandboxFlags() const final { return sandbox_flags_; } + const FramePolicy& GetFramePolicy() const final { return frame_policy_; } bool CanRenderFallbackContent() const override { return false; } void RenderFallbackContent(Frame*) override {} void IntrinsicSizingInfoChanged() override {} @@ -115,7 +115,6 @@ bool AllowPaymentRequest() const override { return false; } bool IsDisplayNone() const override { return !embedded_content_view_; } AtomicString RequiredCsp() const override { return g_null_atom; } - const ParsedFeaturePolicy& ContainerPolicy() const override; bool ShouldLazyLoadChildren() const final; // For unit tests, manually trigger the UpdateContainerPolicy method. @@ -177,9 +176,7 @@ Member<Frame> content_frame_; Member<EmbeddedContentView> embedded_content_view_; - SandboxFlags sandbox_flags_; - - ParsedFeaturePolicy container_policy_; + FramePolicy frame_policy_; Member<LazyLoadFrameObserver> lazy_load_frame_observer_; bool should_lazy_load_children_;
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index 517043c..758dea2 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -91,7 +91,8 @@ DOMFeaturePolicy* HTMLIFrameElement::featurePolicy() { if (!policy_) { policy_ = MakeGarbageCollected<IFramePolicy>( - &GetDocument(), ContainerPolicy(), GetOriginForFeaturePolicy()); + &GetDocument(), GetFramePolicy().container_policy, + GetOriginForFeaturePolicy()); } return policy_.Get(); }
diff --git a/third_party/blink/renderer/core/html/html_iframe_element_test.cc b/third_party/blink/renderer/core/html/html_iframe_element_test.cc index caf0d967..ad81f31 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element_test.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element_test.cc
@@ -176,7 +176,7 @@ frame_element->UpdateContainerPolicyForTests(); const ParsedFeaturePolicy& container_policy = - frame_element->ContainerPolicy(); + frame_element->GetFramePolicy().container_policy; EXPECT_EQ(0UL, container_policy.size()); } @@ -195,7 +195,7 @@ frame_element->UpdateContainerPolicyForTests(); const ParsedFeaturePolicy& container_policy1 = - frame_element->ContainerPolicy(); + frame_element->GetFramePolicy().container_policy; EXPECT_EQ(1UL, container_policy1.size()); EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, @@ -209,7 +209,7 @@ frame_element->UpdateContainerPolicyForTests(); const ParsedFeaturePolicy& container_policy2 = - frame_element->ContainerPolicy(); + frame_element->GetFramePolicy().container_policy; EXPECT_EQ(2UL, container_policy2.size()); EXPECT_TRUE(container_policy2[0].feature == mojom::FeaturePolicyFeature::kFullscreen || @@ -243,7 +243,7 @@ frame_element->UpdateContainerPolicyForTests(); const ParsedFeaturePolicy& container_policy = - frame_element->ContainerPolicy(); + frame_element->GetFramePolicy().container_policy; EXPECT_EQ(expected_number_of_sandbox_features, container_policy.size()); } @@ -265,7 +265,7 @@ frame_element->UpdateContainerPolicyForTests(); const ParsedFeaturePolicy& container_policy = - frame_element->ContainerPolicy(); + frame_element->GetFramePolicy().container_policy; EXPECT_EQ(expected_number_of_sandbox_features + 1, container_policy.size()); const auto& container_policy_item = std::find_if( @@ -301,7 +301,7 @@ frame_element->UpdateContainerPolicyForTests(); const ParsedFeaturePolicy& container_policy = - frame_element->ContainerPolicy(); + frame_element->GetFramePolicy().container_policy; EXPECT_EQ(expected_number_of_sandbox_features + 1, container_policy.size()); const auto& container_policy_item = std::find_if(
diff --git a/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc b/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc index 4224493..26e70c15f 100644 --- a/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc +++ b/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
@@ -98,6 +98,7 @@ DCHECK(GetVideoElement().CcLayer()); GetVideoElement().CcLayer()->SetIsDrawable(false); + GetVideoElement().CcLayer()->SetHitTestable(false); } void PictureInPictureInterstitial::Hide() { @@ -112,8 +113,10 @@ interstitial_timer_.StartOneShot(kPictureInPictureHiddenAnimationSeconds, FROM_HERE); - if (GetVideoElement().CcLayer()) + if (GetVideoElement().CcLayer()) { GetVideoElement().CcLayer()->SetIsDrawable(true); + GetVideoElement().CcLayer()->SetHitTestable(true); + } } Node::InsertionNotificationRequest PictureInPictureInterstitial::InsertedInto(
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc index 1156669..5e0b0a0 100644 --- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -208,6 +208,7 @@ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { layer_ = cc::PictureLayer::Create(this); layer_->SetIsDrawable(true); + layer_->SetHitTestable(true); } } ~InspectorPageOverlayDelegate() override {
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index c3cf805..b735a3bf 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -714,8 +714,8 @@ return false; if (frame_->Owner() && - ((frame_->Owner()->GetSandboxFlags() & WebSandboxFlags::kOrigin) != - WebSandboxFlags::kNone)) + ((frame_->Owner()->GetFramePolicy().sandbox_flags & + WebSandboxFlags::kOrigin) != WebSandboxFlags::kNone)) return false; frame_->GetDocument()->ProcessJavaScriptUrl( @@ -1635,7 +1635,7 @@ SandboxFlags FrameLoader::EffectiveSandboxFlags() const { SandboxFlags flags = forced_sandbox_flags_; if (FrameOwner* frame_owner = frame_->Owner()) - flags |= frame_owner->GetSandboxFlags(); + flags |= frame_owner->GetFramePolicy().sandbox_flags; // Frames need to inherit the sandbox flags of their parent frame. if (Frame* parent_frame = frame_->Tree().Parent()) flags |= parent_frame->GetSecurityContext()->GetSandboxFlags();
diff --git a/third_party/blink/renderer/core/loader/private/prerender_handle.cc b/third_party/blink/renderer/core/loader/private/prerender_handle.cc index 6208a53..bc1ccb7 100644 --- a/third_party/blink/renderer/core/loader/private/prerender_handle.cc +++ b/third_party/blink/renderer/core/loader/private/prerender_handle.cc
@@ -35,6 +35,7 @@ #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/loader/frame_loader.h" #include "third_party/blink/renderer/core/loader/prerenderer_client.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/prerender.h" #include "third_party/blink/renderer/platform/weborigin/security_policy.h" @@ -50,7 +51,7 @@ if (!document.GetFrame()) return nullptr; - Prerender* prerender = Prerender::Create( + auto* prerender = MakeGarbageCollected<Prerender>( client, url, prerender_rel_types, SecurityPolicy::GenerateReferrer(document.GetReferrerPolicy(), url, document.OutgoingReferrer()));
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc index b6d68c7..fd5b415 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
@@ -397,6 +397,7 @@ scrollbar_graphics_layer->SetContentsToCcLayer(nullptr, false); scrollbar_graphics_layer->SetDrawsContent(true); + scrollbar_graphics_layer->SetHitTestable(true); } static void SetupScrollbarLayer( @@ -416,6 +417,7 @@ scrollbar_layer_group->layer.get(), /*prevent_contents_opaque_changes=*/false); scrollbar_graphics_layer->SetDrawsContent(false); + scrollbar_graphics_layer->SetHitTestable(false); } void ScrollingCoordinator::AddScrollbarLayerGroup(
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index 9d8833c..cc8339c 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -268,7 +268,7 @@ CreateGraphicsLayer(owning_layer_.GetCompositingReasons(), owning_layer_.GetSquashingDisallowedReasons()); - UpdateHitTestableWithoutDrawsContent(true); + graphics_layer_->SetHitTestable(true); UpdateOpacity(GetLayoutObject().StyleRef()); UpdateTransform(GetLayoutObject().StyleRef()); if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) @@ -296,11 +296,6 @@ scrolling_contents_layer_ = nullptr; } -void CompositedLayerMapping::UpdateHitTestableWithoutDrawsContent( - const bool& should_hit_test) { - graphics_layer_->SetHitTestableWithoutDrawsContent(should_hit_test); -} - void CompositedLayerMapping::UpdateOpacity(const ComputedStyle& style) { graphics_layer_->SetOpacity(CompositingOpacity(style.Opacity())); } @@ -1342,6 +1337,11 @@ // layers. bool contents_visible = owning_layer_.HasVisibleContent() || HasVisibleNonCompositingDescendant(&owning_layer_); + // TODO(sunxd): Investigate and possibly implement computing hit test regions + // in PaintTouchActionRects code path, so that cc has correct pointer-events + // information. + // For now, there is no need to set graphics_layer_'s hit testable bit here, + // because it is always hit testable from cc's perspective. graphics_layer_->SetContentsVisible(contents_visible); // In BGPT mode, we do not need to update the backface visibility here, as it @@ -2175,7 +2175,9 @@ if (layer->HasContentsLayer()) layer->SetContentsRect(IntRect(IntPoint(), frame_rect.Size())); } - layer->SetDrawsContent(h_bar && !layer->HasContentsLayer()); + bool h_bar_visible = h_bar && !layer->HasContentsLayer(); + layer->SetDrawsContent(h_bar_visible); + layer->SetHitTestable(h_bar_visible); } if (GraphicsLayer* layer = LayerForVerticalScrollbar()) { @@ -2188,7 +2190,9 @@ if (layer->HasContentsLayer()) layer->SetContentsRect(IntRect(IntPoint(), frame_rect.Size())); } - layer->SetDrawsContent(v_bar && !layer->HasContentsLayer()); + bool v_bar_visible = v_bar && !layer->HasContentsLayer(); + layer->SetDrawsContent(v_bar_visible); + layer->SetHitTestable(v_bar_visible); } if (GraphicsLayer* layer = LayerForScrollCorner()) { @@ -2199,6 +2203,7 @@ ToIntSize(scroll_corner_and_resizer.Location())); layer->SetSize(gfx::Size(scroll_corner_and_resizer.Size())); layer->SetDrawsContent(!scroll_corner_and_resizer.IsEmpty()); + layer->SetHitTestable(!scroll_corner_and_resizer.IsEmpty()); } } @@ -2389,7 +2394,7 @@ if (!foreground_layer_) { foreground_layer_ = CreateGraphicsLayer(CompositingReason::kLayerForForeground); - foreground_layer_->SetHitTestableWithoutDrawsContent(true); + foreground_layer_->SetHitTestable(true); layer_changed = true; } } else if (foreground_layer_) { @@ -2477,12 +2482,13 @@ scrolling_layer_ = CreateGraphicsLayer(CompositingReason::kLayerForScrollingContainer); scrolling_layer_->SetDrawsContent(false); + scrolling_layer_->SetHitTestable(false); scrolling_layer_->SetMasksToBounds(true); // Inner layer which renders the content that scrolls. scrolling_contents_layer_ = CreateGraphicsLayer(CompositingReason::kLayerForScrollingContents); - scrolling_contents_layer_->SetHitTestableWithoutDrawsContent(true); + scrolling_contents_layer_->SetHitTestable(true); auto element_id = scrollable_area->GetCompositorElementId(); scrolling_contents_layer_->SetElementId(element_id); @@ -2639,6 +2645,7 @@ squashing_layer_ = CreateGraphicsLayer(CompositingReason::kLayerForSquashingContents); squashing_layer_->SetDrawsContent(true); + squashing_layer_->SetHitTestable(true); layers_changed = true; }
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h index be465bb8..3f62979 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -438,7 +438,6 @@ // Result is transform origin in pixels. FloatPoint3D ComputeTransformOrigin(const IntRect& border_box) const; - void UpdateHitTestableWithoutDrawsContent(const bool&); void UpdateOpacity(const ComputedStyle&); void UpdateTransform(const ComputedStyle&); void UpdateLayerBlendMode(const ComputedStyle&);
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc index 86c9f02..8dff6ab1 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -1045,7 +1045,7 @@ mapping->ForegroundLayer()->PaintingPhase()); // Regression test for crbug.com/767908: a foreground layer should also // participates hit testing. - EXPECT_TRUE(mapping->ForegroundLayer()->GetHitTestableWithoutDrawsContent()); + EXPECT_TRUE(mapping->ForegroundLayer()->GetHitTestable()); Element* negative_composited_child = GetDocument().getElementById("negative-composited-child");
diff --git a/third_party/blink/renderer/core/paint/html_canvas_painter.cc b/third_party/blink/renderer/core/paint/html_canvas_painter.cc index d0f90bc..18733ed 100644 --- a/third_party/blink/renderer/core/paint/html_canvas_painter.cc +++ b/third_party/blink/renderer/core/paint/html_canvas_painter.cc
@@ -46,6 +46,7 @@ gfx::Vector2dF(pixel_snapped_rect.X(), pixel_snapped_rect.Y())); layer->SetBounds(gfx::Size(pixel_snapped_rect.Size())); layer->SetIsDrawable(true); + layer->SetHitTestable(true); RecordForeignLayer(context, DisplayItem::kForeignLayerCanvas, layer); return; }
diff --git a/third_party/blink/renderer/core/paint/video_painter.cc b/third_party/blink/renderer/core/paint/video_painter.cc index b5764b44..3a1ddcd 100644 --- a/third_party/blink/renderer/core/paint/video_painter.cc +++ b/third_party/blink/renderer/core/paint/video_painter.cc
@@ -55,6 +55,7 @@ gfx::Vector2dF(snapped_replaced_rect.X(), snapped_replaced_rect.Y())); layer->SetBounds(gfx::Size(snapped_replaced_rect.Size())); layer->SetIsDrawable(true); + layer->SetHitTestable(true); RecordForeignLayer(context, DisplayItem::kForeignLayerVideo, layer); return; }
diff --git a/third_party/blink/renderer/core/paint/video_painter_test.cc b/third_party/blink/renderer/core/paint/video_painter_test.cc index 1a6fe96..7cdc666 100644 --- a/third_party/blink/renderer/core/paint/video_painter_test.cc +++ b/third_party/blink/renderer/core/paint/video_painter_test.cc
@@ -33,6 +33,7 @@ client_->ReadyStateChanged(); layer_ = cc::Layer::Create(); layer_->SetIsDrawable(true); + layer_->SetHitTestable(true); client_->SetCcLayer(layer_.get()); return LoadTiming::kImmediate; }
diff --git a/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js b/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js index c9b14710..4021f43 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js +++ b/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
@@ -36,6 +36,9 @@ /** @type {?UI.ToolbarCheckbox} */ this._originCheckbox = null; + /** @type {?UI.ToolbarButton} */ + this._saveButton = null; + /** @const {!UI.Toolbar} */ this._toolbar = new UI.Toolbar('background-service-toolbar', this.contentElement); this._setupToolbar(); @@ -68,20 +71,27 @@ */ async _setupToolbar() { this._recordButton = - new UI.ToolbarToggle(Common.UIString('Toggle Record'), 'largeicon-start-recording', 'largeicon-stop-recording'); + new UI.ToolbarToggle(ls`Toggle Record`, 'largeicon-start-recording', 'largeicon-stop-recording'); this._recordButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._toggleRecording()); this._recordButton.setToggleWithRedColor(true); this._toolbar.appendToolbarItem(this._recordButton); - const clearButton = new UI.ToolbarButton(Common.UIString('Clear'), 'largeicon-clear'); + const clearButton = new UI.ToolbarButton(ls`Clear`, 'largeicon-clear'); clearButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._clearEvents()); this._toolbar.appendToolbarItem(clearButton); this._toolbar.appendSeparator(); this._originCheckbox = - new UI.ToolbarCheckbox(Common.UIString('Show events from other domains'), undefined, () => this._refreshView()); + new UI.ToolbarCheckbox(ls`Show events from other domains`, undefined, () => this._refreshView()); this._toolbar.appendToolbarItem(this._originCheckbox); + + this._toolbar.appendSeparator(); + + this._saveButton = new UI.ToolbarButton(ls`Save events`, 'largeicon-download'); + this._saveButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._saveToFile()); + this._saveButton.setEnabled(false); + this._toolbar.appendToolbarItem(this._saveButton); } /** @@ -100,6 +110,7 @@ _clearView() { this._dataGrid.rootNode().removeChildren(); this._showPreview(null); + this._saveButton.setEnabled(false); } /** @@ -151,6 +162,9 @@ const data = this._createEventData(serviceEvent); const dataNode = new Resources.BackgroundServiceView.EventDataNode(data, serviceEvent.eventMetadata); this._dataGrid.rootNode().appendChild(dataNode); + + // There's at least one event. So we can allow saving the events. + this._saveButton.setEnabled(true); } /** @@ -158,12 +172,12 @@ */ _createDataGrid() { const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([ - {id: 'id', title: Common.UIString('#'), weight: 1}, - {id: 'timestamp', title: Common.UIString('Timestamp'), weight: 8}, - {id: 'origin', title: Common.UIString('Origin'), weight: 10}, - {id: 'swSource', title: Common.UIString('SW Source'), weight: 4}, - {id: 'eventName', title: Common.UIString('Event'), weight: 10}, - {id: 'instanceId', title: Common.UIString('Instance ID'), weight: 10}, + {id: 'id', title: ls`#`, weight: 1}, + {id: 'timestamp', title: ls`Timestamp`, weight: 8}, + {id: 'origin', title: ls`Origin`, weight: 10}, + {id: 'swSource', title: ls`SW Source`, weight: 4}, + {id: 'eventName', title: ls`Event`, weight: 10}, + {id: 'instanceId', title: ls`Instance ID`, weight: 10}, ]); const dataGrid = new DataGrid.DataGrid(columns); dataGrid.setStriped(true); @@ -234,6 +248,22 @@ this._preview.show(this._previewPanel.contentElement); } + + /** + * Saves all currently displayed events in a file (JSON format). + */ + async _saveToFile() { + const fileName = `${this._serviceName}-${new Date().toISO8601Compact()}.json`; + const stream = new Bindings.FileOutputStream(); + + const accepted = await stream.open(fileName); + if (!accepted) + return; + + const events = this._model.getEvents(this._serviceName).filter(event => this._acceptEvent(event)); + await stream.write(JSON.stringify(events, undefined, 2)); + stream.close(); + } }; /**
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index 351c1a3..bf07487 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -2844,29 +2844,6 @@ return AXObjectCache().ValidationMessageObjectIfInvalid(); } -void AXLayoutObject::LineBreaks(Vector<int>& line_breaks) const { - if (!IsTextControl()) - return; - - VisiblePosition visible_pos = VisiblePositionForIndex(0); - VisiblePosition prev_visible_pos = visible_pos; - visible_pos = NextLinePosition(visible_pos, LayoutUnit(), kHasEditableAXRole); - // nextLinePosition moves to the end of the current line when there are - // no more lines. - while (visible_pos.IsNotNull() && - !InSameLine(prev_visible_pos, visible_pos)) { - line_breaks.push_back(IndexForVisiblePosition(visible_pos)); - prev_visible_pos = visible_pos; - visible_pos = - NextLinePosition(visible_pos, LayoutUnit(), kHasEditableAXRole); - - // Make sure we always make forward progress. - if (visible_pos.DeepEquivalent().CompareTo( - prev_visible_pos.DeepEquivalent()) < 0) - break; - } -} - // The following is a heuristic used to determine if a // <table> should be with ax::mojom::Role::kTable or // ax::mojom::Role::kLayoutTable.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h index 72a57758..c458081 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
@@ -185,7 +185,6 @@ // Text metrics. Most of these should be deprecated, needs major cleanup. int Index(const VisiblePosition&) const override; VisiblePosition VisiblePositionForIndex(int) const override; - void LineBreaks(Vector<int>&) const final; // For a table. bool IsDataTable() const override;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 98e5689..3500a9db 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -996,7 +996,6 @@ // Text metrics. Most of these should be deprecated, needs major cleanup. virtual VisiblePosition VisiblePositionForIndex(int) const; virtual int Index(const VisiblePosition&) const { return -1; } - virtual void LineBreaks(Vector<int>&) const {} // Static helper functions. static bool IsARIAControl(ax::mojom::Role);
diff --git a/third_party/blink/renderer/modules/exported/web_ax_object.cc b/third_party/blink/renderer/modules/exported/web_ax_object.cc index f748f8d..fbdfaf7 100644 --- a/third_party/blink/renderer/modules/exported/web_ax_object.cc +++ b/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -1211,16 +1211,6 @@ return private_->AccessibilityIsIgnored(); } -bool WebAXObject::LineBreaks(WebVector<int>& result) const { - if (IsDetached()) - return false; - - Vector<int> line_breaks_vector; - private_->LineBreaks(line_breaks_vector); - result = line_breaks_vector; - return true; -} - int WebAXObject::AriaColumnCount() const { if (IsDetached()) return 0;
diff --git a/third_party/blink/renderer/modules/geolocation/OWNERS b/third_party/blink/renderer/modules/geolocation/OWNERS index 51b1f3e2..2dbeb1a 100644 --- a/third_party/blink/renderer/modules/geolocation/OWNERS +++ b/third_party/blink/renderer/modules/geolocation/OWNERS
@@ -1,5 +1,7 @@ mattreynolds@chromium.org + +# Original (legacy) owner. mcasas@chromium.org # TEAM: device-dev@chromium.org -# COMPONENT: Blink>Location +# COMPONENT: Blink>Geolocation
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS b/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS index 14affd71..49f3612 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS +++ b/third_party/blink/renderer/modules/mediacapturefromelement/OWNERS
@@ -1,5 +1,7 @@ emircan@chromium.org + +# Original (legacy) owner. mcasas@chromium.org -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>MediaStream>CaptureFromElement
diff --git a/third_party/blink/renderer/modules/mediarecorder/OWNERS b/third_party/blink/renderer/modules/mediarecorder/OWNERS index c824512..5f88414 100644 --- a/third_party/blink/renderer/modules/mediarecorder/OWNERS +++ b/third_party/blink/renderer/modules/mediarecorder/OWNERS
@@ -1,5 +1,7 @@ -mcasas@chromium.org peter@chromium.org +# Original (legacy) owner. +mcasas@chromium.org + # COMPONENT: Blink>MediaRecording -# TEAM: media-dev@chromium.org +# TEAM: webrtc-dev@chromium.org
diff --git a/third_party/blink/renderer/modules/mediastream/OWNERS b/third_party/blink/renderer/modules/mediastream/OWNERS index fa857a6..77d16fa 100644 --- a/third_party/blink/renderer/modules/mediastream/OWNERS +++ b/third_party/blink/renderer/modules/mediastream/OWNERS
@@ -2,5 +2,5 @@ hbos@chromium.org tommi@chromium.org -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>GetUserMedia
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc index 8b29287e..014bfa4 100644 --- a/third_party/blink/renderer/modules/modules_initializer.cc +++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -234,7 +234,7 @@ session->Append(MakeGarbageCollected<InspectorAccessibilityAgent>( inspected_frames, dom_agent)); if (allow_view_agents) { - session->Append(InspectorDatabaseAgent::Create(page)); + session->Append(MakeGarbageCollected<InspectorDatabaseAgent>(page)); session->Append( MakeGarbageCollected<InspectorCacheStorageAgent>(inspected_frames)); }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc index 9345d832..b3d4356 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -194,7 +194,7 @@ } WebRTCOfferOptions ConvertToWebRTCOfferOptions(const RTCOfferOptions* options) { - return WebRTCOfferOptions(RTCOfferOptionsPlatform::Create( + return WebRTCOfferOptions(MakeGarbageCollected<RTCOfferOptionsPlatform>( options->hasOfferToReceiveVideo() ? std::max(options->offerToReceiveVideo(), 0) : -1, @@ -208,7 +208,7 @@ WebRTCAnswerOptions ConvertToWebRTCAnswerOptions( const RTCAnswerOptions* options) { - return WebRTCAnswerOptions(RTCAnswerOptionsPlatform::Create( + return WebRTCAnswerOptions(MakeGarbageCollected<RTCAnswerOptionsPlatform>( options->hasVoiceActivityDetection() ? options->voiceActivityDetection() : true)); } @@ -484,9 +484,10 @@ voice_activity_detection); DictionaryHelper::Get(options, "iceRestart", ice_restart); - RTCOfferOptionsPlatform* rtc_offer_options = RTCOfferOptionsPlatform::Create( - offer_to_receive_video, offer_to_receive_audio, voice_activity_detection, - ice_restart); + RTCOfferOptionsPlatform* rtc_offer_options = + MakeGarbageCollected<RTCOfferOptionsPlatform>( + offer_to_receive_video, offer_to_receive_audio, + voice_activity_detection, ice_restart); return rtc_offer_options; }
diff --git a/third_party/blink/renderer/modules/shapedetection/OWNERS b/third_party/blink/renderer/modules/shapedetection/OWNERS index 2a126b8..bb37d31 100644 --- a/third_party/blink/renderer/modules/shapedetection/OWNERS +++ b/third_party/blink/renderer/modules/shapedetection/OWNERS
@@ -1,8 +1,10 @@ -mcasas@chromium.org reillyg@chromium.org +# Original (legacy) owner. +mcasas@chromium.org + per-file *_type_converter*.*=set noparent per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS # COMPONENT: Blink>ImageCapture -# TEAM: media-dev@chromium.org +# TEAM: device-dev@chromium.org
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.cc b/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.cc index 3ea1cd65..48866f0 100644 --- a/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.cc +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/modules/speech/speech_synthesis_utterance.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -38,7 +39,8 @@ SpeechSynthesisUtterance::SpeechSynthesisUtterance(ExecutionContext* context, const String& text) : ContextClient(context), - platform_utterance_(PlatformSpeechSynthesisUtterance::Create(this)) { + platform_utterance_( + MakeGarbageCollected<PlatformSpeechSynthesisUtterance>(this)) { platform_utterance_->SetText(text); }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc b/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc index 1399f8f..0237f78 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc
@@ -35,10 +35,6 @@ class MockCrossOriginLocalFrameClient final : public EmptyLocalFrameClient { public: - static MockCrossOriginLocalFrameClient* Create(Frame* parent) { - return MakeGarbageCollected<MockCrossOriginLocalFrameClient>(parent); - } - explicit MockCrossOriginLocalFrameClient(Frame* parent) : parent_(parent) {} void Trace(blink::Visitor* visitor) override {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_listener.h b/third_party/blink/renderer/modules/webaudio/audio_listener.h index 062e013..3c34cc0 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_listener.h +++ b/third_party/blink/renderer/modules/webaudio/audio_listener.h
@@ -46,11 +46,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - static AudioListener* Create(BaseAudioContext& context) { - return MakeGarbageCollected<AudioListener>(context); - } - - AudioListener(BaseAudioContext&); + explicit AudioListener(BaseAudioContext&); ~AudioListener() override; // Location of the listener
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet.cc index 004b6dc..1e51464 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
@@ -16,10 +16,6 @@ namespace blink { -AudioWorklet* AudioWorklet::Create(BaseAudioContext* context) { - return MakeGarbageCollected<AudioWorklet>(context); -} - AudioWorklet::AudioWorklet(BaseAudioContext* context) : Worklet(To<Document>(context->GetExecutionContext())), context_(context) {}
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet.h b/third_party/blink/renderer/modules/webaudio/audio_worklet.h index 5bf74a05..1a51696 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet.h +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet.h
@@ -24,8 +24,6 @@ USING_GARBAGE_COLLECTED_MIXIN(AudioWorklet); public: - static AudioWorklet* Create(BaseAudioContext*); - explicit AudioWorklet(BaseAudioContext*); ~AudioWorklet() override = default;
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc index 4ccfe14..01f826fb 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
@@ -35,13 +35,6 @@ namespace blink { -AudioWorkletGlobalScope* AudioWorkletGlobalScope::Create( - std::unique_ptr<GlobalScopeCreationParams> creation_params, - WorkerThread* thread) { - return MakeGarbageCollected<AudioWorkletGlobalScope>( - std::move(creation_params), thread); -} - AudioWorkletGlobalScope::AudioWorkletGlobalScope( std::unique_ptr<GlobalScopeCreationParams> creation_params, WorkerThread* thread)
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h index ed961630..afc99d1 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h
@@ -53,10 +53,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static AudioWorkletGlobalScope* Create( - std::unique_ptr<GlobalScopeCreationParams>, - WorkerThread*); - AudioWorkletGlobalScope(std::unique_ptr<GlobalScopeCreationParams>, WorkerThread*); ~AudioWorkletGlobalScope() override;
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread.cc index 80f8318c..5ecf1cc 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread.cc
@@ -67,7 +67,8 @@ std::unique_ptr<GlobalScopeCreationParams> creation_params) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio-worklet"), "AudioWorkletThread::createWorkerGlobalScope"); - return AudioWorkletGlobalScope::Create(std::move(creation_params), this); + return MakeGarbageCollected<AudioWorkletGlobalScope>( + std::move(creation_params), this); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc index 8c608b3..b3cd206 100644 --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -120,7 +120,7 @@ FFTFrame::Initialize(); - audio_worklet_ = AudioWorklet::Create(this); + audio_worklet_ = MakeGarbageCollected<AudioWorklet>(this); if (destination_node_) { destination_node_->Handler().Initialize(); @@ -134,7 +134,7 @@ // The AudioParams in the listener need access to the destination node, so // only create the listener if the destination node exists. - listener_ = AudioListener::Create(*this); + listener_ = MakeGarbageCollected<AudioListener>(*this); } }
diff --git a/third_party/blink/renderer/modules/webdatabase/change_version_wrapper.h b/third_party/blink/renderer/modules/webdatabase/change_version_wrapper.h index f7c9896..96b21f1 100644 --- a/third_party/blink/renderer/modules/webdatabase/change_version_wrapper.h +++ b/third_party/blink/renderer/modules/webdatabase/change_version_wrapper.h
@@ -39,11 +39,6 @@ class ChangeVersionWrapper final : public SQLTransactionWrapper { public: - static ChangeVersionWrapper* Create(const String& old_version, - const String& new_version) { - return MakeGarbageCollected<ChangeVersionWrapper>(old_version, new_version); - } - ChangeVersionWrapper(const String& old_version, const String& new_version); bool PerformPreflight(SQLTransactionBackend*) override;
diff --git a/third_party/blink/renderer/modules/webdatabase/database.cc b/third_party/blink/renderer/modules/webdatabase/database.cc index 47fa3aa..a477ee5 100644 --- a/third_party/blink/renderer/modules/webdatabase/database.cc +++ b/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -346,12 +346,13 @@ return nullptr; SQLTransactionWrapper* wrapper = nullptr; - if (data) - wrapper = - ChangeVersionWrapper::Create(data->OldVersion(), data->NewVersion()); + if (data) { + wrapper = MakeGarbageCollected<ChangeVersionWrapper>(data->OldVersion(), + data->NewVersion()); + } - SQLTransactionBackend* transaction_backend = - SQLTransactionBackend::Create(this, transaction, wrapper, read_only); + auto* transaction_backend = MakeGarbageCollected<SQLTransactionBackend>( + this, transaction, wrapper, read_only); transaction_queue_.push_back(transaction_backend); if (!transaction_in_progress_) ScheduleTransaction(); @@ -806,7 +807,7 @@ static void CallTransactionErrorCallback( SQLTransaction::OnErrorCallback* callback, std::unique_ptr<SQLErrorData> error_data) { - callback->OnError(SQLError::Create(*error_data)); + callback->OnError(MakeGarbageCollected<SQLError>(*error_data)); } void Database::RunTransaction(
diff --git a/third_party/blink/renderer/modules/webdatabase/database_context.cc b/third_party/blink/renderer/modules/webdatabase/database_context.cc index 765aaaa..a77f130 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_context.cc +++ b/third_party/blink/renderer/modules/webdatabase/database_context.cc
@@ -145,7 +145,7 @@ // Create the database thread on first request - but not if at least one // database was already opened, because in that case we already had a // database thread and terminated it and should not create another. - database_thread_ = DatabaseThread::Create(); + database_thread_ = MakeGarbageCollected<DatabaseThread>(); database_thread_->Start(); }
diff --git a/third_party/blink/renderer/modules/webdatabase/database_thread.h b/third_party/blink/renderer/modules/webdatabase/database_thread.h index fc146e7..f3628ca 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_thread.h +++ b/third_party/blink/renderer/modules/webdatabase/database_thread.h
@@ -44,10 +44,6 @@ class DatabaseThread : public GarbageCollectedFinalized<DatabaseThread> { public: - static DatabaseThread* Create() { - return MakeGarbageCollected<DatabaseThread>(); - } - DatabaseThread(); ~DatabaseThread(); void Trace(blink::Visitor*);
diff --git a/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc b/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc index 4e21c51..3dc7108 100644 --- a/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc +++ b/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc
@@ -82,11 +82,6 @@ class StatementCallback final : public SQLStatement::OnSuccessCallback { public: - static StatementCallback* Create( - scoped_refptr<ExecuteSQLCallbackWrapper> request_callback) { - return MakeGarbageCollected<StatementCallback>(std::move(request_callback)); - } - explicit StatementCallback( scoped_refptr<ExecuteSQLCallbackWrapper> request_callback) : request_callback_(std::move(request_callback)) {} @@ -130,12 +125,6 @@ class StatementErrorCallback final : public SQLStatement::OnErrorCallback { public: - static StatementErrorCallback* Create( - scoped_refptr<ExecuteSQLCallbackWrapper> request_callback) { - return MakeGarbageCollected<StatementErrorCallback>( - std::move(request_callback)); - } - explicit StatementErrorCallback( scoped_refptr<ExecuteSQLCallbackWrapper> request_callback) : request_callback_(std::move(request_callback)) {} @@ -152,13 +141,6 @@ class TransactionCallback final : public SQLTransaction::OnProcessCallback { public: - static TransactionCallback* Create( - const String& sql_statement, - scoped_refptr<ExecuteSQLCallbackWrapper> request_callback) { - return MakeGarbageCollected<TransactionCallback>( - sql_statement, std::move(request_callback)); - } - explicit TransactionCallback( const String& sql_statement, scoped_refptr<ExecuteSQLCallbackWrapper> request_callback) @@ -168,10 +150,11 @@ bool OnProcess(SQLTransaction* transaction) override { Vector<SQLValue> sql_values; - transaction->ExecuteSQL(sql_statement_, sql_values, - StatementCallback::Create(request_callback_), - StatementErrorCallback::Create(request_callback_), - IGNORE_EXCEPTION_FOR_TESTING); + transaction->ExecuteSQL( + sql_statement_, sql_values, + MakeGarbageCollected<StatementCallback>(request_callback_), + MakeGarbageCollected<StatementErrorCallback>(request_callback_), + IGNORE_EXCEPTION_FOR_TESTING); return true; } @@ -220,8 +203,8 @@ return; } - InspectorDatabaseResource* resource = - InspectorDatabaseResource::Create(database, domain, name, version); + auto* resource = MakeGarbageCollected<InspectorDatabaseResource>( + database, domain, name, version); resources_.Set(resource->Id(), resource); // Resources are only bound while visible. DCHECK(enabled_.Get()); @@ -313,7 +296,7 @@ scoped_refptr<ExecuteSQLCallbackWrapper> wrapper = ExecuteSQLCallbackWrapper::Create(std::move(request_callback)); - TransactionCallback* callback = TransactionCallback::Create(query, wrapper); + auto* callback = MakeGarbageCollected<TransactionCallback>(query, wrapper); TransactionErrorCallback* error_callback = TransactionErrorCallback::Create(wrapper); SQLTransaction::OnSuccessCallback* success_callback = nullptr;
diff --git a/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.h b/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.h index 7d1e8c30..9b9e502 100644 --- a/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.h +++ b/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.h
@@ -46,10 +46,6 @@ class MODULES_EXPORT InspectorDatabaseAgent final : public InspectorBaseAgent<protocol::Database::Metainfo> { public: - static InspectorDatabaseAgent* Create(Page* page) { - return MakeGarbageCollected<InspectorDatabaseAgent>(page); - } - explicit InspectorDatabaseAgent(Page*); ~InspectorDatabaseAgent() override; void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.cc b/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.cc index 9a696e6..8926d25 100644 --- a/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.cc +++ b/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.cc
@@ -36,15 +36,6 @@ static int g_next_unused_id = 1; -InspectorDatabaseResource* InspectorDatabaseResource::Create( - Database* database, - const String& domain, - const String& name, - const String& version) { - return MakeGarbageCollected<InspectorDatabaseResource>(database, domain, name, - version); -} - InspectorDatabaseResource::InspectorDatabaseResource(Database* database, const String& domain, const String& name,
diff --git a/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h b/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h index f5d59f0..dadec74 100644 --- a/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h +++ b/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h
@@ -42,10 +42,6 @@ class InspectorDatabaseResource : public GarbageCollectedFinalized<InspectorDatabaseResource> { public: - static InspectorDatabaseResource* Create(Database*, - const String& domain, - const String& name, - const String& version); InspectorDatabaseResource(Database*, const String& domain, const String& name,
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_error.h b/third_party/blink/renderer/modules/webdatabase/sql_error.h index 0cf5de3..5897d26 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_error.h +++ b/third_party/blink/renderer/modules/webdatabase/sql_error.h
@@ -68,10 +68,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static SQLError* Create(const SQLErrorData& data) { - return MakeGarbageCollected<SQLError>(data); - } - explicit SQLError(const SQLErrorData& data) : data_(data) {} unsigned code() const { return data_.Code(); }
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc b/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc index 3bef9f7..b974182 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc +++ b/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc
@@ -34,7 +34,7 @@ namespace blink { SQLResultSet::SQLResultSet() - : rows_(SQLResultSetRowList::Create()), + : rows_(MakeGarbageCollected<SQLResultSetRowList>()), insert_id_(0), rows_affected_(0), insert_id_set_(false),
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_result_set.h b/third_party/blink/renderer/modules/webdatabase/sql_result_set.h index 8577ba9..5afa63a 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_result_set.h +++ b/third_party/blink/renderer/modules/webdatabase/sql_result_set.h
@@ -41,8 +41,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static SQLResultSet* Create() { return MakeGarbageCollected<SQLResultSet>(); } - SQLResultSet(); void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.h b/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.h index 206ce9b0..48a7524 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.h +++ b/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.h
@@ -43,10 +43,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static SQLResultSetRowList* Create() { - return MakeGarbageCollected<SQLResultSetRowList>(); - } - SQLResultSetRowList() = default; const Vector<String>& ColumnNames() const { return columns_; }
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_statement.cc b/third_party/blink/renderer/modules/webdatabase/sql_statement.cc index d060881..f35c9540 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_statement.cc +++ b/third_party/blink/renderer/modules/webdatabase/sql_statement.cc
@@ -83,12 +83,6 @@ return return_value; } -SQLStatement* SQLStatement::Create(Database* database, - OnSuccessCallback* callback, - OnErrorCallback* error_callback) { - return MakeGarbageCollected<SQLStatement>(database, callback, error_callback); -} - SQLStatement::SQLStatement(Database* database, OnSuccessCallback* callback, OnErrorCallback* error_callback) @@ -136,8 +130,8 @@ // error, because then we need to jump to the transaction error callback. if (error) { if (error_callback) { - callback_error = - error_callback->OnError(transaction, SQLError::Create(*error)); + callback_error = error_callback->OnError( + transaction, MakeGarbageCollected<SQLError>(*error)); } } else if (callback) { callback_error =
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.cc b/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.cc index 2e9d147..4473669 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.cc +++ b/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.cc
@@ -82,15 +82,6 @@ namespace blink { -SQLStatementBackend* SQLStatementBackend::Create( - SQLStatement* frontend, - const String& statement, - const Vector<SQLValue>& arguments, - int permissions) { - return MakeGarbageCollected<SQLStatementBackend>(frontend, statement, - arguments, permissions); -} - SQLStatementBackend::SQLStatementBackend(SQLStatement* frontend, const String& statement, const Vector<SQLValue>& arguments, @@ -100,7 +91,7 @@ arguments_(arguments), has_callback_(frontend_->HasCallback()), has_error_callback_(frontend_->HasErrorCallback()), - result_set_(SQLResultSet::Create()), + result_set_(MakeGarbageCollected<SQLResultSet>()), permissions_(permissions) { DCHECK(IsMainThread());
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h b/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h index bd4174c5..cc1756d3 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h +++ b/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h
@@ -45,11 +45,6 @@ class SQLStatementBackend final : public GarbageCollectedFinalized<SQLStatementBackend> { public: - static SQLStatementBackend* Create(SQLStatement*, - const String& sql_statement, - const Vector<SQLValue>& arguments, - int permissions); - SQLStatementBackend(SQLStatement*, const String& statement, const Vector<SQLValue>& arguments,
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc b/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc index 5bccafb6..ca901e6 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc +++ b/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
@@ -223,7 +223,8 @@ std::make_unique<SQLErrorData>(*backend_->TransactionError()); } DCHECK(transaction_error_); - error_callback->OnError(SQLError::Create(*transaction_error_)); + error_callback->OnError( + MakeGarbageCollected<SQLError>(*transaction_error_)); transaction_error_ = nullptr; } @@ -328,8 +329,8 @@ else if (read_only_) permissions |= DatabaseAuthorizer::kReadOnlyMask; - SQLStatement* statement = - SQLStatement::Create(database_.Get(), callback, callback_error); + auto* statement = MakeGarbageCollected<SQLStatement>( + database_.Get(), callback, callback_error); backend_->ExecuteSQL(statement, sql_statement, arguments, permissions); }
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc b/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc index 8ec97828..b71b5f5 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc +++ b/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc
@@ -366,15 +366,6 @@ namespace blink { -SQLTransactionBackend* SQLTransactionBackend::Create( - Database* db, - SQLTransaction* frontend, - SQLTransactionWrapper* wrapper, - bool read_only) { - return MakeGarbageCollected<SQLTransactionBackend>(db, frontend, wrapper, - read_only); -} - SQLTransactionBackend::SQLTransactionBackend(Database* db, SQLTransaction* frontend, SQLTransactionWrapper* wrapper, @@ -563,8 +554,8 @@ const Vector<SQLValue>& arguments, int permissions) { DCHECK(IsMainThread()); - EnqueueStatementBackend(SQLStatementBackend::Create(statement, sql_statement, - arguments, permissions)); + EnqueueStatementBackend(MakeGarbageCollected<SQLStatementBackend>( + statement, sql_statement, arguments, permissions)); } void SQLTransactionBackend::NotifyDatabaseThreadIsShuttingDown() {
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h b/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h index d6197d4..3525a91 100644 --- a/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h +++ b/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h
@@ -62,11 +62,6 @@ : public GarbageCollectedFinalized<SQLTransactionBackend>, public SQLTransactionStateMachine<SQLTransactionBackend> { public: - static SQLTransactionBackend* Create(Database*, - SQLTransaction*, - SQLTransactionWrapper*, - bool read_only); - SQLTransactionBackend(Database*, SQLTransaction*, SQLTransactionWrapper*,
diff --git a/third_party/blink/renderer/platform/bindings/script_state.cc b/third_party/blink/renderer/platform/bindings/script_state.cc index 67c312eb..19a54f90 100644 --- a/third_party/blink/renderer/platform/bindings/script_state.cc +++ b/third_party/blink/renderer/platform/bindings/script_state.cc
@@ -10,11 +10,6 @@ namespace blink { -ScriptState* ScriptState::Create(v8::Local<v8::Context> context, - scoped_refptr<DOMWrapperWorld> world) { - return MakeGarbageCollected<ScriptState>(context, std::move(world)); -} - ScriptState::ScriptState(v8::Local<v8::Context> context, scoped_refptr<DOMWrapperWorld> world) : isolate_(context->GetIsolate()),
diff --git a/third_party/blink/renderer/platform/bindings/script_state.h b/third_party/blink/renderer/platform/bindings/script_state.h index 4b93fbab..d31eaa6 100644 --- a/third_party/blink/renderer/platform/bindings/script_state.h +++ b/third_party/blink/renderer/platform/bindings/script_state.h
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/platform/bindings/scoped_persistent.h" #include "third_party/blink/renderer/platform/bindings/v8_cross_origin_setter_info.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/self_keep_alive.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "v8/include/v8.h" @@ -95,9 +96,6 @@ v8::Local<v8::Context> context_; }; - static ScriptState* Create(v8::Local<v8::Context>, - scoped_refptr<DOMWrapperWorld>); - ScriptState(v8::Local<v8::Context>, scoped_refptr<DOMWrapperWorld>); ~ScriptState(); @@ -209,10 +207,6 @@ class ScriptStateProtectingContext : public GarbageCollectedFinalized<ScriptStateProtectingContext> { public: - static ScriptStateProtectingContext* Create(ScriptState* script_state) { - return MakeGarbageCollected<ScriptStateProtectingContext>(script_state); - } - explicit ScriptStateProtectingContext(ScriptState* script_state) : script_state_(script_state) { if (script_state_) {
diff --git a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc index 600a10c..ac3eee8 100644 --- a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc +++ b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
@@ -41,6 +41,7 @@ #include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h" #include "third_party/blink/renderer/platform/bindings/v8_private_property.h" #include "third_party/blink/renderer/platform/bindings/v8_value_cache.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/unified_heap_controller.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/leak_annotations.h" @@ -290,7 +291,7 @@ if (!script_regexp_script_state_) { LEAK_SANITIZER_DISABLED_SCOPE; v8::Local<v8::Context> context(v8::Context::New(GetIsolate())); - script_regexp_script_state_ = ScriptState::Create( + script_regexp_script_state_ = MakeGarbageCollected<ScriptState>( context, DOMWrapperWorld::Create(GetIsolate(), DOMWrapperWorld::WorldType::kRegExp)); }
diff --git a/third_party/blink/renderer/platform/exported/mediastream/OWNERS b/third_party/blink/renderer/platform/exported/mediastream/OWNERS index c205d4f9..32889cc 100644 --- a/third_party/blink/renderer/platform/exported/mediastream/OWNERS +++ b/third_party/blink/renderer/platform/exported/mediastream/OWNERS
@@ -2,5 +2,5 @@ per-file media_stream_audio_processor*=aluebs@chromium.org -# TEAM: media-capture-and-streams@grotations.appspotmail.com +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>GetUserMedia
diff --git a/third_party/blink/renderer/platform/exported/web_rtc_offer_options.cc b/third_party/blink/renderer/platform/exported/web_rtc_offer_options.cc index 6340aef..366bb3d 100644 --- a/third_party/blink/renderer/platform/exported/web_rtc_offer_options.cc +++ b/third_party/blink/renderer/platform/exported/web_rtc_offer_options.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/public/platform/web_rtc_offer_options.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h" namespace blink { @@ -15,10 +16,11 @@ int32_t offer_to_receive_video, bool voice_activity_detection, bool ice_restart) - : private_(RTCOfferOptionsPlatform::Create(offer_to_receive_audio, - offer_to_receive_video, - voice_activity_detection, - ice_restart)) {} + : private_(MakeGarbageCollected<RTCOfferOptionsPlatform>( + offer_to_receive_audio, + offer_to_receive_video, + voice_activity_detection, + ice_restart)) {} void WebRTCOfferOptions::Assign(const WebRTCOfferOptions& other) { private_ = other.private_;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc index 1c27aba..ba79034a2 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -299,6 +299,7 @@ if (IsAccelerated() && !layer_) { layer_ = cc::TextureLayer::CreateForMailbox(this); layer_->SetIsDrawable(true); + layer_->SetHitTestable(true); layer_->SetContentsOpaque(ColorParams().GetOpacityMode() == kOpaque); layer_->SetBlendBackgroundColor(ColorParams().GetOpacityMode() != kOpaque); layer_->SetNearestNeighbor(resource_host_->FilterQuality() ==
diff --git a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc index 015bbac..1caf485d 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
@@ -200,6 +200,7 @@ layer_bounds.OffsetFromOrigin()); cc_picture_layer_->SetBounds(layer_bounds.size()); cc_picture_layer_->SetIsDrawable(true); + cc_picture_layer_->SetHitTestable(true); base::Optional<RasterUnderInvalidationCheckingParams> params; if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index 4717d68..99e3da7 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -924,6 +924,7 @@ layer_ = cc::TextureLayer::CreateForMailbox(this); layer_->SetIsDrawable(true); + layer_->SetHitTestable(true); layer_->SetContentsOpaque(!want_alpha_channel_); layer_->SetBlendBackgroundColor(want_alpha_channel_); // If premultiplied_alpha_false_texture_ exists, then premultiplied_alpha_
diff --git a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc index 1fc321b4..a0aa6435 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
@@ -28,6 +28,7 @@ : opacity_mode_(opacity_mode) { layer_ = cc::TextureLayer::CreateForMailbox(this); layer_->SetIsDrawable(true); + layer_->SetHitTestable(true); layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality); if (opacity_mode_ == kOpaque) { layer_->SetContentsOpaque(true);
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc index 7eb93baa..a0959355 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -75,7 +75,7 @@ draws_content_(false), paints_hit_test_(false), contents_visible_(true), - hit_testable_without_draws_content_(false), + hit_testable_(false), needs_check_raster_invalidation_(false), has_scroll_parent_(false), has_clip_parent_(false), @@ -94,6 +94,7 @@ #endif layer_ = cc::PictureLayer::Create(this); CcLayer()->SetIsDrawable(draws_content_ && contents_visible_); + CcLayer()->SetHitTestable(hit_testable_); CcLayer()->SetLayerClient(weak_ptr_factory_.GetWeakPtr()); UpdateTrackingRasterInvalidations(); @@ -544,6 +545,7 @@ // contents_layer, for the correctness of early exit conditions in // SetDrawsContent() and SetContentsVisible(). contents_layer_->SetIsDrawable(contents_visible_); + contents_layer_->SetHitTestable(contents_visible_); // Insert the content layer first. Video elements require this, because they // have shadow content that must display in front of the video. @@ -832,11 +834,11 @@ CcLayer()->SetIsRootForIsolatedGroup(isolated); } -void GraphicsLayer::SetHitTestableWithoutDrawsContent(bool should_hit_test) { - if (hit_testable_without_draws_content_ == should_hit_test) +void GraphicsLayer::SetHitTestable(bool should_hit_test) { + if (hit_testable_ == should_hit_test) return; - hit_testable_without_draws_content_ = should_hit_test; - CcLayer()->SetHitTestableWithoutDrawsContent(should_hit_test); + hit_testable_ = should_hit_test; + CcLayer()->SetHitTestable(should_hit_test); } void GraphicsLayer::SetContentsNeedsDisplay() {
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h index a4b051e3..99b75a9 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.h +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -194,10 +194,8 @@ bool IsRootForIsolatedGroup() const; void SetIsRootForIsolatedGroup(bool); - void SetHitTestableWithoutDrawsContent(bool); - bool GetHitTestableWithoutDrawsContent() const { - return hit_testable_without_draws_content_; - } + void SetHitTestable(bool); + bool GetHitTestable() const { return hit_testable_; } void SetFilters(CompositorFilterOperations); void SetBackdropFilters(CompositorFilterOperations, const gfx::RRectF&); @@ -376,7 +374,7 @@ bool draws_content_ : 1; bool paints_hit_test_ : 1; bool contents_visible_ : 1; - bool hit_testable_without_draws_content_ : 1; + bool hit_testable_ : 1; bool needs_check_raster_invalidation_ : 1; bool has_scroll_parent_ : 1;
diff --git a/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc index 7955701..90975021 100644 --- a/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
@@ -155,6 +155,7 @@ surface_layer_->SetStretchContentToFillBounds(true); surface_layer_->SetIsDrawable(true); + surface_layer_->SetHitTestable(true); surface_layer_->SetMayContainVideo(true); if (observer_) {
diff --git a/third_party/blink/renderer/platform/heap/heap_thread_test.cc b/third_party/blink/renderer/platform/heap/heap_thread_test.cc index 9d6facd..7eab071 100644 --- a/third_party/blink/renderer/platform/heap/heap_thread_test.cc +++ b/third_party/blink/renderer/platform/heap/heap_thread_test.cc
@@ -7,6 +7,7 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" #include "third_party/blink/renderer/platform/heap/thread_state.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" @@ -206,10 +207,6 @@ class DestructorLockingObject : public GarbageCollectedFinalized<DestructorLockingObject> { public: - static DestructorLockingObject* Create() { - return MakeGarbageCollected<DestructorLockingObject>(); - } - DestructorLockingObject() = default; virtual ~DestructorLockingObject() { ++destructor_calls_; } @@ -248,7 +245,7 @@ void WorkerThreadMain() override { // Step 2: Create an object and store the pointer. - object_ = DestructorLockingObject::Create(); + object_ = MakeGarbageCollected<DestructorLockingObject>(); SwitchToMainThread(); // Step 4: Run a GC.
diff --git a/third_party/blink/renderer/platform/lifecycle_context_test.cc b/third_party/blink/renderer/platform/lifecycle_context_test.cc index 373e4e5..aeebb725 100644 --- a/third_party/blink/renderer/platform/lifecycle_context_test.cc +++ b/third_party/blink/renderer/platform/lifecycle_context_test.cc
@@ -26,6 +26,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/lifecycle_notifier.h" #include "third_party/blink/renderer/platform/lifecycle_observer.h" @@ -41,8 +42,6 @@ USING_GARBAGE_COLLECTED_MIXIN(DummyContext); public: - static DummyContext* Create() { return MakeGarbageCollected<DummyContext>(); } - void Trace(blink::Visitor* visitor) override { LifecycleNotifier<DummyContext, TestingObserver>::Trace(visitor); } @@ -57,10 +56,6 @@ USING_GARBAGE_COLLECTED_MIXIN(TestingObserver); public: - static TestingObserver* Create(DummyContext* context) { - return MakeGarbageCollected<TestingObserver>(context); - } - explicit TestingObserver(DummyContext* context) : LifecycleObserver(context), context_destroyed_called_(false) {} @@ -96,8 +91,9 @@ }; TEST(LifecycleContextTest, ShouldObserveContextDestroyed) { - DummyContext* context = DummyContext::Create(); - Persistent<TestingObserver> observer = TestingObserver::Create(context); + auto* context = MakeGarbageCollected<DummyContext>(); + Persistent<TestingObserver> observer = + MakeGarbageCollected<TestingObserver>(context); EXPECT_EQ(observer->LifecycleContext(), context); EXPECT_FALSE(observer->ContextDestroyedCalled()); @@ -109,8 +105,9 @@ } TEST(LifecycleContextTest, ShouldNotObserveContextDestroyedIfUnobserve) { - DummyContext* context = DummyContext::Create(); - Persistent<TestingObserver> observer = TestingObserver::Create(context); + auto* context = MakeGarbageCollected<DummyContext>(); + Persistent<TestingObserver> observer = + MakeGarbageCollected<TestingObserver>(context); observer->Unobserve(); context->NotifyContextDestroyed(); context = nullptr; @@ -120,9 +117,10 @@ } TEST(LifecycleContextTest, ObserverRemovedDuringNotifyDestroyed) { - DummyContext* context = DummyContext::Create(); - Persistent<TestingObserver> observer = TestingObserver::Create(context); - TestingObserver* inner_observer = TestingObserver::Create(context); + auto* context = MakeGarbageCollected<DummyContext>(); + Persistent<TestingObserver> observer = + MakeGarbageCollected<TestingObserver>(context); + auto* inner_observer = MakeGarbageCollected<TestingObserver>(context); // Attach the observer to the other. When 'observer' is notified // of destruction, it will remove & destroy 'innerObserver'. observer->SetObserverToRemoveAndDestroy(inner_observer); @@ -147,10 +145,11 @@ ThreadState* thread_state = ThreadState::Current(); thread_state->IncrementalMarkingStart(BlinkGC::GCReason::kForcedGCForTesting); - DummyContext* context = DummyContext::Create(); + auto* context = MakeGarbageCollected<DummyContext>(); // This should not cause a CFI check failure. - Persistent<TestingObserver> observer = TestingObserver::Create(context); + Persistent<TestingObserver> observer = + MakeGarbageCollected<TestingObserver>(context); EXPECT_FALSE(observer->ContextDestroyedCalled()); context->NotifyContextDestroyed(); @@ -166,8 +165,9 @@ } TEST(LifecycleContextTest, ForEachObserver) { - Persistent<DummyContext> context = DummyContext::Create(); - Persistent<TestingObserver> observer = TestingObserver::Create(context); + Persistent<DummyContext> context = MakeGarbageCollected<DummyContext>(); + Persistent<TestingObserver> observer = + MakeGarbageCollected<TestingObserver>(context); HeapVector<Member<TestingObserver>> seen_observers; context->ForEachObserver(
diff --git a/third_party/blink/renderer/platform/mhtml/archive_resource.cc b/third_party/blink/renderer/platform/mhtml/archive_resource.cc index 2178532..71a9480 100644 --- a/third_party/blink/renderer/platform/mhtml/archive_resource.cc +++ b/third_party/blink/renderer/platform/mhtml/archive_resource.cc
@@ -45,13 +45,4 @@ ArchiveResource::~ArchiveResource() = default; -ArchiveResource* ArchiveResource::Create(scoped_refptr<SharedBuffer> data, - const KURL& url, - const String& content_id, - const AtomicString& mime_type, - const AtomicString& text_encoding) { - return MakeGarbageCollected<ArchiveResource>(std::move(data), url, content_id, - mime_type, text_encoding); -} - } // namespace blink
diff --git a/third_party/blink/renderer/platform/mhtml/archive_resource.h b/third_party/blink/renderer/platform/mhtml/archive_resource.h index 7dcc5be..724bbba 100644 --- a/third_party/blink/renderer/platform/mhtml/archive_resource.h +++ b/third_party/blink/renderer/platform/mhtml/archive_resource.h
@@ -40,12 +40,6 @@ class PLATFORM_EXPORT ArchiveResource final : public GarbageCollectedFinalized<ArchiveResource> { public: - static ArchiveResource* Create(scoped_refptr<SharedBuffer>, - const KURL&, - const String& content_id, - const AtomicString& mime_type, - const AtomicString& text_encoding); - ArchiveResource(scoped_refptr<SharedBuffer>, const KURL&, const String& content_id,
diff --git a/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc b/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc index 5a411aa..b201e403 100644 --- a/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc +++ b/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
@@ -31,6 +31,8 @@ #include "third_party/blink/renderer/platform/mhtml/mhtml_parser.h" #include <stddef.h> + +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/mhtml/archive_resource.h" #include "third_party/blink/renderer/platform/network/http_parsers.h" #include "third_party/blink/renderer/platform/network/parsed_content_type.h" @@ -91,8 +93,6 @@ // files. class MIMEHeader : public GarbageCollectedFinalized<MIMEHeader> { public: - static MIMEHeader* Create() { return MakeGarbageCollected<MIMEHeader>(); } - MIMEHeader(); enum class Encoding { @@ -179,7 +179,7 @@ } MIMEHeader* MIMEHeader::ParseHeader(SharedBufferChunkReader* buffer) { - MIMEHeader* mime_header = MIMEHeader::Create(); + auto* mime_header = MakeGarbageCollected<MIMEHeader>(); KeyValueMap key_value_pairs = RetrieveKeyValuePairs(buffer); KeyValueMap::iterator mime_parameters_iterator = key_value_pairs.find("content-type"); @@ -452,10 +452,10 @@ // http://tools.ietf.org/html/rfc2557#section-5 // IE and Firefox (UNMht) seem to generate only absolute URLs. KURL location = KURL(NullURL(), mime_header.ContentLocation()); - return ArchiveResource::Create(content_buffer, location, - mime_header.ContentID(), - AtomicString(mime_header.ContentType()), - AtomicString(mime_header.Charset())); + return MakeGarbageCollected<ArchiveResource>( + content_buffer, location, mime_header.ContentID(), + AtomicString(mime_header.ContentType()), + AtomicString(mime_header.Charset())); } // static
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h b/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h index 7de4760..6f841c8a 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h +++ b/third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h
@@ -6,17 +6,13 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_RTC_ANSWER_OPTIONS_PLATFORM_H_ #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { class RTCAnswerOptionsPlatform final : public GarbageCollected<RTCAnswerOptionsPlatform> { public: - static RTCAnswerOptionsPlatform* Create(bool voice_activity_detection) { - return MakeGarbageCollected<RTCAnswerOptionsPlatform>( - voice_activity_detection); - } - explicit RTCAnswerOptionsPlatform(bool voice_activity_detection) : voice_activity_detection_(voice_activity_detection) {}
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h b/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h index 0ee6920..a986b96 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h +++ b/third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h
@@ -12,15 +12,6 @@ class RTCOfferOptionsPlatform final : public GarbageCollected<RTCOfferOptionsPlatform> { public: - static RTCOfferOptionsPlatform* Create(int32_t offer_to_receive_video, - int32_t offer_to_receive_audio, - bool voice_activity_detection, - bool ice_restart) { - return MakeGarbageCollected<RTCOfferOptionsPlatform>( - offer_to_receive_video, offer_to_receive_audio, - voice_activity_detection, ice_restart); - } - RTCOfferOptionsPlatform(int32_t offer_to_receive_video, int32_t offer_to_receive_audio, bool voice_activity_detection,
diff --git a/third_party/blink/renderer/platform/prerender.h b/third_party/blink/renderer/platform/prerender.h index 5f0f7fdd..f5cf53f 100644 --- a/third_party/blink/renderer/platform/prerender.h +++ b/third_party/blink/renderer/platform/prerender.h
@@ -35,6 +35,7 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/referrer.h" @@ -55,13 +56,6 @@ virtual ~ExtraData() = default; }; - static Prerender* Create(PrerenderClient* client, - const KURL& url, - unsigned rel_types, - const Referrer& referrer) { - return MakeGarbageCollected<Prerender>(client, url, rel_types, referrer); - } - Prerender(PrerenderClient*, const KURL&, unsigned rel_types, const Referrer&); ~Prerender(); void Trace(blink::Visitor*);
diff --git a/third_party/blink/renderer/platform/speech/platform_speech_synthesis_utterance.cc b/third_party/blink/renderer/platform/speech/platform_speech_synthesis_utterance.cc index defd1e33..7296694 100644 --- a/third_party/blink/renderer/platform/speech/platform_speech_synthesis_utterance.cc +++ b/third_party/blink/renderer/platform/speech/platform_speech_synthesis_utterance.cc
@@ -27,11 +27,6 @@ namespace blink { -PlatformSpeechSynthesisUtterance* PlatformSpeechSynthesisUtterance::Create( - PlatformSpeechSynthesisUtteranceClient* client) { - return MakeGarbageCollected<PlatformSpeechSynthesisUtterance>(client); -} - PlatformSpeechSynthesisUtterance::PlatformSpeechSynthesisUtterance( PlatformSpeechSynthesisUtteranceClient* client) : client_(client) {}
diff --git a/third_party/blink/renderer/platform/speech/platform_speech_synthesis_utterance.h b/third_party/blink/renderer/platform/speech/platform_speech_synthesis_utterance.h index 69ec13bf..d4d5343 100644 --- a/third_party/blink/renderer/platform/speech/platform_speech_synthesis_utterance.h +++ b/third_party/blink/renderer/platform/speech/platform_speech_synthesis_utterance.h
@@ -45,9 +45,6 @@ class PLATFORM_EXPORT PlatformSpeechSynthesisUtterance final : public GarbageCollectedFinalized<PlatformSpeechSynthesisUtterance> { public: - static PlatformSpeechSynthesisUtterance* Create( - PlatformSpeechSynthesisUtteranceClient*); - explicit PlatformSpeechSynthesisUtterance( PlatformSpeechSynthesisUtteranceClient*);
diff --git a/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc b/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc index e646556..f21a436f 100644 --- a/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc +++ b/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc
@@ -22,6 +22,7 @@ page_scale_layer_ = std::make_unique<FakeGraphicsLayer>(client_); graphics_layer_ = std::make_unique<FakeGraphicsLayer>(client_); graphics_layer_->SetDrawsContent(true); + graphics_layer_->SetHitTestable(true); clip_layer_->AddChild(scroll_elasticity_layer_.get()); scroll_elasticity_layer_->AddChild(page_scale_layer_.get()); page_scale_layer_->AddChild(graphics_layer_.get());
diff --git a/third_party/blink/renderer/platform/wtf/text/README.md b/third_party/blink/renderer/platform/wtf/text/README.md new file mode 100644 index 0000000..ce8b1273 --- /dev/null +++ b/third_party/blink/renderer/platform/wtf/text/README.md
@@ -0,0 +1,319 @@ +# Strings in Blink + +_Everything you always wanted to know but were afraid to ask_ + +This document covers the `String` type in Blink, often written with an +explicit namespace as `WTF::String` to disambiguate from string +concepts or other types. It also briefly covers associated classes +used for constructing strings (`StringBuilder`, `StringBuffer`), the +internal `StringImpl` class, and the special `AtomicString` variant. +It does not cover other text-related types or utilities (e.g. +encodings, views, line endings, etc). + +## Overview + +A `WTF::String` represents a sequence of zero or more Unicode code +points. A `String` can also represent one of two zero-length strings: +the empty string and the null string. These correspond to "" and +`null` in JavaScript, respectively. Both the empty and the null string +return true from `String::IsEmpty()` but only the null string returns +true from `String::IsNull()`. + + +Unlike `std::string`, Blink’s `String` object is a pointer to a +reference counted character buffer. This design makes it easier to +share the underlying character buffer between different consumers +because multiple consumers can reference the same underlying buffer. +The disadvantage of this design is that we need to be careful when +mixing Strings with multithreading because the character buffer’s +reference counting is not thread safe. + + +## Storage + +### Encoding + +A `String` can represent Unicode code points with either `LChar`s or +`UChar`s, which use 8 bits and 16 bits per code unit respectively. +Each `LChar` represents a single code unit of ISO-8859-1, more +commonly called Latin-1 (hence the L in `LChar`). Unlike UTF-8, this +encoding cannot represent every Unicode code point. However, also +unlike UTF-8, every representable Unicode code point can represented +with a single code unit and the code unit is simply the 8 least +significant bits of the code point. This property makes Latin-1 an +attractive encoding because we can decode a Latin-1 code unit to a +Unicode code point simply by zero-extending the `LChar` value. + + +Each `UChar` represents a single UTF-16 code unit (hence the U in +`UChar`). Unfortunately, Strings do not always contain valid UTF-16 +sequences. Strings that have round-tripped through JavaScript can +contain invalid UTF-16 sequences because JavaScript isn’t required to +pair surrogates in its strings. Most code that works with Strings can +ignore this issue because they operate code-unit-by-code-unit, but +subsystems need to operate on code points outside the Basic +Multilingual Plane need to be prepared to handle unpaired surrogates. + + +In addition to `LChar` and `UChar`, Strings also use the type +`UChar32`, which is a UTF-32 code unit. `UChar32` is particularly easy +to work with because every UTF-32 code unit has the same numerical +value as its corresponding Unicode code point. Practically speaking, +that means you can treat `UChar32` values as if they were Unicode code +points. + +### Layout + +The `String` object itself is simply a pointer to a `StringImpl` +object, which contains the actual character buffer. `String` uses a +`scoped_refptr<>` to automatically `AddRef()` and `Release()` the +`StringImpl` object on construction and destruction. The `StringImpl` +pointer can be zero, in which case the `String` represents the null +string. Typically, `String` objects are allocated on the stack or as +members variables. `StringImpl` objects are always allocated in the +heap. + + +`StringImpl` objects are (logically) immutable, but a given `String` +object can refer to different `StringImpl` objects over time. For +example, `String::Replace()` works by creating a new `StringImpl` +object with the replaced characters rather than by mutating the +original `StringImpl` object. + + +Rather than using a fixed `sizeof(StringImpl)` allocation size, +`StringImpl` object are allocated a variable amount of memory and +store their character data in the same memory allocation as the +`StringImpl` object itself. In a sense, the `StringImpl` object is a +header for the actual array of characters, be they `LChar`s or +`UChar`s. + +#### Reference count + +The `StringImpl` header contains three 32 bit fields. The first is a +reference count, which is incremented and decremented by the +`AddRef()` and `Release()` functions. When the reference count reaches +zero the `StringImpl` object is deallocated, unless the `StringImpl` +is marked static (in which case the `StringImpl` object is never +deallocated). + + +#### Length + +The next 32 bits represent the (potentially zero) length of the +string. The length field always represents the number of code units, +regardless of whether the `StringImpl` uses `LChar`s or `UChar`s. We +use a 32 bit length on both 32-bit and 64-bit systems. To avoid +creating a string whose length is too long to represent in 32 bits, we +RELEASE_ASSERT that the length doesn’t overflow, which means we’ll +crash in a controlled way if you try to create a string that’s +absurdly long. + +#### Hash and flags + +The final 32 bits are used to cache the string’s hash value and to +store a number of Boolean flags. We use 24 bits for the hash and +reserve 8 bits for flags. As of April 2019, the flags represent +whether the `StringImpl`: + +* ...contains only ASCII (7-bit), or whether this is unknown (2 + flags). +* ...is a member of the `AtomicString` table (discussed below). +* ...contains `LChar`s or `UChar`s. +* ...is Static and will never be deallocated (discussed below). + +We haven’t evaluated the performance trade-offs of caching the hash +value in the `StringImpl` object recently. It’s possible that the +cache hit rate is sufficiently low that we should remove the final 32 +bit field and move the two flags into the length, reducing the length +field to 30 bits. Small changes to `StringImpl` can have large effects +on the overall system, which means we should measure the performance +impact of this sort of change carefully. + + +## Construction + +There are multiple interfaces for constructing strings, each of which +is useful in different situations. + +### `String` constructor +The most straightforward interface for constructing strings is the +`String` constructor. You should use this interface when the source +data for the `String` is an array of `LChar`s or `UChar`s. The +`String` constructor allocates a new `StringImpl` object and copies +the source characters into the `StringImpl` object as efficiently as +possible. + + +The `String` constructor that takes a `UChar` array always creates a +`UChar`-based `StringImpl` object even if all the source characters +would actually fit in `LChar`s. If your source data is an array of +`UChar`s but you have reason to believe that the string will usually +be representable in Latin-1, you should consider using +`StringImpl::Create8BitIfPossible()`, which creates an `LChar`- or +`UChar`-based `StringImpl` object as appropriate at the cost of +checking whether all the source characters can be represented in +Latin-1. + + +### `operator+` + +The + operator on Strings is the most efficient way to combine smaller +strings into larger strings. Using templates, `operator+` builds a +tree of temporary objects that mirrors the tree of `operator+` +invocations. When the temporary objects are (implicitly) collapsed to +a `String`, we first compute the length of the final string and then +allocate a single `StringImpl` object of exactly the correct size. +After allocating the object, we copy all the characters into the +string. This approach means we copy the characters exactly once into +the correctly sized buffer, which is maximally efficient. + +### `StringBuilder` + +If you’re unable to use `operator+` to build your string, for example +because you need to use a loop, you should use `StringBuilder`. Like +similar interfaces in other libraries, `StringBuilder` lets you build +a `String` by incrementally appending content. `StringBuilder` tries +to use 8-bit `StringImpl` objects whenever possible but will upconvert +its internal buffer to 16 bits if necessarily. + + +`StringBuilder::Append()` grows its buffer exponentially, which means +`StringBuilder` avoids the pathologically bad O(N^2) performance that +repeated appends/concatenation can cause. One way to further optimize +`String` construction when using `StringBuilder` is to call +`StringBuilder::ReserveCapacity()` with (an estimate of) the final +length of the `String` (in code units) before appending characters. If +you give `StringBuilder` an accurate estimate of the length of the +string, `StringBuilder` can pre-allocate the appropriate amount of +memory and avoid having to reallocate its buffer and copy your string. + + +### `StringBuffer` + +Finally, there are some cases where neither the `String` constructor +or `StringBuilder` work well. For example, sometimes rather than +having a source array of `UChar`s from which to construct a String, +you might have a function that will write the `UChar`s into a buffer +you provide. `StringBuffer` can help you in these cases by allocating +a character buffer and letting the function write into it. + + +Conceptually, a `StringBuffer` represents the underlying character +buffer from a String. However, unlike `StringImpl` objects, +`StringBuffer`s are mutable. `StringBuffer`s work well when you know +ahead of time exactly how large a buffer you need and whether you want +to use `LChar`s or `UChar`s. If you’re uncertain about the length of +the `String` you’re constructing, you probably should use +`StringBuilder`. + +## Atomic Strings + +Some `StringImpl` objects are marked as _Atomic_, which means they’re +stored in a thread-local `HashSet` called the `AtomicString` table. +Rather than interacting directly with these anointed `StringImpl` +objects, we usually hold pointers to them via `AtomicString` objects +(rather than `String` objects). Using `AtomicString` rather than +`String` to point to an Atomic `StringImpl` object lets the compiler +generate (and skip!) the appropriate hash lookups in the +`AtomicString` table as well as use faster comparison operations with +other `AtomicString`s. + +### Construction + +Typically, constructing an `AtomicString` from a `String` object will +involve a hash lookup in the `AtomicString` table for the current +thread. If the string represented by the `String` object is not +present in the `AtomicString` table, the `StringImpl` object from that +`String` will be marked Atomic and added to the table. If the +represented string is already present in the `AtomicString` table, the +already-Atomic `StringImpl` object from the table will be used to +construct the `AtomicString` rather than the `StringImpl` from the +original String. + + +If you wish to construct an `AtomicString` from an array of `LChar`s +or `UChar`s, you should use the `AtomicString` constructor directly +rather than first constructing a `String` object. If the string is +already present in the `AtomicString` table, the `AtomicString` +constructor will grab a reference to the existing Atomic `StringImpl` +object rather than first allocating and populating a `StringImpl` +object as the `String` constructor would. + +### Fast comparisons + +If two `StringImpl` objects are atomic, you can compare them for +equality by comparing their addresses rather than by comparing them +character-by-character. The reason this works is that we maintain the +invariant that no two Atomic `StringImpl` objects on a given thread +represent the same string. Therefore, the two `StringImpl` objects +represent the same string if, and only if, they are actually the same +`StringImpl` object. We’ve overloaded `operator==` on `AtomicString` +to let the compiler generate these optimized comparisons +automatically. + +### Deduplication + +Because there are no duplicate Atomic `StringImpl` objects on a given +thread, `AtomicString`s are useful for coalescing duplicate strings +into a single `StringImpl` object, saving memory. Unfortunately, +`AtomicString`s are thread-specific and cannot be used to coalesce +duplicate strings across threads. + +## Threading + +### Isolated copies + +String objects that you construct yourself are not thread-safe. The +underlying `StringImpl` object can be shared only by `String` objects +on the same thread because the `StringImpl`’s reference count isn’t +incremented or decremented atomically. + + +In some limited cases, you can safely send a `String` from one thread +to another. In order for that to be safe, you need to make sure that +the underlying `StringImpl` object has exactly one reference---the one +you’re sending to another thread. If there is only one outstanding +reference to the `StringImpl`, then there won’t be any reference count +data races. The easiest way to get a `StringImpl` object with only one +reference is to call `String::IsolatedCopy()`. You can check that a +given `String` is safe to send to another thread by calling +`String::IsSafeToSendToAnotherThread()`, typically in a `DCHECK`. + + +If you look at the implementation of `IsSafeToSendToAnotherThread()`, +you’ll notice that it always returns false if the `StringImpl` is +Atomic, regardless of the reference count. That’s because Atomic +`StringImpl` objects are not safe to send to another thread because +they’re associated with an `AtomicString` table local to the current +thread. If you do send an `AtomicString` to another thread and the +`StringImpl` object is destructed on that thread, it will try to +remove itself from that thread’s `AtomicString` table rather than from +the original thread’s `AtomicString` table. + +### Static Strings + +At startup, we create a number of _Static_ `StringImpl` objects that +are safe to use from any thread. These `StringImpl` objects maintain +the invariant that the least significant bit of their reference count +is always one, which means their reference count never reaches zero +and they are never deallocated. In addition to preventing their +deallocation, we also pre-populate the hash value to ensure that +Static `StringImpl` objects are otherwise immutable. + + +We first introduced these Static strings for the threaded HTML parser, +but we are gradually using them more widely in the codebase. There are +still some delicate interactions between Static strings and the +`AtomicString` table, but hopefully we’ll smooth over these rough +edges over time. + +# Conclusion + +This document contains a brief introduction to Blink’s `String` class. +There are many details that are not included, but hopefully this +document has given you a good high-level understanding of Strings. +More details are available in the source, either in code or in +comments. Happy hacking! + +_Originally authored by Adam Barth (abarth), 5 August 2013._
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.h b/third_party/blink/renderer/platform/wtf/text/wtf_string.h index c437f11..efefc6c 100644 --- a/third_party/blink/renderer/platform/wtf/text/wtf_string.h +++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
@@ -57,8 +57,7 @@ ? op##IgnoringASCIICase args \ : op##IgnoringCase args) -// You can find documentation about this class in this doc: -// https://docs.google.com/document/d/1kOCUlJdh2WJMJGDf-WoEQhmnjKLaOYRbiHz5TiGJl14/edit?usp=sharing +// You can find documentation about this class in README.md in this directory. class WTF_EXPORT String { USING_FAST_MALLOC(String);
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index d8ee1f1..b9763d9 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5114,8 +5114,10 @@ # Prefetching Signed Exchange DevTools tests are flaky. crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch-fail.js [ Pass Failure ] crbug.com/851363 virtual/nobinary-for-devtools/http/tests/devtools/sxg/sxg-prefetch-fail.js [ Pass Failure ] +crbug.com/851363 virtual/sxg-with-network-service/http/tests/devtools/sxg/sxg-prefetch-fail.js [ Pass Failure ] crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch.js [ Pass Failure ] crbug.com/851363 virtual/nobinary-for-devtools/http/tests/devtools/sxg/sxg-prefetch.js [ Pass Failure ] +crbug.com/851363 virtual/sxg-with-network-service/http/tests/devtools/sxg/sxg-prefetch.js [ Pass Failure ] # Sheriff 2018-03-22 crbug.com/824775 [ Win ] media/controls/video-controls-with-cast-rendering.html [ Pass Failure ] @@ -6075,7 +6077,7 @@ crbug.com/937811 [ Win Release ] virtual/nobinary-for-devtools/http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-2.js [ Pass Failure ] crbug.com/937811 [ Win Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ] crbug.com/937811 [ Win Release ] virtual/nobinary-for-devtools/http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ] -crbug.com/935689 [ Mac Linux Debug ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/symbols-function.html [ Failure Pass ] +crbug.com/935689 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/symbols-function.html [ Failure Pass ] crbug.com/937858 [ Debug ] external/wpt/ambient-light/AmbientLightSensor.https.html [ Pass Failure ] crbug.com/937902 [ Linux Debug ] virtual/disable-blink-gen-property-trees/compositing/overflow/overflow-scroll-with-local-background.html [ Pass Failure ] crbug.com/937991 [ Win7 Release ] http/tests/devtools/cache-storage/cache-data.js [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/accessibility/line-for-index-endless-loop.html b/third_party/blink/web_tests/accessibility/line-for-index-endless-loop.html deleted file mode 100644 index e10d9ed..0000000 --- a/third_party/blink/web_tests/accessibility/line-for-index-endless-loop.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE HTML> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="../resources/run-after-layout-and-paint.js"></script> - -<div class="container" id="contentEditable" contentEditable> - <span style="display: inline-block;"> - <span style="position: absolute;"> - <span>x</span> - </span> - <span>2</span> - <span style="display: inline-block;"></span> - </span> - <span>+</span> -</div> - -<script> -test_after_layout_and_paint(function(t) { - var axContentEditable = accessibilityController.accessibleElementById("contentEditable"); - assert_equals(axContentEditable.lineForIndex(0), 0); -}, "No endless loop when getting line for index in contentEditable"); -</script>
diff --git a/third_party/blink/web_tests/accessibility/textarea-line-for-index-expected.txt b/third_party/blink/web_tests/accessibility/textarea-line-for-index-expected.txt deleted file mode 100644 index a151a7a0..0000000 --- a/third_party/blink/web_tests/accessibility/textarea-line-for-index-expected.txt +++ /dev/null
@@ -1,30 +0,0 @@ -This tests that the line number of a character offset is computed correctly for textarea elements. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS axArea1.lineForIndex(index) is 0 -PASS axArea1.lineForIndex(index) is 0 -PASS axArea1.lineForIndex(index) is 0 -PASS axArea1.lineForIndex(index) is 0 -PASS axArea1.lineForIndex(index) is 0 -PASS axArea1.lineForIndex(index) is 0 -PASS axArea1.lineForIndex(index) is 0 -PASS axArea1.lineForIndex(index) is 1 -PASS axArea1.lineForIndex(index) is 1 -PASS axArea1.lineForIndex(index) is 1 -PASS axArea1.lineForIndex(index) is 1 -PASS axArea1.lineForIndex(index) is 1 -PASS axArea1.lineForIndex(index) is 1 -PASS axArea1.lineForIndex(index) is 1 -PASS axArea1.lineForIndex(index) is 2 -PASS axArea1.lineForIndex(index) is 2 -PASS axArea1.lineForIndex(index) is 2 -PASS axArea1.lineForIndex(index) is 2 -PASS axArea1.lineForIndex(index) is 2 -PASS axArea1.lineForIndex(index) is 2 -PASS axArea1.lineForIndex(index) is 2 -PASS axArea1.lineForIndex(area1.textLength) is 2 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/accessibility/textarea-line-for-index.html b/third_party/blink/web_tests/accessibility/textarea-line-for-index.html deleted file mode 100644 index d408318..0000000 --- a/third_party/blink/web_tests/accessibility/textarea-line-for-index.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="../resources/js-test.js"></script> - </head> - <body> - - <textarea name="area1" id="area1" rows="5" cols="40"> -line 1 -line 2 -line 3</textarea> - - <script> - description("This tests that the line number of a character offset is computed correctly for textarea elements."); - - if (window.accessibilityController) { - - var area1 = document.getElementById("area1"); - area1.focus(); - var axArea1 = accessibilityController.focusedElement; - - for (var line = 0; line < 3; ++line) { - for (var character = 0; character < 7; ++character) { - var index = line * 7 + character; - shouldBeEqualToNumber("axArea1.lineForIndex(index)", line); - } - } - - // Placing the caret after the last character should not change the line. - shouldBeEqualToNumber("axArea1.lineForIndex(area1.textLength)", 2); - - } - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/geolocation-API/OWNERS b/third_party/blink/web_tests/external/wpt/geolocation-API/OWNERS index 6d678d8..61e5876 100644 --- a/third_party/blink/web_tests/external/wpt/geolocation-API/OWNERS +++ b/third_party/blink/web_tests/external/wpt/geolocation-API/OWNERS
@@ -1,3 +1,5 @@ # TEAM: device-dev@chromium.org -# COMPONENT: Blink>Location +# COMPONENT: Blink>Geolocation + +# Original (legacy) owner. mcasas@chromium.org
diff --git a/third_party/blink/web_tests/external/wpt/html-media-capture/OWNERS b/third_party/blink/web_tests/external/wpt/html-media-capture/OWNERS index 5db6e74..d96b9bf 100644 --- a/third_party/blink/web_tests/external/wpt/html-media-capture/OWNERS +++ b/third_party/blink/web_tests/external/wpt/html-media-capture/OWNERS
@@ -1,4 +1,4 @@ # TEAM: media-dev@chromium.org # COMPONENT: Blink>ImageCapture + rijubrata.bhaumik@intel.com -mcasas@chromium.org
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-record/OWNERS b/third_party/blink/web_tests/external/wpt/mediacapture-record/OWNERS index 681555b..9c7779b 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-record/OWNERS +++ b/third_party/blink/web_tests/external/wpt/mediacapture-record/OWNERS
@@ -1,3 +1,5 @@ -# TEAM: media-dev@chromium.org +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>MediaRecording + +# Original (legacy) owner. mcasas@chromium.org
diff --git a/third_party/libwebm/OWNERS b/third_party/libwebm/OWNERS index 43542744..ca0fd18a 100644 --- a/third_party/libwebm/OWNERS +++ b/third_party/libwebm/OWNERS
@@ -1,9 +1,12 @@ # The following OWNERS refer to libwebm Chromium integration. emircan@chromium.org -mcasas@chromium.org niklase@chromium.org # The following OWNER refer to libwebm content. tomfinegan@chromium.org +# Original (legacy) owner. +mcasas@chromium.org + +# TEAM: webrtc-dev@chromium.org # COMPONENT: Blink>MediaRecording
diff --git a/third_party/webrtc_overrides/BUILD.gn b/third_party/webrtc_overrides/BUILD.gn index c0de0b91..61048ce8 100644 --- a/third_party/webrtc_overrides/BUILD.gn +++ b/third_party/webrtc_overrides/BUILD.gn
@@ -94,7 +94,6 @@ ":webrtc", "//third_party/webrtc/media:rtc_media", "//third_party/webrtc/media:rtc_media_base", - "//third_party/webrtc/modules/video_capture", "//third_party/webrtc/pc:libjingle_peerconnection", "//third_party/webrtc/pc:rtc_pc", "//third_party/webrtc/system_wrappers",
diff --git a/tools/json_schema_compiler/feature_compiler.py b/tools/json_schema_compiler/feature_compiler.py index 34ccc31f..d08b7a6 100644 --- a/tools/json_schema_compiler/feature_compiler.py +++ b/tools/json_schema_compiler/feature_compiler.py
@@ -64,11 +64,10 @@ } // namespace extensions """ -# Returns true if the list 'l' does not contain any strings that look like -# extension ids. -def ListDoesNotContainPlainExtensionIds(l): - # For now, let's just say anything 32 characters in length is an id. - return len(filter(lambda s: len(s) == 32, l)) == 0 +# Returns true if the list 'l' only contains strings that are a hex-encoded SHA1 +# hashes. +def ListContainsOnlySha1Hashes(l): + return len(filter(lambda s: not re.match("^[A-F0-9]{40}$", s), l)) == 0 # A "grammar" for what is and isn't allowed in the features.json files. This # grammar has to list all possible keys and the requirements for each. The @@ -96,6 +95,8 @@ # assign the list of Feature::BLESSED_EXTENSION_CONTEXT, # Feature::BLESSED_WEB_PAGE_CONTEXT et al for contexts. If not # specified, defaults to false. +# 'allow_empty': Only applicable for lists. Whether an empty list is a valid +# value. If omitted, empty lists are prohibited. # 'validators': A list of (function, str) pairs with a function to run on the # value for a feature. Validators allow for more flexible or # one-off style validation than just what's in the grammar (such @@ -120,7 +121,7 @@ list: { 'subtype': unicode, 'validators': [ - (ListDoesNotContainPlainExtensionIds, + (ListContainsOnlySha1Hashes, 'list should only have hex-encoded SHA1 hashes of extension ids') ] } @@ -161,7 +162,12 @@ bool: {'values': [True]} }, 'dependencies': { - list: {'subtype': unicode} + list: { + # We allow an empty list of dependencies for child features that want + # to override their parents' dependency set. + 'allow_empty': True, + 'subtype': unicode + } }, 'extension_types': { list: { @@ -227,7 +233,7 @@ list: { 'subtype': unicode, 'validators': [ - (ListDoesNotContainPlainExtensionIds, + (ListContainsOnlySha1Hashes, 'list should only have hex-encoded SHA1 hashes of extension ids') ] } @@ -460,6 +466,7 @@ is_all = False if v == 'all' and list in grammar and 'allow_all' in grammar[list]: + assert grammar[list]['allow_all'], '`allow_all` only supports `True`.' v = [] is_all = True @@ -472,6 +479,14 @@ self._AddKeyError(key, 'Illegal value: "%s"' % v) return + if value_type is list and not is_all and len(v) == 0: + if 'allow_empty' in grammar[list]: + assert grammar[list]['allow_empty'], \ + '`allow_empty` only supports `True`.' + else: + self._AddKeyError(key, 'List must specify at least one element.') + return + expected = grammar[value_type] expected_values = None enum_map = None
diff --git a/tools/json_schema_compiler/feature_compiler_test.py b/tools/json_schema_compiler/feature_compiler_test.py index c9c58f6..3a1f500 100755 --- a/tools/json_schema_compiler/feature_compiler_test.py +++ b/tools/json_schema_compiler/feature_compiler_test.py
@@ -38,7 +38,10 @@ def testFeature(self): # Test some basic feature parsing for a sanity check. f = self._parseFeature({ - 'blacklist': ['aaa', 'bbb'], + 'blacklist': [ + 'ABCDEF0123456789ABCDEF0123456789ABCDEF01', + '10FEDCBA9876543210FEDCBA9876543210FEDCBA' + ], 'channel': 'stable', 'command_line_switch': 'switch', 'component_extensions_auto_granted': False, @@ -57,7 +60,10 @@ 'noparent': True, 'platforms': ['mac', 'win'], 'session_types': ['kiosk', 'regular'], - 'whitelist': ['zzz', 'yyy'] + 'whitelist': [ + '0123456789ABCDEF0123456789ABCDEF01234567', + '76543210FEDCBA9876543210FEDCBA9876543210' + ] }) self.assertFalse(f.GetErrors()) @@ -95,6 +101,15 @@ f = self._parseFeature({'noparent': False}) self._hasError(f, 'Illegal value: "False"') + def testEmptyList(self): + f = self._parseFeature({'contexts': []}) + self._hasError(f, 'List must specify at least one element.') + + def testEmptyListWithAllowEmpty(self): + # `dependencies` is the only key that allows an empty list. + f = self._parseFeature({'dependencies': []}) + self.assertFalse(f.GetErrors()) + def testApiFeaturesNeedContexts(self): f = self._parseFeature({'dependencies': 'alpha', 'extension_types': ['extension'],
diff --git a/tools/json_schema_compiler/test/features_generation_unittest.cc b/tools/json_schema_compiler/test/features_generation_unittest.cc index 2335097b..32dfaad 100644 --- a/tools/json_schema_compiler/test/features_generation_unittest.cc +++ b/tools/json_schema_compiler/test/features_generation_unittest.cc
@@ -125,8 +125,10 @@ comparator.extension_types = {Manifest::TYPE_EXTENSION, Manifest::TYPE_PLATFORM_APP}; comparator.location = SimpleFeature::COMPONENT_LOCATION; - comparator.allowlist = {"aaa", "bbb"}; - comparator.blocklist = {"zzz", "yyy"}; + comparator.allowlist = {"ABCDEF0123456789ABCDEF0123456789ABCDEF01", + "10FEDCBA9876543210FEDCBA9876543210FEDCBA"}; + comparator.blocklist = {"0123456789ABCDEF0123456789ABCDEF01234567", + "76543210FEDCBA9876543210FEDCBA9876543210"}; comparator.component_extensions_auto_granted = false; comparator.CompareFeature(feature); } @@ -145,7 +147,7 @@ // case that it specifies its own value. Thus, we reuse |comparator|. feature = GetAsSimpleFeature("gamma.child"); comparator.name = "gamma.child"; - comparator.allowlist = {"ccc"}; + comparator.allowlist = {"0123456789ABCDEF0123456789ABCDEF01234567"}; comparator.platforms = {Feature::LINUX_PLATFORM}; comparator.dependencies.clear(); comparator.CompareFeature(feature); @@ -155,7 +157,7 @@ // other feature. const SimpleFeature* feature = GetAsSimpleFeature("gamma.unparented"); FeatureComparator comparator("gamma.unparented"); - comparator.blocklist = {"ddd"}; + comparator.blocklist = {"0123456789ABCDEF0123456789ABCDEF01234567"}; comparator.contexts = {Feature::UNBLESSED_EXTENSION_CONTEXT}; comparator.channel = version_info::Channel::DEV; comparator.CompareFeature(feature); @@ -259,7 +261,7 @@ comparator.channel = version_info::Channel::BETA; comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; comparator.extension_types = {Manifest::TYPE_EXTENSION}; - comparator.allowlist = {"aaa"}; + comparator.allowlist = {"0123456789ABCDEF0123456789ABCDEF01234567"}; comparator.CompareFeature(other_parent); } }
diff --git a/tools/json_schema_compiler/test/features_test.json b/tools/json_schema_compiler/test/features_test.json index 900e9ecc9..5cd6155 100644 --- a/tools/json_schema_compiler/test/features_test.json +++ b/tools/json_schema_compiler/test/features_test.json
@@ -13,8 +13,14 @@ "contexts": ["blessed_extension"], "extension_types": ["extension", "platform_app"], "location": "component", - "whitelist": ["aaa", "bbb"], - "blacklist": ["zzz", "yyy"], + "whitelist": [ + "ABCDEF0123456789ABCDEF0123456789ABCDEF01", + "10FEDCBA9876543210FEDCBA9876543210FEDCBA" + ], + "blacklist": [ + "0123456789ABCDEF0123456789ABCDEF01234567", + "76543210FEDCBA9876543210FEDCBA9876543210" + ], "component_extensions_auto_granted": false }, "gamma": { @@ -26,13 +32,13 @@ "internal": true }, "gamma.child": { - "whitelist": ["ccc"], + "whitelist": ["0123456789ABCDEF0123456789ABCDEF01234567"], "dependencies": [], "platforms": ["linux"] }, "gamma.unparented": { "channel": "dev", - "blacklist": ["ddd"], + "blacklist": ["0123456789ABCDEF0123456789ABCDEF01234567"], "contexts": ["unblessed_extension"], "noparent": true }, @@ -55,7 +61,7 @@ "channel": "beta", "contexts": ["blessed_extension"], "extension_types": ["extension"], - "whitelist": ["aaa"] + "whitelist": ["0123456789ABCDEF0123456789ABCDEF01234567"] }, { "channel": "stable", "contexts": ["blessed_extension"],
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 67880387..496c60d 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -669,10 +669,12 @@ 'android_angle_deqp_rel_ng': 'deqp_android_release_trybot_arm64', 'android_angle_vk32_deqp_rel_ng': 'deqp_android_vulkan_release_trybot', 'android_angle_vk64_deqp_rel_ng': 'deqp_android_vulkan_release_trybot_arm64', + 'linux-angle-rel': 'gpu_fyi_tests_release_trybot', 'linux_angle_ozone_rel_ng': 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot', 'linux_angle_dbg_ng': 'gpu_fyi_tests_debug_trybot', 'linux_angle_deqp_rel_ng': 'deqp_release_trybot', 'linux_angle_rel_ng': 'gpu_fyi_tests_release_trybot', + 'mac-angle-rel': 'gpu_fyi_tests_release_trybot', 'mac_angle_dbg_ng': 'gpu_fyi_tests_debug_trybot', 'mac_angle_rel_ng': 'gpu_fyi_tests_release_trybot', 'win-angle-rel': 'gpu_fyi_tests_release_trybot_x86',
diff --git a/tools/metrics/BUILD.gn b/tools/metrics/BUILD.gn index 25a8f5b..6f01fdd 100644 --- a/tools/metrics/BUILD.gn +++ b/tools/metrics/BUILD.gn
@@ -97,6 +97,7 @@ "//tools/metrics/common/path_util.py", "//tools/metrics/common/presubmit_util.py", "//tools/metrics/common/pretty_print_xml.py", + "//tools/metrics/common/etree_util.py", "//tools/metrics/histograms/extract_histograms.py", "//tools/metrics/histograms/generate_expired_histograms_array.py",
diff --git a/tools/metrics/actions/actions_print_style.py b/tools/metrics/actions/actions_print_style.py index ed19f6a9..8d1278e 100644 --- a/tools/metrics/actions/actions_print_style.py +++ b/tools/metrics/actions/actions_print_style.py
@@ -50,7 +50,7 @@ # Tags that we allow to be squished into a single line for brevity. TAGS_THAT_ALLOW_SINGLE_LINE = ['obsolete', 'owner', 'description'] -LOWERCASE_NAME_FN = lambda n: n.attributes['name'].value.lower() +LOWERCASE_NAME_FN = lambda n: n.get('name').lower() # Tags whose children we want to alphabetize. The key is the parent tag name, # and the value is a list of pairs of tag name and key functions that maps each
diff --git a/tools/metrics/common/etree_util.py b/tools/metrics/common/etree_util.py new file mode 100644 index 0000000..cbfcbe8 --- /dev/null +++ b/tools/metrics/common/etree_util.py
@@ -0,0 +1,94 @@ +# 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. + +"""Utility functions for parsing XML strings into ElementTree nodes.""" + +import xml.etree.ElementTree as ET +import xml.sax + + +class _FirstTagFoundError(Exception): + """Raised when the first tag is found in an XML document. + + This isn't actually an error. Raising this exception is how we end parsing XML + documents early. + """ + pass + + +class _FirstTagFinder(xml.sax.ContentHandler): + """An XML SAX parser that raises as soon as a tag is found. + + Call getFirstTagLine to determine which line the tag was found on. + """ + + def __init__(self): + xml.sax.ContentHandler.__init__(self) + self.first_tag_line = 0 + self.first_tag_column = 0 + + def GetFirstTagLine(self): + return self.first_tag_line + + def GetFirstTagColumn(self): + return self.first_tag_column + + def setDocumentLocator(self, locator): + self.location = locator + + def startElement(self, tag, attributes): + del tag, attributes # Unused. + + # Now that the first tag is found, remember the location of it. + self.first_tag_line = self.location.getLineNumber() + self.first_tag_column = self.location.getColumnNumber() + + # End parsing by throwing. + raise _FirstTagFoundError() + + +class _CommentedXMLParser(ET.XMLParser): + """An ElementTree builder that preserves comments.""" + + def __init__(self, *args, **kwargs): + super(_CommentedXMLParser, self).__init__(*args, **kwargs) + self._parser.CommentHandler = self.comment + + def comment(self, data): # pylint: disable=invalid-name + self._target.start(ET.Comment, {}) + self._target.data(data) + self._target.end(ET.Comment) + + +def GetTopLevelContent(file_content): + """Returns a string of all the text in the xml file before the first tag.""" + handler = _FirstTagFinder() + + first_tag_line = 0 + first_tag_column = 0 + try: + xml.sax.parseString(file_content, handler) + except _FirstTagFoundError: + # This is the expected case, it means a tag was found in the doc. + first_tag_line = handler.GetFirstTagLine() + first_tag_column = handler.GetFirstTagColumn() + if first_tag_line == 0 and first_tag_column == 0: + return '' + + char = 0 + for _ in range(first_tag_line - 1): + char = file_content.index('\n', char) + 1 + char += first_tag_column - 1 + + # |char| is now pointing at the final character before the opening tag '<'. + top_content = file_content[:char + 1].strip() + if not top_content: + return '' + + return top_content + '\n\n' + + +def ParseXMLString(raw_xml): + """Parses raw_xml and returns an ElementTree node that includes comments.""" + return ET.fromstring(raw_xml, _CommentedXMLParser())
diff --git a/tools/metrics/common/pretty_print_xml.py b/tools/metrics/common/pretty_print_xml.py index ae97ff7..15ab216 100644 --- a/tools/metrics/common/pretty_print_xml.py +++ b/tools/metrics/common/pretty_print_xml.py
@@ -11,7 +11,10 @@ import sys import logging import textwrap -import xml.dom.minidom +from xml.dom import minidom +import xml.etree.ElementTree as ET + +import etree_util WRAP_COLUMN = 80 @@ -29,7 +32,8 @@ Returns: The length of the last line in s, in characters. """ - if s.rfind('\n') == -1: return len(s) + if s.rfind('\n') == -1: + return len(s) return len(s) - s.rfind('\n') - len('\n') @@ -45,6 +49,7 @@ Args: text: The text to split. + Returns: A list of paragraphs as strings. """ @@ -84,58 +89,57 @@ self.wrapper.width = WRAP_COLUMN def PrettyPrintXml(self, tree): + # If it's not an ElementTree instance, we assume it's minidom. + if not isinstance(tree, ET.Element): + assert isinstance(tree, minidom.Document) + return self._PrettyPrintMinidom(tree) + tree = self._TransformByAlphabetizing(tree) - tree = self.PrettyPrintNode(tree) + tree = self.PrettyPrintElementTreeNode(tree) return tree - def _UnsafeAppendChild(self, parent, child): - """Append child to parent's list of children. + def _PrettyPrintMinidom(self, doc): + """Transforms minidom to ElementTree before pretty printing it.""" + raw_xml = doc.toxml() - It ignores the possibility that the child is already in another node's - childNodes list. Requires that the previous parent of child is discarded - (to avoid non-tree DOM graphs). This can provide a significant speedup as - O(n^2) operations are removed (in particular, each child insertion avoids - the need to traverse the old parent's entire list of children). + # minidom prepends a document type, so remove it. + raw_xml = raw_xml.replace(minidom.Document().toxml(), '') - Args: - parent: the parent node to be appended to. - child: the child node to append to |parent| node. - """ - child.parentNode = None - parent.appendChild(child) - child.parentNode = parent + etree_root = etree_util.ParseXMLString(raw_xml) + top_content = etree_util.GetTopLevelContent(raw_xml) + + # Add newlines between top-level comments. + top_content = top_content.replace('--><!--', '-->\n\n<!--') + + formatted_xml = self.PrettyPrintXml(etree_root) + return top_content + formatted_xml + def _TransformByAlphabetizing(self, node): """Transform the given XML by alphabetizing nodes. Args: - node: The minidom node to transform. + node: The elementtree node to transform. Returns: - The minidom node, with children appropriately alphabetized. Note that the - transformation is done in-place, i.e. the original minidom tree is - modified directly. + The elementtree node, with children appropriately alphabetized. Note that + the transformation is done in-place, i.e. the original tree is modified + directly. """ - if node.nodeType != xml.dom.minidom.Node.ELEMENT_NODE: - for c in node.childNodes: - self._TransformByAlphabetizing(c) - return node - # Element node with a tag name that we alphabetize the children of? alpha_rules = self.tags_alphabetization_rules - if node.tagName in alpha_rules: + if node.tag in alpha_rules: # Put subnodes in a list of node, key pairs to allow for custom sorting. subtags = {} - for index, (subtag, key_function) in enumerate(alpha_rules[node.tagName]): + for index, (subtag, key_function) in enumerate(alpha_rules[node.tag]): subtags[subtag] = (index, key_function) subnodes = [] sort_key = -1 pending_node_indices = [] - for c in node.childNodes: - if (c.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and - c.tagName in subtags): - subtag_sort_index, key_function = subtags[c.tagName] + for c in node: + if c.tag in subtags: + subtag_sort_index, key_function = subtags[c.tag] sort_key = (subtag_sort_index, key_function(c)) # Replace sort keys for delayed nodes. for idx in pending_node_indices: @@ -151,60 +155,66 @@ # Sort the subnode list. subnodes.sort(key=lambda pair: pair[1]) - # Re-add the subnodes, transforming each recursively. - while node.firstChild: - node.removeChild(node.firstChild) + # Remove the existing nodes + for child in list(node): + node.remove(child) + + # Re-add the sorted subnodes, transforming each recursively. for (c, _) in subnodes: - self._UnsafeAppendChild(node, self._TransformByAlphabetizing(c)) + node.append(self._TransformByAlphabetizing(c)) return node # Recursively handle other element nodes and other node types. - for c in node.childNodes: + for c in node: self._TransformByAlphabetizing(c) return node - def _PrettyPrintText(self, node, indent): - # Wrap each paragraph in the text to fit in the 80 column limit. + def _PrettyPrintText(self, text, indent): + """Pretty print an element.""" + if not text.strip(): + return "" + self.wrapper.initial_indent = ' ' * indent self.wrapper.subsequent_indent = ' ' * indent - text = XmlEscape(node.data) - paragraphs = SplitParagraphs(text) + escaped_text = XmlEscape(text) + paragraphs = SplitParagraphs(escaped_text) + # Wrap each paragraph and separate with two newlines. return '\n\n'.join(self.wrapper.fill(p) for p in paragraphs) def _PrettyPrintElement(self, node, indent): # Check if tag name is valid. - if node.tagName not in self.attribute_order: - logging.error('Unrecognized tag "%s"', node.tagName) - raise Error('Unrecognized tag "%s"', node.tagName) + if node.tag not in self.attribute_order: + logging.error('Unrecognized tag "%s"', node.tag) + raise Error('Unrecognized tag "%s"' % node.tag) # Newlines. newlines_after_open, newlines_before_close, newlines_after_close = ( - self.tags_that_have_extra_newline.get(node.tagName, (1, 1, 0))) + self.tags_that_have_extra_newline.get(node.tag, (1, 1, 0))) # Open the tag. - s = ' ' * indent + '<' + node.tagName + s = ' ' * indent + '<' + node.tag # Calculate how much space to allow for the '>' or '/>'. - closing_chars = 1 - if not node.childNodes: - closing_chars = 2 + closing_chars = 2 + if len(node) or node.text: + closing_chars = 1 - attributes = node.attributes.keys() + attributes = node.keys() required_attributes = [attribute for attribute in self.required_attributes - if attribute in self.attribute_order[node.tagName]] + if attribute in self.attribute_order[node.tag]] missing_attributes = [attribute for attribute in required_attributes if attribute not in attributes] for attribute in missing_attributes: logging.error( - 'Missing attribute "%s" in tag "%s"', attribute, node.tagName) + 'Missing attribute "%s" in tag "%s"', attribute, node.tag) if missing_attributes: missing_attributes_str = ( ', '.join('"%s"' % attribute for attribute in missing_attributes)) present_attributes = [ ' {0}="{1}"'.format(name, value) - for name, value in node.attributes.items()] - node_str = '<{0}{1}>'.format(node.tagName, ''.join(present_attributes)) + for name, value in node.items()] + node_str = '<{0}{1}>'.format(node.tag, ''.join(present_attributes)) raise Error( 'Missing attributes {0} in tag "{1}"'.format( missing_attributes_str, node_str)) @@ -212,23 +222,22 @@ # Pretty-print the attributes. if attributes: # Reorder the attributes. - unrecognized_attributes = ( - [a for a in attributes - if a not in self.attribute_order[node.tagName]]) - attributes = [a for a in self.attribute_order[node.tagName] - if a in attributes] + unrecognized_attributes = [ + a for a in attributes if a not in self.attribute_order[node.tag] + ] + attributes = [ + a for a in self.attribute_order[node.tag] if a in attributes + ] for a in unrecognized_attributes: - logging.error( - 'Unrecognized attribute "%s" in tag "%s"', a, node.tagName) + logging.error('Unrecognized attribute "%s" in tag "%s"', a, node.tag) if unrecognized_attributes: - raise Error( - 'Unrecognized attributes {0} in tag "{1}"'.format( - ', '.join('"{0}"'.format(a) for a in unrecognized_attributes), - node.tagName)) + raise Error('Unrecognized attributes {0} in tag "{1}"'.format( + ', '.join('"{0}"'.format(a) for a in unrecognized_attributes), + node.tag)) for a in attributes: - value = XmlEscape(node.attributes[a].value) + value = XmlEscape(node.get(a)) # Replace sequences of whitespace with single spaces. words = value.split() a_str = ' %s="%s"' % (a, ' '.join(words)) @@ -255,25 +264,39 @@ s = s.rstrip() # remove any trailing whitespace # Pretty-print the child nodes. - if node.childNodes: + if len(node) > 0 or node.text: # pylint: disable=g-explicit-length-test s += '>' # Calculate the new indent level for child nodes. new_indent = indent - if node.tagName not in self.tags_that_dont_indent: + if node.tag not in self.tags_that_dont_indent: new_indent += 2 - child_nodes = node.childNodes + + children = [] + for c in node: + children.append(c) # Recursively pretty-print the child nodes. - child_nodes = [self.PrettyPrintNode(n, indent=new_indent) - for n in child_nodes] - child_nodes = [c for c in child_nodes if c.strip()] + child_nodes = [] + if node.text: + formatted_text = self._PrettyPrintText(node.text, new_indent) + if formatted_text: + child_nodes.append(formatted_text) + + for child in node: + child_output = self.PrettyPrintElementTreeNode(child, indent=new_indent) + if child_output.strip(): + child_nodes.append(child_output) + + if child.tail: + tail_text = self._PrettyPrintText(child.tail, new_indent) + if tail_text: + child_nodes.append(tail_text) # Determine whether we can fit the entire node on a single line. - close_tag = '</%s>' % node.tagName + close_tag = '</%s>' % node.tag space_left = WRAP_COLUMN - LastLineLength(s) - len(close_tag) - if (node.tagName in self.tags_that_allow_single_line and - len(child_nodes) == 1 and - len(child_nodes[0].strip()) <= space_left): + if (node.tag in self.tags_that_allow_single_line and + len(child_nodes) == 1 and len(child_nodes[0].strip()) <= space_left): s += child_nodes[0].strip() else: s += '\n' * newlines_after_open + '\n'.join(child_nodes) @@ -284,11 +307,11 @@ s += '\n' * newlines_after_close return s - def PrettyPrintNode(self, node, indent=0): + def PrettyPrintElementTreeNode(self, node, indent=0): """Pretty-prints the given XML node at the given indent level. Args: - node: The minidom node to pretty-print. + node: The ElementTree node to pretty-print. indent: The current indent level. Returns: @@ -297,24 +320,9 @@ Raises: Error: if the XML has unknown tags or attributes. """ - # Handle the top-level document node. - if node.nodeType == xml.dom.minidom.Node.DOCUMENT_NODE: - return '\n'.join([self.PrettyPrintNode(n) for n in node.childNodes]) - - # Handle text nodes. - if node.nodeType == xml.dom.minidom.Node.TEXT_NODE: - return self._PrettyPrintText(node, indent) + # Handle comment nodes. + if node.tag is ET.Comment: + return '<!--%s-->\n' % node.text # Handle element nodes. - if node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE: - return self._PrettyPrintElement(node, indent) - - # Handle comment nodes. - if node.nodeType == xml.dom.minidom.Node.COMMENT_NODE: - return '<!--%s-->\n' % node.data - - # Ignore other node types. This could be a processing instruction - # (<? ... ?>) or cdata section (<![CDATA[...]]!>), neither of which are - # legal in the histograms XML at present. - logging.error('Ignoring unrecognized node data: %s', node.toxml()) - raise Error('Ignoring unrecognized node data: {0}'.format(node.toxml())) + return self._PrettyPrintElement(node, indent)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index d5f4e40..dffcfde 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -32001,6 +32001,7 @@ <int value="-2108564200" label="AutofillUpstream:disabled"/> <int value="-2104950596" label="HandwritingGesture:enabled"/> <int value="-2101682955" label="EnableNotificationIndicator:enabled"/> + <int value="-2101337189" label="AutofillOffNoServerData:disabled"/> <int value="-2099457894" label="Mash:enabled"/> <int value="-2099035488" label="enable-data-reduction-proxy-bypass-warning"/> <int value="-2098610409" label="disable-lcd-text"/> @@ -33306,6 +33307,7 @@ <int value="-88273414" label="ContentSuggestionsShowSummary:enabled"/> <int value="-86788587" label="allow-autofill-sync-credential"/> <int value="-86243376" label="LayoutNG:enabled"/> + <int value="-80501013" label="AutofillOffNoServerData:enabled"/> <int value="-80353187" label="disable-display-color-calibration"/> <int value="-79327236" label="ModeSpecificPowerButton:enabled"/> <int value="-78035185" label="custom_summary"/> @@ -36466,6 +36468,13 @@ <int value="2" label="MediaFling"/> </enum> +<enum name="MediaNotificationSource"> + <int value="0" label="Unknown"/> + <int value="1" label="Web"/> + <int value="2" label="Assistant"/> + <int value="3" label="Arc"/> +</enum> + <enum name="MediaOutputProtectionStatus"> <int value="0" label="Queried"/> <int value="1" label="No external link"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index cd630a0..ad0b4fdc 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -52038,6 +52038,16 @@ </summary> </histogram> +<histogram name="Media.Notification.Source" enum="MediaNotificationSource" + expires_after="2019-12-31"> + <owner>beccahughes@chromium.org</owner> + <owner>media-dev@chromium.org</owner> + <summary> + The source of the underlying media session (e.g. arc, web) that displayed + the media notification. This is recorded when the notification is shown. + </summary> +</histogram> + <histogram name="Media.Notification.UserAction" enum="MediaSessionAction" expires_after="2019-12-31"> <owner>beccahughes@chromium.org</owner> @@ -126341,6 +126351,10 @@ <histogram name="UMA.FileMetricsProvider.EmbeddedProfile.RecordTime" units="ms" expires_after="M71"> + <obsolete> + Removed 2019/04 as times are small, consistent, and now on a background + thread. + </obsolete> <owner>bcwhite@chromium.org</owner> <summary> Tracks the time used to record all histograms from a file with an embedded
diff --git a/tools/metrics/histograms/histograms_print_style.py b/tools/metrics/histograms/histograms_print_style.py index 5a44248..65828e6d 100644 --- a/tools/metrics/histograms/histograms_print_style.py +++ b/tools/metrics/histograms/histograms_print_style.py
@@ -65,13 +65,13 @@ # Tags that we allow to be squished into a single line for brevity. TAGS_THAT_ALLOW_SINGLE_LINE = ['summary', 'int', 'owner'] -LOWERCASE_NAME_FN = lambda n: n.attributes['name'].value.lower() +LOWERCASE_NAME_FN = lambda n: n.get('name').lower() def _NaturalSortByName(node): """Sort by name, ordering numbers in the way humans expect.""" # See: https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/ - name = node.attributes['name'].value.lower() + name = node.get('name').lower() convert = lambda text: int(text) if text.isdigit() else text return [convert(c) for c in re.split('([0-9]+)', name)] @@ -82,7 +82,7 @@ TAGS_ALPHABETIZATION_RULES = { 'histograms': [('histogram', LOWERCASE_NAME_FN)], 'enums': [('enum', LOWERCASE_NAME_FN)], - 'enum': [('int', lambda n: int(n.attributes['value'].value))], + 'enum': [('int', lambda n: int(n.get('value')))], 'histogram_suffixes_list': [('histogram_suffixes', LOWERCASE_NAME_FN)], 'histogram_suffixes': [ ('obsolete', lambda n: None),
diff --git a/tools/metrics/histograms/pretty_print.py b/tools/metrics/histograms/pretty_print.py index 1e96b4f4..dd57976d 100755 --- a/tools/metrics/histograms/pretty_print.py +++ b/tools/metrics/histograms/pretty_print.py
@@ -18,19 +18,17 @@ import os import shutil import sys -import xml.dom.minidom sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common')) import diff_util import presubmit_util +import etree_util import histograms_print_style - class Error(Exception): pass - UNIT_REWRITES = { 'microsecond': 'microseconds', 'us': 'microseconds', @@ -49,34 +47,39 @@ 'percentage': '%', } - def canonicalizeUnits(tree): """Canonicalize the spelling of certain units in histograms.""" - histograms = tree.getElementsByTagName('histogram') - for histogram in histograms: - units = histogram.attributes.get('units') - if units and units.value in UNIT_REWRITES: - histogram.attributes['units'] = UNIT_REWRITES[units.value] + if tree.tag == 'histogram': + units = tree.get('units') + if units and units in UNIT_REWRITES: + tree.set('units', UNIT_REWRITES[units]) + for child in tree: + canonicalizeUnits(child) def fixObsoleteOrder(tree): """Put obsolete tags at the beginning of histogram tags.""" - histograms = tree.getElementsByTagName('histogram') - for histogram in histograms: - obsoletes = histogram.getElementsByTagName('obsolete') - if obsoletes: - histogram.insertBefore(obsoletes[0], histogram.firstChild) - + for child in tree: + obsoletes = [] + if child.tag == 'obsolete': + obsoletes.append(child) + for obsolete in obsoletes: + tree.remove(obsolete) + tree.insert(0, obsolete) + fixObsoleteOrder(child) def DropNodesByTagName(tree, tag): """Drop all nodes with named tag from the XML tree.""" - nodes = tree.getElementsByTagName(tag) - for node in nodes: - node.parentNode.removeChild(node) - + for child in tree: + removes = [] + if child.tag == tag: + removes.append(child) + for child in removes: + tree.remove(child) + DropNodesByTagName(child, tag) def PrettyPrintHistograms(raw_xml): - """Pretty-print the given XML. + """Pretty-print the given histograms XML. Args: raw_xml: The contents of the histograms XML file, as a string. @@ -84,43 +87,48 @@ Returns: The pretty-printed version. """ - tree = xml.dom.minidom.parseString(raw_xml) - return PrettyPrintHistogramsTree(tree) - + top_level_content = etree_util.GetTopLevelContent(raw_xml) + root = etree_util.ParseXMLString(raw_xml) + return top_level_content + PrettyPrintHistogramsTree(root) def PrettyPrintHistogramsTree(tree): - """Pretty-print the given xml.dom.minidom.Document object. + """Pretty-print the given ElementTree element. Args: - tree: The xml.dom.minidom.Document object. + tree: The ElementTree element. Returns: The pretty-printed version as an XML string. """ - assert isinstance(tree, xml.dom.minidom.Document) # Prevent accidentally adding enums to histograms.xml DropNodesByTagName(tree, 'enums') canonicalizeUnits(tree) fixObsoleteOrder(tree) return histograms_print_style.GetPrintStyle().PrettyPrintXml(tree) - def PrettyPrintEnums(raw_xml): - """Pretty print the enums.xml file.""" - tree = xml.dom.minidom.parseString(raw_xml) - # Prevent accidentally adding histograms to enums.xml - DropNodesByTagName(tree, 'histograms') - DropNodesByTagName(tree, 'histogram_suffixes_list') - return histograms_print_style.GetPrintStyle().PrettyPrintXml(tree) + """Pretty print the given enums XML.""" + root = etree_util.ParseXMLString(raw_xml) + + # Prevent accidentally adding histograms to enums.xml + DropNodesByTagName(root, 'histograms') + DropNodesByTagName(root, 'histogram_suffixes_list') + + top_level_content = etree_util.GetTopLevelContent(raw_xml) + + formatted_xml = (histograms_print_style.GetPrintStyle() + .PrettyPrintXml(root)) + return top_level_content + formatted_xml def main(): status1 = presubmit_util.DoPresubmit(sys.argv, 'enums.xml', 'enums.before.pretty-print.xml', 'pretty_print.py', PrettyPrintEnums) status2 = presubmit_util.DoPresubmit(sys.argv, 'histograms.xml', - 'histograms.before.pretty-print.xml', - 'pretty_print.py', PrettyPrintHistograms) + 'histograms.before.pretty-print.xml', + 'pretty_print.py', + PrettyPrintHistograms) sys.exit(status1 or status2) if __name__ == '__main__':
diff --git a/tools/metrics/histograms/pretty_print_test.py b/tools/metrics/histograms/pretty_print_test.py index 2df6cfcd..e0c1280c 100755 --- a/tools/metrics/histograms/pretty_print_test.py +++ b/tools/metrics/histograms/pretty_print_test.py
@@ -9,30 +9,55 @@ ORIGINAL_XML = """ +<!-- Top level Comment 1 --> +<!-- Top level Comment 2 --> <histogram-configuration> <histograms> - <histogram name="Test.Histogram" units="things"> + <histogram name="Test.Histogram" units="us"> <owner>person@chromium.org</owner> <summary>A long line that should be formatted in a way that does not result in extra whitespace between words. + + It has multiple paragraphs. </summary> + Mixed content. + <obsolete> + Removed 1/2019. + </obsolete> + </histogram> + <histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz"> + <summary>Foo</summary> </histogram> </histograms> +<enums>This shouldn't be here</enums> </histogram-configuration> """.strip() PRETTY_XML = """ +<!-- Top level Comment 1 --> +<!-- Top level Comment 2 --> + <histogram-configuration> <histograms> -<histogram name="Test.Histogram" units="things"> +<histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz"> + <summary>Foo</summary> +</histogram> + +<histogram name="Test.Histogram" units="microseconds"> + <obsolete> + Removed 1/2019. + </obsolete> <owner>person@chromium.org</owner> <summary> A long line that should be formatted in a way that does not result in extra whitespace between words. + + It has multiple paragraphs. </summary> + Mixed content. </histogram> </histograms> @@ -43,11 +68,10 @@ class PrettyPrintHistogramsXmlTest(unittest.TestCase): - def testWhitespaceWrapping(self): + def testPrettyPrinting(self): result = pretty_print.PrettyPrintHistograms(ORIGINAL_XML) self.maxDiff = None self.assertMultiLineEqual(PRETTY_XML, result.strip()) - if __name__ == '__main__': unittest.main()
diff --git a/tools/metrics/ukm/ukm_model.py b/tools/metrics/ukm/ukm_model.py index a363d5c9..841257d 100644 --- a/tools/metrics/ukm/ukm_model.py +++ b/tools/metrics/ukm/ukm_model.py
@@ -14,7 +14,7 @@ _OWNER_TYPE = models.TextNodeType('owner', single_line=True) _SUMMARY_TYPE = models.TextNodeType('summary') -_LOWERCASE_NAME_FN = lambda n: n.attributes['name'].value.lower() +_LOWERCASE_NAME_FN = lambda n: n.get('name').lower() _ENUMERATION_TYPE = models.ObjectNodeType( 'enumeration',
diff --git a/tools/perf/contrib/leak_detection/data/leak_detection.json b/tools/perf/contrib/leak_detection/data/leak_detection.json index 1720684..25c0adb 100644 --- a/tools/perf/contrib/leak_detection/data/leak_detection.json +++ b/tools/perf/contrib/leak_detection/data/leak_detection.json
@@ -1,612 +1,612 @@ { "archives": { "http://a-rakumo.appspot.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://europa.eu/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://game.co.za": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://hdu.edu.cn": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://infomoney.com.br": { "DEFAULT": "leak_detection_004.wprgo" }, "http://kakaku.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://makfax.com.mk": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://siteadvisor.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://support.wordpress.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://whu.edu.cn": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.22find.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.520mojing.com": { "DEFAULT": "leak_detection_004.wprgo" }, "http://www.aaannunci.it": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.airbnb.ch": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.aljazeera.net": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.amazon.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.ansa.it": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.arabam.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.benzworld.org": { "DEFAULT": "leak_detection_004.wprgo" }, "http://www.besgold.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.bestdic.ir": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.block.io": { "DEFAULT": "leak_detection_004.wprgo" }, "http://www.blu-ray.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.careesma.in": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.chatword.org": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.cheapoair.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.coco.fr": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.contentful.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.dailypost.ng": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.daydao.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.do-search.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.e-shop.gr": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.espn.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.estibot.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.expediapartnercentral.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.ezcardinfo.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.foxnews.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.goal.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.googleapps.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.gradpoint.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.gulfair.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.highwaybus.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.hockeybuzz.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.horairetrain.net": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.inbank.it": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.indeed.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.iowacconline.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.jd.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.leandomainsearch.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.listindiario.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.livedoor.jp": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.magnetmail.net": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.mail.bg": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.mastodon.social": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.mbs.de": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.nicovideo.jp/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.nigma.ru": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.nusatrip.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.omniboxes.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.onlinedown.net": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.opentable.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.pingpang.info": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.podbay.fm": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.privacyassistant.net": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.psiexams.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.qq.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.quora.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.railsguides.jp": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.register.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.reverso.net/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.sakurafile.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.samsung-fun.ru": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.savaari.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.sick.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.silverpop.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.sjp.pl": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.skipaas.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.sklavenzentrale.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.time.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.torrentzeu.to": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.twitter.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.webwebweb.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.wikia.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.wpjam.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://www.zhengjie.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "http://zzz.com.ua": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://9gag.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://ameblo.jp/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://answers.yahoo.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://archive.org/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://billdesk.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://docs.google.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://edition.cnn.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://fc2.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://github.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://gizmodo.com/": { "DEFAULT": "leak_detection_004.wprgo" }, "https://ign.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://imgur.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://mail.ru/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://news.google.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://outlook.live.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://play.google.com/store": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://play.na.leagueoflegends.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://porn555.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://soundcloud.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://stackoverflow.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://translate.google.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://uidai.gov.in/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://vimeo.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://vk.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://weather.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://weibo.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://wordpress.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://world.taobao.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.360.cn/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.aliexpress.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.alipay.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.apple.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.baidu.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.bestbuy.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.bing.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.blizzard.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.blogger.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.booking.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.chase.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.citi.com": { "DEFAULT": "leak_detection_002.wprgo" }, "https://www.craigslist.org/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.cricbuzz.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.csdn.net/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.deviantart.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.dropbox.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.ebay.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.engadget.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.epicgames.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.etsy.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.expedia.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.facebook.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.flipkart.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.gamespot.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.goo.ne.jp/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.goodreads.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.google.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.gsmarena.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.hdfcbank.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.homedepot.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.hotels.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.hotstar.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.hulu.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.icicibank.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.ikea.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.imdb.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.incometaxindiaefiling.gov.in/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.indiatimes.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.instagram.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.irctc.co.in/nget/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.jw.org/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.linkedin.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.livejournal.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.macys.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.mediafire.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.microsoft.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.msn.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.netflix.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.nlm.nih.gov/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.nytimes.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.office.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.onlinesbi.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.patreon.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.paypal.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.pinterest.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.pixiv.net/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.pornhub.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.prezi.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.rakuten.co.jp/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.reddit.com": { "DEFAULT": "leak_detection_003.wprgo" }, "https://www.reddit.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.roblox.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.salesforce.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.scribd.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.shutterstock.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.sina.com.cn/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.slideshare.net/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.sohu.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.target.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.theguardian.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.thesaurus.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.theverge.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.tmall.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.tripadvisor.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.tumblr.com/": { "DEFAULT": "leak_detection_004.wprgo" }, "https://www.twitch.tv/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.udemy.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.weebly.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.whatsapp.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.wikipedia.org": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.xfinity.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.xvideos.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.yahoo.co.jp/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.yahoo.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.yelp.com/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://www.youtube.com": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" }, "https://yandex.ru/": { - "DEFAULT": "leak_detection_004.wprgo" + "DEFAULT": "leak_detection_8da6995ea2.wprgo" } }, "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", "platform_specific": true -} +} \ No newline at end of file
diff --git a/tools/perf/contrib/leak_detection/data/leak_detection_8da6995ea2.wprgo b/tools/perf/contrib/leak_detection/data/leak_detection_8da6995ea2.wprgo new file mode 100644 index 0000000..36e56d9 --- /dev/null +++ b/tools/perf/contrib/leak_detection/data/leak_detection_8da6995ea2.wprgo Binary files differ
diff --git a/tools/perf/contrib/leak_detection/data/leak_detection_8da6995ea2.wprgo.sha1 b/tools/perf/contrib/leak_detection/data/leak_detection_8da6995ea2.wprgo.sha1 new file mode 100644 index 0000000..db8e2b9 --- /dev/null +++ b/tools/perf/contrib/leak_detection/data/leak_detection_8da6995ea2.wprgo.sha1
@@ -0,0 +1 @@ +8da6995ea2940f144c11fbfc24d0e10d4715e9cc \ No newline at end of file
diff --git a/ui/aura/test/ui_controls_factory_ozone.cc b/ui/aura/test/ui_controls_factory_ozone.cc index f2bd4f9..c729b40a 100644 --- a/ui/aura/test/ui_controls_factory_ozone.cc +++ b/ui/aura/test/ui_controls_factory_ozone.cc
@@ -25,6 +25,7 @@ #include "ui/display/screen.h" #include "ui/events/event_utils.h" #include "ui/events/test/events_test_utils.h" +#include "ui/gfx/geometry/point_conversions.h" namespace aura { namespace test { @@ -129,7 +130,7 @@ bool SendMouseMoveNotifyWhenDone(long screen_x, long screen_y, base::OnceClosure closure) override { - gfx::Point host_location(screen_x, screen_y); + gfx::PointF host_location(screen_x, screen_y); int64_t display_id = display::kInvalidDisplayId; if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; @@ -158,13 +159,14 @@ int button_state, base::OnceClosure closure, int accelerator_state) override { - gfx::Point host_location; + gfx::PointF host_location; int64_t display_id = display::kInvalidDisplayId; if (last_mouse_location_.has_value()) { host_location = last_mouse_location_.value(); display_id = last_mouse_display_id_; } else { - host_location = host_->window()->env()->last_mouse_location(); + host_location = + gfx::PointF(host_->window()->env()->last_mouse_location()); if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; } @@ -228,7 +230,7 @@ int y, base::OnceClosure task) override { DCHECK_NE(0, action); - gfx::Point host_location(x, y); + gfx::PointF host_location(x, y); int64_t display_id = display::kInvalidDisplayId; if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; @@ -263,8 +265,24 @@ int64_t display_id, base::OnceClosure closure) { if (event_injector_) { + auto event_to_inject = ui::Event::Clone(*event); + + if (event_to_inject->IsLocatedEvent()) { + // EventInjector expects coordinates relative to host and in DIPs. + display::Display display; + CHECK(display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id, + &display)); + + ui::LocatedEvent* located_event = event_to_inject->AsLocatedEvent(); + gfx::PointF location_in_host_dip = gfx::ScalePoint( + located_event->location_f(), 1 / display.device_scale_factor(), + 1 / display.device_scale_factor()); + located_event->set_location_f(location_in_host_dip); + located_event->set_root_location_f(location_in_host_dip); + } + event_injector_->InjectEvent( - display_id, ui::Event::Clone(*event), + display_id, std::move(event_to_inject), base::BindOnce(&OnWindowServiceProcessedEvent, std::move(closure))); return; } @@ -304,7 +322,7 @@ } void PostMouseEvent(ui::EventType type, - const gfx::Point& host_location, + const gfx::PointF& host_location, int flags, int changed_button_flags, int64_t display_id, @@ -317,7 +335,7 @@ } void PostMouseEventTask(ui::EventType type, - const gfx::Point& host_location, + const gfx::PointF& host_location, int flags, int changed_button_flags, int64_t display_id, @@ -333,7 +351,7 @@ } void PostTouchEvent(ui::EventType type, - const gfx::Point& host_location, + const gfx::PointF& host_location, int id, int64_t display_id, base::OnceClosure closure) { @@ -344,14 +362,14 @@ } void PostTouchEventTask(ui::EventType type, - const gfx::Point& host_location, + const gfx::PointF& host_location, int id, int64_t display_id, base::OnceClosure closure) { ui::PointerDetails details(ui::EventPointerType::POINTER_TYPE_TOUCH, id, 1.0f, 1.0f, 0.0f); - ui::TouchEvent touch_event(type, host_location, ui::EventTimeForNow(), - details); + ui::TouchEvent touch_event(type, host_location, host_location, + ui::EventTimeForNow(), details); SendEventToSink(&touch_event, display_id, std::move(closure)); } @@ -367,19 +385,18 @@ ->BindInterface(ws::mojom::kServiceName, &event_injector_); } - bool ScreenDIPToHostPixels(gfx::Point* location, int64_t* display_id) { + bool ScreenDIPToHostPixels(gfx::PointF* location, int64_t* display_id) { // The location needs to be in display's coordinate. display::Display display = - display::Screen::GetScreen()->GetDisplayNearestPoint(*location); + display::Screen::GetScreen()->GetDisplayNearestPoint( + gfx::ToFlooredPoint(*location)); if (!display.is_valid()) { LOG(ERROR) << "Failed to find the display for " << location->ToString(); return false; } *display_id = display.id(); *location -= display.bounds().OffsetFromOrigin(); - *location = - gfx::ScaleToFlooredPoint(*location, display.device_scale_factor(), - display.device_scale_factor()); + location->Scale(display.device_scale_factor()); return true; } @@ -389,7 +406,7 @@ // The mouse location for the last SendMouseEventsNotifyWhenDone call. This is // used rather than Env::last_mouse_location() as Env::last_mouse_location() // is updated asynchronously with mus. - base::Optional<gfx::Point> last_mouse_location_; + base::Optional<gfx::PointF> last_mouse_location_; // The display ID where the last SendMouseEventsNotifyWhenDone occurred. This // is used along with |last_mouse_location_| to send the mouse event to the
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index aa3d8b5..fe7f544 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -679,6 +679,7 @@ cc_layer_->SetTransformOrigin(gfx::Point3F()); cc_layer_->SetContentsOpaque(fills_bounds_opaquely_); cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); + cc_layer_->SetHitTestable(type_ != LAYER_NOT_DRAWN); cc_layer_->SetHideLayerAndSubtree(!visible_); cc_layer_->SetBackdropFilterQuality(backdrop_filter_quality_); cc_layer_->SetElementId(cc::ElementId(cc_layer_->id())); @@ -1382,6 +1383,9 @@ cc_layer_->SetContentsOpaque(true); cc_layer_->SetSafeOpaqueBackgroundColor(SK_ColorWHITE); cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); + // TODO(sunxd): Allow ui::Layers to set if they accept events or not. See + // https://crbug.com/924294. + cc_layer_->SetHitTestable(type_ != LAYER_NOT_DRAWN); cc_layer_->SetLayerClient(weak_ptr_factory_.GetWeakPtr()); cc_layer_->SetElementId(cc::ElementId(cc_layer_->id())); RecomputePosition();
diff --git a/ui/display/manager/apply_content_protection_task.cc b/ui/display/manager/apply_content_protection_task.cc index 7ffb5a934..b5e4389 100644 --- a/ui/display/manager/apply_content_protection_task.cc +++ b/ui/display/manager/apply_content_protection_task.cc
@@ -4,8 +4,12 @@ #include "ui/display/manager/apply_content_protection_task.h" +#include <utility> +#include <vector> + #include "base/bind.h" #include "ui/display/manager/display_layout_manager.h" +#include "ui/display/manager/display_util.h" #include "ui/display/types/display_snapshot.h" #include "ui/display/types/native_display_delegate.h" @@ -17,24 +21,12 @@ const DisplayLayoutManager& layout_manager, std::vector<DisplaySnapshot*>* hdcp_capable_displays) { for (DisplaySnapshot* display : layout_manager.GetDisplayStates()) { - switch (display->type()) { - case DISPLAY_CONNECTION_TYPE_UNKNOWN: - return false; - // DisplayPort, DVI, and HDMI all support HDCP. - case DISPLAY_CONNECTION_TYPE_DISPLAYPORT: - case DISPLAY_CONNECTION_TYPE_DVI: - case DISPLAY_CONNECTION_TYPE_HDMI: - hdcp_capable_displays->push_back(display); - break; - case DISPLAY_CONNECTION_TYPE_INTERNAL: - case DISPLAY_CONNECTION_TYPE_VGA: - case DISPLAY_CONNECTION_TYPE_NETWORK: - // No protections for these types. Do nothing. - break; - case DISPLAY_CONNECTION_TYPE_NONE: - NOTREACHED(); - break; - } + uint32_t protection_mask; + if (!GetContentProtectionMethods(display->type(), &protection_mask)) + return false; + + if (protection_mask & CONTENT_PROTECTION_METHOD_HDCP) + hdcp_capable_displays->push_back(display); } return true; @@ -45,28 +37,25 @@ ApplyContentProtectionTask::ApplyContentProtectionTask( DisplayLayoutManager* layout_manager, NativeDisplayDelegate* native_display_delegate, - const DisplayConfigurator::ContentProtections& requests, - const ResponseCallback& callback) + DisplayConfigurator::ContentProtections requests, + ResponseCallback callback) : layout_manager_(layout_manager), native_display_delegate_(native_display_delegate), - requests_(requests), - callback_(callback), - query_status_(true), - pending_requests_(0), - weak_ptr_factory_(this) {} + requests_(std::move(requests)), + callback_(std::move(callback)) {} ApplyContentProtectionTask::~ApplyContentProtectionTask() {} void ApplyContentProtectionTask::Run() { std::vector<DisplaySnapshot*> hdcp_capable_displays; if (!GetHDCPCapableDisplays(*layout_manager_, &hdcp_capable_displays)) { - callback_.Run(false); + std::move(callback_).Run(/*success=*/false); return; } pending_requests_ = hdcp_capable_displays.size(); if (pending_requests_ == 0) { - callback_.Run(true); + std::move(callback_).Run(/*success=*/true); return; } @@ -75,24 +64,24 @@ for (DisplaySnapshot* display : hdcp_capable_displays) { native_display_delegate_->GetHDCPState( *display, - base::Bind(&ApplyContentProtectionTask::OnHDCPStateUpdate, - weak_ptr_factory_.GetWeakPtr(), display->display_id())); + base::BindOnce(&ApplyContentProtectionTask::OnGetHDCPState, + weak_ptr_factory_.GetWeakPtr(), display->display_id())); } } -void ApplyContentProtectionTask::OnHDCPStateUpdate(int64_t display_id, - bool success, - HDCPState state) { - query_status_ &= success; - display_hdcp_state_map_[display_id] = state; +void ApplyContentProtectionTask::OnGetHDCPState(int64_t display_id, + bool success, + HDCPState state) { + success_ &= success; + hdcp_states_[display_id] = state; pending_requests_--; // Wait for all the requests before continuing. if (pending_requests_ != 0) return; - if (!query_status_) { - callback_.Run(false); + if (!success_) { + std::move(callback_).Run(/*success=*/false); return; } @@ -102,7 +91,7 @@ void ApplyContentProtectionTask::ApplyProtections() { std::vector<DisplaySnapshot*> hdcp_capable_displays; if (!GetHDCPCapableDisplays(*layout_manager_, &hdcp_capable_displays)) { - callback_.Run(false); + std::move(callback_).Run(/*success=*/false); return; } @@ -111,18 +100,18 @@ for (DisplaySnapshot* display : hdcp_capable_displays) { uint32_t desired_mask = GetDesiredProtectionMask(display->display_id()); - auto it = display_hdcp_state_map_.find(display->display_id()); + auto it = hdcp_states_.find(display->display_id()); // If the display can't be found, the display configuration changed. - if (it == display_hdcp_state_map_.end()) { - callback_.Run(false); + if (it == hdcp_states_.end()) { + std::move(callback_).Run(/*success=*/false); return; } bool hdcp_enabled = it->second != HDCP_STATE_UNDESIRED; bool hdcp_requested = desired_mask & CONTENT_PROTECTION_METHOD_HDCP; if (hdcp_enabled != hdcp_requested) { - hdcp_requests.push_back(std::make_pair( - display, hdcp_requested ? HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED)); + hdcp_requests.emplace_back( + display, hdcp_requested ? HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED); } } @@ -130,24 +119,24 @@ // All the requested changes are the same as the current HDCP state. Nothing // to do anymore, just ack the content protection change. if (pending_requests_ == 0) { - callback_.Run(true); + std::move(callback_).Run(/*success=*/true); return; } for (const auto& pair : hdcp_requests) { native_display_delegate_->SetHDCPState( *pair.first, pair.second, - base::Bind(&ApplyContentProtectionTask::OnHDCPStateApplied, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce(&ApplyContentProtectionTask::OnSetHDCPState, + weak_ptr_factory_.GetWeakPtr())); } } -void ApplyContentProtectionTask::OnHDCPStateApplied(bool success) { - query_status_ &= success; +void ApplyContentProtectionTask::OnSetHDCPState(bool success) { + success_ &= success; pending_requests_--; if (pending_requests_ == 0) - callback_.Run(query_status_); + std::move(callback_).Run(success_); } uint32_t ApplyContentProtectionTask::GetDesiredProtectionMask( @@ -157,7 +146,7 @@ // In non-mirror mode, only request of client's display needs to be // fulfilled. if (layout_manager_->IsMirroring()) { - for (auto pair : requests_) + for (const auto& pair : requests_) desired_mask |= pair.second; } else { auto it = requests_.find(display_id);
diff --git a/ui/display/manager/apply_content_protection_task.h b/ui/display/manager/apply_content_protection_task.h index 2d8610f..be1d902 100644 --- a/ui/display/manager/apply_content_protection_task.h +++ b/ui/display/manager/apply_content_protection_task.h
@@ -5,12 +5,10 @@ #ifndef UI_DISPLAY_MANAGER_APPLY_CONTENT_PROTECTION_TASK_H_ #define UI_DISPLAY_MANAGER_APPLY_CONTENT_PROTECTION_TASK_H_ -#include <stddef.h> -#include <stdint.h> +#include <cstddef> +#include <cstdint> -#include <map> -#include <vector> - +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "ui/display/manager/display_configurator.h" @@ -24,61 +22,47 @@ // manner: // 1) Run() // a) Query NativeDisplayDelegate for HDCP state on capable displays -// b) OnHDCPStateUpdate() called for each display as response to (a) +// b) OnGetHDCPState() called for each display as response to (a) // 2) ApplyProtections() // a) Compute preferred HDCP state for capable displays // b) Call into NativeDisplayDelegate to set HDCP state on capable displays -// c) OnHDCPStateApplied() called for each display as reponse to (b) +// c) OnSetHDCPState() called for each display as response to (b) // 3) Call |callback_| to signal end of task. // // Note, in steps 1a and 2a, if no HDCP capable displays are found or if errors // are reported, the task finishes early and skips to step 3. class DISPLAY_MANAGER_EXPORT ApplyContentProtectionTask { public: - typedef base::Callback<void(bool)> ResponseCallback; + using ResponseCallback = base::OnceCallback<void(bool success)>; - ApplyContentProtectionTask( - DisplayLayoutManager* layout_manager, - NativeDisplayDelegate* native_display_delegate, - const DisplayConfigurator::ContentProtections& requests, - const ResponseCallback& callback); + ApplyContentProtectionTask(DisplayLayoutManager* layout_manager, + NativeDisplayDelegate* native_display_delegate, + DisplayConfigurator::ContentProtections requests, + ResponseCallback callback); ~ApplyContentProtectionTask(); void Run(); private: - // Callback to NatvieDisplayDelegate::GetHDCPState() - void OnHDCPStateUpdate(int64_t display_id, bool success, HDCPState state); - - // Callback to NativeDisplayDelegate::SetHDCPState() - void OnHDCPStateApplied(bool success); + void OnGetHDCPState(int64_t display_id, bool success, HDCPState state); + void OnSetHDCPState(bool success); void ApplyProtections(); uint32_t GetDesiredProtectionMask(int64_t display_id) const; - DisplayLayoutManager* layout_manager_; // Not owned. + DisplayLayoutManager* const layout_manager_; // Not owned. + NativeDisplayDelegate* const native_display_delegate_; // Not owned. - NativeDisplayDelegate* native_display_delegate_; // Not owned. - - DisplayConfigurator::ContentProtections requests_; - - // Callback used to respond once the task finishes. + const DisplayConfigurator::ContentProtections requests_; ResponseCallback callback_; - // Mapping between display IDs and the HDCP state returned by - // NativeDisplayDelegate. - std::map<int64_t, HDCPState> display_hdcp_state_map_; + base::flat_map<int64_t /* display_id */, HDCPState> hdcp_states_; - // Tracks the status of the NativeDisplayDelegate responses. This will be true - // if all the queries were successful, false otherwise. - bool query_status_; + bool success_ = true; + size_t pending_requests_ = 0; - // Tracks the number of NativeDisplayDelegate requests sent but not answered - // yet. - size_t pending_requests_; - - base::WeakPtrFactory<ApplyContentProtectionTask> weak_ptr_factory_; + base::WeakPtrFactory<ApplyContentProtectionTask> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ApplyContentProtectionTask); };
diff --git a/ui/display/manager/apply_content_protection_task_unittest.cc b/ui/display/manager/apply_content_protection_task_unittest.cc index e63e244..294b6ea 100644 --- a/ui/display/manager/apply_content_protection_task_unittest.cc +++ b/ui/display/manager/apply_content_protection_task_unittest.cc
@@ -37,28 +37,29 @@ class ApplyContentProtectionTaskTest : public testing::Test { public: - enum Response { + enum class Response { ERROR, SUCCESS, NOT_CALLED, }; - ApplyContentProtectionTaskTest() - : response_(NOT_CALLED), display_delegate_(&log_) {} - ~ApplyContentProtectionTaskTest() override {} + ApplyContentProtectionTaskTest() = default; + ~ApplyContentProtectionTaskTest() override = default; - void ResponseCallback(bool success) { response_ = success ? SUCCESS : ERROR; } + void ResponseCallback(bool success) { + response_ = success ? Response::SUCCESS : Response::ERROR; + } protected: - Response response_; + Response response_ = Response::NOT_CALLED; ActionLogger log_; - TestNativeDisplayDelegate display_delegate_; + TestNativeDisplayDelegate display_delegate_{&log_}; private: DISALLOW_COPY_AND_ASSIGN(ApplyContentProtectionTaskTest); }; -TEST_F(ApplyContentProtectionTaskTest, ApplyWithNoHDCPCapableDisplay) { +TEST_F(ApplyContentProtectionTaskTest, ApplyHdcpToInternalDisplay) { std::vector<std::unique_ptr<DisplaySnapshot>> displays; displays.push_back( CreateDisplaySnapshot(1, DISPLAY_CONNECTION_TYPE_INTERNAL)); @@ -73,11 +74,11 @@ base::Unretained(this))); task.Run(); - EXPECT_EQ(SUCCESS, response_); + EXPECT_EQ(Response::SUCCESS, response_); EXPECT_EQ(kNoActions, log_.GetActionsAndClear()); } -TEST_F(ApplyContentProtectionTaskTest, ApplyWithHDMIDisplay) { +TEST_F(ApplyContentProtectionTaskTest, ApplyHdcpToExternalDisplay) { std::vector<std::unique_ptr<DisplaySnapshot>> displays; displays.push_back(CreateDisplaySnapshot(1, DISPLAY_CONNECTION_TYPE_HDMI)); TestDisplayLayoutManager layout_manager(std::move(displays), @@ -91,7 +92,7 @@ base::Unretained(this))); task.Run(); - EXPECT_EQ(SUCCESS, response_); + EXPECT_EQ(Response::SUCCESS, response_); EXPECT_EQ( JoinActions(GetSetHDCPStateAction(*layout_manager.GetDisplayStates()[0], HDCP_STATE_DESIRED) @@ -100,7 +101,7 @@ log_.GetActionsAndClear()); } -TEST_F(ApplyContentProtectionTaskTest, ApplyWithUnknownDisplay) { +TEST_F(ApplyContentProtectionTaskTest, ApplyHdcpToUnknownDisplay) { std::vector<std::unique_ptr<DisplaySnapshot>> displays; displays.push_back(CreateDisplaySnapshot(1, DISPLAY_CONNECTION_TYPE_UNKNOWN)); TestDisplayLayoutManager layout_manager(std::move(displays), @@ -114,11 +115,11 @@ base::Unretained(this))); task.Run(); - EXPECT_EQ(ERROR, response_); + EXPECT_EQ(Response::ERROR, response_); EXPECT_EQ(kNoActions, log_.GetActionsAndClear()); } -TEST_F(ApplyContentProtectionTaskTest, FailGettingHDCPState) { +TEST_F(ApplyContentProtectionTaskTest, ApplyHdcpToDisplayThatCannotGetHdcp) { std::vector<std::unique_ptr<DisplaySnapshot>> displays; displays.push_back(CreateDisplaySnapshot(1, DISPLAY_CONNECTION_TYPE_HDMI)); TestDisplayLayoutManager layout_manager(std::move(displays), @@ -133,11 +134,11 @@ base::Unretained(this))); task.Run(); - EXPECT_EQ(ERROR, response_); + EXPECT_EQ(Response::ERROR, response_); EXPECT_EQ(kNoActions, log_.GetActionsAndClear()); } -TEST_F(ApplyContentProtectionTaskTest, FailSettingHDCPState) { +TEST_F(ApplyContentProtectionTaskTest, ApplyHdcpToDisplayThatCannotSetHdcp) { std::vector<std::unique_ptr<DisplaySnapshot>> displays; displays.push_back(CreateDisplaySnapshot(1, DISPLAY_CONNECTION_TYPE_HDMI)); TestDisplayLayoutManager layout_manager(std::move(displays), @@ -152,7 +153,7 @@ base::Unretained(this))); task.Run(); - EXPECT_EQ(ERROR, response_); + EXPECT_EQ(Response::ERROR, response_); EXPECT_EQ( JoinActions(GetSetHDCPStateAction(*layout_manager.GetDisplayStates()[0], HDCP_STATE_DESIRED) @@ -161,7 +162,7 @@ log_.GetActionsAndClear()); } -TEST_F(ApplyContentProtectionTaskTest, ApplyNoopProtection) { +TEST_F(ApplyContentProtectionTaskTest, ApplyNoProtectionToExternalDisplay) { std::vector<std::unique_ptr<DisplaySnapshot>> displays; displays.push_back(CreateDisplaySnapshot(1, DISPLAY_CONNECTION_TYPE_HDMI)); TestDisplayLayoutManager layout_manager(std::move(displays), @@ -176,7 +177,7 @@ base::Unretained(this))); task.Run(); - EXPECT_EQ(SUCCESS, response_); + EXPECT_EQ(Response::SUCCESS, response_); EXPECT_EQ(kNoActions, log_.GetActionsAndClear()); }
diff --git a/ui/events/blink/event_with_callback.h b/ui/events/blink/event_with_callback.h index 1032ad1b..a554275 100644 --- a/ui/events/blink/event_with_callback.h +++ b/ui/events/blink/event_with_callback.h
@@ -50,7 +50,8 @@ const blink::WebInputEvent& event() const { return *event_; } blink::WebInputEvent* event_pointer() { return event_.get(); } - const LatencyInfo latency_info() const { return latency_; } + const LatencyInfo& latency_info() const { return latency_; } + LatencyInfo* mutable_latency_info() { return &latency_; } base::TimeTicks creation_timestamp() const { return creation_timestamp_; } base::TimeTicks last_coalesced_timestamp() const { return last_coalesced_timestamp_;
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index 696adc7..8aceebd 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -263,7 +263,6 @@ std::unique_ptr<EventWithCallback> event_with_callback, const base::TimeTicks now) { ui::LatencyInfo monitored_latency_info = event_with_callback->latency_info(); - std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor = input_handler_->CreateLatencyInfoSwapPromiseMonitor( &monitored_latency_info); @@ -301,12 +300,8 @@ base::TimeTicks now = tick_clock_->NowTicks(); while (!compositor_event_queue_->empty()) { std::unique_ptr<EventWithCallback> event_with_callback = - compositor_event_queue_->Pop(); - if (scroll_predictor_) { - scroll_predictor_->ResampleScrollEvents( - event_with_callback->original_events(), now, - event_with_callback->event_pointer()); - } + scroll_predictor_->ResampleScrollEvents(compositor_event_queue_->Pop(), + now); DispatchSingleInputEvent(std::move(event_with_callback), now); }
diff --git a/ui/events/blink/scroll_predictor.cc b/ui/events/blink/scroll_predictor.cc index ab396ffd..a6cca97 100644 --- a/ui/events/blink/scroll_predictor.cc +++ b/ui/events/blink/scroll_predictor.cc
@@ -55,20 +55,23 @@ } } -void ScrollPredictor::ResampleScrollEvents( - const EventWithCallback::OriginalEventList& original_events, - base::TimeTicks frame_time, - WebInputEvent* event) { +std::unique_ptr<EventWithCallback> ScrollPredictor::ResampleScrollEvents( + std::unique_ptr<EventWithCallback> event_with_callback, + base::TimeTicks frame_time) { if (!should_resample_scroll_events_) - return; + return event_with_callback; - if (event->GetType() == WebInputEvent::kGestureScrollUpdate) { + const EventWithCallback::OriginalEventList& original_events = + event_with_callback->original_events(); + + if (event_with_callback->event().GetType() == + WebInputEvent::kGestureScrollUpdate) { // TODO(eirage): When scroll events are coalesced with pinch, we can have // empty original event list. In that case, we can't use the original events // to update the prediction. We don't want to use the aggregated event to // update because of the event time stamp, so skip the prediction for now. if (original_events.empty()) - return; + return event_with_callback; TRACE_EVENT_BEGIN0("input", "ScrollPredictor::ResampleScrollEvents"); @@ -80,14 +83,18 @@ UpdatePrediction(coalesced_event.event_, frame_time); if (enable_resampling_ && should_resample_scroll_events_) - ResampleEvent(frame_time, event); + ResampleEvent(frame_time, event_with_callback->event_pointer(), + event_with_callback->mutable_latency_info()); TRACE_EVENT_END2("input", "ScrollPredictor::ResampleScrollEvents", "OriginalPosition", current_accumulated_delta_.ToString(), "PredictedPosition", last_accumulated_delta_.ToString()); - } else if (event->GetType() == WebInputEvent::kGestureScrollEnd) { + } else if (event_with_callback->event().GetType() == + WebInputEvent::kGestureScrollEnd) { should_resample_scroll_events_ = false; } + + return event_with_callback; } void ScrollPredictor::Reset() { @@ -118,7 +125,8 @@ } void ScrollPredictor::ResampleEvent(base::TimeTicks time_stamp, - WebInputEvent* event) { + WebInputEvent* event, + LatencyInfo* latency_info) { DCHECK(event->GetType() == WebInputEvent::kGestureScrollUpdate); WebGestureEvent* gesture_event = static_cast<WebGestureEvent*>(event); @@ -145,6 +153,8 @@ (new_delta.y() * gesture_event->data.scroll_update.delta_y < 0) ? 0 : new_delta.y(); + // Sync the predicted delta_y to latency_info for AverageLag metric. + latency_info->set_predicted_scroll_update_delta(new_delta.y()); last_accumulated_delta_.Offset(gesture_event->data.scroll_update.delta_x, gesture_event->data.scroll_update.delta_y);
diff --git a/ui/events/blink/scroll_predictor.h b/ui/events/blink/scroll_predictor.h index e9d7d2b..2ccc44c 100644 --- a/ui/events/blink/scroll_predictor.h +++ b/ui/events/blink/scroll_predictor.h
@@ -35,10 +35,9 @@ // Resampling GestureScrollUpdate events. Updates the prediction with events // in original events list, and apply the prediction to the aggregated GSU // event if enable_resampling is true. - void ResampleScrollEvents( - const EventWithCallback::OriginalEventList& original_events, - base::TimeTicks frame_time, - blink::WebInputEvent* event); + std::unique_ptr<EventWithCallback> ResampleScrollEvents( + std::unique_ptr<EventWithCallback> event_with_callback, + base::TimeTicks frame_time); private: friend class test::InputHandlerProxyEventQueueTest; @@ -53,7 +52,9 @@ base::TimeTicks frame_time); // Apply resampled deltaX/deltaY to gesture events - void ResampleEvent(base::TimeTicks frame_time, blink::WebInputEvent* event); + void ResampleEvent(base::TimeTicks frame_time, + blink::WebInputEvent* event, + LatencyInfo* latency_info); // Reports prediction accuracy UMA histogram. Calculates position in current // event time and compute the distance between real event and predicted event.
diff --git a/ui/events/blink/scroll_predictor_unittest.cc b/ui/events/blink/scroll_predictor_unittest.cc index 597c5bd..588c2264 100644 --- a/ui/events/blink/scroll_predictor_unittest.cc +++ b/ui/events/blink/scroll_predictor_unittest.cc
@@ -78,12 +78,18 @@ void HandleResampleScrollEvents(WebScopedInputEvent& event, double time_delta_in_milliseconds = 0) { - scroll_predictor_->ResampleScrollEvents( - original_events_, + std::unique_ptr<EventWithCallback> event_with_callback = + std::make_unique<EventWithCallback>(std::move(event), LatencyInfo(), + base::TimeTicks(), + base::NullCallback()); + event_with_callback->original_events() = std::move(original_events_); + + event_with_callback = scroll_predictor_->ResampleScrollEvents( + std::move(event_with_callback), WebInputEvent::GetStaticTimeStampForTests() + - base::TimeDelta::FromMillisecondsD(time_delta_in_milliseconds), - event.get()); - original_events_.clear(); + base::TimeDelta::FromMillisecondsD(time_delta_in_milliseconds)); + + event = WebInputEventTraits::Clone(event_with_callback->event()); } bool PredictionAvailable(ui::InputPredictor::InputData* result,
diff --git a/ui/gfx/platform_font_win.h b/ui/gfx/platform_font_win.h index e95423b..61496a3 100644 --- a/ui/gfx/platform_font_win.h +++ b/ui/gfx/platform_font_win.h
@@ -63,7 +63,6 @@ static bool IsDirectWriteEnabled(); private: - FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_UniscribeFallback); FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, Metrics_SkiaVersusGDI); FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, DirectWriteFontSubstitution); @@ -112,7 +111,6 @@ private: friend class base::RefCounted<HFontRef>; - FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_UniscribeFallback); FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, Metrics_SkiaVersusGDI); FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, DirectWriteFontSubstitution);
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index e1b63b1..bdb72e6 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -44,7 +44,6 @@ #if defined(OS_WIN) #include "base/win/windows_version.h" -#include "ui/gfx/platform_font_win.h" #endif #if defined(OS_MACOSX) @@ -4189,12 +4188,35 @@ // Ensure that the fallback fonts of the Uniscribe font are tried for shaping. #if defined(OS_WIN) TEST_F(RenderTextTest, HarfBuzz_UniscribeFallback) { + std::string font_name; + std::string localized_font_name; + + base::win::Version version = base::win::GetVersion(); + if (version < base::win::VERSION_WIN10) { + // The font 'Meiryo' exists on windows 7 and windows 8. see: + // https://docs.microsoft.com/en-us/typography/fonts/windows_7_font_list + // https://docs.microsoft.com/en-us/typography/fonts/windows_8_font_list + font_name = "Meiryo"; + // Japanese name for Meiryo. + localized_font_name = "\u30e1\u30a4\u30ea\u30aa"; + } else { + ASSERT_GE(version, base::win::VERSION_WIN10); + // The font 'Malgun Gothic' exists on windows 10. see: + // https://docs.microsoft.com/en-us/typography/fonts/windows_10_font_list + font_name = "Malgun Gothic"; + // Korean name for Malgun Gothic. + localized_font_name = "\ub9d1\uc740 \uace0\ub515"; + } + + // The localized name won't be found in the system's linked fonts, forcing + // RTHB to try the Uniscribe font and its fallbacks. RenderTextHarfBuzz* render_text = GetRenderText(); - PlatformFontWin* font_win = new PlatformFontWin("Meiryo", 12); - // Japanese name for Meiryo. This name won't be found in the system's linked - // fonts, forcing RTHB to try the Uniscribe font and its fallbacks. - font_win->font_ref_->font_name_ = "\u30e1\u30a4\u30ea\u30aa"; - FontList font_list((Font(font_win))); + Font font(localized_font_name, 12); + FontList font_list(font); + + // Ensures the font didn't got substituted. + EXPECT_NE(font.GetFontName(), font_name); + EXPECT_EQ(font.GetActualFontNameForTesting(), localized_font_name); render_text->SetFontList(font_list); // An invalid Unicode character that somehow yields Korean character "han".
diff --git a/ui/latency/average_lag_tracker.cc b/ui/latency/average_lag_tracker.cc index e1419ba..1cf21c8 100644 --- a/ui/latency/average_lag_tracker.cc +++ b/ui/latency/average_lag_tracker.cc
@@ -90,7 +90,7 @@ last_event_timestamp_ = event_timestamp; last_event_accumulated_delta_ += latency.scroll_update_delta(); - last_rendered_accumulated_delta_ += latency.scroll_update_delta(); + last_rendered_accumulated_delta_ += latency.predicted_scroll_update_delta(); } float AverageLagTracker::LagBetween(base::TimeTicks front_time,
diff --git a/ui/latency/average_lag_tracker_unittest.cc b/ui/latency/average_lag_tracker_unittest.cc index c4c34f1..a684c45 100644 --- a/ui/latency/average_lag_tracker_unittest.cc +++ b/ui/latency/average_lag_tracker_unittest.cc
@@ -30,9 +30,13 @@ void SyntheticTouchScrollBeginLatencyInfo(base::TimeTicks event_time, base::TimeTicks frame_time, - float delta) { + float delta, + float predicted_delta = 0) { ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); touch_latency.set_scroll_update_delta(delta); + touch_latency.set_predicted_scroll_update_delta( + predicted_delta != 0 ? predicted_delta : delta); + touch_latency.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, event_time, 1); @@ -45,9 +49,12 @@ void SyntheticTouchScrollUpdateLatencyInfo(base::TimeTicks event_time, base::TimeTicks frame_time, - float delta) { + float delta, + float predicted_delta = 0) { ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); touch_latency.set_scroll_update_delta(delta); + touch_latency.set_predicted_scroll_update_delta( + predicted_delta != 0 ? predicted_delta : delta); touch_latency.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, event_time, 1); @@ -244,5 +251,125 @@ ElementsAre(Bucket(12, 1))); } +// A simple case without scroll prediction to compare with the two with +// prediction cases below. +TEST_F(AverageLagTrackerTest, NoScrollPrediction) { + // ScrollBegin, at t=5, finter_pos=5px. + base::TimeTicks event_time = MillisecondsToTimeTicks(5); + base::TimeTicks frame_time = MillisecondsToTimeTicks(10); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, + 5 /* scroll_delta */); + + // ScrollUpdate, at t=15, finger_pos=15px. + event_time = MillisecondsToTimeTicks(15); + frame_time = MillisecondsToTimeTicks(20); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + 10 /* scroll_delta */); + + // ScrollUpdate, at t=25, finger_pos=25px. + event_time = MillisecondsToTimeTicks(25); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + 10 /* scroll_delta */); + + // Another ScrollBegin to flush unfinished frames. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, 0); + + // Prediction hasn't take affect on ScrollBegin so it'll stay the same. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(7, 1))); + // At t=10, finger_pos = 10px, rendered_pos = 5px. + // At t=20, finger_pos = 20px, rendered_pos = 15px. + // At t=30, finger_pos = 25px, rendered_pos = 25px. + // AverageLag = ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms + // = 9.375 + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(9, 1))); +} + +// Test AverageLag with perfect scroll prediction. +TEST_F(AverageLagTrackerTest, ScrollPrediction) { + // ScrollBegin, at t=5, finter_pos=5px. + // Predict frame_time=10, predicted_pos = 10px. + base::TimeTicks event_time = MillisecondsToTimeTicks(5); + base::TimeTicks frame_time = MillisecondsToTimeTicks(10); + SyntheticTouchScrollBeginLatencyInfo( + event_time, frame_time, 5 /* scroll_delta */, 10 /* predicted_delta */); + + // ScrollUpdate, at t=15, finger_pos=15px. + // Predict frame_time=20, predicted_pos = 20px. + event_time = MillisecondsToTimeTicks(15); + frame_time = MillisecondsToTimeTicks(20); + SyntheticTouchScrollUpdateLatencyInfo( + event_time, frame_time, 10 /* scroll_delta */, 10 /* predicted_delta */); + + // ScrollUpdate, at t=25, finger_pos=25px. + // Predict frame_time=30, predicted_pos = 30px. + event_time = MillisecondsToTimeTicks(25); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo( + event_time, frame_time, 10 /* scroll_delta */, 10 /* predicted_delta */); + + // Another ScrollBegin to flush unfinished frames. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, 0); + + // Prediction hasn't take affect on ScrollBegin so it'll stay the same. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(7, 1))); + // At t=10, finger_pos = 10px, rendered_pos = 10px. + // At t=20, finger_pos = 20px, rendered_pos = 20px. + // At t=30, finger_pos = 25px, rendered_pos = 30px. + // AverageLag = ((0px+10px)*10ms/2 + (0px+5px)*10ms/2 + 5px*5ms)/20ms + // = 4.375px + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(4, 1))); +} + +// Test AverageLag with imperfect scroll prediction. +TEST_F(AverageLagTrackerTest, ImperfectScrollPrediction) { + // ScrollBegin, at t=5, finter_pos=5px. + // Predict frame_time=10, predicted_pos(over) = 12px. + base::TimeTicks event_time = MillisecondsToTimeTicks(5); + base::TimeTicks frame_time = MillisecondsToTimeTicks(10); + SyntheticTouchScrollBeginLatencyInfo( + event_time, frame_time, 5 /* scroll_delta */, 12 /* predicted_delta */); + + // ScrollUpdate, at t=15, finger_pos=15px. + // Predict frame_time=20, predicted_pos(under) = 17px. + event_time = MillisecondsToTimeTicks(15); + frame_time = MillisecondsToTimeTicks(20); + SyntheticTouchScrollUpdateLatencyInfo( + event_time, frame_time, 10 /* scroll_delta */, 5 /* predicted_delta */); + + // ScrollUpdate, at t=25, finger_pos=25px. + // Predict frame_time=30, predicted_pos(over) = 31px. + event_time = MillisecondsToTimeTicks(25); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo( + event_time, frame_time, 10 /* scroll_delta */, 14 /* predicted_delta */); + + // Another ScrollBegin to flush unfinished frames. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, 0); + + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(7, 1))); + // AverageLag = ((2px*2ms/2+8px*8ms/2)+ ((3px+8px)*5ms/2+8px*5ms))/20ms + // = 5.075px + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(5, 1))); +} + } // namespace } // namespace ui
diff --git a/ui/latency/ipc/latency_info_param_traits.cc b/ui/latency/ipc/latency_info_param_traits.cc index 5aceb85f..d963612 100644 --- a/ui/latency/ipc/latency_info_param_traits.cc +++ b/ui/latency/ipc/latency_info_param_traits.cc
@@ -41,6 +41,7 @@ WriteParam(m, p.terminated_); WriteParam(m, p.source_event_type_); WriteParam(m, p.scroll_update_delta_); + WriteParam(m, p.predicted_scroll_update_delta_); } bool ParamTraits<ui::LatencyInfo>::Read(const base::Pickle* m, @@ -65,6 +66,8 @@ return false; if (!ReadParam(m, iter, &p->scroll_update_delta_)) return false; + if (!ReadParam(m, iter, &p->predicted_scroll_update_delta_)) + return false; return true; } @@ -87,6 +90,8 @@ LogParam(p.source_event_type_, l); l->append(" "); LogParam(p.scroll_update_delta_, l); + l->append(" "); + LogParam(p.predicted_scroll_update_delta_, l); } } // namespace IPC
diff --git a/ui/latency/ipc/latency_info_param_traits_unittest.cc b/ui/latency/ipc/latency_info_param_traits_unittest.cc index b31706c..b133ed4 100644 --- a/ui/latency/ipc/latency_info_param_traits_unittest.cc +++ b/ui/latency/ipc/latency_info_param_traits_unittest.cc
@@ -18,6 +18,7 @@ latency.set_trace_id(5); latency.set_ukm_source_id(10); latency.set_scroll_update_delta(12.5); + latency.set_predicted_scroll_update_delta(12.5); ASSERT_FALSE(latency.terminated()); latency.AddLatencyNumber(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT); latency.AddLatencyNumber(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT); @@ -37,6 +38,8 @@ EXPECT_EQ(latency.ukm_source_id(), output.ukm_source_id()); EXPECT_EQ(latency.terminated(), output.terminated()); EXPECT_EQ(latency.scroll_update_delta(), output.scroll_update_delta()); + EXPECT_EQ(latency.predicted_scroll_update_delta(), + output.predicted_scroll_update_delta()); EXPECT_TRUE(output.FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
diff --git a/ui/latency/latency_info.cc b/ui/latency/latency_info.cc index fd7e1fd..96f6660 100644 --- a/ui/latency/latency_info.cc +++ b/ui/latency/latency_info.cc
@@ -126,7 +126,8 @@ began_(false), terminated_(false), source_event_type_(type), - scroll_update_delta_(0) {} + scroll_update_delta_(0), + predicted_scroll_update_delta_(0) {} LatencyInfo::LatencyInfo(const LatencyInfo& other) = default; @@ -139,7 +140,8 @@ began_(false), terminated_(terminated), source_event_type_(SourceEventType::UNKNOWN), - scroll_update_delta_(0) {} + scroll_update_delta_(0), + predicted_scroll_update_delta_(0) {} bool LatencyInfo::Verify(const std::vector<LatencyInfo>& latency_info, const char* referring_msg) { @@ -325,6 +327,15 @@ } scroll_update_delta_ += other.scroll_update_delta(); + predicted_scroll_update_delta_ += other.predicted_scroll_update_delta(); +} + +LatencyInfo LatencyInfo::ScaledBy(float scale) const { + ui::LatencyInfo scaled_latency_info(*this); + scaled_latency_info.set_scroll_update_delta(scroll_update_delta_ * scale); + scaled_latency_info.set_predicted_scroll_update_delta( + predicted_scroll_update_delta_ * scale); + return scaled_latency_info; } std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/ui/latency/latency_info.h b/ui/latency/latency_info.h index 91b3f91c..ab134cb9 100644 --- a/ui/latency/latency_info.h +++ b/ui/latency/latency_info.h
@@ -174,6 +174,9 @@ // event's scroll_update_delta and the SCROLL_UPDATE_LAST_EVENT_COMPONENT. void CoalesceScrollUpdateWith(const LatencyInfo& other); + // Scale scroll_update_delta and predicted_scroll_update_delta. + LatencyInfo ScaledBy(float scale) const; + const LatencyMap& latency_components() const { return latency_components_; } const SourceEventType& source_event_type() const { @@ -194,6 +197,12 @@ const std::string& trace_name() const { return trace_name_; } void set_scroll_update_delta(float delta) { scroll_update_delta_ = delta; } float scroll_update_delta() const { return scroll_update_delta_; } + void set_predicted_scroll_update_delta(float delta) { + predicted_scroll_update_delta_ = delta; + } + float predicted_scroll_update_delta() const { + return predicted_scroll_update_delta_; + } private: void AddLatencyNumberWithTimestampImpl(LatencyComponentType component, @@ -226,6 +235,7 @@ SourceEventType source_event_type_; float scroll_update_delta_; + float predicted_scroll_update_delta_; #if !defined(OS_IOS) friend struct IPC::ParamTraits<ui::LatencyInfo>;
diff --git a/ui/latency/mojo/latency_info.mojom b/ui/latency/mojo/latency_info.mojom index da021bd..87f8e09 100644 --- a/ui/latency/mojo/latency_info.mojom +++ b/ui/latency/mojo/latency_info.mojom
@@ -82,4 +82,5 @@ bool terminated; SourceEventType source_event_type; float scroll_update_delta; + float predicted_scroll_update_delta; };
diff --git a/ui/latency/mojo/latency_info_struct_traits.cc b/ui/latency/mojo/latency_info_struct_traits.cc index 2ca2451..624c8f34 100644 --- a/ui/latency/mojo/latency_info_struct_traits.cc +++ b/ui/latency/mojo/latency_info_struct_traits.cc
@@ -122,6 +122,12 @@ } // static +float StructTraits<ui::mojom::LatencyInfoDataView, ui::LatencyInfo>:: + predicted_scroll_update_delta(const ui::LatencyInfo& info) { + return info.predicted_scroll_update_delta(); +} + +// static bool StructTraits<ui::mojom::LatencyInfoDataView, ui::LatencyInfo>::Read( ui::mojom::LatencyInfoDataView data, ui::LatencyInfo* out) { @@ -136,6 +142,7 @@ out->terminated_ = data.terminated(); out->source_event_type_ = MojoSourceEventTypeToUI(data.source_event_type()); out->scroll_update_delta_ = data.scroll_update_delta(); + out->predicted_scroll_update_delta_ = data.predicted_scroll_update_delta(); return true; }
diff --git a/ui/latency/mojo/latency_info_struct_traits.h b/ui/latency/mojo/latency_info_struct_traits.h index 5844fec..e5afdf5 100644 --- a/ui/latency/mojo/latency_info_struct_traits.h +++ b/ui/latency/mojo/latency_info_struct_traits.h
@@ -55,6 +55,7 @@ static ui::mojom::SourceEventType source_event_type( const ui::LatencyInfo& info); static float scroll_update_delta(const ui::LatencyInfo& info); + static float predicted_scroll_update_delta(const ui::LatencyInfo& info); static bool Read(ui::mojom::LatencyInfoDataView data, ui::LatencyInfo* out); };
diff --git a/ui/native_theme/native_theme_mac.h b/ui/native_theme/native_theme_mac.h index 0076b510..3605eae 100644 --- a/ui/native_theme/native_theme_mac.h +++ b/ui/native_theme/native_theme_mac.h
@@ -70,6 +70,9 @@ bool round_right, bool focus); + // Updates cached dark mode status and notifies observers if it has changed. + void UpdateDarkModeStatus(); + protected: friend class NativeTheme; friend class base::NoDestructor<NativeThemeMac>; @@ -88,6 +91,8 @@ appearance_observer_; id high_contrast_notification_token_; + bool is_dark_mode_ = false; + DISALLOW_COPY_AND_ASSIGN(NativeThemeMac); };
diff --git a/ui/native_theme/native_theme_mac.mm b/ui/native_theme/native_theme_mac.mm index de3389f..6246830 100644 --- a/ui/native_theme/native_theme_mac.mm +++ b/ui/native_theme/native_theme_mac.mm
@@ -19,6 +19,21 @@ #include "ui/gfx/skia_util.h" #include "ui/native_theme/common_theme.h" +namespace { + +bool IsDarkMode() { + if (@available(macOS 10.14, *)) { + NSAppearanceName appearance = + [[NSApp effectiveAppearance] bestMatchFromAppearancesWithNames:@[ + NSAppearanceNameAqua, NSAppearanceNameDarkAqua + ]]; + return [appearance isEqual:NSAppearanceNameDarkAqua]; + } + + return false; +} +} // namespace + @interface NSWorkspace (Redeclarations) @property(readonly) BOOL accessibilityDisplayShouldIncreaseContrast; @@ -29,11 +44,14 @@ @interface NativeThemeEffectiveAppearanceObserver : NSObject @end -@implementation NativeThemeEffectiveAppearanceObserver +@implementation NativeThemeEffectiveAppearanceObserver { + ui::NativeThemeMac* owner_; +} -- (instancetype)init { +- (instancetype)initWithOwner:(ui::NativeThemeMac*)owner { self = [super init]; if (self) { + owner_ = owner; if (@available(macOS 10.14, *)) { [NSApp addObserver:self forKeyPath:@"effectiveAppearance" @@ -55,7 +73,7 @@ ofObject:(id)object change:(NSDictionary*)change context:(void*)context { - ui::NativeTheme::GetInstanceForNativeUi()->NotifyObservers(); + owner_->UpdateDarkModeStatus(); } @end @@ -262,19 +280,18 @@ bool NativeThemeMac::SystemDarkModeEnabled() const { if (@available(macOS 10.14, *)) { - NSAppearanceName appearance = - [[NSApp effectiveAppearance] bestMatchFromAppearancesWithNames:@[ - NSAppearanceNameAqua, NSAppearanceNameDarkAqua - ]]; - return [appearance isEqual:NSAppearanceNameDarkAqua]; + return is_dark_mode_; + } else { + // Support "--force-dark-mode" in macOS < 10.14. + return NativeThemeBase::SystemDarkModeEnabled(); } - return NativeThemeBase::SystemDarkModeEnabled(); } NativeThemeMac::NativeThemeMac() { if (base::FeatureList::IsEnabled(features::kDarkMode)) { + is_dark_mode_ = IsDarkMode(); appearance_observer_.reset( - [[NativeThemeEffectiveAppearanceObserver alloc] init]); + [[NativeThemeEffectiveAppearanceObserver alloc] initWithOwner:this]); } if (@available(macOS 10.10, *)) { high_contrast_notification_token_ = [[[NSWorkspace sharedWorkspace] @@ -302,4 +319,11 @@ canvas->drawRect(gfx::RectToSkRect(rect), flags); } +void NativeThemeMac::UpdateDarkModeStatus() { + bool was_dark_mode = is_dark_mode_; + is_dark_mode_ = IsDarkMode(); + if (was_dark_mode != is_dark_mode_) + NotifyObservers(); +} + } // namespace ui
diff --git a/ui/views_bridge_mac/bridged_content_view.mm b/ui/views_bridge_mac/bridged_content_view.mm index 345b110..2c04b9b 100644 --- a/ui/views_bridge_mac/bridged_content_view.mm +++ b/ui/views_bridge_mac/bridged_content_view.mm
@@ -568,15 +568,29 @@ // NSView implementation. -// This view must consistently return YES or else dragging a tab may drag the -// entire window. See r549802 for details. +// Refuse first responder so that clicking a blank area of the view don't take +// first responder away from another view. This does not prevent the view +// becoming first responder via -[NSWindow makeFirstResponder:] when invoked +// during Init or by FocusManager. +// +// The condition is to work around an AppKit quirk. When a window is being +// ordered front, if its current first responder returns |NO| for this method, +// it resigns it if it can find another responder in the key loop that replies +// |YES|. - (BOOL)acceptsFirstResponder { - return YES; + return self.window.firstResponder == self; +} + +// This undocumented method determines which parts of the view prevent +// server-side window dragging (i.e. aren't draggable without asking the app +// first). Since Views decides click-by-click whether to handle an event, the +// whole view is off limits but, since the view's content is rendered out of +// process and the view is locally transparent, AppKit won't guess that. +- (NSRect)_opaqueRectForWindowMoveWhenInTitlebar { + return self.bounds; } - (BOOL)becomeFirstResponder { - if ([[self window] firstResponder] != self) - return NO; BOOL result = [super becomeFirstResponder]; if (result && bridge_) bridge_->host()->OnIsFirstResponderChanged(true);