diff --git a/DEPS b/DEPS index 5153173..31513e6f 100644 --- a/DEPS +++ b/DEPS
@@ -124,7 +124,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '5f01324fb627a502823d9e359d243c3430920258', + 'angle_revision': '471358f39a6a53b97575f0074f466892babd8efc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -172,7 +172,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'eee0f6ad0df532b4ba3eee2bf04a5a155817586c', + 'catapult_revision': 'b88aa2d8ba8e67124bac06ab296251420767d636', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -192,31 +192,31 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version # and whatever else without interference from each other. - 'android_sdk_build-tools_version': 'version:27.0.3-cr0', + 'android_sdk_build-tools_version': '125a2abaa0393cd68a2414ec79e514d5d0a80b58', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_emulator_version # and whatever else without interference from each other. - 'android_sdk_emulator_version': 'version:27.1.12-cr0', + 'android_sdk_emulator_version': '731059df93885359487fd9d6085bc7804a23f9c8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_extras_version # and whatever else without interference from each other. - 'android_sdk_extras_version': 'version:47.0.0-cr0', + 'android_sdk_extras_version': '2f33032ef348e2ff37d90d53563f4cb030a879bf', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_platform-tools_version # and whatever else without interference from each other. - 'android_sdk_platform-tools_version': 'version:27.0.1-cr0', + 'android_sdk_platform-tools_version': '7f31093ac2fc930abadb3bf65fc0a663a22cd6dc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_platforms_version # and whatever else without interference from each other. - 'android_sdk_platforms_version': 'version:android-27-cr0', + 'android_sdk_platforms_version': '6a79b931523181e147ddfc7db318bf0b2e34edb5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_sources_version # and whatever else without interference from each other. - 'android_sdk_sources_version': 'version:android-27-cr1', + 'android_sdk_sources_version': '8d8bd74d8f062449b8c44a663cc38a33ddf96752', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_tools_version # and whatever else without interference from each other. - 'android_sdk_tools_version': 'version:26.1.1-cr9', + 'android_sdk_tools_version': '1a659d51804abb9461cd19aeffc2102e47a15a25', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -236,7 +236,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '813bfbd061128113dd7b4c7c80321b536597c362', + 'dawn_revision': 'df72914a60d570678b60ccc2e23b2ff13396f218', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -263,7 +263,7 @@ 'packages': [ { 'package': 'chromium/android_webview/tools/cts_archive', - 'version': 'version:1.1', + 'version': '3JR1LoM5xpNK_jcnwciobRW9H8TM3SUxuSGQJBjt6AUC', }, ], 'condition': 'checkout_android', @@ -288,7 +288,7 @@ 'packages': [ { 'package': 'chromium/chrome/test/data/safe_browsing/dmg', - 'version': 'version:20180816.2', + 'version': 'a543ae3f0b3e67dd5a1c75f63317231a1d242912', }, ], 'condition': 'checkout_mac', @@ -325,7 +325,7 @@ 'packages': [ { 'package': 'chromium/third_party/firebase_ios', - 'version': 'version:5.8.0', + 'version': 'b44315eefb889f856af131d487cc61b46a78777b', }, ], 'condition': 'checkout_ios', @@ -442,7 +442,7 @@ 'packages': [ { 'package': 'chromium/third_party/accessibility-test-framework', - 'version': 'version:2.1-cr0', + 'version': 'b5ec1e56e58e56bc1a0c77d43111c37f9b512c8a', }, ], 'condition': 'checkout_android', @@ -463,7 +463,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_support_test_runner', - 'version': 'version:0.5-cr0', + 'version': '96d4bf848cd210fdcbca6bcc8c1b4b39cbd93141', }, ], 'condition': 'checkout_android', @@ -474,7 +474,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_system_sdk', - 'version': 'version:28-dp3-cr0', + 'version': '0c0a94a9326c045c8aabb7fc418ea9c849b782f2', }, ], 'condition': 'checkout_android', @@ -490,7 +490,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/aapt2', - 'version': 'version:3.3.0-beta01-5013011-cr0', + 'version': 'XPNW95mgY7ws_5lNsyjlq7DowuughMNsRIGuGCT0basC', }, ], 'condition': 'checkout_android', @@ -512,7 +512,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_tools_bundletool', - 'version': 'version:0.7.1-cr0', + 'version': 'bSpsD5lu4IO9FkDBSyjPNU2yibLq89K25354Hx8Ak-QC', }, ], 'condition': 'checkout_android', @@ -579,7 +579,7 @@ 'packages': [ { 'package': 'chromium/third_party/apk-patch-size-estimator', - 'version': 'version:0.2-cr0', + 'version': 'b603e99dca9b90d6a99519c232cd811878283b08', }, ], 'condition': 'checkout_android', @@ -595,7 +595,7 @@ 'packages': [ { 'package': 'chromium/third_party/bazel', - 'version': 'version:0.10.0', + 'version': '1794576f65a721eb0af320a0701e48d31f1b2415', }, ], 'condition': 'checkout_android', @@ -617,7 +617,7 @@ 'packages': [ { 'package': 'chromium/third_party/bouncycastle', - 'version': 'version:1.46-cr0', + 'version': 'c078e87552ba26e776566fdaf0f22cd8712743d0', }, ], 'condition': 'checkout_android', @@ -631,7 +631,7 @@ 'packages': [ { 'package': 'chromium/third_party/byte_buddy', - 'version': 'version:1.8.8-cr0', + 'version': 'c9b53316603fc2d997c899c7ca1707f809b918cd', }, ], 'condition': 'checkout_android', @@ -642,7 +642,7 @@ Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'), 'src/third_party/cct_dynamic_module/src': { - 'url': Var('chromium_git') + '/dynamicmodule' + '@' + 'b5a34248be7ff38ef4d7836123f3c796dfb18225', + 'url': Var('chromium_git') + '/dynamicmodule' + '@' + '4c0a460459bc34177d3a71d6b49e253476431ec9', 'condition': 'checkout_android', }, @@ -651,7 +651,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '81cbcd45e1a28db58d86bb556e1c40a289f35ef9', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '97b903782cf522254f3a531cc05bcba0da721028', 'condition': 'checkout_linux', }, @@ -698,7 +698,7 @@ 'packages': [ { 'package': 'chromium/third_party/espresso', - 'version': 'version:2.2.1-cr0', + 'version': 'c92dcfc4e894555a0b3c309f2b7939640eb1fee4', }, ], 'condition': 'checkout_android', @@ -749,7 +749,7 @@ 'packages': [ { 'package': 'chromium/third_party/google-truth', - 'version': 'version:0.40', + 'version': '4d6fe892fc3150ab40ef1d619baf0038859eb6d2', }, ], 'condition': 'checkout_android', @@ -774,7 +774,7 @@ 'packages': [ { 'package': 'chromium/third_party/gson', - 'version': 'version:2.8.0-cr0', + 'version': '681931c9778045903a0ed59856ce2dd8dd7bf7ca', }, ], 'condition': 'checkout_android', @@ -785,7 +785,7 @@ 'packages': [ { 'package': 'chromium/third_party/guava', - 'version': 'version:23.0-cr0', + 'version': 'a6fba501f3a0de88b9be1daa2052632de5b96a46', }, ], 'condition': 'checkout_android', @@ -806,7 +806,7 @@ 'packages': [ { 'package': 'chromium/third_party/hamcrest', - 'version': 'version:1.3-cr0', + 'version': '37eccfc658fe79695d6abb6dd497463c4372032f', }, ], 'condition': 'checkout_android', @@ -823,7 +823,7 @@ 'packages': [ { 'package': 'chromium/third_party/icu4j', - 'version': 'version:53.1-cr0', + 'version': 'e87e5bed2b4935913ee26a3ebd0b723ee2344354', }, ], 'condition': 'checkout_android', @@ -834,7 +834,7 @@ 'packages': [ { 'package': 'chromium/third_party/intellij', - 'version': 'version:12.0-cr0', + 'version': '77c2721b024b36ee073402c08e6d8428c0295336', }, ], 'condition': 'checkout_android', @@ -974,7 +974,7 @@ 'packages': [ { 'package': 'chromium/third_party/objenesis', - 'version': 'version:2.4-cr0', + 'version': '9e367f55e5a65781ee77bfcbaa88fb82b30e75c0', }, ], 'condition': 'checkout_android', @@ -991,7 +991,7 @@ 'packages': [ { 'package': 'chromium/third_party/ow2_asm', - 'version': 'version:5.0.1-cr0', + 'version': '0dcaea8bd839b3f2eb8415c327b40e8e398a373e', }, ], 'condition': 'checkout_android', @@ -1125,7 +1125,7 @@ 'packages': [ { 'package': 'chromium/third_party/sqlite4java', - 'version': 'version:0.282-cr0', + 'version': '889660698187baa7c8b0d79f7bf58563125fbd66', }, ], 'condition': 'checkout_android', @@ -1182,7 +1182,7 @@ 'packages': [ { 'package': 'chromium/third_party/xstream', - 'version': 'version:1.4.8-cr0', + 'version': '4278b1b78b86ab7a1a29e64d5aec9a47a9aab0fe', }, ], 'condition': 'checkout_android', @@ -1202,7 +1202,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@73b3bde2659f52e891abf622a706feed5dfce112', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9dbf638d6f752c059861c913e202fbdd8fbd2f9a', 'condition': 'checkout_src_internal', }, @@ -1210,7 +1210,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_play_core_verification', - 'version': 'version:1.3.7-cr0', + 'version': 'CMX_sCQTYt-Pj3-xFaCMPNGK3TjVMfToP2glkNm1a4AC', }, ], 'condition': 'checkout_android',
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 5302d57c..535f0b9 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -3,8 +3,8 @@ # found in the LICENSE file. import("//android_webview/system_webview_apk_tmpl.gni") -import("//android_webview/webview_repack_locales.gni") import("//android_webview/variables.gni") +import("//android_webview/webview_repack_locales.gni") import("//build/config/android/chrome_version.gni") import("//build/config/android/config.gni") import("//build/config/android/rules.gni") @@ -852,6 +852,7 @@ "java/src/org/chromium/android_webview/AwDevToolsServer.java", "java/src/org/chromium/android_webview/AwFeatureList.java", "java/src/org/chromium/android_webview/AwFormDatabase.java", + "java/src/org/chromium/android_webview/AwFunctor.java", "java/src/org/chromium/android_webview/AwGeolocationPermissions.java", "java/src/org/chromium/android_webview/AwGLFunctor.java", "java/src/org/chromium/android_webview/AwHttpAuthHandler.java",
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc index 1b30da5a..021e475d 100644 --- a/android_webview/browser/aw_contents.cc +++ b/android_webview/browser/aw_contents.cc
@@ -112,6 +112,8 @@ namespace android_webview { +class CompositorFrameConsumer; + namespace { bool g_should_download_favicons = false; @@ -378,7 +380,7 @@ base::MemoryPressureListener::NotifyMemoryPressure( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); } - SetAwGLFunctor(nullptr); + browser_view_renderer_.SetCurrentCompositorFrameConsumer(nullptr); AwContentsLifecycleNotifier::OnWebViewDestroyed(); } @@ -393,15 +395,12 @@ return web_contents_->GetJavaWebContents(); } -void AwContents::SetAwGLFunctor(AwGLFunctor* functor) { +void AwContents::SetCompositorFrameConsumer( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + jlong compositor_frame_consumer) { browser_view_renderer_.SetCurrentCompositorFrameConsumer( - functor ? functor->GetCompositorFrameConsumer() : nullptr); -} - -void AwContents::SetAwGLFunctor(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - jlong gl_functor) { - SetAwGLFunctor(reinterpret_cast<AwGLFunctor*>(gl_functor)); + reinterpret_cast<CompositorFrameConsumer*>(compositor_frame_consumer)); } ScopedJavaLocalRef<jobject> AwContents::GetRenderProcess(
diff --git a/android_webview/browser/aw_contents.h b/android_webview/browser/aw_contents.h index c623fc5..1d7e579 100644 --- a/android_webview/browser/aw_contents.h +++ b/android_webview/browser/aw_contents.h
@@ -39,7 +39,6 @@ namespace android_webview { class AwContentsClientBridge; -class AwGLFunctor; class AwPdfExporter; class AwWebContentsDelegate; class PermissionRequestHandler; @@ -103,9 +102,10 @@ base::android::ScopedJavaLocalRef<jobject> GetWebContents( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); - void SetAwGLFunctor(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - jlong gl_functor); + void SetCompositorFrameConsumer( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + jlong compositor_frame_consumer); base::android::ScopedJavaLocalRef<jobject> GetRenderProcess( JNIEnv* env, @@ -374,8 +374,6 @@ void SetDipScaleInternal(float dip_scale); - void SetAwGLFunctor(AwGLFunctor* functor); - JavaObjectWeakGlobalRef java_ref_; BrowserViewRenderer browser_view_renderer_; // Must outlive |web_contents_|. std::unique_ptr<content::WebContents> web_contents_;
diff --git a/android_webview/browser/aw_gl_functor.cc b/android_webview/browser/aw_gl_functor.cc index ac39690..a306d495 100644 --- a/android_webview/browser/aw_gl_functor.cc +++ b/android_webview/browser/aw_gl_functor.cc
@@ -85,6 +85,13 @@ return reinterpret_cast<intptr_t>(&render_thread_manager_); } +jlong AwGLFunctor::GetCompositorFrameConsumer( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return reinterpret_cast<intptr_t>(GetCompositorFrameConsumer()); +} + static jint JNI_AwGLFunctor_GetNativeInstanceCount( JNIEnv* env, const JavaParamRef<jclass>&) {
diff --git a/android_webview/browser/aw_gl_functor.h b/android_webview/browser/aw_gl_functor.h index 699474b..12816fd0 100644 --- a/android_webview/browser/aw_gl_functor.h +++ b/android_webview/browser/aw_gl_functor.h
@@ -25,14 +25,17 @@ const base::android::JavaParamRef<jobject>& obj); jlong GetAwDrawGLViewContext(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); + jlong GetCompositorFrameConsumer( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); jlong GetAwDrawGLFunction(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); + private: CompositorFrameConsumer* GetCompositorFrameConsumer() { return &render_thread_manager_; } - private: JavaObjectWeakGlobalRef java_ref_; RenderThreadManager render_thread_manager_; };
diff --git a/android_webview/browser/state_serializer.cc b/android_webview/browser/state_serializer.cc index 9a4289b3f..49caeb3e 100644 --- a/android_webview/browser/state_serializer.cc +++ b/android_webview/browser/state_serializer.cc
@@ -35,8 +35,7 @@ } // namespace -void WriteToPickle(const content::WebContents& web_contents, - base::Pickle* pickle) { +void WriteToPickle(content::WebContents& web_contents, base::Pickle* pickle) { DCHECK(pickle); internal::WriteHeaderToPickle(pickle);
diff --git a/android_webview/browser/state_serializer.h b/android_webview/browser/state_serializer.h index a07bbd2..7a3f1a0 100644 --- a/android_webview/browser/state_serializer.h +++ b/android_webview/browser/state_serializer.h
@@ -29,8 +29,7 @@ // success. // Note that |pickle| may be changed even if function returns false. -void WriteToPickle(const content::WebContents& web_contents, - base::Pickle* pickle); +void WriteToPickle(content::WebContents& web_contents, base::Pickle* pickle); // |web_contents| will not be modified if function returns false. bool RestoreFromPickle(base::PickleIterator* iterator,
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index dcf13c8..01b40e2 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -343,7 +343,7 @@ private long mNativeAwContents; private final AwBrowserContext mBrowserContext; private ViewGroup mContainerView; - private AwGLFunctor mDrawFunctor; + private AwFunctor mDrawFunctor; private final Context mContext; private final int mAppTargetSdkVersion; private AwViewAndroidDelegate mViewAndroidDelegate; @@ -778,7 +778,7 @@ if (isDestroyedOrNoOperation(NO_WARN)) return; if (level >= TRIM_MEMORY_MODERATE) { if (mDrawFunctor != null) { - mDrawFunctor.deleteHardwareRenderer(); + mDrawFunctor.trimMemory(); } } nativeTrimMemory(mNativeAwContents, level, visible); @@ -1145,18 +1145,18 @@ } } - private void setFunctor(AwGLFunctor functor) { + private void setFunctor(AwFunctor functor) { if (mDrawFunctor == functor) return; - AwGLFunctor oldFunctor = mDrawFunctor; + AwFunctor oldFunctor = mDrawFunctor; mDrawFunctor = functor; updateNativeAwGLFunctor(); - if (oldFunctor != null) oldFunctor.releasedByContents(); + if (oldFunctor != null) oldFunctor.destroy(); } private void updateNativeAwGLFunctor() { - nativeSetAwGLFunctor( - mNativeAwContents, mDrawFunctor != null ? mDrawFunctor.getNativeAwGLFunctor() : 0); + nativeSetCompositorFrameConsumer(mNativeAwContents, + mDrawFunctor != null ? mDrawFunctor.getNativeCompositorFrameConsumer() : 0); } /* Common initialization routine for adopting a native AwContents instance into this @@ -3376,7 +3376,7 @@ // Only valid within software onDraw(). private final Rect mClipBoundsTemporary = new Rect(); - @SuppressLint("DrawAllocation") // For new AwGLFunctor. + @SuppressLint("DrawAllocation") // For new AwFunctor. @Override public void onDraw(Canvas canvas) { if (isDestroyedOrNoOperation(NO_WARN)) { @@ -3426,7 +3426,7 @@ } if (did_draw && canvas.isHardwareAccelerated() && !ForceAuxiliaryBitmapRendering.sResult) { - did_draw = mDrawFunctor.requestDrawGL(canvas); + did_draw = mDrawFunctor.requestDraw(canvas); } if (did_draw) { int scrollXDiff = mContainerView.getScrollX() - scrollX; @@ -3773,7 +3773,8 @@ InterceptNavigationDelegate navigationInterceptionDelegate, AutofillProvider autofillProvider); private native WebContents nativeGetWebContents(long nativeAwContents); - private native void nativeSetAwGLFunctor(long nativeAwContents, long nativeAwGLFunctor); + private native void nativeSetCompositorFrameConsumer( + long nativeAwContents, long nativeCompositorFrameConsumer); private native void nativeDocumentHasImages(long nativeAwContents, Message message); private native void nativeGenerateMHTML(
diff --git a/android_webview/java/src/org/chromium/android_webview/AwFunctor.java b/android_webview/java/src/org/chromium/android_webview/AwFunctor.java new file mode 100644 index 0000000..16aebf0 --- /dev/null +++ b/android_webview/java/src/org/chromium/android_webview/AwFunctor.java
@@ -0,0 +1,25 @@ +// 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. + +package org.chromium.android_webview; + +import android.graphics.Canvas; + +/** + * Interface for functor implementation. This allows client to avoid differentiating between GL and + * Vulkan implementations. + */ +public interface AwFunctor { + /** Insert draw functor into recording canvas */ + boolean requestDraw(Canvas canvas); + + /** Return the raw native pointer to CompositorFrameConsumer */ + long getNativeCompositorFrameConsumer(); + + /** Free memory */ + void trimMemory(); + + /** Destroy on UI thread. Client should stop using CompositorFrameConsumer before this */ + void destroy(); +}
diff --git a/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java b/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java index 2893030..ec1bd80 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java +++ b/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java
@@ -19,7 +19,7 @@ * the render node hierarchy. */ @JNINamespace("android_webview") -public class AwGLFunctor { +public class AwGLFunctor implements AwFunctor { private final long mNativeAwGLFunctor; private final AwContents.NativeDrawGLFunctor mNativeDrawGLFunctor; private final ViewGroup mContainerView; @@ -41,7 +41,8 @@ addReference(); } - public void releasedByContents() { + @Override + public void destroy() { assert mRefCount > 0; removeReference(); } @@ -50,12 +51,14 @@ return nativeGetAwDrawGLFunction(); } - public long getNativeAwGLFunctor() { + @Override + public long getNativeCompositorFrameConsumer() { assert mRefCount > 0; - return mNativeAwGLFunctor; + return nativeGetCompositorFrameConsumer(mNativeAwGLFunctor); } - public boolean requestDrawGL(Canvas canvas) { + @Override + public boolean requestDraw(Canvas canvas) { assert mRefCount > 0; boolean success = mNativeDrawGLFunctor.requestDrawGL(canvas, mFunctorReleasedCallback); if (success && mFunctorReleasedCallback != null) { @@ -91,7 +94,8 @@ mContainerView.invalidate(); } - public void deleteHardwareRenderer() { + @Override + public void trimMemory() { assert mRefCount > 0; nativeDeleteHardwareRenderer(mNativeAwGLFunctor); } @@ -107,6 +111,7 @@ private native void nativeDeleteHardwareRenderer(long nativeAwGLFunctor); private native long nativeGetAwDrawGLViewContext(long nativeAwGLFunctor); + private native long nativeGetCompositorFrameConsumer(long nativeAwGLFunctor); private static native long nativeGetAwDrawGLFunction(); private static native void nativeDestroy(long nativeAwGLFunctor);
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index cc3ebc9..bf3ad51c 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -262,6 +262,8 @@ "cancel_mode.h", "cast_config_controller.cc", "cast_config_controller.h", + "contained_shell/contained_shell_controller.cc", + "contained_shell/contained_shell_controller.h", "dbus/ash_dbus_services.cc", "dbus/ash_dbus_services.h", "dbus/display_service_provider.cc", @@ -1636,6 +1638,8 @@ "assistant/util/deep_link_util_unittest.cc", "autoclick/autoclick_drag_event_rewriter_unittest.cc", "autoclick/autoclick_unittest.cc", + "contained_shell/mock_contained_shell_client.cc", + "contained_shell/mock_contained_shell_client.h", "cursor_unittest.cc", "detachable_base/detachable_base_handler_unittest.cc", "detachable_base/detachable_base_notification_controller_unittest.cc", @@ -1948,6 +1952,7 @@ "//net:net", "//services/catalog:lib", "//services/media_session/public/cpp/test:test_support", + "//services/media_session/public/mojom", "//services/service_manager/public/cpp:service_test_support", "//services/ws:test_support", "//services/ws/public/cpp/input_devices:test_support",
diff --git a/ash/contained_shell/OWNERS b/ash/contained_shell/OWNERS new file mode 100644 index 0000000..d95f00a --- /dev/null +++ b/ash/contained_shell/OWNERS
@@ -0,0 +1,3 @@ +qnnguyen@chromium.org +michaelpg@chromium.org +jdufault@chromium.org
diff --git a/ash/contained_shell/contained_shell_controller.cc b/ash/contained_shell/contained_shell_controller.cc new file mode 100644 index 0000000..a8aa3cf --- /dev/null +++ b/ash/contained_shell/contained_shell_controller.cc
@@ -0,0 +1,31 @@ +// 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 "ash/contained_shell/contained_shell_controller.h" + +#include <utility> + +namespace ash { + +ContainedShellController::ContainedShellController() = default; + +ContainedShellController::~ContainedShellController() = default; + +void ContainedShellController::BindRequest( + mojom::ContainedShellControllerRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void ContainedShellController::LaunchContainedShell() { + // TODO(crbug/902571): Implement launch by dispatching to a + // ContainedShellClient method. + NOTIMPLEMENTED(); +} + +void ContainedShellController::SetClient( + mojom::ContainedShellClientPtr client) { + contained_shell_client_ = std::move(client); +} + +} // namespace ash
diff --git a/ash/contained_shell/contained_shell_controller.h b/ash/contained_shell/contained_shell_controller.h new file mode 100644 index 0000000..4d379230 --- /dev/null +++ b/ash/contained_shell/contained_shell_controller.h
@@ -0,0 +1,44 @@ +// 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 ASH_CONTAINED_SHELL_CONTAINED_SHELL_CONTROLLER_H_ +#define ASH_CONTAINED_SHELL_CONTAINED_SHELL_CONTROLLER_H_ + +#include "ash/ash_export.h" +#include "ash/public/interfaces/contained_shell.mojom.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding_set.h" + +namespace ash { + +// ContainedShellController allows a consumer of ash to provide a +// ContainedShellClient, to which we dispatch requests. +// TODO(910226): remove this code once the ContainedShell demo is complete and +// no longer needed. +class ASH_EXPORT ContainedShellController + : public mojom::ContainedShellController { + public: + ContainedShellController(); + ~ContainedShellController() override; + + // Binds the mojom::ContainedShellController interface to this object. + void BindRequest(mojom::ContainedShellControllerRequest request); + + // Starts the ContainedShell feature by sending LaunchContainedShell + // request to ContainedShellClient. + void LaunchContainedShell(); + + // mojom::ContainedShellController: + void SetClient(mojom::ContainedShellClientPtr client) override; + + private: + mojom::ContainedShellClientPtr contained_shell_client_; + mojo::BindingSet<mojom::ContainedShellController> bindings_; + + DISALLOW_COPY_AND_ASSIGN(ContainedShellController); +}; + +} // namespace ash + +#endif // ASH_CONTAINED_SHELL_CONTAINED_SHELL_CONTROLLER_H
diff --git a/ash/contained_shell/mock_contained_shell_client.cc b/ash/contained_shell/mock_contained_shell_client.cc new file mode 100644 index 0000000..6a2bd52e --- /dev/null +++ b/ash/contained_shell/mock_contained_shell_client.cc
@@ -0,0 +1,30 @@ +// 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 "ash/contained_shell/mock_contained_shell_client.h" + +#include "ash/contained_shell/contained_shell_controller.h" +#include "ash/shell.h" + +namespace ash { + +MockContainedShellClient::MockContainedShellClient() = default; + +MockContainedShellClient::~MockContainedShellClient() = default; + +mojom::ContainedShellClientPtr +MockContainedShellClient::CreateInterfacePtrAndBind() { + mojom::ContainedShellClientPtr ptr; + binding_.Bind(mojo::MakeRequest(&ptr)); + return ptr; +} + +std::unique_ptr<MockContainedShellClient> BindMockContainedShellClient() { + auto client = std::make_unique<MockContainedShellClient>(); + Shell::Get()->contained_shell_controller()->SetClient( + client->CreateInterfacePtrAndBind()); + return client; +} + +} // namespace ash
diff --git a/ash/contained_shell/mock_contained_shell_client.h b/ash/contained_shell/mock_contained_shell_client.h new file mode 100644 index 0000000..5ef731b --- /dev/null +++ b/ash/contained_shell/mock_contained_shell_client.h
@@ -0,0 +1,36 @@ +// 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 ASH_CONTAINED_SHELL_MOCK_CONTAINED_SHELL_CLIENT_H_ +#define ASH_CONTAINED_SHELL_MOCK_CONTAINED_SHELL_CLIENT_H_ + +#include <memory> + +#include "ash/public/interfaces/contained_shell.mojom.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace ash { + +class MockContainedShellClient : public mojom::ContainedShellClient { + public: + MockContainedShellClient(); + ~MockContainedShellClient() override; + + mojom::ContainedShellClientPtr CreateInterfacePtrAndBind(); + + private: + mojo::Binding<mojom::ContainedShellClient> binding_{this}; + + DISALLOW_COPY_AND_ASSIGN(MockContainedShellClient); +}; + +// Helper function to bind a ContainedShellClient so that it receives mojo +// calls. +std::unique_ptr<MockContainedShellClient> BindMockContainedShellClient(); + +} // namespace ash + +#endif // ASH_CONTAINED_SHELL_MOCK_CONTAINED_SHELL_CLIENT_H
diff --git a/ash/manifest.json b/ash/manifest.json index 4e0cbe0..0ae64eb1 100644 --- a/ash/manifest.json +++ b/ash/manifest.json
@@ -22,6 +22,7 @@ "ash.mojom.AssistantSetupController", "ash.mojom.AssistantVolumeControl", "ash.mojom.CastConfig", + "ash.mojom.ContainedShellController", "ash.mojom.CrosDisplayConfigController", "ash.mojom.DockedMagnifierController", "ash.mojom.EventRewriterController",
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc index 28fa45c9..fd3d03e 100644 --- a/ash/mojo_interface_factory.cc +++ b/ash/mojo_interface_factory.cc
@@ -14,6 +14,7 @@ #include "ash/assistant/assistant_screen_context_controller.h" #include "ash/assistant/assistant_setup_controller.h" #include "ash/cast_config_controller.h" +#include "ash/contained_shell/contained_shell_controller.h" #include "ash/display/ash_display_controller.h" #include "ash/display/cros_display_config.h" #include "ash/display/display_output_protection.h" @@ -122,6 +123,11 @@ Shell::Get()->cast_config()->BindRequest(std::move(request)); } +void BindContainedShellControllerRequestOnMainThread( + mojom::ContainedShellControllerRequest request) { + Shell::Get()->contained_shell_controller()->BindRequest(std::move(request)); +} + void BindDisplayOutputProtectionRequestOnMainThread( mojom::DisplayOutputProtectionRequest request) { Shell::Get()->display_output_protection()->BindRequest(std::move(request)); @@ -281,6 +287,11 @@ main_thread_task_runner); registry->AddInterface(base::BindRepeating(&BindCastConfigOnMainThread), main_thread_task_runner); + if (base::FeatureList::IsEnabled(features::kContainedShell)) { + registry->AddInterface( + base::BindRepeating(&BindContainedShellControllerRequestOnMainThread), + main_thread_task_runner); + } registry->AddInterface( base::BindRepeating(&BindDisplayOutputProtectionRequestOnMainThread), main_thread_task_runner);
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index 9cf3eff..3588974 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -58,6 +58,9 @@ const base::Feature kUnlockWithExternalBinary{ "UnlockWithExternalBinary", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kContainedShell{"ContainedShell", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kViewsLogin{"ViewsLogin", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kUseBluetoothSystemInAsh{"UseBluetoothSystemInAsh",
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index c3572cef..52e5f084 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -76,6 +76,9 @@ // Enables running an external binary which provides lock screen authentication. ASH_PUBLIC_EXPORT extern const base::Feature kUnlockWithExternalBinary; +// Enables the ContainedShell feature. +ASH_PUBLIC_EXPORT extern const base::Feature kContainedShell; + // Enables views login. ASH_PUBLIC_EXPORT extern const base::Feature kViewsLogin;
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn index d44aa88..f5984197 100644 --- a/ash/public/interfaces/BUILD.gn +++ b/ash/public/interfaces/BUILD.gn
@@ -26,6 +26,7 @@ "assistant_volume_control.mojom", "cast_config.mojom", "constants.mojom", + "contained_shell.mojom", "cros_display_config.mojom", "display_output_protection.mojom", "docked_magnifier_controller.mojom",
diff --git a/ash/public/interfaces/contained_shell.mojom b/ash/public/interfaces/contained_shell.mojom new file mode 100644 index 0000000..516ab2d7 --- /dev/null +++ b/ash/public/interfaces/contained_shell.mojom
@@ -0,0 +1,18 @@ +// 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. + +module ash.mojom; + +// Performs browser-side functionality for the ContainedShell feature, +// e.g. launching a WebView to host the ContainedShell. +interface ContainedShellClient { +}; + +// Allows Ash and its consumers to interact with the ContainedShell +// feature, e.g. by requesting to launch the ContainedShell WebView. +// These requests are forwarded to the ContainedShellClient. +interface ContainedShellController { + // Provides a client for dispatching requests. + SetClient(ContainedShellClient client); +};
diff --git a/ash/shell.cc b/ash/shell.cc index 74bed486..85d6497 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -23,6 +23,7 @@ #include "ash/autoclick/autoclick_controller.h" #include "ash/cast_config_controller.h" #include "ash/components/tap_visualizer/public/mojom/constants.mojom.h" +#include "ash/contained_shell/contained_shell_controller.h" #include "ash/dbus/ash_dbus_services.h" #include "ash/detachable_base/detachable_base_handler.h" #include "ash/detachable_base/detachable_base_notification_controller.h" @@ -656,6 +657,7 @@ std::make_unique<system::BrightnessControllerChromeos>()), cast_config_(std::make_unique<CastConfigController>()), connector_(connector), + contained_shell_controller_(std::make_unique<ContainedShellController>()), first_run_helper_(std::make_unique<FirstRunHelper>()), focus_cycler_(std::make_unique<FocusCycler>()), ime_controller_(std::make_unique<ImeController>()), @@ -1427,6 +1429,11 @@ // Disable drag-and-drop during OOBE and GAIA login screens by only enabling // the controller when the session is active. https://crbug.com/464118 drag_drop_controller_->set_enabled(is_session_active); + + if (base::FeatureList::IsEnabled(features::kContainedShell) && + is_session_active) { + contained_shell_controller_->LaunchContainedShell(); + } } void Shell::OnLoginStatusChanged(LoginStatus login_status) {
diff --git a/ash/shell.h b/ash/shell.h index f9854c3..ffe673c 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -103,6 +103,7 @@ class BrightnessControlDelegate; class CastConfigController; class DisplayOutputProtection; +class ContainedShellController; class CrosDisplayConfig; class DetachableBaseHandler; class DetachableBaseNotificationController; @@ -357,6 +358,9 @@ } CastConfigController* cast_config() { return cast_config_.get(); } service_manager::Connector* connector() { return connector_; } + ContainedShellController* contained_shell_controller() { + return contained_shell_controller_.get(); + } CrosDisplayConfig* cros_display_config() { return cros_display_config_.get(); } @@ -720,6 +724,7 @@ std::unique_ptr<CastConfigController> cast_config_; std::unique_ptr<CrosDisplayConfig> cros_display_config_; service_manager::Connector* const connector_; + std::unique_ptr<ContainedShellController> contained_shell_controller_; std::unique_ptr<DetachableBaseHandler> detachable_base_handler_; std::unique_ptr<DetachableBaseNotificationController> detachable_base_notification_controller_;
diff --git a/base/BUILD.gn b/base/BUILD.gn index 902e44c..9f5395e 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2077,6 +2077,7 @@ if (is_android) { deps += [ "//testing/android/native_test:native_test_native_code" ] + shard_timeout = 600 } }
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index 761d3cb8..dcc9f8d1 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc
@@ -300,16 +300,6 @@ #endif } -// static -MessageLoopCurrentForUI MessageLoopForUI::current() { - return MessageLoopCurrentForUI::Get(); -} - -// static -bool MessageLoopForUI::IsCurrent() { - return MessageLoopCurrentForUI::IsSet(); -} - #if defined(OS_IOS) void MessageLoopForUI::Attach() { backend_->AttachToMessagePump(); @@ -338,17 +328,4 @@ #endif // !defined(OS_NACL) -//------------------------------------------------------------------------------ -// MessageLoopForIO - -// static -MessageLoopCurrentForIO MessageLoopForIO::current() { - return MessageLoopCurrentForIO::Get(); -} - -// static -bool MessageLoopForIO::IsCurrent() { - return MessageLoopCurrentForIO::IsSet(); -} - } // namespace base
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h index 04d45ae..1adfd4cd 100644 --- a/base/message_loop/message_loop.h +++ b/base/message_loop/message_loop.h
@@ -403,10 +403,6 @@ public: explicit MessageLoopForUI(Type type = TYPE_UI); - // TODO(gab): Mass migrate callers to MessageLoopCurrentForUI::Get()/IsSet(). - static MessageLoopCurrentForUI current(); - static bool IsCurrent(); - #if defined(OS_IOS) // On iOS, the main message loop cannot be Run(). Instead call Attach(), // which connects this MessageLoop to the UI thread's CFRunLoop and allows @@ -456,10 +452,6 @@ class BASE_EXPORT MessageLoopForIO : public MessageLoop { public: MessageLoopForIO() : MessageLoop(TYPE_IO) {} - - // TODO(gab): Mass migrate callers to MessageLoopCurrentForIO::Get()/IsSet(). - static MessageLoopCurrentForIO current(); - static bool IsCurrent(); }; // Do not add any member variables to MessageLoopForIO! This is important b/c
diff --git a/base/power_monitor/power_monitor_device_source_win.cc b/base/power_monitor/power_monitor_device_source_win.cc index e74be50..37a4462 100644 --- a/base/power_monitor/power_monitor_device_source_win.cc +++ b/base/power_monitor/power_monitor_device_source_win.cc
@@ -65,7 +65,7 @@ PowerMonitorDeviceSource::PowerMessageWindow::PowerMessageWindow() : instance_(NULL), message_hwnd_(NULL) { - if (!MessageLoopForUI::IsCurrent()) { + if (!MessageLoopCurrentForUI::IsSet()) { // Creating this window in (e.g.) a renderer inhibits shutdown on Windows. // See http://crbug.com/230122. TODO(vandebo): http://crbug.com/236031 DLOG(ERROR)
diff --git a/base/test/fuzzed_data_provider.h b/base/test/fuzzed_data_provider.h index f133959..19e829f 100644 --- a/base/test/fuzzed_data_provider.h +++ b/base/test/fuzzed_data_provider.h
@@ -87,7 +87,7 @@ abort(); // Use the biggest type possible to hold the range and the result. - uint64_t range = max - min; + uint64_t range = static_cast<uint64_t>(max) - min; uint64_t result = 0; size_t offset = 0; @@ -108,7 +108,7 @@ if (range != std::numeric_limits<decltype(range)>::max()) result = result % (range + 1); - return min + static_cast<T>(result); + return static_cast<T>(min + result); } // Returns a std::string of length from 0 to |max_length|. When it runs out of
diff --git a/base/threading/thread.cc b/base/threading/thread.cc index a228216..86062857 100644 --- a/base/threading/thread.cc +++ b/base/threading/thread.cc
@@ -302,7 +302,7 @@ #if defined(OS_POSIX) && !defined(OS_NACL) // Allow threads running a MessageLoopForIO to use FileDescriptorWatcher API. std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher; - if (MessageLoopForIO::IsCurrent()) { + if (MessageLoopCurrentForIO::IsSet()) { file_descriptor_watcher.reset( new FileDescriptorWatcher(message_loop_->task_runner())); }
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index 3da9414e..fabe15f6 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py
@@ -527,6 +527,7 @@ def WriteDepfile(depfile_path, first_gn_output, inputs=None, add_pydeps=True): assert depfile_path != first_gn_output # http://crbug.com/646165 + assert not isinstance(inputs, basestring) # Easy mistake to make inputs = inputs or [] if add_pydeps: inputs = _ComputePythonDependencies() + inputs
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index 701e77e..3b4d641 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -119,6 +119,8 @@ <ignore regexp="content/public/android/java/res/drawable-xxxhdpi"/> <ignore regexp="ui/android/java/res/drawable-xxhdpi"/> <ignore regexp="ui/android/java/res/drawable-xxxhdpi"/> + <!-- This is intentional to reduce APK size. See: http://crrev/c/1352161 --> + <ignore regexp="chrome/android/java/res_autofill_assistant/drawable-*"/> </issue> <issue id="IconDipSize"> <ignore regexp="chromecast/internal"/>
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py index 6ffce53b..f9caabc 100755 --- a/build/fuchsia/test_runner.py +++ b/build/fuchsia/test_runner.py
@@ -32,6 +32,9 @@ parser.add_argument('--gtest_repeat', help='GTest repeat value to use. This also disables the ' 'test launcher timeout.') + parser.add_argument('--test-launcher-retry-limit', + help='Number of times that test suite will retry failing ' + 'tests. This is multiplicative with --gtest_repeat.') parser.add_argument('--gtest_break_on_failure', action='store_true', default=False, help='Should GTest break on failure; useful with ' @@ -79,6 +82,9 @@ if args.gtest_repeat: child_args.append('--gtest_repeat=' + args.gtest_repeat) child_args.append('--test-launcher-timeout=-1') + if args.test_launcher_retry_limit: + child_args.append( + '--test-launcher-retry-limit=' + args.test_launcher_retry_limit) if args.gtest_break_on_failure: child_args.append('--gtest_break_on_failure') if args.child_args:
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java index c6b2aad..7065ccd 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
@@ -4,6 +4,9 @@ package org.chromium.chrome.browser.feed; +import android.support.annotation.NonNull; + +import com.google.android.libraries.feed.api.stream.ScrollListener; import com.google.android.libraries.feed.host.logging.ActionType; import com.google.android.libraries.feed.host.logging.BasicLoggingApi; import com.google.android.libraries.feed.host.logging.ContentLoggingData; @@ -36,14 +39,20 @@ /** Cleans up native half of this bridge. */ public void destroy() { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeDestroy(mNativeFeedLoggingBridge); mNativeFeedLoggingBridge = 0; } @Override public void onContentViewed(ContentLoggingData data) { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnContentViewed(mNativeFeedLoggingBridge, data.getPositionInStream(), TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()), TimeUnit.SECONDS.toMillis(data.getTimeContentBecameAvailable()), data.getScore()); @@ -51,24 +60,39 @@ @Override public void onContentDismissed(ContentLoggingData data) { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnContentDismissed( mNativeFeedLoggingBridge, data.getPositionInStream(), data.getRepresentationUri()); } @Override - public void onContentSwiped(ContentLoggingData data) {} + public void onContentSwiped(ContentLoggingData data) { + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + + nativeOnContentSwiped(mNativeFeedLoggingBridge); + } @Override public void onContentClicked(ContentLoggingData data) { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnContentClicked(mNativeFeedLoggingBridge, data.getPositionInStream(), TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()), data.getScore()); } @Override public void onClientAction(ContentLoggingData data, @ActionType int actionType) { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + recordUserAction(actionType); nativeOnClientAction( mNativeFeedLoggingBridge, feedActionToWindowOpenDisposition(actionType)); @@ -76,43 +100,67 @@ @Override public void onContentContextMenuOpened(ContentLoggingData data) { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnContentContextMenuOpened(mNativeFeedLoggingBridge, data.getPositionInStream(), TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()), data.getScore()); } @Override public void onMoreButtonViewed(int position) { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnMoreButtonViewed(mNativeFeedLoggingBridge, position); } @Override public void onMoreButtonClicked(int position) { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnMoreButtonClicked(mNativeFeedLoggingBridge, position); } @Override public void onOpenedWithContent(int timeToPopulateMs, int contentCount) { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnOpenedWithContent(mNativeFeedLoggingBridge, timeToPopulateMs, contentCount); } @Override public void onOpenedWithNoImmediateContent() { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnOpenedWithNoImmediateContent(mNativeFeedLoggingBridge); } @Override public void onOpenedWithNoContent() { - assert mNativeFeedLoggingBridge != 0; + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + nativeOnOpenedWithNoContent(mNativeFeedLoggingBridge); } @Override - public void onSpinnerShown(int timeShownMs, @SpinnerType int spinnerType) {} + public void onSpinnerShown(int timeShownMs, @SpinnerType int spinnerType) { + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + + nativeOnSpinnerShown(mNativeFeedLoggingBridge, timeShownMs); + } /** * Reports how long a user spends on the page. @@ -168,12 +216,46 @@ } } + private void reportScrolledAfterOpen() { + // Bridge could have been destroyed for policy when this is called. + // See https://crbug.com/901414. + if (mNativeFeedLoggingBridge == 0) return; + + nativeReportScrolledAfterOpen(mNativeFeedLoggingBridge); + } + + /** + * One-shot reporter that records the first time the user scrolls in the {@link Stream}. + */ + public static class ScrollEventReporter implements ScrollListener { + private final FeedLoggingBridge mLoggingBridge; + private boolean mFired; + + public ScrollEventReporter(@NonNull FeedLoggingBridge loggingBridge) { + super(); + mLoggingBridge = loggingBridge; + } + + @Override + public void onScrollStateChanged(@ScrollState int state) { + if (mFired) return; + if (state != ScrollState.DRAGGING) return; + + mLoggingBridge.reportScrolledAfterOpen(); + mFired = true; + } + + @Override + public void onScrolled(int dx, int dy) {} + } + private native long nativeInit(Profile profile); private native void nativeDestroy(long nativeFeedLoggingBridge); private native void nativeOnContentViewed(long nativeFeedLoggingBridge, int position, long publishedTimeMs, long timeContentBecameAvailableMs, float score); private native void nativeOnContentDismissed( long nativeFeedLoggingBridge, int position, String uri); + private native void nativeOnContentSwiped(long nativeFeedLoggingBridge); private native void nativeOnContentClicked( long nativeFeedLoggingBridge, int position, long publishedTimeMs, float score); private native void nativeOnClientAction( @@ -186,6 +268,8 @@ long nativeFeedLoggingBridge, int timeToPopulateMs, int contentCount); private native void nativeOnOpenedWithNoImmediateContent(long nativeFeedLoggingBridge); private native void nativeOnOpenedWithNoContent(long nativeFeedLoggingBridge); + private native void nativeOnSpinnerShown(long nativeFeedLoggingBridge, long spinnerShownTimeMs); private native void nativeOnContentTargetVisited( long nativeFeedLoggingBridge, long visitTimeMs, boolean isOffline, boolean returnToNtp); + private native void nativeReportScrolledAfterOpen(long nativeFeedLoggingBridge); }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java index 692bdc0c..585dfc3 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -282,6 +282,13 @@ mMediator.onThumbnailCaptured(); } + /** + * @return The {@link StreamLifecycleManager} that manages the lifecycle of the {@link Stream}. + */ + StreamLifecycleManager getStreamLifecycleManager() { + return mStreamLifecycleManager; + } + /** @return The {@link Stream} that this class holds. */ Stream getStream() { return mStream; @@ -343,6 +350,7 @@ if (mSigninPromoView != null) UiUtils.removeViewFromParent(mSigninPromoView); mStream.setHeaderViews(Arrays.asList(new NonDismissibleHeader(mNewTabPageLayout), new NonDismissibleHeader(mSectionHeaderView))); + mStream.addScrollListener(new FeedLoggingBridge.ScrollEventReporter(loggingBridge)); // Explicitly request focus on the scroll container to avoid UrlBar being focused after // the scroll container for policy is removed. view.requestFocus(); @@ -362,6 +370,9 @@ void createScrollViewForPolicy() { if (mStream != null) { mRootView.removeView(mStream.getView()); + assert mStreamLifecycleManager + != null + : "StreamLifecycleManager should not be null when the Stream is not null."; mStreamLifecycleManager.destroy(); mStreamLifecycleManager = null; // Do not call mStream.onDestroy(), the mStreamLifecycleManager has done that for us.
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPageMediator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPageMediator.java index ec22014..5b1cefff 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPageMediator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPageMediator.java
@@ -152,14 +152,20 @@ if (stream == null) return; stream.removeScrollListener(mStreamScrollListener); - stream.removeOnContentChangedListener(mStreamContentChangedListener); - MemoryPressureListener.removeCallback(mMemoryPressureCallback); - if (mSignInPromo != null) mSignInPromo.destroy(); - mPrefChangeRegistrar.removeObserver(Pref.NTP_ARTICLES_LIST_VISIBLE); mStreamScrollListener = null; + + stream.removeOnContentChangedListener(mStreamContentChangedListener); mStreamContentChangedListener = null; + + MemoryPressureListener.removeCallback(mMemoryPressureCallback); mMemoryPressureCallback = null; - mSignInPromo = null; + + if (mSignInPromo != null) { + mSignInPromo.destroy(); + mSignInPromo = null; + } + + mPrefChangeRegistrar.removeObserver(Pref.NTP_ARTICLES_LIST_VISIBLE); } /** @@ -178,6 +184,7 @@ if (mSignInPromo != null) { mSignInPromo.setCanShowPersonalizedSuggestions(suggestionsVisible); } + if (suggestionsVisible) mCoordinator.getStreamLifecycleManager().activate(); mStreamContentChanged = true; }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java index a8dc1433..03b0288 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
@@ -29,9 +29,20 @@ public class FeedProcessScopeFactory { private static final String TAG = "FeedProcessScopeFtry"; - /** Flag that tracks whether we've ever been disabled via enterprise policy. Should only be - * accessed through isFeedProcessScopeEnabled(). */ + /** + * Flag that tracks whether we've ever been disabled via enterprise policy. Should only be + * accessed through isFeedProcessScopeEnabled(). + */ private static boolean sEverDisabledForPolicy; + + /** + * Tracks whether the article suggestions should be visible to the user during the current + * session. If user opts in to the suggestions during the current session, the suggestions + * services will be immediately warmed up. If user opts out during the current session, + * the suggestions services will not shut down until the next session. + */ + private static boolean sArticlesVisibleDuringSession; + private static PrefChangeRegistrar sPrefChangeRegistrar; private static FeedAppLifecycle sFeedAppLifecycle; private static FeedProcessScope sFeedProcessScope; @@ -109,6 +120,8 @@ && sFeedAppLifecycle == null && sFeedLoggingBridge == null; if (!isFeedProcessEnabled()) return; + sArticlesVisibleDuringSession = + PrefServiceBridge.getInstance().getBoolean(Pref.NTP_ARTICLES_LIST_VISIBLE); sPrefChangeRegistrar = new PrefChangeRegistrar(); sPrefChangeRegistrar.addObserver(Pref.NTP_ARTICLES_SECTION_ENABLED, FeedProcessScopeFactory::articlesEnabledPrefChange); @@ -193,6 +206,21 @@ destroy(); } + /** + * @return Whether article suggestions are prepared to be shown based on user preference. If + * article suggestions are set hidden within a session, this will still return true + * until the next restart. + */ + static boolean areArticlesVisibleDuringSession() { + // Skip the native call if sArticlesVisibleDuringSession is already true to reduce overhead. + if (!sArticlesVisibleDuringSession + && PrefServiceBridge.getInstance().getBoolean(Pref.NTP_ARTICLES_LIST_VISIBLE)) { + sArticlesVisibleDuringSession = true; + } + + return sArticlesVisibleDuringSession; + } + private static void articlesEnabledPrefChange() { // Should only be subscribed while it was enabled. A change should mean articles are now // disabled.
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java index b268868..0fd5515 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java
@@ -136,8 +136,11 @@ /** @return Whether the {@link Stream} can be shown. */ private boolean canShow() { final int state = ApplicationStatus.getStateForActivity(mActivity); + // We don't call Stream#onShow to prevent feed services from being warmed up if the user + // has opted out from article suggestions during the previous session. return (mStreamState == CREATED || mStreamState == HIDDEN) && !mTab.isHidden() - && (state == ActivityState.STARTED || state == ActivityState.RESUMED); + && (state == ActivityState.STARTED || state == ActivityState.RESUMED) + && FeedProcessScopeFactory.areArticlesVisibleDuringSession(); } /** Calls {@link Stream#onShow()}. */ @@ -150,15 +153,17 @@ /** @return Whether the {@link Stream} can be activated. */ private boolean canActivate() { - return mStreamState != ACTIVE && mStreamState != DESTROYED && mTab.isUserInteractable() - && ApplicationStatus.getStateForActivity(mActivity) == ActivityState.RESUMED; + return (mStreamState == SHOWN || mStreamState == INACTIVE) && mTab.isUserInteractable() + && ApplicationStatus.getStateForActivity(mActivity) == ActivityState.RESUMED + && FeedProcessScopeFactory.areArticlesVisibleDuringSession(); } /** Calls {@link Stream#onActive()}. */ - private void activate() { + void activate() { + // Make sure the Stream can be shown and is set shown before setting it to active state. + show(); if (!canActivate()) return; - show(); mStreamState = ACTIVE; mStream.onActive(); } @@ -175,6 +180,7 @@ private void hide() { if (mStreamState == HIDDEN || mStreamState == CREATED || mStreamState == DESTROYED) return; + // Make sure the Stream is inactive before setting it to hidden state. deactivate(); mStreamState = HIDDEN; // Save instance state as the Stream begins to hide. This matches the activity lifecycle @@ -190,6 +196,7 @@ void destroy() { if (mStreamState == DESTROYED) return; + // Make sure the Stream is hidden before setting it to destroyed state. hide(); mStreamState = DESTROYED; mTab.removeObserver(mTabObserver);
diff --git a/chrome/android/java/res_autofill_assistant/drawable-hdpi/onboarding_background.png b/chrome/android/java/res_autofill_assistant/drawable-hdpi/onboarding_background.png deleted file mode 100644 index 3ea9224d..0000000 --- a/chrome/android/java/res_autofill_assistant/drawable-hdpi/onboarding_background.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable-mdpi/onboarding_background.png b/chrome/android/java/res_autofill_assistant/drawable-mdpi/onboarding_background.png index 79b5754..9812e98 100644 --- a/chrome/android/java/res_autofill_assistant/drawable-mdpi/onboarding_background.png +++ b/chrome/android/java/res_autofill_assistant/drawable-mdpi/onboarding_background.png Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable-xhdpi/onboarding_background.png b/chrome/android/java/res_autofill_assistant/drawable-xhdpi/onboarding_background.png deleted file mode 100644 index 8bbacec..0000000 --- a/chrome/android/java/res_autofill_assistant/drawable-xhdpi/onboarding_background.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable-xxhdpi/onboarding_background.png b/chrome/android/java/res_autofill_assistant/drawable-xxhdpi/onboarding_background.png index e691cdb..d9fa3c3 100644 --- a/chrome/android/java/res_autofill_assistant/drawable-xxhdpi/onboarding_background.png +++ b/chrome/android/java/res_autofill_assistant/drawable-xxhdpi/onboarding_background.png Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable-xxxhdpi/onboarding_background.png b/chrome/android/java/res_autofill_assistant/drawable-xxxhdpi/onboarding_background.png deleted file mode 100644 index e40b1f7..0000000 --- a/chrome/android/java/res_autofill_assistant/drawable-xxxhdpi/onboarding_background.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/layout/init_screen.xml b/chrome/android/java/res_autofill_assistant/layout/init_screen.xml index d95aac7..cd93f12 100644 --- a/chrome/android/java/res_autofill_assistant/layout/init_screen.xml +++ b/chrome/android/java/res_autofill_assistant/layout/init_screen.xml
@@ -38,10 +38,13 @@ <ImageView tools:ignore="contentDescription" android:layout_width="250dp" - android:layout_height="170dp" + android:layout_height="141dp" android:scaleType="centerCrop" android:src="@drawable/onboarding_background" - android:paddingStart="50dp"/> + android:paddingStart="25dp" + android:paddingEnd="25dp" + android:paddingTop="10dp" + android:paddingBottom="15dp"/> <TextView android:layout_height="wrap_content"
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 8b9039e..c97fe4a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -52,6 +52,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.webapps.GooglePlayWebApkInstallDelegate; import org.chromium.chrome.browser.webauth.Fido2ApiHandler; +import org.chromium.chrome.browser.widget.FeatureHighlightProvider; import org.chromium.components.signin.AccountManagerDelegate; import org.chromium.components.signin.SystemAccountManagerDelegate; import org.chromium.policy.AppRestrictionsProvider; @@ -326,6 +327,13 @@ } /** + * @return A new {@link FeatureHighlightProvider}. + */ + public FeatureHighlightProvider createFeatureHighlightProvider() { + return new FeatureHighlightProvider(); + } + + /** * Checks the Google Play services availability on the this device. * * This is a workaround for the
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java index d3069106..202ee81c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -108,6 +108,30 @@ private static final float GENERATED_ICON_PADDING_RATIO = 1.0f / 12.0f; private static final float GENERATED_ICON_FONT_SIZE_RATIO = 1.0f / 3.0f; + // Constants for figuring out the amount of padding required to transform a web manifest + // maskable icon to an Android adaptive icon. + // + // The web standard for maskable icons specifies a larger safe zone inside the icon + // than Android adaptive icons define. Therefore we need to pad the image so that + // the maskable icon's safe zone is reduced to the dimensions expected by Android. See + // https://github.com/w3c/manifest/issues/555#issuecomment-404097653. + // + // The *_RATIO variables give the diameter of the safe zone divided by the width of the icon. + // Sources: + // - https://www.w3.org/TR/appmanifest/#icon-masks + // - https://medium.com/google-design/designing-adaptive-icons-515af294c783 + // + // We subtract 1 from the scaling factor to give the amount we need to increase by, then divide + // it by two to get the amount of padding that we will add to both sides. + private static final float MASKABLE_SAFE_ZONE_RATIO = 4.0f / 5.0f; + private static final float ADAPTABLE_SAFE_ZONE_RATIO = 66.0f / 108.0f; + + private static final float MASKABLE_TO_ADAPTABLE_SCALING_FACTOR = + MASKABLE_SAFE_ZONE_RATIO / ADAPTABLE_SAFE_ZONE_RATIO; + + private static final float MASKABLE_ICON_PADDING_RATIO = + (MASKABLE_TO_ADAPTABLE_SCALING_FACTOR - 1.0f) / 2.0f; + // True when Android O's ShortcutManager.requestPinShortcut() is supported. private static boolean sIsRequestPinShortcutSupported; @@ -120,13 +144,15 @@ public static class Delegate { /** * Request Android to add a shortcut to the home screen. - * @param title Title of the shortcut. - * @param icon Image that represents the shortcut. - * @param intent Intent to fire when the shortcut is activated. + * @param title Title of the shortcut. + * @param icon Image that represents the shortcut. + * @param iconAdaptable Whether to create an Android Adaptable icon. + * @param shortcutIntent Intent to fire when the shortcut is activated. */ - public void addShortcutToHomescreen(String title, Bitmap icon, Intent shortcutIntent) { + public void addShortcutToHomescreen( + String title, Bitmap icon, boolean iconAdaptable, Intent shortcutIntent) { if (isRequestPinShortcutSupported()) { - addShortcutWithShortcutManager(title, icon, shortcutIntent); + addShortcutWithShortcutManager(title, icon, iconAdaptable, shortcutIntent); return; } Intent intent = createAddToHomeIntent(title, icon, shortcutIntent); @@ -160,9 +186,9 @@ @CalledByNative private static void addWebapp(final String id, final String url, final String scopeUrl, final String userTitle, final String name, final String shortName, final String iconUrl, - final Bitmap icon, @WebDisplayMode final int displayMode, final int orientation, - final int source, final long themeColor, final long backgroundColor, - final String splashScreenUrl, final long callbackPointer) { + final Bitmap icon, boolean iconAdaptable, @WebDisplayMode final int displayMode, + final int orientation, final int source, final long themeColor, + final long backgroundColor, final String splashScreenUrl, final long callbackPointer) { new AsyncTask<Intent>() { @Override protected Intent doInBackground() { @@ -185,7 +211,7 @@ } @Override protected void onPostExecute(final Intent resultIntent) { - sDelegate.addShortcutToHomescreen(userTitle, icon, resultIntent); + sDelegate.addShortcutToHomescreen(userTitle, icon, iconAdaptable, resultIntent); // Store the webapp data so that it is accessible without the intent. Once this // process is complete, call back to native code to start the splash image @@ -208,14 +234,14 @@ */ @SuppressWarnings("unused") @CalledByNative - private static void addShortcut( - String id, String url, String userTitle, Bitmap icon, int source) { + private static void addShortcut(String id, String url, String userTitle, Bitmap icon, + boolean iconAdaptable, int source) { Context context = ContextUtils.getApplicationContext(); final Intent shortcutIntent = createShortcutIntent(url); shortcutIntent.putExtra(EXTRA_ID, id); shortcutIntent.putExtra(EXTRA_SOURCE, source); shortcutIntent.setPackage(context.getPackageName()); - sDelegate.addShortcutToHomescreen(userTitle, icon, shortcutIntent); + sDelegate.addShortcutToHomescreen(userTitle, icon, iconAdaptable, shortcutIntent); if (shouldShowToastWhenAddingShortcut()) { showAddedToHomescreenToast(userTitle); } @@ -223,14 +249,17 @@ @TargetApi(Build.VERSION_CODES.O) private static void addShortcutWithShortcutManager( - String title, Bitmap icon, Intent shortcutIntent) { + String title, Bitmap bitmap, boolean isMaskableIcon, Intent shortcutIntent) { String id = shortcutIntent.getStringExtra(ShortcutHelper.EXTRA_ID); Context context = ContextUtils.getApplicationContext(); + Icon icon = isMaskableIcon ? Icon.createWithAdaptiveBitmap(bitmap) + : Icon.createWithBitmap(bitmap); + ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(context, id) .setShortLabel(title) .setLongLabel(title) - .setIcon(Icon.createWithBitmap(icon)) + .setIcon(icon) .setIntent(shortcutIntent) .build(); try { @@ -410,12 +439,12 @@ * Adapts a website's icon (e.g. favicon or touch icon) to make it suitable for the home screen. * This involves adding padding if the icon is a full sized square. * - * @param context Context used to create the intent. * @param webIcon The website's favicon or touch icon. + * @param maskable Whether the icon is suitable for creating an adaptive icon. * @return Bitmap Either the touch-icon or the newly created favicon. */ @CalledByNative - public static Bitmap createHomeScreenIconFromWebIcon(Bitmap webIcon) { + public static Bitmap createHomeScreenIconFromWebIcon(Bitmap webIcon, boolean maskable) { // getLauncherLargeIconSize() is just a guess at the launcher icon size, and is often // wrong -- the launcher can show icons at any size it pleases. Instead of resizing the // icon to the supposed launcher size and then having the launcher resize the icon again, @@ -426,18 +455,21 @@ int maxInnerSize = Math.round(am.getLauncherLargeIconSize() * MAX_INNER_SIZE_RATIO); int innerSize = Math.min(maxInnerSize, Math.max(webIcon.getWidth(), webIcon.getHeight())); - int outerSize = innerSize; Rect innerBounds = new Rect(0, 0, innerSize, innerSize); + int padding = 0; - // Draw the icon with padding around it if all four corners are not transparent. Otherwise, - // don't add padding. - if (shouldPadIcon(webIcon)) { - int padding = Math.round(ICON_PADDING_RATIO * innerSize); - outerSize += 2 * padding; - innerBounds.offset(padding, padding); + if (maskable) { + // See comments for MASKABLE_ICON_PADDING_RATIO. + padding = Math.round(MASKABLE_ICON_PADDING_RATIO * innerSize); + } else if (shouldPadIcon(webIcon)) { + // Draw the icon with padding around it if all four corners are not transparent. + padding = Math.round(ICON_PADDING_RATIO * innerSize); } - Bitmap bitmap = null; + int outerSize = 2 * padding + innerSize; + innerBounds.offset(padding, padding); + + Bitmap bitmap; try { bitmap = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARGB_8888); } catch (OutOfMemoryError e) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java index 99fefe6..2cfd35d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java
@@ -9,7 +9,6 @@ import org.chromium.base.metrics.CachedMetrics; import org.chromium.base.metrics.RecordHistogram; -import org.chromium.base.metrics.RecordUserAction; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -46,20 +45,6 @@ } /** - * Records that a Trusted Web Activity has been opened. - */ - public static void recordTwaOpened() { - RecordUserAction.record("BrowserServices.TwaOpened"); - } - - /** - * Records the time that a Trusted Web Activity has been open for. - */ - public static void recordTwaOpenTime(long duration, TimeUnit unit) { - RecordHistogram.recordTimesHistogram("BrowserServices.TwaOpenTime", duration, unit); - } - - /** * Returns a {@link TimingMetric} that records the amount of time spent querying the Android * system for ResolveInfos that will deal with a given URL when launching from a background * service.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java index ea5ed9a8..4d787176 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java
@@ -7,13 +7,14 @@ import android.app.AlertDialog; import android.content.Context; import android.content.Intent; -import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.preferences.PreferencesLauncher; +import org.chromium.chrome.browser.preferences.website.SettingsNavigationSource; import org.chromium.chrome.browser.preferences.website.SingleCategoryPreferences; import org.chromium.chrome.browser.preferences.website.SiteSettingsCategory; @@ -29,16 +30,18 @@ public class ClearDataDialogActivity extends AppCompatActivity { private static final String EXTRA_DOMAINS = "org.chromium.chrome.extra.domains"; private static final String EXTRA_ORIGINS = "org.chromium.chrome.extra.origins"; + private static final String EXTRA_APP_UNINSTALLED = "org.chromium.chrome.extra.app_uninstalled"; /** * Creates an intent for launching this activity for the TWA client app that was uninstalled or * had its data cleared. */ public static Intent createIntent(Context context, Collection<String> linkedDomains, - Collection<String> linkedOrigins) { + Collection<String> linkedOrigins, boolean appUninstalled) { Intent intent = new Intent(context, ClearDataDialogActivity.class); intent.putExtra(EXTRA_DOMAINS, new ArrayList<>(linkedDomains)); intent.putExtra(EXTRA_ORIGINS, new ArrayList<>(linkedOrigins)); + intent.putExtra(EXTRA_APP_UNINSTALLED, appUninstalled); return intent; } @@ -51,15 +54,19 @@ .setTitle(R.string.twa_clear_data_dialog_title) .setMessage(R.string.twa_clear_data_dialog_message) .setPositiveButton(R.string.preferences, (ignored1, ignored2) -> { + recordDecision(true); openSettings(); finish(); }) .setNegativeButton(R.string.twa_clear_data_dialog_keep_data, - (ignored1, ignored2) -> finish()); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - builder.setOnDismissListener(ignored -> finish()); - } + (ignored1, ignored2) -> { + recordDecision(false); + finish(); + }) + .setOnCancelListener((ignored) -> { + recordDecision(false); + finish(); + }); builder.create().show(); } @@ -86,7 +93,8 @@ } private void openSingleWebsitePrefs(String origin) { - startActivity(PreferencesLauncher.createIntentForSingleWebsitePreferences(this, origin)); + startActivity(PreferencesLauncher.createIntentForSingleWebsitePreferences( + this, origin, SettingsNavigationSource.TWA_CLEAR_DATA_DIALOG)); } private void openFilteredAllSiteSettings(Collection<String> domains) { @@ -97,7 +105,15 @@ getString(R.string.twa_clear_data_site_selection_title)); extras.putStringArrayList( SingleCategoryPreferences.EXTRA_SELECTED_DOMAINS, new ArrayList<>(domains)); + extras.putInt(SettingsNavigationSource.EXTRA_KEY, + SettingsNavigationSource.TWA_CLEAR_DATA_DIALOG); PreferencesLauncher.launchSettingsPage(this, SingleCategoryPreferences.class, extras); } + + private void recordDecision(boolean accepted) { + final boolean appUninstalled = getIntent().getBooleanExtra(EXTRA_APP_UNINSTALLED, false); + ChromeApplication.getComponent().resolveTwaClearDataDialogRecorder() + .handleDialogResult(accepted, appUninstalled); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java new file mode 100644 index 0000000..626c5a4 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java
@@ -0,0 +1,76 @@ +// 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. + +package org.chromium.chrome.browser.browserservices; + +import static org.chromium.chrome.browser.preferences.ChromePreferenceManager.TWA_DIALOG_NUMBER_OF_DIMSISSALS_ON_CLEAR_DATA; +import static org.chromium.chrome.browser.preferences.ChromePreferenceManager.TWA_DIALOG_NUMBER_OF_DIMSISSALS_ON_UNINSTALL; + +import org.chromium.base.StrictModeContext; +import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.preferences.ChromePreferenceManager; + +import javax.inject.Inject; + +import dagger.Lazy; + +/** + * Record the results of showing a clear data dialog on TWA client uninstall or data clear. + */ +public class ClearDataDialogResultRecorder { + private final Lazy<ChromePreferenceManager> mPrefsManager; + private final ChromeBrowserInitializer mBrowserInitializer; + private final TrustedWebActivityUmaRecorder mUmaRecorder; + + @Inject + public ClearDataDialogResultRecorder( + Lazy<ChromePreferenceManager> manager, + ChromeBrowserInitializer browserInitializer, + TrustedWebActivityUmaRecorder umaRecorder) { + mPrefsManager = manager; + mBrowserInitializer = browserInitializer; + mUmaRecorder = umaRecorder; + } + + /** + * Called when the dialog is closed. + * @param accepted Whether positive button was clicked. + * @param triggeredByUninstall Whether the dialog was triggered by uninstall. + */ + public void handleDialogResult(boolean accepted, boolean triggeredByUninstall) { + if (accepted || mBrowserInitializer.hasNativeInitializationCompleted()) { + // If accepted, native is going to be loaded for the settings. + mBrowserInitializer.runNowOrAfterNativeInitialization(() -> + mUmaRecorder.recordClearDataDialogAction(accepted, + triggeredByUninstall)); + } else { + // Avoid loading native just for the sake of recording. Save the info and record + // on next Chrome launch. + String key = triggeredByUninstall ? TWA_DIALOG_NUMBER_OF_DIMSISSALS_ON_UNINSTALL + : TWA_DIALOG_NUMBER_OF_DIMSISSALS_ON_CLEAR_DATA; + + try (StrictModeContext unused = StrictModeContext.allowDiskReads()) { + mPrefsManager.get().writeInt(key, mPrefsManager.get().readInt(key) + 1); + } + } + } + + /** + * Make recordings that were deferred in order to not load native. + */ + public void makeDeferredRecordings() { + try (StrictModeContext unused = StrictModeContext.allowDiskReads()) { + recordDismissals(TWA_DIALOG_NUMBER_OF_DIMSISSALS_ON_UNINSTALL, true); + recordDismissals(TWA_DIALOG_NUMBER_OF_DIMSISSALS_ON_CLEAR_DATA, false); + } + } + + private void recordDismissals(String prefKey, boolean triggeredByUninstall) { + int times = mPrefsManager.get().readInt(prefKey); + for (int i = 0; i < times; i++) { + mUmaRecorder.recordClearDataDialogAction(false /*accepted*/, triggeredByUninstall); + } + mPrefsManager.get().removeKey(prefKey); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java index 1707605..50e2a34 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
@@ -149,7 +149,8 @@ // cleaned up. Set<String> domains = register.getDomainsForRegisteredUid(uid); Set<String> origins = register.getOriginsForRegisteredUid(uid); - Intent intent = ClearDataDialogActivity.createIntent(context, domains, origins); + Intent intent = + ClearDataDialogActivity.createIntent(context, domains, origins, uninstalled); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java index 3995ea05..1b54e42 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java
@@ -15,6 +15,7 @@ import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.preferences.PreferencesLauncher; +import org.chromium.chrome.browser.preferences.website.SettingsNavigationSource; /** * Launched by {@link android.support.customtabs.TrustedWebUtils#launchBrowserSiteSettings}. @@ -39,8 +40,9 @@ private void verifyOriginAndLaunchSettings() { Origin origin = new Origin(getIntent().getData()); if (isVerifiedOrigin(origin)) { + new TrustedWebActivityUmaRecorder().recordOpenedSettingsViaManageSpace(); startActivity(PreferencesLauncher.createIntentForSingleWebsitePreferences(this, - origin.toString())); + origin.toString(), SettingsNavigationSource.TWA_MANAGE_SPACE_ACTIVITY)); } else { logVerificationFailed(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java index 2fa8f0b..5a4deba4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
@@ -4,6 +4,9 @@ package org.chromium.chrome.browser.browserservices; +import static org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder.DelegatedNotificationSmallIconFallback.FALLBACK_ICON_NOT_PROVIDED; +import static org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder.DelegatedNotificationSmallIconFallback.NO_FALLBACK; + import android.app.Notification; import android.content.ComponentName; import android.content.Context; @@ -23,6 +26,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.UrlConstants; +import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder.DelegatedNotificationSmallIconFallback; import org.chromium.chrome.browser.notifications.NotificationBuilderBase; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; @@ -34,12 +38,17 @@ */ public class TrustedWebActivityClient { private final TrustedWebActivityServiceConnectionManager mConnection; + private final TrustedWebActivityUmaRecorder mRecorder; + private final NotificationUmaTracker mNotificationUmaTracker; /** * Creates a TrustedWebActivityService. */ - public TrustedWebActivityClient(TrustedWebActivityServiceConnectionManager connection) { + public TrustedWebActivityClient(TrustedWebActivityServiceConnectionManager connection, + TrustedWebActivityUmaRecorder recorder, NotificationUmaTracker notificationUmaTracker) { mConnection = connection; + mRecorder = recorder; + mNotificationUmaTracker = notificationUmaTracker; } /** @@ -70,27 +79,31 @@ Notification notification = builder.build(); - boolean success = - service.notify(platformTag, platformId, notification, channelDisplayName); + service.notify(platformTag, platformId, notification, channelDisplayName); - if (success) { - NotificationUmaTracker.getInstance().onNotificationShown( - NotificationUmaTracker.SystemNotificationType.SITES, notification); - } + mNotificationUmaTracker.onNotificationShown( + NotificationUmaTracker.SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES, + notification); }); } private void fallbackToIconFromServiceIfNecessary(NotificationBuilderBase builder, TrustedWebActivityServiceWrapper service) throws RemoteException { if (builder.hasSmallIconForContent() && builder.hasStatusBarIconBitmap()) { + recordFallback(NO_FALLBACK); return; } int id = service.getSmallIconId(); if (id == TrustedWebActivityService.NO_ID) { + recordFallback(FALLBACK_ICON_NOT_PROVIDED); return; } + recordFallback(builder.hasSmallIconForContent() + ? DelegatedNotificationSmallIconFallback.FALLBACK_FOR_STATUS_BAR + : DelegatedNotificationSmallIconFallback.FALLBACK_FOR_STATUS_BAR_AND_CONTENT); + Bitmap bitmap = service.getSmallIconBitmap(); if (!builder.hasStatusBarIconBitmap()) { builder.setStatusBarIconForUntrustedRemoteApp(id, bitmap, @@ -101,6 +114,10 @@ } } + private void recordFallback(@DelegatedNotificationSmallIconFallback int fallback) { + mRecorder.recordDelegatedNotificationSmallIconFallback(fallback); + } + /** * Cancels a notification through a Trusted Web Activity client. * @param scope The scope of the Service Worker that triggered the notification.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java new file mode 100644 index 0000000..036c970 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java
@@ -0,0 +1,121 @@ +// 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. + +package org.chromium.chrome.browser.browserservices; + +import android.support.annotation.IntDef; +import android.support.annotation.Nullable; + +import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.metrics.RecordUserAction; +import org.chromium.chrome.browser.tab.Tab; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +/** + * Encapsulates Uma recording actions related to Trusted Web Activities. + */ +public class TrustedWebActivityUmaRecorder { + @Retention(RetentionPolicy.SOURCE) + @IntDef({DelegatedNotificationSmallIconFallback.NO_FALLBACK, + DelegatedNotificationSmallIconFallback.FALLBACK_ICON_NOT_PROVIDED, + DelegatedNotificationSmallIconFallback.FALLBACK_FOR_STATUS_BAR, + DelegatedNotificationSmallIconFallback.FALLBACK_FOR_STATUS_BAR_AND_CONTENT}) + public @interface DelegatedNotificationSmallIconFallback { + int NO_FALLBACK = 0; + int FALLBACK_ICON_NOT_PROVIDED = 1; + int FALLBACK_FOR_STATUS_BAR = 2; + int FALLBACK_FOR_STATUS_BAR_AND_CONTENT = 3; + int NUM_ENTRIES = 4; + } + + @Inject + public TrustedWebActivityUmaRecorder() {} + + /** + * Records that a Trusted Web Activity has been opened. + */ + public void recordTwaOpened(@Nullable Tab tab) { + RecordUserAction.record("BrowserServices.TwaOpened"); + if (tab != null) { + new UkmRecorder.Bridge().recordTwaOpened(tab); + } + } + + /** + * Records the time that a Trusted Web Activity has been in resumed state. + */ + public void recordTwaOpenTime(long durationMs) { + recordDuration(durationMs, "BrowserServices.TwaOpenTime"); + } + + /** + * Records the time spent in verified origin until navigating to unverified one or pausing + * the Trusted Web Activity. + */ + public void recordTimeInVerifiedOrigin(long durationMs) { + recordDuration(durationMs, "TrustedWebActivity.TimeInVerifiedOrigin"); + } + + /** + * Records the time spent in verified origin until navigating to unverified one or pausing + * the Trusted Web Activity. + */ + public void recordTimeOutOfVerifiedOrigin(long durationMs) { + recordDuration(durationMs, "TrustedWebActivity.TimeOutOfVerifiedOrigin"); + } + + private void recordDuration(long durationMs, String histogramName) { + RecordHistogram.recordTimesHistogram(histogramName, durationMs, TimeUnit.MILLISECONDS); + } + + /** + * Records the fact that disclosure was shown. + */ + public void recordDisclosureShown() { + RecordUserAction.record("TrustedWebActivity.DisclosureShown"); + } + + /** + * Records the fact that disclosure was accepted by user. + */ + public void recordDisclosureAccepted() { + RecordUserAction.record("TrustedWebActivity.DisclosureAccepted"); + } + + /** + * Records which action the user took upon seeing a clear data dialog. + * @param accepted Whether user proceeded to the settings from the dialog. + * @param triggeredByUninstall Whether the dialog was triggered by app uninstall as opposed to + * app data getting cleared. + */ + public void recordClearDataDialogAction(boolean accepted, boolean triggeredByUninstall) { + String histogramName = triggeredByUninstall + ? "TrustedWebActivity.ClearDataDialogOnUninstallAccepted" + : "TrustedWebActivity.ClearDataDialogOnClearAppDataAccepted"; + RecordHistogram.recordBooleanHistogram(histogramName, accepted); + } + + /** + * Records the fact that site settings were opened via "Manage Space" button in TWA client app's + * settings. + */ + public void recordOpenedSettingsViaManageSpace() { + RecordUserAction.record("TrustedWebActivity.OpenedSettingsViaManageSpace"); + } + + /** + * Records which fallback (if any) was used for the small icon of a delegated notification. + */ + public void recordDelegatedNotificationSmallIconFallback( + @DelegatedNotificationSmallIconFallback int fallback) { + RecordHistogram.recordEnumeratedHistogram( + "TrustedWebActivity.DelegatedNotificationSmallIconFallback", fallback, + DelegatedNotificationSmallIconFallback.NUM_ENTRIES); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/UkmRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/UkmRecorder.java index e2ded9f..1eff79c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/UkmRecorder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/UkmRecorder.java
@@ -6,6 +6,7 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeCall; +import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.WebContents; /** @@ -14,9 +15,9 @@ */ public interface UkmRecorder { /** - * Records a TWA has been opened. + * Records a TWA has been opened in given tab. */ - void recordTwaOpened(WebContents webContents); + void recordTwaOpened(Tab tab); /** * The actual recorder. @@ -24,8 +25,8 @@ @JNINamespace("browserservices") class Bridge implements UkmRecorder { @Override - public void recordTwaOpened(WebContents webContents) { - nativeRecordOpen(webContents); + public void recordTwaOpened(Tab tab) { + nativeRecordOpen(tab.getWebContents()); } @NativeCall("Bridge")
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureController.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureController.java index db3f629..98142806 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureController.java
@@ -11,6 +11,7 @@ import static org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityModel.DISCLOSURE_STATE_SHOWN; import static org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VERIFICATION_FAILURE; +import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityModel; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VerificationState; import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher; @@ -28,16 +29,19 @@ private final ChromePreferenceManager mPreferenceManager; private final TrustedWebActivityModel mModel; private final TrustedWebActivityVerifier mVerifier; + private final TrustedWebActivityUmaRecorder mRecorder; @Inject TrustedWebActivityDisclosureController( ChromePreferenceManager preferenceManager, TrustedWebActivityModel model, ActivityLifecycleDispatcher lifecycleDispatcher, - TrustedWebActivityVerifier verifier) { + TrustedWebActivityVerifier verifier, + TrustedWebActivityUmaRecorder recorder) { mVerifier = verifier; mPreferenceManager = preferenceManager; mModel = model; + mRecorder = recorder; model.set(DISCLOSURE_EVENTS_CALLBACK, this); verifier.addVerificationObserver(this::onVerificationStatusChanged); lifecycleDispatcher.register(this); @@ -53,6 +57,7 @@ @Override public void onDisclosureAccepted() { + mRecorder.recordDisclosureAccepted(); mPreferenceManager.setUserAcceptedTwaDisclosureForPackage(mVerifier.getClientPackageName()); mModel.set(DISCLOSURE_STATE, DISCLOSURE_STATE_DISMISSED_BY_USER); } @@ -60,6 +65,7 @@ /** Shows the disclosure if it is not already showing and hasn't been accepted. */ private void showIfNeeded() { if (!isShowing() && !wasDismissed()) { + mRecorder.recordDisclosureShown(); mModel.set(DISCLOSURE_STATE, DISCLOSURE_STATE_SHOWN); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorder.java index c6bead01..9b4c45e3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorder.java
@@ -4,15 +4,18 @@ package org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller; +import static org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VERIFICATION_PENDING; +import static org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VERIFICATION_SUCCESS; + import android.os.SystemClock; -import org.chromium.chrome.browser.browserservices.BrowserServicesMetrics; +import org.chromium.chrome.browser.ActivityTabProvider; +import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder; +import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VerificationState; import org.chromium.chrome.browser.dependency_injection.ActivityScope; import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver; -import java.util.concurrent.TimeUnit; - import javax.inject.Inject; /** @@ -20,11 +23,27 @@ */ @ActivityScope public class TrustedWebActivityOpenTimeRecorder implements PauseResumeWithNativeObserver { + private final TrustedWebActivityVerifier mVerifier; + private final TrustedWebActivityUmaRecorder mRecorder; + private final ActivityTabProvider mTabProvider; + private long mOnResumeTimestampMs; + private long mLastStateChangeTimestampMs; + + private boolean mInVerifiedOrigin; + private boolean mTwaOpenedRecorded; @Inject - TrustedWebActivityOpenTimeRecorder(ActivityLifecycleDispatcher lifecycleDispatcher) { + TrustedWebActivityOpenTimeRecorder( + ActivityLifecycleDispatcher lifecycleDispatcher, + TrustedWebActivityVerifier verifier, + TrustedWebActivityUmaRecorder recorder, + ActivityTabProvider provider) { + mVerifier = verifier; + mRecorder = recorder; + mTabProvider = provider; lifecycleDispatcher.register(this); + verifier.addVerificationObserver(this::onVerificationStateChanged); } @Override @@ -35,8 +54,40 @@ @Override public void onPauseWithNative() { assert mOnResumeTimestampMs != 0; - BrowserServicesMetrics.recordTwaOpenTime( - SystemClock.elapsedRealtime() - mOnResumeTimestampMs, TimeUnit.MILLISECONDS); + mRecorder.recordTwaOpenTime(SystemClock.elapsedRealtime() - mOnResumeTimestampMs); + recordTimeCurrentState(); mOnResumeTimestampMs = 0; } + + private void onVerificationStateChanged() { + VerificationState state = mVerifier.getState(); + if (state == null || state.status == VERIFICATION_PENDING) { + return; + } + boolean inVerifiedOrigin = state.status == VERIFICATION_SUCCESS; + if (inVerifiedOrigin == mInVerifiedOrigin) { + return; + } + recordTimeCurrentState(); + mInVerifiedOrigin = inVerifiedOrigin; + mLastStateChangeTimestampMs = SystemClock.elapsedRealtime(); + + if (mInVerifiedOrigin && !mTwaOpenedRecorded) { + mRecorder.recordTwaOpened(mTabProvider.getActivityTab()); + mTwaOpenedRecorded = true; + } + } + + private void recordTimeCurrentState() { + if (mLastStateChangeTimestampMs == 0) { + return; + } + long timeInCurrentState = SystemClock.elapsedRealtime() + - Math.max(mLastStateChangeTimestampMs, mOnResumeTimestampMs); + if (mInVerifiedOrigin) { + mRecorder.recordTimeInVerifiedOrigin(timeInCurrentState); + } else { + mRecorder.recordTimeOutOfVerifiedOrigin(timeInCurrentState); + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java index 582d670..cf06271 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
@@ -11,7 +11,6 @@ import org.chromium.base.ObserverList; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.ChromeFeatureList; -import org.chromium.chrome.browser.browserservices.BrowserServicesMetrics; import org.chromium.chrome.browser.browserservices.Origin; import org.chromium.chrome.browser.browserservices.OriginVerifier; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityModel; @@ -162,7 +161,6 @@ new OriginVerifier((packageName2, origin2, verified, online) -> { if (!origin.equals(new Origin(tab.getUrl()))) return; - BrowserServicesMetrics.recordTwaOpened(); handleVerificationResult(verified, origin); }, mClientPackageName, RELATIONSHIP).start(origin); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/view/PersistentNotificationView.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/view/PersistentNotificationView.java index 706d6aa6..49b7654d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/view/PersistentNotificationView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/view/PersistentNotificationView.java
@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.notifications.NotificationBuilderFactory; import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; import org.chromium.chrome.browser.preferences.PreferencesLauncher; +import org.chromium.chrome.browser.preferences.website.SettingsNavigationSource; import javax.inject.Inject; import javax.inject.Named; @@ -164,7 +165,7 @@ private PendingIntent makeManageDataIntent() { Intent settingsIntent = PreferencesLauncher.createIntentForSingleWebsitePreferences( - mAppContext, mOrigin.toString()); + mAppContext, mOrigin.toString(), SettingsNavigationSource.OTHER); return PendingIntent.getActivity(mAppContext, 0, settingsIntent, FLAG_UPDATE_CURRENT); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppComponent.java index e2a6d1c..fe65f00 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppComponent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppComponent.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.dependency_injection; import org.chromium.chrome.browser.AppHooksModule; +import org.chromium.chrome.browser.browserservices.ClearDataDialogResultRecorder; import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsModule; import org.chromium.chrome.browser.contextual_suggestions.EnabledStateMonitor; import org.chromium.chrome.browser.customtabs.CustomTabsConnection; @@ -32,6 +33,7 @@ CustomTabsConnection resolveCustomTabsConnection(); ChromePreferenceManager resolvePreferenceManager(); + ClearDataDialogResultRecorder resolveTwaClearDataDialogRecorder(); // Temporary getters for DI migration process. All of these getters // should eventually be replaced with constructor injection.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java index 102a7b04..fc16f638 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java
@@ -12,6 +12,7 @@ import org.chromium.base.ContextUtils; import org.chromium.chrome.browser.contextual_suggestions.EnabledStateMonitor; import org.chromium.chrome.browser.contextual_suggestions.EnabledStateMonitorImpl; +import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.profiles.Profile; @@ -51,4 +52,9 @@ public Context provideContext() { return ContextUtils.getApplicationContext(); } + + @Provides + public ChromeBrowserInitializer provideChromeBrowserInitializer() { + return ChromeBrowserInitializer.getInstance(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java index 532c41b1..cc136f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -429,6 +429,10 @@ MediaViewerUtils.updateMediaLauncherActivityEnabled( ContextUtils.getApplicationContext()); }); + + deferredStartupHandler.addDeferredTask( + ChromeApplication.getComponent().resolveTwaClearDataDialogRecorder() + ::makeDeferredRecordings); } private void initChannelsAsync() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java index 850da54..9d7f617 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -30,6 +30,7 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient; +import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager; @@ -132,7 +133,9 @@ mNotificationManager = new NotificationManagerProxyImpl(context); } mTwaClient = new TrustedWebActivityClient( - new TrustedWebActivityServiceConnectionManager(context)); + new TrustedWebActivityServiceConnectionManager(context), + new TrustedWebActivityUmaRecorder(), + NotificationUmaTracker.getInstance()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java index 2df9608e..a6ded43 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
@@ -41,7 +41,8 @@ SystemNotificationType.MEDIA, SystemNotificationType.SITES, SystemNotificationType.SYNC, SystemNotificationType.WEBAPK, SystemNotificationType.BROWSER_ACTIONS, SystemNotificationType.WEBAPP_ACTIONS, - SystemNotificationType.OFFLINE_CONTENT_SUGGESTION}) + SystemNotificationType.OFFLINE_CONTENT_SUGGESTION, + SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES}) @Retention(RetentionPolicy.SOURCE) public @interface SystemNotificationType { int DOWNLOAD_FILES = 0; @@ -60,8 +61,9 @@ int BROWSER_ACTIONS = 10; int WEBAPP_ACTIONS = 11; int OFFLINE_CONTENT_SUGGESTION = 12; + int TRUSTED_WEB_ACTIVITY_SITES = 13; - int NUM_ENTRIES = 13; + int NUM_ENTRIES = 14; } private static final String LAST_SHOWN_NOTIFICATION_TYPE_KEY =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java index ec6c1cc..0d6d7744 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -232,6 +232,15 @@ public static final String LATEST_UNSUPPORTED_VERSION = "android_os_unsupported_chrome_version"; /** + * Keys for deferred recording of the outcomes of showing the clear data dialog after + * Trusted Web Activity client apps are uninstalled or have their data cleared. + */ + public static final String TWA_DIALOG_NUMBER_OF_DIMSISSALS_ON_UNINSTALL = + "twa_dialog_number_of_dismissals_on_uninstall"; + public static final String TWA_DIALOG_NUMBER_OF_DIMSISSALS_ON_CLEAR_DATA = + "twa_dialog_number_of_dismissals_on_clear_data"; + + /** * Deprecated keys for Chrome Home. */ private static final String CHROME_HOME_USER_ENABLED_KEY = "chrome_home_user_enabled";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java index 32f0911..bd2263d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.AppHooks; import org.chromium.chrome.browser.preferences.autofill.AutofillPaymentMethodsFragment; import org.chromium.chrome.browser.preferences.autofill.AutofillProfilesFragment; +import org.chromium.chrome.browser.preferences.website.SettingsNavigationSource; import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.content_public.browser.WebContents; @@ -94,10 +95,11 @@ /** * Creates an intent to launch single website preferences for the specified {@param url}. */ - public static Intent createIntentForSingleWebsitePreferences(Context context, String url) { - return createIntentForSettingsPage( - context, SingleWebsitePreferences.class.getName(), - SingleWebsitePreferences.createFragmentArgsForSite(url)); + public static Intent createIntentForSingleWebsitePreferences( + Context context, String url, @SettingsNavigationSource int navigationSource) { + Bundle args = SingleWebsitePreferences.createFragmentArgsForSite(url); + args.putInt(SettingsNavigationSource.EXTRA_KEY, navigationSource); + return createIntentForSettingsPage(context, SingleWebsitePreferences.class.getName(), args); } @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SettingsNavigationSource.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SettingsNavigationSource.java new file mode 100644 index 0000000..b4fe981 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SettingsNavigationSource.java
@@ -0,0 +1,29 @@ +// 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. + +package org.chromium.chrome.browser.preferences.website; + +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Sources of navigation into settings screens, used for UMA tracking purposes. + */ +@Retention(RetentionPolicy.SOURCE) +@IntDef({ + SettingsNavigationSource.OTHER, + SettingsNavigationSource.TWA_CLEAR_DATA_DIALOG, + SettingsNavigationSource.TWA_MANAGE_SPACE_ACTIVITY, +}) +public @interface SettingsNavigationSource { + int OTHER = 0; + int TWA_CLEAR_DATA_DIALOG = 1; + int TWA_MANAGE_SPACE_ACTIVITY = 2; + int NUM_ENTRIES = 3; + + // The key of the intent extra that is used for passing around the source. + String EXTRA_KEY = "org.chromium.chrome.preferences.navigation_source"; +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java index 1b68318f..9f0b26f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
@@ -382,6 +382,9 @@ } else { website.putSiteAddressIntoExtras(SingleWebsitePreferences.EXTRA_SITE_ADDRESS); } + int navigationSource = getArguments().getInt( + SettingsNavigationSource.EXTRA_KEY, SettingsNavigationSource.OTHER); + website.getExtras().putInt(SettingsNavigationSource.EXTRA_KEY, navigationSource); } return super.onPreferenceTreeClick(screen, preference);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java index d6e2be8b..eaf74787 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
@@ -25,6 +25,7 @@ import android.widget.ListView; import org.chromium.base.VisibleForTesting; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.ContentSettingsType; import org.chromium.chrome.browser.browserservices.Origin; @@ -799,6 +800,11 @@ mSiteDataCleaner.clearData(mSite, mDataClearedCallback); + int navigationSource = getArguments().getInt( + SettingsNavigationSource.EXTRA_KEY, SettingsNavigationSource.OTHER); + RecordHistogram.recordEnumeratedHistogram("SingleWebsitePreferences.NavigatedFromToReset", + navigationSource, SettingsNavigationSource.NUM_ENTRIES); + if (finishActivityImmediately) { getActivity().finish(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java index b339876..0c41146 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
@@ -96,12 +96,13 @@ mMenuButton = toolbarRoot.findViewById(R.id.menu_button_wrapper); - final View iphAnchor = toolbarRoot.findViewById(R.id.bottom_toolbar_container); + final View iphAnchor = toolbarRoot.findViewById(R.id.search_accelerator); tabProvider.addObserverAndTrigger(new HintlessActivityTabObserver() { @Override public void onActivityTabChanged(Tab tab) { if (tab == null) return; - mMediator.showIPH(iphAnchor, TrackerFactory.getTrackerForProfile(tab.getProfile())); + mMediator.showIPH(tab.getActivity(), iphAnchor, + TrackerFactory.getTrackerForProfile(tab.getProfile())); tabProvider.removeObserver(this); } });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java index 103528b..c5cb254 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java
@@ -8,7 +8,9 @@ import android.content.res.Resources; import android.view.View; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.OverlayPanelManagerObserver; import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; @@ -21,13 +23,12 @@ import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener; import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; -import org.chromium.chrome.browser.widget.textbubble.TextBubble; +import org.chromium.chrome.browser.widget.FeatureHighlightProvider; import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.components.feature_engagement.Tracker; import org.chromium.ui.KeyboardVisibilityDelegate; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.resources.ResourceManager; -import org.chromium.ui.widget.ViewRectProvider; /** * This class is responsible for reacting to events from the outside world, interacting with other @@ -41,6 +42,9 @@ /** The amount of time to show the Duet help bubble for. */ private static final int DUET_IPH_BUBBLE_SHOW_DURATION_MS = 6000; + /** The transparency fraction of the IPH bubble. */ + private static final float DUET_IPH_BUBBLE_ALPHA_FRACTION = 0.9f; + /** The model for the browsing mode bottom toolbar that holds all of its state. */ private BrowsingModeBottomToolbarModel mModel; @@ -122,19 +126,27 @@ /** * Maybe show the IPH bubble for Chrome Duet. + * @param activity An activity to attach the IPH to. * @param anchor The view to anchor the IPH to. * @param tracker A tracker for IPH. */ - void showIPH(View anchor, Tracker tracker) { - if (tracker.shouldTriggerHelpUI(FeatureConstants.CHROME_DUET_FEATURE)) { - TextBubble bubble = - new TextBubble(anchor.getContext(), anchor, R.string.iph_duet_icons_moved, - R.string.iph_duet_icons_moved, true, new ViewRectProvider(anchor)); - bubble.setAutoDismissTimeout(DUET_IPH_BUBBLE_SHOW_DURATION_MS); - bubble.addOnDismissListener( - () -> tracker.dismissed(FeatureConstants.CHROME_DUET_FEATURE)); - bubble.show(); - } + void showIPH(ChromeActivity activity, View anchor, Tracker tracker) { + if (!tracker.shouldTriggerHelpUI(FeatureConstants.CHROME_DUET_FEATURE)) return; + int baseColor = + ApiCompatibilityUtils.getColor(anchor.getResources(), R.color.modern_blue_600); + + // Clear out the alpha and use custom transparency. + int finalColor = + (baseColor & 0x00FFFFFF) | ((int) (DUET_IPH_BUBBLE_ALPHA_FRACTION * 255) << 24); + + FeatureHighlightProvider.getInstance().buildForView(activity, anchor, + R.string.iph_duet_start_search, FeatureHighlightProvider.TextAlignment.CENTER, + R.style.WhiteTitle1, R.string.iph_duet_icons_moved, + FeatureHighlightProvider.TextAlignment.CENTER, R.style.WhiteBody, finalColor, + DUET_IPH_BUBBLE_SHOW_DURATION_MS); + + anchor.postDelayed(() -> tracker.dismissed(FeatureConstants.CHROME_DUET_FEATURE), + DUET_IPH_BUBBLE_SHOW_DURATION_MS); } boolean isVisible() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialog.java index f160378c..cad435d8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialog.java
@@ -4,9 +4,12 @@ package org.chromium.chrome.browser.webapps; +import android.annotation.TargetApi; import android.app.Activity; import android.content.DialogInterface; import android.graphics.Bitmap; +import android.graphics.drawable.Icon; +import android.os.Build; import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.TextUtils; @@ -229,13 +232,27 @@ /** * Called when the home screen icon is available. Must be called after onUserTitleAvailable(). - * @param icon Icon to use in the launcher. + * @param icon that will be used in the launcher. */ public void onIconAvailable(Bitmap icon) { + mIconView.setImageBitmap(icon); + setIconAvailable(); + } + + /** + * Called when the home screen icon is available and was generated to be an Android adaptable + * icon. Must be called after onUserTitleAvailable(). + * @param icon that will be used in the launcher. + */ + @TargetApi(Build.VERSION_CODES.O) + public void onAdaptableIconAvailable(Bitmap icon) { + mIconView.setImageIcon(Icon.createWithAdaptiveBitmap(icon)); + setIconAvailable(); + } + + private void setIconAvailable() { mProgressBarView.setVisibility(View.GONE); mIconView.setVisibility(View.VISIBLE); - mIconView.setImageBitmap(icon); - mHasIcon = true; updateAddButtonEnabledState(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenManager.java index 549e0fa..e6f07d7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenManager.java
@@ -6,6 +6,7 @@ import android.app.Activity; import android.graphics.Bitmap; +import android.os.Build; import android.text.TextUtils; import org.chromium.base.annotations.CalledByNative; @@ -93,8 +94,13 @@ } @CalledByNative - private void onIconAvailable(Bitmap icon) { - mDialog.onIconAvailable(icon); + private void onIconAvailable(Bitmap icon, boolean iconAdaptable) { + if (iconAdaptable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + mDialog.onAdaptableIconAvailable(icon); + } else { + assert !iconAdaptable : "Adaptive icons should not be provided pre-Android O."; + mDialog.onIconAvailable(icon); + } } private native long nativeInitializeAndStart(WebContents webContents);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/FeatureHighlightProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/FeatureHighlightProvider.java new file mode 100644 index 0000000..da2327f --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/FeatureHighlightProvider.java
@@ -0,0 +1,59 @@ +// 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. + +package org.chromium.chrome.browser.widget; + +import android.support.annotation.ColorInt; +import android.support.annotation.IntDef; +import android.support.annotation.StringRes; +import android.support.annotation.StyleRes; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +import org.chromium.chrome.browser.AppHooks; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** A means of showing highlight for a particular feature as a form of in product help. */ +public class FeatureHighlightProvider { + /** + * These values determine text alignment and need to match the values in the closed-source + * library. + */ + @IntDef({TextAlignment.START, TextAlignment.CENTER, TextAlignment.END}) + @Retention(RetentionPolicy.SOURCE) + public @interface TextAlignment { + int START = 0; + int CENTER = 1; + int END = 2; + } + + /** Static handle to the sole highlight provider. */ + private static FeatureHighlightProvider sInstance; + + /** + * @return A handle to the highlight provider. + */ + public static FeatureHighlightProvider getInstance() { + if (sInstance == null) sInstance = AppHooks.get().createFeatureHighlightProvider(); + return sInstance; + } + + /** + * Build and show a feature highlight bubble for a particular view. + * @param activity An activity to attach the highlight to. + * @param view The view to focus. + * @param headTextId The text shown in the header section of the bubble. + * @param headAlignment Alignment of the head text. + * @param bodyTextId The text shown in the body section of the bubble. + * @param bodyAlignment Alignment of the body text. + * @param color The color of the bubble. + * @param timeoutMs The amount of time in ms before the bubble disappears. + */ + public void buildForView(AppCompatActivity activity, View view, @StringRes int headTextId, + @TextAlignment int headAlignment, @StyleRes int headStyle, @StringRes int bodyTextId, + @TextAlignment int bodyAlignment, @StyleRes int bodyStyle, @ColorInt int color, + long timeoutMs) {} +}
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 4bcbbc5..9daf9ce 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -3926,8 +3926,11 @@ </message> <!-- Chrome Duet --> + <message name="IDS_IPH_DUET_START_SEARCH" desc="The in-product help message for the split toolbar experiment that explains that the user can start a new web search using the focused icon."> + Tap here to quickly begin a search + </message> <message name="IDS_IPH_DUET_ICONS_MOVED" desc="The in-product help message for the split toolbar experiment that explains that the user's icons (menu button, tab switcher button, and home button) have moved to the bottom of the screen."> - Your icons have moved to the bottom of the screen + Easily navigate anywhere in Chrome using the buttons at the bottom of your screen </message> <!-- Photo picker -->
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 3f7d803..e0cf3fc 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -185,6 +185,7 @@ "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java", "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java", "java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java", + "java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java", "java/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisher.java", "java/src/org/chromium/chrome/browser/browserservices/ClearDataService.java", "java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java", @@ -196,6 +197,7 @@ "java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java", "java/src/org/chromium/chrome/browser/browserservices/Relationship.java", "java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java", + "java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java", "java/src/org/chromium/chrome/browser/browserservices/UkmRecorder.java", "java/src/org/chromium/chrome/browser/browserservices/VerificationResultStore.java", "java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/TrustedWebActivityCoordinator.java", @@ -1365,6 +1367,7 @@ "java/src/org/chromium/chrome/browser/preferences/website/ManageSpaceActivity.java", "java/src/org/chromium/chrome/browser/preferences/website/NotificationCategory.java", "java/src/org/chromium/chrome/browser/preferences/website/PermissionInfo.java", + "java/src/org/chromium/chrome/browser/preferences/website/SettingsNavigationSource.java", "java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java", "java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java", "java/src/org/chromium/chrome/browser/preferences/website/SiteDataCleaner.java", @@ -1725,6 +1728,7 @@ "java/src/org/chromium/chrome/browser/widget/FadingEdgeScrollView.java", "java/src/org/chromium/chrome/browser/widget/FadingShadow.java", "java/src/org/chromium/chrome/browser/widget/FadingShadowView.java", + "java/src/org/chromium/chrome/browser/widget/FeatureHighlightProvider.java", "java/src/org/chromium/chrome/browser/widget/FullscreenControlContainer.java", "java/src/org/chromium/chrome/browser/widget/ListMenuButton.java", "java/src/org/chromium/chrome/browser/widget/LoadingView.java", @@ -2316,6 +2320,7 @@ "junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetControllerTest.java", "junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java", "junit/src/org/chromium/chrome/browser/browseractions/BrowserActionsIntentTest.java", + "junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java", "junit/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisherTest.java", "junit/src/org/chromium/chrome/browser/browserservices/ClearDataServiceTest.java", "junit/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiverTest.java", @@ -2325,6 +2330,7 @@ "junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java", "junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/ClientAppDataRecorderTest.java", "junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureControllerTest.java", + "junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorderTest.java", "junit/src/org/chromium/chrome/browser/cached_image_fetcher/CachedImageFetcherImplTest.java", "junit/src/org/chromium/chrome/browser/cached_image_fetcher/InMemoryCachedImageFetcherTest.java", "junit/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimatorTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index df1c767..dc85b54 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -189,7 +189,8 @@ AppBannerManager.setIsSupported(true); ShortcutHelper.setDelegateForTests(new ShortcutHelper.Delegate() { @Override - public void addShortcutToHomescreen(String title, Bitmap icon, Intent shortcutIntent) { + public void addShortcutToHomescreen( + String title, Bitmap icon, boolean iconAdaptive, Intent shortcutIntent) { // Ignore to prevent adding homescreen shortcuts. } });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java index 6283c259..4a5748b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
@@ -26,9 +26,11 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.R; +import org.chromium.chrome.browser.notifications.NotificationUmaTracker; import org.chromium.chrome.browser.notifications.StandardNotificationBuilder; import java.util.concurrent.TimeoutException; @@ -118,10 +120,12 @@ @Before public void setUp() throws TimeoutException, RemoteException, InterruptedException { + RecordHistogram.setDisabledForTests(true); mTargetContext = InstrumentationRegistry.getTargetContext(); mBuilder = new StandardNotificationBuilder(mTargetContext); mClient = new TrustedWebActivityClient(new TrustedWebActivityServiceConnectionManager( - ContextUtils.getApplicationContext())); + ContextUtils.getApplicationContext()), new TrustedWebActivityUmaRecorder(), + NotificationUmaTracker.getInstance()); // TestTrustedWebActivityService is in the test support apk. TrustedWebActivityClient.registerClient(mTargetContext, ORIGIN, TEST_SUPPORT_PACKAGE);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedContentStorageConformanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedContentStorageConformanceTest.java index f313b01..b26d75c6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedContentStorageConformanceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedContentStorageConformanceTest.java
@@ -37,7 +37,7 @@ @SmallTest @RunWith(ChromeJUnit4ClassRunner.class) public final class FeedContentStorageConformanceTest extends ContentStorageConformanceTest { - private static final long TIMEOUT = scaleTimeout(1000); + private static final long TIMEOUT = scaleTimeout(3000); class ContentStorageWrapper extends FeedContentStorage { public ContentStorageWrapper(Profile p) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java index a7e99ac5..0456028 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -20,7 +20,6 @@ import android.os.Handler; import android.os.Looper; import android.provider.Browser; -import android.support.test.InstrumentationRegistry; import android.support.test.espresso.intent.rule.IntentsTestRule; import android.support.test.filters.SmallTest; import android.support.v7.widget.RecyclerView; @@ -675,7 +674,7 @@ // Sign in to account. Note that if supervised user is set before sign in, the supervised // user setting will be reset. - SigninTestUtil.setUpAuthForTest(InstrumentationRegistry.getInstrumentation()); + SigninTestUtil.setUpAuthForTest(); final Account account = SigninTestUtil.addTestAccount(); ThreadUtils.runOnUiThreadBlocking(() -> { SigninManager.get().onFirstRunCheckDone();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasicTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasicTest.java index 37311ba..2be5667c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasicTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasicTest.java
@@ -54,7 +54,7 @@ @Before public void setUp() throws InterruptedException { - SigninTestUtil.setUpAuthForTest(InstrumentationRegistry.getInstrumentation()); + SigninTestUtil.setUpAuthForTest(); mActivityTestRule.startMainActivityOnBlankPage(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java index 1db9f72..dd826ef 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
@@ -83,7 +83,7 @@ @Before public void setUp() throws Exception { - SigninTestUtil.setUpAuthForTest(InstrumentationRegistry.getInstrumentation()); + SigninTestUtil.setUpAuthForTest(); mActivityTestRule.startMainActivityOnBlankPage(); mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java index 3e54939..e843315 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
@@ -215,7 +215,7 @@ @Before public void setUp() throws Exception { // Mock out the account manager on the device. - SigninTestUtil.setUpAuthForTest(InstrumentationRegistry.getInstrumentation()); + SigninTestUtil.setUpAuthForTest(); mActivityTestRule.startMainActivityOnBlankPage(); mContext = InstrumentationRegistry.getTargetContext();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java index 174a229..44908cf9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
@@ -271,7 +271,7 @@ ApplicationTestUtils.clearAppData(InstrumentationRegistry.getTargetContext()); // This must be called before super.setUp() in order for test authentication to work. - SigninTestUtil.setUpAuthForTest(InstrumentationRegistry.getInstrumentation()); + SigninTestUtil.setUpAuthForTest(); } private void ruleTearDown() throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java index 34c1b9d..04cd2e5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java
@@ -458,7 +458,7 @@ throws Exception { // Load up the metadata file via a TabPersistentStore to make sure that it contains all of // the migrated tab information. - SigninTestUtil.setUpAuthForTest(InstrumentationRegistry.getInstrumentation()); + SigninTestUtil.setUpAuthForTest(); mTestRule.loadNativeLibraryAndInitBrowserProcess(); TabPersistentStore.setBaseStateDirectoryForTests(mTabbedModeDirectory.getBaseDirectory());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ChromeBrowserTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ChromeBrowserTestRule.java index 8dcb8e4..9b8f6361 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ChromeBrowserTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ChromeBrowserTestRule.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.test; -import android.app.Instrumentation; import android.support.test.InstrumentationRegistry; import org.junit.runner.Description; @@ -19,9 +18,9 @@ * initializing the AccountManagerFacade. */ public class ChromeBrowserTestRule extends NativeLibraryTestRule { - private void setUp(Instrumentation instrumentation) { + private void setUp() { ApplicationData.clearAppData(InstrumentationRegistry.getTargetContext()); - SigninTestUtil.setUpAuthForTest(instrumentation); + SigninTestUtil.setUpAuthForTest(); loadNativeLibraryAndInitBrowserProcess(); } @@ -35,7 +34,7 @@ * UI thread). After loading the library, this will initialize the browser process * if necessary. */ - setUp(InstrumentationRegistry.getInstrumentation()); + setUp(); try { base.evaluate(); } finally {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md index 526dde0..29e0ece 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md
@@ -1,5 +1,15 @@ # XR Instrumentation Tests +## TL;DR For Most Local Repros + +1. Get a rooted Pixel device of some sort. +2. Make sure "VR Services" is up to date in the Playstore. +3. Run `ninja -C out/Debug chrome_public_test_vr_apk + && out/Debug/bin/run_chrome_public_test_vr_apk + --num-retries=0 + --shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json + --test-filter=<failing test case>` + ## Introduction This directory contains all the Java-side infrastructure for running
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java index df318b9..098f01f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java
@@ -7,6 +7,7 @@ import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; +import android.os.Build; import android.support.test.filters.SmallTest; import android.text.TextUtils; @@ -18,6 +19,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.RetryOnFailure; @@ -82,14 +84,23 @@ + "<title>" + META_APP_NAME_PAGE_TITLE + "</title>" + "</head><body>Webapp capable</body></html>"); + private static final String NON_MASKABLE_MANIFEST_TEST_PAGE_PATH = + "/chrome/test/data/banners/manifest_test_page.html"; + private static final String MASKABLE_MANIFEST_TEST_PAGE_PATH = + "/chrome/test/data/banners/manifest_test_page.html?manifest=manifest_maskable.json"; + private static final String MANIFEST_TEST_PAGE_TITLE = "Web app banner test page"; + private static class TestShortcutHelperDelegate extends ShortcutHelper.Delegate { public String mRequestedShortcutTitle; public Intent mRequestedShortcutIntent; + public boolean mRequestedShortcutAdaptable; @Override - public void addShortcutToHomescreen(String title, Bitmap icon, Intent shortcutIntent) { + public void addShortcutToHomescreen( + String title, Bitmap icon, boolean iconAdaptable, Intent shortcutIntent) { mRequestedShortcutTitle = title; mRequestedShortcutIntent = shortcutIntent; + mRequestedShortcutAdaptable = iconAdaptable; } @Override @@ -100,6 +111,7 @@ public void clearRequestedShortcutData() { mRequestedShortcutTitle = null; mRequestedShortcutIntent = null; + mRequestedShortcutAdaptable = false; } } @@ -200,6 +212,31 @@ @Test @SmallTest @Feature("{Webapp}") + // The test manifest fulfills the requirements of a WebAPK so disable WebAPKs to force plain old + // add to home screen. + @CommandLineFlags.Add({"disable-features=ImprovedA2HS"}) + @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.O) + public void testAddAdaptableShortcut() throws Exception { + // Test the baseline of no adaptive icon. + loadUrl(mTestServerRule.getServer().getURL(NON_MASKABLE_MANIFEST_TEST_PAGE_PATH), + MANIFEST_TEST_PAGE_TITLE); + addShortcutToTab(mTab, "", true); + + Assert.assertFalse(mShortcutHelperDelegate.mRequestedShortcutAdaptable); + + mShortcutHelperDelegate.clearRequestedShortcutData(); + + // Test the adaptive icon. + loadUrl(mTestServerRule.getServer().getURL(MASKABLE_MANIFEST_TEST_PAGE_PATH), + MANIFEST_TEST_PAGE_TITLE); + addShortcutToTab(mTab, "", true); + + Assert.assertTrue(mShortcutHelperDelegate.mRequestedShortcutAdaptable); + } + + @Test + @SmallTest + @Feature("{Webapp}") public void testAddBookmarkShortcut() throws Exception { loadUrl(NORMAL_HTML, NORMAL_TITLE); addShortcutToTab(mTab, "", true);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java new file mode 100644 index 0000000..8a88fbb --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java
@@ -0,0 +1,120 @@ +// 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. + +package org.chromium.chrome.browser.browserservices; + +import static org.mockito.AdditionalAnswers.answerVoid; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.preferences.ChromePreferenceManager; + +/** + * Tests for {@link ClearDataDialogResultRecorder}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class ClearDataDialogResultRecorderTest { + private final ChromePreferenceManager mPrefsManager = ChromePreferenceManager.getInstance(); + @Mock ChromeBrowserInitializer mBrowserInitializer; + @Mock TrustedWebActivityUmaRecorder mUmaRecorder; + @Captor ArgumentCaptor<Runnable> mTaskOnNativeInitCaptor; + + private ClearDataDialogResultRecorder mRecorder; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + restartApp(); + } + + @Test + public void records_WhenAccepted_AfterNativeInit() { + mRecorder.handleDialogResult(true, true); + finishNativeInit(); + verify(mUmaRecorder).recordClearDataDialogAction(true, true); + } + + @Test + public void records_WhenAccepted_IfNativeAlreadyInited() { + finishNativeInit(); + mRecorder.handleDialogResult(true, true); + verify(mUmaRecorder).recordClearDataDialogAction(true, true); + } + + @Test + public void records_WhenDismissed_IfNativeAlreadyInited() { + finishNativeInit(); + mRecorder.handleDialogResult(false, true); + verify(mUmaRecorder).recordClearDataDialogAction(false, true); + } + + @Test + public void defersRecording_WhenDismissed_IfNativeNotAlreadyInited() { + mRecorder.handleDialogResult(false, true); + verify(mUmaRecorder, never()).recordClearDataDialogAction(anyBoolean(), anyBoolean()); + } + + @Test + public void makesDeferredRecordingOfDismissals() { + mRecorder.handleDialogResult(false, true); + restartApp(); + mRecorder.handleDialogResult(false, true); + restartApp(); + mRecorder.handleDialogResult(false, false); + restartApp(); + + mRecorder.makeDeferredRecordings(); + verify(mUmaRecorder, times(2)).recordClearDataDialogAction(false, true); + verify(mUmaRecorder).recordClearDataDialogAction(false, false); + } + + @Test + public void doesntMakeDeferredRecordingTwice() { + mRecorder.handleDialogResult(false, true); + restartApp(); + mRecorder.makeDeferredRecordings(); + restartApp(); + + clearInvocations(mUmaRecorder); + mRecorder.makeDeferredRecordings(); + verify(mUmaRecorder, never()).recordClearDataDialogAction(anyBoolean(), anyBoolean()); + } + + private void restartApp() { + when(mBrowserInitializer.hasNativeInitializationCompleted()).thenReturn(false); + doNothing().when(mBrowserInitializer).runNowOrAfterNativeInitialization( + mTaskOnNativeInitCaptor.capture()); + mRecorder = new ClearDataDialogResultRecorder(() -> mPrefsManager, mBrowserInitializer, + mUmaRecorder); + } + + private void finishNativeInit() { + for (Runnable task : mTaskOnNativeInitCaptor.getAllValues()) { + task.run(); + } + when(mBrowserInitializer.hasNativeInitializationCompleted()).thenReturn(true); + doAnswer(answerVoid(Runnable::run)).when(mBrowserInitializer) + .runNowOrAfterNativeInitialization(any()); + } + +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java index 2ca5b7c..22f7ec0 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
@@ -29,6 +29,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.notifications.NotificationBuilderBase; +import org.chromium.chrome.browser.notifications.NotificationUmaTracker; /** * Unit tests for {@link TrustedWebActivityClient}. @@ -46,6 +47,10 @@ private TrustedWebActivityServiceWrapper mService; @Mock private NotificationBuilderBase mNotificationBuilder; + @Mock + private TrustedWebActivityUmaRecorder mRecorder; + @Mock + private NotificationUmaTracker mNotificationUmaTracker; @Mock private Bitmap mServiceSmallIconBitmap; @@ -67,7 +72,7 @@ when(mService.getSmallIconBitmap()).thenReturn(mServiceSmallIconBitmap); when(mService.getComponentName()).thenReturn(new ComponentName(CLIENT_PACKAGE_NAME, "")); - mClient = new TrustedWebActivityClient(mConnection); + mClient = new TrustedWebActivityClient(mConnection, mRecorder, mNotificationUmaTracker); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureControllerTest.java index 62497ef..90a29b6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureControllerTest.java
@@ -29,6 +29,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.browserservices.Origin; +import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityModel; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VerificationState; import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher; @@ -46,6 +47,8 @@ @Mock public ChromePreferenceManager mPreferences; @Mock public ActivityLifecycleDispatcher mLifecycleDispatcher; @Mock public TrustedWebActivityVerifier mVerifier; + @Mock public TrustedWebActivityUmaRecorder mRecorder; + @Captor public ArgumentCaptor<Runnable> mVerificationObserverCaptor; public TrustedWebActivityModel mModel = new TrustedWebActivityModel(); @@ -61,7 +64,7 @@ doReturn(false).when(mPreferences).hasUserAcceptedTwaDisclosureForPackage(anyString()); mDisclosureController = new TrustedWebActivityDisclosureController( - mPreferences, mModel, mLifecycleDispatcher, mVerifier); + mPreferences, mModel, mLifecycleDispatcher, mVerifier, mRecorder); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorderTest.java new file mode 100644 index 0000000..9dd02fb --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorderTest.java
@@ -0,0 +1,220 @@ +// 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. + +package org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import static org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VERIFICATION_FAILURE; +import static org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VERIFICATION_PENDING; +import static org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VERIFICATION_SUCCESS; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.ActivityTabProvider; +import org.chromium.chrome.browser.browserservices.Origin; +import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder; +import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VerificationState; +import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VerificationStatus; +import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher; + +import java.util.concurrent.TimeUnit; + +/** + * Tests for {@link TrustedWebActivityOpenTimeRecorder}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class TrustedWebActivityOpenTimeRecorderTest { + + @Mock ActivityLifecycleDispatcher mLifecycleDispatcher; + @Mock TrustedWebActivityVerifier mVerifier; + @Mock TrustedWebActivityUmaRecorder mUmaRecorder; + @Mock ActivityTabProvider mTabProvider; + @Captor ArgumentCaptor<Runnable> mVerificationObserverCaptor; + + private TrustedWebActivityOpenTimeRecorder mRecorder; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + doNothing().when(mVerifier).addVerificationObserver(mVerificationObserverCaptor.capture()); + mRecorder = new TrustedWebActivityOpenTimeRecorder( + mLifecycleDispatcher, mVerifier, mUmaRecorder, mTabProvider); + } + + @Test + public void recordsTwaOpened() { + launchTwa(); + verify(mUmaRecorder).recordTwaOpened(any()); + } + + @Test + public void doesntRecordTwaOpenedTwice() { + launchTwa(); + leaveVerifiedOrigin(); + + clearInvocations(mUmaRecorder); + returnToVerifiedOrigin(); + verify(mUmaRecorder, never()).recordTwaOpened(any()); + } + + @Test + public void recordsTwaOpenTime_OnFirstActivityPause() { + launchTwa(); + advanceTime(3000); + + mRecorder.onPauseWithNative(); + verify(mUmaRecorder).recordTwaOpenTime(3000); + } + + @Test + public void recordsTwaOpenTime_OnSecondActivityPause() { + launchTwa(); + advanceTime(3000); + mRecorder.onPauseWithNative(); + advanceTime(2000); + mRecorder.onResumeWithNative(); + advanceTime(4000); + + clearInvocations(mUmaRecorder); + mRecorder.onPauseWithNative(); + verify(mUmaRecorder).recordTwaOpenTime(4000); + } + + @Test + public void recordsTimeInVerified_WhenLeftVerified() { + launchTwa(); + advanceTime(2000); + + leaveVerifiedOrigin(); + verify(mUmaRecorder).recordTimeInVerifiedOrigin(2000); + } + + @Test + public void recordsTimeOutOfVerified_WhenReturnedToVerified() { + launchTwa(); + advanceTime(2000); + leaveVerifiedOrigin(); + advanceTime(3000); + + returnToVerifiedOrigin(); + verify(mUmaRecorder).recordTimeOutOfVerifiedOrigin(3000); + } + + @Test + public void recordsTimeInVerified_WhenLeftVerifiedAgain() { + launchTwa(); + advanceTime(2000); + leaveVerifiedOrigin(); + advanceTime(3000); + returnToVerifiedOrigin(); + advanceTime(4000); + + clearInvocations(mUmaRecorder); + leaveVerifiedOrigin(); + verify(mUmaRecorder).recordTimeInVerifiedOrigin(4000); + } + + @Test + public void recordsTimeOutOfVerified_WhenReturnedToVerifiedAgain() { + launchTwa(); + advanceTime(2000); + leaveVerifiedOrigin(); + advanceTime(3000); + returnToVerifiedOrigin(); + advanceTime(4000); + leaveVerifiedOrigin(); + advanceTime(5000); + + clearInvocations(mUmaRecorder); + returnToVerifiedOrigin(); + verify(mUmaRecorder).recordTimeOutOfVerifiedOrigin(5000); + } + + @Test + public void recordsTimeInVerified_WhenPausedWhileInVerified() { + launchTwa(); + advanceTime(2000); + + mRecorder.onPauseWithNative(); + verify(mUmaRecorder).recordTimeInVerifiedOrigin(2000); + } + + @Test + public void recordsTimeInVerified_AfterResumedInVerified_AndLeftVerified() { + launchTwa(); + advanceTime(2000); + mRecorder.onPauseWithNative(); + advanceTime(3000); + mRecorder.onResumeWithNative(); + advanceTime(4000); + + clearInvocations(mUmaRecorder); + leaveVerifiedOrigin(); + verify(mUmaRecorder).recordTimeInVerifiedOrigin(4000); + } + + @Test + public void recordsTimeOutOfVerified_WhenPausedWhileOutOfVerified() { + launchTwa(); + advanceTime(2000); + leaveVerifiedOrigin(); + advanceTime(3000); + + mRecorder.onPauseWithNative(); + verify(mUmaRecorder).recordTimeOutOfVerifiedOrigin(3000); + } + + @Test + public void doesntRecordAnyTime_WhenVerifiedForFirstTime() { + launchTwa(); + verify(mUmaRecorder, never()).recordTimeInVerifiedOrigin(anyLong()); + verify(mUmaRecorder, never()).recordTimeOutOfVerifiedOrigin(anyLong()); + verify(mUmaRecorder, never()).recordTwaOpenTime(anyLong()); + } + + private void launchTwa() { + advanceTime(1000); + mRecorder.onResumeWithNative(); + setVerificationStatus(VERIFICATION_PENDING); + setVerificationStatus(VERIFICATION_SUCCESS); + } + + private void leaveVerifiedOrigin() { + setVerificationStatus(VERIFICATION_FAILURE); + } + + private void returnToVerifiedOrigin() { + setVerificationStatus(VERIFICATION_SUCCESS); + } + + private void setVerificationStatus(@VerificationStatus int status) { + VerificationState newState = new VerificationState(mock(Origin.class), status); + when(mVerifier.getState()).thenReturn(newState); + for (Runnable observer : mVerificationObserverCaptor.getAllValues()) { + observer.run(); + } + } + + private void advanceTime(long millis) { + Robolectric.getForegroundThreadScheduler().advanceBy(millis, TimeUnit.MILLISECONDS); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/StreamLifecycleManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/StreamLifecycleManagerTest.java index a3bfe742..39becd4ad 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/StreamLifecycleManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/StreamLifecycleManagerTest.java
@@ -6,7 +6,10 @@ import static org.mockito.AdditionalMatchers.or; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -20,6 +23,7 @@ import com.google.android.libraries.feed.api.stream.Stream; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,6 +36,8 @@ import org.chromium.base.ActivityState; import org.chromium.base.ApplicationStatus; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.preferences.Pref; +import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab.TabHidingType; @@ -47,17 +53,30 @@ private Tab mTab; @Mock private Stream mStream; + @Mock + private PrefServiceBridge mPrefServiceBridge; private StreamLifecycleManager mStreamLifecycleManager; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + + // Initialize a test instance for PrefServiceBridge. + when(mPrefServiceBridge.getBoolean(anyInt())).thenReturn(true); + doNothing().when(mPrefServiceBridge).setBoolean(anyInt(), anyBoolean()); + PrefServiceBridge.setInstanceForTesting(mPrefServiceBridge); + ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.CREATED); mStreamLifecycleManager = new StreamLifecycleManager(mStream, mActivity, mTab); verify(mStream, times(1)).onCreate(or(any(String.class), isNull())); } + @After + public void tearDown() { + PrefServiceBridge.setInstanceForTesting(null); + } + @Test @SmallTest public void testShow() { @@ -84,6 +103,33 @@ @Test @SmallTest + public void testShow_ArticlesNotVisible() { + // Verify that onShow is not called when articles are set hidden by the user. + when(mPrefServiceBridge.getBoolean(Pref.NTP_ARTICLES_LIST_VISIBLE)).thenReturn(false); + ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED); + when(mTab.isHidden()).thenReturn(false); + when(mTab.isUserInteractable()).thenReturn(true); + mStreamLifecycleManager.getTabObserverForTesting().onShown(mTab, FROM_NEW); + verify(mStream, times(0)).onShow(); + + // Verify that onShow is called when articles are set shown by the user. + when(mPrefServiceBridge.getBoolean(Pref.NTP_ARTICLES_LIST_VISIBLE)).thenReturn(true); + mStreamLifecycleManager.getTabObserverForTesting().onShown(mTab, FROM_NEW); + verify(mStream, times(1)).onShow(); + + // Verify that onHide is called after tab is hidden. + mStreamLifecycleManager.getTabObserverForTesting().onHidden(mTab, CHANGED_TABS); + verify(mStream, times(1)).onHide(); + + // Verify that onShow is called when articles are set hidden by the user within the same + // session. + when(mPrefServiceBridge.getBoolean(Pref.NTP_ARTICLES_LIST_VISIBLE)).thenReturn(false); + mStreamLifecycleManager.getTabObserverForTesting().onShown(mTab, FROM_NEW); + verify(mStream, times(2)).onShow(); + } + + @Test + @SmallTest public void testActivate() { // Verify that stream is not active before activity resumed. when(mTab.isHidden()).thenReturn(false);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index a96bc15..1ee0b0b6 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -1675,7 +1675,7 @@ </message> <message name="IDS_DOWNLOAD_STATUS_PERCENT_COMPLETE_ACCESSIBLE_ALERT" desc="The title of a download notification: the current download status is in progress and time remaining is known. This message is for screen reader users."> - Downloading, <ph name="PERCENT_REMAINING">$1<ex>33</ex>% remaining</ph> + Downloading, <ph name="PERCENT_REMAINING">$1<ex>33</ex></ph>% remaining </message> <message name="IDS_DOWNLOAD_STATUS_TIME_REMAINING_ACCESSIBLE_ALERT" desc="The title of a download notification: the current download status is in progress and time remaining is known. This message is for screen reader users."> @@ -1687,11 +1687,11 @@ </message> <message name="IDS_DOWNLOAD_CANCELLED_ACCESSIBLE_ALERT" desc="The title of a download notification: the current download status is cancelled. This message is for screen reader users."> - Download cancelled: <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex>.</ph> + Download cancelled: <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex></ph> </message> <message name="IDS_DOWNLOAD_COMPLETE_ACCESSIBLE_ALERT" desc="The title of a download notification: the current download status is finished successufully. This message is for screen reader users."> - Download complete: <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex>. Press Shift+F6 to cycle to the downloads bar area.</ph> + Download complete: <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex>></ph>. Press Shift+F6 to cycle to the downloads bar area. </message> <!-- Download Notification Labels -->
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 5d6823e..5243974 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -102,6 +102,9 @@ void UiControllerAndroid::Start(JNIEnv* env, const JavaParamRef<jobject>& jcaller, const JavaParamRef<jstring>& initialUrlString) { + if (!ui_delegate_) + return; + GURL initialUrl = GURL(base::android::ConvertJavaStringToUTF8(env, initialUrlString)); ui_delegate_->Start(initialUrl); @@ -179,12 +182,18 @@ const base::android::JavaParamRef<jobject>& obj, float distanceX, float distanceY) { + if (!ui_delegate_) + return; + ui_delegate_->ScrollBy(distanceX, distanceY); } void UiControllerAndroid::UpdateTouchableArea( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) { + if (!ui_delegate_) + return; + ui_delegate_->UpdateTouchableArea(); } @@ -192,6 +201,9 @@ JNIEnv* env, const JavaParamRef<jobject>& jcaller, const JavaParamRef<jstring>& jscript_path) { + if (!ui_delegate_) + return; + std::string script_path; base::android::ConvertJavaStringToUTF8(env, jscript_path, &script_path); ui_delegate_->OnScriptSelected(script_path); @@ -447,6 +459,9 @@ } std::string UiControllerAndroid::GetDebugContext() const { + if (!ui_delegate_) + return ""; + return ui_delegate_->GetDebugContext(); }
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index 59b086e7..013303c 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -132,6 +132,8 @@ base::android::ScopedJavaGlobalRef<jobject> java_autofill_assistant_ui_controller_; + // UI delegate. It can be nullptr during initialization and after the delegate + // has been deleted. Always check for nullptr before using it. UiDelegate* ui_delegate_; content::BrowserContext* browser_context_;
diff --git a/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.cc b/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.cc index 054750f..a6356ae 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.cc +++ b/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.cc
@@ -55,7 +55,7 @@ } void ContextualSearchRankerLoggerImpl::SetupRankerPredictor( - const content::WebContents& web_contents) { + content::WebContents& web_contents) { // Create one predictor for the current BrowserContext. if (browser_context_) { DCHECK(browser_context_ == web_contents.GetBrowserContext());
diff --git a/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.h b/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.h index bd952d3..e7b144d 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.h +++ b/chrome/browser/android/contextualsearch/contextual_search_ranker_logger_impl.h
@@ -74,7 +74,7 @@ void LogFeature(const std::string& feature_name, int value); // Sets up the Ranker Predictor for the given |web_contents|. - void SetupRankerPredictor(const content::WebContents& web_contents); + void SetupRankerPredictor(content::WebContents& web_contents); // Logs to UMA when an important feature or outcome is present in the example. void logImportantFeaturePresent(const std::string& feature,
diff --git a/chrome/browser/android/feed/feed_logging_bridge.cc b/chrome/browser/android/feed/feed_logging_bridge.cc index 444d498..c686743 100644 --- a/chrome/browser/android/feed/feed_logging_bridge.cc +++ b/chrome/browser/android/feed/feed_logging_bridge.cc
@@ -65,6 +65,12 @@ j_position, GURL(ConvertJavaStringToUTF8(j_env, j_url))); } +void FeedLoggingBridge::OnContentSwiped( + JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this) { + feed_logging_metrics_->OnSuggestionSwiped(); +} + void FeedLoggingBridge::OnContentClicked( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, @@ -120,6 +126,14 @@ JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this) {} +void FeedLoggingBridge::OnSpinnerShown( + JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const jlong j_shownTimeMs) { + feed_logging_metrics_->OnSpinnerShown( + base::TimeDelta::FromMilliseconds(j_shownTimeMs)); +} + void FeedLoggingBridge::OnContentTargetVisited( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, @@ -135,4 +149,10 @@ } } +void FeedLoggingBridge::ReportScrolledAfterOpen( + JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this) { + feed_logging_metrics_->ReportScrolledAfterOpen(); +} + } // namespace feed
diff --git a/chrome/browser/android/feed/feed_logging_bridge.h b/chrome/browser/android/feed/feed_logging_bridge.h index 6b10402..27795d0 100644 --- a/chrome/browser/android/feed/feed_logging_bridge.h +++ b/chrome/browser/android/feed/feed_logging_bridge.h
@@ -35,6 +35,9 @@ const jint j_position, const base::android::JavaRef<jstring>& j_url); + void OnContentSwiped(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this); + void OnContentClicked(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, const jint j_position, @@ -71,12 +74,19 @@ void OnOpenedWithNoContent(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this); + void OnSpinnerShown(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const jlong j_shownTimeMs); + void OnContentTargetVisited(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, const jlong visit_time_ms, const jboolean is_offline, const jboolean return_to_ntp); + void ReportScrolledAfterOpen(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this); + private: FeedLoggingMetrics* feed_logging_metrics_;
diff --git a/chrome/browser/android/shortcut_helper.cc b/chrome/browser/android/shortcut_helper.cc index f0fd40d..749ea5a 100644 --- a/chrome/browser/android/shortcut_helper.cc +++ b/chrome/browser/android/shortcut_helper.cc
@@ -79,6 +79,7 @@ void AddWebappWithSkBitmap(const ShortcutInfo& info, const std::string& webapp_id, const SkBitmap& icon_bitmap, + bool is_icon_maskable, const base::Closure& splash_image_callback) { // Send the data to the Java side to create the shortcut. JNIEnv* env = base::android::AttachCurrentThread(); @@ -113,8 +114,8 @@ Java_ShortcutHelper_addWebapp( env, java_webapp_id, java_url, java_scope_url, java_user_title, java_name, - java_short_name, java_best_primary_icon_url, java_bitmap, info.display, - info.orientation, info.source, + java_short_name, java_best_primary_icon_url, java_bitmap, + is_icon_maskable, info.display, info.orientation, info.source, OptionalSkColorToJavaColor(info.theme_color), OptionalSkColorToJavaColor(info.background_color), java_splash_screen_url, callback_pointer); @@ -123,7 +124,8 @@ // Adds a shortcut which opens in a browser tab to the launcher. void AddShortcutWithSkBitmap(const ShortcutInfo& info, const std::string& id, - const SkBitmap& icon_bitmap) { + const SkBitmap& icon_bitmap, + bool is_icon_maskable) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jstring> java_id = base::android::ConvertUTF8ToJavaString(env, id); @@ -136,7 +138,7 @@ java_bitmap = gfx::ConvertToJavaBitmap(&icon_bitmap); Java_ShortcutHelper_addShortcut(env, java_id, java_url, java_user_title, - java_bitmap, info.source); + java_bitmap, is_icon_maskable, info.source); } } // anonymous namespace @@ -171,19 +173,20 @@ void ShortcutHelper::AddToLauncherWithSkBitmap( content::WebContents* web_contents, const ShortcutInfo& info, - const SkBitmap& icon_bitmap) { + const SkBitmap& icon_bitmap, + bool is_icon_maskable) { std::string webapp_id = base::GenerateGUID(); if (info.display == blink::kWebDisplayModeStandalone || info.display == blink::kWebDisplayModeFullscreen || info.display == blink::kWebDisplayModeMinimalUi) { AddWebappWithSkBitmap( - info, webapp_id, icon_bitmap, + info, webapp_id, icon_bitmap, is_icon_maskable, base::Bind(&ShortcutHelper::FetchSplashScreenImage, web_contents, info.splash_image_url, info.ideal_splash_image_size_in_px, info.minimum_splash_image_size_in_px, webapp_id)); return; } - AddShortcutWithSkBitmap(info, webapp_id, icon_bitmap); + AddShortcutWithSkBitmap(info, webapp_id, icon_bitmap, is_icon_maskable); } void ShortcutHelper::ShowWebApkInstallInProgressToast() { @@ -255,6 +258,7 @@ // static SkBitmap ShortcutHelper::FinalizeLauncherIconInBackground( const SkBitmap& bitmap, + bool is_icon_maskable, const GURL& url, bool* is_generated) { base::AssertLongCPUWorkAllowed(); @@ -268,8 +272,8 @@ bitmap.height())) { ScopedJavaLocalRef<jobject> java_bitmap = gfx::ConvertToJavaBitmap(&bitmap); - result = - Java_ShortcutHelper_createHomeScreenIconFromWebIcon(env, java_bitmap); + result = Java_ShortcutHelper_createHomeScreenIconFromWebIcon( + env, java_bitmap, is_icon_maskable); } }
diff --git a/chrome/browser/android/shortcut_helper.h b/chrome/browser/android/shortcut_helper.h index 857dca23..cbf6626 100644 --- a/chrome/browser/android/shortcut_helper.h +++ b/chrome/browser/android/shortcut_helper.h
@@ -42,7 +42,8 @@ // added depends on the properties in |info|. static void AddToLauncherWithSkBitmap(content::WebContents* web_contents, const ShortcutInfo& info, - const SkBitmap& icon_bitmap); + const SkBitmap& icon_bitmap, + bool is_icon_maskable); // Shows toast notifying user that a WebAPK install is already in progress // when user tries to queue a new install for the same WebAPK. @@ -85,6 +86,7 @@ // |is_generated| will be set to |true|. // Must be called on a background worker thread. static SkBitmap FinalizeLauncherIconInBackground(const SkBitmap& icon, + bool is_icon_maskable, const GURL& url, bool* is_generated);
diff --git a/chrome/browser/android/webapk/webapk_install_service.cc b/chrome/browser/android/webapk/webapk_install_service.cc index ad45aaa..dff0770 100644 --- a/chrome/browser/android/webapk/webapk_install_service.cc +++ b/chrome/browser/android/webapk/webapk_install_service.cc
@@ -95,8 +95,10 @@ if (!web_contents) return; + // TODO(https://crbug.com/861643): Support maskable icons here. ShortcutHelper::AddToLauncherWithSkBitmap(web_contents, shortcut_info, - primary_icon); + primary_icon, + /*is_icon_maskable=*/false); } }
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc index f1d6bdf..7b76ee68 100644 --- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc +++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
@@ -40,16 +40,14 @@ // Looks up the original, online, visible URL of |web_contents|. The current // visible URL may be a distilled article which is not appropriate for a home // screen shortcut. -GURL GetShortcutUrl(const content::WebContents* web_contents) { +GURL GetShortcutUrl(content::WebContents* web_contents) { return dom_distiller::url_utils::GetOriginalUrlFromDistillerUrl( web_contents->GetVisibleURL()); } bool DoesAndroidSupportMaskableIcons() { - // TODO(peconn): Enable once Chrome on Android correctly handles maskable - // icons (https://crbug.com/904354). return base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_OREO && false; + base::android::SDK_VERSION_OREO; } InstallableParams ParamsToPerformManifestAndIconFetch() { @@ -77,10 +75,11 @@ // - the generated icon // - whether |icon| was used in generating the launcher icon std::pair<SkBitmap, bool> CreateLauncherIconInBackground(const GURL& start_url, - const SkBitmap& icon) { + const SkBitmap& icon, + bool maskable) { bool is_generated = false; SkBitmap primary_icon = ShortcutHelper::FinalizeLauncherIconInBackground( - icon, start_url, &is_generated); + icon, maskable, start_url, &is_generated); return std::make_pair(primary_icon, is_generated); } @@ -99,7 +98,8 @@ gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), bitmap_result.bitmap_data->size(), &decoded); } - return CreateLauncherIconInBackground(start_url, decoded); + return CreateLauncherIconInBackground(start_url, decoded, + /* maskable */ false); } void RecordAddToHomescreenDialogDuration(base::TimeDelta duration) { @@ -238,6 +238,7 @@ } raw_primary_icon_ = *data.primary_icon; + has_maskable_primary_icon_ = data.has_maskable_primary_icon; shortcut_info_.best_primary_icon_url = data.primary_icon_url; // Save the splash screen URL for the later download. @@ -346,7 +347,8 @@ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::BindOnce(&CreateLauncherIconInBackground, shortcut_info_.url, icon), + base::BindOnce(&CreateLauncherIconInBackground, shortcut_info_.url, icon, + has_maskable_primary_icon_), base::BindOnce(&AddToHomescreenDataFetcher::NotifyObserver, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h index 1de8039..396e7b0 100644 --- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h +++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
@@ -66,6 +66,7 @@ const SkBitmap& badge_icon() const { return badge_icon_; } const SkBitmap& primary_icon() const { return primary_icon_; } ShortcutInfo& shortcut_info() { return shortcut_info_; } + bool has_maskable_primary_icon() const { return has_maskable_primary_icon_; } private: // Called to stop the timeout timer. @@ -99,6 +100,7 @@ SkBitmap badge_icon_; SkBitmap primary_icon_; ShortcutInfo shortcut_info_; + bool has_maskable_primary_icon_; base::CancelableTaskTracker favicon_task_tracker_; base::OneShotTimer data_timeout_timer_;
diff --git a/chrome/browser/android/webapps/add_to_homescreen_manager.cc b/chrome/browser/android/webapps/add_to_homescreen_manager.cc index 9dd1d86..615a5c6 100644 --- a/chrome/browser/android/webapps/add_to_homescreen_manager.cc +++ b/chrome/browser/android/webapps/add_to_homescreen_manager.cc
@@ -77,9 +77,10 @@ base::string16 user_title = base::android::ConvertJavaStringToUTF16(env, j_user_title); data_fetcher_->shortcut_info().user_title = user_title; - ShortcutHelper::AddToLauncherWithSkBitmap(web_contents, - data_fetcher_->shortcut_info(), - data_fetcher_->primary_icon()); + ShortcutHelper::AddToLauncherWithSkBitmap( + web_contents, data_fetcher_->shortcut_info(), + data_fetcher_->primary_icon(), + data_fetcher_->has_maskable_primary_icon()); } // Fire the appinstalled event and do install time logging. @@ -143,5 +144,6 @@ java_bitmap = gfx::ConvertToJavaBitmap(&primary_icon); JNIEnv* env = base::android::AttachCurrentThread(); - Java_AddToHomescreenManager_onIconAvailable(env, java_ref_, java_bitmap); + Java_AddToHomescreenManager_onIconAvailable( + env, java_ref_, java_bitmap, data_fetcher_->has_maskable_primary_icon()); }
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h index 69f0577..35984ff 100644 --- a/chrome/browser/app_controller_mac.h +++ b/chrome/browser/app_controller_mac.h
@@ -123,6 +123,10 @@ // window closure from causing the application to quit. - (void)stopTryingToTerminateApplication:(NSApplication*)app; +// Run the quit confirmation panel and return whether or not to continue +// quitting. +- (BOOL)runConfirmQuitPanel; + // Indicate that the system is powering off or logging out. - (void)willPowerOff:(NSNotification*)inNotification;
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 5648f890..79a30d3 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -463,12 +463,6 @@ // them in, but I'm not sure about UX; we'd also want to disable other things // though.) http://crbug.com/40861 - // Check if the user really wants to quit by employing the confirm-to-quit - // mechanism. - if (!browser_shutdown::IsTryingToQuit() && - [self applicationShouldTerminate:app] != NSTerminateNow) - return NO; - // Check for active apps. If quitting is prevented, only close browsers and // sessions. if (!browser_shutdown::IsTryingToQuit() && !isPoweringOff && @@ -519,30 +513,26 @@ } } -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)app { +- (BOOL)runConfirmQuitPanel { // If there are no windows, quit immediately. if (BrowserList::GetInstance()->empty() && !AppWindowRegistryUtil::IsAppWindowVisibleInAnyProfile(0)) { - return NSTerminateNow; + return YES; } // Check if the preference is turned on. const PrefService* prefs = g_browser_process->local_state(); if (!prefs->GetBoolean(prefs::kConfirmToQuitEnabled)) { confirm_quit::RecordHistogram(confirm_quit::kNoConfirm); - return NSTerminateNow; + return YES; } - // If the application is going to terminate as the result of a Cmd+Q - // invocation, use the special sauce to prevent accidental quitting. - // http://dev.chromium.org/developers/design-documents/confirm-to-quit-experiment - - // This logic is only for keyboard-initiated quits. - if ([[app currentEvent] type] != NSKeyDown) + // Run only for keyboard-initiated quits. + if ([[NSApp currentEvent] type] != NSKeyDown) return NSTerminateNow; return [[ConfirmQuitPanelController sharedController] - runModalLoopForApplication:app]; + runModalLoopForApplication:NSApp]; } // Called when the app is shutting down. Clean-up as appropriate.
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc index a44b862a..39b0f1f8 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -262,7 +262,7 @@ if (!active_browser) return base::Time(); - const content::WebContents* active_tab = + content::WebContents* active_tab = active_browser->tab_strip_model()->GetActiveWebContents(); if (!active_tab) return base::Time();
diff --git a/chrome/browser/banners/app_banner_ui_delegate_android.cc b/chrome/browser/banners/app_banner_ui_delegate_android.cc index 9819c4c..9682c8d 100644 --- a/chrome/browser/banners/app_banner_ui_delegate_android.cc +++ b/chrome/browser/banners/app_banner_ui_delegate_android.cc
@@ -318,8 +318,10 @@ AppBannerSettingsHelper::RecordBannerInstallEvent( web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB); + // TODO(https://crbug.com/861643): Support maskable icons here. ShortcutHelper::AddToLauncherWithSkBitmap(web_contents, *shortcut_info_, - primary_icon_); + primary_icon_, + /*is_icon_maskable=*/false); } void AppBannerUiDelegateAndroid::SendBannerAccepted() {
diff --git a/chrome/browser/browser_process_platform_part_android.cc b/chrome/browser/browser_process_platform_part_android.cc index b83e7aa0..3680a08 100644 --- a/chrome/browser/browser_process_platform_part_android.cc +++ b/chrome/browser/browser_process_platform_part_android.cc
@@ -15,7 +15,7 @@ BrowserProcessPlatformPart::~BrowserProcessPlatformPart() { } -void BrowserProcessPlatformPart::AttemptExit() { +void BrowserProcessPlatformPart::AttemptExit(bool try_to_quit_application) { // Tell the Java code to finish() the Activity. chrome::TerminateAndroid(); }
diff --git a/chrome/browser/browser_process_platform_part_android.h b/chrome/browser/browser_process_platform_part_android.h index 0c2343c..5008e95e 100644 --- a/chrome/browser/browser_process_platform_part_android.h +++ b/chrome/browser/browser_process_platform_part_android.h
@@ -15,7 +15,7 @@ ~BrowserProcessPlatformPart() override; // Overridden from BrowserProcessPlatformPartBase: - void AttemptExit() override; + void AttemptExit(bool try_to_quit_application) override; private: DISALLOW_COPY_AND_ASSIGN(BrowserProcessPlatformPart);
diff --git a/chrome/browser/browser_process_platform_part_base.cc b/chrome/browser/browser_process_platform_part_base.cc index d4a391b..a75a728 100644 --- a/chrome/browser/browser_process_platform_part_base.cc +++ b/chrome/browser/browser_process_platform_part_base.cc
@@ -23,7 +23,7 @@ void BrowserProcessPlatformPartBase::StartTearDown() { } -void BrowserProcessPlatformPartBase::AttemptExit() { +void BrowserProcessPlatformPartBase::AttemptExit(bool try_to_quit_application) { // chrome::CloseAllBrowsers() doesn't link on OS_ANDROID, but it overrides this // method already. #if defined(OS_ANDROID)
diff --git a/chrome/browser/browser_process_platform_part_base.h b/chrome/browser/browser_process_platform_part_base.h index 552de4c..9204bb5 100644 --- a/chrome/browser/browser_process_platform_part_base.h +++ b/chrome/browser/browser_process_platform_part_base.h
@@ -34,7 +34,7 @@ virtual void StartTearDown(); // Called from AttemptExitInternal(). - virtual void AttemptExit(); + virtual void AttemptExit(bool try_to_quit_application); // Called at the end of BrowserProcessImpl::PreMainMessageLoopRun(). virtual void PreMainMessageLoopRun();
diff --git a/chrome/browser/browser_process_platform_part_mac.h b/chrome/browser/browser_process_platform_part_mac.h index a273a0f..6d326407 100644 --- a/chrome/browser/browser_process_platform_part_mac.h +++ b/chrome/browser/browser_process_platform_part_mac.h
@@ -19,7 +19,7 @@ // Overridden from BrowserProcessPlatformPartBase: void StartTearDown() override; - void AttemptExit() override; + void AttemptExit(bool try_to_quit_application) override; void PreMainMessageLoopRun() override; AppShimHostManager* app_shim_host_manager();
diff --git a/chrome/browser/browser_process_platform_part_mac.mm b/chrome/browser/browser_process_platform_part_mac.mm index 7c40a0a..48f09af9 100644 --- a/chrome/browser/browser_process_platform_part_mac.mm +++ b/chrome/browser/browser_process_platform_part_mac.mm
@@ -4,6 +4,8 @@ #include "chrome/browser/browser_process_platform_part_mac.h" +#include "base/mac/foundation_util.h" +#import "chrome/browser/app_controller_mac.h" #include "chrome/browser/chrome_browser_application_mac.h" BrowserProcessPlatformPart::BrowserProcessPlatformPart() { @@ -16,10 +18,26 @@ app_shim_host_manager_ = NULL; } -void BrowserProcessPlatformPart::AttemptExit() { +void BrowserProcessPlatformPart::AttemptExit(bool try_to_quit_application) { // On the Mac, the application continues to run once all windows are closed. // Terminate will result in a CloseAllBrowsers() call, and once (and if) // that is done, will cause the application to exit cleanly. + // + // This function is called for two types of attempted exits: URL requests + // (chrome://quit or chrome://restart), and a keyboard menu invocations of + // command-Q. (Interestingly, selecting the Quit command with the mouse don't + // come down this code path at all.) URL requests to exit have + // |try_to_quit_application| set to true; keyboard menu invocations have it + // set to false. + + if (!try_to_quit_application) { + // A keyboard menu invocation. + AppController* app_controller = + base::mac::ObjCCastStrict<AppController>([NSApp delegate]); + if (![app_controller runConfirmQuitPanel]) + return; + } + chrome_browser_application_mac::Terminate(); }
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc index c68bed7..31dcf1c6 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -63,6 +63,7 @@ #include "content/public/test/simple_url_loader_test_helper.h" #include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/google_service_auth_error.h" +#include "media/base/media_switches.h" #include "media/mojo/services/video_decode_perf_history.h" #include "net/cookies/canonical_cookie.h" #include "net/dns/mock_host_resolver.h" @@ -79,6 +80,15 @@ #include "third_party/re2/src/re2/re2.h" #include "url/gurl.h" +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) +#if defined(OS_MACOSX) +#include "base/threading/platform_thread.h" +#endif +#include "base/memory/scoped_refptr.h" +#include "chrome/browser/browsing_data/browsing_data_media_license_helper.h" +#include "chrome/browser/media/library_cdm_test_helper.h" +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + using content::BrowserThread; using content::BrowsingDataFilterBuilder; @@ -280,14 +290,7 @@ class BrowsingDataRemoverBrowserTest : public InProcessBrowserTest { public: - BrowsingDataRemoverBrowserTest() { - feature_list_.InitWithFeatures( - {leveldb::kLevelDBRewriteFeature, - // Ensure that kOnionSoupDOMStorage is enabled because the old - // SessionStorage implementation causes flaky tests. - blink::features::kOnionSoupDOMStorage}, - {}); - } + BrowsingDataRemoverBrowserTest() {} // Call to use an Incognito browser rather than the default. void UseIncognitoBrowser() { @@ -351,16 +354,22 @@ } void RemoveAndWait(int remove_mask) { - RemoveAndWait(remove_mask, base::Time()); + RemoveAndWait(remove_mask, base::Time(), base::Time::Max()); } void RemoveAndWait(int remove_mask, base::Time delete_begin) { + RemoveAndWait(remove_mask, delete_begin, base::Time::Max()); + } + + void RemoveAndWait(int remove_mask, + base::Time delete_begin, + base::Time delete_end) { content::BrowsingDataRemover* remover = content::BrowserContext::GetBrowsingDataRemover( GetBrowser()->profile()); content::BrowsingDataRemoverCompletionObserver completion_observer(remover); remover->RemoveAndReply( - delete_begin, base::Time::Max(), remove_mask, + delete_begin, delete_end, remove_mask, content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, &completion_observer); completion_observer.BlockUntilCompletion(); @@ -446,6 +455,30 @@ return count; } +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) + int GetMediaLicenseCount() { + base::RunLoop run_loop; + int count = -1; + content::StoragePartition* partition = + content::BrowserContext::GetDefaultStoragePartition( + browser()->profile()); + scoped_refptr<BrowsingDataMediaLicenseHelper> media_license_helper = + BrowsingDataMediaLicenseHelper::Create( + partition->GetFileSystemContext()); + media_license_helper->StartFetching(base::BindLambdaForTesting( + [&](const std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>& + licenses) { + count = licenses.size(); + LOG(INFO) << "Found " << count << " licenses."; + for (const auto& license : licenses) + LOG(INFO) << license.last_modified_time; + run_loop.Quit(); + })); + run_loop.Run(); + return count; + } +#endif + inline void ExpectCookieTreeModelCount(int expected) { std::unique_ptr<CookiesTreeModel> model = GetCookiesTreeModel(); EXPECT_EQ(expected, GetCookiesTreeModelCount(model->GetRoot())) @@ -520,6 +553,25 @@ return model; } + void SetUpCommandLine(base::CommandLine* command_line) override { + InProcessBrowserTest::SetUpCommandLine(command_line); + + std::vector<base::Feature> enabled_features = { + leveldb::kLevelDBRewriteFeature, + // Ensure that kOnionSoupDOMStorage is enabled because the old + // SessionStorage implementation causes flaky tests. + blink::features::kOnionSoupDOMStorage}; + +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) + // Testing MediaLicenses requires additional command line parameters as + // it uses the External Clear Key CDM. + RegisterClearKeyCdm(command_line); + enabled_features.push_back(media::kExternalClearKeyForTesting); +#endif + + feature_list_.InitWithFeatures(enabled_features, {}); + } + base::test::ScopedFeatureList feature_list_; Browser* incognito_browser_ = nullptr; }; @@ -1059,6 +1111,130 @@ TestEmptySiteData("IndexedDb", GetParam()); } +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) +// Test Media Licenses by creating one and checking it is counted by the +// cookie counter. Then delete it and check that the cookie counter is back +// to zero. +IN_PROC_BROWSER_TEST_P(BrowsingDataRemoverBrowserTestP, MediaLicenseDeletion) { + const std::string kMediaLicenseType = "MediaLicense"; + const base::Time delete_begin = GetParam(); + + EXPECT_EQ(0, GetSiteDataCount()); + EXPECT_EQ(0, GetMediaLicenseCount()); + GURL url = + embedded_test_server()->GetURL("/browsing_data/media_license.html"); + ui_test_utils::NavigateToURL(browser(), url); + + EXPECT_EQ(0, GetSiteDataCount()); + EXPECT_EQ(0, GetMediaLicenseCount()); + ExpectCookieTreeModelCount(0); + EXPECT_FALSE(HasDataForType(kMediaLicenseType)); + + SetDataForType(kMediaLicenseType); + EXPECT_EQ(0, GetSiteDataCount()); + EXPECT_EQ(1, GetMediaLicenseCount()); + ExpectCookieTreeModelCount(1); + EXPECT_TRUE(HasDataForType(kMediaLicenseType)); + + // Try to remove the Media Licenses using a time frame up until an hour ago, + // which should not remove the recently created Media License. + RemoveAndWait(content::BrowsingDataRemover::DATA_TYPE_MEDIA_LICENSES, + delete_begin, kLastHour); + EXPECT_EQ(0, GetSiteDataCount()); + EXPECT_EQ(1, GetMediaLicenseCount()); + ExpectCookieTreeModelCount(1); + EXPECT_TRUE(HasDataForType(kMediaLicenseType)); + + // Now try with a time range that includes the current time, which should + // clear the Media License created for this test. + RemoveAndWait(content::BrowsingDataRemover::DATA_TYPE_MEDIA_LICENSES, + delete_begin, base::Time::Max()); + EXPECT_EQ(0, GetSiteDataCount()); + EXPECT_EQ(0, GetMediaLicenseCount()); + ExpectCookieTreeModelCount(0); + EXPECT_FALSE(HasDataForType(kMediaLicenseType)); +} + +// Create and save a media license (which will be deleted in the following +// test). +IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, + PRE_MediaLicenseTimedDeletion) { + const std::string kMediaLicenseType = "MediaLicense"; + + EXPECT_EQ(0, GetSiteDataCount()); + EXPECT_EQ(0, GetMediaLicenseCount()); + + GURL url = + embedded_test_server()->GetURL("/browsing_data/media_license.html"); + ui_test_utils::NavigateToURL(browser(), url); + + EXPECT_EQ(0, GetSiteDataCount()); + EXPECT_EQ(0, GetMediaLicenseCount()); + ExpectCookieTreeModelCount(0); + EXPECT_FALSE(HasDataForType(kMediaLicenseType)); + + SetDataForType(kMediaLicenseType); + EXPECT_EQ(0, GetSiteDataCount()); + EXPECT_EQ(1, GetMediaLicenseCount()); + ExpectCookieTreeModelCount(1); + EXPECT_TRUE(HasDataForType(kMediaLicenseType)); +} + +// Create and save a second media license, and then verify that timed deletion +// selects the correct license to delete. +IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, + MediaLicenseTimedDeletion) { + const std::string kMediaLicenseType = "MediaLicense"; + + // As the PRE_ test should run first, there should be one media license + // still stored. The time of it's creation should be sometime before + // this test starts. We can't see the license, since it's stored for a + // different origin (but we can delete it). + const base::Time start = base::Time::Now(); + LOG(INFO) << "MediaLicenseTimedDeletion starting @ " << start; + EXPECT_EQ(1, GetMediaLicenseCount()); + + GURL url = + embedded_test_server()->GetURL("/browsing_data/media_license.html"); + ui_test_utils::NavigateToURL(browser(), url); + +#if defined(OS_MACOSX) + // On some Macs the file system uses second granularity. So before + // creating the second license, delay for 1 second so that the new + // license's time is not the same second as |start|. + base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); +#endif + + // This test should use a different domain than the PRE_ test, so there + // should be no existing media license for it. + // Note that checking HasDataForType() may result in an empty file being + // created. Deleting licenses checks for any file within the time range + // specified in order to delete all the files for the domain, so this may + // cause problems (especially with Macs that use second granularity). + // http://crbug.com/909829. + EXPECT_FALSE(HasDataForType(kMediaLicenseType)); + + // Create a media license for this domain. + SetDataForType(kMediaLicenseType); + EXPECT_EQ(2, GetMediaLicenseCount()); + EXPECT_TRUE(HasDataForType(kMediaLicenseType)); + + // As Clear Browsing Data typically deletes recent data (e.g. last hour, + // last day, etc.), try to remove the Media Licenses created since the + // the start of this test, which should only delete the just created + // media license, and leave the one created by the PRE_ test. + RemoveAndWait(content::BrowsingDataRemover::DATA_TYPE_MEDIA_LICENSES, start); + EXPECT_EQ(1, GetMediaLicenseCount()); + EXPECT_FALSE(HasDataForType(kMediaLicenseType)); + + // Now try with a time range that includes all time, which should + // clear the media license created by the PRE_ test. + RemoveAndWait(content::BrowsingDataRemover::DATA_TYPE_MEDIA_LICENSES); + EXPECT_EQ(0, GetMediaLicenseCount()); + ExpectCookieTreeModelCount(0); +} +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + const std::vector<std::string> kStorageTypes{ "Cookie", "LocalStorage", "FileSystem", "SessionStorage", "IndexedDb", "WebSql", "ServiceWorker", "CacheStorage",
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 3d71dee..b8e666b7 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -1876,7 +1876,7 @@ // across versions. RecordBrowserStartupTime(); - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); performance_monitor::PerformanceMonitor::GetInstance()->StartGatherCycle();
diff --git a/chrome/browser/chromeos/file_system_provider/request_manager.cc b/chrome/browser/chromeos/file_system_provider/request_manager.cc index fec162f..7a71413 100644 --- a/chrome/browser/chromeos/file_system_provider/request_manager.cc +++ b/chrome/browser/chromeos/file_system_provider/request_manager.cc
@@ -230,8 +230,7 @@ const TabStripModel* const tabs = browser->tab_strip_model(); DCHECK(tabs); for (int i = 0; i < tabs->count(); ++i) { - const content::WebContents* const web_contents = - tabs->GetWebContentsAt(i); + content::WebContents* const web_contents = tabs->GetWebContentsAt(i); const GURL& url = web_contents->GetURL(); if (url.SchemeIs(extensions::kExtensionScheme) && url.host_piece() == provider_id_) {
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc index adf25df..3277838 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -514,7 +514,7 @@ // static void ScreenLocker::Show() { base::RecordAction(UserMetricsAction("ScreenLocker_Show")); - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); // Check whether the currently logged in user is a guest account and if so, // refuse to lock the screen (crosbug.com/23764). @@ -541,7 +541,7 @@ // static void ScreenLocker::Hide() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); // For a guest user, screen_locker_ would have never been initialized. if (user_manager::UserManager::Get()->IsLoggedInAsGuest()) { VLOG(1) << "Refusing to hide lock screen for guest account"; @@ -595,7 +595,7 @@ ScreenLocker::~ScreenLocker() { VLOG(1) << "Destroying ScreenLocker " << this; - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); if (authenticator_) authenticator_->SetConsumer(nullptr);
diff --git a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc index e06877a0..0587585 100644 --- a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc +++ b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
@@ -56,7 +56,7 @@ } void OnFocusPOD() { - ASSERT_TRUE(base::MessageLoopForUI::IsCurrent()); + ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet()); focused_ = true; if (runner_.get()) { base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc index 47fb7e4..6fa3043 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
@@ -230,7 +230,7 @@ void SetUpCommandLine(base::CommandLine* command_line) override { OobeBaseTest::SetUpCommandLine(command_line); - // Disable sync sinc we don't really need this for these tests and it also + // Disable sync since we don't really need this for these tests and it also // makes OAuth2Test.MergeSession test flaky http://crbug.com/408867. command_line->AppendSwitch(switches::kDisableSync); } @@ -494,7 +494,7 @@ // PRE_MergeSession is testing merge session for a new profile. IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_PRE_PRE_MergeSession) { StartNewUserSession(/*wait_for_merge=*/true, - /*is_under_advanced_protectionis_true=*/false); + /*is_under_advanced_protection=*/false); // Check for existence of refresh token. std::string account_id = PickAccountId(profile(), kTestGaiaId, kTestEmail); identity::IdentityManager* identity_manager = @@ -519,7 +519,7 @@ LoginAsExistingUser(); scoped_refptr<CookieReader> cookie_reader(new CookieReader()); cookie_reader->ReadCookies(profile()); - // These are still cookie values form the initial session since + // These are still cookie values from the initial session since // /ListAccounts EXPECT_EQ(cookie_reader->GetCookieValue("SID"), kTestSessionSIDCookie); EXPECT_EQ(cookie_reader->GetCookieValue("LSID"), kTestSessionLSIDCookie); @@ -574,7 +574,7 @@ // Sets up a new user with stored refresh token. IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_OverlappingContinueSessionRestore) { StartNewUserSession(/*wait_for_merge=*/true, - /*is_under_advanced_protectionis_true=*/false); + /*is_under_advanced_protection=*/false); } // Tests that ContinueSessionRestore could be called multiple times. @@ -660,7 +660,7 @@ IN_PROC_BROWSER_TEST_F(OAuth2Test, VerifyInAdvancedProtectionAfterOnlineAuth) { StartNewUserSession(/*wait_for_merge=*/true, - /*is_under_advanced_protectionis_true=*/true); + /*is_under_advanced_protection=*/true); // Verify that AccountInfo is properly updated. AccountTrackerService* account_tracker = @@ -672,7 +672,7 @@ IN_PROC_BROWSER_TEST_F(OAuth2Test, VerifyNotInAdvancedProtectionAfterOnlineAuth) { StartNewUserSession(/*wait_for_merge=*/true, - /*is_under_advanced_protectionis_true=*/false); + /*is_under_advanced_protection=*/false); // Verify that AccountInfo is properly updated. AccountTrackerService* account_tracker = @@ -684,7 +684,7 @@ // Sets up a new user with stored refresh token. IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_SetInvalidTokenStatus) { StartNewUserSession(/*wait_for_merge=*/true, - /*is_under_advanced_protectionis_true=*/false); + /*is_under_advanced_protection=*/false); } // Tests that an auth error marks invalid auth token status despite @@ -896,7 +896,7 @@ IN_PROC_BROWSER_TEST_F(MergeSessionTest, PageThrottle) { StartNewUserSession(/*wait_for_merge=*/false, - /*is_under_advanced_protectionis_true=*/false); + /*is_under_advanced_protection=*/false); // Try to open a page from google.com. Browser* browser = FindOrCreateVisibleBrowser(profile()); @@ -943,7 +943,7 @@ IN_PROC_BROWSER_TEST_F(MergeSessionTest, XHRThrottle) { StartNewUserSession(/*wait_for_merge=*/false, - /*is_under_advanced_protectionis_true=*/false); + /*is_under_advanced_protection=*/false); // Wait until we get send merge session request. WaitForMergeSessionToStart(); @@ -972,7 +972,7 @@ fake_google_page_url_.spec().c_str(), non_google_page_url_.spec().c_str())); - // Verify that we've sent XHR request form the extension side... + // Verify that we've sent XHR request from the extension side... JsExpectOnBackgroundPage(ext->id(), "googleRequestSent && !googleResponseReceived");
diff --git a/chrome/browser/chromeos/login/signin_partition_manager.cc b/chrome/browser/chromeos/login/signin_partition_manager.cc index 5eeabba..83662764 100644 --- a/chrome/browser/chromeos/login/signin_partition_manager.cc +++ b/chrome/browser/chromeos/login/signin_partition_manager.cc
@@ -98,7 +98,7 @@ SigninPartitionManager::~SigninPartitionManager() {} void SigninPartitionManager::StartSigninSession( - const content::WebContents* embedder_web_contents, + content::WebContents* embedder_web_contents, StartSigninSessionDoneCallback signin_session_started) { // If we already were in a sign-in session, close it first. // This clears stale data from the last-used StorageParittion.
diff --git a/chrome/browser/chromeos/login/signin_partition_manager.h b/chrome/browser/chromeos/login/signin_partition_manager.h index 1a5478e..6bfaa1f 100644 --- a/chrome/browser/chromeos/login/signin_partition_manager.h +++ b/chrome/browser/chromeos/login/signin_partition_manager.h
@@ -52,7 +52,7 @@ // |signin_session_started| will be invoked with the partition name of the // started signin session on completition. void StartSigninSession( - const content::WebContents* embedder_web_contents, + content::WebContents* embedder_web_contents, StartSigninSessionDoneCallback signin_session_started); // Closes the current StoragePartition. All cached data in the
diff --git a/chrome/browser/chromeos/login/test/wizard_in_process_browser_test.cc b/chrome/browser/chromeos/login/test/wizard_in_process_browser_test.cc index b5b7daa9..83d58dd 100644 --- a/chrome/browser/chromeos/login/test/wizard_in_process_browser_test.cc +++ b/chrome/browser/chromeos/login/test/wizard_in_process_browser_test.cc
@@ -44,7 +44,7 @@ } void WizardInProcessBrowserTest::TearDownOnMainThread() { - ASSERT_TRUE(base::MessageLoopForUI::IsCurrent()); + ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet()); if (!host_) return;
diff --git a/chrome/browser/download/download_permission_request.cc b/chrome/browser/download/download_permission_request.cc index f4ebc6de..dda8f22 100644 --- a/chrome/browser/download/download_permission_request.cc +++ b/chrome/browser/download/download_permission_request.cc
@@ -19,7 +19,7 @@ DownloadPermissionRequest::DownloadPermissionRequest( base::WeakPtr<DownloadRequestLimiter::TabDownloadState> host) : host_(host) { - const content::WebContents* web_contents = host_->web_contents(); + content::WebContents* web_contents = host_->web_contents(); DCHECK(web_contents); request_origin_ = web_contents->GetURL().GetOrigin(); }
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc index 6f9993b0..1b545c0 100644 --- a/chrome/browser/extensions/activity_log/activity_log.cc +++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -743,10 +743,9 @@ return is_active_ && !ActivityLogAPI::IsExtensionWhitelisted(extension_id); } -void ActivityLog::OnScriptsExecuted( - const content::WebContents* web_contents, - const ExecutingScriptsMap& extension_ids, - const GURL& on_url) { +void ActivityLog::OnScriptsExecuted(content::WebContents* web_contents, + const ExecutingScriptsMap& extension_ids, + const GURL& on_url) { if (!is_active_) return; ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
diff --git a/chrome/browser/extensions/activity_log/activity_log.h b/chrome/browser/extensions/activity_log/activity_log.h index b9b05ced..1012ed7 100644 --- a/chrome/browser/extensions/activity_log/activity_log.h +++ b/chrome/browser/extensions/activity_log/activity_log.h
@@ -64,7 +64,7 @@ static ActivityLog* GetInstance(content::BrowserContext* context); // Invoked when a ContentScript is executed. - void OnScriptsExecuted(const content::WebContents* web_contents, + void OnScriptsExecuted(content::WebContents* web_contents, const ExecutingScriptsMap& extension_ids, const GURL& on_url);
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc index 656deed4..911813d 100644 --- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc +++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -137,7 +137,7 @@ bool CanRequestAutomation(const Extension* extension, const AutomationInfo* automation_info, - const content::WebContents* contents) { + content::WebContents* contents) { if (automation_info->desktop) return true;
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc index 1bba7b5e..9bdef0a5 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -1351,8 +1351,9 @@ ->FlushProxyConfigMonitorForTesting(); // Verify that the extension can't intercept the network request. - ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL( - "/pages_with_script/page.html")); + ui_test_utils::NavigateToURL( + browser(), + GURL("http://does.not.resolve.test/pages_with_script/page.html")); EXPECT_TRUE(WasFrameWithScriptLoaded(GetMainFrame())); EXPECT_EQ(content::PAGE_TYPE_NORMAL, GetPageType()); }
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 6e956fb..9c38e42 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -1256,8 +1256,8 @@ ->FlushProxyConfigMonitorForTesting(); // Navigate to a page. The URL doesn't matter. - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title2.html")); + ui_test_utils::NavigateToURL( + browser(), GURL("http://does.not.resolve.test/title2.html")); // The extension should not have seen the PAC request. EXPECT_EQ(0, GetCountFromBackgroundPage(extension, profile(),
diff --git a/chrome/browser/extensions/user_script_listener_browsertest.cc b/chrome/browser/extensions/user_script_listener_browsertest.cc index 2d1df834..7fb616c 100644 --- a/chrome/browser/extensions/user_script_listener_browsertest.cc +++ b/chrome/browser/extensions/user_script_listener_browsertest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/user_script_listener.h" #include "chrome/test/base/testing_profile.h" @@ -42,17 +41,9 @@ using UserScriptListenerTest = ExtensionBrowserTest; -#if defined(OS_WIN) -#define MAYBE_NavigationWaitsForContentScriptsToLoad \ - DISABLED_NavigationWaitsForContentScriptsToLoad -#else -#define MAYBE_NavigationWaitsForContentScriptsToLoad \ - NavigationWaitsForContentScriptsToLoad -#endif - // Test that navigations block while waiting for content scripts to load. IN_PROC_BROWSER_TEST_F(UserScriptListenerTest, - MAYBE_NavigationWaitsForContentScriptsToLoad) { + NavigationWaitsForContentScriptsToLoad) { ASSERT_TRUE(embedded_test_server()->Start()); TestingProfile profile;
diff --git a/chrome/browser/interstitials/enterprise_util.cc b/chrome/browser/interstitials/enterprise_util.cc index 0163485f..6597a0a5 100644 --- a/chrome/browser/interstitials/enterprise_util.cc +++ b/chrome/browser/interstitials/enterprise_util.cc
@@ -29,7 +29,7 @@ browser_context); } -std::string GetUserName(const content::WebContents* web_contents) { +std::string GetUserName(content::WebContents* web_contents) { Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); auto* identity_manager =
diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime.cc index d0accd53..cbf53fb 100644 --- a/chrome/browser/lifetime/application_lifetime.cc +++ b/chrome/browser/lifetime/application_lifetime.cc
@@ -149,7 +149,7 @@ content::NotificationService::AllSources(), content::NotificationService::NoDetails()); - g_browser_process->platform_part()->AttemptExit(); + g_browser_process->platform_part()->AttemptExit(try_to_quit_application); } #if !defined(OS_ANDROID)
diff --git a/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc b/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc index c380d88..3d8d11c 100644 --- a/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc +++ b/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc
@@ -49,6 +49,12 @@ }; // Makes a call and checks that there's encryption or not in the SDP offer. +// TODO(crbub.com/910216): De-flake this for ChromeOs. +#if defined(OS_CHROMEOS) +#define MAYBE_TestInMenuDrag DISABLED_VerifyEncryption +#else +#define MAYBE_TestInMenuDrag VerifyEncryption +#endif IN_PROC_BROWSER_TEST_F(WebRtcDisableEncryptionFlagBrowserTest, VerifyEncryption) { ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc index d6463f4..9b1a8a5 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc
@@ -22,6 +22,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" +#include "components/data_reduction_proxy/core/common/uma_util.h" #include "components/data_reduction_proxy/proto/client_config.pb.h" #include "components/prefs/pref_service.h" #include "content/public/browser/network_service_instance.h"
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index e627337..9411427 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -74,7 +74,7 @@ if (browser->profile() != profile) continue; - const content::WebContents* active_contents = + content::WebContents* active_contents = browser->tab_strip_model()->GetActiveWebContents(); if (!active_contents) continue;
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc index bc9eb5b..31fae59f 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -685,20 +685,6 @@ } } -bool MetricsWebContentsObserver::ReportNavigationRestartPenalty( - content::NavigationHandle* navigation_handle, - const base::TimeDelta mainframe_navigation_restart_penalty) { - DCHECK(!navigation_handle->HasCommitted()); - auto it = provisional_loads_.find(navigation_handle); - if (it == provisional_loads_.end()) - return false; - - it->second->metrics_update_dispatcher() - ->ReportMainFrameNavigationRestartPenalty( - mainframe_navigation_restart_penalty); - return true; -} - void MetricsWebContentsObserver::UpdateTiming( mojom::PageLoadTimingPtr timing, mojom::PageLoadMetadataPtr metadata,
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h index 73596f0..a5a8004 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -154,18 +154,6 @@ const std::vector<mojom::ResourceDataUpdatePtr>& resources, mojom::PageRenderDataPtr render_data); - // Used to report that a NavigationThrottle or other browser intervention - // canceled a navigation and replaced it with a new navigation. - // |mainframe_navigation_restart_penalty| will be applied across all relevant - // timing deltas within the page for the page load tracker corresponding to - // |navigation_handle|. Returns whether or not there was an applicable - // navigation to update. This must be called before commit. Note: This method - // should not be called from a WebContentsObserver's DidFinishNavigation or - // DidStartNavigation since this would cause a race condition. - bool ReportNavigationRestartPenalty( - content::NavigationHandle* navigation_handle, - const base::TimeDelta mainframe_navigation_restart_penalty); - // Informs the observers of the currently committed load that the event // corresponding to |event_key| has occurred. This should not be called within // WebContentsObserver::DidFinishNavigation methods.
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc index 334a545..1692289 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
@@ -459,35 +459,6 @@ CheckNoErrorEvents(); } -TEST_F(MetricsWebContentsObserverTest, ReportNavigationRestartPenalty) { - mojom::PageLoadTiming timing; - page_load_metrics::InitPageLoadTimingForTest(&timing); - timing.navigation_start = base::Time::FromDoubleT(1); - timing.response_start = base::TimeDelta::FromMilliseconds(10); - - std::unique_ptr<content::NavigationSimulator> navigation_simulator = - content::NavigationSimulator::CreateRendererInitiated( - GURL(kDefaultTestUrl), main_rfh()); - navigation_simulator->Start(); - - const base::TimeDelta penalty = base::TimeDelta::FromMilliseconds(5); - observer()->ReportNavigationRestartPenalty( - navigation_simulator->GetNavigationHandle(), penalty); - - navigation_simulator->Commit(); - SimulateTimingUpdate(timing); - - NavigateToUntrackedUrl(); - CheckNoErrorEvents(); - - ASSERT_EQ(1, CountCompleteTimingReported()); - mojom::PageLoadTimingPtr got_timing = complete_timings()[0].Clone(); - // TODO(crbug.com/906718): Test all updated metrics. - EXPECT_EQ(got_timing->navigation_start, timing.navigation_start - penalty); - EXPECT_EQ(got_timing->response_start.value(), - timing.response_start.value() - penalty); -} - TEST_F(MetricsWebContentsObserverTest, SameDocumentNoTrigger) { mojom::PageLoadTiming timing; page_load_metrics::InitPageLoadTimingForTest(&timing);
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc index 8a9d503..4e6f63f 100644 --- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc
@@ -377,7 +377,7 @@ vanilla_script_response->WaitForRequest(); vanilla_script_response->Send(kHttpResponseHeader); vanilla_script_response->Send(std::string(1024, ' ')); - waiter->AddMinimumResourceBytesExpectation(4000); + waiter->AddMinimumNetworkBytesExpectation(4000); waiter->Wait(); // Verify correct numbers of resources are recorded.
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc index c8ef974..8f443bd 100644 --- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc +++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/page_load_metrics/observers/previews_ukm_observer.h" #include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/optional.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" @@ -109,6 +110,9 @@ void PreviewsUKMObserver::RecordPreviewsTypes( const page_load_metrics::PageLoadExtraInfo& info) { // Record the page end reason in UMA. + UMA_HISTOGRAM_ENUMERATION( + "Previews.PageEndReason", info.page_end_reason, + page_load_metrics::PageEndReason::PAGE_END_REASON_COUNT); base::UmaHistogramExactLinear( base::StringPrintf( "Previews.PageEndReason.%s",
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc index 4a9631e..2d84087 100644 --- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
@@ -873,6 +873,9 @@ NavigateToUntrackedUrl(); tester.ExpectUniqueSample( + "Previews.PageEndReason", + page_load_metrics::PageEndReason::END_NEW_NAVIGATION, 1); + tester.ExpectUniqueSample( "Previews.PageEndReason." + GetStringNameForType(type), page_load_metrics::PageEndReason::END_NEW_NAVIGATION, 1); }
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index a3a8728..0009c4f 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -1795,7 +1795,7 @@ browser(), embedded_test_server()->GetURL( "foo.com", "/cross_site_iframe_factory.html?foo")); waiter->Wait(); - int64_t one_frame_page_size = waiter->current_resource_bytes(); + int64_t one_frame_page_size = waiter->current_network_bytes(); waiter = CreatePageLoadMetricsTestWaiter(); waiter->AddPageExpectation(TimingField::kLoadEvent); @@ -1805,10 +1805,47 @@ "a.com", "/cross_site_iframe_factory.html?a(b,c,d(e,f,g))")); // Verify that 7 iframes are fetched, with some amount of tolerance since // favicon is fetched only once. - waiter->AddMinimumResourceBytesExpectation(7 * (one_frame_page_size - 100)); + waiter->AddMinimumNetworkBytesExpectation(7 * (one_frame_page_size - 100)); waiter->Wait(); } +IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, + ChunkedResponse_OverheadDoesNotCountForBodyBytes) { + const char kHttpResponseHeader[] = + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n"; + const int kChunkSize = 5; + const int kNumChunks = 5; + auto main_response = + std::make_unique<net::test_server::ControllableHttpResponse>( + embedded_test_server(), "/mock_page.html", + true /*relative_url_is_prefix*/); + ASSERT_TRUE(embedded_test_server()->Start()); + + auto waiter = CreatePageLoadMetricsTestWaiter(); + + browser()->OpenURL(content::OpenURLParams( + embedded_test_server()->GetURL("/mock_page.html"), content::Referrer(), + WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false)); + + main_response->WaitForRequest(); + main_response->Send(kHttpResponseHeader); + for (int i = 0; i < kNumChunks; i++) { + main_response->Send(std::to_string(kChunkSize)); + main_response->Send("\r\n"); + main_response->Send(std::string(kChunkSize, '*')); + main_response->Send("\r\n"); + } + main_response->Done(); + waiter->AddMinimumCompleteResourcesExpectation(1); + waiter->Wait(); + + // Verify that overheads for each chunk are not reported as body bytes. + EXPECT_EQ(waiter->current_network_body_bytes(), kChunkSize * kNumChunks); +} + IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, ReceivedCompleteResources) { const char kHttpResponseHeader[] = "HTTP/1.1 200 OK\r\n" @@ -1841,7 +1878,7 @@ main_html_response->Send(std::string(1000, ' ')); main_html_response->Done(); waiter->AddMinimumCompleteResourcesExpectation(1); - waiter->AddMinimumResourceBytesExpectation(1000); + waiter->AddMinimumNetworkBytesExpectation(1000); waiter->Wait(); script_response->WaitForRequest(); @@ -1853,7 +1890,7 @@ script_response->Send(std::string(1000, ' ')); // Data received but resource not complete waiter->AddMinimumCompleteResourcesExpectation(1); - waiter->AddMinimumResourceBytesExpectation(2000); + waiter->AddMinimumNetworkBytesExpectation(2000); waiter->Wait(); script_response->Done(); waiter->AddMinimumCompleteResourcesExpectation(2); @@ -1865,7 +1902,7 @@ iframe_response->Send(std::string(2000, ' ')); iframe_response->Done(); waiter->AddMinimumCompleteResourcesExpectation(3); - waiter->AddMinimumResourceBytesExpectation(4000); + waiter->AddMinimumNetworkBytesExpectation(4000); waiter->Wait(); }
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.cc b/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.cc index 84367dd..8a6bfc8 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.cc
@@ -43,9 +43,9 @@ expected_minimum_complete_resources_ = expected_minimum_complete_resources; } -void PageLoadMetricsTestWaiter::AddMinimumResourceBytesExpectation( - int expected_minimum_resource_bytes) { - expected_minimum_resource_bytes_ = expected_minimum_resource_bytes; +void PageLoadMetricsTestWaiter::AddMinimumNetworkBytesExpectation( + int expected_minimum_network_bytes) { + expected_minimum_network_bytes_ = expected_minimum_network_bytes; } bool PageLoadMetricsTestWaiter::DidObserveInPage(TimingField field) const { @@ -117,9 +117,12 @@ std::forward_as_tuple(resource->request_id), std::forward_as_tuple(resource->Clone())); } - if (resource->is_complete) + if (resource->is_complete) { current_complete_resources_++; - current_resource_bytes_ += resource->delta_bytes; + if (!resource->was_fetched_via_cache) + current_network_body_bytes_ += resource->encoded_body_length; + } + current_network_bytes_ += resource->delta_bytes; } if (ExpectationsSatisfied() && run_loop_) run_loop_->Quit(); @@ -186,8 +189,8 @@ return (expected_minimum_complete_resources_ == 0 || current_complete_resources_ >= expected_minimum_complete_resources_) && - (expected_minimum_resource_bytes_ == 0 || - current_resource_bytes_ >= expected_minimum_resource_bytes_); + (expected_minimum_network_bytes_ == 0 || + current_network_bytes_ >= expected_minimum_network_bytes_); } bool PageLoadMetricsTestWaiter::ExpectationsSatisfied() const {
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h b/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h index 88eca45c..d7046df 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h
@@ -45,7 +45,7 @@ int expected_minimum_complete_resources); // Add aggregate received resource bytes expectation. - void AddMinimumResourceBytesExpectation(int expected_minimum_resource_bytes); + void AddMinimumNetworkBytesExpectation(int expected_minimum_network_bytes); // Whether the given TimingField was observed in the page. bool DidObserveInPage(TimingField field) const; @@ -54,7 +54,11 @@ // expectation methods. All matching fields must be set to end this wait. void Wait(); - int64_t current_resource_bytes() const { return current_resource_bytes_; } + int64_t current_network_bytes() const { return current_network_bytes_; } + + int64_t current_network_body_bytes() const { + return current_network_body_bytes_; + } protected: virtual bool ExpectationsSatisfied() const; @@ -163,9 +167,12 @@ TimingFieldBitSet observed_page_fields_; int current_complete_resources_ = 0; - int64_t current_resource_bytes_ = 0; + int64_t current_network_bytes_ = 0; + + // Network body bytes are only counted for complete resources. + int64_t current_network_body_bytes_ = 0; int expected_minimum_complete_resources_ = 0; - int expected_minimum_resource_bytes_ = 0; + int expected_minimum_network_bytes_ = 0; bool attach_on_tracker_creation_ = false; bool did_add_observer_ = false;
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc index 301c122..7968182 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
@@ -261,34 +261,15 @@ : target_(target) {} // Merge timing values from |new_page_load_timing| into the target - // PageLoadTiming, applying the |navigation_start_offset| to applicable - // metrics with respect to |is_main_frame|. - void MergeAndApplyOffset(base::TimeDelta navigation_start_offset, - const mojom::PageLoadTiming& new_page_load_timing, - bool is_main_frame) { - // TODO(crbug.com/906718): This approach is hard to maintain and likely to - // get stale over time. + // PageLoadTiming; + void Merge(base::TimeDelta navigation_start_offset, + const mojom::PageLoadTiming& new_page_load_timing, + bool is_main_frame) { MergePaintTiming(navigation_start_offset, *new_page_load_timing.paint_timing, is_main_frame); MergeInteractiveTiming(navigation_start_offset, *new_page_load_timing.interactive_timing, is_main_frame); - // Don't need to merge these main-frame only metrics: merely apply the - // offset. - if (is_main_frame) { - target_->navigation_start = - new_page_load_timing.navigation_start + navigation_start_offset; - MaybeUpdateTimeDelta(&target_->response_start, navigation_start_offset, - new_page_load_timing.response_start); - MaybeUpdateTimeDelta(&target_->input_to_navigation_start, - navigation_start_offset, - new_page_load_timing.input_to_navigation_start); - - ApplyDocumentTimingOffset(navigation_start_offset, - *new_page_load_timing.document_timing); - ApplyParseTimingOffset(navigation_start_offset, - *new_page_load_timing.parse_timing); - } } // Whether we merged a new value. @@ -362,25 +343,10 @@ MaybeUpdateTimeDelta(&target_paint_timing->first_contentful_paint, navigation_start_offset, new_paint_timing.first_contentful_paint); - // These are currently a no-op on main frames. - MaybeUpdateTimeDelta(&target_paint_timing->largest_image_paint, - navigation_start_offset, - new_paint_timing.largest_image_paint); - MaybeUpdateTimeDelta(&target_paint_timing->last_image_paint, - navigation_start_offset, - new_paint_timing.last_image_paint); - MaybeUpdateTimeDelta(&target_paint_timing->largest_text_paint, - navigation_start_offset, - new_paint_timing.largest_text_paint); - MaybeUpdateTimeDelta(&target_paint_timing->last_text_paint, - navigation_start_offset, - new_paint_timing.last_text_paint); - if (is_main_frame) { // First meaningful paint is only tracked in the main frame. - MaybeUpdateTimeDelta(&target_paint_timing->first_meaningful_paint, - navigation_start_offset, - new_paint_timing.first_meaningful_paint); + target_paint_timing->first_meaningful_paint = + new_paint_timing.first_meaningful_paint; } } @@ -425,32 +391,6 @@ } } - void ApplyDocumentTimingOffset( - base::TimeDelta navigation_start_offset, - const mojom::DocumentTiming& new_document_timing) { - mojom::DocumentTiming* target_document_timing = - target_->document_timing.get(); - MaybeUpdateTimeDelta( - &target_document_timing->dom_content_loaded_event_start, - navigation_start_offset, - new_document_timing.dom_content_loaded_event_start); - MaybeUpdateTimeDelta(&target_document_timing->load_event_start, - navigation_start_offset, - new_document_timing.load_event_start); - MaybeUpdateTimeDelta(&target_document_timing->first_layout, - navigation_start_offset, - new_document_timing.first_layout); - } - - void ApplyParseTimingOffset(base::TimeDelta navigation_start_offset, - const mojom::ParseTiming& new_parse_timing) { - mojom::ParseTiming* target_parse_timing = target_->parse_timing.get(); - MaybeUpdateTimeDelta(&target_parse_timing->parse_start, - navigation_start_offset, new_parse_timing.parse_start); - MaybeUpdateTimeDelta(&target_parse_timing->parse_stop, - navigation_start_offset, new_parse_timing.parse_stop); - } - // The target PageLoadTiming we are merging values into. mojom::PageLoadTiming* const target_; @@ -522,11 +462,6 @@ } } -void PageLoadMetricsUpdateDispatcher::ReportMainFrameNavigationRestartPenalty( - base::TimeDelta penalty) { - total_main_frame_navigation_restart_penalty_ += penalty; -} - void PageLoadMetricsUpdateDispatcher::UpdateMetrics( content::RenderFrameHost* render_frame_host, mojom::PageLoadTimingPtr new_timing, @@ -600,13 +535,9 @@ client_->OnSubFrameTimingChanged(render_frame_host, *new_timing); - // |total_main_frame_navigation_restart_penalty_| should also be applied to - // subframes since this penalty is associated with the main frame. - base::TimeDelta navigation_start_offset = - it->second - total_main_frame_navigation_restart_penalty_; + base::TimeDelta navigation_start_offset = it->second; PageLoadTimingMerger merger(pending_merged_page_timing_.get()); - merger.MergeAndApplyOffset(navigation_start_offset, *new_timing, - false /* is_main_frame */); + merger.Merge(navigation_start_offset, *new_timing, false /* is_main_frame */); MaybeDispatchTimingUpdates(merger.should_buffer_timing_update_callback()); } @@ -654,33 +585,9 @@ mojom::InteractiveTimingPtr last_interactive_timing = std::move(pending_merged_page_timing_->interactive_timing); - base::TimeDelta navigation_start_offset = - -total_main_frame_navigation_restart_penalty_; // Update the latest candidate to the corresponding buffers. We will dispatch // the last candidate at the page load end. Because we don't want to dispatch // the non-last candidate here, we clear it from |new_timing|. - // Since this also means that these timings won't get - // |navigation_start_offset| applied in the merger, apply it here. - if (new_timing->paint_timing->largest_image_paint.has_value()) { - new_timing->paint_timing->largest_image_paint = - new_timing->paint_timing->largest_image_paint.value() + - navigation_start_offset; - } - if (new_timing->paint_timing->last_image_paint.has_value()) { - new_timing->paint_timing->last_image_paint = - new_timing->paint_timing->last_image_paint.value() + - navigation_start_offset; - } - if (new_timing->paint_timing->largest_text_paint.has_value()) { - new_timing->paint_timing->largest_text_paint = - new_timing->paint_timing->largest_text_paint.value() + - navigation_start_offset; - } - if (new_timing->paint_timing->last_text_paint.has_value()) { - new_timing->paint_timing->last_text_paint = - new_timing->paint_timing->last_text_paint.value() + - navigation_start_offset; - } largest_image_paint_.swap(new_timing->paint_timing->largest_image_paint); new_timing->paint_timing->largest_image_paint.reset(); last_image_paint_.swap(new_timing->paint_timing->last_image_paint); @@ -699,8 +606,7 @@ std::move(last_interactive_timing); PageLoadTimingMerger merger(pending_merged_page_timing_.get()); - merger.MergeAndApplyOffset(navigation_start_offset, *new_timing, - true /* is_main_frame */); + merger.Merge(base::TimeDelta(), *new_timing, true /* is_main_frame */); MaybeDispatchTimingUpdates(merger.should_buffer_timing_update_callback()); }
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h index 3307afc4b..f343290 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
@@ -136,11 +136,6 @@ void DidFinishSubFrameNavigation( content::NavigationHandle* navigation_handle); - // Increases |total_main_frame_navigation_restart_penalty_| by the given - // delta. This should be fully updated before commit. See the comment on - // |total_main_frame_navigation_restart_penalty_|. - void ReportMainFrameNavigationRestartPenalty(base::TimeDelta penalty); - void ShutDown(); const mojom::PageLoadTiming& timing() const { @@ -204,13 +199,6 @@ mojom::PageLoadMetadataPtr subframe_metadata_; mojom::PageRenderDataPtr main_frame_render_data_; - // This time delta is an otherwise unknown penalty where the final navigation - // to a page was not the original (i.e.: user started) navigation. This can be - // caused by client redirects or other browser-based interventions like - // previews. Applying this delta will reconcile this page load metric with the - // time when the original navigation started. This will be applied to all - // metrics just before they are sent to the client. - base::TimeDelta total_main_frame_navigation_restart_penalty_; // Navigation start offsets for the most recently committed document in each // frame.
diff --git a/chrome/browser/permissions/permission_uma_util.cc b/chrome/browser/permissions/permission_uma_util.cc index e2c560d..e409651 100644 --- a/chrome/browser/permissions/permission_uma_util.cc +++ b/chrome/browser/permissions/permission_uma_util.cc
@@ -101,7 +101,7 @@ } void RecordEngagementMetric(const std::vector<PermissionRequest*>& requests, - const content::WebContents* web_contents, + content::WebContents* web_contents, const std::string& action) { PermissionRequestType type = requests[0]->GetPermissionRequestType(); if (requests.size() > 1) @@ -239,7 +239,7 @@ void PermissionUmaUtil::PermissionPromptResolved( const std::vector<PermissionRequest*>& requests, - const content::WebContents* web_contents, + content::WebContents* web_contents, PermissionAction permission_action) { std::string action_string;
diff --git a/chrome/browser/permissions/permission_uma_util.h b/chrome/browser/permissions/permission_uma_util.h index afa054e2..59f2372b 100644 --- a/chrome/browser/permissions/permission_uma_util.h +++ b/chrome/browser/permissions/permission_uma_util.h
@@ -87,7 +87,7 @@ static void PermissionPromptResolved( const std::vector<PermissionRequest*>& requests, - const content::WebContents* web_contents, + content::WebContents* web_contents, PermissionAction permission_action); static void RecordWithBatteryBucket(const std::string& histogram);
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc index 4346da0..bd8ad51a 100644 --- a/chrome/browser/previews/previews_lite_page_browsertest.cc +++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -636,10 +636,6 @@ 1); histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", false, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); } { @@ -649,10 +645,6 @@ VerifyPreviewLoaded(); histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", true, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); } { @@ -668,10 +660,6 @@ 1); histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", false, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); } { @@ -693,10 +681,6 @@ PreviewsLitePageNavigationThrottle::IneligibleReason::kHttpPost, 1); histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", false, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); } { @@ -712,10 +696,6 @@ 1); histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", false, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); } { @@ -729,10 +709,6 @@ 1); histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", false, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); VerifyErrorPageLoaded(); } @@ -749,10 +725,6 @@ 1); histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", false, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); } { @@ -772,10 +744,6 @@ 1); histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", false, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); // Reset ECT for future tests. g_browser_process->network_quality_tracker() @@ -885,10 +853,6 @@ histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", true, 1); histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( "Previews.ServerLitePage.HttpOnlyFallbackPenalty", 1); histogram_tester.ExpectBucketCount( "Previews.ServerLitePage.ServerResponse", @@ -908,10 +872,6 @@ histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", true, 1); histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( "Previews.ServerLitePage.HttpOnlyFallbackPenalty", 1); histogram_tester.ExpectBucketCount( "Previews.ServerLitePage.ServerResponse", @@ -941,10 +901,6 @@ histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", true, 1); histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 2); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( "Previews.ServerLitePage.HttpOnlyFallbackPenalty", 1); histogram_tester.ExpectBucketCount( "Previews.ServerLitePage.ServerResponse", @@ -960,10 +916,6 @@ histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", true, 1); histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 2); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); - histogram_tester.ExpectTotalCount( "Previews.ServerLitePage.HttpOnlyFallbackPenalty", 1); histogram_tester.ExpectBucketCount( "Previews.ServerLitePage.ServerResponse", @@ -1088,29 +1040,6 @@ histogram_tester.ExpectBucketCount( "Previews.ServerLitePage.ServerResponse", PreviewsLitePageNavigationThrottle::ServerResponse::kTimeout, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 2); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); - // Since this test already has a delay baked in, make sure the reported - // penalty is at least the length of the delay. - int max_penalty = 0; - for (const base::Bucket& bucket : histogram_tester.GetAllSamples( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty")) { - if (bucket.min > max_penalty) { - max_penalty = bucket.min; - } - } - // Expecting |max_penalty| > |kTimeoutMs| is flaky in release builds because - // of histogram bucketing. Since HistogramTester::Bucket doesn't provide a - // bucket max, if |max_penalty| < |kTimeoutMs|, check that a sample exists - // in the |kTimeoutMs| bucket. - if (max_penalty <= kTimeoutMs) { - EXPECT_GE(histogram_tester.GetBucketCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", - kTimeoutMs), - 1); - } // else, test passes } { @@ -1154,10 +1083,6 @@ histogram_tester.ExpectBucketCount("Previews.ServerLitePage.Triggered", true, 1); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", 2); - histogram_tester.ExpectTotalCount( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", 0); histogram_tester.ExpectBucketCount( "Previews.ServerLitePage.ServerResponse", PreviewsLitePageNavigationThrottle::ServerResponse::kFailed, 1);
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc index 70ebe5f5..335f475c 100644 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc +++ b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
@@ -24,7 +24,6 @@ #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" -#include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" #include "chrome/browser/previews/previews_lite_page_decider.h" #include "chrome/browser/previews/previews_service.h" #include "chrome/browser/previews/previews_service_factory.h" @@ -93,43 +92,6 @@ return url_params; } -// This is called on |WillStartRequest| to check whether the given |handle| is -// for a navigation that was started by this preview. If it was, the penalty -// (time between the original navigation start and the navigation start of -// |handle|) is reported to PLM. -void MaybeReportNavigationRestartPenalty(content::NavigationHandle* handle) { - PreviewsUITabHelper* ui_tab_helper = - PreviewsUITabHelper::FromWebContents(handle->GetWebContents()); - if (!ui_tab_helper) - return; - - previews::PreviewsUserData* previews_data = - ui_tab_helper->GetPreviewsUserData(handle); - if (!previews_data) - return; - - previews::PreviewsUserData::ServerLitePageInfo* info = - previews_data->server_lite_page_info(); - if (!info) - return; - - DCHECK_GT(info->original_navigation_start, base::TimeTicks()); - base::TimeDelta penalty = - handle->NavigationStart() - info->original_navigation_start; - - bool updated = page_load_metrics::MetricsWebContentsObserver::FromWebContents( - handle->GetWebContents()) - ->ReportNavigationRestartPenalty(handle, penalty); - DCHECK(updated); - if (updated) { - UMA_HISTOGRAM_MEDIUM_TIMES( - "Previews.ServerLitePage.ReportedNavigationRestartPenalty", penalty); - } else { - UMA_HISTOGRAM_MEDIUM_TIMES( - "Previews.ServerLitePage.NotReportedNavigationRestartPenalty", penalty); - } -} - // Gets the ServerLitePageInfo struct from an existing attempted lite page // navigation, if there is one. If not, returns nullptr. std::unique_ptr<previews::PreviewsUserData::ServerLitePageInfo> @@ -581,7 +543,6 @@ return content::NavigationThrottle::CANCEL; } - MaybeReportNavigationRestartPenalty(navigation_handle()); return MaybeNavigateToPreview(); }
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc index 7f44a891..4664e65 100644 --- a/chrome/browser/printing/print_job.cc +++ b/chrome/browser/printing/print_job.cc
@@ -43,7 +43,7 @@ : is_job_pending_(false), is_canceling_(false), task_runner_(base::ThreadTaskRunnerHandle::Get()) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); } PrintJob::~PrintJob() {
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc index 3df598de..b44f906 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc
@@ -23,7 +23,7 @@ ContextMenuContentTypePlatformApp::~ContextMenuContentTypePlatformApp() { } -const Extension* ContextMenuContentTypePlatformApp::GetExtension() const { +const Extension* ContextMenuContentTypePlatformApp::GetExtension() { ProcessManager* process_manager = ProcessManager::Get(source_web_contents()->GetBrowserContext()); return process_manager->GetExtensionForWebContents(
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.h b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.h index 1dccf81f..407a930 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.h +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.h
@@ -26,7 +26,7 @@ private: friend class ContextMenuContentTypeFactory; - const extensions::Extension* GetExtension() const; + const extensions::Extension* GetExtension(); DISALLOW_COPY_AND_ASSIGN(ContextMenuContentTypePlatformApp); };
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 0e22e0e..6482e62 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -2541,8 +2541,9 @@ else base::RecordAction(UserMetricsAction("MediaContextMenu_Pause")); - MediaPlayerActionAt(gfx::Point(params_.x, params_.y), - WebMediaPlayerAction(WebMediaPlayerAction::kPlay, play)); + MediaPlayerActionAt( + gfx::Point(params_.x, params_.y), + WebMediaPlayerAction(WebMediaPlayerAction::Type::kPlay, play)); } void RenderViewContextMenu::ExecMute() { @@ -2552,15 +2553,16 @@ else base::RecordAction(UserMetricsAction("MediaContextMenu_Unmute")); - MediaPlayerActionAt(gfx::Point(params_.x, params_.y), - WebMediaPlayerAction(WebMediaPlayerAction::kMute, mute)); + MediaPlayerActionAt( + gfx::Point(params_.x, params_.y), + WebMediaPlayerAction(WebMediaPlayerAction::Type::kMute, mute)); } void RenderViewContextMenu::ExecLoop() { base::RecordAction(UserMetricsAction("MediaContextMenu_Loop")); MediaPlayerActionAt( gfx::Point(params_.x, params_.y), - WebMediaPlayerAction(WebMediaPlayerAction::kLoop, + WebMediaPlayerAction(WebMediaPlayerAction::Type::kLoop, !IsCommandIdChecked(IDC_CONTENT_CONTEXT_LOOP))); } @@ -2568,7 +2570,7 @@ base::RecordAction(UserMetricsAction("MediaContextMenu_Controls")); MediaPlayerActionAt( gfx::Point(params_.x, params_.y), - WebMediaPlayerAction(WebMediaPlayerAction::kControls, + WebMediaPlayerAction(WebMediaPlayerAction::Type::kControls, !IsCommandIdChecked(IDC_CONTENT_CONTEXT_CONTROLS))); } @@ -2700,7 +2702,7 @@ MediaPlayerActionAt( gfx::Point(params_.x, params_.y), - WebMediaPlayerAction(WebMediaPlayerAction::kPictureInPicture, + WebMediaPlayerAction(WebMediaPlayerAction::Type::kPictureInPicture, !picture_in_picture_active)); }
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc index 948b53d..f62c3f2 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -205,7 +205,7 @@ } void CheckIfTabCanCommunicateWithUserWhileInBackground( - const content::WebContents* web_contents, + content::WebContents* web_contents, DecisionDetails* details) { DCHECK(details);
diff --git a/chrome/browser/resource_coordinator/tab_metrics_logger.cc b/chrome/browser/resource_coordinator/tab_metrics_logger.cc index bec14f94..28493d78 100644 --- a/chrome/browser/resource_coordinator/tab_metrics_logger.cc +++ b/chrome/browser/resource_coordinator/tab_metrics_logger.cc
@@ -81,7 +81,7 @@ // static int TabMetricsLogger::GetSiteEngagementScore( - const content::WebContents* web_contents) { + content::WebContents* web_contents) { if (!SiteEngagementService::IsEnabled()) return -1;
diff --git a/chrome/browser/resource_coordinator/tab_metrics_logger.h b/chrome/browser/resource_coordinator/tab_metrics_logger.h index c60888c..519d188 100644 --- a/chrome/browser/resource_coordinator/tab_metrics_logger.h +++ b/chrome/browser/resource_coordinator/tab_metrics_logger.h
@@ -89,7 +89,7 @@ // Returns the site engagement score for the WebContents, rounded down to 10s // to limit granularity. Returns -1 if site engagement service is disabled. - static int GetSiteEngagementScore(const content::WebContents* web_contents); + static int GetSiteEngagementScore(content::WebContents* web_contents); // Creates TabFeatures for logging or scoring tabs. // A common function for populating these features ensures that the same
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/live_regions_test.unitjs b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/live_regions_test.unitjs index bf7256d..6ff3391 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/live_regions_test.unitjs +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/live_regions_test.unitjs
@@ -131,7 +131,8 @@ /** * Test adding element to a atomic and non-atomic live regions. */ -TEST_F('ChromeVoxLiveRegionsUnitTest', 'AddToLiveRegion', function() { +// Flaky on Chromium OS: crbug.com/909973. +TEST_F('ChromeVoxLiveRegionsUnitTest', 'DISABLED_AddToLiveRegion', function() { this.loadDoc(function() {/*! <div> <div id="non_atomic_buddylist" aria-live="polite">
diff --git a/chrome/browser/resources/settings/people_page/BUILD.gn b/chrome/browser/resources/settings/people_page/BUILD.gn index dc855b4..dab2acb9 100644 --- a/chrome/browser/resources/settings/people_page/BUILD.gn +++ b/chrome/browser/resources/settings/people_page/BUILD.gn
@@ -19,6 +19,7 @@ ":lock_state_behavior", ":manage_profile", ":manage_profile_browser_proxy", + ":people_browser_proxy", ":people_page", ":profile_info_browser_proxy", ":setup_fingerprint_dialog", @@ -150,10 +151,17 @@ ] } +js_library("people_browser_proxy") { + deps = [ + "//ui/webui/resources/js:cr", + ] +} + js_library("people_page") { deps = [ ":lock_screen", ":lock_state_behavior", + ":people_browser_proxy", ":profile_info_browser_proxy", ":signout_dialog", ":sync_browser_proxy",
diff --git a/chrome/browser/resources/settings/people_page/people_browser_proxy.html b/chrome/browser/resources/settings/people_page/people_browser_proxy.html new file mode 100644 index 0000000..8fa2b67c --- /dev/null +++ b/chrome/browser/resources/settings/people_page/people_browser_proxy.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="people_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/settings/people_page/people_browser_proxy.js b/chrome/browser/resources/settings/people_page/people_browser_proxy.js new file mode 100644 index 0000000..1484661 --- /dev/null +++ b/chrome/browser/resources/settings/people_page/people_browser_proxy.js
@@ -0,0 +1,38 @@ +// 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. + +/** + * @fileoverview A helper object used from the People section to interact with + * the browser. + */ + +cr.exportPath('settings'); + +cr.define('settings', function() { + /** @interface */ + class PeopleBrowserProxy { + // TODO(dpapad): Create a simple OpenWindowProxy class that replaces the + // need for this method and similar methods in other BrowserProxy classes. + /** + * Opens the specified URL in a new tab. + * @param {string} url + */ + openURL(url) {} + } + + /** @implements {settings.PeopleBrowserProxy} */ + class PeopleBrowserProxyImpl { + /** @override */ + openURL(url) { + window.open(url); + } + } + + cr.addSingletonGetter(PeopleBrowserProxyImpl); + + return { + PeopleBrowserProxy: PeopleBrowserProxy, + PeopleBrowserProxyImpl: PeopleBrowserProxyImpl, + }; +});
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html index b5ad088..5700245 100644 --- a/chrome/browser/resources/settings/people_page/people_page.html +++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -12,9 +12,10 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="../controls/settings_toggle_button.html"> -<link rel="import" href="sync_page.html"> +<link rel="import" href="people_browser_proxy.html"> <link rel="import" href="profile_info_browser_proxy.html"> <link rel="import" href="sync_browser_proxy.html"> +<link rel="import" href="sync_page.html"> <link rel="import" href="../icons.html"> <link rel="import" href="../route.html"> <link rel="import" href="../settings_page/settings_animated_pages.html">
diff --git a/chrome/browser/resources/settings/people_page/people_page.js b/chrome/browser/resources/settings/people_page/people_page.js index f49e7fd..c84611e 100644 --- a/chrome/browser/resources/settings/people_page/people_page.js +++ b/chrome/browser/resources/settings/people_page/people_page.js
@@ -311,12 +311,16 @@ }, /** - * Shows the manage passwords sub page. + * Shows a page to manage passwords. This is either the passwords sub page or + * the Google Password Manager page. * @param {!Event} event * @private */ onPasswordsTap_: function(event) { - settings.navigateTo(settings.routes.MANAGE_PASSWORDS); + loadTimeData.getBoolean('navigateToGooglePasswordManager') ? + settings.PeopleBrowserProxyImpl.getInstance().openURL( + loadTimeData.getString('googlePasswordManagerUrl')) : + settings.navigateTo(settings.routes.MANAGE_PASSWORDS); }, /**
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 4099d46..ca10f698 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -763,6 +763,12 @@ <structure name="IDR_SETTINGS_PAYMENTS_SECTION_JS" file="passwords_and_forms_page/payments_section.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_PEOPLE_BROWSER_PROXY_HTML" + file="people_page/people_browser_proxy.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_PEOPLE_BROWSER_PROXY_JS" + file="people_page/people_browser_proxy.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_PEOPLE_PAGE_HTML" file="people_page/people_page.html" type="chrome_html"
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn index b8f2eec..4e16a6fa 100644 --- a/chrome/browser/safe_browsing/BUILD.gn +++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -27,6 +27,7 @@ sources += [ "chrome_cleaner/chrome_cleaner_controller_impl_win.cc", "chrome_cleaner/chrome_cleaner_controller_impl_win.h", + "chrome_cleaner/chrome_cleaner_controller_win.cc", "chrome_cleaner/chrome_cleaner_controller_win.h", "chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc", "chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.h",
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc index 728e850..c66b45f 100644 --- a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc +++ b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
@@ -168,7 +168,7 @@ // Feature extraction takes ownership of the request object // and passes it along to the done callback in the end. StartExtractMalwareFeatures(request); - ASSERT_TRUE(base::MessageLoopForUI::IsCurrent()); + ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet()); base::RunLoop().Run(); EXPECT_EQ(1U, success_.count(request)); EXPECT_TRUE(success_[request]);
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win_unittest.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win_unittest.cc index acda30f..23e1a3e 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win_unittest.cc
@@ -28,6 +28,7 @@ #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/chrome_cleaner/public/constants/constants.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h" @@ -50,10 +51,13 @@ using ::testing::Values; using ::testing::ValuesIn; using CrashPoint = MockChromeCleanerProcess::CrashPoint; +using ExtensionCleaningFeatureStatus = + MockChromeCleanerProcess::ExtensionCleaningFeatureStatus; using IdleReason = ChromeCleanerController::IdleReason; using ItemsReporting = MockChromeCleanerProcess::ItemsReporting; using State = ChromeCleanerController::State; using UserResponse = ChromeCleanerController::UserResponse; +using UwsFoundStatus = MockChromeCleanerProcess::UwsFoundStatus; // Returns the PromptAcceptance value that ChromeCleanerController is supposed // to send to the Chrome Cleaner process when ReplyWithUserResponse() is @@ -221,17 +225,6 @@ kFetchSuccessValidProcess, }; -enum class UwsFoundStatus { - kNoUwsFound, - kUwsFoundRebootRequired, - kUwsFoundNoRebootRequired, -}; - -enum class ExtensionCleaningFeatureStatus { - kEnabled, - kDisabled, -}; - typedef std::tuple<CleanerProcessStatus, CrashPoint, UwsFoundStatus, @@ -660,100 +653,6 @@ } } -std::ostream& operator<<(std::ostream& out, CrashPoint crash_point) { - switch (crash_point) { - case CrashPoint::kNone: - return out << "NoCrash"; - case CrashPoint::kOnStartup: - return out << "CrashOnStartup"; - case CrashPoint::kAfterConnection: - return out << "CrashAfterConnection"; - case CrashPoint::kAfterRequestSent: - return out << "CrashAfterRequestSent"; - case CrashPoint::kAfterResponseReceived: - return out << "CrashAfterResponseReceived"; - default: - NOTREACHED(); - return out << "UnknownCrashPoint" << crash_point; - } -} - -std::ostream& operator<<(std::ostream& out, UwsFoundStatus status) { - switch (status) { - case UwsFoundStatus::kNoUwsFound: - return out << "NoUwsFound"; - case UwsFoundStatus::kUwsFoundRebootRequired: - return out << "UwsFoundRebootRequired"; - case UwsFoundStatus::kUwsFoundNoRebootRequired: - return out << "UwsFoundNoRebootRequired"; - default: - NOTREACHED(); - return out << "UnknownFoundStatus" << status; - } -} - -std::ostream& operator<<(std::ostream& out, - ExtensionCleaningFeatureStatus status) { - switch (status) { - case ExtensionCleaningFeatureStatus::kEnabled: - return out << "ExtensionCleaningEnabled"; - case ExtensionCleaningFeatureStatus::kDisabled: - return out << "ExtensionCleaningDisabled"; - default: - NOTREACHED(); - return out << "UnknownExtensionCleaningStatus" << status; - } -} - -std::ostream& operator<<(std::ostream& out, ItemsReporting items_reporting) { - switch (items_reporting) { - case ItemsReporting::kUnsupported: - return out << "kUnsupported"; - case ItemsReporting::kNotReported: - return out << "kNotReported"; - case ItemsReporting::kReported: - return out << "kReported"; - default: - NOTREACHED(); - return out << "UnknownItemsReporting"; - } -} - -std::ostream& operator<<(std::ostream& out, UserResponse response) { - switch (response) { - case UserResponse::kAcceptedWithLogs: - return out << "UserAcceptedWithLogs"; - case UserResponse::kAcceptedWithoutLogs: - return out << "UserAcceptedWithoutLogs"; - case UserResponse::kDenied: - return out << "UserDenied"; - case UserResponse::kDismissed: - return out << "UserDismissed"; - default: - NOTREACHED(); - return out << "UnknownUserResponse" << response; - } -} - -// ::testing::PrintToStringParamName does not format tuples as a valid test -// name, so this functor can be used to get each element in the tuple -// explicitly and format them using the above operator<< overrides. -struct ChromeCleanerControllerTestParamsToString { - std::string operator()( - const ::testing::TestParamInfo<ChromeCleanerControllerTestParams>& info) - const { - std::ostringstream param_name; - param_name << std::get<0>(info.param) << "_"; - param_name << std::get<1>(info.param) << "_"; - param_name << std::get<2>(info.param) << "_"; - param_name << std::get<3>(info.param) << "_"; - param_name << std::get<4>(info.param) << "_"; - param_name << std::get<5>(info.param) << "_"; - param_name << std::get<6>(info.param); - return param_name.str(); - } -}; - // This includes all crash points after kOnStartup, except kAfterRequestSent. // That one's not used because if we induce a crash after the mock cleaner // sends a request, there would be a race condition between the request being @@ -783,7 +682,7 @@ UserResponse::kAcceptedWithoutLogs, UserResponse::kDenied, UserResponse::kDismissed)), - ChromeCleanerControllerTestParamsToString()); + chrome_cleaner::GetParamNameForTest()); // Tests where the process gets past the startup phase but finds nothing to // clean. Since we don't progress to any stage where the parameters after @@ -799,7 +698,7 @@ Values(ItemsReporting::kNotReported), Values(ItemsReporting::kNotReported), Values(UserResponse::kDismissed)), - ChromeCleanerControllerTestParamsToString()); + chrome_cleaner::GetParamNameForTest()); // Tests where the process fails before starting a scan. This never gets far // enough to collect results, so we can save time by not repeating the tests @@ -819,7 +718,7 @@ Values(ItemsReporting::kUnsupported), Values(ItemsReporting::kUnsupported), Values(UserResponse::kAcceptedWithLogs)), - ChromeCleanerControllerTestParamsToString()); + chrome_cleaner::GetParamNameForTest()); // Tests for the interaction between reporter runs and all possible states. // Signals from reporter execution may lead to state transitions only if there @@ -939,36 +838,15 @@ SwReporterInvocationResult::kCleanupToBeOffered); } -std::ostream& operator<<(std::ostream& out, - ChromeCleanerController::State state) { - switch (state) { - case ChromeCleanerController::State::kIdle: - return out << "Idle"; - case ChromeCleanerController::State::kReporterRunning: - return out << "ReporterRunning"; - case ChromeCleanerController::State::kScanning: - return out << "Scanning"; - case ChromeCleanerController::State::kInfected: - return out << "Infected"; - case ChromeCleanerController::State::kCleaning: - return out << "Cleaning"; - case ChromeCleanerController::State::kRebootRequired: - return out << "RebootRequired"; - default: - NOTREACHED(); - return out << "UnknownUserResponse" << state; - } -} - -INSTANTIATE_TEST_CASE_P( - All, - ChromeCleanerControllerReporterInteractionTest, - Values(ChromeCleanerController::State::kIdle, - ChromeCleanerController::State::kReporterRunning, - ChromeCleanerController::State::kScanning, - ChromeCleanerController::State::kInfected, - ChromeCleanerController::State::kCleaning, - ChromeCleanerController::State::kRebootRequired)); +INSTANTIATE_TEST_CASE_P(All, + ChromeCleanerControllerReporterInteractionTest, + Values(ChromeCleanerController::State::kIdle, + ChromeCleanerController::State::kReporterRunning, + ChromeCleanerController::State::kScanning, + ChromeCleanerController::State::kInfected, + ChromeCleanerController::State::kCleaning, + ChromeCleanerController::State::kRebootRequired), + chrome_cleaner::GetParamNameForTest()); } // namespace } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc new file mode 100644 index 0000000..2ab9d444 --- /dev/null +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
@@ -0,0 +1,48 @@ +// 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/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h" + +namespace safe_browsing { + +using UserResponse = ChromeCleanerController::UserResponse; + +std::ostream& operator<<(std::ostream& out, + ChromeCleanerController::State state) { + switch (state) { + case ChromeCleanerController::State::kIdle: + return out << "Idle"; + case ChromeCleanerController::State::kReporterRunning: + return out << "ReporterRunning"; + case ChromeCleanerController::State::kScanning: + return out << "Scanning"; + case ChromeCleanerController::State::kInfected: + return out << "Infected"; + case ChromeCleanerController::State::kCleaning: + return out << "Cleaning"; + case ChromeCleanerController::State::kRebootRequired: + return out << "RebootRequired"; + default: + NOTREACHED(); + return out << "UnknownUserResponse" << state; + } +} + +std::ostream& operator<<(std::ostream& out, UserResponse response) { + switch (response) { + case UserResponse::kAcceptedWithLogs: + return out << "UserAcceptedWithLogs"; + case UserResponse::kAcceptedWithoutLogs: + return out << "UserAcceptedWithoutLogs"; + case UserResponse::kDenied: + return out << "UserDenied"; + case UserResponse::kDismissed: + return out << "UserDismissed"; + default: + NOTREACHED(); + return out << "UnknownUserResponse"; + } +} + +} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h index 048c5cb..dae7ce3a 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
@@ -224,6 +224,13 @@ DISALLOW_COPY_AND_ASSIGN(ChromeCleanerController); }; +// These are used for debug output in tests. +std::ostream& operator<<(std::ostream& out, + ChromeCleanerController::State state); + +std::ostream& operator<<(std::ostream& out, + ChromeCleanerController::UserResponse response); + } // namespace safe_browsing #endif // CHROME_BROWSER_SAFE_BROWSING_CHROME_CLEANER_CHROME_CLEANER_CONTROLLER_WIN_H_
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc index d21a5142..d4f6cc91 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc
@@ -26,6 +26,7 @@ #include "chrome/test/base/testing_profile_manager.h" #include "components/chrome_cleaner/public/constants/constants.h" #include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -45,6 +46,9 @@ using ::testing::UnorderedElementsAreArray; using ::testing::Values; using ChromeMetricsStatus = ChromeCleanerRunner::ChromeMetricsStatus; +using ExtensionCleaningFeatureStatus = + MockChromeCleanerProcess::ExtensionCleaningFeatureStatus; +using UwsFoundStatus = MockChromeCleanerProcess::UwsFoundStatus; enum class ReporterEngine { kUnspecified, @@ -234,33 +238,18 @@ ChromePromptValue::kUserInitiated), Bool())); -// Enum to be used as parameter for the ChromeCleanerRunnerTest fixture below. -enum class UwsFoundState { - kNoUwsFound, - kUwsFoundRebootRequired, - kUwsFoundNoRebootRequired, -}; +typedef std::tuple<UwsFoundStatus, + ExtensionCleaningFeatureStatus, + MockChromeCleanerProcess::ItemsReporting, + MockChromeCleanerProcess::ItemsReporting, + MockChromeCleanerProcess::CrashPoint, + PromptAcceptance> + ChromeCleanerRunnerTestParams; // Test fixture for testing ChromeCleanerRunner with a mock Chrome Cleaner // process. -// -// Parameters: -// -// - uws_found_state (UwsFoundState): Whether the Chrome Cleaner process should -// find UwS on the system and if so whether reboot is required. -// - crash_point (CrashPoint): a single crash point where the Chrome Cleaner -// process will crash. See the MockChromeCleanerProcess documentation for -// possible values. -// - prompt_acceptance_to_send (PromptAcceptance): the prompt acceptance value -// that Chrome should send to the Chrome Cleaner process. Must be DENIED -// if |found_uws| is false. class ChromeCleanerRunnerTest - : public testing::TestWithParam< - std::tuple<UwsFoundState, - MockChromeCleanerProcess::ItemsReporting, - MockChromeCleanerProcess::ItemsReporting, - MockChromeCleanerProcess::CrashPoint, - PromptAcceptance>>, + : public testing::TestWithParam<ChromeCleanerRunnerTestParams>, public ChromeCleanerRunnerTestDelegate { public: ChromeCleanerRunnerTest() @@ -274,26 +263,31 @@ testing_profile_ = profile_manager_.CreateTestingProfile("Profile 1"); MockChromeCleanerProcess::AddMockExtensionsToProfile(testing_profile_); - UwsFoundState uws_found_state; + UwsFoundStatus uws_found_state; MockChromeCleanerProcess::ItemsReporting registry_keys_reporting; MockChromeCleanerProcess::ItemsReporting extensions_reporting; MockChromeCleanerProcess::CrashPoint crash_point; - PromptAcceptance prompt_acceptance_to_send; - std::tie(uws_found_state, registry_keys_reporting, extensions_reporting, - crash_point, prompt_acceptance_to_send) = GetParam(); + std::tie(uws_found_state, extension_cleaning_feature_status_, + registry_keys_reporting, extensions_reporting, crash_point, + prompt_acceptance_to_send_) = GetParam(); - ASSERT_FALSE(uws_found_state == UwsFoundState::kNoUwsFound && - prompt_acceptance_to_send != PromptAcceptance::DENIED); + ASSERT_FALSE(uws_found_state == UwsFoundStatus::kNoUwsFound && + prompt_acceptance_to_send_ != PromptAcceptance::DENIED); + + if (extension_cleaning_feature_status_ == + ExtensionCleaningFeatureStatus::kEnabled) + features_.InitAndEnableFeature(kChromeCleanupExtensionsFeature); + else + features_.InitAndDisableFeature(kChromeCleanupExtensionsFeature); cleaner_process_options_.SetReportedResults( - uws_found_state != UwsFoundState::kNoUwsFound, registry_keys_reporting, + uws_found_state != UwsFoundStatus::kNoUwsFound, registry_keys_reporting, extensions_reporting); cleaner_process_options_.set_reboot_required( - uws_found_state == UwsFoundState::kUwsFoundRebootRequired); + uws_found_state == UwsFoundStatus::kUwsFoundRebootRequired); cleaner_process_options_.set_crash_point(crash_point); cleaner_process_options_.set_expected_user_response( - prompt_acceptance_to_send); - prompt_acceptance_to_send_ = prompt_acceptance_to_send; + prompt_acceptance_to_send_); SetChromeCleanerRunnerTestDelegateForTesting(this); } @@ -376,6 +370,7 @@ MockChromeCleanerProcess::Options cleaner_process_options_; PromptAcceptance prompt_acceptance_to_send_ = PromptAcceptance::UNSPECIFIED; + ExtensionCleaningFeatureStatus extension_cleaning_feature_status_; // Set by OnProcessDone(). ChromeCleanerRunner::ProcessStatus process_status_; @@ -386,6 +381,8 @@ bool on_prompt_user_called_ = false; bool on_connection_closed_called_ = false; bool on_process_done_called_ = false; + + base::test::ScopedFeatureList features_; }; MULTIPROCESS_TEST_MAIN(MockChromeCleanerProcessMain) { @@ -409,8 +406,7 @@ return mock_cleaner_process.Run(); } -// Fails for official builds. http://crbug.com/907443 -TEST_P(ChromeCleanerRunnerTest, DISABLED_WithMockCleanerProcess) { +TEST_P(ChromeCleanerRunnerTest, WithMockCleanerProcess) { CallRunChromeCleaner(); run_loop_.Run(); @@ -439,7 +435,9 @@ std::set<base::string16> extension_names; received_scanner_results_.FetchExtensionNames(testing_profile_, &extension_names); - if (cleaner_process_options_.extension_ids()) { + if (cleaner_process_options_.extension_ids() && + extension_cleaning_feature_status_ == + ExtensionCleaningFeatureStatus::kEnabled) { EXPECT_THAT(extension_names, UnorderedElementsAreArray( *cleaner_process_options_.expected_extension_names())); @@ -456,10 +454,12 @@ } INSTANTIATE_TEST_CASE_P( - All, + NoUwsFound, ChromeCleanerRunnerTest, Combine( - Values(UwsFoundState::kNoUwsFound), + Values(UwsFoundStatus::kNoUwsFound), + // When no UwS is found we don't care about extension removel. + Values(ExtensionCleaningFeatureStatus::kDisabled), Values(MockChromeCleanerProcess::ItemsReporting::kUnsupported, MockChromeCleanerProcess::ItemsReporting::kNotReported, MockChromeCleanerProcess::ItemsReporting::kReported), @@ -471,14 +471,17 @@ MockChromeCleanerProcess::CrashPoint::kAfterConnection, MockChromeCleanerProcess::CrashPoint::kAfterRequestSent, MockChromeCleanerProcess::CrashPoint::kAfterResponseReceived), - Values(PromptAcceptance::DENIED))); + Values(PromptAcceptance::DENIED)), + chrome_cleaner::GetParamNameForTest()); INSTANTIATE_TEST_CASE_P( UwsFound, ChromeCleanerRunnerTest, Combine( - Values(UwsFoundState::kUwsFoundRebootRequired, - UwsFoundState::kUwsFoundNoRebootRequired), + Values(UwsFoundStatus::kUwsFoundRebootRequired, + UwsFoundStatus::kUwsFoundNoRebootRequired), + Values(ExtensionCleaningFeatureStatus::kEnabled, + ExtensionCleaningFeatureStatus::kDisabled), Values(MockChromeCleanerProcess::ItemsReporting::kUnsupported, MockChromeCleanerProcess::ItemsReporting::kNotReported, MockChromeCleanerProcess::ItemsReporting::kReported), @@ -492,7 +495,8 @@ MockChromeCleanerProcess::CrashPoint::kAfterResponseReceived), Values(PromptAcceptance::DENIED, PromptAcceptance::ACCEPTED_WITH_LOGS, - PromptAcceptance::ACCEPTED_WITHOUT_LOGS))); + PromptAcceptance::ACCEPTED_WITHOUT_LOGS)), + chrome_cleaner::GetParamNameForTest()); } // namespace } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.cc index 2b9a0b7..af403fa 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.cc
@@ -39,6 +39,11 @@ using ::chrome_cleaner::mojom::ChromePromptPtr; using ::chrome_cleaner::mojom::ChromePromptPtrInfo; using ::chrome_cleaner::mojom::PromptAcceptance; +using CrashPoint = MockChromeCleanerProcess::CrashPoint; +using ExtensionCleaningFeatureStatus = + MockChromeCleanerProcess::ExtensionCleaningFeatureStatus; +using ItemsReporting = MockChromeCleanerProcess::ItemsReporting; +using UwsFoundStatus = MockChromeCleanerProcess::UwsFoundStatus; constexpr char kCrashPointSwitch[] = "mock-crash-point"; constexpr char kUwsFoundSwitch[] = "mock-uws-found"; @@ -420,4 +425,63 @@ std::move(quit_closure).Run(); } +std::ostream& operator<<(std::ostream& out, CrashPoint crash_point) { + switch (crash_point) { + case CrashPoint::kNone: + return out << "NoCrash"; + case CrashPoint::kOnStartup: + return out << "CrashOnStartup"; + case CrashPoint::kAfterConnection: + return out << "CrashAfterConnection"; + case CrashPoint::kAfterRequestSent: + return out << "CrashAfterRequestSent"; + case CrashPoint::kAfterResponseReceived: + return out << "CrashAfterResponseReceived"; + default: + NOTREACHED(); + return out << "UnknownCrashPoint"; + } +} + +std::ostream& operator<<(std::ostream& out, UwsFoundStatus status) { + switch (status) { + case UwsFoundStatus::kNoUwsFound: + return out << "NoUwsFound"; + case UwsFoundStatus::kUwsFoundRebootRequired: + return out << "UwsFoundRebootRequired"; + case UwsFoundStatus::kUwsFoundNoRebootRequired: + return out << "UwsFoundNoRebootRequired"; + default: + NOTREACHED(); + return out << "UnknownFoundStatus"; + } +} + +std::ostream& operator<<(std::ostream& out, + ExtensionCleaningFeatureStatus status) { + switch (status) { + case ExtensionCleaningFeatureStatus::kEnabled: + return out << "ExtensionCleaningEnabled"; + case ExtensionCleaningFeatureStatus::kDisabled: + return out << "ExtensionCleaningDisabled"; + default: + NOTREACHED(); + return out << "UnknownExtensionCleaningStatus"; + } +} + +std::ostream& operator<<(std::ostream& out, ItemsReporting items_reporting) { + switch (items_reporting) { + case ItemsReporting::kUnsupported: + return out << "kUnsupported"; + case ItemsReporting::kNotReported: + return out << "kNotReported"; + case ItemsReporting::kReported: + return out << "kReported"; + default: + NOTREACHED(); + return out << "UnknownItemsReporting"; + } +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.h b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.h index 509438a5..3b82927 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.h +++ b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.h
@@ -59,6 +59,17 @@ kNumItemsReporting, }; + enum class UwsFoundStatus { + kNoUwsFound, + kUwsFoundRebootRequired, + kUwsFoundNoRebootRequired, + }; + + enum class ExtensionCleaningFeatureStatus { + kEnabled, + kDisabled, + }; + static constexpr int kInternalTestFailureExitCode = 100001; static constexpr int kDeliberateCrashExitCode = 100002; static constexpr int kNothingFoundExitCode = 2; @@ -174,6 +185,22 @@ chrome_cleaner::mojom::ChromePromptPtr* chrome_prompt_ptr_ = nullptr; }; +// Making test parameter types printable. + +std::ostream& operator<<(std::ostream& out, + MockChromeCleanerProcess::CrashPoint crash_point); + +std::ostream& operator<<(std::ostream& out, + MockChromeCleanerProcess::UwsFoundStatus status); + +std::ostream& operator<<( + std::ostream& out, + MockChromeCleanerProcess::ExtensionCleaningFeatureStatus status); + +std::ostream& operator<<( + std::ostream& out, + MockChromeCleanerProcess::ItemsReporting items_reporting); + } // namespace safe_browsing #endif // CHROME_BROWSER_SAFE_BROWSING_CHROME_CLEANER_MOCK_CHROME_CLEANER_PROCESS_WIN_H_
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc index 56199a15..933dfac 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -117,7 +117,7 @@ // Given a |web_contents|, returns the navigation id of its last committed // navigation. -int64_t GetLastCommittedNavigationID(const content::WebContents* web_contents) { +int64_t GetLastCommittedNavigationID(content::WebContents* web_contents) { if (!web_contents) return 0; content::NavigationEntry* navigation = @@ -546,7 +546,7 @@ safe_browsing::TriggerType::GAIA_PASSWORD_REUSE, web_contents, resource, url_loader_factory, /*history_service=*/nullptr, TriggerManager::GetSBErrorDisplayOptions(*profile_->GetPrefs(), - *web_contents)); + web_contents)); } void ChromePasswordProtectionService::MaybeFinishCollectingThreatDetails( @@ -563,7 +563,7 @@ safe_browsing::TriggerType::GAIA_PASSWORD_REUSE, web_contents, base::TimeDelta::FromMilliseconds(0), did_proceed, /*num_visit=*/0, TriggerManager::GetSBErrorDisplayOptions(*profile_->GetPrefs(), - *web_contents)); + web_contents)); } PrefService* ChromePasswordProtectionService::GetPrefs() {
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection/download_protection_service.cc index 424ff8a..9535a63 100644 --- a/chrome/browser/safe_browsing/download_protection/download_protection_service.cc +++ b/chrome/browser/safe_browsing/download_protection/download_protection_service.cc
@@ -183,7 +183,7 @@ download::DownloadItem* item, const CheckDownloadCallback& callback) { DCHECK(!item->GetUrlChain().empty()); - const content::WebContents* web_contents = + content::WebContents* web_contents = content::DownloadItemUtils::GetWebContents(item); // |web_contents| can be null in tests. // Checks if this download is whitelisted by enterprise policy.
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc index c25cab16..2fbcf07 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -202,7 +202,7 @@ } void MaybeReportSafeBrowsingHit(const HitReport& hit_report, - const WebContents* web_contents) override { + WebContents* web_contents) override { if (SafeBrowsingUIManager::ShouldSendHitReport(hit_report, web_contents)) { hit_report_sent_ = true; }
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc index a44e796a..be573ea 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -290,9 +290,8 @@ class FakeSafeBrowsingUIManager : public TestSafeBrowsingUIManager { public: - void MaybeReportSafeBrowsingHit( - const safe_browsing::HitReport& hit_report, - const content::WebContents* web_contents) override { + void MaybeReportSafeBrowsingHit(const safe_browsing::HitReport& hit_report, + content::WebContents* web_contents) override { EXPECT_FALSE(got_hit_report_); got_hit_report_ = true; hit_report_ = hit_report;
diff --git a/chrome/browser/safe_browsing/trigger_creator.cc b/chrome/browser/safe_browsing/trigger_creator.cc index 9a11840..94765c2 100644 --- a/chrome/browser/safe_browsing/trigger_creator.cc +++ b/chrome/browser/safe_browsing/trigger_creator.cc
@@ -46,7 +46,7 @@ // running on old tabs, but that's acceptable. The trigger will be started for // new tabs. SBErrorOptions options = TriggerManager::GetSBErrorDisplayOptions( - *profile->GetPrefs(), *web_contents); + *profile->GetPrefs(), web_contents); scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory = content::BrowserContext::GetDefaultStoragePartition(profile) ->GetURLLoaderFactoryForBrowserProcess();
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc index 7c3ab4e..606bd95 100644 --- a/chrome/browser/safe_browsing/ui_manager.cc +++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -105,9 +105,8 @@ } // static -bool SafeBrowsingUIManager::ShouldSendHitReport( - const HitReport& hit_report, - const WebContents* web_contents) { +bool SafeBrowsingUIManager::ShouldSendHitReport(const HitReport& hit_report, + WebContents* web_contents) { return web_contents && hit_report.extended_reporting_level != SBER_LEVEL_OFF && !web_contents->GetBrowserContext()->IsOffTheRecord(); @@ -118,7 +117,7 @@ // extended-reporting users. void SafeBrowsingUIManager::MaybeReportSafeBrowsingHit( const HitReport& hit_report, - const WebContents* web_contents) { + WebContents* web_contents) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // Send report if user opted-in to extended reporting and is not in
diff --git a/chrome/browser/safe_browsing/ui_manager.h b/chrome/browser/safe_browsing/ui_manager.h index 4287c044..073567a 100644 --- a/chrome/browser/safe_browsing/ui_manager.h +++ b/chrome/browser/safe_browsing/ui_manager.h
@@ -75,9 +75,8 @@ // Report hits to unsafe contents (malware, phishing, unsafe download URL) // to the server. Can only be called on UI thread. The hit report will // only be sent if the user has enabled SBER and is not in incognito mode. - void MaybeReportSafeBrowsingHit( - const safe_browsing::HitReport& hit_report, - const content::WebContents* web_contents) override; + void MaybeReportSafeBrowsingHit(const safe_browsing::HitReport& hit_report, + content::WebContents* web_contents) override; // Creates the whitelist URL set for tests that create a blocking page // themselves and then simulate OnBlockingPageDone(). OnBlockingPageDone() @@ -108,7 +107,7 @@ // Helper method to ensure hit reports are only sent when the user has // opted in to extended reporting and is not currently in incognito mode. static bool ShouldSendHitReport(const HitReport& hit_report, - const content::WebContents* web_contents); + content::WebContents* web_contents); private: friend class SafeBrowsingUIManagerTest;
diff --git a/chrome/browser/search/iframe_source.cc b/chrome/browser/search/iframe_source.cc index e8e9bba9..a772485 100644 --- a/chrome/browser/search/iframe_source.cc +++ b/chrome/browser/search/iframe_source.cc
@@ -57,7 +57,7 @@ std::string* origin) const { if (wc_getter.is_null()) return false; - const content::WebContents* contents = wc_getter.Run(); + content::WebContents* contents = wc_getter.Run(); if (!contents) return false; const content::NavigationEntry* entry =
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc index 6b0b967..c5730d8 100644 --- a/chrome/browser/search/search.cc +++ b/chrome/browser/search/search.cc
@@ -219,7 +219,7 @@ const NewTabURLState state; }; -bool IsRenderedInInstantProcess(const content::WebContents* contents, +bool IsRenderedInInstantProcess(content::WebContents* contents, Profile* profile) { #if defined(OS_ANDROID) return false; @@ -270,7 +270,7 @@ url == chrome::kChromeSearchLocalNtpUrl); } -bool IsInstantNTP(const content::WebContents* contents) { +bool IsInstantNTP(content::WebContents* contents) { if (!contents) return false; @@ -284,7 +284,7 @@ return NavEntryIsInstantNTP(contents, entry); } -bool NavEntryIsInstantNTP(const content::WebContents* contents, +bool NavEntryIsInstantNTP(content::WebContents* contents, const content::NavigationEntry* entry) { if (!contents || !entry || !IsInstantExtendedAPIEnabled()) return false;
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h index 04ed373..0bca746 100644 --- a/chrome/browser/search/search.h +++ b/chrome/browser/search/search.h
@@ -39,11 +39,11 @@ // Returns true if the active navigation entry of |contents| is a New Tab page // rendered in an Instant process. This is the last committed entry if it // exists, and otherwise the visible entry. -bool IsInstantNTP(const content::WebContents* contents); +bool IsInstantNTP(content::WebContents* contents); // Same as IsInstantNTP but uses |nav_entry| to determine the URL for the page // instead of using the visible entry. -bool NavEntryIsInstantNTP(const content::WebContents* contents, +bool NavEntryIsInstantNTP(content::WebContents* contents, const content::NavigationEntry* nav_entry); // Returns true if |url| corresponds to a New Tab page that would get rendered
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc index 3fb4b3ca..eb6be50 100644 --- a/chrome/browser/search/search_unittest.cc +++ b/chrome/browser/search/search_unittest.cc
@@ -89,7 +89,7 @@ template_url_service->SetUserSelectedDefaultSearchProvider(template_url); } - bool InInstantProcess(const content::WebContents* contents) { + bool InInstantProcess(content::WebContents* contents) { InstantService* instant_service = InstantServiceFactory::GetForProfile(profile()); return instant_service->IsInstantProcess( @@ -181,7 +181,7 @@ for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) { const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i]; AddTab(browser(), GURL("chrome://blank")); - const content::WebContents* contents = + content::WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); // Navigate to start URL. @@ -278,7 +278,7 @@ AddTab(browser(), GURL("chrome://blank")); for (const SearchTestCase& test : kInstantNTPTestCases) { NavigateAndCommitActiveTab(GURL(test.url)); - const content::WebContents* contents = + content::WebContents* contents = browser()->tab_strip_model()->GetWebContentsAt(0); EXPECT_EQ(test.expected_result, IsInstantNTP(contents)) << test.url << " " << test.comment;
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index cc4bc001..4cd122a1 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc
@@ -81,7 +81,7 @@ bool HasSingleNewTabPage(Browser* browser) { if (browser->tab_strip_model()->count() != 1) return false; - const content::WebContents* active_tab = + content::WebContents* active_tab = browser->tab_strip_model()->GetWebContentsAt(0); return active_tab->GetURL() == chrome::kChromeUINewTabURL || search::IsInstantNTP(active_tab);
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index 9fb41d85..1408ff4c 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -608,7 +608,7 @@ // Make sure that the restored tab was restored with the correct // timestamp and status code. - const content::WebContents* contents = + content::WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); ASSERT_TRUE(contents); const content::NavigationEntry* entry =
diff --git a/chrome/browser/ssl/cert_verifier_browser_test.cc b/chrome/browser/ssl/cert_verifier_browser_test.cc index b47891c..be8e279 100644 --- a/chrome/browser/ssl/cert_verifier_browser_test.cc +++ b/chrome/browser/ssl/cert_verifier_browser_test.cc
@@ -11,11 +11,13 @@ ChromeMockCertVerifier::~ChromeMockCertVerifier() = default; void ChromeMockCertVerifier::SetUpInProcessBrowserTestFixture() { + ContentMockCertVerifier::SetUpInProcessBrowserTestFixture(); IOThread::SetCertVerifierForTesting(mock_cert_verifier_internal()); ProfileIOData::SetCertVerifierForTesting(mock_cert_verifier_internal()); } void ChromeMockCertVerifier::TearDownInProcessBrowserTestFixture() { + ContentMockCertVerifier::TearDownInProcessBrowserTestFixture(); IOThread::SetCertVerifierForTesting(nullptr); ProfileIOData::SetCertVerifierForTesting(nullptr); }
diff --git a/chrome/browser/translate/chrome_translate_client.cc b/chrome/browser/translate/chrome_translate_client.cc index 48e40f54..2ceec889 100644 --- a/chrome/browser/translate/chrome_translate_client.cc +++ b/chrome/browser/translate/chrome_translate_client.cc
@@ -82,7 +82,7 @@ // ========== LOG TRANSLATE EVENT ============== -void LogTranslateEvent(const content::WebContents* const web_contents, +void LogTranslateEvent(content::WebContents* const web_contents, const metrics::TranslateEventProto& translate_event) { if (!FeatureList::IsEnabled(switches::kSyncUserTranslationEvents)) return;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index fcd74aad..8e91c8a 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1336,6 +1336,8 @@ "ash/chrome_screenshot_grabber_test_observer.h", "ash/chrome_shell_delegate.cc", "ash/chrome_shell_delegate.h", + "ash/contained_shell_client.cc", + "ash/contained_shell_client.h", "ash/ime_controller_client.cc", "ash/ime_controller_client.h", "ash/ksv/keyboard_shortcut_viewer_util.cc",
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc index 2ff497b..c7fdf59 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -1325,7 +1325,9 @@ } std::unordered_set<std::string> apps_to_remove = - GetAppsForPackage(package_name); + GetAppsAndShortcutsForPackage(package_name, + true, /* include_only_launchable_apps */ + false /* include_shortcuts */); for (const auto& app : apps) { const std::string app_id = GetAppId(app->package_name, app->activity); @@ -1386,11 +1388,13 @@ std::unordered_set<std::string> ArcAppListPrefs::GetAppsForPackage( const std::string& package_name) const { return GetAppsAndShortcutsForPackage(package_name, + false, /* include_only_launchable_apps */ false /* include_shortcuts */); } std::unordered_set<std::string> ArcAppListPrefs::GetAppsAndShortcutsForPackage( const std::string& package_name, + bool include_only_launchable_apps, bool include_shortcuts) const { std::unordered_set<std::string> app_set; const base::DictionaryValue* apps = @@ -1422,6 +1426,13 @@ continue; } + if (include_only_launchable_apps) { + // Filter out non-lauchable apps. + bool launchable = false; + if (!app->GetBoolean(kLaunchable, &launchable) || !launchable) + continue; + } + app_set.insert(app_it.key()); } @@ -1431,7 +1442,9 @@ void ArcAppListPrefs::HandlePackageRemoved(const std::string& package_name) { DCHECK(IsArcAndroidEnabledForProfile(profile_)); const std::unordered_set<std::string> apps_to_remove = - GetAppsAndShortcutsForPackage(package_name, true /* include_shortcuts */); + GetAppsAndShortcutsForPackage(package_name, + false /* include_only_launchable_apps */, + true /* include_shortcuts */); for (const auto& app_id : apps_to_remove) RemoveApp(app_id);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h index f52a4b3..0c74d78 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -394,8 +394,13 @@ void DisableAllApps(); void RemoveAllAppsAndPackages(); std::vector<std::string> GetAppIdsNoArcEnabledCheck() const; + // Retrieves registered apps and shortcuts for specific package |package_name| + // If |include_only_launchable_apps| is set to true then only launchable apps + // are included and runtime apps are ignored. Otherwise all apps are returned. + // |include_shortcuts| specifies if shorcuts needs to be included. std::unordered_set<std::string> GetAppsAndShortcutsForPackage( const std::string& package_name, + bool include_only_launchable_apps, bool include_shortcuts) const; // Enumerates apps from preferences and notifies listeners about available
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc index f9738a6f..a2110813 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -186,6 +186,20 @@ } } +ArcAppListPrefs::AppInfo GetAppInfoExpectation(const arc::mojom::AppInfo& app, + bool launchable) { + return ArcAppListPrefs::AppInfo( + app.name, app.package_name, app.activity, std::string() /* intent_uri */, + std::string() /* icon_resource_id */, base::Time() /* last_launch_time */, + base::Time() /* install_time */, app.sticky, app.notifications_enabled, + true /* ready */, false /* suspended */, launchable /* show_in_launcher*/, + false /* shortcut */, launchable); +} + +MATCHER_P(ArcPackageInfoIs, package, "") { + return arg.Equals(package); +} + } // namespace class ArcAppModelBuilderTest : public extensions::ExtensionServiceTestBase, @@ -1235,12 +1249,8 @@ const std::string app_id = ArcAppTest::GetAppId(app); ArcAppListPrefs::AppInfo::SetIgnoreCompareInstallTimeForTesting(true); - const ArcAppListPrefs::AppInfo expected_app_info_registered( - app.name, app.package_name, app.activity, std::string() /* intent_uri */, - std::string() /* icon_resource_id */, base::Time() /* last_launch_time */, - base::Time() /* install_time */, app.sticky, app.notifications_enabled, - true /* ready */, false /* suspended */, true /* show_in_launcher*/, - false /* shortcut */, true /* launchable */); + const ArcAppListPrefs::AppInfo expected_app_info_registered = + GetAppInfoExpectation(app, true /* launchable */); ArcAppListPrefs::AppInfo expected_app_info_disabled( expected_app_info_registered); @@ -2146,6 +2156,76 @@ std::vector<arc::mojom::ShortcutInfo>()); } +// This validates that runtime apps are not removed on package change event. +TEST_P(ArcAppModelBuilderTest, DontRemoveRuntimeAppOnPackageChange) { + ArcAppListPrefs::AppInfo::SetIgnoreCompareInstallTimeForTesting(true); + ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get()); + ASSERT_TRUE(prefs); + + arc::MockArcAppListPrefsObserver observer; + + ASSERT_GE(fake_apps().size(), 2U); + + // Second app should be preserved after the package update. + std::vector<arc::mojom::AppInfo> apps(fake_apps().begin(), + fake_apps().begin() + 2); + apps[0].package_name = apps[1].package_name; + + const std::string app_id1 = ArcAppTest::GetAppId(apps[0]); + const std::string app_id2 = ArcAppTest::GetAppId(apps[1]); + + arc::mojom::ArcPackageInfoPtr package = CreatePackage(apps[0].package_name); + + prefs->AddObserver(&observer); + + EXPECT_CALL(observer, OnPackageInstalled(ArcPackageInfoIs(*package))) + .Times(1); + EXPECT_CALL(observer, + OnAppRegistered(app_id1, GetAppInfoExpectation( + apps[0], true /* launchable */))) + .Times(1); + EXPECT_CALL(observer, + OnAppRegistered(app_id2, GetAppInfoExpectation( + apps[1], true /* launchable */))) + .Times(1); + + AddPackage(package); + + app_instance()->RefreshAppList(); + app_instance()->SendRefreshAppList(apps); + + // Send a task for non-existing lauchable app. That would register new runtime + // app. + arc::mojom::AppInfo app_runtime = apps[0]; + app_runtime.activity += "_runtime"; + // Runtime apps have notifications_enabled and sticky false. + app_runtime.notifications_enabled = false; + app_runtime.sticky = false; + const std::string app_id3 = ArcAppTest::GetAppId(app_runtime); + + EXPECT_CALL(observer, OnAppRegistered( + app_id3, GetAppInfoExpectation( + app_runtime, false /* launchable */))) + .Times(1); + EXPECT_CALL(observer, + OnTaskCreated(1 /* task_id */, app_runtime.package_name, + app_runtime.activity, std::string() /* name */)) + .Times(1); + + app_instance()->SendTaskCreated(1, app_runtime, std::string()); + + // Simulate package update when first launchable app is removed. This should + // trigger app removing for it but not for the runtime app. + EXPECT_CALL(observer, OnAppRemoved(app_id1)).Times(1); + EXPECT_CALL(observer, OnAppRemoved(app_id2)).Times(0); + EXPECT_CALL(observer, OnAppRemoved(app_id3)).Times(0); + + apps.erase(apps.begin()); + app_instance()->SendPackageAppListRefreshed(apps[0].package_name, apps); + + prefs->RemoveObserver(&observer); +} + TEST_P(ArcDefaulAppTest, DefaultApps) { ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get()); ASSERT_NE(nullptr, prefs);
diff --git a/chrome/browser/ui/ash/assistant/assistant_context_util.cc b/chrome/browser/ui/ash/assistant/assistant_context_util.cc index 2d34ddec..89e2caed 100644 --- a/chrome/browser/ui/ash/assistant/assistant_context_util.cc +++ b/chrome/browser/ui/ash/assistant/assistant_context_util.cc
@@ -33,7 +33,7 @@ } ax::mojom::AssistantExtraPtr CreateAssistantExtra( - const content::WebContents* web_contents, + content::WebContents* web_contents, const gfx::Rect& bounds_pixel) { auto assistant_extra = ax::mojom::AssistantExtra::New(); assistant_extra->url = web_contents->GetLastCommittedURL();
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index b4f8f6e..d1b8b57 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -30,6 +30,7 @@ #include "chrome/browser/ui/ash/ash_shell_init.h" #include "chrome/browser/ui/ash/cast_config_client_media_router.h" #include "chrome/browser/ui/ash/chrome_new_window_client.h" +#include "chrome/browser/ui/ash/contained_shell_client.h" #include "chrome/browser/ui/ash/ime_controller_client.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/ash/login_screen_client.h" @@ -283,6 +284,9 @@ // Initialize TabScrubber after the Ash Shell has been initialized. TabScrubber::GetInstance(); } + + if (base::FeatureList::IsEnabled(ash::features::kContainedShell)) + contained_shell_client_ = std::make_unique<ContainedShellClient>(); } void ChromeBrowserMainExtraPartsAsh::PostBrowserStart() { @@ -316,6 +320,7 @@ media_client_.reset(); login_screen_client_.reset(); cast_config_client_media_router_.reset(); + contained_shell_client_.reset(); // Initialized in PreProfileInit: system_tray_client_.reset();
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h index 2ff85ee..1b2510f6 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
@@ -36,6 +36,7 @@ class AshShellInit; class CastConfigClientMediaRouter; class ChromeNewWindowClient; +class ContainedShellClient; class DataPromoNotification; class ImeControllerClient; class ImmersiveContextMus; @@ -118,6 +119,7 @@ // Initialized in PostProfileInit in all configs: std::unique_ptr<CastConfigClientMediaRouter> cast_config_client_media_router_; + std::unique_ptr<ContainedShellClient> contained_shell_client_; std::unique_ptr<LoginScreenClient> login_screen_client_; std::unique_ptr<MediaClient> media_client_; std::unique_ptr<policy::DisplaySettingsHandler> display_settings_handler_;
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc index 27d074c5..b0db9e2 100644 --- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc +++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -335,7 +335,7 @@ scoped_refptr<base::RefCountedMemory> png_data, ScreenshotFileResult result, const base::FilePath& local_path) { - DCHECK(!base::MessageLoopForUI::IsCurrent()); + DCHECK(!base::MessageLoopCurrentForUI::IsSet()); DCHECK(!screenshot_path.empty()); ScreenshotResult screenshot_result = ScreenshotResult::SUCCESS; @@ -369,7 +369,7 @@ void EnsureLocalDirectoryExists( const base::FilePath& path, ChromeScreenshotGrabber::FileCallback callback) { - DCHECK(!base::MessageLoopForUI::IsCurrent()); + DCHECK(!base::MessageLoopCurrentForUI::IsSet()); DCHECK(!path.empty()); if (!base::CreateDirectory(path.DirName())) {
diff --git a/chrome/browser/ui/ash/contained_shell_client.cc b/chrome/browser/ui/ash/contained_shell_client.cc new file mode 100644 index 0000000..92e3473d --- /dev/null +++ b/chrome/browser/ui/ash/contained_shell_client.cc
@@ -0,0 +1,25 @@ +// 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/ui/ash/contained_shell_client.h" + +#include <utility> + +#include "ash/public/interfaces/constants.mojom.h" +#include "content/public/common/service_manager_connection.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "services/service_manager/public/cpp/connector.h" + +ContainedShellClient::ContainedShellClient() { + ash::mojom::ContainedShellControllerPtr contained_shell_controller; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &contained_shell_controller); + + ash::mojom::ContainedShellClientPtr client; + binding_.Bind(mojo::MakeRequest(&client)); + contained_shell_controller->SetClient(std::move(client)); +} + +ContainedShellClient::~ContainedShellClient() = default;
diff --git a/chrome/browser/ui/ash/contained_shell_client.h b/chrome/browser/ui/ash/contained_shell_client.h new file mode 100644 index 0000000..d21d124 --- /dev/null +++ b/chrome/browser/ui/ash/contained_shell_client.h
@@ -0,0 +1,23 @@ +// 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 CHROME_BROWSER_UI_ASH_CONTAINED_SHELL_CLIENT_H_ +#define CHROME_BROWSER_UI_ASH_CONTAINED_SHELL_CLIENT_H_ + +#include "ash/public/interfaces/contained_shell.mojom.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" + +class ContainedShellClient : public ash::mojom::ContainedShellClient { + public: + ContainedShellClient(); + ~ContainedShellClient() override; + + private: + mojo::Binding<ash::mojom::ContainedShellClient> binding_{this}; + + DISALLOW_COPY_AND_ASSIGN(ContainedShellClient); +}; + +#endif // CHROME_BROWSER_UI_ASH_CONTAINED_SHELL_CLIENT_H_
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc index b52414d8..9a34d36 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -1070,7 +1070,7 @@ } bool ChromeLauncherController::IsIncognito( - const content::WebContents* web_contents) const { + content::WebContents* web_contents) const { const Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); return profile->IsOffTheRecord() && !profile->IsGuestSession() &&
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h index 736d2fc..1d6b09f 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -321,7 +321,7 @@ void CreateBrowserShortcutLauncherItem(); // Check if the given |web_contents| is in incognito mode. - bool IsIncognito(const content::WebContents* web_contents) const; + bool IsIncognito(content::WebContents* web_contents) const; // Finds the index of where to insert the next item. int FindInsertionPoint();
diff --git a/chrome/browser/ui/ash/media_client.cc b/chrome/browser/ui/ash/media_client.cc index a4d68ae..db2788a 100644 --- a/chrome/browser/ui/ash/media_client.cc +++ b/chrome/browser/ui/ash/media_client.cc
@@ -226,7 +226,7 @@ int render_frame_id, content::MediaStreamType stream_type, const content::MediaRequestState state) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); // The PostTask is necessary because the state of MediaStreamCaptureIndicator // gets updated after this. base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/ui/ash/tablet_mode_page_behavior_browsertest.cc b/chrome/browser/ui/ash/tablet_mode_page_behavior_browsertest.cc index c7ffcfb..bc7e4456 100644 --- a/chrome/browser/ui/ash/tablet_mode_page_behavior_browsertest.cc +++ b/chrome/browser/ui/ash/tablet_mode_page_behavior_browsertest.cc
@@ -53,11 +53,11 @@ } content::WebPreferences GetWebKitPreferences( - const content::WebContents* web_contents) const { + content::WebContents* web_contents) const { return web_contents->GetRenderViewHost()->GetWebkitPreferences(); } - void ValidateWebPrefs(const content::WebContents* web_contents, + void ValidateWebPrefs(content::WebContents* web_contents, bool tablet_mode_enabled) const { const content::WebPreferences web_prefs = GetWebKitPreferences(web_contents);
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.cc b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.cc index cc760f1..bd09cc0 100644 --- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.cc +++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.cc
@@ -180,7 +180,7 @@ } bool SafeBrowsingTriggeredPopupBlocker::IsEnabled( - const content::WebContents* web_contents) { + content::WebContents* web_contents) { // If feature is disabled, return false. This is done so that if the feature // is broken it can be disabled irrespective of the policy. if (!base::FeatureList::IsEnabled(kAbusiveExperienceEnforce))
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h index cd289e9..3d3ec5eb 100644 --- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h +++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h
@@ -97,7 +97,7 @@ // Enabled state is governed by both a feature flag and a pref (which can be // controlled by enterprise policy). - static bool IsEnabled(const content::WebContents* web_contents); + static bool IsEnabled(content::WebContents* web_contents); // Data scoped to a single page. Will be reset at navigation commit. class PageData {
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 9d52c42..2cb2def 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1616,7 +1616,7 @@ namespace { -int GetZoomPercent(const content::WebContents* contents, +int GetZoomPercent(content::WebContents* contents, bool* enable_plus, bool* enable_minus) { int percent =
diff --git a/chrome/browser/ui/browser_tabrestore_browsertest.cc b/chrome/browser/ui/browser_tabrestore_browsertest.cc index 2a72fa14..d5c2064 100644 --- a/chrome/browser/ui/browser_tabrestore_browsertest.cc +++ b/chrome/browser/ui/browser_tabrestore_browsertest.cc
@@ -89,7 +89,7 @@ // Thus we should wait for "load stop" event before we will perform // CheckVisbility on "about:blank". { - const content::WebContents* about_blank_contents = + content::WebContents* about_blank_contents = browser->tab_strip_model()->GetWebContentsAt(0); EXPECT_EQ("about:blank", about_blank_contents->GetURL().spec()); if (about_blank_contents->IsLoading() || @@ -146,7 +146,7 @@ // The same as in RecentTabsMenuTabDisposition test case. // See there for the explanation. { - const content::WebContents* about_blank_contents = + content::WebContents* about_blank_contents = browser->tab_strip_model()->GetWebContentsAt(0); EXPECT_EQ("about:blank", about_blank_contents->GetURL().spec()); if (about_blank_contents->IsLoading() ||
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index 209fa583..6548c59 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -271,7 +271,7 @@ return false; if (scheme.empty()) // Any trusted popup window return true; - const content::WebContents* web_contents = + content::WebContents* web_contents = browser->tab_strip_model()->GetWebContentsAt(0); if (!web_contents) return false;
diff --git a/chrome/browser/ui/cocoa/confirm_quit_panel_controller.h b/chrome/browser/ui/cocoa/confirm_quit_panel_controller.h index 34ba656..36d30e97 100644 --- a/chrome/browser/ui/cocoa/confirm_quit_panel_controller.h +++ b/chrome/browser/ui/cocoa/confirm_quit_panel_controller.h
@@ -22,9 +22,8 @@ + (ConfirmQuitPanelController*)sharedController; // Runs a modal loop that brings up the panel and handles the logic for if and -// when to terminate. Returns NSApplicationTerminateReply for use in -// -[NSApplicationDelegate applicationShouldTerminate:]. -- (NSApplicationTerminateReply)runModalLoopForApplication:(NSApplication*)app; +// when to terminate. Returns YES if the quit should continue. +- (BOOL)runModalLoopForApplication:(NSApplication*)app; // Shows the window. - (void)showWindow:(id)sender;
diff --git a/chrome/browser/ui/cocoa/confirm_quit_panel_controller.mm b/chrome/browser/ui/cocoa/confirm_quit_panel_controller.mm index d237f4a..9192773a 100644 --- a/chrome/browser/ui/cocoa/confirm_quit_panel_controller.mm +++ b/chrome/browser/ui/cocoa/confirm_quit_panel_controller.mm
@@ -198,7 +198,7 @@ return self; } -- (NSApplicationTerminateReply)runModalLoopForApplication:(NSApplication*)app { +- (BOOL)runModalLoopForApplication:(NSApplication*)app { base::scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]); // If this is the second of two such attempts to quit within a certain time @@ -227,7 +227,7 @@ confirm_quit::RecordHistogram(confirm_quit::kDoubleTap); else confirm_quit::RecordHistogram(confirm_quit::kTapHold); - return NSTerminateNow; + return YES; } else { [lastQuitAttempt release]; // Harmless if already nil. lastQuitAttempt = [timeNow retain]; // Record this attempt for next time. @@ -277,16 +277,16 @@ // The user held down the combination long enough that quitting should // happen. confirm_quit::RecordHistogram(confirm_quit::kHoldDuration); - return NSTerminateNow; + return YES; } else { // Slowly fade the confirm window out in case the user doesn't // understand what they have to do to quit. [self dismissPanel]; - return NSTerminateCancel; + return NO; } // Default case: terminate. - return NSTerminateNow; + return YES; } - (void)windowWillClose:(NSNotification*)notif {
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc index 9b2f1d15..f6e8831f 100644 --- a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc +++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
@@ -191,7 +191,7 @@ DCHECK(extension->is_hosted_app()); - const content::WebContents* web_contents = + content::WebContents* web_contents = browser_->tab_strip_model()->GetActiveWebContents(); // Don't show a toolbar until a navigation has occurred.
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc index cd5a3458..9ebd1d3 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
@@ -190,6 +190,14 @@ return net::AppendQueryParameter(url, "utm_campaign", campaign); } +bool ShouldManagePasswordsinGooglePasswordManager(Profile* profile) { + return base::FeatureList::IsEnabled( + password_manager::features::kGooglePasswordManager) && + password_manager_util::GetPasswordSyncState( + ProfileSyncServiceFactory::GetForProfile(profile)) == + password_manager::SYNCING_NORMAL_ENCRYPTION; +} + // Navigation is handled differently on Android. #if !defined(OS_ANDROID) void NavigateToGooglePasswordManager(Profile* profile, @@ -202,11 +210,7 @@ void NavigateToManagePasswordsPage(Browser* browser, ManagePasswordsReferrer referrer) { - if (base::FeatureList::IsEnabled( - password_manager::features::kGooglePasswordManager) && - password_manager_util::GetPasswordSyncState( - ProfileSyncServiceFactory::GetForProfile(browser->profile())) == - password_manager::SYNCING_NORMAL_ENCRYPTION) { + if (ShouldManagePasswordsinGooglePasswordManager(browser->profile())) { NavigateToGooglePasswordManager(browser->profile(), referrer); } else { chrome::ShowPasswordManager(browser);
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.h b/chrome/browser/ui/passwords/manage_passwords_view_utils.h index b2ac3b33..2d32a2fd 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.h +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.h
@@ -79,6 +79,13 @@ GURL GetGooglePasswordManagerURL( password_manager::ManagePasswordsReferrer referrer); +// Returns whether users should manage their passwords in the Google Password +// Manager. This includes users that are syncing their passwords without a +// custom passphrase and for which the Google Password Manager experiment is +// activated. For these users links to the Chrome password settings will be +// repaced with links to the Google Password Manager, i.e. passwords.google.com. +bool ShouldManagePasswordsinGooglePasswordManager(Profile* profile); + // Navigates to the Google Password Manager, i.e. passwords.google.com. void NavigateToGooglePasswordManager( Profile* profile,
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc index 634f89d5..76719a82 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc +++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
@@ -9,9 +9,8 @@ #include "content/public/browser/web_contents.h" SearchIPCRouterPolicyImpl::SearchIPCRouterPolicyImpl( - const content::WebContents* web_contents) - : web_contents_(web_contents), - is_incognito_(true) { + content::WebContents* web_contents) + : web_contents_(web_contents), is_incognito_(true) { DCHECK(web_contents); Profile* profile =
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.h b/chrome/browser/ui/search/search_ipc_router_policy_impl.h index ea9bc595..d1ecd9b 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_impl.h +++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.h
@@ -20,7 +20,7 @@ // The SearchIPCRouter::Policy implementation. class SearchIPCRouterPolicyImpl : public SearchIPCRouter::Policy { public: - explicit SearchIPCRouterPolicyImpl(const content::WebContents* web_contents); + explicit SearchIPCRouterPolicyImpl(content::WebContents* web_contents); ~SearchIPCRouterPolicyImpl() override; private: @@ -54,7 +54,7 @@ is_incognito_ = is_incognito; } - const content::WebContents* web_contents_; + content::WebContents* web_contents_; bool is_incognito_; DISALLOW_COPY_AND_ASSIGN(SearchIPCRouterPolicyImpl);
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc b/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc index bb84aca..2738eaf 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc +++ b/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc
@@ -57,7 +57,7 @@ // Now the visible URL corresponds to the download, but the last committed URL // is still the NTP. - const content::WebContents* tab = + content::WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); ASSERT_EQ(GURL("http://foo/download.zip"), tab->GetVisibleURL()); ASSERT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), tab->GetLastCommittedURL());
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc index 2d04367a..27f7033 100644 --- a/chrome/browser/ui/search/search_tab_helper.cc +++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -49,7 +49,7 @@ namespace { -bool IsCacheableNTP(const content::WebContents* contents) { +bool IsCacheableNTP(content::WebContents* contents) { const content::NavigationEntry* entry = contents->GetController().GetLastCommittedEntry(); return search::NavEntryIsInstantNTP(contents, entry) && @@ -58,7 +58,7 @@ // Returns true if |contents| are rendered inside an Instant process. bool InInstantProcess(const InstantService* instant_service, - const content::WebContents* contents) { + content::WebContents* contents) { if (!instant_service || !contents) return false;
diff --git a/chrome/browser/ui/settings_window_manager_chromeos.cc b/chrome/browser/ui/settings_window_manager_chromeos.cc index ce55f02..01da3df 100644 --- a/chrome/browser/ui/settings_window_manager_chromeos.cc +++ b/chrome/browser/ui/settings_window_manager_chromeos.cc
@@ -47,7 +47,7 @@ Browser* browser = FindBrowserForProfile(profile); if (browser) { DCHECK(browser->profile() == profile); - const content::WebContents* web_contents = + content::WebContents* web_contents = browser->tab_strip_model()->GetWebContentsAt(0); if (web_contents && web_contents->GetURL() == gurl) { browser->window()->Show();
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index 6a3cf24..ec106e9 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -1088,14 +1088,7 @@ policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); } -// http://crbug.com/691707 -#if defined(OS_MACOSX) -#define MAYBE_AddFirstRunTab DISABLED_AddFirstRunTab -#else -#define MAYBE_AddFirstRunTab AddFirstRunTab -#endif -IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest, - MAYBE_AddFirstRunTab) { +IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest, AddFirstRunTab) { ASSERT_TRUE(embedded_test_server()->Start()); StartupBrowserCreator browser_creator; browser_creator.AddFirstRunTab( @@ -1230,13 +1223,7 @@ tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName()); } -// http://crbug.com/691707 -#if defined(OS_MACOSX) -#define MAYBE_WelcomePages DISABLED_WelcomePages -#else -#define MAYBE_WelcomePages WelcomePages -#endif -IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest, MAYBE_WelcomePages) { +IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest, WelcomePages) { ASSERT_TRUE(embedded_test_server()->Start()); ProfileManager* profile_manager = g_browser_process->profile_manager(); @@ -1287,14 +1274,8 @@ tab_strip->GetWebContentsAt(0)->GetURL().possibly_invalid_spec()); } -// http://crbug.com/691707 -#if defined(OS_MACOSX) -#define MAYBE_WelcomePagesWithPolicy DISABLED_WelcomePagesWithPolicy -#else -#define MAYBE_WelcomePagesWithPolicy WelcomePagesWithPolicy -#endif IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest, - MAYBE_WelcomePagesWithPolicy) { + WelcomePagesWithPolicy) { ASSERT_TRUE(embedded_test_server()->Start()); // Set the following user policies:
diff --git a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc b/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc index fa65cee..16359c5 100644 --- a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc +++ b/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc
@@ -26,7 +26,7 @@ views::ViewsDelegate::ProcessMenuAcceleratorResult ChromeViewsDelegate::ProcessAcceleratorWhileMenuShowing( const ui::Accelerator& accelerator) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); // Early return because mash chrome does not have access to ash::Shell if (features::IsMultiProcessMash())
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index f7d1fbd..4ba264d 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -394,8 +394,7 @@ bool GlassBrowserFrameView::ShouldTabIconViewAnimate() const { DCHECK(ShowCustomIcon()); - const content::WebContents* current_tab = - browser_view()->GetActiveWebContents(); + content::WebContents* current_tab = browser_view()->GetActiveWebContents(); return current_tab && current_tab->IsLoading(); }
diff --git a/chrome/browser/ui/views/menu_model_adapter_test.cc b/chrome/browser/ui/views/menu_model_adapter_test.cc index 170cb20c..7e52499 100644 --- a/chrome/browser/ui/views/menu_model_adapter_test.cc +++ b/chrome/browser/ui/views/menu_model_adapter_test.cc
@@ -234,7 +234,7 @@ menu_model_adapter_.BuildMenu(menu_); - ASSERT_TRUE(base::MessageLoopForUI::IsCurrent()); + ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, CreateEventTask(this, &MenuModelAdapterTest::Step3)); }
diff --git a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc index f55a790..3a1947b 100644 --- a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc +++ b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
@@ -345,12 +345,7 @@ // Disabled for being flaky. Tracked in: // TODO(erg): Fix DND tests on linux_aura. http://crbug.com/163931. // TODO(tapted): De-flake and run on Mac. http://crbug.com/449058. -#if defined(OS_WIN) -#define MAYBE_TestInMenuDrag TestInMenuDrag -#else -#define MAYBE_TestInMenuDrag DISABLED_TestInMenuDrag -#endif -VIEW_TEST(MenuViewDragAndDropTestTestInMenuDrag, MAYBE_TestInMenuDrag) +VIEW_TEST(MenuViewDragAndDropTestTestInMenuDrag, DISABLED_TestInMenuDrag) class MenuViewDragAndDropTestNestedDrag : public MenuViewDragAndDropTest { public:
diff --git a/chrome/browser/ui/views/simple_message_box_views.cc b/chrome/browser/ui/views/simple_message_box_views.cc index 93a41ef..d8d1cda2 100644 --- a/chrome/browser/ui/views/simple_message_box_views.cc +++ b/chrome/browser/ui/views/simple_message_box_views.cc
@@ -109,7 +109,7 @@ // ResourceBundle is not initialized yet. // Fallback to logging with a default response or a Windows MessageBox. #if defined(OS_WIN) - if (!base::MessageLoopForUI::IsCurrent() || + if (!base::MessageLoopCurrentForUI::IsSet() || !base::RunLoop::IsRunningOnCurrentThread() || !ui::ResourceBundle::HasSharedInstance()) { LOG_IF(ERROR, !checkbox_text.empty()) << "Dialog checkbox won't be shown"; @@ -121,7 +121,7 @@ return chrome::MESSAGE_BOX_RESULT_DEFERRED; } #elif defined(OS_MACOSX) - if (!base::MessageLoopForUI::IsCurrent() || + if (!base::MessageLoopCurrentForUI::IsSet() || !base::RunLoop::IsRunningOnCurrentThread() || !ui::ResourceBundle::HasSharedInstance()) { // Even though this function could return a value synchronously here in @@ -132,7 +132,7 @@ return chrome::MESSAGE_BOX_RESULT_DEFERRED; } #else - if (!base::MessageLoopForUI::IsCurrent() || + if (!base::MessageLoopCurrentForUI::IsSet() || !ui::ResourceBundle::HasSharedInstance() || !display::Screen::GetScreen()) { LOG(ERROR) << "Unable to show a dialog outside the UI thread message loop: "
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc index e83c5a5..e19fc68 100644 --- a/chrome/browser/ui/views/toolbar/app_menu.cc +++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -250,10 +250,6 @@ : LabelButton(listener, text) {} ~InMenuButton() override {} - void set_role_is_button(bool role_is_button) { - role_is_button_ = role_is_button; - } - void Init(InMenuButtonBackground::ButtonType type) { // An InMenuButton should always be focusable regardless of the platform. // Hence we don't use SetFocusForPlatform(). @@ -268,8 +264,7 @@ void GetAccessibleNodeData(ui::AXNodeData* node_data) override { LabelButton::GetAccessibleNodeData(node_data); - if (!role_is_button_) - node_data->role = ax::mojom::Role::kMenuItem; + node_data->role = ax::mojom::Role::kMenuItem; } // views::LabelButton @@ -295,10 +290,6 @@ } private: - // Indicates whether to expose this to accessibility as a Button. If it is a - // button, the accelerator will not be added to the accessible label. - bool role_is_button_ = false; - DISALLOW_COPY_AND_ASSIGN(InMenuButton); }; @@ -337,14 +328,15 @@ int string_id, InMenuButtonBackground::ButtonType type, int index) { - return CreateButtonWithAccName(string_id, type, index, string_id, false); + return CreateButtonWithAccName(string_id, type, index, string_id, + /*add_accelerator_text*/ true); } InMenuButton* CreateButtonWithAccName(int string_id, InMenuButtonBackground::ButtonType type, int index, int acc_string_id, - bool role_is_button) { + bool add_accelerator_text) { // Should only be invoked during construction when |menu_| is valid. DCHECK(menu_); InMenuButton* button = new InMenuButton( @@ -352,10 +344,9 @@ '&', nullptr, nullptr)); button->Init(type); button->SetAccessibleName(GetAccessibleNameForAppMenuItem( - menu_model_, index, acc_string_id, !role_is_button)); + menu_model_, index, acc_string_id, add_accelerator_text)); button->set_tag(index); button->SetEnabled(menu_model_->IsEnabledAt(index)); - button->set_role_is_button(role_is_button); AddChildView(button); // all buttons on menu should must be a custom button in order for @@ -502,7 +493,8 @@ decrement_button_ = CreateButtonWithAccName( IDS_ZOOM_MINUS2, InMenuButtonBackground::LEADING_BORDER, - decrement_index, IDS_ACCNAME_ZOOM_MINUS2, true); + decrement_index, IDS_ACCNAME_ZOOM_MINUS2, + /*add_accelerator_text*/ false); zoom_label_ = new Label(base::FormatPercent(100)); zoom_label_->SetAutoColorReadabilityEnabled(false); @@ -520,7 +512,7 @@ increment_button_ = CreateButtonWithAccName( IDS_ZOOM_PLUS2, InMenuButtonBackground::NO_BORDER, increment_index, - IDS_ACCNAME_ZOOM_PLUS2, true); + IDS_ACCNAME_ZOOM_PLUS2, /*add_accelerator_text*/ false); fullscreen_button_ = new FullscreenButton(this); // all buttons on menu should must be a custom button in order for @@ -540,7 +532,8 @@ fullscreen_button_->SetBackground(std::make_unique<InMenuButtonBackground>( InMenuButtonBackground::LEADING_BORDER)); fullscreen_button_->SetAccessibleName(GetAccessibleNameForAppMenuItem( - menu_model, fullscreen_index, IDS_ACCNAME_FULLSCREEN, true)); + menu_model, fullscreen_index, IDS_ACCNAME_FULLSCREEN, + /*add_accelerator_text*/ true)); AddChildView(fullscreen_button_); // Need to set a font list for the zoom label width calculations.
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.h b/chrome/browser/ui/views/toolbar/browser_actions_container.h index 09337f88..f39a410 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container.h +++ b/chrome/browser/ui/views/toolbar/browser_actions_container.h
@@ -164,7 +164,7 @@ std::string GetIdAt(size_t index) const; // Returns the ToolbarActionView* associated with the given |extension|, or - // NULL if none exists. + // nullptr if none exists. ToolbarActionView* GetViewForId(const std::string& id); // Update the views to reflect the state of the toolbar actions. @@ -258,8 +258,6 @@ // A struct representing the position at which an action will be dropped. struct DropPosition; - typedef std::vector<std::unique_ptr<ToolbarActionView>> ToolbarActionViews; - // Clears the |active_bubble_|, and unregisters the container as an observer. void ClearActiveBubble(views::Widget* widget); @@ -285,8 +283,8 @@ // The controlling ToolbarActionsBar, which handles most non-view logic. std::unique_ptr<ToolbarActionsBar> toolbar_actions_bar_; - // The vector of toolbar actions (icons/image buttons for each action). - ToolbarActionViews toolbar_action_views_; + // Child toolbar action buttons. + std::vector<std::unique_ptr<ToolbarActionView>> toolbar_action_views_; // The Browser object the container is associated with. Browser* const browser_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc index f4a61c4..8cfbe4a 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -97,7 +97,8 @@ void ToolbarActionView::GetAccessibleNodeData(ui::AXNodeData* node_data) { views::MenuButton::GetAccessibleNodeData(node_data); - node_data->role = ax::mojom::Role::kButton; + node_data->role = delegate_->ShownInsideMenu() ? ax::mojom::Role::kMenuItem + : ax::mojom::Role::kButton; } std::unique_ptr<LabelButtonBorder> ToolbarActionView::CreateDefaultBorder()
diff --git a/chrome/browser/ui/views/translate/translate_language_browsertest.cc b/chrome/browser/ui/views/translate/translate_language_browsertest.cc index cba454e..9a8c9209 100644 --- a/chrome/browser/ui/views/translate/translate_language_browsertest.cc +++ b/chrome/browser/ui/views/translate/translate_language_browsertest.cc
@@ -140,7 +140,7 @@ } language::UrlLanguageHistogram* GetUrlLanguageHistogram() { - const content::WebContents* const web_contents = + content::WebContents* const web_contents = browser_->tab_strip_model()->GetActiveWebContents(); EXPECT_TRUE(web_contents); content::BrowserContext* const browser_context =
diff --git a/chrome/browser/ui/views/uninstall_view.cc b/chrome/browser/ui/views/uninstall_view.cc index 559d893..bd1f281 100644 --- a/chrome/browser/ui/views/uninstall_view.cc +++ b/chrome/browser/ui/views/uninstall_view.cc
@@ -179,7 +179,7 @@ namespace chrome { int ShowUninstallBrowserPrompt() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); int result = service_manager::RESULT_CODE_NORMAL_EXIT; base::RunLoop run_loop;
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/discover_window_manager.cc b/chrome/browser/ui/webui/chromeos/login/discover/discover_window_manager.cc index 908dff82..648f2e7 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/discover_window_manager.cc +++ b/chrome/browser/ui/webui/chromeos/login/discover/discover_window_manager.cc
@@ -54,7 +54,7 @@ Browser* browser = FindBrowserForProfile(profile); if (browser) { DCHECK(browser->profile() == profile); - const content::WebContents* web_contents = + content::WebContents* web_contents = browser->tab_strip_model()->GetWebContentsAt(0); if (web_contents && web_contents->GetURL() == gurl) { browser->window()->Show();
diff --git a/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc b/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc index 69675d4..3632a26 100644 --- a/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc +++ b/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc
@@ -152,7 +152,7 @@ } void CustomHomePagesTableModel::SetToCurrentlyOpenPages( - const content::WebContents* ignore_contents) { + content::WebContents* ignore_contents) { // Remove the current entries. while (RowCount()) RemoveWithoutNotification(0); @@ -166,7 +166,7 @@ for (int tab_index = 0; tab_index < browser->tab_strip_model()->count(); ++tab_index) { - const content::WebContents* contents = + content::WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(tab_index); if (contents == ignore_contents) continue;
diff --git a/chrome/browser/ui/webui/settings/custom_home_pages_table_model.h b/chrome/browser/ui/webui/settings/custom_home_pages_table_model.h index 04760e43..80937b2 100644 --- a/chrome/browser/ui/webui/settings/custom_home_pages_table_model.h +++ b/chrome/browser/ui/webui/settings/custom_home_pages_table_model.h
@@ -54,7 +54,7 @@ // Clears any entries and fills the list with pages currently opened in the // browser. |ignore_contents| is omitted from the open pages. - void SetToCurrentlyOpenPages(const content::WebContents* ignore_contents); + void SetToCurrentlyOpenPages(content::WebContents* ignore_contents); // Returns the set of urls this model contains. std::vector<GURL> GetURLs();
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 82bc2fca..23b674e 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1500,14 +1500,15 @@ IDS_SETTINGS_CREDIT_CARD_NONE); } + GURL google_password_manager_url = GetGooglePasswordManagerURL( + password_manager::ManagePasswordsReferrer::kChromeSettings); html_source->AddString( "managePasswordsLabel", l10n_util::GetStringFUTF16( IDS_SETTINGS_PASSWORDS_MANAGE_PASSWORDS, - base::UTF8ToUTF16( - GetGooglePasswordManagerURL( - password_manager::ManagePasswordsReferrer::kChromeSettings) - .spec()))); + base::UTF8ToUTF16(google_password_manager_url.spec()))); + html_source->AddString("googlePasswordManagerUrl", + google_password_manager_url.spec()); html_source->AddString("passwordManagerLearnMoreURL", chrome::kPasswordManagerLearnMoreURL); html_source->AddString("manageAddressesUrl",
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index d1d9811..da2476b 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -16,6 +16,7 @@ #include "base/metrics/histogram_macros.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/browser/ui/webui/settings/about_handler.h" #include "chrome/browser/ui/webui/settings/appearance_handler.h" @@ -368,6 +369,10 @@ "autofillHomeEnabled", base::FeatureList::IsEnabled(password_manager::features::kAutofillHome)); + html_source->AddBoolean( + "navigateToGooglePasswordManager", + ShouldManagePasswordsinGooglePasswordManager(profile)); + html_source->AddBoolean("showImportPasswords", base::FeatureList::IsEnabled( password_manager::features::kPasswordImport));
diff --git a/chrome/browser/ui/webui/signin/signin_utils_desktop.cc b/chrome/browser/ui/webui/signin/signin_utils_desktop.cc index ce84ff5..5c72f19 100644 --- a/chrome/browser/ui/webui/signin/signin_utils_desktop.cc +++ b/chrome/browser/ui/webui/signin/signin_utils_desktop.cc
@@ -12,8 +12,8 @@ #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/chrome_signin_client.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/investigator_dependency_provider.h" -#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/signin_util.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" @@ -21,6 +21,7 @@ #include "components/signin/core/browser/identity_utils.h" #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/browser/signin_pref_names.h" +#include "services/identity/public/cpp/identity_manager.h" #include "ui/base/l10n/l10n_util.h" bool CanOfferSignin(Profile* profile, @@ -34,15 +35,15 @@ if (!profile) return false; - SigninManager* manager = SigninManagerFactory::GetForProfile(profile); - if (manager && !manager->IsSigninAllowed()) + if (!profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed)) return false; if (!ChromeSigninClient::ProfileAllowsSigninCookies(profile)) return false; if (!email.empty()) { - if (!manager) + auto* identity_manager = IdentityManagerFactory::GetForProfile(profile); + if (!identity_manager) return false; // Make sure this username is not prohibited by policy. @@ -62,7 +63,7 @@ // If the signin manager already has an authenticated name, then this is a // re-auth scenario. Make sure the email just signed in corresponds to // the one sign in manager expects. - std::string current_email = manager->GetAuthenticatedAccountInfo().email; + std::string current_email = identity_manager->GetPrimaryAccountInfo().email; const bool same_email = gaia::AreEmailsSame(current_email, email); if (!current_email.empty() && !same_email) { UMA_HISTOGRAM_ENUMERATION("Signin.Reauth",
diff --git a/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.cc b/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.cc index b765da2..e4f43af 100644 --- a/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.cc +++ b/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.cc
@@ -18,7 +18,7 @@ BookmarkAppInstallManager::~BookmarkAppInstallManager() = default; bool BookmarkAppInstallManager::CanInstallWebApp( - const content::WebContents* web_contents) { + content::WebContents* web_contents) { return extensions::TabHelper::FromWebContents(web_contents) ->CanCreateBookmarkApp(); }
diff --git a/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h b/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h index 3820cf8..36366e7 100644 --- a/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h +++ b/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h
@@ -16,7 +16,7 @@ ~BookmarkAppInstallManager() override; // InstallManager interface implementation. - bool CanInstallWebApp(const content::WebContents* web_contents) override; + bool CanInstallWebApp(content::WebContents* web_contents) override; void InstallWebApp(content::WebContents* web_contents, bool force_shortcut_app, OnceInstallCallback callback) override;
diff --git a/chrome/browser/web_applications/components/install_manager.h b/chrome/browser/web_applications/components/install_manager.h index 41666a0..36a0672 100644 --- a/chrome/browser/web_applications/components/install_manager.h +++ b/chrome/browser/web_applications/components/install_manager.h
@@ -22,7 +22,7 @@ base::OnceCallback<void(const AppId& app_id, InstallResultCode code)>; // Returns true if a web app can be installed for a given |web_contents|. - virtual bool CanInstallWebApp(const content::WebContents* web_contents) = 0; + virtual bool CanInstallWebApp(content::WebContents* web_contents) = 0; // Starts a web app installation process for a given |web_contents|. // |force_shortcut_app| forces the creation of a shortcut app instead of a PWA
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc index f463ef6..73996f2 100644 --- a/chrome/browser/web_applications/web_app_install_manager.cc +++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -31,7 +31,7 @@ WebAppInstallManager::~WebAppInstallManager() = default; bool WebAppInstallManager::CanInstallWebApp( - const content::WebContents* web_contents) { + content::WebContents* web_contents) { return IsValidWebAppUrl(web_contents->GetURL()); }
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h index 130b7191..8137030 100644 --- a/chrome/browser/web_applications/web_app_install_manager.h +++ b/chrome/browser/web_applications/web_app_install_manager.h
@@ -37,7 +37,7 @@ ~WebAppInstallManager() override; // InstallManager: - bool CanInstallWebApp(const content::WebContents* web_contents) override; + bool CanInstallWebApp(content::WebContents* web_contents) override; void InstallWebApp(content::WebContents* contents, bool force_shortcut_app, OnceInstallCallback callback) override;
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index c61e2a9..9a493716 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -41,7 +41,7 @@ // static WebAppProvider* WebAppProvider::GetForWebContents( - const content::WebContents* web_contents) { + content::WebContents* web_contents) { Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); DCHECK(profile); @@ -105,8 +105,7 @@ } // static -bool WebAppProvider::CanInstallWebApp( - const content::WebContents* web_contents) { +bool WebAppProvider::CanInstallWebApp(content::WebContents* web_contents) { auto* provider = WebAppProvider::GetForWebContents(web_contents); if (!provider || !provider->install_manager_) return false;
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h index e37b6cb..468c7b91 100644 --- a/chrome/browser/web_applications/web_app_provider.h +++ b/chrome/browser/web_applications/web_app_provider.h
@@ -48,8 +48,7 @@ public content::NotificationObserver { public: static WebAppProvider* Get(Profile* profile); - static WebAppProvider* GetForWebContents( - const content::WebContents* web_contents); + static WebAppProvider* GetForWebContents(content::WebContents* web_contents); explicit WebAppProvider(Profile* profile); @@ -62,7 +61,7 @@ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); // Returns true if a bookmark can be installed for a given |web_contents|. - static bool CanInstallWebApp(const content::WebContents* web_contents); + static bool CanInstallWebApp(content::WebContents* web_contents); // Starts a bookmark installation process for a given |web_contents|. static void InstallWebApp(content::WebContents* web_contents,
diff --git a/chrome/chrome_cleaner/interfaces/typemaps/BUILD.gn b/chrome/chrome_cleaner/interfaces/typemaps/BUILD.gn index a3dfc69..ad355e3 100644 --- a/chrome/chrome_cleaner/interfaces/typemaps/BUILD.gn +++ b/chrome/chrome_cleaner/interfaces/typemaps/BUILD.gn
@@ -18,6 +18,7 @@ "//chrome/chrome_cleaner/strings", "//chrome/chrome_cleaner/strings:string_test_helpers", "//chrome/chrome_cleaner/test:test_util", + "//components/chrome_cleaner/test:test_name_helper", "//mojo/core/embedder:embedder", "//testing/gtest", ]
diff --git a/chrome/chrome_cleaner/interfaces/typemaps/pup_typemap_unittest.cc b/chrome/chrome_cleaner/interfaces/typemaps/pup_typemap_unittest.cc index a08c485..c67b81e 100644 --- a/chrome/chrome_cleaner/interfaces/typemaps/pup_typemap_unittest.cc +++ b/chrome/chrome_cleaner/interfaces/typemaps/pup_typemap_unittest.cc
@@ -9,8 +9,8 @@ #include "chrome/chrome_cleaner/ipc/ipc_test_util.h" #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" #include "chrome/chrome_cleaner/pup_data/pup_data.h" -#include "chrome/chrome_cleaner/test/test_name_helper.h" #include "chrome/chrome_cleaner/test/test_util.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "mojo/core/embedder/embedder.h" #include "mojo/public/cpp/bindings/binding.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/chrome_cleaner/ipc/BUILD.gn b/chrome/chrome_cleaner/ipc/BUILD.gn index da4d7cd7..937919b 100644 --- a/chrome/chrome_cleaner/ipc/BUILD.gn +++ b/chrome/chrome_cleaner/ipc/BUILD.gn
@@ -93,6 +93,7 @@ "//chrome/chrome_cleaner/os:common_os", "//chrome/chrome_cleaner/test:test_util", "//components/chrome_cleaner/public/interfaces:interfaces", + "//components/chrome_cleaner/test:test_name_helper", "//mojo/core/embedder", "//sandbox/win:sandbox", "//testing/gmock",
diff --git a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc index 23eaf89..71c59c4 100644 --- a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc +++ b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc
@@ -17,9 +17,9 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/chrome_cleaner/ipc/ipc_test_util.h" #include "chrome/chrome_cleaner/logging/scoped_logging.h" -#include "chrome/chrome_cleaner/test/test_name_helper.h" #include "chrome/chrome_cleaner/test/test_util.h" #include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/message_pipe.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/chrome_cleaner/logging/BUILD.gn b/chrome/chrome_cleaner/logging/BUILD.gn index 4bb2c19..c832a5f3 100644 --- a/chrome/chrome_cleaner/logging/BUILD.gn +++ b/chrome/chrome_cleaner/logging/BUILD.gn
@@ -264,6 +264,7 @@ "//chrome/chrome_cleaner/test:test_util", "//chrome/chrome_cleaner/test/resources:test_resources", "//components/chrome_cleaner/public/constants:constants", + "//components/chrome_cleaner/test:test_name_helper", "//net/traffic_annotation:test_support", "//testing/gmock", "//testing/gtest",
diff --git a/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc b/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc index 3924fc0..eb94ffa0 100644 --- a/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc +++ b/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc
@@ -37,10 +37,10 @@ #include "chrome/chrome_cleaner/proto/shared_pup_enums.pb.h" #include "chrome/chrome_cleaner/pup_data/pup_data.h" #include "chrome/chrome_cleaner/test/test_file_util.h" -#include "chrome/chrome_cleaner/test/test_name_helper.h" #include "chrome/chrome_cleaner/test/test_settings_util.h" #include "chrome/chrome_cleaner/test/test_task_scheduler.h" #include "components/chrome_cleaner/public/constants/constants.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/protobuf/src/google/protobuf/repeated_field.h"
diff --git a/chrome/chrome_cleaner/logging/pending_logs_service.cc b/chrome/chrome_cleaner/logging/pending_logs_service.cc index 7e5731a..6730fb3 100644 --- a/chrome/chrome_cleaner/logging/pending_logs_service.cc +++ b/chrome/chrome_cleaner/logging/pending_logs_service.cc
@@ -39,7 +39,7 @@ const ChromeCleanerReport& chrome_cleaner_report, base::FilePath* log_file, RegistryLogger* registry_logger) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(log_file); DCHECK(registry_logger); // This can happen when we fail while retrying. The logging service is not @@ -123,7 +123,7 @@ } PendingLogsService::PendingLogsService() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); } PendingLogsService::~PendingLogsService() = default;
diff --git a/chrome/chrome_cleaner/os/BUILD.gn b/chrome/chrome_cleaner/os/BUILD.gn index 206ddef5..c9073ae 100644 --- a/chrome/chrome_cleaner/os/BUILD.gn +++ b/chrome/chrome_cleaner/os/BUILD.gn
@@ -167,6 +167,7 @@ "//chrome/chrome_cleaner/zip_archiver/broker:common", "//chrome/chrome_cleaner/zip_archiver/target:common", "//components/chrome_cleaner/public/constants:constants", + "//components/chrome_cleaner/test:test_name_helper", "//sandbox/win:sandbox", "//testing/gmock", "//testing/gtest",
diff --git a/chrome/chrome_cleaner/os/file_remover_unittest.cc b/chrome/chrome_cleaner/os/file_remover_unittest.cc index c1a9ad6..64abccd 100644 --- a/chrome/chrome_cleaner/os/file_remover_unittest.cc +++ b/chrome/chrome_cleaner/os/file_remover_unittest.cc
@@ -35,12 +35,12 @@ #include "chrome/chrome_cleaner/test/resources/grit/test_resources.h" #include "chrome/chrome_cleaner/test/test_file_util.h" #include "chrome/chrome_cleaner/test/test_layered_service_provider.h" -#include "chrome/chrome_cleaner/test/test_name_helper.h" #include "chrome/chrome_cleaner/test/test_strings.h" #include "chrome/chrome_cleaner/test/test_util.h" #include "chrome/chrome_cleaner/zip_archiver/broker/sandbox_setup.h" #include "chrome/chrome_cleaner/zip_archiver/sandboxed_zip_archiver.h" #include "chrome/chrome_cleaner/zip_archiver/target/sandbox_setup.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "sandbox/win/src/sandbox.h" #include "sandbox/win/src/sandbox_factory.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/chrome_cleaner/scanner/BUILD.gn b/chrome/chrome_cleaner/scanner/BUILD.gn index a994a5a..877b5e8 100644 --- a/chrome/chrome_cleaner/scanner/BUILD.gn +++ b/chrome/chrome_cleaner/scanner/BUILD.gn
@@ -143,6 +143,7 @@ "//chrome/chrome_cleaner/test:test_strings", "//chrome/chrome_cleaner/test:test_util", "//chrome/chrome_cleaner/test/resources:test_resources", + "//components/chrome_cleaner/test:test_name_helper", "//sandbox/win:sandbox", "//testing/gmock", "//testing/gtest",
diff --git a/chrome/chrome_cleaner/scanner/urza_scanner_impl_unittest.cc b/chrome/chrome_cleaner/scanner/urza_scanner_impl_unittest.cc index 21f7c7fa..4ab8a780 100644 --- a/chrome/chrome_cleaner/scanner/urza_scanner_impl_unittest.cc +++ b/chrome/chrome_cleaner/scanner/urza_scanner_impl_unittest.cc
@@ -42,12 +42,12 @@ #include "chrome/chrome_cleaner/proto/shared_pup_enums.pb.h" #include "chrome/chrome_cleaner/strings/string_util.h" #include "chrome/chrome_cleaner/test/test_file_util.h" -#include "chrome/chrome_cleaner/test/test_name_helper.h" #include "chrome/chrome_cleaner/test/test_pup_data.h" #include "chrome/chrome_cleaner/test/test_registry_util.h" #include "chrome/chrome_cleaner/test/test_signature_matcher.h" #include "chrome/chrome_cleaner/test/test_strings.h" #include "chrome/chrome_cleaner/test/test_util.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/chrome_cleaner/settings/BUILD.gn b/chrome/chrome_cleaner/settings/BUILD.gn index 549872d..a2d2f23 100644 --- a/chrome/chrome_cleaner/settings/BUILD.gn +++ b/chrome/chrome_cleaner/settings/BUILD.gn
@@ -74,6 +74,7 @@ "//chrome/chrome_cleaner/constants:common_strings", "//chrome/chrome_cleaner/test:test_util", "//components/chrome_cleaner/public/constants:constants", + "//components/chrome_cleaner/test:test_name_helper", "//testing/gtest", ] }
diff --git a/chrome/chrome_cleaner/settings/cleaner_settings_unittest.cc b/chrome/chrome_cleaner/settings/cleaner_settings_unittest.cc index 973ce34a..9219991 100644 --- a/chrome/chrome_cleaner/settings/cleaner_settings_unittest.cc +++ b/chrome/chrome_cleaner/settings/cleaner_settings_unittest.cc
@@ -9,8 +9,8 @@ #include "base/command_line.h" #include "base/strings/string_number_conversions.h" #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" -#include "chrome/chrome_cleaner/test/test_name_helper.h" #include "components/chrome_cleaner/public/constants/constants.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "testing/gtest/include/gtest/gtest.h" namespace chrome_cleaner {
diff --git a/chrome/chrome_cleaner/test/BUILD.gn b/chrome/chrome_cleaner/test/BUILD.gn index 098bad2..e28ebf92 100644 --- a/chrome/chrome_cleaner/test/BUILD.gn +++ b/chrome/chrome_cleaner/test/BUILD.gn
@@ -142,7 +142,6 @@ "test_file_util.h", "test_layered_service_provider.cc", "test_layered_service_provider.h", - "test_name_helper.h", "test_registry_util.cc", "test_registry_util.h", "test_settings_util.cc",
diff --git a/chrome/chrome_cleaner/ui/BUILD.gn b/chrome/chrome_cleaner/ui/BUILD.gn index 45d0f6c3..39629ae 100644 --- a/chrome/chrome_cleaner/ui/BUILD.gn +++ b/chrome/chrome_cleaner/ui/BUILD.gn
@@ -42,6 +42,7 @@ "//chrome/chrome_cleaner/ipc:mock_chrome_prompt_ipc", "//chrome/chrome_cleaner/test:test_pup_data", "//chrome/chrome_cleaner/test:test_util", + "//components/chrome_cleaner/test:test_name_helper", "//testing/gmock", "//testing/gtest", ]
diff --git a/chrome/chrome_cleaner/ui/silent_main_dialog_unittest.cc b/chrome/chrome_cleaner/ui/silent_main_dialog_unittest.cc index 83854565..b727c4c 100644 --- a/chrome/chrome_cleaner/ui/silent_main_dialog_unittest.cc +++ b/chrome/chrome_cleaner/ui/silent_main_dialog_unittest.cc
@@ -11,10 +11,10 @@ #include "base/files/file_path.h" #include "chrome/chrome_cleaner/constants/uws_id.h" -#include "chrome/chrome_cleaner/test/test_name_helper.h" #include "chrome/chrome_cleaner/test/test_pup_data.h" #include "chrome/chrome_cleaner/test/test_settings_util.h" #include "chrome/chrome_cleaner/ui/mock_main_dialog_delegate.h" +#include "components/chrome_cleaner/test/test_name_helper.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc b/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc index 1a71362..d67da619 100644 --- a/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc +++ b/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
@@ -4,15 +4,17 @@ #include "chrome/common/apps/platform_apps/chrome_apps_api_permissions.h" +#include <memory> + #include "chrome/common/apps/platform_apps/media_galleries_permission.h" namespace chrome_apps_api_permissions { namespace { template <typename T> -extensions::APIPermission* CreateAPIPermission( +std::unique_ptr<extensions::APIPermission> CreateAPIPermission( const extensions::APIPermissionInfo* permission) { - return new T(permission); + return std::make_unique<T>(permission); } // WARNING: If you are modifying a permission message in this list, be sure to
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc index 69238bf..6fa6139d 100644 --- a/chrome/common/extensions/permissions/chrome_api_permissions.cc +++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -21,8 +21,9 @@ namespace { template <typename T> -APIPermission* CreateAPIPermission(const APIPermissionInfo* permission) { - return new T(permission); +std::unique_ptr<APIPermission> CreateAPIPermission( + const APIPermissionInfo* permission) { + return std::make_unique<T>(permission); } // WARNING: If you are modifying a permission message in this list, be sure to
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc index 0dab07f..9d0543d 100644 --- a/chrome/common/extensions/permissions/permission_set_unittest.cc +++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -345,8 +345,8 @@ const APIPermissionInfo* permission_info = PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket); - std::unique_ptr<APIPermission> permission( - permission_info->CreateAPIPermission()); + std::unique_ptr<APIPermission> permission = + permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -389,7 +389,7 @@ apis2.insert(APIPermission::kProxy); apis2.insert(APIPermission::kClipboardWrite); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -402,7 +402,7 @@ expected_apis.insert(APIPermission::kProxy); expected_apis.insert(APIPermission::kClipboardWrite); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -466,8 +466,8 @@ // Intersection with an empty set. apis1.insert(APIPermission::kTab); apis1.insert(APIPermission::kBackground); - std::unique_ptr<APIPermission> permission( - permission_info->CreateAPIPermission()); + std::unique_ptr<APIPermission> permission = + permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -502,7 +502,7 @@ apis2.insert(APIPermission::kTab); apis2.insert(APIPermission::kProxy); apis2.insert(APIPermission::kClipboardWrite); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("udp-bind::8080"); @@ -513,7 +513,7 @@ apis2.insert(std::move(permission)); expected_apis.insert(APIPermission::kTab); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("udp-bind::8080"); @@ -574,8 +574,8 @@ // Difference with an empty set. apis1.insert(APIPermission::kTab); apis1.insert(APIPermission::kBackground); - std::unique_ptr<APIPermission> permission( - permission_info->CreateAPIPermission()); + std::unique_ptr<APIPermission> permission = + permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -599,7 +599,7 @@ apis2.insert(APIPermission::kTab); apis2.insert(APIPermission::kProxy); apis2.insert(APIPermission::kClipboardWrite); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -609,7 +609,7 @@ apis2.insert(std::move(permission)); expected_apis.insert(APIPermission::kBackground); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("udp-bind::8080");
diff --git a/chrome/common/page_load_metrics/page_load_metrics.mojom b/chrome/common/page_load_metrics/page_load_metrics.mojom index 6f8e7a3c..c54ca69 100644 --- a/chrome/common/page_load_metrics/page_load_metrics.mojom +++ b/chrome/common/page_load_metrics/page_load_metrics.mojom
@@ -180,7 +180,7 @@ int64 received_data_length = 0; // The length of the response body for the resource before removing any - // content encodings. + // content encodings. Only set for complete resources. int64 encoded_body_length = 0; // Whether this resource load has completed.
diff --git a/chrome/common/safe_browsing/binary_feature_extractor_fuzzer.cc b/chrome/common/safe_browsing/binary_feature_extractor_fuzzer.cc new file mode 100644 index 0000000..6372463 --- /dev/null +++ b/chrome/common/safe_browsing/binary_feature_extractor_fuzzer.cc
@@ -0,0 +1,24 @@ +// 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/common/safe_browsing/binary_feature_extractor.h" + +#include <stddef.h> +#include <stdint.h> + +#include <string> + +#include "components/safe_browsing/proto/csd.pb.h" + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + static safe_browsing::BinaryFeatureExtractor* extractor = + new safe_browsing::BinaryFeatureExtractor(); + + google::protobuf::RepeatedPtrField<std::string> signed_data; + safe_browsing::ClientDownloadRequest_ImageHeaders image_headers; + extractor->ExtractImageFeaturesFromData( + data, size, safe_browsing::BinaryFeatureExtractor::kDefaultOptions, + &image_headers, &signed_data); + return 0; +}
diff --git a/chrome/renderer/page_load_metrics/page_resource_data_use.cc b/chrome/renderer/page_load_metrics/page_resource_data_use.cc index b31015b..35d6cbc 100644 --- a/chrome/renderer/page_load_metrics/page_resource_data_use.cc +++ b/chrome/renderer/page_load_metrics/page_resource_data_use.cc
@@ -38,8 +38,6 @@ data_reduction_proxy::EstimateCompressionRatioFromHeaders(&response_head); proxy_used_ = !response_head.proxy_server.is_direct(); mime_type_ = response_head.mime_type; - total_received_bytes_ = 0; - last_update_bytes_ = 0; was_fetched_via_cache_ = response_head.was_fetched_via_cache; is_secure_scheme_ = response_url.SchemeIsCryptographic(); } @@ -82,7 +80,7 @@ int PageResourceDataUse::CalculateNewlyReceivedBytes() { int newly_received_bytes = total_received_bytes_ - last_update_bytes_; last_update_bytes_ = total_received_bytes_; - DCHECK(newly_received_bytes >= 0); + DCHECK_GE(newly_received_bytes, 0); return newly_received_bytes; }
diff --git a/chrome/renderer/page_load_metrics/page_resource_data_use.h b/chrome/renderer/page_load_metrics/page_resource_data_use.h index 9723bd0..7431f65 100644 --- a/chrome/renderer/page_load_metrics/page_resource_data_use.h +++ b/chrome/renderer/page_load_metrics/page_resource_data_use.h
@@ -63,8 +63,8 @@ // used. double data_reduction_proxy_compression_ratio_estimate_; - uint64_t total_received_bytes_; - uint64_t last_update_bytes_; + uint64_t total_received_bytes_ = 0; + uint64_t last_update_bytes_ = 0; uint64_t encoded_body_length_ = 0; bool is_complete_;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index fbcc2c9..95eb77f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3299,6 +3299,7 @@ "//chrome/browser/resource_coordinator/tab_ranker:tab_features_test_helper", "//chrome/services/app_service:unit_tests", "//chrome/services/app_service/public/cpp/:unit_tests", + "//components/chrome_cleaner/test:test_name_helper", "//components/signin/core/browser:signin_buildflags", "//services/metrics/public/cpp:ukm_builders", "//third_party/libaddressinput", @@ -5789,12 +5790,12 @@ } } -# Note: this compiles and runs on Mac but may cause -# system instability; if you try it out, close other -# programs and then reboot afterwards. It should be -# possible to make it work on Linux if you use the -# --enable-speech-dispatcher flag. if (is_win) { + # Note: this compiles and runs on Mac but may cause + # system instability; if you try it out, close other + # programs and then reboot afterwards. It should be + # possible to make it work on Linux if you use the + # --enable-speech-dispatcher flag. fuzzer_test("tts_platform_fuzzer") { sources = [ "../browser/speech/mock_tts_controller.cc", @@ -5813,4 +5814,23 @@ "//ui/base", ] } + + fuzzer_test("safe_browsing_binary_feature_extractor_fuzzer") { + sources = [ + "../common/safe_browsing/binary_feature_extractor.cc", + "../common/safe_browsing/binary_feature_extractor_fuzzer.cc", + "../common/safe_browsing/binary_feature_extractor_win.cc", + "../common/safe_browsing/pe_image_reader_win.cc", + ] + deps = [ + "//base", + "//components/safe_browsing:csd_proto", + "//crypto", + ] + libs = [ "wintrust.lib" ] + + # Directory contains useful and non-useful files. Don't worry about + # non-useful since they are eliminated during pruning. + seed_corpus = "data/safe_browsing/download_protection/" + } }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java index 2c3ea67..4e4bed3 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -6,8 +6,6 @@ import android.accounts.Account; import android.annotation.SuppressLint; -import android.app.Instrumentation; -import android.content.Context; import android.support.annotation.WorkerThread; import org.chromium.base.ContextUtils; @@ -34,8 +32,6 @@ private static final String DEFAULT_ACCOUNT = "test@gmail.com"; @SuppressLint("StaticFieldLeak") - private static Context sContext; - @SuppressLint("StaticFieldLeak") private static FakeAccountManagerDelegate sAccountManager; @SuppressLint("StaticFieldLeak") private static List<AccountHolder> sAddedAccounts = new ArrayList<>(); @@ -46,15 +42,9 @@ * This must be called before native is loaded. */ @WorkerThread - public static void setUpAuthForTest(Instrumentation instrumentation) { - assert sContext == null; - sContext = instrumentation.getTargetContext(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ProcessInitializationHandler.getInstance().initializePreNative(); - } - }); + public static void setUpAuthForTest() { + ThreadUtils.runOnUiThreadBlocking( + () -> ProcessInitializationHandler.getInstance().initializePreNative()); sAccountManager = new FakeAccountManagerDelegate( FakeAccountManagerDelegate.DISABLE_PROFILE_DATA_SOURCE); AccountManagerFacade.overrideAccountManagerFacadeForTests(sAccountManager); @@ -71,14 +61,12 @@ sAccountManager.removeAccountHolderBlocking(accountHolder); } sAddedAccounts.clear(); - sContext = null; } /** * Returns the currently signed in account. */ public static Account getCurrentAccount() { - assert sContext != null; return ChromeSigninController.get().getSignedInUser(); } @@ -115,21 +103,18 @@ } private static void overrideAccountIdProvider() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - AccountIdProvider.setInstanceForTest(new AccountIdProvider() { - @Override - public String getAccountId(String accountName) { - return "gaia-id-" + accountName; - } + ThreadUtils.runOnUiThreadBlocking(() -> { + AccountIdProvider.setInstanceForTest(new AccountIdProvider() { + @Override + public String getAccountId(String accountName) { + return "gaia-id-" + accountName; + } - @Override - public boolean canBeUsed() { - return true; - } - }); - } + @Override + public boolean canBeUsed() { + return true; + } + }); }); } @@ -142,7 +127,7 @@ ChromeSigninController.get().setSignedInAccountName(null); ContextUtils.getAppSharedPreferences() .edit() - .putStringSet(OAuth2TokenService.STORED_ACCOUNTS_KEY, new HashSet<String>()) + .putStringSet(OAuth2TokenService.STORED_ACCOUNTS_KEY, new HashSet<>()) .apply(); }
diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc index 8e344e50..84e9f39 100644 --- a/chrome/test/chromedriver/capabilities.cc +++ b/chrome/test/chromedriver/capabilities.cc
@@ -756,8 +756,6 @@ parser_map["networkConnectionEnabled"] = base::BindRepeating(&ParseBoolean, &network_emulation_enabled); } - // goog:testName is set by some tests to help debugging, and is ignored. - parser_map["goog:testName"] = base::BindRepeating(&IgnoreCapability); for (base::DictionaryValue::Iterator it(desired_caps); !it.IsAtEnd(); it.Advance()) { @@ -765,9 +763,10 @@ continue; if (parser_map.find(it.key()) == parser_map.end()) { // The specified capability is unrecognized. W3C spec requires us to - // return an error. In legacy mode, for backward compatibility reasons, + // return an error if capability does not contain ":". + // In legacy mode, for backward compatibility reasons, // we ignore unrecognized capabilities. - if (w3c_compliant) + if (w3c_compliant && it.key().find(':') == std::string::npos) return Status(kInvalidArgument, "unrecognized capability: " + it.key()); else continue;
diff --git a/chrome/test/chromedriver/chrome/adb_impl.cc b/chrome/test/chromedriver/chrome/adb_impl.cc index acd002e0..77be2f60 100644 --- a/chrome/test/chromedriver/chrome/adb_impl.cc +++ b/chrome/test/chromedriver/chrome/adb_impl.cc
@@ -82,7 +82,7 @@ void ExecuteCommandOnIOThread( const std::string& command, scoped_refptr<ResponseBuffer> response_buffer, int port) { - CHECK(base::MessageLoopForIO::IsCurrent()); + CHECK(base::MessageLoopCurrentForIO::IsSet()); AdbClientSocket::AdbQuery(port, command, base::Bind(&ResponseBuffer::OnResponse, response_buffer)); } @@ -92,7 +92,7 @@ const std::string& content, scoped_refptr<ResponseBuffer> response_buffer, int port) { - CHECK(base::MessageLoopForIO::IsCurrent()); + CHECK(base::MessageLoopCurrentForIO::IsSet()); AdbClientSocket::SendFile( port, device_serial, filename, content, base::Bind(&ResponseBuffer::OnResponse, response_buffer));
diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js index 8bb7100..f4f7def 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js +++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
@@ -3074,8 +3074,11 @@ // Focus twice, then make sure that the internal element is still focused. webview.focus(); webview.focus(); - embedder.test.assertTrue(document.activeElement = webview); - embedder.test.assertTrue(webview.shadowRoot.activeElement); + embedder.test.assertEq(document.activeElement, webview); + var webviewPrivates = + chrome.test.getModuleSystem(webview).privates(webview); + var shadowRoot = webviewPrivates.internal.shadowRoot; + embedder.test.assertTrue(shadowRoot.activeElement); embedder.test.succeed(); });
diff --git a/chrome/test/data/webui/settings/people_page_test.js b/chrome/test/data/webui/settings/people_page_test.js index 6a108653..0066bbe 100644 --- a/chrome/test/data/webui/settings/people_page_test.js +++ b/chrome/test/data/webui/settings/people_page_test.js
@@ -3,6 +3,20 @@ // found in the LICENSE file. cr.define('settings_people_page', function() { + /** @implements {settings.PeopleBrowserProxy} */ + class TestPeopleBrowserProxy extends TestBrowserProxy { + constructor() { + super([ + 'openURL', + ]); + } + + /** @override */ + openURL(url) { + this.methodCalled('openURL', url); + } + } + suite('ProfileInfoTests', function() { /** @type {SettingsPeoplePageElement} */ let peoplePage = null; @@ -501,4 +515,66 @@ assertEquals(settings.getCurrentRoute(), settings.routes.SYNC); }); }); + + suite('PasswordsUITest', function() { + /** @type {SettingsPeoplePageElement} */ + let peoplePage = null; + /** @type {settings.PeopleBrowserProxy} */ + let browserProxy = null; + + suiteSetup(function() { + // Forces navigation to Google Password Manager to be off by default. + loadTimeData.overrideValues({ + navigateToGooglePasswordManager: false, + }); + }); + + setup(function() { + browserProxy = new TestPeopleBrowserProxy(); + settings.PeopleBrowserProxyImpl.instance_ = browserProxy; + + PolymerTest.clearBody(); + peoplePage = document.createElement('settings-people-page'); + + // Force enable Autofill Home. + // TODO(jdoerrie): https://crbug.com/854562. + // Remove when removing Autofill Home flag. + peoplePage.autofillHomeEnabled = true; + document.body.appendChild(peoplePage); + + Polymer.dom.flush(); + }); + + teardown(function() { + peoplePage.remove(); + }); + + test('Google Password Manager Off', function() { + assertTrue(!!peoplePage.$$('#passwordManagerButton')); + peoplePage.$$('#passwordManagerButton').click(); + Polymer.dom.flush(); + + assertEquals( + settings.getCurrentRoute(), settings.routes.MANAGE_PASSWORDS); + }); + + test('Google Password Manager On', function() { + // Hardcode this value so that the test is independent of the production + // implementation that might include additional query parameters. + const googlePasswordManagerUrl = 'https://passwords.google.com'; + + loadTimeData.overrideValues({ + navigateToGooglePasswordManager: true, + googlePasswordManagerUrl: googlePasswordManagerUrl, + }); + + assertTrue(!!peoplePage.$$('#passwordManagerButton')); + peoplePage.$$('#passwordManagerButton').click(); + Polymer.dom.flush(); + + return browserProxy.whenCalled('openURL').then(url => { + assertEquals(googlePasswordManagerUrl, url); + }); + }); + }); });
diff --git a/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc b/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc index 25ef92eb..89209dc4 100644 --- a/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc +++ b/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -136,7 +136,7 @@ bool CanRequestAutomation(const Extension* extension, const AutomationInfo* automation_info, - const content::WebContents* contents) { + content::WebContents* contents) { if (automation_info->desktop) return true;
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index 593dec5d..7e3099f 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc
@@ -296,6 +296,9 @@ // Enables "hide Skip button" for ARC setup in the OOBE flow. const char kEnableArcOobeOptinNoSkip[] = "enable-arc-oobe-optin-no-skip"; +// Enables ARC VM. +const char kEnableArcVm[] = "enable-arcvm"; + // Enables using a random url for captive portal detection. const char kEnableCaptivePortalRandomUrl[] = "enable-captive-portal-random-url";
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index 743c983a..de729f7 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h
@@ -86,6 +86,7 @@ CHROMEOS_EXPORT extern const char kDisableWakeOnWifi[]; CHROMEOS_EXPORT extern const char kEnableArc[]; CHROMEOS_EXPORT extern const char kEnableArcOobeOptinNoSkip[]; +CHROMEOS_EXPORT extern const char kEnableArcVm[]; CHROMEOS_EXPORT extern const char kEnableCaptivePortalRandomUrl[]; CHROMEOS_EXPORT extern const char kEnableCastReceiver[]; CHROMEOS_EXPORT extern const char kEnableChromevoxDeveloperOption[];
diff --git a/components/arc/arc_util.cc b/components/arc/arc_util.cc index 04159182..aaff5903 100644 --- a/components/arc/arc_util.cc +++ b/components/arc/arc_util.cc
@@ -71,6 +71,11 @@ base::FeatureList::IsEnabled(kEnableArcFeature)); } +bool IsArcVmEnabled() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kEnableArcVm); +} + bool ShouldArcAlwaysStart() { const auto* command_line = base::CommandLine::ForCurrentProcess(); if (!command_line->HasSwitch(chromeos::switches::kArcStartMode))
diff --git a/components/arc/arc_util.h b/components/arc/arc_util.h index 7d6ec124..c066692 100644 --- a/components/arc/arc_util.h +++ b/components/arc/arc_util.h
@@ -36,6 +36,9 @@ // check, so it is ok to access them directly. bool IsArcAvailable(); +// Returns true if ARC VM is enabled. +bool IsArcVmEnabled(); + // Returns true if ARC should always start within the primary user session // (opted in user or not), and other supported mode such as guest and Kiosk // mode.
diff --git a/components/arc/arc_util_unittest.cc b/components/arc/arc_util_unittest.cc index bf81c4ef..fd75726 100644 --- a/components/arc/arc_util_unittest.cc +++ b/components/arc/arc_util_unittest.cc
@@ -155,6 +155,14 @@ EXPECT_TRUE(IsArcKioskAvailable()); } +TEST_F(ArcUtilTest, IsArcVmEnablede) { + EXPECT_FALSE(IsArcVmEnabled()); + + auto* command_line = base::CommandLine::ForCurrentProcess(); + command_line->InitFromArgv({"", "--enable-arcvm"}); + EXPECT_TRUE(IsArcVmEnabled()); +} + // TODO(hidehiko): Add test for IsArcKioskMode(). // It depends on UserManager, but a utility to inject fake instance is // available only in chrome/. To use it in components/, refactoring is needed.
diff --git a/components/assist_ranker/base_predictor.cc b/components/assist_ranker/base_predictor.cc index 9060cd8..07e585a 100644 --- a/components/assist_ranker/base_predictor.cc +++ b/components/assist_ranker/base_predictor.cc
@@ -124,6 +124,10 @@ return GURL(config_.field_trial_url_param->Get()); } +float BasePredictor::GetPredictThresholdReplacement() const { + return config_.field_trial_threshold_replacement_param; +} + RankerExample BasePredictor::PreprocessExample(const RankerExample& example) { if (ranker_model_->proto().has_metadata() && ranker_model_->proto().metadata().input_features_names_are_hex_hashes()) {
diff --git a/components/assist_ranker/base_predictor.h b/components/assist_ranker/base_predictor.h index 6904ad2..c89a4ae6 100644 --- a/components/assist_ranker/base_predictor.h +++ b/components/assist_ranker/base_predictor.h
@@ -22,6 +22,10 @@ namespace assist_ranker { +// Value to use for when no prediction threshold replacement should be applied. +// See |GetPredictThresholdReplacement| method. +const float kNoPredictThresholdReplacement = 0.0; + class Feature; class RankerExample; class RankerModel; @@ -29,7 +33,7 @@ // Predictors are objects that provide an interface for prediction, as well as // encapsulate the logic for loading the model and logging. Sub-classes of // BasePredictor implement an interface that depends on the nature of the -// suported model. Subclasses of BasePredictor will also need to implement an +// supported model. Subclasses of BasePredictor will also need to implement an // Initialize method that will be called once the model is available, and a // static validation function with the following signature: // @@ -49,6 +53,9 @@ // Returns the model URL. GURL GetModelUrl() const; + // Returns the threshold to use for prediction, or + // kNoPredictThresholdReplacement to leave it unchanged. + float GetPredictThresholdReplacement() const; // Returns the model name. std::string GetModelName() const;
diff --git a/components/assist_ranker/base_predictor_unittest.cc b/components/assist_ranker/base_predictor_unittest.cc index 5b770768..6b330ba 100644 --- a/components/assist_ranker/base_predictor_unittest.cc +++ b/components/assist_ranker/base_predictor_unittest.cc
@@ -54,37 +54,41 @@ const base::FeatureParam<std::string> kTestRankerUrl{ &kTestRankerQuery, kTestUrlParamName, kTestDefaultModelUrl}; -const PredictorConfig kTestPredictorConfig = PredictorConfig{ - kTestModelName, kTestLoggingName, kTestUmaPrefixName, LOG_UKM, - &kFeatureWhitelist, &kTestRankerQuery, &kTestRankerUrl}; +const PredictorConfig kTestPredictorConfig = + PredictorConfig{kTestModelName, kTestLoggingName, + kTestUmaPrefixName, LOG_UKM, + &kFeatureWhitelist, &kTestRankerQuery, + &kTestRankerUrl, kNoPredictThresholdReplacement}; // Class that implements virtual functions of the base class. class FakePredictor : public BasePredictor { public: - static std::unique_ptr<FakePredictor> Create(); + // Creates a |FakePredictor| using the default config (from this file). + static std::unique_ptr<FakePredictor> Create() { + return Create(kTestPredictorConfig); + } + // Creates a |FakePredictor| using the |PredictorConfig| passed in + // |predictor_config|. + static std::unique_ptr<FakePredictor> Create( + PredictorConfig predictor_config); ~FakePredictor() override{}; // Validation will always succeed. - static RankerModelStatus ValidateModel(const RankerModel& model); + static RankerModelStatus ValidateModel(const RankerModel& model) { + return RankerModelStatus::OK; + } protected: // Not implementing any inference logic. bool Initialize() override { return true; }; private: - FakePredictor(const PredictorConfig& config); + FakePredictor(const PredictorConfig& config) : BasePredictor(config) {} DISALLOW_COPY_AND_ASSIGN(FakePredictor); }; -FakePredictor::FakePredictor(const PredictorConfig& config) - : BasePredictor(config) {} - -RankerModelStatus FakePredictor::ValidateModel(const RankerModel& model) { - return RankerModelStatus::OK; -} - -std::unique_ptr<FakePredictor> FakePredictor::Create() { - std::unique_ptr<FakePredictor> predictor( - new FakePredictor(kTestPredictorConfig)); +std::unique_ptr<FakePredictor> FakePredictor::Create( + PredictorConfig predictor_config) { + std::unique_ptr<FakePredictor> predictor(new FakePredictor(predictor_config)); auto ranker_model = std::make_unique<RankerModel>(); auto fake_model_loader = std::make_unique<FakeRankerModelLoader>( base::BindRepeating(&FakePredictor::ValidateModel), @@ -184,4 +188,14 @@ GetTestUkmRecorder()->EntryHasMetric(entries[0], kFeatureNotWhitelisted)); } +TEST_F(BasePredictorTest, GetPredictThresholdReplacement) { + float altered_threshold = 0.78f; // Arbitrary value. + const PredictorConfig altered_threshold_config{ + kTestModelName, kTestLoggingName, kTestUmaPrefixName, + LOG_UKM, &kFeatureWhitelist, &kTestRankerQuery, + &kTestRankerUrl, altered_threshold}; + auto predictor = FakePredictor::Create(altered_threshold_config); + EXPECT_EQ(altered_threshold, predictor->GetPredictThresholdReplacement()); +} + } // namespace assist_ranker
diff --git a/components/assist_ranker/binary_classifier_predictor.cc b/components/assist_ranker/binary_classifier_predictor.cc index 651eaab8..402aa59 100644 --- a/components/assist_ranker/binary_classifier_predictor.cc +++ b/components/assist_ranker/binary_classifier_predictor.cc
@@ -36,6 +36,8 @@ const GURL& model_url = predictor->GetModelUrl(); DVLOG(1) << "Creating predictor instance for " << predictor->GetModelName(); DVLOG(1) << "Model URL: " << model_url; + DVLOG(1) << "Using predict threshold replacement: " + << predictor->GetPredictThresholdReplacement(); auto model_loader = std::make_unique<RankerModelLoaderImpl>( base::BindRepeating(&BinaryClassifierPredictor::ValidateModel), base::BindRepeating(&BinaryClassifierPredictor::OnModelAvailable, @@ -52,7 +54,13 @@ return false; } - *prediction = inference_module_->Predict(PreprocessExample(example)); + float predict_threshold_replacement = GetPredictThresholdReplacement(); + if (predict_threshold_replacement != kNoPredictThresholdReplacement) { + *prediction = inference_module_->PredictScore(PreprocessExample(example)) >= + predict_threshold_replacement; + } else { + *prediction = inference_module_->Predict(PreprocessExample(example)); + } DVLOG(1) << "Predictor " << GetModelName() << " predicted: " << *prediction; return true; }
diff --git a/components/assist_ranker/binary_classifier_predictor_unittest.cc b/components/assist_ranker/binary_classifier_predictor_unittest.cc index 672c80f..03dfa53 100644 --- a/components/assist_ranker/binary_classifier_predictor_unittest.cc +++ b/components/assist_ranker/binary_classifier_predictor_unittest.cc
@@ -31,6 +31,7 @@ GenericLogisticRegressionModel GetSimpleLogisticRegressionModel(); PredictorConfig GetConfig(); + PredictorConfig GetConfig(float predictor_threshold_replacement); protected: const std::string feature_ = "feature"; @@ -66,9 +67,14 @@ &kTestRankerQuery, "url-param-name", "https://default.model.url"}; PredictorConfig BinaryClassifierPredictorTest::GetConfig() { + return GetConfig(kNoPredictThresholdReplacement); +} + +PredictorConfig BinaryClassifierPredictorTest::GetConfig( + float predictor_threshold_replacement) { PredictorConfig config("model_name", "logging_name", "uma_prefix", LOG_NONE, GetEmptyWhitelist(), &kTestRankerQuery, - &kTestRankerUrl); + &kTestRankerUrl, predictor_threshold_replacement); return config; } @@ -171,4 +177,30 @@ EXPECT_LT(float_response, threshold_); } +TEST_F(BinaryClassifierPredictorTest, + GenericLogisticRegressionPreprocessedModelReplacedThreshold) { + auto ranker_model = std::make_unique<RankerModel>(); + auto& glr = *ranker_model->mutable_proto()->mutable_logistic_regression(); + glr = GetSimpleLogisticRegressionModel(); + glr.clear_weights(); + glr.set_is_preprocessed_model(true); + (*glr.mutable_fullname_weights())[feature_] = weight_; + + float high_threshold = 0.9; // Some high threshold. + auto predictor = + InitPredictor(std::move(ranker_model), GetConfig(high_threshold)); + EXPECT_TRUE(predictor->IsReady()); + + RankerExample ranker_example; + auto& features = *ranker_example.mutable_features(); + features[feature_].set_bool_value(true); + bool bool_response; + EXPECT_TRUE(predictor->Predict(ranker_example, &bool_response)); + EXPECT_FALSE(bool_response); + float float_response; + EXPECT_TRUE(predictor->PredictScore(ranker_example, &float_response)); + EXPECT_GT(float_response, threshold_); + EXPECT_LT(float_response, high_threshold); +} + } // namespace assist_ranker
diff --git a/components/assist_ranker/generic_logistic_regression_inference.h b/components/assist_ranker/generic_logistic_regression_inference.h index ad4b1dbf..eb34804 100644 --- a/components/assist_ranker/generic_logistic_regression_inference.h +++ b/components/assist_ranker/generic_logistic_regression_inference.h
@@ -23,7 +23,7 @@ // Returns a boolean decision given a RankerExample. Uses the same logic as // PredictScore, and then applies the model decision threshold. bool Predict(const RankerExample& example); - // Returns a score between 0 and 1 give a RankerExample. + // Returns a score between 0 and 1 given a RankerExample. float PredictScore(const RankerExample& example); private:
diff --git a/components/assist_ranker/predictor_config.h b/components/assist_ranker/predictor_config.h index 6a54588..944164b4 100644 --- a/components/assist_ranker/predictor_config.h +++ b/components/assist_ranker/predictor_config.h
@@ -30,21 +30,25 @@ const LogType log_type, const base::flat_set<std::string>* feature_whitelist, const base::Feature* field_trial, - const base::FeatureParam<std::string>* field_trial_url_param) + const base::FeatureParam<std::string>* field_trial_url_param, + float field_trial_threshold_replacement_param) : model_name(model_name), logging_name(logging_name), uma_prefix(uma_prefix), log_type(log_type), feature_whitelist(feature_whitelist), field_trial(field_trial), - field_trial_url_param(field_trial_url_param) {} - const char* model_name; - const char* logging_name; - const char* uma_prefix; + field_trial_url_param(field_trial_url_param), + field_trial_threshold_replacement_param( + field_trial_threshold_replacement_param) {} + const char* const model_name; + const char* const logging_name; + const char* const uma_prefix; const LogType log_type; const base::flat_set<std::string>* feature_whitelist; const base::Feature* field_trial; const base::FeatureParam<std::string>* field_trial_url_param; + const float field_trial_threshold_replacement_param; }; } // namespace assist_ranker
diff --git a/components/assist_ranker/predictor_config_definitions.cc b/components/assist_ranker/predictor_config_definitions.cc index e967f68..7bcfc641 100644 --- a/components/assist_ranker/predictor_config_definitions.cc +++ b/components/assist_ranker/predictor_config_definitions.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "components/assist_ranker/predictor_config_definitions.h" +#include "components/assist_ranker/base_predictor.h" namespace assist_ranker { @@ -28,6 +29,15 @@ return kContextualSearchRankerUrl; } +float GetContextualSearchRankerThresholdFeatureParam() { + static auto* kContextualSearchRankerThreshold = + new base::FeatureParam<double>( + &kContextualSearchRankerQuery, + "contextual-search-ranker-predict-threshold", + kNoPredictThresholdReplacement); + return static_cast<float>(kContextualSearchRankerThreshold->Get()); +} + // NOTE: This list needs to be kept in sync with tools/metrics/ukm/ukm.xml! // Only features within this list will be logged to UKM. // TODO(chrome-ranker-team) Deprecate the whitelist once it is available through @@ -77,7 +87,8 @@ kContextualSearchModelName, kContextualSearchLoggingName, kContextualSearchUmaPrefixName, LOG_UKM, GetContextualSearchFeatureWhitelist(), &kContextualSearchRankerQuery, - GetContextualSearchRankerUrlFeatureParam())); + GetContextualSearchRankerUrlFeatureParam(), + GetContextualSearchRankerThresholdFeatureParam())); return kContextualSearchPredictorConfig; } #endif // OS_ANDROID
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index 0cb575f8..76068b4 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -673,6 +673,20 @@ password_generation_agent_ = generation_agent; } +PasswordAutofillAgent::FormStructureInfo::FormStructureInfo() = default; + +PasswordAutofillAgent::FormStructureInfo::FormStructureInfo( + const FormStructureInfo& other) = default; + +PasswordAutofillAgent::FormStructureInfo::FormStructureInfo( + FormStructureInfo&& other) = default; + +PasswordAutofillAgent::FormStructureInfo::~FormStructureInfo() = default; + +PasswordAutofillAgent::FormStructureInfo& +PasswordAutofillAgent::FormStructureInfo::operator=( + PasswordAutofillAgent::FormStructureInfo&& other) = default; + PasswordAutofillAgent::FocusStateNotifier::FocusStateNotifier( PasswordAutofillAgent* agent) : was_fillable_(false), was_password_field_(false), agent_(agent) {} @@ -1183,9 +1197,11 @@ if (logger) logger->LogPasswordForm(Logger::STRING_FORM_IS_PASSWORD, *password_form); - const FormData& form_data = password_form->form_data; - if (only_visible || WasFormStructureChanged(form_data)) { - forms_structure_cache_[form_data.unique_renderer_id] = form_data; + FormStructureInfo form_structure_info = + ExtractFormStructureInfo(password_form->form_data); + if (only_visible || WasFormStructureChanged(form_structure_info)) { + forms_structure_cache_[form_structure_info.unique_renderer_id] = + std::move(form_structure_info); password_forms.push_back(std::move(*password_form)); continue; @@ -2030,23 +2046,42 @@ last_supplied_password_info_iter_ = web_input_to_password_info_.begin(); } -bool PasswordAutofillAgent::WasFormStructureChanged( - const FormData& form_data) const { - if (form_data.unique_renderer_id == FormData::kNotSetFormRendererId) - return true; - - auto cached_form = forms_structure_cache_.find(form_data.unique_renderer_id); - if (cached_form == forms_structure_cache_.end()) - return true; - - const FormData& cached_form_data = cached_form->second; - - if (form_data.fields.size() != cached_form_data.fields.size()) - return true; +PasswordAutofillAgent::FormStructureInfo +PasswordAutofillAgent::ExtractFormStructureInfo(const FormData& form_data) { + FormStructureInfo result; + result.unique_renderer_id = form_data.unique_renderer_id; + result.fields.resize(form_data.fields.size()); for (size_t i = 0; i < form_data.fields.size(); ++i) { const FormFieldData& form_field = form_data.fields[i]; - const FormFieldData& cached_form_field = cached_form_data.fields[i]; + + FormFieldInfo& field_info = result.fields[i]; + field_info.unique_renderer_id = form_field.unique_renderer_id; + field_info.form_control_type = form_field.form_control_type; + field_info.autocomplete_attribute = form_field.autocomplete_attribute; + field_info.is_focusable = form_field.is_focusable; + } + + return result; +} + +bool PasswordAutofillAgent::WasFormStructureChanged( + const FormStructureInfo& form_info) const { + if (form_info.unique_renderer_id == FormData::kNotSetFormRendererId) + return true; + + auto cached_form = forms_structure_cache_.find(form_info.unique_renderer_id); + if (cached_form == forms_structure_cache_.end()) + return true; + + const FormStructureInfo& cached_form_info = cached_form->second; + + if (form_info.fields.size() != cached_form_info.fields.size()) + return true; + + for (size_t i = 0; i < form_info.fields.size(); ++i) { + const FormFieldInfo& form_field = form_info.fields[i]; + const FormFieldInfo& cached_form_field = cached_form_info.fields[i]; if (form_field.unique_renderer_id != cached_form_field.unique_renderer_id) return true;
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h index 668a37f3..f4f300a9 100644 --- a/components/autofill/content/renderer/password_autofill_agent.h +++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -221,6 +221,27 @@ using PasswordToLoginMap = std::map<blink::WebInputElement, blink::WebInputElement>; + // Stores information about form field structure. + struct FormFieldInfo { + uint32_t unique_renderer_id = FormFieldData::kNotSetFormControlRendererId; + std::string form_control_type; + std::string autocomplete_attribute; + bool is_focusable = false; + }; + + // Stores information about form structure. + struct FormStructureInfo { + FormStructureInfo(); + FormStructureInfo(const FormStructureInfo& other); + FormStructureInfo(FormStructureInfo&& other); + ~FormStructureInfo(); + + FormStructureInfo& operator=(FormStructureInfo&& other); + + uint32_t unique_renderer_id = FormData::kNotSetFormRendererId; + std::vector<FormFieldInfo> fields; + }; + // This class ensures that the driver will only receive relevant signals by // caching the parameters of the last message sent to the driver. class FocusStateNotifier { @@ -386,9 +407,11 @@ // |form_data|. void MaybeStoreFallbackData(const PasswordFormFillData& form_data); + // Extracts information about form structure. + static FormStructureInfo ExtractFormStructureInfo(const FormData& form_data); // Checks whether the form structure (amount of elements, element types etc) // was changed. - bool WasFormStructureChanged(const FormData& form_data) const; + bool WasFormStructureChanged(const FormStructureInfo& form_data) const; // Tries to restore |control_elements| values with cached values. void TryFixAutofilledForm( std::vector<blink::WebFormControlElement>* control_elements) const; @@ -469,7 +492,7 @@ // Keeps forms structure (amount of elements, element types etc). // TODO(crbug/898109): It's too expensive to keep the whole FormData // structure. Replace FormData with a smaller structure. - std::map<unsigned /*unique renderer element id*/, FormData> + std::map<unsigned /*unique renderer element id*/, FormStructureInfo> forms_structure_cache_; DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgent); };
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc index 54dc7c5..0d85d9a 100644 --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -85,6 +85,8 @@ const char kDefaultAutofillServerURL[] = "https://clients1.google.com/tbproxy/af/"; +// Header for API key. +constexpr char kGoogApiKey[] = "X-Goog-Api-Key"; // Header to get base64 encoded serialized proto from API for safety. constexpr char kGoogEncodeResponseIfExecutable[] = "X-Goog-Encode-Response-If-Executable"; @@ -612,9 +614,6 @@ // Add the query parameter to set the response format to a serialized proto. url = net::AppendQueryParameter(url, "alt", "proto"); - // Add the API key query parameter. - if (!api_key_.empty()) - url = net::AppendQueryParameter(url, "key", api_key_); // Determine the HTTP method that should be used. std::string method = @@ -654,6 +653,9 @@ // Encode response serialized proto in base64 for safety. resource_request->headers.SetHeader(kGoogEncodeResponseIfExecutable, "base64"); + // Put API key in request's header if there is. + if (!api_key_.empty()) + resource_request->headers.SetHeader(kGoogApiKey, api_key_); } auto simple_loader = network::SimpleURLLoader::Create(
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc index 61ef55d..9f2ce54 100644 --- a/components/autofill/core/browser/autofill_download_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -495,8 +495,12 @@ const std::string expected_url = { "https://clients1.google.com/v1/pages/" "Chc2LjEuMTcxNS4xNDQyL2VuIChHR0xMKRIWEgkNeuFP4BIAGgASCQ2cTkrQEgAaAA==?" - "alt=proto&key=dummykey"}; - EXPECT_THAT(request->request.url, expected_url); + "alt=proto"}; + EXPECT_EQ(request->request.url, expected_url); + std::string api_key_header_value; + EXPECT_TRUE(request->request.headers.GetHeader("X-Goog-Api-Key", + &api_key_header_value)); + EXPECT_EQ(api_key_header_value, "dummykey"); test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList( request, "dummy response"); @@ -558,8 +562,12 @@ // default one used by the download manager. Request upload data is in the // payload when uploading. const std::string expected_url = - "https://clients1.google.com/v1/forms:vote?alt=proto&key=dummykey"; - EXPECT_THAT(request->request.url, expected_url); + "https://clients1.google.com/v1/forms:vote?alt=proto"; + EXPECT_EQ(request->request.url, expected_url); + std::string api_key_header_value; + EXPECT_TRUE(request->request.headers.GetHeader("X-Goog-Api-Key", + &api_key_header_value)); + EXPECT_EQ(api_key_header_value, "dummykey"); // Assert some of the fields within the uploaded proto to make sure it was // filled with something else than default data.
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc index a1b0089..9f3e961c 100644 --- a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc +++ b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
@@ -75,7 +75,7 @@ // DEPRECATED: the field `keycode' used to contain a single character to // input as text. Since there is no easy way to convert keycodes to text, // this field is now deprecated and only works for US-ASCII characters. - // You should use the `key' field instead. + // You should use the `keyboard_input' field instead. if (key_field.keycode() < 128) { // US-ASCII delegate->SendKeyboardInput( selector, std::string(1, char(key_field.keycode())),
diff --git a/components/autofill_assistant/browser/batch_element_checker.h b/components/autofill_assistant/browser/batch_element_checker.h index 58afd03..aaa91ed 100644 --- a/components/autofill_assistant/browser/batch_element_checker.h +++ b/components/autofill_assistant/browser/batch_element_checker.h
@@ -93,6 +93,10 @@ // |try_done| or |all_done| can delete their calling BatchElementChecker to // interrupt any future checks. If |try_done| deletes BatchElementChecker, // |all_done| will never be called. + // + // Sync |try_done| and |all_done| can be called after the element checker has + // been deleted, they should always be called with callbacks that use a weak + // ptr instead of Unretained(this), even from objects that own the checker. void Run(const base::TimeDelta& duration, base::RepeatingCallback<void()> try_done, base::OnceCallback<void()> all_done);
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index 3bc8872..cc0b185 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -115,11 +115,11 @@ client_(std::move(client)), web_controller_(std::move(web_controller)), service_(std::move(service)), - script_tracker_(std::make_unique<ScriptTracker>(/* delegate= */ this, - /* listener= */ this)), parameters_(std::move(parameters)), memory_(std::make_unique<ClientMemory>()), touchable_element_area_(web_controller_.get()), + script_tracker_(std::make_unique<ScriptTracker>(/* delegate= */ this, + /* listener= */ this)), weak_ptr_factory_(this) { DCHECK(parameters_);
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h index 57379f9..9f7a982 100644 --- a/components/autofill_assistant/browser/controller.h +++ b/components/autofill_assistant/browser/controller.h
@@ -132,12 +132,11 @@ std::unique_ptr<Client> client_; std::unique_ptr<WebController> web_controller_; std::unique_ptr<Service> service_; - std::unique_ptr<ScriptTracker> script_tracker_; std::unique_ptr<std::map<std::string, std::string>> parameters_; + std::unique_ptr<ClientMemory> memory_; // Domain of the last URL the controller requested scripts from. std::string script_domain_; - std::unique_ptr<ClientMemory> memory_; bool allow_autostart_ = true; // Whether a task for periodic checks is scheduled. @@ -162,6 +161,11 @@ // Flag indicates whether it is ready to fetch and execute scripts. bool started_ = false; + // Tracks scripts and script execution. It's kept at the end, as it tend to + // depend on everything the controller support, through script and script + // actions. + std::unique_ptr<ScriptTracker> script_tracker_; + base::WeakPtrFactory<Controller> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(Controller);
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc index 580641c..ab9abd2c 100644 --- a/components/autofill_assistant/browser/script_executor.cc +++ b/components/autofill_assistant/browser/script_executor.cc
@@ -100,7 +100,7 @@ wait_with_interrupts_ = std::make_unique<WaitWithInterrupts>( this, max_wait_time, kVisibilityCheck, selector, base::BindOnce(&ScriptExecutor::OnWaitForElementVisible, - base::Unretained(this), std::move(callback))); + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); wait_with_interrupts_->Run(); } @@ -479,7 +479,8 @@ check_type_(check_type), selector_(selector), callback_(std::move(callback)), - element_found_(false) {} + element_found_(false), + weak_ptr_factory_(this) {} ScriptExecutor::WaitWithInterrupts::~WaitWithInterrupts() = default; @@ -500,17 +501,18 @@ batch_element_checker_.get(), main_script_->delegate_->GetParameters(), *main_script_->scripts_state_, base::BindOnce(&WaitWithInterrupts::OnPreconditionCheckDone, - base::Unretained(this), base::Unretained(interrupt))); + weak_ptr_factory_.GetWeakPtr(), + base::Unretained(interrupt))); } + // The base::Unretained(this) above are safe, since the pointers belong to the + // main script, which own this instance. batch_element_checker_->Run( max_wait_time_, base::BindRepeating(&WaitWithInterrupts::OnTryDone, - base::Unretained(this)), - base::BindOnce(&WaitWithInterrupts::OnAllDone, base::Unretained(this))); - - // base::Unretained(this) above is safe because batch_element_checker_ belongs - // to this. + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&WaitWithInterrupts::OnAllDone, + weak_ptr_factory_.GetWeakPtr())); } void ScriptExecutor::WaitWithInterrupts::OnServerPayloadChanged(
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h index d36cda8..ed79fc2 100644 --- a/components/autofill_assistant/browser/script_executor.h +++ b/components/autofill_assistant/browser/script_executor.h
@@ -230,6 +230,8 @@ // The status message that was displayed when the interrupt started. std::string pre_interrupt_status_; + base::WeakPtrFactory<WaitWithInterrupts> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(WaitWithInterrupts); }; friend class WaitWithInterrupts;
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index 2c31f30..2d1656b 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -579,10 +579,9 @@ string text = 1; // DEPRECATED: A single US-ASCII character (e.g., 13 for carriage return). int32 keycode = 2; - // One or multiple UTF-8 characters to input in the form element. In - // contrast to |text|, |keyboard_input| is evaluated as if the user had - // tapped the keyboard. This can also be used for control sequences such - // as "\r". + // Text as generated by processing a virtual key code with a keyboard + // layout. This can also be used for keyboard control sequences such + // as "\r" or "\t". string keyboard_input = 3; } }
diff --git a/components/chrome_cleaner/test/BUILD.gn b/components/chrome_cleaner/test/BUILD.gn new file mode 100644 index 0000000..593b2bb --- /dev/null +++ b/components/chrome_cleaner/test/BUILD.gn
@@ -0,0 +1,16 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("test_name_helper") { + testonly = true + + sources = [ + "test_name_helper.h", + ] + + public_deps = [ + "//base:base", + "//testing/gtest", + ] +}
diff --git a/components/chrome_cleaner/test/DEPS b/components/chrome_cleaner/test/DEPS new file mode 100644 index 0000000..a372d9b3 --- /dev/null +++ b/components/chrome_cleaner/test/DEPS
@@ -0,0 +1,5 @@ +# Allow the typemaps to access their dependencies. +include_rules = [ + '+base/strings/string_util.h', + '+testing/gtest/include/gtest/gtest.h', +]
diff --git a/chrome/chrome_cleaner/test/test_name_helper.h b/components/chrome_cleaner/test/test_name_helper.h similarity index 89% rename from chrome/chrome_cleaner/test/test_name_helper.h rename to components/chrome_cleaner/test/test_name_helper.h index a831d448..080e7c8 100644 --- a/chrome/chrome_cleaner/test/test_name_helper.h +++ b/components/chrome_cleaner/test/test_name_helper.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 CHROME_CHROME_CLEANER_TEST_TEST_NAME_HELPER_H_ -#define CHROME_CHROME_CLEANER_TEST_TEST_NAME_HELPER_H_ +#ifndef COMPONENTS_CHROME_CLEANER_TEST_TEST_NAME_HELPER_H_ +#define COMPONENTS_CHROME_CLEANER_TEST_TEST_NAME_HELPER_H_ #include <string> @@ -45,4 +45,4 @@ } // namespace chrome_cleaner -#endif // CHROME_CHROME_CLEANER_TEST_TEST_NAME_HELPER_H_ +#endif // COMPONENTS_CHROME_CLEANER_TEST_TEST_NAME_HELPER_H_
diff --git a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc index 09c3091..d62d00b 100644 --- a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc +++ b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
@@ -10,6 +10,8 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h" +#include "components/data_reduction_proxy/core/common/uma_util.h" +#include "net/base/load_flags.h" namespace net { class HttpRequestHeaders; @@ -34,6 +36,8 @@ url_chain_.clear(); url_chain_.push_back(request->url); request_method_ = request->method; + is_main_frame_ = request->resource_type == content::RESOURCE_TYPE_MAIN_FRAME; + final_load_flags_ = request->load_flags; MaybeSetAcceptTransformHeader( request->url, static_cast<content::ResourceType>(request->resource_type), @@ -115,6 +119,19 @@ } } +void DataReductionProxyURLLoaderThrottle::WillProcessResponse( + const GURL& response_url, + network::ResourceResponseHead* response_head, + bool* defer) { + base::Optional<DataReductionProxyTypeInfo> proxy_info = + manager_->FindConfiguredDataReductionProxy(response_head->proxy_server); + if (!proxy_info || (final_load_flags_ & net::LOAD_BYPASS_PROXY) != 0) + return; + + LogSuccessfulProxyUMAs(proxy_info.value(), response_head->proxy_server, + is_main_frame_); +} + void DataReductionProxyURLLoaderThrottle::MarkProxiesAsBad( const std::vector<net::ProxyServer>& bad_proxies, base::TimeDelta bypass_duration) { @@ -156,6 +173,7 @@ pending_restart_ = false; pending_restart_load_flags_ = 0; + final_load_flags_ |= load_flags; delegate_->RestartWithFlags(load_flags); }
diff --git a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h index d9f9576..4b6032ed 100644 --- a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h +++ b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
@@ -42,6 +42,9 @@ const GURL& response_url, const network::ResourceResponseHead& response_head, bool* defer) override; + void WillProcessResponse(const GURL& response_url, + network::ResourceResponseHead* response_head, + bool* defer) override; private: // Marks |bad_proxies| to be bypassed for |bypass_duration|. Once that action @@ -69,6 +72,12 @@ // Set to true while waiting for OnMarkProxiesAsBadComplete to run. bool waiting_for_mark_proxies_ = false; + + // Whether this throttle is intercepting a main frame request. + bool is_main_frame_ = false; + + // The final load flags used to complete the request. + int final_load_flags_ = 0; }; } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc index ad596bd..e15155f1 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
@@ -12,6 +12,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" +#include "components/data_reduction_proxy/core/common/uma_util.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/base/proxy_server.h" @@ -138,23 +139,9 @@ successful_requests_through_proxy_count_++; NotifyUnavailabilityIfChanged(); - // Report the success counts. - UMA_HISTOGRAM_COUNTS_100( - "DataReductionProxy.SuccessfulRequestCompletionCounts", - proxy_info->proxy_index); - - // It is possible that the scheme of request->proxy_server() is different - // from the scheme of proxy_info.proxy_servers.front(). The former may be set - // to QUIC by the network stack, while the latter may be set to HTTPS. - UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.ProxySchemeUsed", - util::ConvertNetProxySchemeToProxyScheme( - request->proxy_server().scheme()), - PROXY_SCHEME_MAX); - if (request->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) { - UMA_HISTOGRAM_COUNTS_100( - "DataReductionProxy.SuccessfulRequestCompletionCounts.MainFrame", - proxy_info->proxy_index); - } + LogSuccessfulProxyUMAs( + proxy_info.value(), request->proxy_server(), + request->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED); } void DataReductionProxyBypassStats::SetBypassType(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc index 9b44186..acfc90d6 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc
@@ -271,23 +271,6 @@ EstimateOriginalBodySize(request, lofi_decider); } -ProxyScheme ConvertNetProxySchemeToProxyScheme( - net::ProxyServer::Scheme scheme) { - switch (scheme) { - case net::ProxyServer::SCHEME_HTTP: - return PROXY_SCHEME_HTTP; - case net::ProxyServer::SCHEME_HTTPS: - return PROXY_SCHEME_HTTPS; - case net::ProxyServer::SCHEME_QUIC: - return PROXY_SCHEME_QUIC; - case net::ProxyServer::SCHEME_DIRECT: - return PROXY_SCHEME_DIRECT; - default: - NOTREACHED() << scheme; - return PROXY_SCHEME_UNKNOWN; - } -} - const char* GetSiteBreakdownOtherHostName() { return kOtherHostName; }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h index c4addb5..130cce1 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h
@@ -48,16 +48,6 @@ CHROME_QNX, }; -// Scheme of the proxy used. -enum ProxyScheme { - PROXY_SCHEME_UNKNOWN = 0, - PROXY_SCHEME_HTTP, - PROXY_SCHEME_HTTPS, - PROXY_SCHEME_QUIC, - PROXY_SCHEME_DIRECT, - PROXY_SCHEME_MAX -}; - namespace util { // Returns the version of Chromium that is being used, e.g. "1.2.3.4". @@ -119,9 +109,6 @@ int64_t EstimateOriginalReceivedBytes(const net::URLRequest& request, const LoFiDecider* lofi_decider); -// Converts net::ProxyServer::Scheme to type ProxyScheme. -ProxyScheme ConvertNetProxySchemeToProxyScheme(net::ProxyServer::Scheme scheme); - // Returns the hostname used for the other bucket to record datause not scoped // to a page load such as chrome-services traffic, service worker, Downloads. const char* GetSiteBreakdownOtherHostName();
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc index 7c9612ae..00b58f5 100644 --- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc +++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
@@ -14,6 +14,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" +#include "components/data_reduction_proxy/core/common/uma_util.h" #include "components/data_use_measurement/core/data_use_user_data.h" #include "content/public/browser/network_service_instance.h" #include "net/base/load_flags.h" @@ -246,7 +247,7 @@ nullptr /* has_intermediary */)); UMA_HISTOGRAM_ENUMERATION( "DataReductionProxy.WarmupURL.ProxySchemeUsed", - util::ConvertNetProxySchemeToProxyScheme(proxy_server_.scheme()), + ConvertNetProxySchemeToProxyScheme(proxy_server_.scheme()), PROXY_SCHEME_MAX); }
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc b/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc index c66e433..9ad4bc7 100644 --- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc +++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
@@ -21,6 +21,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" +#include "components/data_reduction_proxy/core/common/uma_util.h" #include "net/base/proxy_server.h" #include "net/http/http_status_code.h" #include "net/socket/socket_test_util.h" @@ -214,8 +215,7 @@ "DataReductionProxy.WarmupURL.HasViaHeader", 0, 1); histogram_tester.ExpectUniqueSample( "DataReductionProxy.WarmupURL.ProxySchemeUsed", - util::ConvertNetProxySchemeToProxyScheme(net::ProxyServer::SCHEME_DIRECT), - 1); + ConvertNetProxySchemeToProxyScheme(net::ProxyServer::SCHEME_DIRECT), 1); EXPECT_EQ(1u, warmup_url_fetcher.callback_received_count()); EXPECT_EQ(net::ProxyServer::SCHEME_DIRECT, @@ -268,8 +268,7 @@ "DataReductionProxy.WarmupURL.HasViaHeader", 1, 1); histogram_tester.ExpectUniqueSample( "DataReductionProxy.WarmupURL.ProxySchemeUsed", - util::ConvertNetProxySchemeToProxyScheme(net::ProxyServer::SCHEME_DIRECT), - 1); + ConvertNetProxySchemeToProxyScheme(net::ProxyServer::SCHEME_DIRECT), 1); EXPECT_EQ(1u, warmup_url_fetcher.callback_received_count()); EXPECT_EQ(net::ProxyServer::SCHEME_DIRECT, @@ -321,8 +320,7 @@ "DataReductionProxy.WarmupURL.HasViaHeader", 1, 1); histogram_tester.ExpectUniqueSample( "DataReductionProxy.WarmupURL.ProxySchemeUsed", - util::ConvertNetProxySchemeToProxyScheme(net::ProxyServer::SCHEME_DIRECT), - 1); + ConvertNetProxySchemeToProxyScheme(net::ProxyServer::SCHEME_DIRECT), 1); // The callback should be run. EXPECT_EQ(1u, warmup_url_fetcher.callback_received_count()); @@ -458,8 +456,7 @@ "DataReductionProxy.WarmupURL.HasViaHeader", 1, 1); histogram_tester.ExpectUniqueSample( "DataReductionProxy.WarmupURL.ProxySchemeUsed", - util::ConvertNetProxySchemeToProxyScheme(net::ProxyServer::SCHEME_DIRECT), - 1); + ConvertNetProxySchemeToProxyScheme(net::ProxyServer::SCHEME_DIRECT), 1); EXPECT_EQ(1u, warmup_url_fetcher.callback_received_count()); EXPECT_EQ(net::ProxyServer::SCHEME_DIRECT,
diff --git a/components/data_reduction_proxy/core/common/BUILD.gn b/components/data_reduction_proxy/core/common/BUILD.gn index 637d56a..6e5f685 100644 --- a/components/data_reduction_proxy/core/common/BUILD.gn +++ b/components/data_reduction_proxy/core/common/BUILD.gn
@@ -35,6 +35,8 @@ "lofi_decider.h", "lofi_ui_service.h", "resource_type_provider.h", + "uma_util.cc", + "uma_util.h", ] public_deps = [
diff --git a/components/data_reduction_proxy/core/common/uma_util.cc b/components/data_reduction_proxy/core/common/uma_util.cc new file mode 100644 index 0000000..8911d39 --- /dev/null +++ b/components/data_reduction_proxy/core/common/uma_util.cc
@@ -0,0 +1,51 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/data_reduction_proxy/core/common/uma_util.h" + +#include "base/metrics/histogram_macros.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" + +namespace data_reduction_proxy { + +ProxyScheme ConvertNetProxySchemeToProxyScheme( + net::ProxyServer::Scheme scheme) { + switch (scheme) { + case net::ProxyServer::SCHEME_HTTP: + return PROXY_SCHEME_HTTP; + case net::ProxyServer::SCHEME_HTTPS: + return PROXY_SCHEME_HTTPS; + case net::ProxyServer::SCHEME_QUIC: + return PROXY_SCHEME_QUIC; + case net::ProxyServer::SCHEME_DIRECT: + return PROXY_SCHEME_DIRECT; + default: + NOTREACHED() << scheme; + return PROXY_SCHEME_UNKNOWN; + } +} + +void LogSuccessfulProxyUMAs(const DataReductionProxyTypeInfo& proxy_info, + const net::ProxyServer& proxy_server, + bool is_main_frame) { + // Report the success counts. + UMA_HISTOGRAM_COUNTS_100( + "DataReductionProxy.SuccessfulRequestCompletionCounts", + proxy_info.proxy_index); + + // It is possible that the scheme of request->proxy_server() is different + // from the scheme of proxy_info.proxy_servers.front(). The former may be set + // to QUIC by the network stack, while the latter may be set to HTTPS. + UMA_HISTOGRAM_ENUMERATION( + "DataReductionProxy.ProxySchemeUsed", + ConvertNetProxySchemeToProxyScheme(proxy_server.scheme()), + PROXY_SCHEME_MAX); + if (is_main_frame) { + UMA_HISTOGRAM_COUNTS_100( + "DataReductionProxy.SuccessfulRequestCompletionCounts.MainFrame", + proxy_info.proxy_index); + } +} + +} // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/uma_util.h b/components/data_reduction_proxy/core/common/uma_util.h new file mode 100644 index 0000000..879d4ad --- /dev/null +++ b/components/data_reduction_proxy/core/common/uma_util.h
@@ -0,0 +1,33 @@ +// 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 COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_UMA_UTIL_H_ +#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_UMA_UTIL_H_ + +#include "net/base/proxy_server.h" + +namespace data_reduction_proxy { +struct DataReductionProxyTypeInfo; + +// Scheme of the proxy used. +enum ProxyScheme { + PROXY_SCHEME_UNKNOWN = 0, + PROXY_SCHEME_HTTP, + PROXY_SCHEME_HTTPS, + PROXY_SCHEME_QUIC, + PROXY_SCHEME_DIRECT, + PROXY_SCHEME_MAX +}; + +// Converts net::ProxyServer::Scheme to type ProxyScheme. +ProxyScheme ConvertNetProxySchemeToProxyScheme(net::ProxyServer::Scheme scheme); + +// Logs UMAs for a successful request through a data reduction proxy. +void LogSuccessfulProxyUMAs(const DataReductionProxyTypeInfo& proxy_info, + const net::ProxyServer& proxy_server, + bool is_main_frame); + +} // namespace data_reduction_proxy + +#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_UMA_UTIL_H_
diff --git a/components/dom_distiller/core/distilled_content_store_unittest.cc b/components/dom_distiller/core/distilled_content_store_unittest.cc index 96583b4..f4713932 100644 --- a/components/dom_distiller/core/distilled_content_store_unittest.cc +++ b/components/dom_distiller/core/distilled_content_store_unittest.cc
@@ -7,8 +7,8 @@ #include <utility> #include "base/bind.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "components/dom_distiller/core/article_entry.h" #include "components/dom_distiller/core/proto/distilled_article.pb.h" #include "testing/gtest/include/gtest/gtest.h" @@ -78,7 +78,7 @@ // Tests whether saving and then loading a single article works as expected. TEST_F(InMemoryContentStoreTest, SaveAndLoadSingleArticle) { - base::MessageLoop loop; + base::test::ScopedTaskEnvironment task_environment; const ArticleEntry entry = CreateEntry("test-id", "url1", "url2", "url3"); const DistilledArticleProto stored_proto = CreateDistilledArticleForEntry(entry); @@ -102,7 +102,7 @@ // Tests that loading articles which have never been stored, yields a callback // where success is false. TEST_F(InMemoryContentStoreTest, LoadNonExistentArticle) { - base::MessageLoop loop; + base::test::ScopedTaskEnvironment task_environment; const ArticleEntry entry = CreateEntry("bogus-id", "url1", "url2", "url3"); store_->LoadContent(entry, base::Bind(&InMemoryContentStoreTest::OnLoadCallback, @@ -115,7 +115,7 @@ // of save and store does not matter when the total number of articles does not // exceed |kDefaultMaxNumCachedEntries|. TEST_F(InMemoryContentStoreTest, SaveAndLoadMultipleArticles) { - base::MessageLoop loop; + base::test::ScopedTaskEnvironment task_environment; // Store first article. const ArticleEntry first_entry = CreateEntry("first", "url1", "url2", "url3"); const DistilledArticleProto first_stored_proto = @@ -165,7 +165,7 @@ // Verifies that the content store does not store unlimited number of articles, // but expires the oldest ones when the limit for number of articles is reached. TEST_F(InMemoryContentStoreTest, SaveAndLoadMoreThanMaxArticles) { - base::MessageLoop loop; + base::test::ScopedTaskEnvironment task_environment; // Create a new store with only |kMaxNumArticles| articles as the limit. const int kMaxNumArticles = 3; @@ -246,7 +246,7 @@ // Tests whether saving and then loading a single article works as expected. TEST_F(InMemoryContentStoreTest, LookupArticleByURL) { - base::MessageLoop loop; + base::test::ScopedTaskEnvironment task_environment; const ArticleEntry entry = CreateEntry("test-id", "url1", "url2", "url3"); const DistilledArticleProto stored_proto = CreateDistilledArticleForEntry(entry); @@ -283,7 +283,7 @@ // Verifies that the content store does not store unlimited number of articles, // but expires the oldest ones when the limit for number of articles is reached. TEST_F(InMemoryContentStoreTest, LoadArticleByURLAfterExpungedFromCache) { - base::MessageLoop loop; + base::test::ScopedTaskEnvironment task_environment; // Create a new store with only |kMaxNumArticles| articles as the limit. const int kMaxNumArticles = 1;
diff --git a/components/dom_distiller/core/distiller_unittest.cc b/components/dom_distiller/core/distiller_unittest.cc index de51505..1de5eb92 100644 --- a/components/dom_distiller/core/distiller_unittest.cc +++ b/components/dom_distiller/core/distiller_unittest.cc
@@ -17,11 +17,11 @@ #include "base/bind_helpers.h" #include "base/location.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_current.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" +#include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "components/dom_distiller/core/article_distillation_update.h" @@ -36,11 +36,11 @@ #include "third_party/dom_distiller_js/dom_distiller.pb.h" #include "third_party/dom_distiller_js/dom_distiller_json_converter.h" -using std::vector; using std::string; +using std::vector; +using ::testing::_; using ::testing::Invoke; using ::testing::Return; -using ::testing::_; using dom_distiller::proto::DomDistillerOptions; using dom_distiller::proto::DomDistillerResult; @@ -54,9 +54,8 @@ const size_t kTotalGoodImages = 2; const size_t kTotalImages = 3; // Good images need to be in the front. -const char* kImageURLs[kTotalImages] = {"http://a.com/img1.jpg", - "http://a.com/img2.jpg", - "./bad_url_should_fail"}; +const char* kImageURLs[kTotalImages] = { + "http://a.com/img1.jpg", "http://a.com/img2.jpg", "./bad_url_should_fail"}; const char* kImageData[kTotalImages] = {"abcde", "12345", "VWXYZ"}; const char kDebugLog[] = "Debug Log"; @@ -103,7 +102,7 @@ ~MultipageDistillerData() {} vector<string> page_urls; vector<string> content; - vector<vector<int> > image_ids; + vector<vector<int>> image_ids; // The Javascript values returned by mock distiller. std::vector<std::unique_ptr<base::Value>> distilled_values; @@ -153,8 +152,9 @@ } } -string GenerateNextPageUrl(const std::string& url_prefix, size_t page_num, - size_t pages_size) { +string GenerateNextPageUrl(const std::string& url_prefix, + size_t page_num, + size_t pages_size) { return page_num + 1 < pages_size ? url_prefix + base::NumberToString(page_num + 1) : ""; @@ -176,8 +176,7 @@ base::NumberToString(page_num)); string next_page_url = GenerateNextPageUrl(url_prefix, page_num, pages_size); - string prev_page_url = - GeneratePrevPageUrl(url_prefix, page_num); + string prev_page_url = GeneratePrevPageUrl(url_prefix, page_num); std::unique_ptr<base::Value> distilled_value = CreateDistilledValueReturnedFromJS(kTitle, result->content[page_num], image_ids[page_num], next_page_url, @@ -309,6 +308,8 @@ } protected: + base::test::ScopedTaskEnvironment task_environment_{ + base::test::ScopedTaskEnvironment::MainThreadType::UI}; std::unique_ptr<DistillerImpl> distiller_; std::unique_ptr<DistilledArticleProto> article_proto_; std::vector<ArticleDistillationUpdate> in_sequence_updates_; @@ -359,7 +360,6 @@ } TEST_F(DistillerTest, DistillPage) { - base::MessageLoopForUI loop; std::unique_ptr<base::Value> result = CreateDistilledValueReturnedFromJS(kTitle, kContent, vector<int>(), ""); distiller_.reset( @@ -374,7 +374,6 @@ } TEST_F(DistillerTest, DistillPageWithDebugInfo) { - base::MessageLoopForUI loop; DomDistillerResult dd_result; dd_result.mutable_debug_info()->set_log(kDebugLog); std::unique_ptr<base::Value> result = @@ -393,17 +392,16 @@ } TEST_F(DistillerTest, DistillPageWithTimingInfo) { - base::MessageLoopForUI loop; DomDistillerResult dd_result; dd_result.mutable_timing_info()->set_total_time(1.0); dd_result.mutable_timing_info()->set_markup_parsing_time(2.0); dd_result.mutable_timing_info()->set_document_construction_time(3.0); dd_result.mutable_timing_info()->set_article_processing_time(4.0); dd_result.mutable_timing_info()->set_formatting_time(5.0); - SetTimingEntry( - dd_result.mutable_timing_info()->add_other_times(), "time0", 6.0); - SetTimingEntry( - dd_result.mutable_timing_info()->add_other_times(), "time1", 7.0); + SetTimingEntry(dd_result.mutable_timing_info()->add_other_times(), "time0", + 6.0); + SetTimingEntry(dd_result.mutable_timing_info()->add_other_times(), "time1", + 7.0); std::unique_ptr<base::Value> result = dom_distiller::proto::json::DomDistillerResult::WriteToValue(dd_result); distiller_.reset( @@ -427,7 +425,6 @@ } TEST_F(DistillerTest, DistillPageWithImages) { - base::MessageLoopForUI loop; vector<int> image_indices; image_indices.push_back(0); image_indices.push_back(1); @@ -463,7 +460,6 @@ } TEST_F(DistillerTest, DistillMultiplePages) { - base::MessageLoopForUI loop; const size_t kNumPages = 8; // Add images. @@ -493,7 +489,6 @@ } TEST_F(DistillerTest, DistillLinkLoop) { - base::MessageLoopForUI loop; // Create a loop, the next page is same as the current page. This could // happen if javascript misparses a next page link. std::unique_ptr<base::Value> result = @@ -507,7 +502,6 @@ } TEST_F(DistillerTest, CheckMaxPageLimitExtraPage) { - base::MessageLoopForUI loop; const size_t kMaxPagesInArticle = 10; std::unique_ptr<MultipageDistillerData> distiller_data = CreateMultipageDistillerDataWithoutImages(kMaxPagesInArticle); @@ -538,7 +532,6 @@ } TEST_F(DistillerTest, CheckMaxPageLimitExactLimit) { - base::MessageLoopForUI loop; const size_t kMaxPagesInArticle = 10; std::unique_ptr<MultipageDistillerData> distiller_data = CreateMultipageDistillerDataWithoutImages(kMaxPagesInArticle); @@ -559,7 +552,6 @@ } TEST_F(DistillerTest, SinglePageDistillationFailure) { - base::MessageLoopForUI loop; // To simulate failure return a null value. auto null_value = std::make_unique<base::Value>(); distiller_.reset( @@ -571,7 +563,6 @@ } TEST_F(DistillerTest, MultiplePagesDistillationFailure) { - base::MessageLoopForUI loop; const size_t kNumPages = 8; std::unique_ptr<MultipageDistillerData> distiller_data = CreateMultipageDistillerDataWithoutImages(kNumPages); @@ -597,7 +588,6 @@ } TEST_F(DistillerTest, DistillMultiplePagesFirstEmpty) { - base::MessageLoopForUI loop; const size_t kNumPages = 8; std::unique_ptr<MultipageDistillerData> distiller_data = CreateMultipageDistillerDataWithoutImages(kNumPages); @@ -606,9 +596,10 @@ const size_t empty_page_num = 0; distiller_data->content[empty_page_num] = ""; std::unique_ptr<base::Value> distilled_value = - CreateDistilledValueReturnedFromJS(kTitle, "", vector<int>(), - GenerateNextPageUrl(kURL, empty_page_num, kNumPages), - GeneratePrevPageUrl(kURL, empty_page_num)); + CreateDistilledValueReturnedFromJS( + kTitle, "", vector<int>(), + GenerateNextPageUrl(kURL, empty_page_num, kNumPages), + GeneratePrevPageUrl(kURL, empty_page_num)); // Reset distilled data of the first page. distiller_data->distilled_values.erase( distiller_data->distilled_values.begin() + empty_page_num); @@ -623,12 +614,11 @@ base::RunLoop().RunUntilIdle(); // If the first page has no content, stop fetching the next page. EXPECT_EQ(1, article_proto_->pages_size()); - VerifyArticleProtoMatchesMultipageData( - article_proto_.get(), distiller_data.get(), 1, 1); + VerifyArticleProtoMatchesMultipageData(article_proto_.get(), + distiller_data.get(), 1, 1); } TEST_F(DistillerTest, DistillMultiplePagesSecondEmpty) { - base::MessageLoopForUI loop; const size_t kNumPages = 8; std::unique_ptr<MultipageDistillerData> distiller_data = CreateMultipageDistillerDataWithoutImages(kNumPages); @@ -637,9 +627,10 @@ const size_t empty_page_num = 1; distiller_data->content[empty_page_num] = ""; std::unique_ptr<base::Value> distilled_value = - CreateDistilledValueReturnedFromJS(kTitle, "", vector<int>(), - GenerateNextPageUrl(kURL, empty_page_num, kNumPages), - GeneratePrevPageUrl(kURL, empty_page_num)); + CreateDistilledValueReturnedFromJS( + kTitle, "", vector<int>(), + GenerateNextPageUrl(kURL, empty_page_num, kNumPages), + GeneratePrevPageUrl(kURL, empty_page_num)); // Reset distilled data of the second page. distiller_data->distilled_values.erase( distiller_data->distilled_values.begin() + empty_page_num); @@ -658,7 +649,6 @@ } TEST_F(DistillerTest, DistillPreviousPage) { - base::MessageLoopForUI loop; const size_t kNumPages = 8; // The page number of the article on which distillation starts. @@ -677,7 +667,6 @@ } TEST_F(DistillerTest, IncrementalUpdates) { - base::MessageLoopForUI loop; const size_t kNumPages = 8; // The page number of the article on which distillation starts. @@ -695,12 +684,11 @@ ASSERT_EQ(kNumPages, static_cast<size_t>(article_proto_->pages_size())); EXPECT_EQ(kNumPages, in_sequence_updates_.size()); - VerifyIncrementalUpdatesMatch( - distiller_data.get(), kNumPages, in_sequence_updates_, start_page_num); + VerifyIncrementalUpdatesMatch(distiller_data.get(), kNumPages, + in_sequence_updates_, start_page_num); } TEST_F(DistillerTest, IncrementalUpdatesDoNotDeleteFinalArticle) { - base::MessageLoopForUI loop; const size_t kNumPages = 8; int start_page_num = 3; std::unique_ptr<MultipageDistillerData> distiller_data = @@ -722,7 +710,6 @@ } TEST_F(DistillerTest, DeletingArticleDoesNotInterfereWithUpdates) { - base::MessageLoopForUI loop; const size_t kNumPages = 8; std::unique_ptr<MultipageDistillerData> distiller_data = CreateMultipageDistillerDataWithoutImages(kNumPages); @@ -741,14 +728,14 @@ // Delete the article. article_proto_.reset(); - VerifyIncrementalUpdatesMatch( - distiller_data.get(), kNumPages, in_sequence_updates_, start_page_num); + VerifyIncrementalUpdatesMatch(distiller_data.get(), kNumPages, + in_sequence_updates_, start_page_num); } TEST_F(DistillerTest, CancelWithDelayedImageFetchCallback) { if (!DistillerImpl::DoesFetchImages()) return; - base::MessageLoopForUI loop; + vector<int> image_indices; image_indices.push_back(0); std::unique_ptr<base::Value> distilled_value = @@ -770,15 +757,13 @@ } TEST_F(DistillerTest, CancelWithDelayedJSCallback) { - base::MessageLoopForUI loop; std::unique_ptr<base::Value> distilled_value = CreateDistilledValueReturnedFromJS(kTitle, kContent, vector<int>(), ""); MockDistillerPage* distiller_page = nullptr; distiller_.reset( new DistillerImpl(url_fetcher_factory_, DomDistillerOptions())); - DistillPage(kURL, - CreateMockDistillerPageWithPendingJSCallback(&distiller_page, - GURL(kURL))); + DistillPage(kURL, CreateMockDistillerPageWithPendingJSCallback( + &distiller_page, GURL(kURL))); base::RunLoop().RunUntilIdle(); ASSERT_TRUE(distiller_page);
diff --git a/components/dom_distiller/core/distiller_url_fetcher_unittest.cc b/components/dom_distiller/core/distiller_url_fetcher_unittest.cc index a19e6a0..0d5317409 100644 --- a/components/dom_distiller/core/distiller_url_fetcher_unittest.cc +++ b/components/dom_distiller/core/distiller_url_fetcher_unittest.cc
@@ -5,8 +5,8 @@ #include "components/dom_distiller/core/distiller_url_fetcher.h" #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_utils.h" @@ -14,10 +14,9 @@ #include "url/gurl.h" const char kTestPageA[] = "http://www.a.com/"; -const char kTestPageAResponse[] = { 1, 2, 3, 4, 5, 6, 7 }; +const char kTestPageAResponse[] = {1, 2, 3, 4, 5, 6, 7}; const char kTestPageB[] = "http://www.b.com/"; -const char kTestPageBResponse[] = { 'a', 'b', 'c' }; - +const char kTestPageBResponse[] = {'a', 'b', 'c'}; class DistillerURLFetcherTest : public testing::Test { public: @@ -26,9 +25,7 @@ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)) {} - void FetcherCallback(const std::string& response) { - response_ = response; - } + void FetcherCallback(const std::string& response) { response_ = response; } protected: // testing::Test implementation: @@ -45,17 +42,16 @@ network::URLLoaderCompletionStatus(net::OK)); } - void Fetch(const std::string& url, - const std::string& expected_response) { - base::MessageLoopForUI loop; - url_fetcher_->FetchURL( - url, - base::Bind(&DistillerURLFetcherTest::FetcherCallback, - base::Unretained(this))); + void Fetch(const std::string& url, const std::string& expected_response) { + url_fetcher_->FetchURL(url, + base::Bind(&DistillerURLFetcherTest::FetcherCallback, + base::Unretained(this))); base::RunLoop().RunUntilIdle(); CHECK_EQ(expected_response, response_); } + base::test::ScopedTaskEnvironment task_environment_{ + base::test::ScopedTaskEnvironment::MainThreadType::UI}; std::unique_ptr<dom_distiller::DistillerURLFetcher> url_fetcher_; network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/components/dom_distiller/core/dom_distiller_service_unittest.cc b/components/dom_distiller/core/dom_distiller_service_unittest.cc index 2e2271d4..a61a60e 100644 --- a/components/dom_distiller/core/dom_distiller_service_unittest.cc +++ b/components/dom_distiller/core/dom_distiller_service_unittest.cc
@@ -9,9 +9,9 @@ #include "base/bind.h" #include "base/callback.h" #include "base/containers/hash_tables.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/test/scoped_task_environment.h" #include "components/dom_distiller/core/article_entry.h" #include "components/dom_distiller/core/distilled_page_prefs.h" #include "components/dom_distiller/core/dom_distiller_model.h" @@ -82,7 +82,6 @@ class DomDistillerServiceTest : public testing::Test { public: void SetUp() override { - main_loop_.reset(new base::MessageLoop()); FakeDB<ArticleEntry>* fake_db = new FakeDB<ArticleEntry>(&db_model_); FakeDB<ArticleEntry>::EntryMap store_model; store_ = @@ -106,12 +105,12 @@ } protected: + base::test::ScopedTaskEnvironment task_environment_; // store is owned by service_. DomDistillerStoreInterface* store_; MockDistillerFactory* distiller_factory_; MockDistillerPageFactory* distiller_page_factory_; std::unique_ptr<DomDistillerService> service_; - std::unique_ptr<base::MessageLoop> main_loop_; FakeDB<ArticleEntry>::EntryMap db_model_; };
diff --git a/components/dom_distiller/core/dom_distiller_store_unittest.cc b/components/dom_distiller/core/dom_distiller_store_unittest.cc index ce188a3..92b35c70 100644 --- a/components/dom_distiller/core/dom_distiller_store_unittest.cc +++ b/components/dom_distiller/core/dom_distiller_store_unittest.cc
@@ -13,8 +13,8 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "base/time/time.h" #include "components/dom_distiller/core/article_entry.h" #include "components/dom_distiller/core/dom_distiller_test_util.h" @@ -159,7 +159,7 @@ return data; } - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment task_environment_; EntryMap db_model_; EntryMap sync_model_;
diff --git a/components/dom_distiller/core/task_tracker_unittest.cc b/components/dom_distiller/core/task_tracker_unittest.cc index 5759cfa..da98901e 100644 --- a/components/dom_distiller/core/task_tracker_unittest.cc +++ b/components/dom_distiller/core/task_tracker_unittest.cc
@@ -6,8 +6,8 @@ #include <utility> -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "components/dom_distiller/core/article_distillation_update.h" #include "components/dom_distiller/core/article_entry.h" #include "components/dom_distiller/core/distilled_content_store.h" @@ -61,7 +61,6 @@ class DomDistillerTaskTrackerTest : public testing::Test { public: void SetUp() override { - message_loop_.reset(new base::MessageLoop()); entry_id_ = "id0"; page_0_url_ = GURL("http://www.example.com/1"); page_1_url_ = GURL("http://www.example.com/2"); @@ -78,7 +77,7 @@ } protected: - std::unique_ptr<base::MessageLoop> message_loop_; + base::test::ScopedTaskEnvironment task_environment_; std::string entry_id_; GURL page_0_url_; GURL page_1_url_;
diff --git a/components/exo/display.cc b/components/exo/display.cc index 393a75c..6c5243a 100644 --- a/components/exo/display.cc +++ b/components/exo/display.cc
@@ -7,23 +7,18 @@ #include <iterator> #include <utility> -#include "ash/public/cpp/shell_window_ids.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" -#include "components/exo/client_controlled_shell_surface.h" #include "components/exo/data_device.h" #include "components/exo/file_helper.h" -#include "components/exo/input_method_surface.h" #include "components/exo/input_method_surface_manager.h" #include "components/exo/notification_surface.h" #include "components/exo/notification_surface_manager.h" #include "components/exo/shared_memory.h" -#include "components/exo/shell_surface.h" #include "components/exo/sub_surface.h" #include "components/exo/surface.h" -#include "components/exo/xdg_shell_surface.h" #include "ui/gfx/linux/client_native_pixmap_factory_dmabuf.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/coordinate_conversion.h" @@ -37,26 +32,36 @@ #include "ui/ozone/public/ozone_switches.h" #endif +#if defined(OS_CHROMEOS) +#include "ash/public/cpp/shell_window_ids.h" +#include "components/exo/client_controlled_shell_surface.h" +#include "components/exo/input_method_surface.h" +#include "components/exo/shell_surface.h" +#include "components/exo/xdg_shell_surface.h" +#endif + namespace exo { //////////////////////////////////////////////////////////////////////////////// // Display, public: -Display::Display() : Display(nullptr, nullptr, std::unique_ptr<FileHelper>()) {} +Display::Display() : file_helper_(std::unique_ptr<FileHelper>()) {} +#if defined(OS_CHROMEOS) Display::Display(NotificationSurfaceManager* notification_surface_manager, InputMethodSurfaceManager* input_method_surface_manager, std::unique_ptr<FileHelper> file_helper) - : notification_surface_manager_(notification_surface_manager), - input_method_surface_manager_(input_method_surface_manager), - file_helper_(std::move(file_helper)) + : file_helper_(std::move(file_helper)) #if defined(USE_OZONE) , client_native_pixmap_factory_( gfx::CreateClientNativePixmapFactoryDmabuf()) -#endif +#endif // defined(USE_OZONE) { + notification_surface_manager_ = notification_surface_manager; + input_method_surface_manager_ = input_method_surface_manager; } +#endif // defined(OS_CHROMEOS) Display::~Display() {} @@ -118,8 +123,9 @@ GL_COMMANDS_COMPLETED_CHROMIUM, use_zero_copy, is_overlay_candidate, y_invert); } -#endif +#endif // defined(USE_OZONE) +#if defined(OS_CHROMEOS) std::unique_ptr<ShellSurface> Display::CreateShellSurface(Surface* surface) { TRACE_EVENT1("exo", "Display::CreateShellSurface", "surface", surface->AsTracedValue()); @@ -171,24 +177,6 @@ return shell_surface; } -std::unique_ptr<SubSurface> Display::CreateSubSurface(Surface* surface, - Surface* parent) { - TRACE_EVENT2("exo", "Display::CreateSubSurface", "surface", - surface->AsTracedValue(), "parent", parent->AsTracedValue()); - - if (surface->window()->Contains(parent->window())) { - DLOG(ERROR) << "Parent is contained within surface's hierarchy"; - return nullptr; - } - - if (surface->HasSurfaceDelegate()) { - DLOG(ERROR) << "Surface has already been assigned a role"; - return nullptr; - } - - return std::make_unique<SubSurface>(surface, parent); -} - std::unique_ptr<NotificationSurface> Display::CreateNotificationSurface( Surface* surface, const std::string& notification_key) { @@ -205,11 +193,6 @@ surface, notification_key); } -std::unique_ptr<DataDevice> Display::CreateDataDevice( - DataDeviceDelegate* delegate) { - return std::make_unique<DataDevice>(delegate, &seat_, file_helper_.get()); -} - std::unique_ptr<InputMethodSurface> Display::CreateInputMethodSurface( Surface* surface, double default_device_scale_factor) { @@ -229,5 +212,29 @@ return std::make_unique<InputMethodSurface>( input_method_surface_manager_, surface, default_device_scale_factor); } +#endif // defined(OS_CHROMEOS) + +std::unique_ptr<SubSurface> Display::CreateSubSurface(Surface* surface, + Surface* parent) { + TRACE_EVENT2("exo", "Display::CreateSubSurface", "surface", + surface->AsTracedValue(), "parent", parent->AsTracedValue()); + + if (surface->window()->Contains(parent->window())) { + DLOG(ERROR) << "Parent is contained within surface's hierarchy"; + return nullptr; + } + + if (surface->HasSurfaceDelegate()) { + DLOG(ERROR) << "Surface has already been assigned a role"; + return nullptr; + } + + return std::make_unique<SubSurface>(surface, parent); +} + +std::unique_ptr<DataDevice> Display::CreateDataDevice( + DataDeviceDelegate* delegate) { + return std::make_unique<DataDevice>(delegate, &seat_, file_helper_.get()); +} } // namespace exo
diff --git a/components/exo/display.h b/components/exo/display.h index bb749ab5..a1fa2d5 100644 --- a/components/exo/display.h +++ b/components/exo/display.h
@@ -30,15 +30,18 @@ class DataDevice; class DataDeviceDelegate; class FileHelper; -class InputMethodSurface; class InputMethodSurfaceManager; class NotificationSurface; class NotificationSurfaceManager; class SharedMemory; -class ShellSurface; class SubSurface; class Surface; + +#if defined(OS_CHROMEOS) +class InputMethodSurface; +class ShellSurface; class XdgShellSurface; +#endif #if defined(USE_OZONE) class Buffer; @@ -50,9 +53,13 @@ class Display { public: Display(); + +#if defined(OS_CHROMEOS) Display(NotificationSurfaceManager* notification_surface_manager, InputMethodSurfaceManager* input_method_surface_manager, std::unique_ptr<FileHelper> file_helper); +#endif // defined(OS_CHROMEOS) + ~Display(); // Creates a new surface. @@ -71,8 +78,9 @@ const std::vector<gfx::NativePixmapPlane>& planes, bool y_invert, std::vector<base::ScopedFD>&& fds); -#endif +#endif // defined(USE_OZONE) +#if defined(OS_CHROMEOS) // Creates a shell surface for an existing surface. std::unique_ptr<ShellSurface> CreateShellSurface(Surface* surface); @@ -86,36 +94,40 @@ int container, double default_device_scale_factor); - // Creates a sub-surface for an existing surface. The sub-surface will be - // a child of |parent|. - std::unique_ptr<SubSurface> CreateSubSurface(Surface* surface, - Surface* parent); - // Creates a notification surface for a surface and notification id. std::unique_ptr<NotificationSurface> CreateNotificationSurface( Surface* surface, const std::string& notification_key); - // Creates a data device for a |delegate|. - std::unique_ptr<DataDevice> CreateDataDevice(DataDeviceDelegate* delegate); - // Creates a input method surface for a surface. std::unique_ptr<InputMethodSurface> CreateInputMethodSurface( Surface* surface, double default_device_scale_factor); +#endif // defined(OS_CHROMEOS) + + // Creates a sub-surface for an existing surface. The sub-surface will be + // a child of |parent|. + std::unique_ptr<SubSurface> CreateSubSurface(Surface* surface, + Surface* parent); + + // Creates a data device for a |delegate|. + std::unique_ptr<DataDevice> CreateDataDevice(DataDeviceDelegate* delegate); // Obtains seat instance. Seat* seat() { return &seat_; } private: - NotificationSurfaceManager* const notification_surface_manager_; - InputMethodSurfaceManager* const input_method_surface_manager_; +#if defined(OS_CHROMEOS) + NotificationSurfaceManager* notification_surface_manager_ = nullptr; + InputMethodSurfaceManager* input_method_surface_manager_ = nullptr; +#endif // defined(OS_CHROMEOS) + std::unique_ptr<FileHelper> file_helper_; Seat seat_; #if defined(USE_OZONE) std::unique_ptr<gfx::ClientNativePixmapFactory> client_native_pixmap_factory_; -#endif +#endif // defined(USE_OZONE) DISALLOW_COPY_AND_ASSIGN(Display); };
diff --git a/components/feed/core/feed_logging_metrics.cc b/components/feed/core/feed_logging_metrics.cc index 3d5ba4b..63263a7 100644 --- a/components/feed/core/feed_logging_metrics.cc +++ b/components/feed/core/feed_logging_metrics.cc
@@ -181,6 +181,10 @@ base::RecordAction(base::UserMetricsAction("Suggestions.Content.Dismissed")); } +void FeedLoggingMetrics::OnSuggestionSwiped() { + base::RecordAction(base::UserMetricsAction("Suggestions.Card.SwipedAway")); +} + void FeedLoggingMetrics::OnSuggestionArticleVisited(base::TimeDelta visit_time, bool return_to_ntp) { base::UmaHistogramLongTimes( @@ -212,6 +216,15 @@ kMaxSuggestionsForArticle + 1); } +void FeedLoggingMetrics::OnSpinnerShown(base::TimeDelta shown_time) { + base::UmaHistogramLongTimes( + "ContentSuggestions.FetchPendingSpinner.VisibleDuration", shown_time); +} + +void FeedLoggingMetrics::ReportScrolledAfterOpen() { + base::RecordAction(base::UserMetricsAction("Suggestions.ScrolledAfterOpen")); +} + void FeedLoggingMetrics::CheckURLVisitedDone(int position, bool visited) { if (visited) { UMA_HISTOGRAM_EXACT_LINEAR("NewTabPage.ContentSuggestions.DismissedVisited",
diff --git a/components/feed/core/feed_logging_metrics.h b/components/feed/core/feed_logging_metrics.h index ae4397d..abb42d1 100644 --- a/components/feed/core/feed_logging_metrics.h +++ b/components/feed/core/feed_logging_metrics.h
@@ -58,6 +58,8 @@ void OnSuggestionDismissed(int position, const GURL& url); + void OnSuggestionSwiped(); + void OnSuggestionArticleVisited(base::TimeDelta visit_time, bool return_to_ntp); @@ -69,6 +71,10 @@ void OnMoreButtonClicked(int position); + void OnSpinnerShown(base::TimeDelta shown_time); + + void ReportScrolledAfterOpen(); + private: void CheckURLVisitedDone(int position, bool visited);
diff --git a/components/offline_pages/core/background/add_request_task_unittest.cc b/components/offline_pages/core/background/add_request_task_unittest.cc index a2dc2ef..2892dde7 100644 --- a/components/offline_pages/core/background/add_request_task_unittest.cc +++ b/components/offline_pages/core/background/add_request_task_unittest.cc
@@ -9,9 +9,11 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -86,7 +88,7 @@ TEST_F(AddRequestTaskTest, AddSingleRequest) { InitializeStore(&store_); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time, true); AddRequestTask task(&store_, request_1, @@ -110,7 +112,7 @@ TEST_F(AddRequestTaskTest, AddMultipleRequests) { InitializeStore(&store_); - base::Time creation_time_1 = base::Time::Now(); + base::Time creation_time_1 = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time_1, true); AddRequestTask task(&store_, request_1, @@ -122,7 +124,7 @@ EXPECT_EQ(ItemActionStatus::SUCCESS, last_status()); ClearResults(); - base::Time creation_time_2 = base::Time::Now(); + base::Time creation_time_2 = OfflineClock()->Now(); SavePageRequest request_2(kRequestId2, kUrl2, kClientId2, creation_time_2, true); AddRequestTask task_2(&store_, request_2, @@ -149,7 +151,7 @@ TEST_F(AddRequestTaskTest, AddDuplicateRequest) { InitializeStore(&store_); - base::Time creation_time_1 = base::Time::Now(); + base::Time creation_time_1 = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time_1, true); AddRequestTask task(&store_, request_1, @@ -161,7 +163,7 @@ EXPECT_EQ(ItemActionStatus::SUCCESS, last_status()); ClearResults(); - base::Time creation_time_2 = base::Time::Now(); + base::Time creation_time_2 = OfflineClock()->Now(); // This was has the same request ID. SavePageRequest request_2(kRequestId1, kUrl2, kClientId2, creation_time_2, true);
diff --git a/components/offline_pages/core/background/change_requests_state_task_unittest.cc b/components/offline_pages/core/background/change_requests_state_task_unittest.cc index c81d93a..cb68eb5a 100644 --- a/components/offline_pages/core/background/change_requests_state_task_unittest.cc +++ b/components/offline_pages/core/background/change_requests_state_task_unittest.cc
@@ -9,9 +9,11 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -41,7 +43,7 @@ }; void ChangeRequestsStateTaskTest::AddItemsToStore() { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time, true); store_.AddRequest(request_1,
diff --git a/components/offline_pages/core/background/cleanup_task_unittest.cc b/components/offline_pages/core/background/cleanup_task_unittest.cc index 3c6b494..c6576b1 100644 --- a/components/offline_pages/core/background/cleanup_task_unittest.cc +++ b/components/offline_pages/core/background/cleanup_task_unittest.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/background/request_coordinator_event_logger.h" @@ -18,6 +19,7 @@ #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -159,7 +161,7 @@ } TEST_F(CleanupTaskTest, CleanupExpiredRequest) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); base::Time expired_time = creation_time - base::TimeDelta::FromSeconds( policy()->GetRequestExpirationTimeInSeconds() + 10); @@ -183,7 +185,7 @@ } TEST_F(CleanupTaskTest, CleanupStartCountExceededRequest) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); // Request2 will have an exceeded start count. SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested); @@ -205,7 +207,7 @@ } TEST_F(CleanupTaskTest, CleanupCompletionCountExceededRequest) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); // Request2 will have an exceeded completion count. SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested); @@ -227,7 +229,7 @@ } TEST_F(CleanupTaskTest, IgnoreRequestInProgress) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); // Both requests will have an exceeded completion count. // The first request will be marked as started. SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time,
diff --git a/components/offline_pages/core/background/get_requests_task_unittest.cc b/components/offline_pages/core/background/get_requests_task_unittest.cc index 0f78a3d2..83f1d53 100644 --- a/components/offline_pages/core/background/get_requests_task_unittest.cc +++ b/components/offline_pages/core/background/get_requests_task_unittest.cc
@@ -9,9 +9,11 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -50,13 +52,13 @@ }; void GetRequestsTaskTest::AddItemsToStore(RequestQueueStore* store) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time, true); store->AddRequest(request_1, base::BindOnce(&GetRequestsTaskTest::AddRequestDone, base::Unretained(this))); - creation_time = base::Time::Now(); + creation_time = OfflineClock()->Now(); SavePageRequest request_2(kRequestId2, kUrl2, kClientId2, creation_time, true); store->AddRequest(request_2,
diff --git a/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc index 37db9a4..1688862b 100644 --- a/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc
@@ -9,11 +9,13 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/change_requests_state_task.h" #include "components/offline_pages/core/background/mark_attempt_started_task.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -44,7 +46,7 @@ }; void MarkAttemptAbortedTaskTest::AddItemToStore(RequestQueueStore* store) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time, true); store->AddRequest(request_1,
diff --git a/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc index e458554..a75923e 100644 --- a/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc
@@ -8,9 +8,11 @@ #include <utility> #include "base/bind.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -37,10 +39,10 @@ }; void MarkAttemptCompletedTaskTest::AddStartedItemToStore() { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time, true); - request_1.MarkAttemptStarted(base::Time::Now()); + request_1.MarkAttemptStarted(OfflineClock()->Now()); store_.AddRequest( request_1, base::BindOnce(&MarkAttemptCompletedTaskTest::AddRequestDone, base::Unretained(this)));
diff --git a/components/offline_pages/core/background/mark_attempt_deferred_task.cc b/components/offline_pages/core/background/mark_attempt_deferred_task.cc index 3023d3a..ca2786e 100644 --- a/components/offline_pages/core/background/mark_attempt_deferred_task.cc +++ b/components/offline_pages/core/background/mark_attempt_deferred_task.cc
@@ -7,7 +7,9 @@ #include <utility> #include "base/bind.h" +#include "base/time/clock.h" #include "base/time/time.h" +#include "components/offline_pages/core/offline_clock.h" namespace offline_pages { @@ -28,7 +30,7 @@ // It is perfectly fine to reuse the read_result.updated_items collection, as // it is owned by this callback and will be destroyed when out of scope. - read_result.updated_items[0].MarkAttemptDeferred(base::Time::Now()); + read_result.updated_items[0].MarkAttemptDeferred(OfflineClock()->Now()); store()->UpdateRequests( read_result.updated_items, base::BindOnce(&MarkAttemptDeferredTask::CompleteWithResult,
diff --git a/components/offline_pages/core/background/mark_attempt_started_task.cc b/components/offline_pages/core/background/mark_attempt_started_task.cc index 5067348..3d702fe5 100644 --- a/components/offline_pages/core/background/mark_attempt_started_task.cc +++ b/components/offline_pages/core/background/mark_attempt_started_task.cc
@@ -7,7 +7,9 @@ #include <utility> #include "base/bind.h" +#include "base/time/clock.h" #include "base/time/time.h" +#include "components/offline_pages/core/offline_clock.h" namespace offline_pages { @@ -28,7 +30,7 @@ // It is perfectly fine to reuse the read_result.updated_items collection, as // it is owned by this callback and will be destroyed when out of scope. - read_result.updated_items[0].MarkAttemptStarted(base::Time::Now()); + read_result.updated_items[0].MarkAttemptStarted(OfflineClock()->Now()); store()->UpdateRequests( read_result.updated_items, base::BindOnce(&MarkAttemptStartedTask::CompleteWithResult,
diff --git a/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc index 92fab85b..12b3ab7 100644 --- a/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc
@@ -9,9 +9,11 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -38,7 +40,7 @@ }; void MarkAttemptStartedTaskTest::AddItemToStore() { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time, true); store_.AddRequest(request_1, @@ -83,7 +85,7 @@ base::Unretained(this))); // Current time for verification. - base::Time before_time = base::Time::Now(); + base::Time before_time = OfflineClock()->Now(); task.Run(); PumpLoop(); ASSERT_TRUE(last_result()); @@ -94,7 +96,7 @@ EXPECT_EQ(1UL, last_result()->updated_items.size()); EXPECT_LE(before_time, last_result()->updated_items.at(0).last_attempt_time()); - EXPECT_GE(base::Time::Now(), + EXPECT_GE(OfflineClock()->Now(), last_result()->updated_items.at(0).last_attempt_time()); EXPECT_EQ(1, last_result()->updated_items.at(0).started_attempt_count()); EXPECT_EQ(SavePageRequest::RequestState::OFFLINING,
diff --git a/components/offline_pages/core/background/offliner_policy_utils.cc b/components/offline_pages/core/background/offliner_policy_utils.cc index a9383f24..2ba3e608 100644 --- a/components/offline_pages/core/background/offliner_policy_utils.cc +++ b/components/offline_pages/core/background/offliner_policy_utils.cc
@@ -4,8 +4,10 @@ #include "components/offline_pages/core/background/offliner_policy_utils.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/save_page_request.h" +#include "components/offline_pages/core/offline_clock.h" namespace offline_pages { @@ -17,7 +19,7 @@ DCHECK(request); DCHECK(policy); - if (base::Time::Now() - request->creation_time() >= + if (OfflineClock()->Now() - request->creation_time() >= base::TimeDelta::FromSeconds( policy->GetRequestExpirationTimeInSeconds())) { return RequestExpirationStatus::EXPIRED;
diff --git a/components/offline_pages/core/background/pick_request_task.cc b/components/offline_pages/core/background/pick_request_task.cc index cfda513..02f0dde 100644 --- a/components/offline_pages/core/background/pick_request_task.cc +++ b/components/offline_pages/core/background/pick_request_task.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/logging.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "components/offline_pages/core/background/device_conditions.h" #include "components/offline_pages/core/background/offliner_policy.h" @@ -20,6 +21,7 @@ #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/offline_clock.h" namespace { template <typename T> @@ -137,7 +139,8 @@ if (policy_controller_->GetPolicy(request->client_id().name_space) .defer_background_fetch_while_page_is_active) { if (!request->last_attempt_time().is_null() && - base::Time::Now() - request->last_attempt_time() < kDeferInterval) { + OfflineClock()->Now() - request->last_attempt_time() < + kDeferInterval) { defer_available_time = request->last_attempt_time() + kDeferInterval; continue; }
diff --git a/components/offline_pages/core/background/pick_request_task_unittest.cc b/components/offline_pages/core/background/pick_request_task_unittest.cc index 16ae3d5..945498b 100644 --- a/components/offline_pages/core/background/pick_request_task_unittest.cc +++ b/components/offline_pages/core/background/pick_request_task_unittest.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/containers/circular_deque.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "components/offline_pages/core/background/device_conditions.h" #include "components/offline_pages/core/background/offliner_policy.h" @@ -21,6 +22,7 @@ #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/background/test_request_queue_store.h" #include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -234,7 +236,7 @@ kMaxCompletedTries + 1, kBackgroundProcessingTimeBudgetSeconds)); MakePickRequestTask(); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time, @@ -255,8 +257,8 @@ TEST_F(PickRequestTaskTest, ChooseRequestWithSameRetryCountButEarlier) { base::Time creation_time1 = - base::Time::Now() - base::TimeDelta::FromSeconds(10); - base::Time creation_time2 = base::Time::Now(); + OfflineClock()->Now() - base::TimeDelta::FromSeconds(10); + base::Time creation_time2 = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time1, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time2, @@ -280,8 +282,8 @@ MakePickRequestTask(); base::Time creation_time1 = - base::Time::Now() - base::TimeDelta::FromSeconds(10); - base::Time creation_time2 = base::Time::Now(); + OfflineClock()->Now() - base::TimeDelta::FromSeconds(10); + base::Time creation_time2 = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time1, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time2, @@ -305,7 +307,7 @@ kMaxCompletedTries + 1, kBackgroundProcessingTimeBudgetSeconds)); MakePickRequestTask(); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time, @@ -329,7 +331,7 @@ kMaxCompletedTries + 1, kBackgroundProcessingTimeBudgetSeconds)); MakePickRequestTask(); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time, @@ -354,8 +356,8 @@ MakePickRequestTask(); base::Time creation_time1 = - base::Time::Now() - base::TimeDelta::FromSeconds(10); - base::Time creation_time2 = base::Time::Now(); + OfflineClock()->Now() - base::TimeDelta::FromSeconds(10); + base::Time creation_time2 = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time1, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time2, @@ -372,7 +374,7 @@ } TEST_F(PickRequestTaskTest, ChooseNonExpiredRequest) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); base::Time expired_time = creation_time - base::TimeDelta::FromSeconds( policy_->GetRequestExpirationTimeInSeconds() + 60); @@ -396,8 +398,8 @@ TEST_F(PickRequestTaskTest, ChooseRequestThatHasNotExceededStartLimit) { base::Time creation_time1 = - base::Time::Now() - base::TimeDelta::FromSeconds(1); - base::Time creation_time2 = base::Time::Now(); + OfflineClock()->Now() - base::TimeDelta::FromSeconds(1); + base::Time creation_time2 = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time1, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time2, @@ -422,8 +424,8 @@ TEST_F(PickRequestTaskTest, ChooseRequestThatHasNotExceededCompletionLimit) { base::Time creation_time1 = - base::Time::Now() - base::TimeDelta::FromSeconds(1); - base::Time creation_time2 = base::Time::Now(); + OfflineClock()->Now() - base::TimeDelta::FromSeconds(1); + base::Time creation_time2 = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time1, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time2, @@ -454,7 +456,7 @@ disabled_requests_.insert(kRequestId2); MakePickRequestTask(); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time, @@ -483,7 +485,7 @@ prioritized_requests_.push_back(kRequestId2); MakePickRequestTask(); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested); SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time, @@ -522,7 +524,7 @@ // Making request 1 more attractive to be picked not considering the // prioritizing issues with older creation time, fewer attempt count and it's // earlier in the request queue. - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); base::Time older_creation_time = creation_time - base::TimeDelta::FromMinutes(10); SavePageRequest request1(kRequestId1, kUrl1, kClientId1, older_creation_time,
diff --git a/components/offline_pages/core/background/reconcile_task_unittest.cc b/components/offline_pages/core/background/reconcile_task_unittest.cc index e92b7c3d..240eebe 100644 --- a/components/offline_pages/core/background/reconcile_task_unittest.cc +++ b/components/offline_pages/core/background/reconcile_task_unittest.cc
@@ -10,11 +10,13 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -116,7 +118,7 @@ } TEST_F(ReconcileTaskTest, Reconcile) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); // Request2 will be expired, request1 will be current. SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested); @@ -151,7 +153,7 @@ } TEST_F(ReconcileTaskTest, NothingToReconcile) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); // Request2 will be expired, request1 will be current. SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested);
diff --git a/components/offline_pages/core/background/remove_requests_task_unittest.cc b/components/offline_pages/core/background/remove_requests_task_unittest.cc index b93eae05..be0af62 100644 --- a/components/offline_pages/core/background/remove_requests_task_unittest.cc +++ b/components/offline_pages/core/background/remove_requests_task_unittest.cc
@@ -9,9 +9,11 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -47,7 +49,7 @@ } void RemoveRequestsTaskTest::AddRequestsToStore() { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request_1(kRequestId1, kUrl1, kClientId1, creation_time, true); store_.AddRequest(request_1,
diff --git a/components/offline_pages/core/background/request_coordinator.cc b/components/offline_pages/core/background/request_coordinator.cc index 5dcae9f..086ae2d2 100644 --- a/components/offline_pages/core/background/request_coordinator.cc +++ b/components/offline_pages/core/background/request_coordinator.cc
@@ -15,11 +15,13 @@ #include "base/rand_util.h" #include "base/stl_util.h" #include "base/system/sys_info.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "components/offline_pages/core/background/offliner.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_model.h" @@ -63,7 +65,7 @@ // For successful requests also record time from request to save. if (request_status == Offliner::RequestStatus::SAVED || request_status == Offliner::RequestStatus::SAVED_ON_LAST_RETRY) { - base::TimeDelta duration = base::Time::Now() - request_creation_time; + base::TimeDelta duration = OfflineClock()->Now() - request_creation_time; base::UmaHistogramCustomCounts( AddHistogramSuffix(client_id, "OfflinePages.Background.TimeToSaved"), duration.InSeconds(), kMinDuration.InSeconds(), @@ -98,7 +100,7 @@ histogram_name += ".Svelte"; } - base::TimeDelta duration = base::Time::Now() - request.creation_time(); + base::TimeDelta duration = OfflineClock()->Now() - request.creation_time(); base::UmaHistogramCustomTimes( AddHistogramSuffix(request.client_id(), histogram_name.c_str()), duration, base::TimeDelta::FromMilliseconds(100), base::TimeDelta::FromDays(7), 50); @@ -108,7 +110,7 @@ // Using regular histogram (with dynamic suffix) rather than time-oriented // one to record samples in seconds rather than milliseconds. base::TimeDelta duration = - base::Time::Now() - canceled_request.creation_time(); + OfflineClock()->Now() - canceled_request.creation_time(); base::UmaHistogramCustomCounts( AddHistogramSuffix(canceled_request.client_id(), "OfflinePages.Background.TimeToCanceled"), @@ -259,7 +261,7 @@ // Build a SavePageRequest. offline_pages::SavePageRequest request( id, save_page_later_params.url, save_page_later_params.client_id, - base::Time::Now(), save_page_later_params.user_requested); + OfflineClock()->Now(), save_page_later_params.user_requested); request.set_original_url(save_page_later_params.original_url); request.set_request_origin(save_page_later_params.request_origin); pending_state_updater_.SetPendingState(request); @@ -661,7 +663,7 @@ // Mark the time at which we started processing so we can check our time // budget. - operation_start_time_ = base::Time::Now(); + operation_start_time_ = OfflineClock()->Now(); TryNextRequest(kStartOfProcessing); @@ -775,7 +777,8 @@ // will return to us at the next opportunity to run background tasks. if (connection_type == net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE || - (base::Time::Now() - operation_start_time_) > processing_time_budget) { + (OfflineClock()->Now() - operation_start_time_) > + processing_time_budget) { state_ = RequestCoordinatorState::IDLE; // If we were doing immediate processing, try to start it again @@ -847,7 +850,7 @@ } else if (!available_time.is_null()) { scheduler_->BackupSchedule( GetTriggerConditions(kUserRequest), - (available_time - base::Time::Now()).InSeconds() + + (available_time - OfflineClock()->Now()).InSeconds() + 1 /*Add an extra second to avoid rounding down.*/); }
diff --git a/components/offline_pages/core/background/request_coordinator_unittest.cc b/components/offline_pages/core/background/request_coordinator_unittest.cc index 1abf67dd..28ea3e22 100644 --- a/components/offline_pages/core/background/request_coordinator_unittest.cc +++ b/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -19,6 +19,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "components/offline_items_collection/core/pending_state.h" #include "components/offline_pages/core/background/device_conditions.h" @@ -32,6 +33,7 @@ #include "components/offline_pages/core/background/scheduler.h" #include "components/offline_pages/core/background/scheduler_stub.h" #include "components/offline_pages/core/client_namespace_constants.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_feature.h" #include "services/network/test/test_network_quality_tracker.h" #include "testing/gtest/include/gtest/gtest.h" @@ -470,7 +472,7 @@ offline_pages::SavePageRequest* request) { // Mark request as started and add it to the queue, // then wait for callback to finish. - request->MarkAttemptStarted(base::Time::Now()); + request->MarkAttemptStarted(OfflineClock()->Now()); queue()->AddRequest(*request, base::BindOnce(&RequestCoordinatorTest::AddRequestDone, base::Unretained(this))); @@ -485,7 +487,7 @@ // Mock that coordinator is in actively processing state starting now. SetProcessingStateForTest( RequestCoordinator::ProcessingWindowState::IMMEDIATE_WINDOW); - SetOperationStartTimeForTest(base::Time::Now()); + SetOperationStartTimeForTest(OfflineClock()->Now()); } void RequestCoordinatorTest::SendOfflinerDoneCallback( @@ -496,8 +498,8 @@ } SavePageRequest RequestCoordinatorTest::AddRequest1() { - offline_pages::SavePageRequest request1(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + offline_pages::SavePageRequest request1( + kRequestId1, kUrl1, kClientId1, OfflineClock()->Now(), kUserRequested); queue()->AddRequest(request1, base::BindOnce(&RequestCoordinatorTest::AddRequestDone, base::Unretained(this))); @@ -505,8 +507,8 @@ } SavePageRequest RequestCoordinatorTest::AddRequest2() { - offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2, - base::Time::Now(), kUserRequested); + offline_pages::SavePageRequest request2( + kRequestId2, kUrl2, kClientId2, OfflineClock()->Now(), kUserRequested); queue()->AddRequest(request2, base::BindOnce(&RequestCoordinatorTest::AddRequestDone, base::Unretained(this))); @@ -713,7 +715,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceeded) { // Add a request to the queue, wait for callbacks to finish. offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); // Call the OfflinerDoneCallback to simulate the page being completed, wait @@ -744,7 +746,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceededButLostNetwork) { // Add a request to the queue and set offliner done callback for it. offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); EnableOfflinerCallback(false); @@ -773,7 +775,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) { // Add a request to the queue, wait for callbacks to finish. offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), kUserRequested); request.set_completed_attempt_count(kMaxCompletedTries - 1); SetupForOfflinerDoneCallbackTest(&request); // Stop processing before completing the second request on the queue. @@ -816,7 +818,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoRetryFailure) { // Add a request to the queue, wait for callbacks to finish. offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); EnableOfflinerCallback(false); @@ -859,7 +861,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoNextFailure) { // Add a request to the queue, wait for callbacks to finish. offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); EnableOfflinerCallback(false); @@ -891,7 +893,7 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneForegroundCancel) { // Add a request to the queue, wait for callbacks to finish. offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); // Call the OfflinerDoneCallback to simulate the request failed, wait @@ -1020,8 +1022,8 @@ // Put two requests on the queue - The first is user requested, and // the second is not user requested. AddRequest1(); - offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2, - base::Time::Now(), !kUserRequested); + offline_pages::SavePageRequest request2( + kRequestId2, kUrl2, kClientId2, OfflineClock()->Now(), !kUserRequested); queue()->AddRequest(request2, base::BindOnce(&RequestCoordinatorTest::AddRequestDone, base::Unretained(this))); @@ -1237,7 +1239,7 @@ WatchdogTimeoutForScheduledProcessingNoLastSnapshot) { // Build a request to use with the pre-renderer, and put it on the queue. offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), kUserRequested); // Set request to allow one more completed attempt. int max_tries = coordinator()->policy()->GetMaxCompletedTries(); request.set_completed_attempt_count(max_tries - 1); @@ -1312,7 +1314,8 @@ AddRequest1(); // The second request will have a larger completed attempt count. offline_pages::SavePageRequest request2(kRequestId1 + 1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), + kUserRequested); request2.set_completed_attempt_count(kAttemptCount); queue()->AddRequest(request2, base::BindOnce(&RequestCoordinatorTest::AddRequestDone, @@ -1584,7 +1587,7 @@ TEST_F(RequestCoordinatorTest, SnapshotOnLastTryForScheduledProcessing) { // Build a request to use with the pre-renderer, and put it on the queue. offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, - base::Time::Now(), kUserRequested); + OfflineClock()->Now(), kUserRequested); // Set request to allow one more completed attempt. So that the next try would // be the last retry. int max_tries = coordinator()->policy()->GetMaxCompletedTries();
diff --git a/components/offline_pages/core/background/request_queue_store_unittest.cc b/components/offline_pages/core/background/request_queue_store_unittest.cc index 3f5d328..c448a6d 100644 --- a/components/offline_pages/core/background/request_queue_store_unittest.cc +++ b/components/offline_pages/core/background/request_queue_store_unittest.cc
@@ -13,8 +13,10 @@ #include "base/files/scoped_temp_dir.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/request_queue.h" #include "components/offline_pages/core/background/save_page_request.h" +#include "components/offline_pages/core/offline_clock.h" #include "sql/database.h" #include "sql/statement.h" #include "testing/gtest/include/gtest/gtest.h" @@ -409,7 +411,7 @@ std::unique_ptr<RequestQueueStore> store(this->BuildStore()); this->InitializeStore(store.get()); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request1(kRequestId, kUrl, kClientId, creation_time, kUserRequested); store->AddRequest(request1, @@ -470,7 +472,7 @@ std::unique_ptr<RequestQueueStore> store(this->BuildStore()); this->InitializeStore(store.get()); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); request.set_original_url(kUrl2); @@ -532,7 +534,7 @@ std::unique_ptr<RequestQueueStore> store(this->BuildStore()); this->InitializeStore(store.get()); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest original_request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); store->AddRequest(original_request, @@ -588,7 +590,7 @@ std::unique_ptr<RequestQueueStore> store(this->BuildStore()); this->InitializeStore(store.get()); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request1(kRequestId, kUrl, kClientId, creation_time, kUserRequested); store->AddRequest(request1, @@ -652,7 +654,7 @@ std::unique_ptr<RequestQueueStore> store(this->BuildStore()); this->InitializeStore(store.get()); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest original_request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); store->AddRequest(original_request, @@ -682,7 +684,7 @@ std::unique_ptr<RequestQueueStore> store(BuildStore()); this->InitializeStore(store.get()); - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest original_request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); store->AddRequest(original_request,
diff --git a/components/offline_pages/core/background/request_queue_unittest.cc b/components/offline_pages/core/background/request_queue_unittest.cc index 0ea44f9..c07dd3d 100644 --- a/components/offline_pages/core/background/request_queue_unittest.cc +++ b/components/offline_pages/core/background/request_queue_unittest.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/background/device_conditions.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/request_coordinator.h" @@ -18,6 +19,7 @@ #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/background/test_request_queue_store.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -208,7 +210,7 @@ } TEST_F(RequestQueueTest, AddRequest) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); queue()->AddRequest(request, base::BindOnce(&RequestQueueTest::AddRequestDone, @@ -226,7 +228,7 @@ } TEST_F(RequestQueueTest, RemoveRequest) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); queue()->AddRequest(request, base::BindOnce(&RequestQueueTest::AddRequestDone, @@ -254,7 +256,7 @@ } TEST_F(RequestQueueTest, RemoveSeveralRequests) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); queue()->AddRequest(request, base::BindOnce(&RequestQueueTest::AddRequestDone, @@ -302,7 +304,7 @@ } TEST_F(RequestQueueTest, PauseAndResume) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); queue()->AddRequest(request, base::BindOnce(&RequestQueueTest::AddRequestDone, @@ -371,7 +373,7 @@ // A longer test populating the request queue with more than one item, properly // listing multiple items and removing the right item. TEST_F(RequestQueueTest, MultipleRequestsAddGetRemove) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request1(kRequestId, kUrl, kClientId, creation_time, kUserRequested); queue()->AddRequest(request1, @@ -414,14 +416,14 @@ TEST_F(RequestQueueTest, MarkAttemptStarted) { // First add a request. Retry count will be set to 0. - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); queue()->AddRequest(request, base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); PumpLoop(); - base::Time before_time = base::Time::Now(); + base::Time before_time = OfflineClock()->Now(); // Update the request, ensure it succeeded. queue()->MarkAttemptStarted( kRequestId, base::BindOnce(&RequestQueueTest::UpdateRequestsDone, @@ -434,7 +436,7 @@ EXPECT_EQ(1UL, update_requests_result()->updated_items.size()); EXPECT_LE(before_time, update_requests_result()->updated_items.at(0).last_attempt_time()); - EXPECT_GE(base::Time::Now(), + EXPECT_GE(OfflineClock()->Now(), update_requests_result()->updated_items.at(0).last_attempt_time()); EXPECT_EQ( 1, update_requests_result()->updated_items.at(0).started_attempt_count()); @@ -452,7 +454,7 @@ TEST_F(RequestQueueTest, MarkAttempStartedRequestNotPresent) { // First add a request. Retry count will be set to 0. - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); // This request is never put into the queue. SavePageRequest request1(kRequestId, kUrl, kClientId, creation_time, kUserRequested); @@ -469,7 +471,7 @@ } TEST_F(RequestQueueTest, MarkAttemptAborted) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); queue()->AddRequest(request, base::BindOnce(&RequestQueueTest::AddRequestDone, @@ -500,7 +502,7 @@ TEST_F(RequestQueueTest, MarkAttemptAbortedRequestNotPresent) { // First add a request. Retry count will be set to 0. - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); // This request is never put into the queue. SavePageRequest request1(kRequestId, kUrl, kClientId, creation_time, kUserRequested); @@ -517,7 +519,7 @@ } TEST_F(RequestQueueTest, MarkAttemptCompleted) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); queue()->AddRequest(request, base::BindOnce(&RequestQueueTest::AddRequestDone, @@ -550,7 +552,8 @@ TEST_F(RequestQueueTest, CleanStaleRequests) { // Create a request that is already expired. base::Time creation_time = - base::Time::Now() - base::TimeDelta::FromSeconds(2 * kOneWeekInSeconds); + OfflineClock()->Now() - + base::TimeDelta::FromSeconds(2 * kOneWeekInSeconds); SavePageRequest original_request(kRequestId, kUrl, kClientId, creation_time, kUserRequested);
diff --git a/components/offline_pages/core/background/save_page_request_unittest.cc b/components/offline_pages/core/background/save_page_request_unittest.cc index ab7e722..e285317 100644 --- a/components/offline_pages/core/background/save_page_request_unittest.cc +++ b/components/offline_pages/core/background/save_page_request_unittest.cc
@@ -4,6 +4,8 @@ #include "components/offline_pages/core/background/save_page_request.h" +#include "base/time/clock.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -25,7 +27,7 @@ SavePageRequestTest::~SavePageRequestTest() {} TEST_F(SavePageRequestTest, CreatePendingReqeust) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); request.set_original_url(kUrl2); @@ -43,7 +45,7 @@ } TEST_F(SavePageRequestTest, StartAndCompleteRequest) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested); request.set_request_origin(kRequestOrigin); @@ -77,7 +79,7 @@ } TEST_F(SavePageRequestTest, StartAndAbortRequest) { - base::Time creation_time = base::Time::Now(); + base::Time creation_time = OfflineClock()->Now(); SavePageRequest request(kRequestId, kUrl, kClientId, creation_time, kUserRequested);
diff --git a/components/offline_pages/core/prefetch/prefetch_item.h b/components/offline_pages/core/prefetch/prefetch_item.h index 27e244b..b5ae3dba 100644 --- a/components/offline_pages/core/prefetch/prefetch_item.h +++ b/components/offline_pages/core/prefetch/prefetch_item.h
@@ -103,8 +103,10 @@ // item. It holds a negative value otherwise. int64_t archive_body_length = -1; - // Time when this item was inserted into the store with the URL to be - // prefetched. + // The last time the URL was attempted to be added to the store. Normally this + // is just the time the item was added. If the same URL is added multiple + // times, this is the timestamp of the last time. creation_time + // is used as a proxy for priority. base::Time creation_time; // Time used for the expiration of the item depending on the applicable policy
diff --git a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task.cc b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task.cc index ef51030..942183a 100644 --- a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task.cc +++ b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task.cc
@@ -31,22 +31,26 @@ using Result = AddUniqueUrlsTask::Result; namespace { +struct ItemInfo { + int64_t offline_id; + PrefetchItemState state; +}; -std::map<std::string, std::pair<int64_t, PrefetchItemState>> -FindExistingPrefetchItemsInNamespaceSync(sql::Database* db, - const std::string& name_space) { +std::map<std::string, ItemInfo> FindExistingPrefetchItemsInNamespaceSync( + sql::Database* db, + const std::string& name_space) { static const char kSql[] = "SELECT offline_id, state, requested_url FROM prefetch_items" " WHERE client_namespace = ?"; sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindString(0, name_space); - std::map<std::string, std::pair<int64_t, PrefetchItemState>> result; + std::map<std::string, ItemInfo> result; while (statement.Step()) { - result.emplace( - statement.ColumnString(2), - std::make_pair(statement.ColumnInt64(0), - static_cast<PrefetchItemState>(statement.ColumnInt(1)))); + result.emplace(statement.ColumnString(2), + ItemInfo{.offline_id = statement.ColumnInt64(0), + .state = static_cast<PrefetchItemState>( + statement.ColumnInt(1))}); } return result; @@ -75,6 +79,22 @@ return statement.Run(); } +bool UpdateItemTimeSync(sql::Database* db, + int64_t offline_id, + base::Time now_db_time) { + static const char kSql[] = + "UPDATE prefetch_items SET" + " freshness_time=?,creation_time=?" + " WHERE offline_id=?"; + + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt64(0, store_utils::ToDatabaseTime(now_db_time)); + statement.BindInt64(1, store_utils::ToDatabaseTime(now_db_time)); + statement.BindInt64(2, offline_id); + + return statement.Run(); +} + // Adds new prefetch item entries to the store using the URLs and client IDs // from |candidate_prefetch_urls| and the client's |name_space|. Also cleans up // entries in the Zombie state from the client's |name_space| except for the @@ -88,7 +108,7 @@ if (!transaction.Begin()) return Result::STORE_ERROR; - std::map<std::string, std::pair<int64_t, PrefetchItemState>> existing_items = + std::map<std::string, ItemInfo> existing_items = FindExistingPrefetchItemsInNamespaceSync(db, name_space); int added_row_count = 0; @@ -104,23 +124,26 @@ store_utils::ToDatabaseTime(now))) return Result::STORE_ERROR; // Transaction rollback. added_row_count++; - - // We artificially add a microsecond to ensure that the timestamp is - // different (and guarantee a particular order when sorting by timestamp). - now += base::TimeDelta::FromMicroseconds(1); } else { + // The existing item is still being suggested, update its timestamp (and + // therefore priority). + if (!UpdateItemTimeSync(db, iter->second.offline_id, now)) + return Result::STORE_ERROR; // Transaction rollback. // Removing from the list of existing items if it was requested again, to // prevent it from being removed in the next step. existing_items.erase(iter); } + // We artificially add a microsecond to ensure that the timestamp is + // different (and guarantee a particular order when sorting by timestamp). + now += base::TimeDelta::FromMicroseconds(1); } // Purge remaining zombie IDs. for (const auto& existing_item : existing_items) { - if (existing_item.second.second != PrefetchItemState::ZOMBIE) + if (existing_item.second.state != PrefetchItemState::ZOMBIE) continue; if (!PrefetchStoreUtils::DeletePrefetchItemByOfflineIdSync( - db, existing_item.second.first)) { + db, existing_item.second.offline_id)) { return Result::STORE_ERROR; // Transaction rollback. } }
diff --git a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc index 750814e8..17fb480 100644 --- a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc +++ b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc
@@ -12,12 +12,14 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "components/offline_pages/core/offline_store_utils.h" #include "components/offline_pages/core/prefetch/prefetch_item.h" #include "components/offline_pages/core/prefetch/prefetch_types.h" #include "components/offline_pages/core/prefetch/store/prefetch_store.h" #include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" #include "components/offline_pages/core/prefetch/tasks/prefetch_task_test_base.h" #include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h" +#include "components/offline_pages/core/test_scoped_offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -39,11 +41,19 @@ class AddUniqueUrlsTaskTest : public PrefetchTaskTestBase { public: - AddUniqueUrlsTaskTest(); + AddUniqueUrlsTaskTest() = default; ~AddUniqueUrlsTaskTest() override = default; // Returns all items stored in a map keyed with client id. - std::map<std::string, PrefetchItem> GetAllItems(); + std::map<std::string, PrefetchItem> GetAllItems() { + std::set<PrefetchItem> set; + store_util()->GetAllItems(&set); + + std::map<std::string, PrefetchItem> map; + for (const auto& item : set) + map[item.client_id.id] = item; + return map; + } TestPrefetchDispatcher* dispatcher() { return &dispatcher_; } @@ -51,17 +61,6 @@ TestPrefetchDispatcher dispatcher_; }; -AddUniqueUrlsTaskTest::AddUniqueUrlsTaskTest() {} - -std::map<std::string, PrefetchItem> AddUniqueUrlsTaskTest::GetAllItems() { - std::set<PrefetchItem> set; - store_util()->GetAllItems(&set); - - std::map<std::string, PrefetchItem> map; - for (const auto& item : set) - map[item.client_id.id] = item; - return map; -} TEST_F(AddUniqueUrlsTaskTest, StoreFailure) { store_util()->SimulateInitializationError(); @@ -113,17 +112,24 @@ } TEST_F(AddUniqueUrlsTaskTest, DontAddURLIfItExists) { + TestScopedOfflineClock clock; std::vector<PrefetchURL> urls; urls.push_back(PrefetchURL{kClientId1, kTestURL1, kTestTitle1}); urls.push_back(PrefetchURL{kClientId2, kTestURL2, kTestTitle2}); RunTask(std::make_unique<AddUniqueUrlsTask>(dispatcher(), store(), kTestNamespace, urls)); EXPECT_EQ(1, dispatcher()->task_schedule_count); + std::map<std::string, PrefetchItem> items_before = GetAllItems(); - urls.clear(); - // This PrefetchURL has a duplicate URL, should not be added. - urls.push_back(PrefetchURL{kClientId4, kTestURL1, kTestTitle4}); - urls.push_back(PrefetchURL{kClientId3, kTestURL3, kTestTitle3}); + // Advance time to verify that timestamp of kClientId1 is updated on the next + // task execution. + clock.Advance(base::TimeDelta::FromSeconds(1)); + + urls = { + // This PrefetchURL has a duplicate URL, should not be added. + {kClientId4, kTestURL1, kTestTitle4}, + {kClientId3, kTestURL3, kTestTitle3}, + }; RunTask(std::make_unique<AddUniqueUrlsTask>(dispatcher(), store(), kTestNamespace, urls)); @@ -143,6 +149,12 @@ EXPECT_EQ(kTestURL3, items[kClientId3].url); EXPECT_EQ(kTestNamespace, items[kClientId3].client_id.name_space); EXPECT_EQ(kTestTitle3, items[kClientId3].title); + + // Although kClientId4 was not inserted, it should have resulted in updating + // kClientId1's timestamp. + EXPECT_GT(items[kClientId1].creation_time, + items_before[kClientId1].creation_time); + EXPECT_EQ(items[kClientId1].creation_time, items[kClientId1].freshness_time); } TEST_F(AddUniqueUrlsTaskTest, HandleZombiePrefetchItems) { @@ -158,10 +170,11 @@ EXPECT_EQ(1, store_util()->ZombifyPrefetchItems(kTestNamespace, urls[0].url)); EXPECT_EQ(1, store_util()->ZombifyPrefetchItems(kTestNamespace, urls[1].url)); - urls.clear(); - urls.push_back(PrefetchURL{kClientId1, kTestURL1, kTestTitle1}); - urls.push_back(PrefetchURL{kClientId3, kTestURL3, kTestTitle3}); - urls.push_back(PrefetchURL{kClientId4, kTestURL4, kTestTitle4}); + urls = { + {kClientId1, kTestURL1, kTestTitle1}, + {kClientId3, kTestURL3, kTestTitle3}, + {kClientId4, kTestURL4, kTestTitle4}, + }; // ID-1 is expected to stay in zombie state. // ID-2 is expected to be removed, because it is in zombie state. // ID-3 is still requested, so it is ignored.
diff --git a/components/previews/content/previews_decider_impl.cc b/components/previews/content/previews_decider_impl.cc index 936f4cfc..6332c7bb 100644 --- a/components/previews/content/previews_decider_impl.cc +++ b/components/previews/content/previews_decider_impl.cc
@@ -13,6 +13,7 @@ #include "base/files/file_path.h" #include "base/location.h" #include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/sequenced_task_runner.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" @@ -30,6 +31,8 @@ void LogPreviewsEligibilityReason(PreviewsEligibilityReason status, PreviewsType type) { + UMA_HISTOGRAM_ENUMERATION("Previews.EligibilityReason", status, + PreviewsEligibilityReason::LAST); int32_t max_limit = static_cast<int32_t>(PreviewsEligibilityReason::LAST); base::LinearHistogram::FactoryGet( base::StringPrintf("Previews.EligibilityReason.%s",
diff --git a/components/previews/content/previews_decider_impl_unittest.cc b/components/previews/content/previews_decider_impl_unittest.cc index 5d25b9d..caff62a 100644 --- a/components/previews/content/previews_decider_impl_unittest.cc +++ b/components/previews/content/previews_decider_impl_unittest.cc
@@ -445,6 +445,10 @@ &user_data, GURL("https://www.google.com"), false, PreviewsType::OFFLINE)); histogram_tester.ExpectBucketCount( + "Previews.EligibilityReason", + static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED), + 1); + histogram_tester.ExpectBucketCount( "Previews.EligibilityReason.Offline", static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED), 1); @@ -465,6 +469,10 @@ "Previews.EligibilityReason.Offline", static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED), 2); + histogram_tester.ExpectBucketCount( + "Previews.EligibilityReason", + static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED), + 2); histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0); variations::testing::ClearAllVariationParams(); @@ -507,6 +515,10 @@ "Previews.EligibilityReason.Offline", static_cast<int>(PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE), 1); + histogram_tester.ExpectUniqueSample( + "Previews.EligibilityReason", + static_cast<int>(PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE), + 1); } TEST_F(PreviewsDeciderImplTest, TestAllowLitePageWhenNetworkQualityFast) { @@ -557,6 +569,9 @@ EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart( &user_data, GURL("https://www.google.com"), true, PreviewsType::OFFLINE)); histogram_tester.ExpectUniqueSample( + "Previews.EligibilityReason", + static_cast<int>(PreviewsEligibilityReason::RELOAD_DISALLOWED), 1); + histogram_tester.ExpectUniqueSample( "Previews.EligibilityReason.Offline", static_cast<int>(PreviewsEligibilityReason::RELOAD_DISALLOWED), 1); } @@ -901,6 +916,9 @@ PreviewsType::LITE_PAGE_REDIRECT)); histogram_tester.ExpectUniqueSample( + "Previews.EligibilityReason", + static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1); + histogram_tester.ExpectUniqueSample( "Previews.EligibilityReason.LitePageRedirect", static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1); } @@ -931,6 +949,10 @@ PreviewsType::LITE_PAGE_REDIRECT)); histogram_tester.ExpectBucketCount( + "Previews.EligibilityReason", + static_cast<int>(PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER), + 1); + histogram_tester.ExpectBucketCount( "Previews.EligibilityReason.LitePageRedirect", static_cast<int>(PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER), 1); @@ -963,6 +985,11 @@ &user_data, GURL("https://whitelisted.example.com"), false, PreviewsType::RESOURCE_LOADING_HINTS)); histogram_tester.ExpectUniqueSample( + "Previews.EligibilityReason", + static_cast<int>( + PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER), + 1); + histogram_tester.ExpectUniqueSample( "Previews.EligibilityReason.ResourceLoadingHints", static_cast<int>( PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
diff --git a/components/previews/core/previews_black_list.cc b/components/previews/core/previews_black_list.cc index d718e84..5fbc7a0 100644 --- a/components/previews/core/previews_black_list.cc +++ b/components/previews/core/previews_black_list.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/optional.h" #include "base/strings/stringprintf.h" #include "base/time/clock.h" @@ -95,7 +96,7 @@ bool opt_out, PreviewsType type) { DCHECK(url.has_host()); - + UMA_HISTOGRAM_BOOLEAN("Previews.OptOut.UserOptedOut", opt_out); base::BooleanHistogram::FactoryGet( base::StringPrintf("Previews.OptOut.UserOptedOut.%s", GetStringNameForType(type).c_str()),
diff --git a/components/previews/core/previews_black_list_unittest.cc b/components/previews/core/previews_black_list_unittest.cc index 53909cf..28265e4f 100644 --- a/components/previews/core/previews_black_list_unittest.cc +++ b/components/previews/core/previews_black_list_unittest.cc
@@ -177,9 +177,11 @@ black_list_->AddPreviewNavigation(url, false, PreviewsType::OFFLINE); histogram_tester.ExpectUniqueSample("Previews.OptOut.UserOptedOut.Offline", 0, 1); + histogram_tester.ExpectUniqueSample("Previews.OptOut.UserOptedOut", 0, 1); black_list_->AddPreviewNavigation(url, true, PreviewsType::OFFLINE); histogram_tester.ExpectBucketCount("Previews.OptOut.UserOptedOut.Offline", 1, 1); + histogram_tester.ExpectBucketCount("Previews.OptOut.UserOptedOut", 1, 1); } TEST_F(PreviewsBlackListTest, SessionParams) {
diff --git a/components/renderer_context_menu/context_menu_content_type.h b/components/renderer_context_menu/context_menu_content_type.h index 0cce18f..aef21b4 100644 --- a/components/renderer_context_menu/context_menu_content_type.h +++ b/components/renderer_context_menu/context_menu_content_type.h
@@ -67,7 +67,7 @@ protected: const content::ContextMenuParams& params() const { return params_; } - const content::WebContents* source_web_contents() const { + content::WebContents* source_web_contents() const { return source_web_contents_; }
diff --git a/components/safe_browsing/base_ui_manager.cc b/components/safe_browsing/base_ui_manager.cc index 07506ea9..6c2d4f8 100644 --- a/components/safe_browsing/base_ui_manager.cc +++ b/components/safe_browsing/base_ui_manager.cc
@@ -258,7 +258,7 @@ // users who are not in incognito mode. void BaseUIManager::MaybeReportSafeBrowsingHit( const HitReport& hit_report, - const content::WebContents* web_contents) { + content::WebContents* web_contents) { DCHECK_CURRENTLY_ON(BrowserThread::UI); return; }
diff --git a/components/safe_browsing/base_ui_manager.h b/components/safe_browsing/base_ui_manager.h index b349f00..2321da8a 100644 --- a/components/safe_browsing/base_ui_manager.h +++ b/components/safe_browsing/base_ui_manager.h
@@ -52,7 +52,7 @@ // report if the user has enabled SBER and is not currently in incognito mode. virtual void MaybeReportSafeBrowsingHit( const safe_browsing::HitReport& hit_report, - const content::WebContents* web_contents); + content::WebContents* web_contents); // A convenience wrapper method for IsUrlWhitelistedOrPendingForWebContents. virtual bool IsWhitelisted(const UnsafeResource& resource);
diff --git a/components/safe_browsing/triggers/ad_sampler_trigger.cc b/components/safe_browsing/triggers/ad_sampler_trigger.cc index 0524324..90cba93 100644 --- a/components/safe_browsing/triggers/ad_sampler_trigger.cc +++ b/components/safe_browsing/triggers/ad_sampler_trigger.cc
@@ -166,7 +166,7 @@ void AdSamplerTrigger::CreateAdSampleReport() { SBErrorOptions error_options = - TriggerManager::GetSBErrorDisplayOptions(*prefs_, *web_contents()); + TriggerManager::GetSBErrorDisplayOptions(*prefs_, web_contents()); security_interstitials::UnsafeResource resource; resource.threat_type = SB_THREAT_TYPE_AD_SAMPLE;
diff --git a/components/safe_browsing/triggers/suspicious_site_trigger.cc b/components/safe_browsing/triggers/suspicious_site_trigger.cc index 0f225c8..5b5cd23d 100644 --- a/components/safe_browsing/triggers/suspicious_site_trigger.cc +++ b/components/safe_browsing/triggers/suspicious_site_trigger.cc
@@ -89,7 +89,7 @@ bool SuspiciousSiteTrigger::MaybeStartReport() { SBErrorOptions error_options = - TriggerManager::GetSBErrorDisplayOptions(*prefs_, *web_contents()); + TriggerManager::GetSBErrorDisplayOptions(*prefs_, web_contents()); security_interstitials::UnsafeResource resource; resource.threat_type = SB_THREAT_TYPE_SUSPICIOUS_SITE; @@ -124,7 +124,7 @@ void SuspiciousSiteTrigger::FinishReport() { SBErrorOptions error_options = - TriggerManager::GetSBErrorDisplayOptions(*prefs_, *web_contents()); + TriggerManager::GetSBErrorDisplayOptions(*prefs_, web_contents()); if (trigger_manager_->FinishCollectingThreatDetails( TriggerType::SUSPICIOUS_SITE, web_contents(), base::TimeDelta(), /*did_proceed=*/false, /*num_visits=*/0, error_options)) { @@ -139,7 +139,7 @@ void SuspiciousSiteTrigger::SuspiciousSiteDetectedWhenMonitoring() { DCHECK_EQ(TriggerState::MONITOR_MODE, current_state_); SBErrorOptions error_options = - TriggerManager::GetSBErrorDisplayOptions(*prefs_, *web_contents()); + TriggerManager::GetSBErrorDisplayOptions(*prefs_, web_contents()); TriggerManagerReason reason; if (trigger_manager_->CanStartDataCollectionWithReason( error_options, TriggerType::SUSPICIOUS_SITE, &reason) ||
diff --git a/components/safe_browsing/triggers/trigger_manager.cc b/components/safe_browsing/triggers/trigger_manager.cc index 5d38ce8..d6a0bc9 100644 --- a/components/safe_browsing/triggers/trigger_manager.cc +++ b/components/safe_browsing/triggers/trigger_manager.cc
@@ -74,10 +74,10 @@ // static SBErrorOptions TriggerManager::GetSBErrorDisplayOptions( const PrefService& pref_service, - const content::WebContents& web_contents) { + content::WebContents* web_contents) { return SBErrorOptions(/*is_main_frame_load_blocked=*/false, IsExtendedReportingOptInAllowed(pref_service), - web_contents.GetBrowserContext()->IsOffTheRecord(), + web_contents->GetBrowserContext()->IsOffTheRecord(), IsExtendedReportingEnabled(pref_service), IsExtendedReportingPolicyManaged(pref_service), /*is_proceed_anyway_disabled=*/false,
diff --git a/components/safe_browsing/triggers/trigger_manager.h b/components/safe_browsing/triggers/trigger_manager.h index 1a62749..db26345 100644 --- a/components/safe_browsing/triggers/trigger_manager.h +++ b/components/safe_browsing/triggers/trigger_manager.h
@@ -96,7 +96,7 @@ // |pref_service|. Only the fields needed by TriggerManager will be set. static SBErrorOptions GetSBErrorDisplayOptions( const PrefService& pref_service, - const content::WebContents& web_contents); + content::WebContents* web_contents); // Returns whether data collection can be started for the |trigger_type| based // on the settings specified in |error_display_options| as well as quota.
diff --git a/components/safe_browsing/triggers/trigger_manager_unittest.cc b/components/safe_browsing/triggers/trigger_manager_unittest.cc index 3b03d92..abac318 100644 --- a/components/safe_browsing/triggers/trigger_manager_unittest.cc +++ b/components/safe_browsing/triggers/trigger_manager_unittest.cc
@@ -113,7 +113,7 @@ bool StartCollectingThreatDetails(const TriggerType trigger_type, content::WebContents* web_contents) { SBErrorOptions options = - TriggerManager::GetSBErrorDisplayOptions(pref_service_, *web_contents); + TriggerManager::GetSBErrorDisplayOptions(pref_service_, web_contents); return trigger_manager_.StartCollectingThreatDetails( trigger_type, web_contents, security_interstitials::UnsafeResource(), nullptr, nullptr, options); @@ -129,7 +129,7 @@ EXPECT_CALL(*threat_details, FinishCollection(_, _)).Times(1); } SBErrorOptions options = - TriggerManager::GetSBErrorDisplayOptions(pref_service_, *web_contents); + TriggerManager::GetSBErrorDisplayOptions(pref_service_, web_contents); bool result = trigger_manager_.FinishCollectingThreatDetails( trigger_type, web_contents, base::TimeDelta(), false, 0, options);
diff --git a/components/sessions/content/content_live_tab.cc b/components/sessions/content/content_live_tab.cc index 12a86003..d9d566f 100644 --- a/components/sessions/content/content_live_tab.cc +++ b/components/sessions/content/content_live_tab.cc
@@ -64,7 +64,7 @@ web_contents()); } -const std::string& ContentLiveTab::GetUserAgentOverride() const { +const std::string& ContentLiveTab::GetUserAgentOverride() { return web_contents()->GetUserAgentOverride(); }
diff --git a/components/sessions/content/content_live_tab.h b/components/sessions/content/content_live_tab.h index 5c04ba1..c4ff024 100644 --- a/components/sessions/content/content_live_tab.h +++ b/components/sessions/content/content_live_tab.h
@@ -41,7 +41,7 @@ int GetEntryCount() override; std::unique_ptr<PlatformSpecificTabData> GetPlatformSpecificTabData() override; - const std::string& GetUserAgentOverride() const override; + const std::string& GetUserAgentOverride() override; content::WebContents* web_contents() { return web_contents_; } const content::WebContents* web_contents() const { return web_contents_; }
diff --git a/components/sessions/core/live_tab.h b/components/sessions/core/live_tab.h index 4902199..1ea71f1 100644 --- a/components/sessions/core/live_tab.h +++ b/components/sessions/core/live_tab.h
@@ -33,7 +33,7 @@ virtual std::unique_ptr<PlatformSpecificTabData> GetPlatformSpecificTabData(); // Returns the user agent override, if any. - virtual const std::string& GetUserAgentOverride() const = 0; + virtual const std::string& GetUserAgentOverride() = 0; }; } // namespace sessions
diff --git a/components/sessions/ios/ios_live_tab.h b/components/sessions/ios/ios_live_tab.h index 17b6fe54..14f3d89 100644 --- a/components/sessions/ios/ios_live_tab.h +++ b/components/sessions/ios/ios_live_tab.h
@@ -35,7 +35,7 @@ sessions::SerializedNavigationEntry GetEntryAtIndex(int index) override; sessions::SerializedNavigationEntry GetPendingEntry() override; int GetEntryCount() override; - const std::string& GetUserAgentOverride() const override; + const std::string& GetUserAgentOverride() override; web::WebState* web_state() { return web_state_; } const web::WebState* web_state() const { return web_state_; }
diff --git a/components/sessions/ios/ios_live_tab.mm b/components/sessions/ios/ios_live_tab.mm index 0d0b1c90..9a50135 100644 --- a/components/sessions/ios/ios_live_tab.mm +++ b/components/sessions/ios/ios_live_tab.mm
@@ -55,7 +55,7 @@ return navigation_manager()->GetItemCount(); } -const std::string& IOSLiveTab::GetUserAgentOverride() const { +const std::string& IOSLiveTab::GetUserAgentOverride() { // Dynamic user agent overrides are not supported on iOS. return user_agent_override_; }
diff --git a/components/zoom/zoom_controller.cc b/components/zoom/zoom_controller.cc index 94fc93bd..20ce115 100644 --- a/components/zoom/zoom_controller.cc +++ b/components/zoom/zoom_controller.cc
@@ -24,7 +24,7 @@ namespace zoom { double ZoomController::GetZoomLevelForWebContents( - const content::WebContents* web_contents) { + content::WebContents* web_contents) { if (!web_contents) return 0.0;
diff --git a/components/zoom/zoom_controller.h b/components/zoom/zoom_controller.h index 3aa98a5..7c5318f 100644 --- a/components/zoom/zoom_controller.h +++ b/components/zoom/zoom_controller.h
@@ -91,8 +91,7 @@ // Since it's possible for a WebContents to not have a ZoomController, provide // a simple, safe and reliable method to find the current zoom level for a // given WebContents*. - static double GetZoomLevelForWebContents( - const content::WebContents* web_contents); + static double GetZoomLevelForWebContents(content::WebContents* web_contents); ~ZoomController() override;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 6df8fd81..bce899c 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -124,6 +124,7 @@ #include "media/mojo/buildflags.h" #include "mojo/core/embedder/embedder.h" #include "mojo/core/embedder/scoped_ipc_support.h" +#include "mojo/public/cpp/bindings/mojo_buildflags.h" #include "mojo/public/cpp/bindings/sync_call_restrictions.h" #include "net/base/network_change_notifier.h" #include "net/socket/client_socket_factory.h" @@ -244,6 +245,10 @@ #include "base/mac/foundation_util.h" #endif +#if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED) +#include "mojo/public/cpp/bindings/lib/test_random_mojo_delays.h" +#endif + // One of the linux specific headers defines this as a macro. #ifdef DestroyAll #undef DestroyAll @@ -1595,6 +1600,10 @@ parts_->ServiceManagerConnectionStarted( ServiceManagerConnection::GetForProcess()); } + +#if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED) + mojo::BeginRandomMojoDelays(); +#endif } base::FilePath BrowserMainLoop::GetStartupTraceFileName() const {
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc index babcf10..a97648e 100644 --- a/content/browser/frame_host/interstitial_page_impl.cc +++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -425,7 +425,7 @@ return this; } -ui::AXMode InterstitialPageImpl::GetAccessibilityMode() const { +ui::AXMode InterstitialPageImpl::GetAccessibilityMode() { if (web_contents_) return static_cast<WebContentsImpl*>(web_contents_)->GetAccessibilityMode(); else @@ -488,7 +488,7 @@ return web_contents(); } -const GURL& InterstitialPageImpl::GetMainFrameLastCommittedURL() const { +const GURL& InterstitialPageImpl::GetMainFrameLastCommittedURL() { return url_; } @@ -548,7 +548,7 @@ return nullptr; } -const std::string& InterstitialPageImpl::GetUserAgentOverride() const { +const std::string& InterstitialPageImpl::GetUserAgentOverride() { return base::EmptyString(); } @@ -556,7 +556,7 @@ return false; } -bool InterstitialPageImpl::ShowingInterstitialPage() const { +bool InterstitialPageImpl::ShowingInterstitialPage() { // An interstitial page never shows a second interstitial. return false; } @@ -796,7 +796,7 @@ } } -Visibility InterstitialPageImpl::GetVisibility() const { +Visibility InterstitialPageImpl::GetVisibility() { // Interstitials always occlude the underlying web content. return Visibility::OCCLUDED; }
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h index 486a40e..c3c81b8 100644 --- a/content/browser/frame_host/interstitial_page_impl.h +++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -99,9 +99,9 @@ // NavigatorDelegate implementation. WebContents* OpenURL(const OpenURLParams& params) override; - const std::string& GetUserAgentOverride() const override; + const std::string& GetUserAgentOverride() override; bool ShouldOverrideUserAgentInNewTabs() override; - bool ShowingInterstitialPage() const override; + bool ShowingInterstitialPage() override; protected: // NotificationObserver method: @@ -117,7 +117,7 @@ const base::string16& title, base::i18n::TextDirection title_direction) override; InterstitialPage* GetAsInterstitialPage() override; - ui::AXMode GetAccessibilityMode() const override; + ui::AXMode GetAccessibilityMode() override; void ExecuteEditCommand(const std::string& command, const base::Optional<base::string16>& value) override; void Cut() override; @@ -137,7 +137,7 @@ const gfx::Rect& initial_rect, bool user_gesture) override; void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) override; - Visibility GetVisibility() const override; + Visibility GetVisibility() override; void AudioContextPlaybackStarted(RenderFrameHost* host, int context_id) override; void AudioContextPlaybackStopped(RenderFrameHost* host, @@ -147,7 +147,7 @@ RenderViewHostDelegateView* GetDelegateView() override; bool OnMessageReceived(RenderViewHostImpl* render_view_host, const IPC::Message& message) override; - const GURL& GetMainFrameLastCommittedURL() const override; + const GURL& GetMainFrameLastCommittedURL() override; void RenderViewTerminated(RenderViewHost* render_view_host, base::TerminationStatus status, int error_code) override;
diff --git a/content/browser/frame_host/navigation_controller_delegate.h b/content/browser/frame_host/navigation_controller_delegate.h index 8a54d98..3a1e77dc 100644 --- a/content/browser/frame_host/navigation_controller_delegate.h +++ b/content/browser/frame_host/navigation_controller_delegate.h
@@ -32,12 +32,12 @@ virtual ~NavigationControllerDelegate() {} // Duplicates of WebContents methods. - virtual RenderViewHost* GetRenderViewHost() const = 0; - virtual InterstitialPage* GetInterstitialPage() const = 0; - virtual const std::string& GetContentsMimeType() const = 0; + virtual RenderViewHost* GetRenderViewHost() = 0; + virtual InterstitialPage* GetInterstitialPage() = 0; + virtual const std::string& GetContentsMimeType() = 0; virtual void NotifyNavigationStateChanged(InvalidateTypes changed_flags) = 0; virtual void Stop() = 0; - virtual bool IsBeingDestroyed() const = 0; + virtual bool IsBeingDestroyed() = 0; virtual bool CanOverscrollContent() const = 0; // Methods from WebContentsImpl that NavigationControllerImpl needs to
diff --git a/content/browser/frame_host/navigator_delegate.h b/content/browser/frame_host/navigator_delegate.h index cc58d99..909f3dfd 100644 --- a/content/browser/frame_host/navigator_delegate.h +++ b/content/browser/frame_host/navigator_delegate.h
@@ -96,7 +96,7 @@ virtual bool ShouldPreserveAbortedURLs(); // Returns the overriden user agent string if it's set. - virtual const std::string& GetUserAgentOverride() const = 0; + virtual const std::string& GetUserAgentOverride() = 0; // Returns whether we should override the user agent in new tabs, e.g., for // Android Webview's popup window when current entry. @@ -132,7 +132,7 @@ // Whether the delegate is displaying an interstitial page over the current // page. - virtual bool ShowingInterstitialPage() const = 0; + virtual bool ShowingInterstitialPage() = 0; }; } // namspace content
diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc index 61ceec5..a925637d 100644 --- a/content/browser/frame_host/render_frame_host_delegate.cc +++ b/content/browser/frame_host/render_frame_host_delegate.cc
@@ -22,7 +22,7 @@ return false; } -const GURL& RenderFrameHostDelegate::GetMainFrameLastCommittedURL() const { +const GURL& RenderFrameHostDelegate::GetMainFrameLastCommittedURL() { return GURL::EmptyGURL(); } @@ -79,7 +79,7 @@ return std::string(); } -ui::AXMode RenderFrameHostDelegate::GetAccessibilityMode() const { +ui::AXMode RenderFrameHostDelegate::GetAccessibilityMode() { return ui::AXMode(); } @@ -133,11 +133,11 @@ } #endif -bool RenderFrameHostDelegate::IsBeingDestroyed() const { +bool RenderFrameHostDelegate::IsBeingDestroyed() { return false; } -Visibility RenderFrameHostDelegate::GetVisibility() const { +Visibility RenderFrameHostDelegate::GetVisibility() { return Visibility::HIDDEN; }
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h index b417e7b..e54342a 100644 --- a/content/browser/frame_host/render_frame_host_delegate.h +++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -107,7 +107,7 @@ // Gets the last committed URL. See WebContents::GetLastCommittedURL for a // description of the semantics. - virtual const GURL& GetMainFrameLastCommittedURL() const; + virtual const GURL& GetMainFrameLastCommittedURL(); // A message was added to to the console. virtual bool DidAddMessageToConsole(int32_t level, @@ -215,7 +215,7 @@ virtual std::string GetDefaultMediaDeviceID(MediaStreamType type); // Get the accessibility mode for the WebContents that owns this frame. - virtual ui::AXMode GetAccessibilityMode() const; + virtual ui::AXMode GetAccessibilityMode(); // Called when accessibility events or location changes are received // from a render frame, when the accessibility mode has the @@ -383,7 +383,7 @@ // Whether the delegate is being destroyed, in which case the RenderFrameHost // should not be asked to create a RenderFrame. - virtual bool IsBeingDestroyed() const; + virtual bool IsBeingDestroyed(); // Notifies that the render frame started loading a subresource. virtual void SubresourceResponseStarted(const GURL& url, @@ -407,7 +407,7 @@ const gfx::Size& natural_size) {} // Returns the visibility of the delegate. - virtual Visibility GetVisibility() const; + virtual Visibility GetVisibility(); // Get the UKM source ID for current content. This is used for providing // data about the content to the URL-keyed metrics service.
diff --git a/content/browser/host_zoom_map_impl.cc b/content/browser/host_zoom_map_impl.cc index b97855d..6c900b0 100644 --- a/content/browser/host_zoom_map_impl.cc +++ b/content/browser/host_zoom_map_impl.cc
@@ -79,7 +79,7 @@ return partition->GetHostZoomMap(); } -HostZoomMap* HostZoomMap::GetForWebContents(const WebContents* contents) { +HostZoomMap* HostZoomMap::GetForWebContents(WebContents* contents) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(wjmaclean): Update this behaviour to work with OOPIF. // See crbug.com/528407. @@ -92,32 +92,31 @@ // Helper function for setting/getting zoom levels for WebContents without // having to import HostZoomMapImpl everywhere. -double HostZoomMap::GetZoomLevel(const WebContents* web_contents) { +double HostZoomMap::GetZoomLevel(WebContents* web_contents) { DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( HostZoomMap::GetForWebContents(web_contents)); return host_zoom_map->GetZoomLevelForWebContents( - *static_cast<const WebContentsImpl*>(web_contents)); + static_cast<WebContentsImpl*>(web_contents)); } -bool HostZoomMap::PageScaleFactorIsOne(const WebContents* web_contents) { +bool HostZoomMap::PageScaleFactorIsOne(WebContents* web_contents) { DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( HostZoomMap::GetForWebContents(web_contents)); return host_zoom_map->PageScaleFactorIsOneForWebContents( - *static_cast<const WebContentsImpl*>(web_contents)); + static_cast<WebContentsImpl*>(web_contents)); } -void HostZoomMap::SetZoomLevel(const WebContents* web_contents, double level) { +void HostZoomMap::SetZoomLevel(WebContents* web_contents, double level) { DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( HostZoomMap::GetForWebContents(web_contents)); host_zoom_map->SetZoomLevelForWebContents( - *static_cast<const WebContentsImpl*>(web_contents), level); + static_cast<WebContentsImpl*>(web_contents), level); } -void HostZoomMap::SendErrorPageZoomLevelRefresh( - const WebContents* web_contents) { +void HostZoomMap::SendErrorPageZoomLevelRefresh(WebContents* web_contents) { DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext( @@ -342,11 +341,11 @@ } double HostZoomMapImpl::GetZoomLevelForWebContents( - const WebContentsImpl& web_contents_impl) const { + WebContentsImpl* web_contents_impl) const { DCHECK_CURRENTLY_ON(BrowserThread::UI); int render_process_id = - web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(); - int routing_id = web_contents_impl.GetRenderViewHost()->GetRoutingID(); + web_contents_impl->GetRenderViewHost()->GetProcess()->GetID(); + int routing_id = web_contents_impl->GetRenderViewHost()->GetRoutingID(); if (UsesTemporaryZoomLevel(render_process_id, routing_id)) return GetTemporaryZoomLevel(render_process_id, routing_id); @@ -356,7 +355,7 @@ // is different than is stored in the map. GURL url; NavigationEntry* entry = - web_contents_impl.GetController().GetLastCommittedEntry(); + web_contents_impl->GetController().GetLastCommittedEntry(); // It is possible for a WebContent's zoom level to be queried before // a navigation has occurred. if (entry) @@ -366,12 +365,12 @@ } void HostZoomMapImpl::SetZoomLevelForWebContents( - const WebContentsImpl& web_contents_impl, + WebContentsImpl* web_contents_impl, double level) { DCHECK_CURRENTLY_ON(BrowserThread::UI); int render_process_id = - web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(); - int render_view_id = web_contents_impl.GetRenderViewHost()->GetRoutingID(); + web_contents_impl->GetRenderViewHost()->GetProcess()->GetID(); + int render_view_id = web_contents_impl->GetRenderViewHost()->GetRoutingID(); if (UsesTemporaryZoomLevel(render_process_id, render_view_id)) { SetTemporaryZoomLevel(render_process_id, render_view_id, level); } else { @@ -380,7 +379,7 @@ // is different than what the render view is using. If the two don't match, // the attempt to set the zoom will fail. NavigationEntry* entry = - web_contents_impl.GetController().GetLastCommittedEntry(); + web_contents_impl->GetController().GetLastCommittedEntry(); // Tests may invoke this function with a null entry, but we don't // want to save zoom levels in this case. if (!entry) @@ -414,14 +413,14 @@ } bool HostZoomMapImpl::PageScaleFactorIsOneForWebContents( - const WebContentsImpl& web_contents_impl) const { + WebContentsImpl* web_contents_impl) const { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (!web_contents_impl.GetRenderViewHost()->GetProcess()) + if (!web_contents_impl->GetRenderViewHost()->GetProcess()) return true; const auto it = view_page_scale_factors_are_one_.find(RenderViewKey( - web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(), - web_contents_impl.GetRenderViewHost()->GetRoutingID())); + web_contents_impl->GetRenderViewHost()->GetProcess()->GetID(), + web_contents_impl->GetRenderViewHost()->GetRoutingID())); return it != view_page_scale_factors_are_one_.end() ? it->second : true; }
diff --git a/content/browser/host_zoom_map_impl.h b/content/browser/host_zoom_map_impl.h index 51a26a52..3bf890a6d 100644 --- a/content/browser/host_zoom_map_impl.h +++ b/content/browser/host_zoom_map_impl.h
@@ -59,16 +59,15 @@ // Returns the current zoom level for the specified WebContents. This may // be a temporary zoom level, depending on UsesTemporaryZoomLevel(). - double GetZoomLevelForWebContents( - const WebContentsImpl& web_contents_impl) const; + double GetZoomLevelForWebContents(WebContentsImpl* web_contents_impl) const; bool PageScaleFactorIsOneForWebContents( - const WebContentsImpl& web_contents_impl) const; + WebContentsImpl* web_contents_impl) const; // Sets the zoom level for this WebContents. If this WebContents is using // a temporary zoom level, then level is only applied to this WebContents. // Otherwise, the level will be applied on a host level. - void SetZoomLevelForWebContents(const WebContentsImpl& web_contents_impl, + void SetZoomLevelForWebContents(WebContentsImpl* web_contents_impl, double level); // Sets the zoom level for the specified view. The level may be set for only
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc index fc73b531..f626c60 100644 --- a/content/browser/media/media_internals.cc +++ b/content/browser/media/media_internals.cc
@@ -284,7 +284,7 @@ return; } - const WebContents* web_contents = WebContents::FromRenderFrameHost( + WebContents* web_contents = WebContents::FromRenderFrameHost( RenderFrameHost::FromID(render_process_id, render_frame_id)); if (!web_contents) return;
diff --git a/content/browser/net/reporting_service_proxy.cc b/content/browser/net/reporting_service_proxy.cc index 90176c2..f668a839 100644 --- a/content/browser/net/reporting_service_proxy.cc +++ b/content/browser/net/reporting_service_proxy.cc
@@ -11,6 +11,8 @@ #include "base/memory/ref_counted.h" #include "base/values.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/storage_partition.h" #include "mojo/public/cpp/bindings/strong_binding.h" @@ -19,6 +21,7 @@ #include "net/url_request/http_user_agent_settings.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" +#include "services/network/public/mojom/network_context.mojom.h" #include "third_party/blink/public/platform/reporting.mojom.h" #include "url/gurl.h" @@ -28,9 +31,8 @@ class ReportingServiceProxyImpl : public blink::mojom::ReportingServiceProxy { public: - ReportingServiceProxyImpl( - scoped_refptr<net::URLRequestContextGetter> request_context_getter) - : request_context_getter_(std::move(request_context_getter)) {} + explicit ReportingServiceProxyImpl(int render_process_id) + : render_process_id_(render_process_id) {} // blink::mojom::ReportingServiceProxy: @@ -132,55 +134,29 @@ const std::string& group, const std::string& type, std::unique_ptr<base::Value> body) { - net::URLRequestContext* request_context = - request_context_getter_->GetURLRequestContext(); - if (!request_context) { - net::ReportingReport::RecordReportDiscardedForNoURLRequestContext(); + auto* rph = RenderProcessHost::FromID(render_process_id_); + if (!rph) return; - } - net::ReportingService* reporting_service = - request_context->reporting_service(); - if (!reporting_service) { - net::ReportingReport::RecordReportDiscardedForNoReportingService(); - return; - } - - // Depth is only non-zero for NEL reports, and those can't come from the - // renderer. - std::string user_agent; - if (request_context->http_user_agent_settings() != nullptr) - user_agent = request_context->http_user_agent_settings()->GetUserAgent(); - reporting_service->QueueReport(url, user_agent, group, type, - std::move(body), - /* depth= */ 0); + rph->GetStoragePartition()->GetNetworkContext()->QueueReport( + type, group, url, /*user_agent=*/base::nullopt, + base::Value::FromUniquePtrValue(std::move(body))); } - scoped_refptr<net::URLRequestContextGetter> request_context_getter_; + int render_process_id_; }; -void CreateReportingServiceProxyOnNetworkTaskRunner( - blink::mojom::ReportingServiceProxyRequest request, - scoped_refptr<net::URLRequestContextGetter> request_context_getter) { - mojo::MakeStrongBinding(std::make_unique<ReportingServiceProxyImpl>( - std::move(request_context_getter)), - std::move(request)); -} - } // namespace // static void CreateReportingServiceProxy( - StoragePartition* storage_partition, + int render_process_id, blink::mojom::ReportingServiceProxyRequest request) { - scoped_refptr<net::URLRequestContextGetter> request_context_getter( - storage_partition->GetURLRequestContext()); - scoped_refptr<base::SingleThreadTaskRunner> network_task_runner( - request_context_getter->GetNetworkTaskRunner()); - network_task_runner->PostTask( - FROM_HERE, - base::BindOnce(&CreateReportingServiceProxyOnNetworkTaskRunner, - std::move(request), std::move(request_context_getter))); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + mojo::MakeStrongBinding( + std::make_unique<ReportingServiceProxyImpl>(render_process_id), + std::move(request)); } } // namespace content
diff --git a/content/browser/net/reporting_service_proxy.h b/content/browser/net/reporting_service_proxy.h index cd0f42ea..cbd9a363 100644 --- a/content/browser/net/reporting_service_proxy.h +++ b/content/browser/net/reporting_service_proxy.h
@@ -9,10 +9,10 @@ namespace content { -class StoragePartition; - +// Binds a mojom::ReportingServiceProxy to |request| that queues reports using +// |render_process_id|'s NetworkContext. This must be called on the UI thread. void CreateReportingServiceProxy( - StoragePartition* storage_partition, + int render_process_id, blink::mojom::ReportingServiceProxyRequest request); } // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 079dcad1..d1823eb 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2223,8 +2223,9 @@ storage_partition_impl_->GetGeneratedCodeCacheContext()))); #if BUILDFLAG(ENABLE_REPORTING) - registry->AddInterface( - base::Bind(&CreateReportingServiceProxy, storage_partition_impl_)); + AddUIThreadInterface( + registry.get(), + base::BindRepeating(&CreateReportingServiceProxy, GetID())); #endif // BUILDFLAG(ENABLE_REPORTING) registry->AddInterface(base::BindRepeating(
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc index 419a683..efd2a7a 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.cc +++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -49,7 +49,7 @@ return false; } -double RenderWidgetHostDelegate::GetPendingPageZoomLevel() const { +double RenderWidgetHostDelegate::GetPendingPageZoomLevel() { return 0.0; } @@ -82,7 +82,7 @@ return nullptr; } -bool RenderWidgetHostDelegate::IsFullscreenForCurrentTab() const { +bool RenderWidgetHostDelegate::IsFullscreenForCurrentTab() { return false; }
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h index 79ac33c..83878e9 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.h +++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -78,7 +78,7 @@ // for the pending page. Otherwise, this returns the zoom level for the // current page. Note that subframe navigations do not affect the zoom level, // which is tracked at the level of the page. - virtual double GetPendingPageZoomLevel() const; + virtual double GetPendingPageZoomLevel(); // The RenderWidgetHost lost the focus. virtual void RenderWidgetLostFocus( @@ -199,7 +199,7 @@ bool privileged) {} // Returns whether the associated tab is in fullscreen mode. - virtual bool IsFullscreenForCurrentTab() const; + virtual bool IsFullscreenForCurrentTab(); // Returns the display mode for the view. virtual blink::WebDisplayMode GetDisplayMode(
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index d8bad409..f0b0c4cf 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -569,7 +569,7 @@ void SetZoomLevel(double zoom_level) { zoom_level_ = zoom_level; } - double GetPendingPageZoomLevel() const override { return zoom_level_; } + double GetPendingPageZoomLevel() override { return zoom_level_; } void FocusOwningWebContents( RenderWidgetHostImpl* render_widget_host) override {
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc index 8ccba9c..bdaf4c8 100644 --- a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc +++ b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -106,7 +106,7 @@ return fake_contents_window_.get(); } - bool IsBeingDestroyed() const override { return is_being_destroyed_; } + bool IsBeingDestroyed() override { return is_being_destroyed_; } private: std::unique_ptr<aura::Window> fake_native_view_;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index f5853dce..8d1eaa3 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -917,27 +917,23 @@ return controller_; } -const NavigationControllerImpl& WebContentsImpl::GetController() const { - return controller_; -} - -BrowserContext* WebContentsImpl::GetBrowserContext() const { +BrowserContext* WebContentsImpl::GetBrowserContext() { return controller_.GetBrowserContext(); } -const GURL& WebContentsImpl::GetURL() const { +const GURL& WebContentsImpl::GetURL() { // We may not have a navigation entry yet. NavigationEntry* entry = controller_.GetVisibleEntry(); return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); } -const GURL& WebContentsImpl::GetVisibleURL() const { +const GURL& WebContentsImpl::GetVisibleURL() { // We may not have a navigation entry yet. NavigationEntry* entry = controller_.GetVisibleEntry(); return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); } -const GURL& WebContentsImpl::GetLastCommittedURL() const { +const GURL& WebContentsImpl::GetLastCommittedURL() { // We may not have a navigation entry yet. NavigationEntry* entry = controller_.GetLastCommittedEntry(); return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); @@ -964,7 +960,7 @@ } } -RenderFrameHostImpl* WebContentsImpl::GetMainFrame() const { +RenderFrameHostImpl* WebContentsImpl::GetMainFrame() { return frame_tree_.root()->current_frame_host(); } @@ -1031,7 +1027,7 @@ frame_tree_.root()->render_manager()->SendPageMessage(msg, nullptr); } -RenderViewHostImpl* WebContentsImpl::GetRenderViewHost() const { +RenderViewHostImpl* WebContentsImpl::GetRenderViewHost() { return GetRenderManager()->current_host(); } @@ -1047,7 +1043,7 @@ GetRenderViewHost()->ClosePage(); } -RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const { +RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() { return GetRenderManager()->GetRenderWidgetHostView(); } @@ -1057,8 +1053,7 @@ return GetRenderManager()->GetRenderWidgetHostView(); } -RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView() - const { +RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView() { if (auto* widget_host = GetFullscreenRenderWidgetHost()) return widget_host->GetView(); return nullptr; @@ -1073,7 +1068,7 @@ screen_orientation_provider_->OnOrientationChange(); } -SkColor WebContentsImpl::GetThemeColor() const { +SkColor WebContentsImpl::GetThemeColor() { return theme_color_; } @@ -1176,7 +1171,7 @@ observer.ViewportFitChanged(value); } -FindRequestManager* WebContentsImpl::GetFindRequestManagerForTesting() const { +FindRequestManager* WebContentsImpl::GetFindRequestManagerForTesting() { return GetFindRequestManager(); } @@ -1253,13 +1248,13 @@ observer.DidUpdateWebManifestURL(manifest_url); } -WebUI* WebContentsImpl::GetWebUI() const { +WebUI* WebContentsImpl::GetWebUI() { WebUI* commited_web_ui = GetCommittedWebUI(); return commited_web_ui ? commited_web_ui : GetRenderManager()->GetNavigatingWebUI(); } -WebUI* WebContentsImpl::GetCommittedWebUI() const { +WebUI* WebContentsImpl::GetCommittedWebUI() { return frame_tree_.root()->current_frame_host()->web_ui(); } @@ -1287,7 +1282,7 @@ observer.UserAgentOverrideSet(override); } -const std::string& WebContentsImpl::GetUserAgentOverride() const { +const std::string& WebContentsImpl::GetUserAgentOverride() { return renderer_preferences_.user_agent_override; } @@ -1304,15 +1299,15 @@ } } -bool WebContentsImpl::IsWebContentsOnlyAccessibilityModeForTesting() const { +bool WebContentsImpl::IsWebContentsOnlyAccessibilityModeForTesting() { return accessibility_mode_ == ui::kAXModeWebContentsOnly; } -bool WebContentsImpl::IsFullAccessibilityModeForTesting() const { +bool WebContentsImpl::IsFullAccessibilityModeForTesting() { return accessibility_mode_ == ui::kAXModeComplete; } -const PageImportanceSignals& WebContentsImpl::GetPageImportanceSignals() const { +const PageImportanceSignals& WebContentsImpl::GetPageImportanceSignals() { return page_importance_signals_; } @@ -1329,7 +1324,7 @@ #endif -const base::string16& WebContentsImpl::GetTitle() const { +const base::string16& WebContentsImpl::GetTitle() { // Transient entries take precedence. They are used for interstitial pages // that are shown on top of existing pages. NavigationEntry* entry = controller_.GetTransientEntry(); @@ -1383,24 +1378,24 @@ return page_title_when_no_navigation_entry_; } -SiteInstanceImpl* WebContentsImpl::GetSiteInstance() const { +SiteInstanceImpl* WebContentsImpl::GetSiteInstance() { return GetRenderManager()->current_host()->GetSiteInstance(); } -bool WebContentsImpl::IsLoading() const { +bool WebContentsImpl::IsLoading() { return frame_tree_.IsLoading() && !(ShowingInterstitialPage() && interstitial_page_->pause_throbber()); } -double WebContentsImpl::GetLoadProgress() const { +double WebContentsImpl::GetLoadProgress() { return frame_tree_.load_progress(); } -bool WebContentsImpl::IsLoadingToDifferentDocument() const { +bool WebContentsImpl::IsLoadingToDifferentDocument() { return IsLoading() && is_load_to_different_document_; } -bool WebContentsImpl::IsWaitingForResponse() const { +bool WebContentsImpl::IsWaitingForResponse() { NavigationRequest* ongoing_navigation_request = frame_tree_.root()->navigation_request(); @@ -1408,23 +1403,23 @@ return ongoing_navigation_request != nullptr; } -const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const { +const net::LoadStateWithParam& WebContentsImpl::GetLoadState() { return load_state_; } -const base::string16& WebContentsImpl::GetLoadStateHost() const { +const base::string16& WebContentsImpl::GetLoadStateHost() { return load_state_host_; } -uint64_t WebContentsImpl::GetUploadSize() const { +uint64_t WebContentsImpl::GetUploadSize() { return upload_size_; } -uint64_t WebContentsImpl::GetUploadPosition() const { +uint64_t WebContentsImpl::GetUploadPosition() { return upload_position_; } -const std::string& WebContentsImpl::GetEncoding() const { +const std::string& WebContentsImpl::GetEncoding() { return canonical_encoding_; } @@ -1483,11 +1478,11 @@ } } -bool WebContentsImpl::IsBeingCaptured() const { +bool WebContentsImpl::IsBeingCaptured() { return capturer_count_ > 0; } -bool WebContentsImpl::IsAudioMuted() const { +bool WebContentsImpl::IsAudioMuted() { if (base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams)) { return audio_stream_factory_ && audio_stream_factory_->IsMuted(); } @@ -1525,11 +1520,11 @@ return is_currently_audible_; } -bool WebContentsImpl::IsConnectedToBluetoothDevice() const { +bool WebContentsImpl::IsConnectedToBluetoothDevice() { return bluetooth_connected_device_count_ > 0; } -bool WebContentsImpl::HasPictureInPictureVideo() const { +bool WebContentsImpl::HasPictureInPictureVideo() { return has_picture_in_picture_video_; } @@ -1544,7 +1539,7 @@ observer.MediaPictureInPictureChanged(has_picture_in_picture_video_); } -bool WebContentsImpl::IsCrashed() const { +bool WebContentsImpl::IsCrashed() { switch (crashed_status_) { case base::TERMINATION_STATUS_PROCESS_CRASHED: case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: @@ -1580,15 +1575,15 @@ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB); } -base::TerminationStatus WebContentsImpl::GetCrashedStatus() const { +base::TerminationStatus WebContentsImpl::GetCrashedStatus() { return crashed_status_; } -int WebContentsImpl::GetCrashedErrorCode() const { +int WebContentsImpl::GetCrashedErrorCode() { return crashed_error_code_; } -bool WebContentsImpl::IsBeingDestroyed() const { +bool WebContentsImpl::IsBeingDestroyed() { return is_being_destroyed_; } @@ -1636,7 +1631,7 @@ observer.OnAudioStateChanged(is_currently_audible_); } -base::TimeTicks WebContentsImpl::GetLastActiveTime() const { +base::TimeTicks WebContentsImpl::GetLastActiveTime() { return last_active_time_; } @@ -1690,7 +1685,7 @@ SetVisibility(Visibility::HIDDEN); } -bool WebContentsImpl::HasRecentInteractiveInputEvent() const { +bool WebContentsImpl::HasRecentInteractiveInputEvent() { static constexpr base::TimeDelta kMaxInterval = base::TimeDelta::FromSeconds(5); base::TimeDelta delta = @@ -1728,7 +1723,7 @@ SetVisibility(Visibility::OCCLUDED); } -Visibility WebContentsImpl::GetVisibility() const { +Visibility WebContentsImpl::GetVisibility() { return visibility_; } @@ -2457,7 +2452,7 @@ } #endif -bool WebContentsImpl::IsFullscreenForCurrentTab() const { +bool WebContentsImpl::IsFullscreenForCurrentTab() { return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false; } @@ -3043,7 +3038,7 @@ return DevToolsAgentHost::IsDebuggerAttached(this); } -ui::AXMode WebContentsImpl::GetAccessibilityMode() const { +ui::AXMode WebContentsImpl::GetAccessibilityMode() { return accessibility_mode_; } @@ -3663,11 +3658,11 @@ view_->FocusThroughTabTraversal(reverse); } -bool WebContentsImpl::ShowingInterstitialPage() const { +bool WebContentsImpl::ShowingInterstitialPage() { return interstitial_page_ != nullptr; } -InterstitialPageImpl* WebContentsImpl::GetInterstitialPage() const { +InterstitialPageImpl* WebContentsImpl::GetInterstitialPage() { return interstitial_page_; } @@ -3799,11 +3794,11 @@ std::move(callback)); } -const std::string& WebContentsImpl::GetContentsMimeType() const { +const std::string& WebContentsImpl::GetContentsMimeType() { return contents_mime_type_; } -bool WebContentsImpl::WillNotifyDisconnection() const { +bool WebContentsImpl::WillNotifyDisconnection() { return notify_disconnection_; } @@ -3895,15 +3890,15 @@ closed_by_user_gesture_ = value; } -bool WebContentsImpl::GetClosedByUserGesture() const { +bool WebContentsImpl::GetClosedByUserGesture() { return closed_by_user_gesture_; } -int WebContentsImpl::GetMinimumZoomPercent() const { +int WebContentsImpl::GetMinimumZoomPercent() { return minimum_zoom_percent_; } -int WebContentsImpl::GetMaximumZoomPercent() const { +int WebContentsImpl::GetMaximumZoomPercent() { return maximum_zoom_percent_; } @@ -3912,7 +3907,7 @@ GetRenderViewHost()->GetRoutingID(), page_scale_factor)); } -gfx::Size WebContentsImpl::GetPreferredSize() const { +gfx::Size WebContentsImpl::GetPreferredSize() { return IsBeingCaptured() ? preferred_size_for_capture_ : preferred_size_; } @@ -3958,20 +3953,20 @@ return true; } -bool WebContentsImpl::HasOpener() const { +bool WebContentsImpl::HasOpener() { return GetOpener() != nullptr; } -RenderFrameHostImpl* WebContentsImpl::GetOpener() const { +RenderFrameHostImpl* WebContentsImpl::GetOpener() { FrameTreeNode* opener_ftn = frame_tree_.root()->opener(); return opener_ftn ? opener_ftn->current_frame_host() : nullptr; } -bool WebContentsImpl::HasOriginalOpener() const { +bool WebContentsImpl::HasOriginalOpener() { return GetOriginalOpener() != nullptr; } -RenderFrameHostImpl* WebContentsImpl::GetOriginalOpener() const { +RenderFrameHostImpl* WebContentsImpl::GetOriginalOpener() { FrameTreeNode* opener_ftn = frame_tree_.root()->original_opener(); return opener_ftn ? opener_ftn->current_frame_host() : nullptr; } @@ -5079,7 +5074,7 @@ delegate_->OnDidBlockFramebust(this, url); } -const GURL& WebContentsImpl::GetMainFrameLastCommittedURL() const { +const GURL& WebContentsImpl::GetMainFrameLastCommittedURL() { return GetLastCommittedURL(); } @@ -5313,7 +5308,7 @@ } #if !defined(OS_ANDROID) -double WebContentsImpl::GetPendingPageZoomLevel() const { +double WebContentsImpl::GetPendingPageZoomLevel() { NavigationEntry* pending_entry = GetController().GetPendingEntry(); if (!pending_entry) return HostZoomMap::GetZoomLevel(this); @@ -5350,7 +5345,7 @@ return frame && frame->has_focused_editable_element(); } -bool WebContentsImpl::IsShowingContextMenu() const { +bool WebContentsImpl::IsShowingContextMenu() { return showing_context_menu_; } @@ -5390,7 +5385,7 @@ browser_plugin_embedder_.reset(); } -WebContentsImpl* WebContentsImpl::GetOuterWebContents() const { +WebContentsImpl* WebContentsImpl::GetOuterWebContents() { if (GuestMode::IsCrossProcessFrameGuest(this)) return node_.outer_web_contents(); @@ -6276,7 +6271,7 @@ #endif -bool WebContentsImpl::CompletedFirstVisuallyNonEmptyPaint() const { +bool WebContentsImpl::CompletedFirstVisuallyNonEmptyPaint() { return did_first_visually_non_empty_paint_; } @@ -6432,8 +6427,8 @@ return nullptr; } -FindRequestManager* WebContentsImpl::GetFindRequestManager() const { - for (const auto* contents = this; contents; +FindRequestManager* WebContentsImpl::GetFindRequestManager() { + for (auto* contents = this; contents; contents = contents->GetOuterWebContents()) { if (contents->find_request_manager_) return contents->find_request_manager_.get();
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 5a0e315..492ad274 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -295,12 +295,11 @@ WebContentsDelegate* GetDelegate() override; void SetDelegate(WebContentsDelegate* delegate) override; NavigationControllerImpl& GetController() override; - const NavigationControllerImpl& GetController() const override; - BrowserContext* GetBrowserContext() const override; - const GURL& GetURL() const override; - const GURL& GetVisibleURL() const override; - const GURL& GetLastCommittedURL() const override; - RenderFrameHostImpl* GetMainFrame() const override; + BrowserContext* GetBrowserContext() override; + const GURL& GetURL() override; + const GURL& GetVisibleURL() override; + const GURL& GetLastCommittedURL() override; + RenderFrameHostImpl* GetMainFrame() override; RenderFrameHostImpl* GetFocusedFrame() override; RenderFrameHostImpl* FindFrameByFrameTreeNodeId(int frame_tree_node_id, int process_id) override; @@ -310,65 +309,65 @@ const base::RepeatingCallback<void(RenderFrameHost*)>& on_frame) override; std::vector<RenderFrameHost*> GetAllFrames() override; int SendToAllFrames(IPC::Message* message) override; - RenderViewHostImpl* GetRenderViewHost() const override; - RenderWidgetHostView* GetRenderWidgetHostView() const override; + RenderViewHostImpl* GetRenderViewHost() override; + RenderWidgetHostView* GetRenderWidgetHostView() override; RenderWidgetHostView* GetTopLevelRenderWidgetHostView() override; void ClosePage() override; - RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const override; - SkColor GetThemeColor() const override; - WebUI* GetWebUI() const override; - WebUI* GetCommittedWebUI() const override; + RenderWidgetHostView* GetFullscreenRenderWidgetHostView() override; + SkColor GetThemeColor() override; + WebUI* GetWebUI() override; + WebUI* GetCommittedWebUI() override; void SetUserAgentOverride(const std::string& override, bool override_in_new_tabs) override; - const std::string& GetUserAgentOverride() const override; + const std::string& GetUserAgentOverride() override; bool ShouldOverrideUserAgentInNewTabs() override; void EnableWebContentsOnlyAccessibilityMode() override; - bool IsWebContentsOnlyAccessibilityModeForTesting() const override; - bool IsFullAccessibilityModeForTesting() const override; - const PageImportanceSignals& GetPageImportanceSignals() const override; - const base::string16& GetTitle() const override; + bool IsWebContentsOnlyAccessibilityModeForTesting() override; + bool IsFullAccessibilityModeForTesting() override; + const PageImportanceSignals& GetPageImportanceSignals() override; + const base::string16& GetTitle() override; void UpdateTitleForEntry(NavigationEntry* entry, const base::string16& title) override; - SiteInstanceImpl* GetSiteInstance() const override; - bool IsLoading() const override; - double GetLoadProgress() const override; - bool IsLoadingToDifferentDocument() const override; - bool IsWaitingForResponse() const override; - const net::LoadStateWithParam& GetLoadState() const override; - const base::string16& GetLoadStateHost() const override; + SiteInstanceImpl* GetSiteInstance() override; + bool IsLoading() override; + double GetLoadProgress() override; + bool IsLoadingToDifferentDocument() override; + bool IsWaitingForResponse() override; + const net::LoadStateWithParam& GetLoadState() override; + const base::string16& GetLoadStateHost() override; void RequestAXTreeSnapshot(AXTreeSnapshotCallback callback, ui::AXMode ax_mode) override; - uint64_t GetUploadSize() const override; - uint64_t GetUploadPosition() const override; - const std::string& GetEncoding() const override; + uint64_t GetUploadSize() override; + uint64_t GetUploadPosition() override; + const std::string& GetEncoding() override; bool WasDiscarded() override; void SetWasDiscarded(bool was_discarded) override; void IncrementCapturerCount(const gfx::Size& capture_size) override; void DecrementCapturerCount() override; - bool IsBeingCaptured() const override; - bool IsAudioMuted() const override; + bool IsBeingCaptured() override; + bool IsAudioMuted() override; void SetAudioMuted(bool mute) override; bool IsCurrentlyAudible() override; - bool IsConnectedToBluetoothDevice() const override; - bool HasPictureInPictureVideo() const override; - bool IsCrashed() const override; + bool IsConnectedToBluetoothDevice() override; + bool HasPictureInPictureVideo() override; + bool IsCrashed() override; void SetIsCrashed(base::TerminationStatus status, int error_code) override; - base::TerminationStatus GetCrashedStatus() const override; - int GetCrashedErrorCode() const override; - bool IsBeingDestroyed() const override; + base::TerminationStatus GetCrashedStatus() override; + int GetCrashedErrorCode() override; + bool IsBeingDestroyed() override; void NotifyNavigationStateChanged(InvalidateTypes changed_flags) override; void OnAudioStateChanged() override; - base::TimeTicks GetLastActiveTime() const override; + base::TimeTicks GetLastActiveTime() override; void WasShown() override; void WasHidden() override; void WasOccluded() override; - Visibility GetVisibility() const override; + Visibility GetVisibility() override; bool NeedToFireBeforeUnload() override; void DispatchBeforeUnload(bool auto_cancel) override; void AttachToOuterWebContentsFrame( std::unique_ptr<WebContents> current_web_contents, RenderFrameHost* outer_contents_frame) override; - WebContentsImpl* GetOuterWebContents() const override; + WebContentsImpl* GetOuterWebContents() override; WebContentsImpl* GetOutermostWebContents() override; void DidChangeVisibleSecurityState() override; void NotifyPreferencesChanged() override; @@ -408,8 +407,8 @@ void StoreFocus() override; void RestoreFocus() override; void FocusThroughTabTraversal(bool reverse) override; - bool ShowingInterstitialPage() const override; - InterstitialPageImpl* GetInterstitialPage() const override; + bool ShowingInterstitialPage() override; + InterstitialPageImpl* GetInterstitialPage() override; bool IsSavable() override; void OnSavePage() override; bool SavePage(const base::FilePath& main_file, @@ -422,24 +421,24 @@ const base::string16& suggested_filename) override; void GenerateMHTML(const MHTMLGenerationParams& params, base::OnceCallback<void(int64_t)> callback) override; - const std::string& GetContentsMimeType() const override; - bool WillNotifyDisconnection() const override; + const std::string& GetContentsMimeType() override; + bool WillNotifyDisconnection() override; RendererPreferences* GetMutableRendererPrefs() override; void Close() override; void SystemDragEnded(RenderWidgetHost* source_rwh) override; void NavigatedByUser() override; void SetClosedByUserGesture(bool value) override; - bool GetClosedByUserGesture() const override; - int GetMinimumZoomPercent() const override; - int GetMaximumZoomPercent() const override; + bool GetClosedByUserGesture() override; + int GetMinimumZoomPercent() override; + int GetMaximumZoomPercent() override; void SetPageScale(float page_scale_factor) override; - gfx::Size GetPreferredSize() const override; + gfx::Size GetPreferredSize() override; bool GotResponseToLockMouseRequest(bool allowed) override; bool GotResponseToKeyboardLockRequest(bool allowed) override; - bool HasOpener() const override; - RenderFrameHostImpl* GetOpener() const override; - bool HasOriginalOpener() const override; - RenderFrameHostImpl* GetOriginalOpener() const override; + bool HasOpener() override; + RenderFrameHostImpl* GetOpener() override; + bool HasOriginalOpener() override; + RenderFrameHostImpl* GetOriginalOpener() override; void DidChooseColorInColorChooser(SkColor color) override; void DidEndColorChooser() override; int DownloadImage(const GURL& url, @@ -453,17 +452,17 @@ void StopFinding(StopFindAction action) override; bool WasEverAudible() override; void GetManifest(GetManifestCallback callback) override; - bool IsFullscreenForCurrentTab() const override; + bool IsFullscreenForCurrentTab() override; void ExitFullscreen(bool will_cause_resize) override; void ResumeLoadingCreatedWebContents() override; void SetIsOverlayContent(bool is_overlay_content) override; bool IsFocusedElementEditable() override; void ClearFocusedElement() override; - bool IsShowingContextMenu() const override; + bool IsShowingContextMenu() override; void SetShowingContextMenu(bool showing) override; void PausePageScheduledTasks(bool paused) override; base::UnguessableToken GetAudioGroupId() override; - bool CompletedFirstVisuallyNonEmptyPaint() const override; + bool CompletedFirstVisuallyNonEmptyPaint() override; #if defined(OS_ANDROID) base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override; @@ -473,7 +472,7 @@ service_manager::InterfaceProvider* GetJavaInterfaces() override; #endif - bool HasRecentInteractiveInputEvent() const override; + bool HasRecentInteractiveInputEvent() override; void SetIgnoreInputEvents(bool ignore_input_events) override; // Implementation of PageNavigator. @@ -491,7 +490,7 @@ const std::string& interface_name, mojo::ScopedMessagePipeHandle* interface_pipe) override; void OnDidBlockFramebust(const GURL& url) override; - const GURL& GetMainFrameLastCommittedURL() const override; + const GURL& GetMainFrameLastCommittedURL() override; void RenderFrameCreated(RenderFrameHost* render_frame_host) override; void RenderFrameDeleted(RenderFrameHost* render_frame_host) override; void ShowContextMenu(RenderFrameHost* render_frame_host, @@ -524,7 +523,7 @@ const std::string& encoding) override; WebContents* GetAsWebContents() override; bool IsNeverVisible() override; - ui::AXMode GetAccessibilityMode() const override; + ui::AXMode GetAccessibilityMode() override; // Broadcasts the mode change to all frames. void SetAccessibilityMode(ui::AXMode mode) override; void AccessibilityEventReceived( @@ -722,7 +721,7 @@ InputEventShim* GetInputEventShim() const override; #if !defined(OS_ANDROID) - double GetPendingPageZoomLevel() const override; + double GetPendingPageZoomLevel() override; #endif // !defined(OS_ANDROID) KeyboardEventProcessingResult PreHandleKeyboardEvent( @@ -1004,7 +1003,7 @@ // Returns the current FindRequestManager associated with the WebContents; // this won't create one if none exists. - FindRequestManager* GetFindRequestManagerForTesting() const; + FindRequestManager* GetFindRequestManagerForTesting(); private: friend class WebContentsObserver; @@ -1390,7 +1389,7 @@ JavaScriptDialogManager* dialog_manager); // Returns the FindRequestManager, which may be found in an outer WebContents. - FindRequestManager* GetFindRequestManager() const; + FindRequestManager* GetFindRequestManager(); // Returns the FindRequestManager, or tries to create one if it doesn't // already exist. The FindRequestManager may be found in an outer
diff --git a/content/browser/webui/web_ui_url_loader_factory.cc b/content/browser/webui/web_ui_url_loader_factory.cc index 37bab92..63fe012 100644 --- a/content/browser/webui/web_ui_url_loader_factory.cc +++ b/content/browser/webui/web_ui_url_loader_factory.cc
@@ -7,7 +7,6 @@ #include <map> #include "base/bind.h" -#include "base/debug/alias.h" #include "base/debug/crash_logging.h" #include "base/lazy_instance.h" #include "base/logging.h" @@ -58,12 +57,9 @@ void ReadData(scoped_refptr<network::ResourceResponse> headers, const ui::TemplateReplacements* replacements, bool gzipped, - const GURL& url, scoped_refptr<URLDataSourceImpl> data_source, network::mojom::URLLoaderClientPtrInfo client_info, scoped_refptr<base::RefCountedMemory> bytes) { - // TODO(jam): remove after https://crbug.com/891074 is fixed. - DEBUG_ALIAS_FOR_GURL(url_buf, url); if (!bytes) { CallOnError(std::move(client_info), net::ERR_FAILED); return; @@ -131,7 +127,6 @@ void DataAvailable(scoped_refptr<network::ResourceResponse> headers, const ui::TemplateReplacements* replacements, bool gzipped, - const GURL& url, scoped_refptr<URLDataSourceImpl> source, network::mojom::URLLoaderClientPtrInfo client_info, scoped_refptr<base::RefCountedMemory> bytes) { @@ -142,7 +137,7 @@ {base::TaskPriority::USER_BLOCKING, base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}) ->PostTask(FROM_HERE, - base::BindOnce(ReadData, headers, replacements, gzipped, url, + base::BindOnce(ReadData, headers, replacements, gzipped, source, std::move(client_info), bytes)); } @@ -198,7 +193,6 @@ // |replacements| is owned by |source| keep a reference to it in the callback. auto data_available_callback = base::Bind(DataAvailable, resource_response, replacements, gzipped, - request.url, base::RetainedRef(source), base::Passed(&client_info)); // TODO(jam): once we only have this code path for WebUI, and not the
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index b0635bb4..17be42a 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -141,7 +141,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::UserActivationUpdateType, blink::UserActivationUpdateType::kMaxValue) IPC_ENUM_TRAITS_MAX_VALUE(blink::WebMediaPlayerAction::Type, - blink::WebMediaPlayerAction::Type::kTypeLast) + blink::WebMediaPlayerAction::Type::kMaxValue) IPC_ENUM_TRAITS_MAX_VALUE(content::WasActivatedOption, content::WasActivatedOption::kMaxValue) IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScrollDirection,
diff --git a/content/public/browser/host_zoom_map.h b/content/public/browser/host_zoom_map.h index a72fc20..66b566c2 100644 --- a/content/public/browser/host_zoom_map.h +++ b/content/public/browser/host_zoom_map.h
@@ -77,26 +77,24 @@ // Returns the HostZoomMap associated with this WebContent's main frame. If // multiple WebContents share the same SiteInstance, then they share a single // HostZoomMap. - CONTENT_EXPORT static HostZoomMap* GetForWebContents( - const WebContents* contents); + CONTENT_EXPORT static HostZoomMap* GetForWebContents(WebContents* contents); // Returns the current zoom level for the specified WebContents. May be // temporary or host-specific. - CONTENT_EXPORT static double GetZoomLevel(const WebContents* web_contents); + CONTENT_EXPORT static double GetZoomLevel(WebContents* web_contents); // Returns true if the page scale factor for the WebContents is one. - CONTENT_EXPORT static bool PageScaleFactorIsOne( - const WebContents* web_contents); + CONTENT_EXPORT static bool PageScaleFactorIsOne(WebContents* web_contents); // Sets the current zoom level for the specified WebContents. The level may // be temporary or host-specific depending on the particular WebContents. - CONTENT_EXPORT static void SetZoomLevel(const WebContents* web_contents, + CONTENT_EXPORT static void SetZoomLevel(WebContents* web_contents, double level); // Send an IPC to refresh any displayed error page's zoom levels. Needs to // be called since error pages don't get loaded via the normal channel. CONTENT_EXPORT static void SendErrorPageZoomLevelRefresh( - const WebContents* web_contents); + WebContents* web_contents); // Set or clear whether or not the page scale factor for a view is one. virtual void SetPageScaleFactorIsOneForView(
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 1f1167b5..060e2194 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -264,16 +264,15 @@ // Gets the controller for this WebContents. virtual NavigationController& GetController() = 0; - virtual const NavigationController& GetController() const = 0; // Returns the user browser context associated with this WebContents (via the // NavigationController). - virtual content::BrowserContext* GetBrowserContext() const = 0; + virtual content::BrowserContext* GetBrowserContext() = 0; // Gets the URL that is currently being displayed, if there is one. // This method is deprecated. DO NOT USE! Pick either |GetVisibleURL| or // |GetLastCommittedURL| as appropriate. - virtual const GURL& GetURL() const = 0; + virtual const GURL& GetURL() = 0; // Gets the virtual URL currently being displayed in the URL bar, if there is // one. This URL might be a pending navigation that hasn't committed yet, so @@ -281,7 +280,7 @@ // typical example of this is interstitials, which show the URL of the // new/loading page (active) but the security context is of the old page (last // committed). - virtual const GURL& GetVisibleURL() const = 0; + virtual const GURL& GetVisibleURL() = 0; // Gets the virtual URL of the last committed page in this WebContents. // Virtual URLs are meant to be displayed to the user (e.g., they include the @@ -289,10 +288,10 @@ // and NavigationHandle::GetURL). The last committed page is the current // security context and the content that is actually displayed within the tab. // See also GetVisibleURL above, which may differ from this URL. - virtual const GURL& GetLastCommittedURL() const = 0; + virtual const GURL& GetLastCommittedURL() = 0; // Returns the main frame for the currently active view. - virtual RenderFrameHost* GetMainFrame() const = 0; + virtual RenderFrameHost* GetMainFrame() = 0; // Returns the focused frame for the currently active view. virtual RenderFrameHost* GetFocusedFrame() = 0; @@ -333,11 +332,11 @@ virtual int SendToAllFrames(IPC::Message* message) = 0; // Gets the current RenderViewHost for this tab. - virtual RenderViewHost* GetRenderViewHost() const = 0; + virtual RenderViewHost* GetRenderViewHost() = 0; // Returns the currently active RenderWidgetHostView. This may change over // time and can be nullptr (during setup and teardown). - virtual RenderWidgetHostView* GetRenderWidgetHostView() const = 0; + virtual RenderWidgetHostView* GetRenderWidgetHostView() = 0; // Returns the outermost RenderWidgetHostView. This will return the platform // specific RenderWidgetHostView (as opposed to @@ -358,22 +357,22 @@ // Returns the currently active fullscreen widget. If there is none, returns // nullptr. - virtual RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const = 0; + virtual RenderWidgetHostView* GetFullscreenRenderWidgetHostView() = 0; // Returns the theme color for the underlying content as set by the // theme-color meta tag. - virtual SkColor GetThemeColor() const = 0; + virtual SkColor GetThemeColor() = 0; // Returns the committed WebUI if one exists, otherwise the pending one. - virtual WebUI* GetWebUI() const = 0; - virtual WebUI* GetCommittedWebUI() const = 0; + virtual WebUI* GetWebUI() = 0; + virtual WebUI* GetCommittedWebUI() = 0; // Allows overriding the user agent used for NavigationEntries it owns. // |override_in_new_tabs| is set when we are overriding user agent for new // tabs. virtual void SetUserAgentOverride(const std::string& override, bool override_in_new_tabs) = 0; - virtual const std::string& GetUserAgentOverride() const = 0; + virtual const std::string& GetUserAgentOverride() = 0; // Set the accessibility mode so that accessibility events are forwarded // to each WebContentsObserver. @@ -381,26 +380,26 @@ // Returns true only if the WebContentsObserver accessibility mode is // enabled. - virtual bool IsWebContentsOnlyAccessibilityModeForTesting() const = 0; + virtual bool IsWebContentsOnlyAccessibilityModeForTesting() = 0; // Returns true only if complete accessibility mode is on, meaning there's // both renderer accessibility, and a native browser accessibility tree. - virtual bool IsFullAccessibilityModeForTesting() const = 0; + virtual bool IsFullAccessibilityModeForTesting() = 0; - virtual ui::AXMode GetAccessibilityMode() const = 0; + virtual ui::AXMode GetAccessibilityMode() = 0; virtual void SetAccessibilityMode(ui::AXMode mode) = 0; virtual base::string16 DumpAccessibilityTree(bool internal) = 0; - virtual const PageImportanceSignals& GetPageImportanceSignals() const = 0; + virtual const PageImportanceSignals& GetPageImportanceSignals() = 0; // Tab navigation state ------------------------------------------------------ // Returns the current navigation properties, which if a navigation is // pending may be provisional (e.g., the navigation could result in a // download, in which case the URL would revert to what it was previously). - virtual const base::string16& GetTitle() const = 0; + virtual const base::string16& GetTitle() = 0; // Saves the given title to the navigation entry and does associated work. It // will update history and the view with the new title, and also synthesize @@ -409,35 +408,35 @@ const base::string16& title) = 0; // Returns the SiteInstance associated with the current page. - virtual SiteInstance* GetSiteInstance() const = 0; + virtual SiteInstance* GetSiteInstance() = 0; // Returns whether this WebContents is loading a resource. - virtual bool IsLoading() const = 0; + virtual bool IsLoading() = 0; // Returns the current load progress. - virtual double GetLoadProgress() const = 0; + virtual double GetLoadProgress() = 0; // Returns whether this WebContents is loading and and the load is to a // different top-level document (rather than being a navigation within the // same document) in the main frame. This being true implies that IsLoading() // is also true. - virtual bool IsLoadingToDifferentDocument() const = 0; + virtual bool IsLoadingToDifferentDocument() = 0; // Returns whether this WebContents is waiting for a first-response for the // main resource of the page. - virtual bool IsWaitingForResponse() const = 0; + virtual bool IsWaitingForResponse() = 0; // Returns the current load state and the URL associated with it. // The load state is only updated while IsLoading() is true. - virtual const net::LoadStateWithParam& GetLoadState() const = 0; - virtual const base::string16& GetLoadStateHost() const = 0; + virtual const net::LoadStateWithParam& GetLoadState() = 0; + virtual const base::string16& GetLoadStateHost() = 0; // Returns the upload progress. - virtual uint64_t GetUploadSize() const = 0; - virtual uint64_t GetUploadPosition() const = 0; + virtual uint64_t GetUploadSize() = 0; + virtual uint64_t GetUploadPosition() = 0; // Returns the character encoding of the page. - virtual const std::string& GetEncoding() const = 0; + virtual const std::string& GetEncoding() = 0; // Indicates that the tab was previously discarded. // wasDiscarded is exposed on Document after discard, see: @@ -461,10 +460,10 @@ // returned by GetPreferredSize() until all captures have ended. virtual void IncrementCapturerCount(const gfx::Size& capture_size) = 0; virtual void DecrementCapturerCount() = 0; - virtual bool IsBeingCaptured() const = 0; + virtual bool IsBeingCaptured() = 0; // Indicates/Sets whether all audio output from this WebContents is muted. - virtual bool IsAudioMuted() const = 0; + virtual bool IsAudioMuted() = 0; virtual void SetAudioMuted(bool mute) = 0; // Returns true if the audio is currently audible. @@ -472,21 +471,21 @@ // Indicates whether any frame in the WebContents is connected to a Bluetooth // Device. - virtual bool IsConnectedToBluetoothDevice() const = 0; + virtual bool IsConnectedToBluetoothDevice() = 0; // Indicates whether a video is in Picture-in-Picture for |this|. - virtual bool HasPictureInPictureVideo() const = 0; + virtual bool HasPictureInPictureVideo() = 0; // Indicates whether this tab should be considered crashed. The setter will // also notify the delegate when the flag is changed. - virtual bool IsCrashed() const = 0; + virtual bool IsCrashed() = 0; virtual void SetIsCrashed(base::TerminationStatus status, int error_code) = 0; - virtual base::TerminationStatus GetCrashedStatus() const = 0; - virtual int GetCrashedErrorCode() const = 0; + virtual base::TerminationStatus GetCrashedStatus() = 0; + virtual int GetCrashedErrorCode() = 0; // Whether the tab is in the process of being destroyed. - virtual bool IsBeingDestroyed() const = 0; + virtual bool IsBeingDestroyed() = 0; // Convenience method for notifying the delegate of a navigation state // change. @@ -499,7 +498,7 @@ // Get/Set the last time that the WebContents was made active (either when it // was created or shown with WasShown()). - virtual base::TimeTicks GetLastActiveTime() const = 0; + virtual base::TimeTicks GetLastActiveTime() = 0; // Invoked when the WebContents becomes shown/hidden. A hidden WebContents // isn't painted on the screen. @@ -512,7 +511,7 @@ virtual void WasOccluded() = 0; // Returns the visibility of the WebContents' view. - virtual Visibility GetVisibility() const = 0; + virtual Visibility GetVisibility() = 0; // Returns true if the before unload and unload listeners need to be // fired. The value of this changes over time. For example, if true and the @@ -537,7 +536,7 @@ // Returns the outer WebContents of this WebContents if any. // Otherwise, return nullptr. - virtual WebContents* GetOuterWebContents() const = 0; + virtual WebContents* GetOuterWebContents() = 0; // Returns the root WebContents of the WebContents tree. Always returns // non-null value. @@ -659,7 +658,7 @@ // Interstitials ------------------------------------------------------------- // Various other systems need to know about our interstitials. - virtual bool ShowingInterstitialPage() const = 0; + virtual bool ShowingInterstitialPage() = 0; // Returns the currently visible interstitial, nullptr if no interstitial is // visible. Note: This returns nullptr from the time the interstitial page has @@ -667,7 +666,7 @@ // interstitial is displayed. // // Compare to InterstitialPage::GetInterstitialPage. - virtual InterstitialPage* GetInterstitialPage() const = 0; + virtual InterstitialPage* GetInterstitialPage() = 0; // Misc state & callbacks ---------------------------------------------------- @@ -709,10 +708,10 @@ base::OnceCallback<void(int64_t /* size of the file */)> callback) = 0; // Returns the contents MIME type after a navigation. - virtual const std::string& GetContentsMimeType() const = 0; + virtual const std::string& GetContentsMimeType() = 0; // Returns true if this WebContents will notify about disconnection. - virtual bool WillNotifyDisconnection() const = 0; + virtual bool WillNotifyDisconnection() = 0; // Returns the settings which get passed to the renderer. virtual content::RendererPreferences* GetMutableRendererPrefs() = 0; @@ -734,17 +733,17 @@ // such as closing the window. The setter is maintained by TabStripModel, and // the getter only useful from within TAB_CLOSED notification virtual void SetClosedByUserGesture(bool value) = 0; - virtual bool GetClosedByUserGesture() const = 0; + virtual bool GetClosedByUserGesture() = 0; // Gets the minimum/maximum zoom percent. - virtual int GetMinimumZoomPercent() const = 0; - virtual int GetMaximumZoomPercent() const = 0; + virtual int GetMinimumZoomPercent() = 0; + virtual int GetMaximumZoomPercent() = 0; // Set the renderer's page scale to the given factor. virtual void SetPageScale(float page_scale_factor) = 0; // Gets the preferred size of the contents. - virtual gfx::Size GetPreferredSize() const = 0; + virtual gfx::Size GetPreferredSize() = 0; // Called when the response to a pending mouse lock request has arrived. // Returns true if |allowed| is true and the mouse has been successfully @@ -768,10 +767,10 @@ // Does this have an opener (corresponding to window.opener in JavaScript) // associated with it? - virtual bool HasOpener() const = 0; + virtual bool HasOpener() = 0; // Returns the opener if HasOpener() is true, or nullptr otherwise. - virtual RenderFrameHost* GetOpener() const = 0; + virtual RenderFrameHost* GetOpener() = 0; // Returns true if this WebContents was opened by another WebContents, even // if the opener was suppressed. In contrast to HasOpener/GetOpener, the @@ -779,11 +778,11 @@ // updated. This traces all the way back, so if the original owner was closed, // but _it_ had an original owner, this will return the original owner's // original owner, etc. - virtual bool HasOriginalOpener() const = 0; + virtual bool HasOriginalOpener() = 0; // Returns the original opener if HasOriginalOpener() is true, or nullptr // otherwise. - virtual RenderFrameHost* GetOriginalOpener() const = 0; + virtual RenderFrameHost* GetOriginalOpener() = 0; // Returns the WakeLockContext accociated with this WebContents. virtual device::mojom::WakeLockContext* GetWakeLockContext() = 0; @@ -839,7 +838,7 @@ virtual void GetManifest(GetManifestCallback callback) = 0; // Returns whether the renderer is in fullscreen mode. - virtual bool IsFullscreenForCurrentTab() const = 0; + virtual bool IsFullscreenForCurrentTab() = 0; // Requests the renderer to exit fullscreen. // |will_cause_resize| indicates whether the fullscreen change causes a @@ -872,7 +871,7 @@ virtual bool IsFocusedElementEditable() = 0; // Returns true if a context menu is showing on the page. - virtual bool IsShowingContextMenu() const = 0; + virtual bool IsShowingContextMenu() = 0; // Tells the WebContents whether the context menu is showing. virtual void SetShowingContextMenu(bool showing) = 0; @@ -918,14 +917,14 @@ // Returns true if the WebContents has completed its first meaningful paint // since the last navigation. - virtual bool CompletedFirstVisuallyNonEmptyPaint() const = 0; + virtual bool CompletedFirstVisuallyNonEmptyPaint() = 0; // TODO(https://crbug.com/826293): This is a simple mitigation to validate // that an action that requires a user gesture actually has one in the // trustworthy browser process, rather than relying on the untrustworthy // renderer. This should be eventually merged into and accounted for in the // user activation work. - virtual bool HasRecentInteractiveInputEvent() const = 0; + virtual bool HasRecentInteractiveInputEvent() = 0; // Sets a flag that causes the WebContents to ignore input events. virtual void SetIgnoreInputEvents(bool ignore_input_events) = 0;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 84e89a6..35fe221 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1467,6 +1467,15 @@ // pulling the device scale factor off the WebView itself. render_widget->UpdateWebViewWithDeviceScaleFactor(); + // It may be questionable, since we create un-frozen RenderWidgets at this + // point for subframes, but we don't un-freeze the main frame's RenderWidget + // here, instead deferring until the non-provisional frame is swapped in. + // But we do need to start the creating compositor resources in parallel to + // the navigation being done with the provisional frame, so we inform the + // frozen RenderWidget to get prepared. We must abort this if we are no + // longer planning to un-freeze the RenderWidget (ie in FrameDetached). + render_widget->WarmupCompositor(); + render_frame->render_widget_ = render_widget; } else if (widget_params.routing_id != MSG_ROUTING_NONE) { // This frame is a child local root, so we require a separate RenderWidget @@ -2254,7 +2263,7 @@ // Now that all of the cleanup is complete and the browser side is notified, // start using the RenderFrameProxy. // - // The swap call deletes this RenderFrame via frameDetached. Do not access + // The swap call deletes this RenderFrame via FrameDetached. Do not access // any members after this call. // // TODO(creis): WebFrame::swap() can return false. Most of those cases @@ -2304,7 +2313,7 @@ } void RenderFrameImpl::OnDeleteFrame() { - // This will result in a call to RenderFrameImpl::frameDetached, which + // This will result in a call to RenderFrameImpl::FrameDetached, which // deletes the object. Do not access |this| after detach. frame_->Detach(); } @@ -2763,46 +2772,25 @@ if (!document_loader) return; - const WebURLRequest& failed_request = document_loader->GetRequest(); - // Notify the browser that we failed a provisional load with an error. - SendFailedProvisionalLoad(failed_request, error, frame_); + SendFailedProvisionalLoad(document_loader->GetRequest(), error, frame_); if (!ShouldDisplayErrorPageForFailedLoad(error.reason(), error.url())) return; - NavigationState* navigation_state = - NavigationState::FromDocumentLoader(document_loader); - - std::unique_ptr<blink::WebNavigationParams> navigation_params; - std::unique_ptr<DocumentState> document_state; - - // If we failed on a browser initiated request, then make sure that our error - // page load is regarded as the same browser initiated request. - if (!navigation_state->IsContentInitiated()) { - document_state = BuildDocumentStateFromParams( - navigation_state->common_params(), navigation_state->request_params(), - base::TimeTicks(), // Not used for failed navigation. - CommitNavigationCallback(), nullptr); - navigation_params = BuildNavigationParams( - navigation_state->common_params(), navigation_state->request_params(), - BuildServiceWorkerNetworkProviderForNavigation( - nullptr /* request_params */, - nullptr /* controller_service_worker_info */)); - } - // If this is a failed back/forward/reload navigation, then we need to do a // 'replace' load. This is necessary to avoid messing up session history. // Otherwise, we do a normal load, which simulates a 'go' navigation as far // as session history is concerned. - bool replace = commit_type != blink::kWebStandardCommit; + bool replace_current_item = commit_type != blink::kWebStandardCommit; - std::string error_html; - GetContentClient()->renderer()->PrepareErrorPage(this, failed_request, error, - &error_html); - LoadNavigationErrorPage(error_html, error.url(), replace, nullptr, - std::move(navigation_params), - std::move(document_state), &failed_request); + // If we failed on a browser initiated request, then make sure that our error + // page load is regarded as the same browser initiated request. + bool inherit_document_state = + !NavigationState::FromDocumentLoader(document_loader) + ->IsContentInitiated(); + LoadNavigationErrorPage(document_loader, error, base::nullopt, + replace_current_item, inherit_document_state); } void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad( @@ -2814,41 +2802,53 @@ } void RenderFrameImpl::LoadNavigationErrorPage( - const std::string& error_html, - const GURL& error_url, - bool replace, - HistoryEntry* history_entry, - std::unique_ptr<blink::WebNavigationParams> navigation_params, - std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data, - const WebURLRequest* failed_request) { + WebDocumentLoader* document_loader, + const WebURLError& error, + const base::Optional<std::string>& error_page_content, + bool replace_current_item, + bool inherit_document_state) { + WebURLRequest failed_request = document_loader->GetRequest(); + + std::string error_html; + if (error_page_content) { + error_html = error_page_content.value(); + } else { + GetContentClient()->renderer()->PrepareErrorPage(this, failed_request, + error, &error_html); + } + + std::unique_ptr<blink::WebNavigationParams> navigation_params; + std::unique_ptr<DocumentState> document_state; + + if (inherit_document_state) { + NavigationState* navigation_state = + NavigationState::FromDocumentLoader(document_loader); + document_state = BuildDocumentStateFromParams( + navigation_state->common_params(), navigation_state->request_params(), + base::TimeTicks(), // Not used for failed navigation. + CommitNavigationCallback(), nullptr); + navigation_params = BuildNavigationParams( + navigation_state->common_params(), navigation_state->request_params(), + BuildServiceWorkerNetworkProviderForNavigation( + nullptr /* request_params */, + nullptr /* controller_service_worker_info */)); + } else { + document_state = BuildDocumentState(); + } + // Make sure we never show errors in view source mode. frame_->EnableViewSourceMode(false); - blink::WebFrameLoadType frame_load_type = - history_entry ? blink::WebFrameLoadType::kBackForward - : blink::WebFrameLoadType::kStandard; - const blink::WebHistoryItem& history_item = - history_entry ? history_entry->root() : blink::WebHistoryItem(); - if (replace && frame_load_type == WebFrameLoadType::kStandard) - frame_load_type = WebFrameLoadType::kReplaceCurrentItem; + // Locally generated error pages should not be cached. + failed_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore); + failed_request.SetURL(GURL(kUnreachableWebDataURL)); - // Failed navigations will always provide a |failed_request|. Error induced - // by the client/renderer side after a commit won't have a |failed_request|. - bool is_client_redirect = !failed_request; - - WebURLRequest new_request; - if (failed_request) - new_request = *failed_request; - new_request.SetURL(GURL(kUnreachableWebDataURL)); - - // Locally generated error pages should not be cached (in particular they - // should not inherit the cache mode from |failed_request|). - new_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore); - - frame_->CommitDataNavigation(new_request, error_html, "text/html", "UTF-8", - error_url, frame_load_type, history_item, - is_client_redirect, std::move(navigation_params), - std::move(navigation_data)); + frame_->CommitDataNavigation( + failed_request, error_html, "text/html", "UTF-8", error.url(), + replace_current_item ? WebFrameLoadType::kReplaceCurrentItem + : WebFrameLoadType::kStandard, + WebHistoryItem(), false /* is_client_redirect */, + std::move(navigation_params), std::move(document_state)); } void RenderFrameImpl::DidMeaningfulLayout( @@ -2964,16 +2964,10 @@ } void RenderFrameImpl::LoadErrorPage(int reason) { - WebURLError error(reason, frame_->GetDocument().Url()); - - std::string error_html; - GetContentClient()->renderer()->PrepareErrorPage( - this, frame_->GetDocumentLoader()->GetRequest(), error, &error_html); - - LoadNavigationErrorPage( - error_html, error.url(), true /* replace */, nullptr /* history_entry */, - nullptr /* navigation_params */, nullptr /* navigation_data */, - nullptr /* failed_request */); + LoadNavigationErrorPage(frame_->GetDocumentLoader(), + WebURLError(reason, frame_->GetDocument().Url()), + base::nullopt, true /* replace_current_item */, + false /* inherit_document_state */); } void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) { @@ -3452,21 +3446,29 @@ error, &error_html); } + // Make sure we never show errors in view source mode. + frame_->EnableViewSourceMode(false); + + WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; + if (history_entry) + frame_load_type = WebFrameLoadType::kBackForward; + else if (replace) + frame_load_type = WebFrameLoadType::kReplaceCurrentItem; + + failed_request.SetURL(GURL(kUnreachableWebDataURL)); + failed_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore); + // The load of the error page can result in this frame being removed. // Use a WeakPtr as an easy way to detect whether this has occured. If so, // this method should return immediately and not touch any part of the object, // otherwise it will result in a use-after-free bug. base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); - - // Don't pass history entry for renderer initiated navigations. - bool pass_history_entry = request_params.nav_entry_id != 0; - // TODO(dgozman): if this DCHECK never triggers, we can just pass - // |history_entry| unconditionally. - DCHECK(pass_history_entry || !history_entry); - LoadNavigationErrorPage(error_html, error.url(), replace, - pass_history_entry ? history_entry.get() : nullptr, - std::move(navigation_params), - std::move(document_state), &failed_request); + frame_->CommitDataNavigation( + failed_request, error_html, "text/html", "UTF-8", error.url(), + frame_load_type, + history_entry ? history_entry->root() : blink::WebHistoryItem(), + false /* is_client_redirect */, std::move(navigation_params), + std::move(document_state)); if (!weak_this) return; @@ -3981,6 +3983,14 @@ // closing the RenderWidget we only drop the WebFrameWidget in order to also // drop its reference on the WebLocalFrameImpl for this detaching frame. render_view_->DetachWebFrameWidget(); + // In the main frame case, we WarmupCompositor() when setting up the + // WebFrameWidget, because we can't unfreeze the RenderWidget until + // navigation completes. If that navigation aborts then we detach the + // provisional main frame, and drop the WebFrameWidget. Since we then no + // longer expect to use this RenderWidget immediately, we drop any resources + // that were being prepared. This is a no-op if the RenderWidget was + // unfrozen and not in a warming up state. + render_widget_->AbortWarmupCompositor(); } else if (render_widget_) { // This closes/deletes the RenderWidget if this frame was a local root. render_widget_->CloseForFrame(); @@ -4529,23 +4539,22 @@ frame_->GetDocumentLoader()); int http_status_code = internal_data->http_status_code(); if (GetContentClient()->renderer()->HasErrorPage(http_status_code)) { - // This call may run scripts, e.g. via the beforeunload event. - std::unique_ptr<DocumentState> document_state(BuildDocumentState()); - std::unique_ptr<blink::WebNavigationParams> navigation_params = - std::make_unique<blink::WebNavigationParams>(); - navigation_params->service_worker_network_provider = - BuildServiceWorkerNetworkProviderForNavigation( - nullptr /* request_params */, nullptr /* controller_info */); - WebURLRequest failed_request = frame_->GetDocumentLoader()->GetRequest(); + WebDocumentLoader* document_loader = frame_->GetDocumentLoader(); WebURL unreachable_url = frame_->GetDocument().Url(); std::string error_html; GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError( - this, failed_request, unreachable_url, http_status_code, &error_html); - LoadNavigationErrorPage(error_html, unreachable_url, true /* replace */, - nullptr /* entry */, std::move(navigation_params), - std::move(document_state), &failed_request); + this, document_loader->GetRequest(), unreachable_url, http_status_code, + &error_html); + // This call may run scripts, e.g. via the beforeunload event, and possibly + // delete |this|. + LoadNavigationErrorPage(document_loader, + WebURLError(net::ERR_FAILED, unreachable_url), + error_html, true /* replace_current_item */, + false /* inherit_document_state */); + if (!weak_self) + return; + // Do not use |this| or |frame_| here without checking |weak_self|. } - // Do not use |this| or |frame_| here without checking |weak_self|. } void RenderFrameImpl::RunScriptsAtDocumentIdle() { @@ -5896,7 +5905,7 @@ // The proxy should always exist. If it was detached while the provisional // LocalFrame was being navigated, the provisional frame would've been - // cleaned up by RenderFrameProxy::frameDetached. See + // cleaned up by RenderFrameProxy::FrameDetached. See // https://crbug.com/526304 and https://crbug.com/568676 for context. RenderFrameProxy* proxy = RenderFrameProxy::FromRoutingID(proxy_routing_id_); CHECK(proxy);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 8359b31..5106218 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -127,7 +127,6 @@ struct FramePolicy; struct WebContextMenuData; struct WebCursorInfo; -struct WebNavigationParams; struct WebMediaPlayerAction; struct WebImeTextSpan; struct WebScrollIntoViewParams; @@ -160,7 +159,6 @@ class CompositorDependencies; class ExternalPopupMenu; class FrameRequestBlocker; -class HistoryEntry; class ManifestManager; class MediaPermissionDispatcher; class MediaStreamDeviceObserver; @@ -1130,15 +1128,12 @@ base::string16* result); // Loads the appropriate error page for the specified failure into the frame. - // |entry| is only when navigating to a history item. void LoadNavigationErrorPage( - const std::string& error_html, - const GURL& error_url, - bool replace, - HistoryEntry* history_entry, - std::unique_ptr<blink::WebNavigationParams> navigation_params, - std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data, - const blink::WebURLRequest* failed_request); + blink::WebDocumentLoader* document_loader, + const blink::WebURLError& error, + const base::Optional<std::string>& error_page_content, + bool replace_current_item, + bool inherit_document_state); void HandleJavascriptExecutionResult(const base::string16& javascript, int id,
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 6e67445..68682fd 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1888,7 +1888,7 @@ } void RenderThreadImpl::RequestNewLayerTreeFrameSink( - int routing_id, + int widget_routing_id, scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue, const GURL& url, LayerTreeFrameSinkCallback callback, @@ -1933,7 +1933,7 @@ #if defined(USE_AURA) if (features::IsMultiProcessMash()) { - if (!RendererWindowTreeClient::Get(routing_id)) { + if (!RendererWindowTreeClient::Get(widget_routing_id)) { std::move(callback).Run(nullptr); return; } @@ -1944,12 +1944,13 @@ std::move(callback).Run(nullptr); return; } - RendererWindowTreeClient::Get(routing_id) + RendererWindowTreeClient::Get(widget_routing_id) ->RequestLayerTreeFrameSink( gpu_->CreateContextProvider(std::move(channel)), GetGpuMemoryBufferManager(), std::move(callback)); frame_sink_provider_->RegisterRenderFrameMetadataObserver( - routing_id, std::move(render_frame_metadata_observer_client_request), + widget_routing_id, + std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer_ptr)); return; } @@ -1964,10 +1965,11 @@ if (is_gpu_compositing_disabled_) { DCHECK(!layout_test_mode()); frame_sink_provider_->CreateForWidget( - routing_id, std::move(compositor_frame_sink_request), + widget_routing_id, std::move(compositor_frame_sink_request), std::move(compositor_frame_sink_client)); frame_sink_provider_->RegisterRenderFrameMetadataObserver( - routing_id, std::move(render_frame_metadata_observer_client_request), + widget_routing_id, + std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer_ptr)); std::move(callback).Run( std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>( @@ -2026,9 +2028,9 @@ if (layout_test_deps_) { if (!layout_test_deps_->UseDisplayCompositorPixelDump()) { std::move(callback).Run(layout_test_deps_->CreateLayerTreeFrameSink( - routing_id, std::move(gpu_channel_host), std::move(context_provider), - std::move(worker_context_provider), GetGpuMemoryBufferManager(), - this)); + widget_routing_id, std::move(gpu_channel_host), + std::move(context_provider), std::move(worker_context_provider), + GetGpuMemoryBufferManager(), this)); return; } else if (!params.compositor_task_runner) { // The frame sink provider expects a compositor task runner, but we might @@ -2040,12 +2042,13 @@ #if defined(OS_ANDROID) if (GetContentClient()->UsingSynchronousCompositing()) { - RenderWidget* widget = RenderWidget::FromRoutingID(routing_id); + RenderWidget* widget = RenderWidget::FromRoutingID(widget_routing_id); if (widget) { std::move(callback).Run(std::make_unique<SynchronousLayerTreeFrameSink>( std::move(context_provider), std::move(worker_context_provider), compositor_task_runner_, GetGpuMemoryBufferManager(), - sync_message_filter(), routing_id, g_next_layer_tree_frame_sink_id++, + sync_message_filter(), widget_routing_id, + g_next_layer_tree_frame_sink_id++, std::move(params.synthetic_begin_frame_source), widget->widget_input_handler_manager() ->GetSynchronousCompositorRegistry(), @@ -2057,10 +2060,11 @@ } #endif frame_sink_provider_->CreateForWidget( - routing_id, std::move(compositor_frame_sink_request), + widget_routing_id, std::move(compositor_frame_sink_request), std::move(compositor_frame_sink_client)); frame_sink_provider_->RegisterRenderFrameMetadataObserver( - routing_id, std::move(render_frame_metadata_observer_client_request), + widget_routing_id, + std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer_ptr)); params.gpu_memory_buffer_manager = GetGpuMemoryBufferManager(); std::move(callback).Run( @@ -2076,11 +2080,12 @@ std::unique_ptr<cc::SwapPromise> RenderThreadImpl::RequestCopyOfOutputForLayoutTest( - int32_t routing_id, + int32_t widget_routing_id, std::unique_ptr<viz::CopyOutputRequest> request) { DCHECK(layout_test_deps_ && !layout_test_deps_->UseDisplayCompositorPixelDump()); - return layout_test_deps_->RequestCopyOfOutput(routing_id, std::move(request)); + return layout_test_deps_->RequestCopyOfOutput(widget_routing_id, + std::move(request)); } std::unique_ptr<blink::WebMediaStreamCenter>
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index a831902..a9d0667 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -268,7 +268,7 @@ using LayerTreeFrameSinkCallback = base::OnceCallback<void(std::unique_ptr<cc::LayerTreeFrameSink>)>; void RequestNewLayerTreeFrameSink( - int routing_id, + int widget_routing_id, scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue, const GURL& url, LayerTreeFrameSinkCallback callback, @@ -280,7 +280,7 @@ blink::AssociatedInterfaceRegistry* GetAssociatedInterfaceRegistry(); std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest( - int32_t routing_id, + int32_t widget_routing_id, std::unique_ptr<viz::CopyOutputRequest> request); // True if we are running layout tests. This currently disables forwarding
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index ec352c5..68f6d85 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -421,6 +421,7 @@ was_shown_time_(base::TimeTicks::Now()), current_content_source_id_(0), widget_binding_(this, std::move(widget_request)), + warmup_weak_ptr_factory_(this), weak_ptr_factory_(this) { DCHECK_NE(routing_id_, MSG_ROUTING_NONE); DCHECK(RenderThread::Get()); @@ -972,7 +973,7 @@ // For widgets that are never visible, we don't start the compositor, so we // never get a request for a cc::LayerTreeFrameSink. DCHECK(!compositor_never_visible_); - // Inactive RenderWidgets should not be doing any compositing. + // Frozen RenderWidgets should not be doing any compositing. DCHECK(!is_frozen_); if (is_closing()) { @@ -990,6 +991,23 @@ if (for_child_local_root_frame_) CHECK(GetFrameWidget()); + // If we have a warmup in progress, wait for that and store the callback + // to be run when the warmup completes. + if (warmup_frame_sink_request_pending_) { + after_warmup_callback_ = std::move(callback); + return; + } + // If a warmup previously completed, use the result. + if (warmup_frame_sink_) { + std::move(callback).Run(std::move(warmup_frame_sink_)); + return; + } + + DoRequestNewLayerTreeFrameSink(std::move(callback)); +} + +void RenderWidget::DoRequestNewLayerTreeFrameSink( + LayerTreeFrameSinkCallback callback) { // TODO(jonross): have this generated by the LayerTreeFrameSink itself, which // would then handle binding. mojom::RenderFrameMetadataObserverPtr ptr; @@ -1613,6 +1631,55 @@ StartCompositor(); } +void RenderWidget::WarmupCompositor() { + DCHECK(is_frozen_); + + // Tests have no RenderThreadImpl /o\. + if (!RenderThreadImpl::current()) + return; + + // Keeping things simple. This would cancel any outstanding warmup if we + // happened to have one (this should be basically impossible). This avoids any + // extra book keeping about the outstanding reqeust. + warmup_weak_ptr_factory_.InvalidateWeakPtrs(); + // And if we already did a warmup then we're done. + if (warmup_frame_sink_) + return; + + // Mark us pending the warmup frame sink *before* calling + // DoRequestNewLayerTreeFrameSink() as it may run the reply callback + // synchronously. So we don't want to change any state after the call + // to DoRequestNewLayerTreeFrameSink() here. + warmup_frame_sink_request_pending_ = true; + + auto cb = base::BindOnce(&RenderWidget::OnReplyForWarmupCompositor, + warmup_weak_ptr_factory_.GetWeakPtr()); + DoRequestNewLayerTreeFrameSink(std::move(cb)); +} + +void RenderWidget::OnReplyForWarmupCompositor( + std::unique_ptr<cc::LayerTreeFrameSink> sink) { + warmup_frame_sink_request_pending_ = false; + + if (after_warmup_callback_) + std::move(after_warmup_callback_).Run(std::move(sink)); + else + warmup_frame_sink_ = std::move(sink); +} + +void RenderWidget::AbortWarmupCompositor() { + warmup_frame_sink_request_pending_ = false; + // Drop any pending warmup. + warmup_weak_ptr_factory_.InvalidateWeakPtrs(); + // And drop any completed one. + warmup_frame_sink_.reset(); + + // If we had saved a callback to run after warmup, just do so now indicating + // failure. + if (after_warmup_callback_) + std::move(after_warmup_callback_).Run(nullptr); +} + void RenderWidget::DoDeferredClose() { Send(new WidgetHostMsg_Close(routing_id_)); }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index e181fd9..db21d9a 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -240,6 +240,20 @@ void SetIsFrozen(bool is_frozen); bool is_frozen() const { return is_frozen_; } + // When a RenderWidget is created, even if frozen, if we expect to unfreeze + // and use the RenderWidget imminently, then we want to pre-emptively start + // the process of getting the resources needed for the compositor. This helps + // to parallelize the critical path to first pixels with the loading process. + // This should only be called when the RenderWidget is frozen, otherwise it + // would be redundant at best. Non-frozen RenderWidgets will start to warmup + // immediately on their own. + void WarmupCompositor(); + // If after calling WarmupCompositor() we can determine that the RenderWidget + // does not expect to be used shortly after all, call this to cancel the + // warmup process and release any unused resources that had been created by + // it. + void AbortWarmupCompositor(); + // This is true once a Close IPC has been received. The actual action of // closing must be done on another stack frame, in case the IPC receipt // is in a nested message loop and will unwind back up to javascript (from @@ -752,6 +766,15 @@ // belongs to the frame tree associated with this RenderWidget. blink::WebLocalFrame* GetFocusedWebLocalFrameInWidget() const; + // Called with the resulting frame sink from WarmupCompositor() since frame + // sink creation can be asynchronous. + void OnReplyForWarmupCompositor(std::unique_ptr<cc::LayerTreeFrameSink> sink); + + // Common code shared to execute the creation of a LayerTreeFrameSink, shared + // by the warmup and standard request paths. Callers should verify they really + // want to do this before calling it as this method does no verification. + void DoRequestNewLayerTreeFrameSink(LayerTreeFrameSinkCallback callback); + // Routing ID that allows us to communicate to the parent browser process // RenderWidgetHost. const int32_t routing_id_; @@ -925,6 +948,18 @@ // Wraps the |webwidget_| as a MouseLockDispatcher::LockTarget interface. std::unique_ptr<MouseLockDispatcher::LockTarget> webwidget_mouse_lock_target_; + // Set to true while a warmup is in progress. Set to false if the warmup is + // completed or aborted. If aborted, the reply callback is also cancelled by + // invalidating the |warmup_weak_ptr_factory_|. + bool warmup_frame_sink_request_pending_ = false; + // Set after warmup completes without being aborted. This frame sink will be + // returned on the next request for a frame sink instead of creating a new + // one. + std::unique_ptr<cc::LayerTreeFrameSink> warmup_frame_sink_; + // Set if a request for a frame sink arrives while a warmup is in progress. + // Then this stores the request to be satisfied once the warmup completes. + LayerTreeFrameSinkCallback after_warmup_callback_; + viz::LocalSurfaceIdAllocation local_surface_id_allocation_from_parent_; // Indicates whether this widget has focus. @@ -994,6 +1029,10 @@ uint32_t last_capture_sequence_number_ = 0u; + // Used to generate a callback for the reply when making the warmup frame + // sink, and to cancel that callback if the warmup is aborted. + base::WeakPtrFactory<RenderWidget> warmup_weak_ptr_factory_; + base::WeakPtrFactory<RenderWidget> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidget);
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc index ed59ce3..e9a1225 100644 --- a/content/renderer/renderer_main.cc +++ b/content/renderer/renderer_main.cc
@@ -35,6 +35,7 @@ #include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_main_platform_delegate.h" #include "media/media_buildflags.h" +#include "mojo/public/cpp/bindings/mojo_buildflags.h" #include "ppapi/buildflags/buildflags.h" #include "services/service_manager/sandbox/switches.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" @@ -59,6 +60,10 @@ #include "content/renderer/pepper/pepper_plugin_registry.h" #endif +#if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED) +#include "mojo/public/cpp/bindings/lib/test_random_mojo_delays.h" +#endif + namespace content { namespace { @@ -208,6 +213,10 @@ if (need_sandbox) should_run_loop = platform.EnableSandbox(); +#if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED) + mojo::BeginRandomMojoDelays(); +#endif + base::HighResolutionTimerManager hi_res_timer_manager; if (should_run_loop) {
diff --git a/content/test/data/browsing_data/media_license.html b/content/test/data/browsing_data/media_license.html new file mode 100644 index 0000000..5768f2a --- /dev/null +++ b/content/test/data/browsing_data/media_license.html
@@ -0,0 +1,81 @@ +<html> +<script> + + function success_() { + domAutomationController.send(true); + } + + function failure_() { + domAutomationController.send(false); + } + + // EME creates session IDs dynamically, so we have no idea what it will be. + // As the tests only need to create a single session, keep track of the + // last session ID created. + var savedSessionId = 'UnknownSessionId'; + + function createPersistentSession() { + // This function creates a persistent-license type session, and resolves + // with the created session object on success. + return navigator.requestMediaKeySystemAccess( + 'org.chromium.externalclearkey', [{ + initDataTypes: ['keyids'], + audioCapabilities: [ + // Include a set of codecs that should cover all user agents. + {contentType: 'audio/mp4; codecs="mp4a.40.2"'}, + {contentType: 'audio/webm; codecs="opus"'} + ], + persistentState: 'required', + sessionTypes: ['persistent-license'], + }]) + .then(function(access) { + return access.createMediaKeys(); + }) + .then(function(mediaKeys) { + return mediaKeys.createSession('persistent-license'); + }); + } + + function handleMessageEvent(e) { + var session = e.target; + var te = new TextEncoder(); + var license = te.encode( + '{"keys":[{"kty":"oct","k":"tQ0bJVWb6b0KPL6KtZIy_A","kid":"LwVHf8JLtPrv2GUXFW2v_A"}],"type":"persistent-license"}'); + + savedSessionId = session.sessionId; + session.update(license).then(success_, failure_); + } + + function setMediaLicense() { + var te = new TextEncoder(); + var initData = te.encode('{"kids":["LwVHf8JLtPrv2GUXFW2v_A"]}'); + + createPersistentSession().then(function(session) { + // generateRequest() will trigger a 'message' event, which we need to + // wait for in order to call update() which provides the license. + session.addEventListener('message', handleMessageEvent, false); + return session.generateRequest('keyids', initData); + }) + // Success is reported from handleMessageEvent(). + .catch(failure_); + } + + function hasMediaLicense() { + createPersistentSession().then(function(session) { + return session.load(savedSessionId); + }) + .then(function(result) { + // |result| is a boolean, indicating if the session was loaded or not. + domAutomationController.send(result); + }) + .catch(failure_); + } +</script> + +<body> + This page is used to test creation and deletion of Media Licenses. + The functions are called from BrowsingDataRemoverBrowserTest::HasDataForType + and BrowsingDataRemoverBrowserTest::SetDataForType. +</body> + +</html> \ No newline at end of file
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 9735dad..d0b64720 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -404,40 +404,14 @@ ['win', 'passthrough', 'vulkan'], bug=2708) # ANGLE bug ID self.Fail('conformance/canvas/canvas-test.html', ['win', 'passthrough', 'vulkan'], bug=2929) # ANGLE bug ID - self.Fail('conformance/canvas/canvas-zero-size.html', - ['win', 'passthrough', 'vulkan'], bug=2918) # ANGLE bug ID self.Fail('conformance/context/' + 'context-attribute-preserve-drawing-buffer.html', ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID - self.Fail('conformance/extensions/webgl-debug-shaders.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/extensions/webgl-draw-buffers.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/bugs/sampler-array-using-loop-index.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/bugs/uniforms-should-not-lose-values.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/bugs/' + - 'varying-arrays-should-not-be-reversed.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/functions/glsl-function*', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/matrices/glsl-mat3-construction.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/matrices/glsl-mat4-to-mat3.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/misc/shader-with-non-reserved-words.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/misc/shader-with-reserved-words.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID self.Fail('conformance/glsl/misc/' + 'shader-with-short-circuiting-operators.html', ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID - self.Fail('conformance/glsl/misc/' + - 'uninitialized-local-global-variables.html', - ['win', 'passthrough', 'vulkan'], bug=2909) # ANGLE bug ID self.Fail('conformance/misc/uninitialized-test.html', - ['win', 'passthrough', 'vulkan'], bug=2722) # ANGLE bug ID + ['win', 'passthrough', 'vulkan'], bug=2987) # ANGLE bug ID self.Fail('conformance/more/functions/copyTexSubImage2D.html', ['win', 'passthrough', 'vulkan'], bug=2911) # ANGLE bug ID self.Fail('conformance/offscreencanvas/context-lost-restored-worker.html', @@ -458,23 +432,6 @@ ['win', 'passthrough', 'vulkan'], bug=0) # ANGLE bug ID self.Fail('conformance/rendering/preservedrawingbuffer-leak.html', ['win', 'passthrough', 'vulkan'], bug=2919) # ANGLE bug ID - self.Fail('conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_byte.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID - self.Fail('conformance/textures/canvas/' + - 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID - self.Fail('conformance/textures/canvas/' + - 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID - self.Fail('conformance/textures/image_bitmap_from_canvas/' + - 'tex-2d-rgb-rgb-unsigned_byte.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID - self.Fail('conformance/textures/image_bitmap_from_canvas/' + - 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID - self.Fail('conformance/textures/image_bitmap_from_canvas/' + - 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID self.Fail('conformance/textures/misc/copy-tex-image-and-sub-image-2d.html', ['win', 'passthrough', 'vulkan'], bug=2722) # ANGLE bug ID self.Fail('conformance/textures/misc/' + @@ -497,15 +454,6 @@ ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID self.Fail('conformance/textures/misc/texture-mips.html', ['win', 'passthrough', 'vulkan'], bug=2722) # ANGLE bug ID - self.Fail('conformance/textures/webgl_canvas/' + - 'tex-2d-rgb-rgb-unsigned_byte.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID - self.Fail('conformance/textures/webgl_canvas/' + - 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID - self.Fail('conformance/textures/webgl_canvas/' + - 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', - ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID self.Fail('conformance/uniforms/out-of-bounds-uniform-array-access.html', ['win', 'passthrough', 'vulkan'], bug=2921) # ANGLE bug ID self.Fail('WebglExtension_ANGLE_instanced_arrays', @@ -522,8 +470,6 @@ ['win', 'passthrough', 'vulkan'], bug=2899) # ANGLE bug ID self.Fail('WebglExtension_EXT_sRGB', ['win', 'passthrough', 'vulkan'], bug=2900) # ANGLE bug ID - self.Fail('WebglExtension_EXT_texture_filter_anisotropic', - ['win', 'passthrough', 'vulkan'], bug=2901) # ANGLE bug ID self.Fail('WebglExtension_OES_element_index_uint', ['win', 'passthrough', 'vulkan'], bug=2902) # ANGLE bug ID self.Fail('WebglExtension_OES_standard_derivatives', @@ -582,8 +528,7 @@ ['win', 'passthrough', 'vulkan', 'amd'], bug=2922) # ANGLE bug ID self.Fail('conformance/rendering/clipping-wide-points.html', ['win', 'passthrough', 'vulkan', 'amd'], bug=2722) # ANGLE bug ID - self.Fail('conformance/textures/image_bitmap_from_canvas/' + - 'tex-2d-rgba-rgba-unsigned_byte.html', + self.Fail('conformance/textures/image_bitmap_from_canvas/*', ['win', 'passthrough', 'vulkan', 'amd'], bug=2913) # ANGLE bug ID self.Fail('deqp/data/gles2/shaders/conversions.html', ['win', 'passthrough', 'vulkan', 'amd'], bug=2926) # ANGLE bug ID
diff --git a/content/test/mock_render_widget_host_delegate.cc b/content/test/mock_render_widget_host_delegate.cc index bb23893..721d4cb 100644 --- a/content/test/mock_render_widget_host_delegate.cc +++ b/content/test/mock_render_widget_host_delegate.cc
@@ -53,7 +53,7 @@ return &text_input_manager_; } -bool MockRenderWidgetHostDelegate::IsFullscreenForCurrentTab() const { +bool MockRenderWidgetHostDelegate::IsFullscreenForCurrentTab() { return is_fullscreen_; }
diff --git a/content/test/mock_render_widget_host_delegate.h b/content/test/mock_render_widget_host_delegate.h index 048ff0de..78bbdc5ed 100644 --- a/content/test/mock_render_widget_host_delegate.h +++ b/content/test/mock_render_widget_host_delegate.h
@@ -47,7 +47,7 @@ RenderWidgetHostImpl* widget_host) override; void SendScreenRects() override; TextInputManager* GetTextInputManager() override; - bool IsFullscreenForCurrentTab() const override; + bool IsFullscreenForCurrentTab() override; private: std::unique_ptr<NativeWebKeyboardEvent> last_event_;
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc index f5809ec..f0bccb8 100644 --- a/content/test/test_web_contents.cc +++ b/content/test/test_web_contents.cc
@@ -81,13 +81,12 @@ EXPECT_FALSE(expect_set_history_offset_and_length_); } -TestRenderFrameHost* TestWebContents::GetMainFrame() const { +TestRenderFrameHost* TestWebContents::GetMainFrame() { return static_cast<TestRenderFrameHost*>(WebContentsImpl::GetMainFrame()); } -TestRenderViewHost* TestWebContents::GetRenderViewHost() const { - return static_cast<TestRenderViewHost*>( - WebContentsImpl::GetRenderViewHost()); +TestRenderViewHost* TestWebContents::GetRenderViewHost() { + return static_cast<TestRenderViewHost*>(WebContentsImpl::GetRenderViewHost()); } TestRenderFrameHost* TestWebContents::GetPendingMainFrame() { @@ -107,14 +106,14 @@ return g_next_image_download_id; } -const GURL& TestWebContents::GetLastCommittedURL() const { +const GURL& TestWebContents::GetLastCommittedURL() { if (last_committed_url_.is_valid()) { return last_committed_url_; } return WebContentsImpl::GetLastCommittedURL(); } -const base::string16& TestWebContents::GetTitle() const { +const base::string16& TestWebContents::GetTitle() { if (title_) return title_.value();
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h index 880b4ae..7fc8011 100644 --- a/content/test/test_web_contents.h +++ b/content/test/test_web_contents.h
@@ -53,16 +53,16 @@ static TestWebContents* Create(const CreateParams& params); // WebContentsImpl overrides (returning the same values, but in Test* types) - TestRenderFrameHost* GetMainFrame() const override; - TestRenderViewHost* GetRenderViewHost() const override; + TestRenderFrameHost* GetMainFrame() override; + TestRenderViewHost* GetRenderViewHost() override; // Overrides to avoid establishing Mojo connection with renderer process. int DownloadImage(const GURL& url, bool is_favicon, uint32_t max_bitmap_size, bool bypass_cache, ImageDownloadCallback callback) override; - const GURL& GetLastCommittedURL() const override; - const base::string16& GetTitle() const override; + const GURL& GetLastCommittedURL() override; + const base::string16& GetTitle() override; // WebContentsTester implementation. void CommitPendingNavigation() override;
diff --git a/device/fido/authenticator_get_assertion_response.cc b/device/fido/authenticator_get_assertion_response.cc index dc635d4..44d304b 100644 --- a/device/fido/authenticator_get_assertion_response.cc +++ b/device/fido/authenticator_get_assertion_response.cc
@@ -36,9 +36,15 @@ if (key_handle.empty()) return base::nullopt; - auto flags = u2f_data.subspan<kFlagIndex, kFlagLength>(); + auto flags = u2f_data.subspan<kFlagIndex, kFlagLength>()[0]; + if (flags & + (static_cast<uint8_t>(AuthenticatorData::Flag::kExtensionDataIncluded) | + static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation))) { + // U2F responses cannot assert CTAP2 features. + return base::nullopt; + } auto counter = u2f_data.subspan<kCounterIndex, kCounterLength>(); - AuthenticatorData authenticator_data(relying_party_id_hash, flags[0], counter, + AuthenticatorData authenticator_data(relying_party_id_hash, flags, counter, base::nullopt); auto signature =
diff --git a/device/fido/ctap_response_unittest.cc b/device/fido/ctap_response_unittest.cc index 8feeffa..609965c 100644 --- a/device/fido/ctap_response_unittest.cc +++ b/device/fido/ctap_response_unittest.cc
@@ -530,6 +530,21 @@ EXPECT_FALSE(response); } +TEST(CTAPResponseTest, TestParseU2fSignWithCTAP2Flags) { + std::vector<uint8_t> sign_response = GetTestSignResponse(); + // Set two flags that should only be set in CTAP2 responses and expect parsing + // to fail. + sign_response[0] |= + static_cast<uint8_t>(AuthenticatorData::Flag::kExtensionDataIncluded); + sign_response[0] |= + static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation); + + auto response = AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse( + test_data::kApplicationParameter, sign_response, + GetTestCredentialRawIdBytes()); + EXPECT_FALSE(response); +} + TEST(CTAPResponseTest, TestParseU2fSignWithNullCorruptedCounter) { // A sign response of less than 5 bytes. auto response = AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
diff --git a/docs/cipd.md b/docs/cipd.md index f9e438a..e689e9a5 100644 --- a/docs/cipd.md +++ b/docs/cipd.md
@@ -121,11 +121,6 @@ To actually create your package, you'll need: - the cipd.yaml file (described above) - - a package version. For third-party packages, this should typically include - the version of the third-party package itself. If you want to support future - modifications within a given version of a third-party package (e.g., if you - want to make chromium-specific changes), it's best to include a suffix with - a numerical component. - [permission](#permissions-in-cipd). Once you have those, you can create your package like so: @@ -134,9 +129,17 @@ # Assuming that the third-party dependency in question is at version 1.2.3 # and this is the first chromium revision of that version. $ cipd auth-login # One-time auth. -$ cipd create --pkg-def cipd.yaml -tag version:1.2.3-cr0 +$ cipd create --pkg-def cipd.yaml +... +[P114210 10:14:17.215 client.go:931 I] cipd: instance +chromium/third_party/sample_cipd_dep:TX7HeY1_1JLwFVx-xiETOpT8YK4W5CbyO26SpmaMA0IC was +successfully registered ``` +Take note of the instance ID printed in the log +(`TX7HeY1_1JLwFVx-xiETOpT8YK4W5CbyO26SpmaMA0IC` in the example above). +You'll be adding it to DEPS momentarily. + ### 5. Add your CIPD package to DEPS You can add your package to DEPS by adding an entry of the following form to @@ -154,7 +157,7 @@ 'packages': [ { 'package': 'chromium/third_party/sample_cipd_dep', - 'version': 'version:1.2.3-cr0', + 'version': 'TX7HeY1_1JLwFVx-xiETOpT8YK4W5CbyO26SpmaMA0IC', }, ], @@ -168,8 +171,8 @@ ``` This will result in CIPD package `chromium/third_party/sample_cipd_dep` at -`version:1.2.3-cr0` being installed in `src/third_party/sample_cipd_dep` -(relative to the gclient root directory). +`TX7HeY1_1JLwFVx-xiETOpT8YK4W5CbyO26SpmaMA0IC` being installed in +`src/third_party/sample_cipd_dep` (relative to the gclient root directory). ## Updating a CIPD dependency
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc index 6a88e39e..585657e 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
@@ -83,7 +83,7 @@ } HostID GenerateHostIDFromEmbedder(const extensions::Extension* extension, - const content::WebContents* web_contents) { + content::WebContents* web_contents) { if (extension) return HostID(HostID::EXTENSIONS, extension->id());
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc index 867cbca..33c09e4 100644 --- a/extensions/browser/guest_view/web_view/web_view_apitest.cc +++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -832,4 +832,8 @@ RunTest("testFocus", "web_view/no_internal_calls_to_user_code", false); } +IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestClosedShadowRoot) { + RunTest("testClosedShadowRoot", "web_view/apitest"); +} + } // namespace extensions
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index 5be5c1b09..fde870c 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc
@@ -450,7 +450,7 @@ } const Extension* ProcessManager::GetExtensionForWebContents( - const content::WebContents* web_contents) { + content::WebContents* web_contents) { if (!web_contents->GetSiteInstance()) return nullptr; const Extension* extension =
diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h index dfbd40b58..73cf098 100644 --- a/extensions/browser/process_manager.h +++ b/extensions/browser/process_manager.h
@@ -118,7 +118,7 @@ // Returns the extension associated with the main frame of the given // |web_contents|, or null if there isn't one. const Extension* GetExtensionForWebContents( - const content::WebContents* web_contents); + content::WebContents* web_contents); // Getter and setter for the lazy background page's keepalive count. This is // the count of how many outstanding "things" are keeping the page alive.
diff --git a/extensions/browser/script_executor.h b/extensions/browser/script_executor.h index ce07949..0e5b2407 100644 --- a/extensions/browser/script_executor.h +++ b/extensions/browser/script_executor.h
@@ -36,7 +36,7 @@ // Callback that ScriptExecutor uses to notify when content scripts and/or // tabs.executeScript calls run on a page. using ScriptsExecutedNotification = base::RepeatingCallback< - void(const content::WebContents*, const ExecutingScriptsMap&, const GURL&)>; + void(content::WebContents*, const ExecutingScriptsMap&, const GURL&)>; // Interface for executing extension content scripts (e.g. executeScript) as // described by the ExtensionMsg_ExecuteCode_Params IPC, and notifying the
diff --git a/extensions/common/manifest_handlers/content_capabilities_handler.cc b/extensions/common/manifest_handlers/content_capabilities_handler.cc index 68aa79b..3ce1ed7 100644 --- a/extensions/common/manifest_handlers/content_capabilities_handler.cc +++ b/extensions/common/manifest_handlers/content_capabilities_handler.cc
@@ -8,7 +8,6 @@ #include "base/command_line.h" #include "base/lazy_instance.h" -#include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -111,8 +110,7 @@ keys::kContentCapabilities, permission_name)); } else { - info->permissions.insert( - base::WrapUnique(permission_info->CreateAPIPermission())); + info->permissions.insert(permission_info->CreateAPIPermission()); } }
diff --git a/extensions/common/permissions/api_permission.cc b/extensions/common/permissions/api_permission.cc index 62e00ad4..47d791a 100644 --- a/extensions/common/permissions/api_permission.cc +++ b/extensions/common/permissions/api_permission.cc
@@ -112,9 +112,10 @@ APIPermissionInfo::~APIPermissionInfo() { } -APIPermission* APIPermissionInfo::CreateAPIPermission() const { - return api_permission_constructor_ ? - api_permission_constructor_(this) : new SimpleAPIPermission(this); +std::unique_ptr<APIPermission> APIPermissionInfo::CreateAPIPermission() const { + if (api_permission_constructor_) + return api_permission_constructor_(this); + return std::make_unique<SimpleAPIPermission>(this); } } // namespace extensions
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h index d129d777..044e431 100644 --- a/extensions/common/permissions/api_permission.h +++ b/extensions/common/permissions/api_permission.h
@@ -380,7 +380,8 @@ kFlagSupportsContentCapabilities = 1 << 5, }; - typedef APIPermission* (*APIPermissionConstructor)(const APIPermissionInfo*); + using APIPermissionConstructor = + std::unique_ptr<APIPermission> (*)(const APIPermissionInfo*); typedef std::set<APIPermission::ID> IDSet; @@ -398,7 +399,7 @@ ~APIPermissionInfo(); // Creates a APIPermission instance. - APIPermission* CreateAPIPermission() const; + std::unique_ptr<APIPermission> CreateAPIPermission() const; int flags() const { return flags_; }
diff --git a/extensions/common/permissions/api_permission_set.cc b/extensions/common/permissions/api_permission_set.cc index 3e5df07..80cbe37 100644 --- a/extensions/common/permissions/api_permission_set.cc +++ b/extensions/common/permissions/api_permission_set.cc
@@ -5,7 +5,6 @@ #include "extensions/common/permissions/api_permission_set.h" #include "base/logging.h" -#include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" @@ -133,7 +132,7 @@ const APIPermissionInfo* permission_info = PermissionsInfo::GetInstance()->GetByID(id); DCHECK(permission_info); - insert(base::WrapUnique(permission_info->CreateAPIPermission())); + insert(permission_info->CreateAPIPermission()); } void APIPermissionSet::insert(std::unique_ptr<APIPermission> permission) {
diff --git a/extensions/common/permissions/api_permission_set_unittest.cc b/extensions/common/permissions/api_permission_set_unittest.cc index d081cfa..d3ea00b 100644 --- a/extensions/common/permissions/api_permission_set_unittest.cc +++ b/extensions/common/permissions/api_permission_set_unittest.cc
@@ -40,8 +40,8 @@ const APIPermissionInfo* permission_info = PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket); - std::unique_ptr<APIPermission> permission( - permission_info->CreateAPIPermission()); + std::unique_ptr<APIPermission> permission = + permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -76,7 +76,7 @@ apis2.insert(APIPermission::kPower); apis2.insert(APIPermission::kSerial); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -90,7 +90,7 @@ expected_apis.insert(APIPermission::kPower); expected_apis.insert(APIPermission::kSerial); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -126,8 +126,8 @@ // Intersection with an empty set. apis1.insert(APIPermission::kAudioCapture); apis1.insert(APIPermission::kDns); - std::unique_ptr<APIPermission> permission( - permission_info->CreateAPIPermission()); + std::unique_ptr<APIPermission> permission = + permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -155,7 +155,7 @@ apis2.insert(APIPermission::kHid); apis2.insert(APIPermission::kPower); apis2.insert(APIPermission::kSerial); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("udp-bind::8080"); @@ -166,7 +166,7 @@ apis2.insert(std::move(permission)); expected_apis.insert(APIPermission::kAudioCapture); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("udp-bind::8080"); @@ -199,8 +199,8 @@ // Difference with an empty set. apis1.insert(APIPermission::kAudioCapture); apis1.insert(APIPermission::kDns); - std::unique_ptr<APIPermission> permission( - permission_info->CreateAPIPermission()); + std::unique_ptr<APIPermission> permission = + permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -220,7 +220,7 @@ apis2.insert(APIPermission::kHid); apis2.insert(APIPermission::kPower); apis2.insert(APIPermission::kSerial); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80"); @@ -230,7 +230,7 @@ apis2.insert(std::move(permission)); expected_apis.insert(APIPermission::kDns); - permission.reset(permission_info->CreateAPIPermission()); + permission = permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("udp-bind::8080"); @@ -261,8 +261,8 @@ apis.insert(APIPermission::kAudioCapture); apis.insert(APIPermission::kDns); - std::unique_ptr<APIPermission> permission( - permission_info->CreateAPIPermission()); + std::unique_ptr<APIPermission> permission = + permission_info->CreateAPIPermission(); { std::unique_ptr<base::ListValue> value(new base::ListValue()); value->AppendString("tcp-connect:*.example.com:80");
diff --git a/extensions/common/permissions/base_set_operators.h b/extensions/common/permissions/base_set_operators.h index 48cf9a2..7e878367 100644 --- a/extensions/common/permissions/base_set_operators.h +++ b/extensions/common/permissions/base_set_operators.h
@@ -11,7 +11,7 @@ #include <map> #include <memory> -#include "base/memory/linked_ptr.h" +#include "base/logging.h" namespace extensions { @@ -31,8 +31,7 @@ typedef typename BaseSetOperatorsTraits<T>::ElementType ElementType; typedef typename BaseSetOperatorsTraits<T>::ElementIDType ElementIDType; - // TODO(devlin): Un-link-ptr-ify this. - using Map = std::map<ElementIDType, linked_ptr<ElementType>>; + using Map = std::map<ElementIDType, std::unique_ptr<ElementType>>; class const_iterator : public std::iterator<std::input_iterator_tag, const ElementType*> { @@ -249,7 +248,7 @@ void insert(std::unique_ptr<ElementType> item) { ElementIDType id = item->id(); - map_[id].reset(item.release()); + map_[id] = std::move(item); } size_t size() const { return map_.size(); }
diff --git a/extensions/common/permissions/extensions_api_permissions.cc b/extensions/common/permissions/extensions_api_permissions.cc index a89e9ed..2ce55ed2 100644 --- a/extensions/common/permissions/extensions_api_permissions.cc +++ b/extensions/common/permissions/extensions_api_permissions.cc
@@ -6,6 +6,8 @@ #include <stddef.h> +#include <memory> + #include "extensions/common/api/declarative_net_request/constants.h" #include "extensions/common/permissions/api_permission.h" #include "extensions/common/permissions/socket_permission.h" @@ -17,8 +19,9 @@ namespace { template <typename T> -APIPermission* CreateAPIPermission(const APIPermissionInfo* permission) { - return new T(permission); +std::unique_ptr<APIPermission> CreateAPIPermission( + const APIPermissionInfo* permission) { + return std::make_unique<T>(permission); } // WARNING: If you are modifying a permission message in this list, be sure to
diff --git a/extensions/renderer/resources/guest_view/guest_view_container.js b/extensions/renderer/resources/guest_view/guest_view_container.js index 17a40b9..c5ac2d1 100644 --- a/extensions/renderer/resources/guest_view/guest_view_container.js +++ b/extensions/renderer/resources/guest_view/guest_view_container.js
@@ -32,7 +32,7 @@ this.setupAttributes(); this.internalElement = this.createInternalElement$(); - this.shadowRoot = $Element.attachShadow(this.element, {mode: 'open'}); + this.shadowRoot = $Element.attachShadow(this.element, {mode: 'closed'}); $Node.appendChild(this.shadowRoot, this.internalElement); GuestViewInternalNatives.RegisterView(this.viewInstanceId, this, viewType);
diff --git a/extensions/shell/test/shell_test.cc b/extensions/shell/test/shell_test.cc index 251a882d..362eb7d 100644 --- a/extensions/shell/test/shell_test.cc +++ b/extensions/shell/test/shell_test.cc
@@ -39,7 +39,7 @@ extension_system_ = static_cast<ShellExtensionSystem*>( ExtensionSystem::Get(browser_context_)); extension_system_->FinishInitialization(); - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); base::RunLoop().RunUntilIdle(); }
diff --git a/extensions/test/data/web_view/apitest/main.js b/extensions/test/data/web_view/apitest/main.js index 582be355..d970de5 100644 --- a/extensions/test/data/web_view/apitest/main.js +++ b/extensions/test/data/web_view/apitest/main.js
@@ -1831,6 +1831,29 @@ function captureVisibleRegionDoCapture() {} +// Ensure we use the closed encapsulation mode for the guest view shadow DOM +// to prevent script from interfering with our internal elements and producing +// unexpected behaviour. +function testClosedShadowRoot() { + // Script could overwrite attachShadow to ignore the provided encapsulation + // mode. Ensure this does not happen when creating the guest view shadow + // DOM. + Element.prototype.realAttachShadow = Element.prototype.attachShadow; + Element.prototype.attachShadow = function() { + window.console.log('Tainted attachShadow was called.'); + embedder.test.fail(); + return this.realAttachShadow({mode: 'open'}); + }; + + var webview = document.createElement('webview'); + webview.src = 'data:text/html,webview test' + webview.addEventListener('loadstop', () => { + embedder.test.assertFalse(webview.shadowRoot); + embedder.test.succeed(); + }); + document.body.appendChild(webview); +} + // Tests end. embedder.test.testList = { @@ -1905,7 +1928,8 @@ 'testWebRequestAPIWithHeaders': testWebRequestAPIWithHeaders, 'testWebRequestAPIExistence': testWebRequestAPIExistence, 'testWebRequestAPIGoogleProperty': testWebRequestAPIGoogleProperty, - 'testCaptureVisibleRegion': testCaptureVisibleRegion + 'testCaptureVisibleRegion': testCaptureVisibleRegion, + 'testClosedShadowRoot': testClosedShadowRoot, }; onload = function() {
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index e46ab62..8e69787 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -2304,6 +2304,13 @@ mixins: "libfuzzer" } builders { + name: "Libfuzzer Upload Chrome OS ASan" + dimensions: "os:Ubuntu-14.04" + mixins: "fyi-ci" + # mixins: "fuzz-ci" + mixins: "libfuzzer" + } + builders { name: "Mac 10.6" dimensions: "os:Mac-10.12.2" mixins: "chromedriver-ci"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index 8f8fd20..dd58e0b 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -1474,6 +1474,11 @@ short_name: "med" } builders { + name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Chrome OS ASan" + category: "libfuzz" + short_name: "chromeos-asan" + } + builders { name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux ASan" category: "libfuzz" short_name: "linux" @@ -2570,6 +2575,10 @@ category: "chromium_afl" } builders { + name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Chrome OS ASan" + category: "chromium_libfuzzer" + } + builders { name: "buildbot/chromium.fyi/Libfuzzer Upload Linux ASan" name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux ASan" category: "chromium_libfuzzer"
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg index b6b50d8..08ebe8e 100644 --- a/infra/config/global/luci-scheduler.cfg +++ b/infra/config/global/luci-scheduler.cfg
@@ -154,6 +154,7 @@ triggers: "Jumbo Mac" triggers: "Jumbo Win x64" triggers: "Leak Detection Linux" + triggers: "Libfuzzer Upload Chrome OS ASan" triggers: "Libfuzzer Upload Linux ASan Debug" triggers: "Libfuzzer Upload Linux ASan" triggers: "Libfuzzer Upload Linux MSan" @@ -3182,6 +3183,19 @@ } job { + id: "Libfuzzer Upload Chrome OS ASan" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Libfuzzer Upload Chrome OS ASan" + } + triggering_policy: { + max_concurrent_invocations: 3 + } +} + +job { id: "Libfuzzer Upload Linux ASan" acl_sets: "default" buildbucket: {
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json index 245a3ee5..90d020b5 100644 --- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json +++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
@@ -22,17 +22,32 @@ { "include": "webrtc_tests.json", "device type": "iPhone 6s Plus", - "os": "11.4" + "os": "11.4", + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ] }, { "include": "webrtc_tests.json", "device type": "iPhone 6s", - "os": "11.4" + "os": "11.4", + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ] }, { "include": "webrtc_tests.json", "device type": "iPad Air 2", - "os": "11.4" + "os": "11.4", + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ] } ] }
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm index f655ae8e..e474ea6 100644 --- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm +++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm
@@ -28,8 +28,6 @@ #error "This file requires ARC support." #endif -DEFINE_WEB_STATE_USER_DATA_KEY(AppLauncherTabHelper); - namespace { bool IsValidAppUrl(const GURL& app_url) {
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_controller.h b/ios/chrome/browser/autofill/form_input_accessory_view_controller.h index 93bb005..8d82d8d 100644 --- a/ios/chrome/browser/autofill/form_input_accessory_view_controller.h +++ b/ios/chrome/browser/autofill/form_input_accessory_view_controller.h
@@ -18,7 +18,8 @@ // Creates and manages a custom input accessory view while the user is // interacting with a form. Also handles hiding and showing the default -// accessory view elements. +// accessory view elements. Defaults in paused state and needs to be started by +// calling |continueCustomKeyboardView|. @interface FormInputAccessoryViewController : NSObject<FormInputAccessoryConsumer>
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm index 2621200..613ae0f 100644 --- a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm +++ b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
@@ -78,6 +78,7 @@ manualFillAccessoryViewControllerDelegate { self = [super init]; if (self) { + _paused = YES; _manualFillAccessoryViewControllerDelegate = manualFillAccessoryViewControllerDelegate; if (autofill::features::IsPasswordManualFallbackEnabled()) { @@ -209,10 +210,9 @@ - (void)restoreOriginalKeyboardView { [self.manualFillAccessoryViewController reset]; - [self restoreOriginalInputAccessoryView]; + [self removeCustomInputAccessoryView]; [self.keyboardReplacementView removeFromSuperview]; self.keyboardReplacementView = nil; - self.paused = NO; } - (void)pauseCustomKeyboardView { @@ -278,11 +278,6 @@ [self.grayBackgroundView removeFromSuperview]; } -// Removes the custom input accessory views and clears the references. -- (void)restoreOriginalInputAccessoryView { - [self removeCustomInputAccessoryView]; -} - // This searches in a keyboard view hierarchy for the best candidate to // constrain a view to the keyboard. - (UIView*)recursiveGetKeyboardConstraintView:(UIView*)view {
diff --git a/ios/chrome/browser/find_in_page/find_tab_helper.mm b/ios/chrome/browser/find_in_page/find_tab_helper.mm index 0732b065..c34c39d 100644 --- a/ios/chrome/browser/find_in_page/find_tab_helper.mm +++ b/ios/chrome/browser/find_in_page/find_tab_helper.mm
@@ -18,8 +18,6 @@ const char kFindNextActionName[] = "FindNext"; const char kFindPreviousActionName[] = "FindPrevious"; -DEFINE_WEB_STATE_USER_DATA_KEY(FindTabHelper); - FindTabHelper::FindTabHelper(web::WebState* web_state) { web_state->AddObserver(this); controller_ = [[FindInPageController alloc] initWithWebState:web_state];
diff --git a/ios/chrome/browser/infobars/infobar_manager_impl.mm b/ios/chrome/browser/infobars/infobar_manager_impl.mm index c67ab9ea..d1755753 100644 --- a/ios/chrome/browser/infobars/infobar_manager_impl.mm +++ b/ios/chrome/browser/infobars/infobar_manager_impl.mm
@@ -21,8 +21,6 @@ #error "This file requires ARC support." #endif -DEFINE_WEB_STATE_USER_DATA_KEY(InfoBarManagerImpl); - namespace { infobars::InfoBarDelegate::NavigationDetails
diff --git a/ios/chrome/browser/search_engines/search_engine_tab_helper.mm b/ios/chrome/browser/search_engines/search_engine_tab_helper.mm index 36357ca9..c506036 100644 --- a/ios/chrome/browser/search_engines/search_engine_tab_helper.mm +++ b/ios/chrome/browser/search_engines/search_engine_tab_helper.mm
@@ -22,8 +22,6 @@ #error "This file requires ARC support." #endif -DEFINE_WEB_STATE_USER_DATA_KEY(SearchEngineTabHelper); - namespace { const char kCommandPrefix[] = "searchEngine"; @@ -105,8 +103,9 @@ ios::ChromeBrowserState::FromBrowserState(web_state_->GetBrowserState()); TemplateURLService* url_service = ios::TemplateURLServiceFactory::GetForBrowserState(browser_state); - if (url_service && url_service->loaded()) - url_service->UpdateProviderFavicons(driver->GetActiveURL(), icon_url); + const GURL potential_search_url = driver->GetActiveURL(); + if (url_service && url_service->loaded() && potential_search_url.is_valid()) + url_service->UpdateProviderFavicons(potential_search_url, icon_url); } // When the page is loaded, checks if |searchable_url_| has a value generated
diff --git a/ios/chrome/browser/sessions/ios_chrome_session_tab_helper.mm b/ios/chrome/browser/sessions/ios_chrome_session_tab_helper.mm index 68b8a256..46345af 100644 --- a/ios/chrome/browser/sessions/ios_chrome_session_tab_helper.mm +++ b/ios/chrome/browser/sessions/ios_chrome_session_tab_helper.mm
@@ -8,8 +8,6 @@ #error "This file requires ARC support." #endif -DEFINE_WEB_STATE_USER_DATA_KEY(IOSChromeSessionTabHelper); - IOSChromeSessionTabHelper::IOSChromeSessionTabHelper(web::WebState* web_state) : session_id_(SessionID::NewUnique()), window_id_(SessionID::InvalidValue()) {}
diff --git a/ios/chrome/browser/tabs/legacy_tab_helper.mm b/ios/chrome/browser/tabs/legacy_tab_helper.mm index bd1eef8..a204394 100644 --- a/ios/chrome/browser/tabs/legacy_tab_helper.mm +++ b/ios/chrome/browser/tabs/legacy_tab_helper.mm
@@ -10,8 +10,6 @@ #error "This file requires ARC support." #endif -DEFINE_WEB_STATE_USER_DATA_KEY(LegacyTabHelper); - // static void LegacyTabHelper::CreateForWebState(web::WebState* web_state) { CreateForWebStateInternal(web_state, nil);
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index a6280af61..2db3d5f 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -346,7 +346,6 @@ "//ios/chrome/browser/ui/payments", "//ios/chrome/browser/ui/popup_menu", "//ios/chrome/browser/ui/presenters", - "//ios/chrome/browser/ui/print", "//ios/chrome/browser/ui/qr_scanner:coordinator", "//ios/chrome/browser/ui/reading_list", "//ios/chrome/browser/ui/sad_tab",
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn index 3436677b..af226a2 100644 --- a/ios/chrome/browser/ui/authentication/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -63,7 +63,8 @@ "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/images", "//ios/public/provider/chrome/browser/signin", - "//services/identity/public/cpp:cpp", + "//services/identity/public/cpp", + "//services/identity/public/objc", "//ui/base", "//ui/gfx", "//url", @@ -200,6 +201,6 @@ "//ios/public/provider/chrome/browser/signin", "//ios/public/provider/chrome/browser/signin:test_support", "//ios/third_party/earl_grey:earl_grey+link", - "//services/identity/public/cpp:cpp", + "//services/identity/public/cpp", ] }
diff --git a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm index c25570a..f6b7eeb 100644 --- a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
@@ -5,15 +5,11 @@ #import "ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.h" #import "base/mac/foundation_util.h" -#include "components/signin/core/browser/account_tracker_service.h" -#include "components/signin/core/browser/profile_oauth2_token_service.h" -#include "components/signin/ios/browser/oauth2_token_service_observer_bridge.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/signin/account_tracker_service_factory.h" #include "ios/chrome/browser/signin/authentication_service.h" #include "ios/chrome/browser/signin/authentication_service_factory.h" #include "ios/chrome/browser/signin/chrome_identity_service_observer_bridge.h" -#include "ios/chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "ios/chrome/browser/signin/identity_manager_factory.h" #import "ios/chrome/browser/ui/authentication/resized_avatar_cache.h" #import "ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h" #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" @@ -31,6 +27,8 @@ #import "ios/third_party/material_components_ios/src/components/Dialogs/src/MaterialDialogs.h" #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" +#include "services/identity/public/cpp/identity_manager.h" +#import "services/identity/public/objc/identity_manager_observer_bridge.h" #include "ui/base/l10n/l10n_util_mac.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -39,7 +37,7 @@ namespace { -const int kMaxShownAccounts = 3; +const size_t kMaxShownAccounts = 3; const CGFloat kAccountsExtraBottomInset = 16; const CGFloat kVerticalPadding = 24; const CGFloat kButtonVerticalPadding = 16; @@ -110,16 +108,14 @@ - (void)loadModel { [super loadModel]; CollectionViewModel* model = self.collectionViewModel; + [model addSectionWithIdentifier:SectionIdentifierAccounts]; + NSMutableDictionary<NSString*, CollectionViewItem*>* mutableIdentityMap = [[NSMutableDictionary alloc] init]; - [model addSectionWithIdentifier:SectionIdentifierAccounts]; - ProfileOAuth2TokenService* oauth2_service = - ProfileOAuth2TokenServiceFactory::GetForBrowserState(_browserState); - AccountTrackerService* accountTracker = - ios::AccountTrackerServiceFactory::GetForBrowserState(_browserState); - for (const std::string& account_id : oauth2_service->GetAccounts()) { - AccountInfo account = accountTracker->GetAccountInfo(account_id); + identity::IdentityManager* identityManager = + IdentityManagerFactory::GetForBrowserState(_browserState); + for (const auto& account : identityManager->GetAccountsWithRefreshTokens()) { ChromeIdentity* identity = ios::GetChromeBrowserProvider() ->GetChromeIdentityService() ->GetIdentityWithGaiaID(account.gaia); @@ -181,10 +177,11 @@ @end -@interface SignedInAccountsViewController ()< - OAuth2TokenServiceObserverBridgeDelegate> { +@interface SignedInAccountsViewController () < + IdentityManagerObserverBridgeDelegate> { ios::ChromeBrowserState* _browserState; // Weak. - std::unique_ptr<OAuth2TokenServiceObserverBridge> _tokenServiceObserver; + std::unique_ptr<identity::IdentityManagerObserverBridge> + _identityManagerObserver; MDCDialogTransitionController* _transitionController; UILabel* _titleLabel; @@ -219,9 +216,9 @@ if (self) { _browserState = browserState; _dispatcher = dispatcher; - _tokenServiceObserver.reset(new OAuth2TokenServiceObserverBridge( - ProfileOAuth2TokenServiceFactory::GetForBrowserState(_browserState), - self)); + _identityManagerObserver = + std::make_unique<identity::IdentityManagerObserverBridge>( + IdentityManagerFactory::GetForBrowserState(_browserState), self); _transitionController = [[MDCDialogTransitionController alloc] init]; self.modalPresentationStyle = UIModalPresentationCustom; self.transitioningDelegate = _transitionController; @@ -246,13 +243,14 @@ #pragma mark UIViewController - (CGSize)preferredContentSize { - CGFloat width = MIN(kDialogMaxWidth, - self.presentingViewController.view.bounds.size.width - - 2 * kMDCMinHorizontalPadding); - OAuth2TokenService* token_service = - ProfileOAuth2TokenServiceFactory::GetForBrowserState(_browserState); + CGFloat width = std::min( + kDialogMaxWidth, self.presentingViewController.view.bounds.size.width - + 2 * kMDCMinHorizontalPadding); + identity::IdentityManager* identityManager = + IdentityManagerFactory::GetForBrowserState(_browserState); int shownAccounts = - MIN(kMaxShownAccounts, token_service->GetAccounts().size()); + std::min(kMaxShownAccounts, + identityManager->GetAccountsWithRefreshTokens().size()); CGSize maxSize = CGSizeMake(width - 2 * kHorizontalPadding, CGFLOAT_MAX); CGSize buttonSize = [_primaryButton sizeThatFits:maxSize]; CGSize infoSize = [_infoLabel sizeThatFits:maxSize]; @@ -388,12 +386,12 @@ }]; } -#pragma mark OAuth2TokenServiceObserverBridgeDelegate +#pragma mark IdentityManagerObserverBridgeDelegate -- (void)onEndBatchChanges { - ProfileOAuth2TokenService* tokenService = - ProfileOAuth2TokenServiceFactory::GetForBrowserState(_browserState); - if (tokenService->GetAccounts().empty()) { +- (void)onEndBatchOfRefreshTokenStateChanges { + identity::IdentityManager* identityManager = + IdentityManagerFactory::GetForBrowserState(_browserState); + if (identityManager->GetAccountsWithRefreshTokens().empty()) { [self dismissWithCompletion:nil]; return; }
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm b/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm index cbeaa47..9cb9c6f 100644 --- a/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm +++ b/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm
@@ -51,6 +51,9 @@ // The object that manages the currently-shown custom accessory view. @property(nonatomic, weak) id<FormInputSuggestionsProvider> currentProvider; +// YES if the first responder is a text input other than the web view. +@property(nonatomic, assign) BOOL editingUIKitTextInput; + // The form input handler. This is in charge of form navigation. @property(nonatomic, strong) FormInputAccessoryViewHandler* formInputAccessoryHandler; @@ -82,6 +85,10 @@ // Whether suggestions are disabled. @property(nonatomic, assign) BOOL suggestionsDisabled; +// YES if the latest form activity was made in a form that supports the +// accessory. +@property(nonatomic, assign) BOOL validActivityForAccessoryView; + // The WebState this instance is observing. Can be null. @property(nonatomic, assign) web::WebState* webState; @@ -227,10 +234,7 @@ - (void)keyboardWillShowWithHardwareKeyboardAttached:(BOOL)isHardwareKeyboard { self.hardwareKeyboard = isHardwareKeyboard; - if (self.lastSuggestions) { - [self updateWithProvider:self.lastProvider - suggestions:self.lastSuggestions]; - } + [self updateWithProvider:self.lastProvider suggestions:self.lastSuggestions]; } - (void)keyboardDidStayOnScreen { @@ -249,30 +253,54 @@ didRegisterFormActivity:(const autofill::FormActivityParams&)params inFrame:(web::WebFrame*)frame { DCHECK_EQ(_webState, webState); + self.validActivityForAccessoryView = NO; + + // Return early if |params| is not complete. + if (params.input_missing) { + return; + } + + // Return early if the URL can't be verified. web::URLVerificationTrustLevel trustLevel; const GURL pageURL(webState->GetCurrentURL(&trustLevel)); - if (params.input_missing || - trustLevel != web::URLVerificationTrustLevel::kAbsolute || - !web::UrlHasWebScheme(pageURL) || !webState->ContentIsHTML()) { + if (trustLevel != web::URLVerificationTrustLevel::kAbsolute) { + return; + } + + // Return early, pause and reset if the url is not HTML. + if (!web::UrlHasWebScheme(pageURL) || !webState->ContentIsHTML()) { + [self pauseCustomKeyboardView]; [self reset]; return; } + // Return early and reset if messaging is enabled but frame is missing or + // can't call JS. if (autofill::switches::IsAutofillIFrameMessagingEnabled() && (!frame || !frame->CanCallJavaScriptFunction())) { [self reset]; return; } + self.validActivityForAccessoryView = YES; + [self continueCustomKeyboardView]; + + NSString* frameID; + if (frame) { + frameID = base::SysUTF8ToNSString(frame->GetFrameId()); + } else { + frameID = base::SysUTF8ToNSString(params.frame_id); + } + + [self.formInputAccessoryHandler setLastFocusFormActivityWebFrameID:frameID]; + [self synchronizeNavigationControls]; + + // Don't look for suggestions in the next events. if (params.type == "blur" || params.type == "change" || params.type == "form_changed") { return; } - [self.formInputAccessoryHandler - setLastFocusFormActivityWebFrameID:base::SysUTF8ToNSString( - params.frame_id)]; - [self synchronizeNavigationControls]; [self retrieveSuggestionsForForm:params webState:webState]; } @@ -296,7 +324,7 @@ - (void)webStateWasShown:(web::WebState*)webState { DCHECK_EQ(_webState, webState); - [self.consumer continueCustomKeyboardView]; + [self continueCustomKeyboardView]; } - (void)webStateWasHidden:(web::WebState*)webState { @@ -311,7 +339,7 @@ if (IsIPadIdiom()) { [self reset]; } else { - [self.consumer pauseCustomKeyboardView]; + [self pauseCustomKeyboardView]; } } @@ -363,6 +391,32 @@ #pragma mark - Private +// Tells the consumer to pause the custom keyboard view. +- (void)pauseCustomKeyboardView { + [self.consumer pauseCustomKeyboardView]; +} + +// Tells the consumer to continue the custom keyboard view if the last activity +// is valid, the web state is visible, and there is no other text input. +- (void)continueCustomKeyboardView { + // Return early if the form is not a supported one. + if (!self.validActivityForAccessoryView) { + return; + } + + // Return early if the current webstate is not visible. + if (!self.webState || !self.webState->IsVisible()) { + return; + } + + // Return early if the current text input is not the web view. + if (self.editingUIKitTextInput) { + return; + } + + [self.consumer continueCustomKeyboardView]; +} + // Update the status of the consumer form navigation buttons to match the // handler state. - (void)synchronizeNavigationControls { @@ -407,6 +461,9 @@ // Resets the current provider, the consumer view and the navigation handler. As // well as reenables suggestions. - (void)reset { + self.lastSuggestions = nil; + self.lastProvider = nil; + [self.consumer restoreOriginalKeyboardView]; [self.formInputAccessoryHandler reset]; @@ -511,13 +568,15 @@ // begins editing, pause the consumer so it doesn't present the custom view over // the keyboard. - (void)handleTextInputDidBeginEditing:(NSNotification*)notification { - [self.consumer pauseCustomKeyboardView]; + self.editingUIKitTextInput = YES; + [self pauseCustomKeyboardView]; } // When any text field or text view (e.g. omnibox, settings, card unmask dialog) // ends editing, continue presenting. - (void)handleTextInputDidEndEditing:(NSNotification*)notification { - [self.consumer continueCustomKeyboardView]; + self.editingUIKitTextInput = NO; + [self continueCustomKeyboardView]; } #pragma mark - PasswordFetcherDelegate
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 6eb3837..e06f5a8c5 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -99,7 +99,6 @@ #import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/tabs/tab_model_observer.h" #import "ios/chrome/browser/tabs/tab_private.h" -#import "ios/chrome/browser/tabs/tab_title_util.h" #import "ios/chrome/browser/tabs/tab_util.h" #import "ios/chrome/browser/translate/chrome_ios_translate_client.h" #import "ios/chrome/browser/translate/language_selection_handler.h" @@ -161,7 +160,6 @@ #import "ios/chrome/browser/ui/payments/payment_request_manager.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.h" #import "ios/chrome/browser/ui/presenters/vertical_animation_container.h" -#import "ios/chrome/browser/ui/print/print_controller.h" #import "ios/chrome/browser/ui/reading_list/offline_page_native_content.h" #import "ios/chrome/browser/ui/reading_list/reading_list_menu_notifier.h" #include "ios/chrome/browser/ui/sad_tab/features.h" @@ -249,7 +247,6 @@ #import "net/base/mac/url_conversions.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/ssl/ssl_info.h" -#include "net/url_request/url_request_context_getter.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "third_party/google_toolbox_for_mac/src/iPhone/GTMUIImage+Resize.h" #include "ui/base/l10n/l10n_util.h" @@ -477,9 +474,6 @@ // Used to display the Find In Page UI. Nil if not visible. FindBarControllerIOS* _findBarController; - // Used to display the Print UI. Nil if not visible. - PrintController* _printController; - // Adapter to let BVC be the delegate for WebState. std::unique_ptr<web::WebStateDelegateBridge> _webStateDelegate; @@ -1431,8 +1425,6 @@ } [_paymentRequestManager cancelRequest]; - [_printController dismissAnimated:YES]; - _printController = nil; [self.dispatcher dismissPopupMenuAnimated:NO]; [_contextMenuCoordinator stop]; @@ -4373,17 +4365,6 @@ self.currentWebState]]; } -- (void)printTab { - if (!_printController) { - _printController = [[PrintController alloc] - initWithContextGetter:_browserState->GetRequestContext()]; - } - Tab* currentTab = self.tabModel.currentTab; - [_printController printView:[currentTab viewForPrinting] - withTitle:tab_util::GetTabTitle(currentTab.webState) - viewController:self]; -} - - (void)addToReadingList:(ReadingListAddCommand*)command { [self addToReadingListURL:[command URL] title:[command title]]; }
diff --git a/ios/chrome/browser/ui/commands/OWNERS b/ios/chrome/browser/ui/commands/OWNERS new file mode 100644 index 0000000..446fcc2 --- /dev/null +++ b/ios/chrome/browser/ui/commands/OWNERS
@@ -0,0 +1,7 @@ +edchin@chromium.org +gambard@chromium.org +marq@chromium.org +rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index 13045e7..1315a9c 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -48,9 +48,6 @@ // Bookmarks the current page. - (void)bookmarkPage; -// Prints the currently active tab. -- (void)printTab; - // Adds a page to the reading list using data in |command|. - (void)addToReadingList:(ReadingListAddCommand*)command;
diff --git a/ios/chrome/browser/ui/commands/browser_coordinator_commands.h b/ios/chrome/browser/ui/commands/browser_coordinator_commands.h index d2e2391..946d3b8f 100644 --- a/ios/chrome/browser/ui/commands/browser_coordinator_commands.h +++ b/ios/chrome/browser/ui/commands/browser_coordinator_commands.h
@@ -12,6 +12,9 @@ // and representative of the contents. @protocol BrowserCoordinatorCommands +// Prints the currently active tab. +- (void)printTab; + // Shows the Reading List UI. - (void)showReadingList;
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index b5669b0..2ce78c6 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -37,6 +37,7 @@ "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/download", "//ios/chrome/browser/ui/page_info:coordinator", + "//ios/chrome/browser/ui/print", "//ios/chrome/browser/ui/qr_scanner:coordinator", "//ios/chrome/browser/ui/reading_list", "//ios/chrome/browser/ui/recent_tabs", @@ -45,6 +46,7 @@ "//ios/chrome/browser/web:tab_helper_delegates", "//ios/chrome/browser/web_state_list", "//ios/public/provider/chrome/browser", + "//net", ] public_deps = [ "//ios/chrome/browser/ui:ui_internal",
diff --git a/ios/chrome/browser/ui/main/browser_coordinator.mm b/ios/chrome/browser/ui/main/browser_coordinator.mm index c26c269..b240c5ab 100644 --- a/ios/chrome/browser/ui/main/browser_coordinator.mm +++ b/ios/chrome/browser/ui/main/browser_coordinator.mm
@@ -9,9 +9,12 @@ #include "base/scoped_observer.h" #import "ios/chrome/browser/app_launcher/app_launcher_abuse_detector.h" #import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/download/pass_kit_tab_helper.h" #import "ios/chrome/browser/store_kit/store_kit_coordinator.h" #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" +#import "ios/chrome/browser/tabs/tab.h" +#import "ios/chrome/browser/tabs/tab_title_util.h" #import "ios/chrome/browser/ui/alert_coordinator/repost_form_coordinator.h" #import "ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h" #import "ios/chrome/browser/ui/autofill/form_input_accessory_coordinator.h" @@ -22,6 +25,7 @@ #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/download/pass_kit_coordinator.h" #import "ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h" +#import "ios/chrome/browser/ui/print/print_controller.h" #import "ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.h" #import "ios/chrome/browser/ui/reading_list/reading_list_coordinator.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h" @@ -30,6 +34,7 @@ #import "ios/chrome/browser/web/repost_form_tab_helper_delegate.h" #include "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" +#include "net/url_request/url_request_context_getter.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -60,6 +65,10 @@ // Coordinator for the PassKit UI presentation. @property(nonatomic, strong) PassKitCoordinator* passKitCoordinator; +// Used to display the Print UI. Nil if not visible. +// TODO(crbug.com/910017): Convert to coordinator. +@property(nonatomic, strong) PrintController* printController; + // Coordinator for the QR scanner. @property(nonatomic, strong) QRScannerLegacyCoordinator* qrScannerCoordinator; @@ -118,6 +127,10 @@ - (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion dismissOmnibox:(BOOL)dismissOmnibox { [self.passKitCoordinator stop]; + + [self.printController dismissAnimated:YES]; + self.printController = nil; + [self.viewController clearPresentedStateWithCompletion:completion dismissOmnibox:dismissOmnibox]; } @@ -153,6 +166,7 @@ self.appLauncherCoordinator = [[AppLauncherCoordinator alloc] initWithBaseViewController:self.viewController]; + self.formInputAccessoryCoordinator = [[FormInputAccessoryCoordinator alloc] initWithBaseViewController:self.viewController browserState:self.browserState @@ -171,6 +185,8 @@ self.passKitCoordinator = [[PassKitCoordinator alloc] initWithBaseViewController:self.viewController]; + /* PrintController is created and started by a BrowserCommand */ + self.qrScannerCoordinator = [[QRScannerLegacyCoordinator alloc] initWithBaseViewController:self.viewController]; self.qrScannerCoordinator.dispatcher = self.dispatcher; @@ -204,6 +220,8 @@ [self.passKitCoordinator stop]; self.passKitCoordinator = nil; + self.printController = nil; + [self.qrScannerCoordinator stop]; self.qrScannerCoordinator = nil; @@ -223,6 +241,19 @@ self.storeKitCoordinator = nil; } +#pragma mark - BrowserCoordinatorCommands + +- (void)printTab { + if (!self.printController) { + self.printController = [[PrintController alloc] + initWithContextGetter:self.browserState->GetRequestContext()]; + } + Tab* currentTab = self.tabModel.currentTab; + [self.printController printView:[currentTab viewForPrinting] + withTitle:tab_util::GetTabTitle(currentTab.webState) + viewController:self.viewController]; +} + - (void)showReadingList { self.readingListCoordinator = [[ReadingListCoordinator alloc] initWithBaseViewController:self.viewController
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn index 1c2ccc7a..3cd95a0 100644 --- a/ios/chrome/browser/ui/reading_list/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -20,8 +20,6 @@ "reading_list_menu_notification_delegate.h", "reading_list_menu_notifier.h", "reading_list_menu_notifier.mm", - "reading_list_side_swipe_provider.h", - "reading_list_side_swipe_provider.mm", "reading_list_table_view_item.h", "reading_list_table_view_item.mm", "reading_list_utils.h", @@ -97,7 +95,6 @@ deps = [ "resources:reading_list_empty_state", "resources:reading_list_empty_state_new", - "resources:reading_list_side_swipe", "resources:reading_list_tools_icon", "//base", "//base:i18n",
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.h b/ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.h deleted file mode 100644 index 242a917..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_SIDE_SWIPE_PROVIDER_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_SIDE_SWIPE_PROVIDER_H_ - -#import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h" - -class ReadingListModel; - -@interface ReadingListSideSwipeProvider : NSObject<SideSwipeContentProvider> -- (instancetype)initWithReadingList:(ReadingListModel*)readingListModel; -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_SIDE_SWIPE_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.mm b/ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.mm deleted file mode 100644 index fd9df181..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.mm +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.h" - -#include "base/logging.h" -#include "base/metrics/user_metrics.h" -#include "base/metrics/user_metrics_action.h" -#include "components/reading_list/core/reading_list_entry.h" -#include "components/reading_list/core/reading_list_model.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/metrics/new_tab_page_uma.h" -#include "ios/web/public/web_state/web_state.h" -#include "net/base/network_change_notifier.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -class ReadingListObserverBridge; - -@interface ReadingListSideSwipeProvider () { - // Keep a reference to detach before deallocing. - ReadingListModel* _readingListModel; // weak -} - -@end - -@implementation ReadingListSideSwipeProvider -- (instancetype)initWithReadingList:(ReadingListModel*)readingListModel { - if (self = [super init]) { - _readingListModel = readingListModel; - } - return self; -} - -- (BOOL)canGoBack { - return NO; -} - -- (void)goBack:(web::WebState*)webState { - NOTREACHED(); -} - -- (BOOL)canGoForward { - return _readingListModel->unread_size() > 0; -} - -- (UIImage*)paneIcon { - return [UIImage imageNamed:@"reading_list_side_swipe"]; -} - -- (BOOL)rotateForwardIcon { - return NO; -} - -- (void)goForward:(web::WebState*)webState { - if (!webState || _readingListModel->unread_size() == 0) { - return; - } - const ReadingListEntry* firstEntry = _readingListModel->GetFirstUnreadEntry( - net::NetworkChangeNotifier::IsOffline()); - DCHECK(firstEntry); - base::RecordAction(base::UserMetricsAction("MobileReadingListOpen")); - new_tab_page_uma::RecordAction( - ios::ChromeBrowserState::FromBrowserState(webState->GetBrowserState()), - new_tab_page_uma::ACTION_OPENED_READING_LIST_ENTRY); - - web::NavigationManager::WebLoadParams params(firstEntry->URL()); - params.transition_type = ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK; - webState->GetNavigationManager()->LoadURLWithParams(params); -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/resources/BUILD.gn b/ios/chrome/browser/ui/reading_list/resources/BUILD.gn index ade93f7..d5a3baa 100644 --- a/ios/chrome/browser/ui/reading_list/resources/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/resources/BUILD.gn
@@ -31,15 +31,6 @@ ] } -imageset("reading_list_side_swipe") { - sources = [ - "reading_list_side_swipe.imageset/Contents.json", - "reading_list_side_swipe.imageset/reading_list_side_swipe.png", - "reading_list_side_swipe.imageset/reading_list_side_swipe@2x.png", - "reading_list_side_swipe.imageset/reading_list_side_swipe@3x.png", - ] -} - imageset("reading_list_tools_icon") { sources = [ "reading_list_tools_icon.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/Contents.json b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/Contents.json deleted file mode 100644 index e4d2212..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/Contents.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "scale": "1x", - "filename": "reading_list_side_swipe.png" - }, - { - "idiom": "universal", - "scale": "2x", - "filename": "reading_list_side_swipe@2x.png" - }, - { - "idiom": "universal", - "scale": "3x", - "filename": "reading_list_side_swipe@3x.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe.png deleted file mode 100644 index ef386f07..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe@2x.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe@2x.png deleted file mode 100644 index 11a90f5a..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe@3x.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe@3x.png deleted file mode 100644 index e910790..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.imageset/reading_list_side_swipe@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/side_swipe/BUILD.gn b/ios/chrome/browser/ui/side_swipe/BUILD.gn index 240926fa..333368ed 100644 --- a/ios/chrome/browser/ui/side_swipe/BUILD.gn +++ b/ios/chrome/browser/ui/side_swipe/BUILD.gn
@@ -7,8 +7,6 @@ sources = [ "card_side_swipe_view.h", "card_side_swipe_view.mm", - "history_side_swipe_provider.h", - "history_side_swipe_provider.mm", "side_swipe_controller.h", "side_swipe_controller.mm", "side_swipe_navigation_view.h", @@ -33,6 +31,7 @@ "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/ntp", + "//ios/chrome/browser/ui/ntp:util", "//ios/chrome/browser/ui/tab_grid/grid:grid_ui", "//ios/chrome/browser/ui/tabs/requirements", "//ios/chrome/browser/ui/toolbar/public", @@ -54,6 +53,8 @@ deps = [ ":side_swipe", "//base", + "//base/test:test_support", + "//ios/chrome/browser", "//ios/chrome/browser/browser_state:test_support", "//ios/web/public/test", "//testing/gtest",
diff --git a/ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.h b/ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.h deleted file mode 100644 index 04677c1d..0000000 --- a/ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SIDE_SWIPE_HISTORY_SIDE_SWIPE_PROVIDER_H_ -#define IOS_CHROME_BROWSER_UI_SIDE_SWIPE_HISTORY_SIDE_SWIPE_PROVIDER_H_ - -#import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h" - -@class TabModel; - -@interface HistorySideSwipeProvider : NSObject<SideSwipeContentProvider> -- (instancetype)initWithTabModel:(TabModel*)tabModel; -@end - -#endif // IOS_CHROME_BROWSER_UI_SIDE_SWIPE_HISTORY_SIDE_SWIPE_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.mm b/ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.mm deleted file mode 100644 index a86e19f..0000000 --- a/ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.mm +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.h" - -#include "ios/chrome/browser/tabs/tab.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface HistorySideSwipeProvider () { - // Keep a reference to detach before deallocing. - __weak TabModel* _tabModel; // weak -} - -@end - -@implementation HistorySideSwipeProvider -- (instancetype)initWithTabModel:(TabModel*)tabModel { - self = [super init]; - if (self) { - _tabModel = tabModel; - } - return self; -} - -- (BOOL)canGoBack { - return [[_tabModel currentTab] canGoBack]; -} - -- (BOOL)canGoForward { - return [[_tabModel currentTab] canGoForward]; -} - -- (void)goForward:(web::WebState*)webState { - [[_tabModel currentTab] goForward]; -} - -- (void)goBack:(web::WebState*)webState { - [[_tabModel currentTab] goBack]; -} - -- (UIImage*)paneIcon { - return [UIImage imageNamed:@"side_swipe_navigation_back"]; -} - -- (BOOL)rotateForwardIcon { - return YES; -} - -@end
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.h b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.h index 7cc5152..0fdcd2fe 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.h +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.h
@@ -22,24 +22,6 @@ // Notification sent when the user finishes a side swipe (on tablet). extern NSString* const kSideSwipeDidStopNotification; -// A protocol for the Side Swipe controller sources. -@protocol SideSwipeContentProvider -// Returns whether this source can provide content for a back/forward side swipe -// gesture. -- (BOOL)canGoBack; -- (BOOL)canGoForward; - -// Called on completion of a back/forward gesture. -- (void)goBack:(web::WebState*)webState; -- (void)goForward:(web::WebState*)webState; - -// The icon to display in the side panel. -- (UIImage*)paneIcon; - -// Whether the icon is oriented and should be reflected on forward pane. -- (BOOL)rotateForwardIcon; -@end - @protocol SideSwipeControllerDelegate @required // Called when the horizontal stack view is done and should be removed.
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm index 198f035..57a2f27 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
@@ -9,9 +9,7 @@ #include "base/feature_list.h" #import "base/ios/block_types.h" #include "base/scoped_observer.h" -#include "components/reading_list/core/reading_list_model.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/snapshots/snapshot_cache.h" #import "ios/chrome/browser/snapshots/snapshot_cache_factory.h" #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" @@ -20,9 +18,7 @@ #import "ios/chrome/browser/ui/fullscreen/animated_scoped_fullscreen_disabler.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h" #import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.h" #import "ios/chrome/browser/ui/side_swipe/card_side_swipe_view.h" -#import "ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.h" #import "ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.h" #import "ios/chrome/browser/ui/side_swipe/side_swipe_util.h" #import "ios/chrome/browser/ui/side_swipe_gesture_recognizer.h" @@ -31,6 +27,7 @@ #import "ios/chrome/browser/ui/toolbar/public/side_swipe_toolbar_interacting.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/web/page_placeholder_tab_helper.h" +#import "ios/web/public/navigation_item.h" #import "ios/web/public/web_client.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" @@ -94,14 +91,6 @@ // Curtain over web view while waiting for it to load. UIView* curtain_; - // Provides forward/back action for history entries. - HistorySideSwipeProvider* historySideSwipeProvider_; - - // Provides forward action for reading list. - ReadingListSideSwipeProvider* readingListSideSwipeProvider_; - - __weak id<SideSwipeContentProvider> currentContentProvider_; - // The disabler that prevents the toolbar from being scrolled away when the // side swipe gesture is being recognized. std::unique_ptr<ScopedFullscreenDisabler> fullscreenDisabler_; @@ -114,6 +103,11 @@ ios::ChromeBrowserState* browserState_; } +// Whether to allow navigating from the leading edge. +@property(nonatomic, assign) BOOL leadingEdgeNavigationEnabled; +// Whether to allow navigating from the trailing edge. +@property(nonatomic, assign) BOOL trailingEdgeNavigationEnabled; + // Load grey snapshots for the next |kIpadGreySwipeTabCount| tabs in // |direction|. - (void)createGreyCache:(UISwipeGestureRecognizerDirection)direction; @@ -150,13 +144,6 @@ if (self) { model_ = model; [model_ addObserver:self]; - historySideSwipeProvider_ = - [[HistorySideSwipeProvider alloc] initWithTabModel:model_]; - - readingListSideSwipeProvider_ = [[ReadingListSideSwipeProvider alloc] - initWithReadingList:ReadingListModelFactory::GetForBrowserState( - browserState)]; - webStateObserverBridge_ = std::make_unique<web::WebStateObserverBridge>(self); scopedWebStateObserver_ = @@ -219,11 +206,17 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer: (UIGestureRecognizer*)otherGestureRecognizer { - // Only take precedence over a pan gesture recognizer so that moving up and + // Take precedence over a pan gesture recognizer so that moving up and // down while swiping doesn't trigger overscroll actions. if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) { return YES; } + // Take precedence over a WKWebView side swipe gesture. + if ([otherGestureRecognizer + isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) { + return YES; + } + return NO; } @@ -259,6 +252,16 @@ if (![gesture isEqual:swipeGestureRecognizer_]) { return NO; } + + if (gesture.direction == UISwipeGestureRecognizerDirectionRight && + !self.leadingEdgeNavigationEnabled) { + return NO; + } + + if (gesture.direction == UISwipeGestureRecognizerDirectionLeft && + !self.trailingEdgeNavigationEnabled) { + return NO; + } swipeType_ = SwipeType::CHANGE_PAGE; return YES; } @@ -402,20 +405,14 @@ } } -- (id<SideSwipeContentProvider>)contentProviderForGesture:(BOOL)goBack { - if (goBack && [historySideSwipeProvider_ canGoBack]) { - return historySideSwipeProvider_; +- (BOOL)canNavigate:(BOOL)goBack { + if (goBack && [[model_ currentTab] canGoBack]) { + return YES; } - if (!goBack && [historySideSwipeProvider_ canGoForward]) { - return historySideSwipeProvider_; + if (!goBack && [[model_ currentTab] canGoForward]) { + return YES; } - if (goBack && [readingListSideSwipeProvider_ canGoBack]) { - return readingListSideSwipeProvider_; - } - if (!goBack && [readingListSideSwipeProvider_ canGoForward]) { - return readingListSideSwipeProvider_; - } - return nil; + return NO; } // Show swipe to navigate. @@ -432,9 +429,6 @@ [swipeDelegate_ updateAccessoryViewsForSideSwipeWithVisibility:NO]; BOOL goBack = IsSwipingBack(gesture.direction); - currentContentProvider_ = [self contentProviderForGesture:goBack]; - BOOL canNavigate = currentContentProvider_ != nil; - CGRect gestureBounds = gesture.view.bounds; CGFloat headerHeight = [swipeDelegate_ headerHeightForSideSwipe]; CGRect navigationFrame = @@ -446,9 +440,8 @@ pageSideSwipeView_ = [[SideSwipeNavigationView alloc] initWithFrame:navigationFrame withDirection:gesture.direction - canNavigate:canNavigate - image:[currentContentProvider_ paneIcon] - rotateForward:[currentContentProvider_ rotateForwardIcon]]; + canNavigate:[self canNavigate:goBack] + image:[UIImage imageNamed:@"side_swipe_navigation_back"]]; [pageSideSwipeView_ setTargetView:[swipeDelegate_ sideSwipeContentView]]; [gesture.view insertSubview:pageSideSwipeView_ @@ -467,9 +460,9 @@ BOOL wantsBack = IsSwipingBack(gesture.direction); web::WebState* webState = [weakCurrentTab webState]; if (wantsBack) { - [currentContentProvider_ goBack:webState]; + [[model_ currentTab] goBack]; } else { - [currentContentProvider_ goForward:webState]; + [[model_ currentTab] goForward]; } // Checking -IsLoading() is likely incorrect, but to narrow the scope of @@ -586,6 +579,41 @@ completionHandler(); } +- (void)updateNavigationEdgeSwipeForWebState:(web::WebState*)webState { + // With slim nav disabled, always use SideSwipeController's edge swipe for + // navigation. + if (!web::GetWebClient()->IsSlimNavigationManagerEnabled()) { + self.leadingEdgeNavigationEnabled = YES; + self.trailingEdgeNavigationEnabled = YES; + return; + } + + // With slim nav enabled, disable SideSwipeController's edge swipe for a + // typical navigation. Continue to use SideSwipeController when on, before, + // or after a native page. + self.leadingEdgeNavigationEnabled = NO; + self.trailingEdgeNavigationEnabled = NO; + + web::NavigationItem* item = + webState->GetNavigationManager()->GetVisibleItem(); + if (item && UseNativeSwipe(item)) { + self.leadingEdgeNavigationEnabled = YES; + self.trailingEdgeNavigationEnabled = YES; + } + + // If the previous page is an NTP, enable leading edge swipe. + web::NavigationItemList backItems = + webState->GetNavigationManager()->GetBackwardItems(); + if (backItems.size() > 0 && UseNativeSwipe(backItems[0])) + self.leadingEdgeNavigationEnabled = YES; + + // If the next page is an NTP, enable trailing edge swipe. + web::NavigationItemList fordwardItems = + webState->GetNavigationManager()->GetForwardItems(); + if (fordwardItems.size() > 0 && UseNativeSwipe(fordwardItems[0])) + self.trailingEdgeNavigationEnabled = YES; +} + #pragma mark - CRWWebStateObserver Methods // Checking -webStateDidStopLoading is likely incorrect, but to narrow the scope @@ -621,6 +649,12 @@ // the gesture recognizer. [swipeGestureRecognizer_ setEnabled:NO]; [swipeGestureRecognizer_ setEnabled:YES]; + + [self updateNavigationEdgeSwipeForWebState:newTab.webState]; +} + +- (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab { + [self updateNavigationEdgeSwipeForWebState:tab.webState]; } @end
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller_unittest.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_controller_unittest.mm index a98d8bfb..3f0d12e 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller_unittest.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller_unittest.mm
@@ -2,8 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h" +#include "base/test/scoped_feature_list.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#include "ios/chrome/browser/chrome_url_constants.h" +#include "ios/web/public/features.h" +#import "ios/web/public/navigation_item.h" +#import "ios/web/public/test/fakes/test_navigation_manager.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "ios/web/public/test/test_web_thread_bundle.h" #include "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" @@ -14,6 +20,12 @@ #error "This file requires ARC support." #endif +@interface SideSwipeController (ExposedForTesting) +@property(nonatomic, assign) BOOL leadingEdgeNavigationEnabled; +@property(nonatomic, assign) BOOL trailingEdgeNavigationEnabled; +- (void)updateNavigationEdgeSwipeForWebState:(web::WebState*)webState; +@end + namespace { class SideSwipeControllerTest : public PlatformTest { @@ -39,6 +51,7 @@ UIView* view_; TabModel* tab_model_; SideSwipeController* side_swipe_controller_; + base::test::ScopedFeatureList feature_list_; }; TEST_F(SideSwipeControllerTest, TestConstructor) { @@ -55,4 +68,46 @@ EXPECT_TRUE(hasRecognizer); } +// Tests that pages that need to use Chromium native swipe +TEST_F(SideSwipeControllerTest, TestEdgeNavigationEnabled) { + feature_list_.InitAndEnableFeature(web::features::kSlimNavigationManager); + + auto testWebState = std::make_unique<web::TestWebState>(); + auto testNavigationManager = std::make_unique<web::TestNavigationManager>(); + std::unique_ptr<web::NavigationItem> item = web::NavigationItem::Create(); + testNavigationManager->SetVisibleItem(item.get()); + testWebState->SetNavigationManager(std::move(testNavigationManager)); + + // The NTP and chrome://crash should use native swipe. + item->SetURL(GURL(kChromeUINewTabURL)); + [side_swipe_controller_ + updateNavigationEdgeSwipeForWebState:testWebState.get()]; + EXPECT_TRUE(side_swipe_controller_.leadingEdgeNavigationEnabled); + EXPECT_TRUE(side_swipe_controller_.trailingEdgeNavigationEnabled); + + item->SetURL(GURL("chrome://crash")); + [side_swipe_controller_ + updateNavigationEdgeSwipeForWebState:testWebState.get()]; + EXPECT_TRUE(side_swipe_controller_.leadingEdgeNavigationEnabled); + EXPECT_TRUE(side_swipe_controller_.trailingEdgeNavigationEnabled); + + item->SetURL(GURL("http://wwww.test.com")); + [side_swipe_controller_ + updateNavigationEdgeSwipeForWebState:testWebState.get()]; + EXPECT_FALSE(side_swipe_controller_.leadingEdgeNavigationEnabled); + EXPECT_FALSE(side_swipe_controller_.trailingEdgeNavigationEnabled); + + item->SetURL(GURL("chrome://foo")); + [side_swipe_controller_ + updateNavigationEdgeSwipeForWebState:testWebState.get()]; + EXPECT_FALSE(side_swipe_controller_.leadingEdgeNavigationEnabled); + EXPECT_FALSE(side_swipe_controller_.trailingEdgeNavigationEnabled); + + item->SetURL(GURL("chrome://version")); + [side_swipe_controller_ + updateNavigationEdgeSwipeForWebState:testWebState.get()]; + EXPECT_FALSE(side_swipe_controller_.leadingEdgeNavigationEnabled); + EXPECT_FALSE(side_swipe_controller_.trailingEdgeNavigationEnabled); +} + } // anonymous namespace
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.h b/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.h index c8a4e2b..0994865c 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.h +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.h
@@ -19,8 +19,7 @@ - (instancetype)initWithFrame:(CGRect)frame withDirection:(UISwipeGestureRecognizerDirection)direction canNavigate:(BOOL)canNavigate - image:(UIImage*)image - rotateForward:(BOOL)rotateForward; + image:(UIImage*)image; // Update views for latest gesture, and call completion blocks whether // |threshold| is met.
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.mm index 7b07882..d84eccf7 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.mm
@@ -81,10 +81,6 @@ // If |NO| this is an edge gesture and navigation isn't possible. Don't show // arrows and bubbles and don't allow navigate. BOOL canNavigate_; - - // If |YES| arrowView_ is directionnal and must be rotated 180 degreed for the - // forward panes. - BOOL rotateForward_; } // Returns a newly allocated and configured selection circle shape. - (CAShapeLayer*)newSelectionCircleLayer; @@ -100,14 +96,12 @@ - (instancetype)initWithFrame:(CGRect)frame withDirection:(UISwipeGestureRecognizerDirection)direction canNavigate:(BOOL)canNavigate - image:(UIImage*)image - rotateForward:(BOOL)rotateForward { + image:(UIImage*)image { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor colorWithWhite:90.0 / 256 alpha:1.0]; canNavigate_ = canNavigate; - rotateForward_ = rotateForward; if (canNavigate) { image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; const CGRect imageSize = CGRectMake(0, 0, 24, 24); @@ -188,13 +182,8 @@ CGFloat rotationStart = -CGFloat(base::kPiDouble) / 2; CGFloat rotationEnd = 0; if (gesture.direction == UISwipeGestureRecognizerDirectionLeft) { - if (rotateForward_) { - rotationStart = CGFloat(base::kPiDouble) * 1.5; - rotationEnd = CGFloat(base::kPiDouble); - } else { - rotationStart = CGFloat(base::kPiDouble) / 2; - rotationEnd = 0; - } + rotationStart = CGFloat(base::kPiDouble) * 1.5; + rotationEnd = CGFloat(base::kPiDouble); } CGAffineTransform rotation = CGAffineTransformMakeRotation(MapValueToRange( {0, kArrowThreshold}, {rotationStart, rotationEnd}, distance));
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_util.h b/ios/chrome/browser/ui/side_swipe/side_swipe_util.h index 27f28ac..715c145 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_util.h +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_util.h
@@ -7,10 +7,18 @@ #import <UIKit/UIKit.h> +namespace web { +class NavigationItem; +} + // If swiping to the right (or left in RTL). BOOL IsSwipingBack(UISwipeGestureRecognizerDirection direction); // If swiping to the left (or right in RTL). BOOL IsSwipingForward(UISwipeGestureRecognizerDirection direction); +// Returns |YES| if the item should use Chromium native swipe. This is true for +// the NTP and chrome://crash. +BOOL UseNativeSwipe(web::NavigationItem* item); + #endif // IOS_CHROME_BROWSER_UI_SIDE_SWIPE_SIDE_SWIPE_UTIL_H_
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_util.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_util.mm index 9b0e44c..bdcd3faf 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_util.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_util.mm
@@ -6,7 +6,11 @@ #import <UIKit/UIKit.h> +#include "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/chrome_url_util.h" +#import "ios/chrome/browser/ui/ntp/ntp_util.h" #include "ios/chrome/browser/ui/util/rtl_geometry.h" +#import "ios/web/public/navigation_item.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -25,3 +29,14 @@ else return direction == UISwipeGestureRecognizerDirectionLeft; } + +BOOL UseNativeSwipe(web::NavigationItem* item) { + if (IsURLNewTabPage(item->GetVirtualURL())) + return YES; + + GURL url(item->GetURL()); + if (UrlHasChromeScheme(url) && url.host_piece() == kChromeUICrashHost) + return YES; + + return NO; +}
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn index 5308f62c..01547397f 100644 --- a/ios/third_party/material_components_ios/BUILD.gn +++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -8,11 +8,13 @@ visibility = [ ":material_components_ios" ] include_dirs = [ "src/components/ActivityIndicator/src", + "src/components/Buttons/src/ButtonThemer", "src/components/Buttons/src/ShapeThemer", "src/components/AppBar/src", "src/components/private/ShapeLibrary/src", "src/components/ButtonBar/src", "src/components/Buttons/src", + "src/components/Cards/src", "src/components/CollectionCells/src", "src/components/CollectionLayoutAttributes/src", "src/components/Collections/src", @@ -137,6 +139,10 @@ "src/components/Buttons/src/TypographyThemer/MDCButtonTypographyThemer.h", "src/components/Buttons/src/TypographyThemer/MDCButtonTypographyThemer.m", "src/components/Buttons/src/private/MDCButton+Subclassing.h", + "src/components/Cards/src/ColorThemer/MDCCardsColorThemer.h", + "src/components/Cards/src/ColorThemer/MDCCardsColorThemer.m", + "src/components/Cards/src/MDCCard.h", + "src/components/Cards/src/MDCCard.m", "src/components/CollectionCells/src/MDCCollectionViewCell.h", "src/components/CollectionCells/src/MDCCollectionViewCell.m", "src/components/CollectionCells/src/MDCCollectionViewTextCell.h",
diff --git a/ios/web/public/test/fakes/test_navigation_manager.mm b/ios/web/public/test/fakes/test_navigation_manager.mm index 1f3485c..cecff9c 100644 --- a/ios/web/public/test/fakes/test_navigation_manager.mm +++ b/ios/web/public/test/fakes/test_navigation_manager.mm
@@ -154,12 +154,10 @@ } NavigationItemList TestNavigationManager::GetBackwardItems() const { - NOTREACHED(); return NavigationItemList(); } NavigationItemList TestNavigationManager::GetForwardItems() const { - NOTREACHED(); return NavigationItemList(); }
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 0cbf1daa..3c1e05c 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -954,6 +954,10 @@ if (self) { _webStateImpl = webState; _webUsageEnabled = YES; + + if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) + _allowsBackForwardNavigationGestures = YES; + DCHECK(_webStateImpl); // Load phase when no WebView present is 'loaded' because this represents // the idle state.
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm index d7c6f5c..bfd994b 100644 --- a/ios/web/web_state/ui/crw_web_controller_unittest.mm +++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -212,7 +212,7 @@ context:nullptr]; [[result stub] removeObserver:web_controller() forKeyPath:OCMOCK_ANY]; [[result stub] evaluateJavaScript:OCMOCK_ANY completionHandler:OCMOCK_ANY]; - // CRWWebController sets this property to NO by default. + [[result stub] setAllowsBackForwardNavigationGestures:YES]; [[result stub] setAllowsBackForwardNavigationGestures:NO]; return result; @@ -310,13 +310,18 @@ EXPECT_FALSE(observer.did_finish_navigation_info()); } -// Tests allowsBackForwardNavigationGestures default value and setting this -// property to YES. +// Tests allowsBackForwardNavigationGestures default value and negating this +// property. TEST_P(CRWWebControllerTest, SetAllowsBackForwardNavigationGestures) { - OCMExpect([mock_web_view_ setAllowsBackForwardNavigationGestures:YES]); - EXPECT_FALSE(web_controller().allowsBackForwardNavigationGestures); - web_controller().allowsBackForwardNavigationGestures = YES; - EXPECT_TRUE(web_controller().allowsBackForwardNavigationGestures); + if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) { + EXPECT_TRUE(web_controller().allowsBackForwardNavigationGestures); + web_controller().allowsBackForwardNavigationGestures = NO; + EXPECT_FALSE(web_controller().allowsBackForwardNavigationGestures); + } else { + EXPECT_FALSE(web_controller().allowsBackForwardNavigationGestures); + web_controller().allowsBackForwardNavigationGestures = YES; + EXPECT_TRUE(web_controller().allowsBackForwardNavigationGestures); + } } INSTANTIATE_TEST_CASES(CRWWebControllerTest);
diff --git a/ios/web_view/internal/translate/web_view_translate_client.mm b/ios/web_view/internal/translate/web_view_translate_client.mm index 6871fd4..1e5106bc 100644 --- a/ios/web_view/internal/translate/web_view_translate_client.mm +++ b/ios/web_view/internal/translate/web_view_translate_client.mm
@@ -32,8 +32,6 @@ #error "This file requires ARC support." #endif -DEFINE_WEB_STATE_USER_DATA_KEY(ios_web_view::WebViewTranslateClient); - namespace ios_web_view { WebViewTranslateClient::WebViewTranslateClient(web::WebState* web_state)
diff --git a/media/audio/audio_output_device.cc b/media/audio/audio_output_device.cc index fa6a12c..b298f7a 100644 --- a/media/audio/audio_output_device.cc +++ b/media/audio/audio_output_device.cc
@@ -15,6 +15,7 @@ #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/threading/platform_thread.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_restrictions.h" #include "base/timer/timer.h" #include "base/trace_event/trace_event.h" @@ -22,6 +23,7 @@ #include "media/audio/audio_device_description.h" #include "media/audio/audio_output_controller.h" #include "media/audio/audio_output_device_thread_callback.h" +#include "media/base/bind_to_current_loop.h" #include "media/base/limits.h" namespace media { @@ -64,6 +66,17 @@ } AudioOutputDevice::~AudioOutputDevice() { + { + // Abort any pending callbacks. Technically we don't need to acquire the + // lock here since ther eshould be no other calls outstanding, but because + // we've used the GUARDED_BY compiler syntax, we'll get an error without it. + base::AutoLock auto_lock(device_info_lock_); + if (pending_device_info_cb_) { + std::move(pending_device_info_cb_) + .Run(OutputDeviceInfo(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL)); + } + } + #if DCHECK_IS_ON() // Make sure we've stopped the stream properly before destructing |this|. DCHECK(audio_thread_lock_.Try()); @@ -97,7 +110,6 @@ audio_thread_.reset(); stopping_hack_ = true; } - io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&AudioOutputDevice::ShutDownOnIOThread, this)); } @@ -128,13 +140,29 @@ OutputDeviceInfo AudioOutputDevice::GetOutputDeviceInfo() { TRACE_EVENT0("audio", "AudioOutputDevice::GetOutputDeviceInfo"); DCHECK(!io_task_runner_->BelongsToCurrentThread()); - did_receive_auth_.Wait(); - return OutputDeviceInfo(AudioDeviceDescription::UseSessionIdToSelectDevice( - session_id_, device_id_) - ? matched_device_id_ - : device_id_, - device_status_, output_params_); + return GetOutputDeviceInfo_Signaled(); +} + +void AudioOutputDevice::GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) { + { + // Hold the lock while checking the signal and setting the pending callback + // to avoid racing with authorization completion on the IO thread. + base::AutoLock auto_lock(device_info_lock_); + if (!did_receive_auth_.IsSignaled()) { + DCHECK(!pending_device_info_cb_); + pending_device_info_cb_ = BindToCurrentLoop(std::move(info_cb)); + return; + } + } + + // Always post to avoid the caller being reentrant. Local testing shows even + // on a powerful desktop, we haven't received device authorization by this + // point when AOD construction and GetOutputDeviceInfoAsync() happen back to + // back (which is the most common use case). + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(info_cb), GetOutputDeviceInfo_Signaled())); } bool AudioOutputDevice::IsOptimizedForHardwareParameters() { @@ -307,7 +335,7 @@ << ", device_id: " << device_id_ << ", matched_device_id: " << matched_device_id_; - did_receive_auth_.Signal(); + OnAuthSignal(); } } else { TRACE_EVENT1("audio", "AudioOutputDevice not authorized", "auth status", @@ -378,8 +406,39 @@ ipc_.reset(); state_ = IDLE; - // Signal to unblock any blocked threads waiting for parameters + OnAuthSignal(); +} + +OutputDeviceInfo AudioOutputDevice::GetOutputDeviceInfo_Signaled() { + DCHECK(did_receive_auth_.IsSignaled()); + return OutputDeviceInfo(AudioDeviceDescription::UseSessionIdToSelectDevice( + session_id_, device_id_) + ? matched_device_id_ + : device_id_, + device_status_, output_params_); +} + +void AudioOutputDevice::OnAuthSignal() { + DCHECK(io_task_runner_->BelongsToCurrentThread()); + + // This lock is held while signaling to avoid any thread safety issues while + // GetOutputDeviceInfoAsync() may be checking the signal and modifying the + // |pending_device_info_cb_| on another thread. + // + // We might be able to get away with signaling outside of the lock, but this + // requires more careful construction for anyone checking the signal and + // using the result to set or get the pending callback value. The failure + // mode is also more subtle, callbacks will be lost versus a thread hang which + // is more easily detectable in the production population. + base::AutoLock auto_lock(device_info_lock_); + + // Signal to unblock any blocked threads waiting for parameters. did_receive_auth_.Signal(); + + // The callback is always posted by way media::BindToCurrentLoop() usage upon + // receipt, so this is safe to run under the lock. + if (pending_device_info_cb_) + std::move(pending_device_info_cb_).Run(GetOutputDeviceInfo_Signaled()); } void AudioOutputDevice::NotifyRenderCallbackOfError() {
diff --git a/media/audio/audio_output_device.h b/media/audio/audio_output_device.h index cc48143..a512e72b 100644 --- a/media/audio/audio_output_device.h +++ b/media/audio/audio_output_device.h
@@ -110,6 +110,7 @@ void Pause() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override; bool IsOptimizedForHardwareParameters() override; bool CurrentThreadIsRenderingThread() override; @@ -171,6 +172,9 @@ void NotifyRenderCallbackOfError(); + OutputDeviceInfo GetOutputDeviceInfo_Signaled(); + void OnAuthSignal(); + const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; AudioParameters audio_parameters_; @@ -226,6 +230,14 @@ const base::TimeDelta auth_timeout_; std::unique_ptr<base::OneShotTimer> auth_timeout_action_; + // Pending callback for OutputDeviceInfo if it has not been received by the + // time a call to GetGetOutputDeviceInfoAsync() is called. + // + // Lock for use ONLY with |pending_device_info_cb_| and |did_receive_auth_|, + // if you add more usage of this lock ensure you have not added a deadlock. + base::Lock device_info_lock_; + OutputDeviceInfoCB pending_device_info_cb_ GUARDED_BY(device_info_lock_); + DISALLOW_COPY_AND_ASSIGN(AudioOutputDevice); };
diff --git a/media/audio/audio_output_device_unittest.cc b/media/audio/audio_output_device_unittest.cc index 9eaba2e..416d057f 100644 --- a/media/audio/audio_output_device_unittest.cc +++ b/media/audio/audio_output_device_unittest.cc
@@ -99,9 +99,11 @@ void StartAudioDevice(); void CallOnStreamCreated(); void StopAudioDevice(); - void CreateDevice(const std::string& device_id); + void CreateDevice(const std::string& device_id, + base::TimeDelta timeout = kAuthTimeout); void SetDevice(const std::string& device_id); - void CheckDeviceStatus(OutputDeviceStatus device_status); + + MOCK_METHOD1(OnDeviceInfoReceived, void(OutputDeviceInfo)); protected: base::test::ScopedTaskEnvironment task_env_{ @@ -134,7 +136,8 @@ audio_device_ = nullptr; } -void AudioOutputDeviceTest::CreateDevice(const std::string& device_id) { +void AudioOutputDeviceTest::CreateDevice(const std::string& device_id, + base::TimeDelta timeout) { // Make sure the previous device is properly cleaned up. if (audio_device_) StopAudioDevice(); @@ -142,7 +145,7 @@ audio_output_ipc_ = new NiceMock<MockAudioOutputIPC>(); audio_device_ = new AudioOutputDevice( base::WrapUnique(audio_output_ipc_), task_env_.GetMainThreadTaskRunner(), - AudioSinkParameters(0, device_id), kAuthTimeout); + AudioSinkParameters(0, device_id), timeout); } void AudioOutputDeviceTest::SetDevice(const std::string& device_id) { @@ -163,11 +166,6 @@ &callback_); } -void AudioOutputDeviceTest::CheckDeviceStatus(OutputDeviceStatus status) { - DCHECK(!task_env_.GetMainThreadTaskRunner()->BelongsToCurrentThread()); - EXPECT_EQ(status, audio_device_->GetOutputDeviceInfo().device_status()); -} - void AudioOutputDeviceTest::ReceiveAuthorization(OutputDeviceStatus status) { device_status_ = status; if (device_status_ != OUTPUT_DEVICE_STATUS_OK) @@ -333,6 +331,57 @@ task_env_.FastForwardBy(base::TimeDelta()); } +TEST_F(AudioOutputDeviceTest, GetOutputDeviceInfoAsync_Error) { + CreateDevice(kUnauthorizedDeviceId, base::TimeDelta()); + EXPECT_CALL(*audio_output_ipc_, + RequestDeviceAuthorization(audio_device_.get(), 0, + kUnauthorizedDeviceId)); + audio_device_->RequestDeviceAuthorization(); + audio_device_->GetOutputDeviceInfoAsync(base::BindOnce( + &AudioOutputDeviceTest::OnDeviceInfoReceived, base::Unretained(this))); + task_env_.FastForwardBy(base::TimeDelta()); + + OutputDeviceInfo info; + constexpr auto kExpectedStatus = OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED; + EXPECT_CALL(*this, OnDeviceInfoReceived(_)) + .WillOnce(testing::SaveArg<0>(&info)); + ReceiveAuthorization(kExpectedStatus); + + task_env_.FastForwardUntilNoTasksRemain(); + EXPECT_EQ(kExpectedStatus, info.device_status()); + EXPECT_EQ(kUnauthorizedDeviceId, info.device_id()); + EXPECT_TRUE( + AudioParameters::UnavailableDeviceParams().Equals(info.output_params())); + + audio_device_->Stop(); + task_env_.FastForwardBy(base::TimeDelta()); +} + +TEST_F(AudioOutputDeviceTest, GetOutputDeviceInfoAsync_Okay) { + CreateDevice(kDefaultDeviceId, base::TimeDelta()); + EXPECT_CALL( + *audio_output_ipc_, + RequestDeviceAuthorization(audio_device_.get(), 0, kDefaultDeviceId)); + audio_device_->RequestDeviceAuthorization(); + audio_device_->GetOutputDeviceInfoAsync(base::BindOnce( + &AudioOutputDeviceTest::OnDeviceInfoReceived, base::Unretained(this))); + task_env_.FastForwardBy(base::TimeDelta()); + + OutputDeviceInfo info; + constexpr auto kExpectedStatus = OUTPUT_DEVICE_STATUS_OK; + EXPECT_CALL(*this, OnDeviceInfoReceived(_)) + .WillOnce(testing::SaveArg<0>(&info)); + ReceiveAuthorization(kExpectedStatus); + + task_env_.FastForwardUntilNoTasksRemain(); + EXPECT_EQ(kExpectedStatus, info.device_status()); + EXPECT_EQ(kDefaultDeviceId, info.device_id()); + EXPECT_TRUE(default_audio_parameters_.Equals(info.output_params())); + + audio_device_->Stop(); + task_env_.FastForwardBy(base::TimeDelta()); +} + namespace { // This struct collects useful stuff without doing anything magical. It is used
diff --git a/media/audio/audio_output_stream_sink.cc b/media/audio/audio_output_stream_sink.cc index 2ff00123..7974224a 100644 --- a/media/audio/audio_output_stream_sink.cc +++ b/media/audio/audio_output_stream_sink.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/location.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "media/audio/audio_manager.h" #include "media/base/audio_timestamp_helper.h" @@ -77,7 +78,13 @@ } OutputDeviceInfo AudioOutputStreamSink::GetOutputDeviceInfo() { - return OutputDeviceInfo(); + return OutputDeviceInfo(OUTPUT_DEVICE_STATUS_OK); +} + +void AudioOutputStreamSink::GetOutputDeviceInfoAsync( + OutputDeviceInfoCB info_cb) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(info_cb), GetOutputDeviceInfo())); } bool AudioOutputStreamSink::IsOptimizedForHardwareParameters() {
diff --git a/media/audio/audio_output_stream_sink.h b/media/audio/audio_output_stream_sink.h index 40bbecf0..e5fadfa90 100644 --- a/media/audio/audio_output_stream_sink.h +++ b/media/audio/audio_output_stream_sink.h
@@ -42,6 +42,7 @@ void Play() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override; bool IsOptimizedForHardwareParameters() override; bool CurrentThreadIsRenderingThread() override;
diff --git a/media/audio/clockless_audio_sink.cc b/media/audio/clockless_audio_sink.cc index 4f15d24..a41bf20 100644 --- a/media/audio/clockless_audio_sink.cc +++ b/media/audio/clockless_audio_sink.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/single_thread_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/simple_thread.h" #include "media/base/audio_hash.h" @@ -47,27 +48,27 @@ } private: - // Call Render() repeatedly, keeping track of the rendering time. + // Call Render() repeatedly, keeping track of the rendering time. void Run() override { - base::TimeTicks start; - while (!stop_event_->IsSignaled()) { - const int frames_received = callback_->Render( - base::TimeDelta(), base::TimeTicks::Now(), 0, audio_bus_.get()); - DCHECK_GE(frames_received, 0); - if (audio_hash_) - audio_hash_->Update(audio_bus_.get(), frames_received); - if (!frames_received) { - // No data received, so let other threads run to provide data. - base::PlatformThread::YieldCurrentThread(); - } else if (start.is_null()) { - // First time we processed some audio, so record the starting time. - start = base::TimeTicks::Now(); - } else { - // Keep track of the last time data was rendered. - playback_time_ = base::TimeTicks::Now() - start; - } - } - } + base::TimeTicks start; + while (!stop_event_->IsSignaled()) { + const int frames_received = callback_->Render( + base::TimeDelta(), base::TimeTicks::Now(), 0, audio_bus_.get()); + DCHECK_GE(frames_received, 0); + if (audio_hash_) + audio_hash_->Update(audio_bus_.get(), frames_received); + if (!frames_received) { + // No data received, so let other threads run to provide data. + base::PlatformThread::YieldCurrentThread(); + } else if (start.is_null()) { + // First time we processed some audio, so record the starting time. + start = base::TimeTicks::Now(); + } else { + // Keep track of the last time data was rendered. + playback_time_ = base::TimeTicks::Now() - start; + } + } + } AudioRendererSink::RenderCallback* callback_; std::unique_ptr<AudioBus> audio_bus_; @@ -135,6 +136,11 @@ return device_info_; } +void ClocklessAudioSink::GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(info_cb), device_info_)); +} + bool ClocklessAudioSink::IsOptimizedForHardwareParameters() { return is_optimized_for_hw_params_; }
diff --git a/media/audio/clockless_audio_sink.h b/media/audio/clockless_audio_sink.h index fec3dd5..8dbfb52 100644 --- a/media/audio/clockless_audio_sink.h +++ b/media/audio/clockless_audio_sink.h
@@ -31,6 +31,7 @@ void Play() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override; bool IsOptimizedForHardwareParameters() override; bool CurrentThreadIsRenderingThread() override;
diff --git a/media/audio/null_audio_sink.cc b/media/audio/null_audio_sink.cc index 3a11ef6..f436cf2 100644 --- a/media/audio/null_audio_sink.cc +++ b/media/audio/null_audio_sink.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/single_thread_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "media/base/audio_hash.h" #include "media/base/fake_audio_worker.h" @@ -79,6 +80,11 @@ return OutputDeviceInfo(OUTPUT_DEVICE_STATUS_OK); } +void NullAudioSink::GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(info_cb), GetOutputDeviceInfo())); +} + bool NullAudioSink::IsOptimizedForHardwareParameters() { return false; }
diff --git a/media/audio/null_audio_sink.h b/media/audio/null_audio_sink.h index 21d255e9..69e1a48 100644 --- a/media/audio/null_audio_sink.h +++ b/media/audio/null_audio_sink.h
@@ -34,6 +34,7 @@ void Play() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override; bool IsOptimizedForHardwareParameters() override; bool CurrentThreadIsRenderingThread() override; void SwitchOutputDevice(const std::string& device_id,
diff --git a/media/base/audio_renderer_mixer_input.cc b/media/base/audio_renderer_mixer_input.cc index ba821ee0..9754bb68 100644 --- a/media/base/audio_renderer_mixer_input.cc +++ b/media/base/audio_renderer_mixer_input.cc
@@ -21,14 +21,9 @@ const std::string& device_id, AudioLatency::LatencyType latency) : mixer_pool_(mixer_pool), - started_(false), - playing_(false), - volume_(1.0f), owner_id_(owner_id), device_id_(device_id), latency_(latency), - mixer_(nullptr), - callback_(nullptr), error_cb_(base::Bind(&AudioRendererMixerInput::OnRenderError, base::Unretained(this))) { DCHECK(mixer_pool_); @@ -112,6 +107,12 @@ owner_id_, 0 /* session_id */, device_id_); } +void AudioRendererMixerInput::GetOutputDeviceInfoAsync( + OutputDeviceInfoCB info_cb) { + // TODO(dalecurtis): Implement this for https://crbug.com/905506. + NOTREACHED(); +} + bool AudioRendererMixerInput::IsOptimizedForHardwareParameters() { return true; } @@ -173,8 +174,8 @@ // AudioConverter expects unfilled frames to be zeroed. if (frames_filled < audio_bus->frames()) { - audio_bus->ZeroFramesPartial( - frames_filled, audio_bus->frames() - frames_filled); + audio_bus->ZeroFramesPartial(frames_filled, + audio_bus->frames() - frames_filled); } // We're reading |volume_| from the audio device thread and must avoid racing
diff --git a/media/base/audio_renderer_mixer_input.h b/media/base/audio_renderer_mixer_input.h index c4cfc49..aeb5781 100644 --- a/media/base/audio_renderer_mixer_input.h +++ b/media/base/audio_renderer_mixer_input.h
@@ -47,6 +47,8 @@ void Pause() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override; + bool IsOptimizedForHardwareParameters() override; void Initialize(const AudioParameters& params, AudioRendererSink::RenderCallback* renderer) override; @@ -74,9 +76,9 @@ // SetVolume(). base::Lock volume_lock_; - bool started_; - bool playing_; - double volume_ GUARDED_BY(volume_lock_); + bool started_ = false; + bool playing_ = false; + double volume_ GUARDED_BY(volume_lock_) = 1.0; // AudioConverter::InputCallback implementation. double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) override; @@ -90,10 +92,10 @@ // AudioRendererMixer obtained from mixer pool during Initialize(), // guaranteed to live (at least) until it is returned to the pool. - AudioRendererMixer* mixer_; + AudioRendererMixer* mixer_ = nullptr; // Source of audio data which is provided to the mixer. - AudioRendererSink::RenderCallback* callback_; + AudioRendererSink::RenderCallback* callback_ = nullptr; // Error callback for handing to AudioRendererMixer. const base::Closure error_cb_;
diff --git a/media/base/audio_renderer_sink.h b/media/base/audio_renderer_sink.h index 9b38c98..fefc018 100644 --- a/media/base/audio_renderer_sink.h +++ b/media/base/audio_renderer_sink.h
@@ -66,12 +66,29 @@ virtual bool SetVolume(double volume) = 0; // Returns current output device information. If the information is not - // available yet, this method may block until it becomes available. - // If the sink is not associated with any output device, |device_status| of - // OutputDeviceInfo should be set to OUTPUT_DEVICE_STATUS_ERROR_INTERNAL. - // Must never be called on the IO thread. + // available yet, this method may block until it becomes available. If the + // sink is not associated with any output device, |device_status| of + // OutputDeviceInfo should be set to OUTPUT_DEVICE_STATUS_ERROR_INTERNAL. Must + // never be called on the IO thread. + // + // Note: Prefer to use GetOutputDeviceInfoAsync instead if possible. virtual OutputDeviceInfo GetOutputDeviceInfo() = 0; + // Same as the above, but does not block and will execute |info_cb| when the + // OutputDeviceInfo is available. Callback will be executed on the calling + // thread. Prefer this function to the synchronous version, it does not have a + // timeout so will result in less spurious timeout errors. + // + // |info_cb| will always be posted (I.e., executed after this function + // returns), even if OutputDeviceInfo is already available. + // + // Upon destruction if OutputDeviceInfo is still not available, |info_cb| will + // be posted with OUTPUT_DEVICE_STATUS_ERROR_INTERNAL. Note: Because |info_cb| + // is posted it will execute after destruction, so clients must handle + // cancellation of the callback if needed. + using OutputDeviceInfoCB = base::OnceCallback<void(OutputDeviceInfo)>; + virtual void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) = 0; + // Returns |true| if a source with hardware parameters is preferable. virtual bool IsOptimizedForHardwareParameters() = 0;
diff --git a/media/base/fake_audio_renderer_sink.cc b/media/base/fake_audio_renderer_sink.cc index e80a0f81..924691ea 100644 --- a/media/base/fake_audio_renderer_sink.cc +++ b/media/base/fake_audio_renderer_sink.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/threading/sequenced_task_runner_handle.h" namespace media { @@ -69,6 +70,12 @@ return output_device_info_; } +void FakeAudioRendererSink::GetOutputDeviceInfoAsync( + OutputDeviceInfoCB info_cb) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(info_cb), output_device_info_)); +} + bool FakeAudioRendererSink::IsOptimizedForHardwareParameters() { return is_optimized_for_hw_params_; }
diff --git a/media/base/fake_audio_renderer_sink.h b/media/base/fake_audio_renderer_sink.h index 7e87a96..de599d2 100644 --- a/media/base/fake_audio_renderer_sink.h +++ b/media/base/fake_audio_renderer_sink.h
@@ -39,6 +39,7 @@ void Play() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override; bool IsOptimizedForHardwareParameters() override; bool CurrentThreadIsRenderingThread() override;
diff --git a/media/base/mock_audio_renderer_sink.cc b/media/base/mock_audio_renderer_sink.cc index ecf21658..4c7c656d 100644 --- a/media/base/mock_audio_renderer_sink.cc +++ b/media/base/mock_audio_renderer_sink.cc
@@ -4,6 +4,9 @@ #include "media/base/mock_audio_renderer_sink.h" +#include "base/bind.h" +#include "base/threading/sequenced_task_runner_handle.h" + namespace media { MockAudioRendererSink::MockAudioRendererSink() : MockAudioRendererSink(OUTPUT_DEVICE_STATUS_OK) {} @@ -45,6 +48,12 @@ return output_device_info_; } +void MockAudioRendererSink::GetOutputDeviceInfoAsync( + OutputDeviceInfoCB info_cb) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(info_cb), output_device_info_)); +} + bool MockAudioRendererSink::IsOptimizedForHardwareParameters() { return false; }
diff --git a/media/base/mock_audio_renderer_sink.h b/media/base/mock_audio_renderer_sink.h index 78110e9..3c848812 100644 --- a/media/base/mock_audio_renderer_sink.h +++ b/media/base/mock_audio_renderer_sink.h
@@ -32,6 +32,7 @@ MOCK_METHOD0(CurrentThreadIsRenderingThread, bool()); OutputDeviceInfo GetOutputDeviceInfo() override; + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override; bool IsOptimizedForHardwareParameters() override;
diff --git a/media/blink/webaudiosourceprovider_impl.cc b/media/blink/webaudiosourceprovider_impl.cc index 672d44d42..e24103f0 100644 --- a/media/blink/webaudiosourceprovider_impl.cc +++ b/media/blink/webaudiosourceprovider_impl.cc
@@ -16,6 +16,7 @@ #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/thread_annotations.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h" #include "media/audio/null_audio_sink.h" #include "media/base/audio_timestamp_helper.h" @@ -266,6 +267,20 @@ : OutputDeviceInfo(OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND); } +void WebAudioSourceProviderImpl::GetOutputDeviceInfoAsync( + OutputDeviceInfoCB info_cb) { + base::AutoLock auto_lock(sink_lock_); + if (sink_) { + sink_->GetOutputDeviceInfoAsync(std::move(info_cb)); + return; + } + + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(info_cb), + OutputDeviceInfo(OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND))); +} + bool WebAudioSourceProviderImpl::IsOptimizedForHardwareParameters() { base::AutoLock auto_lock(sink_lock_); return client_ ? false : true;
diff --git a/media/blink/webaudiosourceprovider_impl.h b/media/blink/webaudiosourceprovider_impl.h index 52f881f..4c68db2e 100644 --- a/media/blink/webaudiosourceprovider_impl.h +++ b/media/blink/webaudiosourceprovider_impl.h
@@ -67,6 +67,7 @@ void Pause() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override; bool IsOptimizedForHardwareParameters() override; bool CurrentThreadIsRenderingThread() override; void SwitchOutputDevice(const std::string& device_id,
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index 6107c0b4..c152880 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -8,12 +8,21 @@ declare_args() { enable_mojo_tracing = false + + # enable_random_mojo_delays starts a task runner that periodically pauses + # random Mojo bindings and later resumes them, in order to test whether parts + # of the code implicitly rely on FIFO processing of messages sent on different + # message pipes (which they should not). + enable_random_mojo_delays = false } buildflag_header("mojo_buildflags") { header = "mojo_buildflags.h" - flags = [ "MOJO_TRACE_ENABLED=$enable_mojo_tracing" ] + flags = [ + "MOJO_TRACE_ENABLED=$enable_mojo_tracing", + "MOJO_RANDOM_DELAYS_ENABLED=$enable_random_mojo_delays", + ] } # Headers and sources which generated bindings can depend upon. No need for @@ -167,6 +176,13 @@ "unique_ptr_impl_ref_traits.h", ] + if (enable_random_mojo_delays) { + sources += [ + "lib/test_random_mojo_delays.cc", + "lib/test_random_mojo_delays.h", + ] + } + if (enable_ipc_fuzzer && !is_nacl_nonsfi) { sources += [ "lib/message_dumper.cc",
diff --git a/mojo/public/cpp/bindings/lib/binding_state.cc b/mojo/public/cpp/bindings/lib/binding_state.cc index bb4a20f..846c9ef 100644 --- a/mojo/public/cpp/bindings/lib/binding_state.cc +++ b/mojo/public/cpp/bindings/lib/binding_state.cc
@@ -3,8 +3,12 @@ // found in the LICENSE file. #include "mojo/public/cpp/bindings/lib/binding_state.h" - #include "mojo/public/cpp/bindings/lib/task_runner_helper.h" +#include "mojo/public/cpp/bindings/mojo_buildflags.h" + +#if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED) +#include "mojo/public/cpp/bindings/lib/test_random_mojo_delays.h" +#endif namespace mojo { namespace internal { @@ -41,6 +45,8 @@ if (!router_) return; + weak_ptr_factory_.InvalidateWeakPtrs(); + endpoint_client_.reset(); router_->CloseMessagePipe(); router_ = nullptr; @@ -92,6 +98,7 @@ auto sequenced_runner = GetTaskRunnerToUseFromUserProvidedTaskRunner(std::move(runner)); + MultiplexRouter::Config config = passes_associated_kinds ? MultiplexRouter::MULTI_INTERFACE @@ -106,7 +113,12 @@ router_->CreateLocalEndpointHandle(kMasterInterfaceId), stub, std::move(request_validator), has_sync_methods, std::move(sequenced_runner), interface_version)); + +#if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED) + MakeBindingRandomlyPaused(base::SequencedTaskRunnerHandle::Get(), + weak_ptr_factory_.GetWeakPtr()); +#endif } -} // namesapce internal +} // namespace internal } // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h index d1c561c..42a8892 100644 --- a/mojo/public/cpp/bindings/lib/binding_state.h +++ b/mojo/public/cpp/bindings/lib/binding_state.h
@@ -31,6 +31,7 @@ #include "mojo/public/cpp/system/core.h" namespace mojo { + namespace internal { class MOJO_CPP_BINDINGS_EXPORT BindingStateBase { @@ -117,6 +118,7 @@ } InterfaceRequest<Interface> Unbind() { + weak_ptr_factory_.InvalidateWeakPtrs(); endpoint_client_.reset(); InterfaceRequest<Interface> request(router_->PassMessagePipe()); router_ = nullptr; @@ -136,7 +138,7 @@ DISALLOW_COPY_AND_ASSIGN(BindingState); }; -} // namesapce internal +} // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h index 155e1fe..d2ebebc 100644 --- a/mojo/public/cpp/bindings/lib/multiplex_router.h +++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -45,8 +45,7 @@ // single message pipe. // // It is created on the sequence where the master interface of the message pipe -// lives. Although it is ref-counted, it is guarateed to be destructed on the -// same sequence. +// lives. // Some public methods are only allowed to be called on the creating sequence; // while the others are safe to call from any sequence. Please see the method // comments for more details.
diff --git a/mojo/public/cpp/bindings/lib/test_random_mojo_delays.cc b/mojo/public/cpp/bindings/lib/test_random_mojo_delays.cc new file mode 100644 index 0000000..861aa99 --- /dev/null +++ b/mojo/public/cpp/bindings/lib/test_random_mojo_delays.cc
@@ -0,0 +1,226 @@ +// 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 <list> + +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/no_destructor.h" +#include "base/rand_util.h" +#include "base/sequence_checker.h" +#include "base/sequenced_task_runner.h" +#include "base/synchronization/lock.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "base/time/time.h" +#include "mojo/public/cpp/bindings/lib/binding_state.h" +#include "mojo/public/cpp/bindings/lib/test_random_mojo_delays.h" + +namespace mojo { +namespace internal { + +namespace { +constexpr int kInverseProbabilityOfDelay = 8; +constexpr int kInverseProbabilityOfNotResuming = 10; +constexpr base::TimeDelta kMillisecondsToResume = + base::TimeDelta::FromMilliseconds(2); +constexpr base::TimeDelta kPauseBindingsFrequency = + base::TimeDelta::FromMilliseconds(7); +} // namespace + +// TODO(mpdenton) This only adds random delays on method call processing. This +// also should add random delays on response processing. It is a mistake if a +// user assumes a response callback is received and run before a subsequent +// asynch call (over a different message pipe), and these random delays won't +// make it any more likely to find the mistake during testing. +class RandomMojoDelays { + public: + RandomMojoDelays() + : runner_for_pauses_( + base::CreateSequencedTaskRunnerWithTraits(base::TaskTraits())) { + DETACH_FROM_SEQUENCE(runner_for_pauses_sequence_checker); + } + + void Start() { + runner_for_pauses_->PostTask( + FROM_HERE, + base::BindOnce(&RandomMojoDelays::PauseRandomBindingStateBases, + base::Unretained(this))); + } + + // TODO(mpdenton) what about bindings with associated interfaces? Apparently + // you cannot pause on those? May need to change DCHECK to if(...) return; + void AddBindingStateBase(scoped_refptr<base::SequencedTaskRunner> runner, + base::WeakPtr<BindingStateBase> binding_state_base) { + runner_for_pauses_->PostTask( + FROM_HERE, + base::BindOnce(&RandomMojoDelays::AddBindingStateBaseInternal, + base::Unretained(this), std::move(runner), + std::move(binding_state_base))); + } + + private: + using BindingList = std::list<base::WeakPtr<BindingStateBase>>; + + // Must be called on |runner_for_pauses_| sequence. Adds a BindingStateBase + // for random pausing purposes. + void AddBindingStateBaseInternal( + scoped_refptr<base::SequencedTaskRunner> runner, + base::WeakPtr<BindingStateBase> binding_state_base) { + DCHECK_CALLED_ON_VALID_SEQUENCE(runner_for_pauses_sequence_checker); + + binding_state_base_map_[std::move(runner)].push_back( + std::move(binding_state_base)); + } + + // Adds a list of BindingStateBases to be randomly paused. Used to re-attach + // a list of BindingStateBases to the map after randomly pausing some of the + // bindings on their bound sequences. + void AddBindingStateBaseList(scoped_refptr<base::SequencedTaskRunner> runner, + BindingList binding_state_bases) { + DCHECK_CALLED_ON_VALID_SEQUENCE(runner_for_pauses_sequence_checker); + + BindingList& list = binding_state_base_map_[std::move(runner)]; + list.splice(list.end(), std::move(binding_state_bases)); + } + + // Resumes all bindings in |paused_binding_state_bases|. + void ResumeFrozenBindingStateBasesOnTaskRunner( + BindingList binding_state_bases, + BindingList paused_binding_state_bases) { + auto it = paused_binding_state_bases.begin(); + while (it != paused_binding_state_bases.end()) { + base::WeakPtr<BindingStateBase> wptr = *it; + if (!wptr) { + // This WeakPtr was invalidated. We'll delete it + // from the binding_state_bases list on the next PauseLoop. + it = paused_binding_state_bases.erase(it); + continue; + } + // Skip the resume with a 1/kInverseProbabilityOfNotResuming chance. + if (base::RandInt(1, kInverseProbabilityOfNotResuming) >= 2) { + wptr->ResumeIncomingMethodCallProcessing(); + it = paused_binding_state_bases.erase(it); + continue; + } + it++; + } + if (!paused_binding_state_bases.empty()) { + // Because we haven't resumed all the bindings, we should schedule another + // resumption task in the future. + // TODO(mpdenton) similar problem as below: can freeze shutdown if we + // forget to unpause bindings. + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &RandomMojoDelays::ResumeFrozenBindingStateBasesOnTaskRunner, + base::Unretained(this), std::move(binding_state_bases), + std::move(paused_binding_state_bases)), + kMillisecondsToResume); + return; + } + // Re-attach the bindings to the global map for future pausing. + runner_for_pauses_->PostTask( + FROM_HERE, base::BindOnce(&RandomMojoDelays::AddBindingStateBaseList, + base::Unretained(this), + base::SequencedTaskRunnerHandle::Get(), + std::move(binding_state_bases))); + } + + // Pause a random selection of bindings in the list |binding_state_bases|, + // and set them to resume in the future. + void PauseRandomBindingStateBasesOnTaskRunner( + BindingList binding_state_bases) { + BindingList paused_binding_state_bases; + auto it = binding_state_bases.begin(); + while (it != binding_state_bases.end()) { + // Remove any BindingStateBases that have been destroyed already. + base::WeakPtr<BindingStateBase> wptr = *it; + if (!wptr) { + it = binding_state_bases.erase(it); + continue; + } + if (base::RandInt(1, kInverseProbabilityOfDelay) >= 2) { + it++; + continue; + } + wptr->PauseIncomingMethodCallProcessing(); + paused_binding_state_bases.push_back(wptr); + it++; + } + // Set the bindings to resume soon. + // TODO(mpdenton) may cause deadlock on shutdown if this doesn't run. But + // there is no PostDelayedTaskWithTraits for a SequencedTaskRunner. + if (paused_binding_state_bases.size() > 0) { + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &RandomMojoDelays::ResumeFrozenBindingStateBasesOnTaskRunner, + base::Unretained(this), std::move(binding_state_bases), + std::move(paused_binding_state_bases)), + kMillisecondsToResume); + } else if (binding_state_bases.size() > 0) { + // If we did not pause any bindings, re-attach the bindings to the global + // map for future pausing, if there are any left after deleting all the + // invalidated weak ptrs. + runner_for_pauses_->PostTask( + FROM_HERE, base::BindOnce(&RandomMojoDelays::AddBindingStateBaseList, + base::Unretained(this), + base::SequencedTaskRunnerHandle::Get(), + std::move(binding_state_bases))); + } + } + + // Post tasks to every sequence with bound Mojo bindings, telling each to + // pause random Mojo bindings bound on the respective sequence. + void PauseRandomBindingStateBases() { + DCHECK_CALLED_ON_VALID_SEQUENCE(runner_for_pauses_sequence_checker); + + auto map_it = binding_state_base_map_.begin(); + while (map_it != binding_state_base_map_.end()) { + // Tell sequence to randomly pause some of its bindings. + map_it->first->PostTask( + FROM_HERE, + base::BindOnce( + &RandomMojoDelays::PauseRandomBindingStateBasesOnTaskRunner, + base::Unretained(this), std::move(map_it->second))); + // Erase the current key-value pair (it will be re-added if necessary + // after resuming the bindings--for now, drop the reference to the + // SequencedTaskRunner). + map_it = binding_state_base_map_.erase(map_it); + } + // Post delayed task, instead of using a RepeatingTimer, to avoid + // overwhelming the task scheduling. + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&RandomMojoDelays::PauseRandomBindingStateBases, + base::Unretained(this)), + kPauseBindingsFrequency); + } + + scoped_refptr<base::SequencedTaskRunner> runner_for_pauses_; + std::map<scoped_refptr<base::SequencedTaskRunner>, BindingList> + binding_state_base_map_; + SEQUENCE_CHECKER(runner_for_pauses_sequence_checker); +}; + +RandomMojoDelays& GetRandomMojoDelays() { + static base::NoDestructor<RandomMojoDelays> random_mojo_delays; + return *random_mojo_delays; +} + +void MakeBindingRandomlyPaused( + scoped_refptr<base::SequencedTaskRunner> runner, + base::WeakPtr<BindingStateBase> binding_state_base) { + GetRandomMojoDelays().AddBindingStateBase(std::move(runner), + binding_state_base); +} + +} // namespace internal + +void BeginRandomMojoDelays() { + internal::GetRandomMojoDelays().Start(); +} + +} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/test_random_mojo_delays.h b/mojo/public/cpp/bindings/lib/test_random_mojo_delays.h new file mode 100644 index 0000000..87a0e0d --- /dev/null +++ b/mojo/public/cpp/bindings/lib/test_random_mojo_delays.h
@@ -0,0 +1,25 @@ +// 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_TEST_RANDOM_MOJO_DELAYS_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_TEST_RANDOM_MOJO_DELAYS_H_ + +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "mojo/public/cpp/bindings/bindings_export.h" + +namespace mojo { +// Begins issuing temporary pauses on randomly selected Mojo bindings for +// debugging purposes. +MOJO_CPP_BINDINGS_EXPORT void BeginRandomMojoDelays(); +namespace internal { +class BindingStateBase; +// Adds a binding state base to make it eligible for pausing. +MOJO_CPP_BINDINGS_EXPORT void MakeBindingRandomlyPaused( + scoped_refptr<base::SequencedTaskRunner>, + base::WeakPtr<BindingStateBase>); +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_TEST_RANDOM_MOJO_DELAYS_H_
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni index f50370c..1071530 100644 --- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni +++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -32,6 +32,7 @@ "//services/audio/public/cpp/typemaps.gni", "//services/device/public/mojom/typemaps.gni", "//services/identity/public/cpp/typemaps.gni", + "//services/media_session/public/cpp/typemaps.gni", "//services/network/public/cpp/typemaps.gni", "//services/preferences/public/cpp/typemaps.gni", "//services/proxy_resolver/public/cpp/typemaps.gni",
diff --git a/net/BUILD.gn b/net/BUILD.gn index 250423f..f335159 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1402,6 +1402,7 @@ "third_party/quic/core/http/spdy_utils.cc", "third_party/quic/core/http/spdy_utils.h", "third_party/quic/core/packet_number_indexed_queue.h", + "third_party/quic/core/qpack/qpack_constants.cc", "third_party/quic/core/qpack/qpack_constants.h", "third_party/quic/core/qpack/qpack_decoder.cc", "third_party/quic/core/qpack/qpack_decoder.h", @@ -1413,6 +1414,8 @@ "third_party/quic/core/qpack/qpack_encoder_stream_sender.h", "third_party/quic/core/qpack/qpack_header_table.cc", "third_party/quic/core/qpack/qpack_header_table.h", + "third_party/quic/core/qpack/qpack_instruction_decoder.cc", + "third_party/quic/core/qpack/qpack_instruction_decoder.h", "third_party/quic/core/qpack/qpack_static_table.cc", "third_party/quic/core/qpack/qpack_static_table.h", "third_party/quic/core/quic_ack_listener_interface.cc", @@ -5079,6 +5082,7 @@ "third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc", "third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc", "third_party/quic/core/qpack/qpack_encoder_test.cc", + "third_party/quic/core/qpack/qpack_instruction_decoder_test.cc", "third_party/quic/core/qpack/qpack_static_table_test.cc", "third_party/quic/core/quic_alarm_test.cc", "third_party/quic/core/quic_arena_scoped_ptr_test.cc",
diff --git a/net/cert/cert_database_mac.cc b/net/cert/cert_database_mac.cc index fa1e99a..e37e5e6 100644 --- a/net/cert/cert_database_mac.cc +++ b/net/cert/cert_database_mac.cc
@@ -35,7 +35,7 @@ registered_(false), called_shutdown_(false) { // Ensure an associated CFRunLoop. - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(task_runner_->BelongsToCurrentThread()); task_runner_->PostTask(FROM_HERE, base::Bind(&Notifier::Init,
diff --git a/net/cert_net/nss_ocsp.cc b/net/cert_net/nss_ocsp.cc index 7bb72b4..cc3ef8b 100644 --- a/net/cert_net/nss_ocsp.cc +++ b/net/cert_net/nss_ocsp.cc
@@ -70,7 +70,7 @@ void StartUsing() { base::AutoLock autolock(lock_); - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); } @@ -370,7 +370,7 @@ { base::AutoLock autolock(lock_); DCHECK(!io_task_runner_); - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); g_ocsp_io_loop.Get().AddRequest(this); }
diff --git a/net/dns/dns_reloader.cc b/net/dns/dns_reloader.cc index ad96f68..e054568 100644 --- a/net/dns/dns_reloader.cc +++ b/net/dns/dns_reloader.cc
@@ -49,7 +49,7 @@ // NetworkChangeNotifier::DNSObserver: void OnDNSChanged() override { - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); base::AutoLock lock(lock_); resolver_generation_++; }
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc index fcb3b0c..95331e3c 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc
@@ -174,6 +174,11 @@ return HandleConnectResult(result); } +void HttpProxyConnectJob::ChangePriorityInternal(RequestPriority priority) { + if (client_socket_) + client_socket_->SetPriority(priority); +} + void HttpProxyConnectJob::OnConnectComplete(int result) { DCHECK_NE(ERR_IO_PENDING, result); result = HandleConnectResult(result);
diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h index 5938c20..90f49f5 100644 --- a/net/http/http_proxy_client_socket_pool.h +++ b/net/http/http_proxy_client_socket_pool.h
@@ -139,6 +139,8 @@ // a standard net error code will be returned. int ConnectInternal() override; + void ChangePriorityInternal(RequestPriority priority) override; + void OnConnectComplete(int result); int HandleConnectResult(int result);
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index f5b5368d4..edc4273 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -222,6 +222,10 @@ return transport_socket_pool_.last_request_priority(); } + RequestPriority GetTransportRequestPriority(size_t index) const { + return transport_socket_pool_.requests()[index]->priority(); + } + const base::HistogramTester& histogram_tester() { return histogram_tester_; } TestNetworkQualityEstimator* estimator() { return &estimator_; } @@ -293,6 +297,26 @@ CompletionOnceCallback(), pool_.get(), NetLogWithSource())); EXPECT_EQ(HIGHEST, GetLastTransportRequestPriority()); + EXPECT_EQ(HIGHEST, GetTransportRequestPriority(0)); +} + +TEST_P(HttpProxyClientSocketPoolTest, SetPriority) { + data_ = std::make_unique<SequencedSocketData>(); + data_->set_connect_data(MockConnect(ASYNC, OK)); + + socket_factory()->AddSocketDataProvider(data_.get()); + + int rv = handle_.Init("a", CreateTunnelParams(), LOW, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, + callback_.callback(), pool_.get(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + EXPECT_FALSE(handle_.is_initialized()); + EXPECT_FALSE(handle_.socket()); + + EXPECT_EQ(LOW, GetTransportRequestPriority(0)); + + handle_.SetPriority(HIGHEST); + EXPECT_EQ(HIGHEST, GetTransportRequestPriority(0)); } TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) { @@ -425,15 +449,14 @@ } // Make sure that HttpProxyConnectJob passes on its priority to its -// SPDY session's socket request on Init (if applicable). -TEST_P(HttpProxyClientSocketPoolTest, - SetSpdySessionSocketRequestPriorityOnInit) { +// SPDY session's socket request on Init, and on SetPriority. +TEST_P(HttpProxyClientSocketPoolTest, SetSpdySessionSocketRequestPriority) { if (GetParam() != SPDY) return; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, MEDIUM, - HostPortPair("www.google.com", 443))); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( + kAuthHeaders, kAuthHeadersSize, 1, HIGHEST, + HostPortPair("www.google.com", 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0, ASYNC)}; spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1)); MockRead spdy_reads[] = {CreateMockRead(resp, 1, ASYNC), @@ -449,7 +472,10 @@ ClientSocketPool::RespectLimits::ENABLED, callback_.callback(), pool_.get(), NetLogWithSource())); EXPECT_EQ(MEDIUM, GetLastTransportRequestPriority()); + EXPECT_EQ(MEDIUM, GetTransportRequestPriority(0)); + handle_.SetPriority(HIGHEST); + // Expect frame with HIGHEST priority, not MEDIUM. EXPECT_THAT(callback_.WaitForResult(), IsOk()); }
diff --git a/net/http/http_proxy_client_socket_wrapper.cc b/net/http/http_proxy_client_socket_wrapper.cc index c62ec6fb..74bea38 100644 --- a/net/http/http_proxy_client_socket_wrapper.cc +++ b/net/http/http_proxy_client_socket_wrapper.cc
@@ -73,7 +73,7 @@ tunnel_(tunnel), using_spdy_(false), is_trusted_proxy_(is_trusted_proxy), - quic_stream_request_(quic_stream_factory), + quic_stream_factory_(quic_stream_factory), http_auth_controller_( tunnel ? new HttpAuthController( HttpAuth::AUTH_PROXY, @@ -136,6 +136,27 @@ return std::move(error_response_info_); } +void HttpProxyClientSocketWrapper::SetPriority(RequestPriority priority) { + if (respect_limits_ == ClientSocketPool::RespectLimits::DISABLED) { + DCHECK_EQ(MAXIMUM_PRIORITY, priority_); + return; + } + + priority_ = priority; + + if (transport_socket_handle_) + transport_socket_handle_->SetPriority(priority); + + if (spdy_stream_request_) + spdy_stream_request_->SetPriority(priority); + + if (quic_stream_request_) + quic_stream_request_->SetPriority(priority); + + if (transport_socket_) + transport_socket_->SetStreamPriority(priority); +} + const HttpResponseInfo* HttpProxyClientSocketWrapper::GetConnectResponseInfo() const { if (transport_socket_) @@ -203,7 +224,8 @@ connect_callback_.Reset(); connect_timer_.Stop(); next_state_ = STATE_NONE; - spdy_stream_request_.CancelRequest(); + spdy_stream_request_.reset(); + quic_stream_request_.reset(); if (transport_socket_handle_) { if (transport_socket_handle_->socket()) transport_socket_handle_->socket()->Disconnect(); @@ -615,7 +637,8 @@ } next_state_ = STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE; - return spdy_stream_request_.StartRequest( + spdy_stream_request_ = std::make_unique<SpdyStreamRequest>(); + return spdy_stream_request_->StartRequest( SPDY_BIDIRECTIONAL_STREAM, spdy_session, GURL("https://" + endpoint_.ToString()), priority_, initial_socket_tag_, spdy_session->net_log(), @@ -625,11 +648,14 @@ } int HttpProxyClientSocketWrapper::DoSpdyProxyCreateStreamComplete(int result) { - if (result < 0) + if (result < 0) { + spdy_stream_request_.reset(); return result; + } next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE; - base::WeakPtr<SpdyStream> stream = spdy_stream_request_.ReleaseStream(); + base::WeakPtr<SpdyStream> stream = spdy_stream_request_->ReleaseStream(); + spdy_stream_request_.reset(); DCHECK(stream.get()); // |transport_socket_| will set itself as |stream|'s delegate. transport_socket_.reset(new SpdyProxyClientSocket( @@ -644,7 +670,9 @@ next_state_ = STATE_QUIC_PROXY_CREATE_STREAM; const HostPortPair& proxy_server = ssl_params_->GetDirectConnectionParams()->destination().host_port_pair(); - return quic_stream_request_.Request( + quic_stream_request_ = + std::make_unique<QuicStreamRequest>(quic_stream_factory_); + return quic_stream_request_->Request( proxy_server, quic_version_, ssl_params_->privacy_mode(), priority_, initial_socket_tag_, ssl_params_->ssl_config().GetCertVerifyFlags(), GURL("https://" + proxy_server.ToString()), net_log_, @@ -655,11 +683,15 @@ } int HttpProxyClientSocketWrapper::DoQuicProxyCreateStream(int result) { - if (result < 0) + if (result < 0) { + quic_stream_request_.reset(); return result; + } next_state_ = STATE_QUIC_PROXY_CREATE_STREAM_COMPLETE; - quic_session_ = quic_stream_request_.ReleaseSessionHandle(); + quic_session_ = quic_stream_request_->ReleaseSessionHandle(); + quic_stream_request_.reset(); + return quic_session_->RequestStream( false, base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete,
diff --git a/net/http/http_proxy_client_socket_wrapper.h b/net/http/http_proxy_client_socket_wrapper.h index ab8a1e7..8ddfcb84 100644 --- a/net/http/http_proxy_client_socket_wrapper.h +++ b/net/http/http_proxy_client_socket_wrapper.h
@@ -87,6 +87,8 @@ std::unique_ptr<HttpResponseInfo> GetAdditionalErrorState(); + void SetPriority(RequestPriority priority); + // ProxyClientSocket implementation. const HttpResponseInfo* GetConnectResponseInfo() const override; std::unique_ptr<HttpStream> CreateConnectResponseStream() override; @@ -218,9 +220,10 @@ // if necessary. CompletionOnceCallback connect_callback_; - SpdyStreamRequest spdy_stream_request_; + std::unique_ptr<SpdyStreamRequest> spdy_stream_request_; - QuicStreamRequest quic_stream_request_; + QuicStreamFactory* const quic_stream_factory_; + std::unique_ptr<QuicStreamRequest> quic_stream_request_; std::unique_ptr<QuicChromiumClientSession::Handle> quic_session_; scoped_refptr<HttpAuthController> http_auth_controller_;
diff --git a/net/http/http_proxy_client_socket_wrapper_unittest.cc b/net/http/http_proxy_client_socket_wrapper_unittest.cc index e57c271..4ef82b3 100644 --- a/net/http/http_proxy_client_socket_wrapper_unittest.cc +++ b/net/http/http_proxy_client_socket_wrapper_unittest.cc
@@ -162,13 +162,14 @@ } std::unique_ptr<quic::QuicReceivedPacket> ConstructConnectRequestPacket( - quic::QuicPacketNumber packet_number) { + quic::QuicPacketNumber packet_number, + RequestPriority priority) { spdy::SpdyHeaderBlock block; PopulateConnectRequestIR(&block); return client_maker_.MakeRequestHeadersPacket( packet_number, client_data_stream_id1_, kIncludeVersion, !kFin, - ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY), - std::move(block), 0, nullptr, &header_stream_offset_); + ConvertRequestPriorityToQuicPriority(priority), std::move(block), 0, + nullptr, &header_stream_offset_); } std::unique_ptr<quic::QuicReceivedPacket> ConstructServerConnectReplyPacket( @@ -258,7 +259,8 @@ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1)); - mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2)); + mock_quic_data_.AddWrite(SYNCHRONOUS, + ConstructConnectRequestPacket(2, HIGHEST)); mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin)); mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING); mock_quic_data_.AddWrite( @@ -283,7 +285,7 @@ client_socket_wrapper_.reset(new HttpProxyClientSocketWrapper( /*group_name=*/std::string(), /*requiest_priority=*/DEFAULT_PRIORITY, /*socket_tag=*/SocketTag(), - /*respect_limits=*/ClientSocketPool::RespectLimits::DISABLED, + /*respect_limits=*/ClientSocketPool::RespectLimits::ENABLED, /*connect_timeout_duration=*/base::TimeDelta::FromHours(1), /*proxy_negotiation_timeout_duration=*/base::TimeDelta::FromHours(1), /*transport_pool=*/nullptr, /*ssl_pool=*/nullptr, @@ -295,7 +297,11 @@ TestCompletionCallback callback; client_socket_wrapper_->Connect(callback.callback()); + EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_.request_priority(1)); + client_socket_wrapper_->SetPriority(HIGHEST); + + // Expect connect request packet with HIGHEST priority, not DEFAULT_PRIORITY. EXPECT_THAT(callback.WaitForResult(), IsOk()); client_socket_wrapper_.reset(); @@ -311,7 +317,8 @@ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1)); - mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2)); + mock_quic_data_.AddWrite(SYNCHRONOUS, + ConstructConnectRequestPacket(2, DEFAULT_PRIORITY)); mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin)); mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING); mock_quic_data_.AddWrite( @@ -337,7 +344,7 @@ client_socket_wrapper_.reset(new HttpProxyClientSocketWrapper( /*group_name=*/std::string(), /*requiest_priority=*/DEFAULT_PRIORITY, /*socket_tag=*/tag, - /*respect_limits=*/ClientSocketPool::RespectLimits::DISABLED, + /*respect_limits=*/ClientSocketPool::RespectLimits::ENABLED, /*connect_timeout_duration=*/base::TimeDelta::FromHours(1), /*proxy_negotiation_timeout_duration=*/base::TimeDelta::FromHours(1), /*transport_pool=*/nullptr, /*ssl_pool=*/nullptr,
diff --git a/net/http/proxy_client_socket.cc b/net/http/proxy_client_socket.cc index fe23978..e646fe1e 100644 --- a/net/http/proxy_client_socket.cc +++ b/net/http/proxy_client_socket.cc
@@ -19,6 +19,8 @@ namespace net { +void ProxyClientSocket::SetStreamPriority(RequestPriority priority) {} + // static void ProxyClientSocket::BuildTunnelRequest( const HostPortPair& endpoint,
diff --git a/net/http/proxy_client_socket.h b/net/http/proxy_client_socket.h index 046ea6c7..639ac30 100644 --- a/net/http/proxy_client_socket.h +++ b/net/http/proxy_client_socket.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "net/base/completion_once_callback.h" #include "net/base/net_export.h" +#include "net/base/request_priority.h" #include "net/socket/ssl_client_socket.h" #include "net/socket/stream_socket.h" @@ -58,6 +59,9 @@ // Returns the protocol negotiated with the proxy. virtual NextProto GetProxyNegotiatedProtocol() const = 0; + // Set the priority of the underlying stream (for SPDY and QUIC) + virtual void SetStreamPriority(RequestPriority priority); + protected: // The HTTP CONNECT method for establishing a tunnel connection is documented // in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2
diff --git a/net/http/transport_security_persister_unittest.cc b/net/http/transport_security_persister_unittest.cc index b5392b9..e74c841 100644 --- a/net/http/transport_security_persister_unittest.cc +++ b/net/http/transport_security_persister_unittest.cc
@@ -31,13 +31,13 @@ TransportSecurityPersisterTest() = default; ~TransportSecurityPersisterTest() override { - EXPECT_TRUE(base::MessageLoopForIO::IsCurrent()); + EXPECT_TRUE(base::MessageLoopCurrentForIO::IsSet()); base::RunLoop().RunUntilIdle(); } void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); + ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet()); persister_ = std::make_unique<TransportSecurityPersister>( &state_, temp_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get()); }
diff --git a/net/quic/quic_chromium_client_stream.cc b/net/quic/quic_chromium_client_stream.cc index fd52cc92..6433249b 100644 --- a/net/quic/quic_chromium_client_stream.cc +++ b/net/quic/quic_chromium_client_stream.cc
@@ -480,7 +480,7 @@ session_->HandlePromised(id(), promised_id, promise_headers); } -void QuicChromiumClientStream::OnDataAvailable() { +void QuicChromiumClientStream::OnBodyAvailable() { if (!FinishedReadingHeaders() || !headers_delivered_) { // Buffer the data in the sequencer until the headers have been read. return;
diff --git a/net/quic/quic_chromium_client_stream.h b/net/quic/quic_chromium_client_stream.h index e0019e4..5b1ad12 100644 --- a/net/quic/quic_chromium_client_stream.h +++ b/net/quic/quic_chromium_client_stream.h
@@ -218,7 +218,7 @@ void OnPromiseHeaderList(quic::QuicStreamId promised_id, size_t frame_len, const quic::QuicHeaderList& header_list) override; - void OnDataAvailable() override; + void OnBodyAvailable() override; void OnClose() override; void OnCanWrite() override; size_t WriteHeaders(
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index 653a291..2edd5c1 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -219,9 +219,6 @@ FLAGS_quic_reloadable_flag_quic_fix_has_pending_crypto_data, true) -// This flag fixes a bug where a zombie stream cannot be correctly reset. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_reset_zombie_streams, true) - // When true, fix initialization and updating of // |time_of_first_packet_sent_after_receiving_| in QuicConnection. QUIC_FLAG( @@ -229,20 +226,10 @@ FLAGS_quic_reloadable_flag_quic_fix_time_of_first_packet_sent_after_receiving, true) -// If true, deprecate PostProcessAfterData from QuicConnection. This is used to -// fix a bug where window update causes session to write data. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_deprecate_post_process_after_data, - true) - // When the STMP connection option is sent by the client, timestamps in the QUIC // ACK frame are sent and processed. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_send_timestamps, false) -// When true, don't arm the path degrading alarm on the server side and stop -// using HasUnackedPackets to decide when to arm it. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_path_degrading_alarm, true) - // When true, QUIC server push uses a unidirectional stream. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_unidirectional_server_push_stream, @@ -252,7 +239,7 @@ // a new decryption key is made available. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_decrypt_packets_on_key_change, - false) + true) // This flag fixes a bug where dispatcher's last_packet_is_ietf_quic may be // wrong when getting proof asynchronously. @@ -316,3 +303,18 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_startup_rate_reduction, false) + +// If true, enable the fix for the bug where v44 packets are rejected +// by a lower-version connection close. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_fix_reject_by_session_type, + true) + +// If true, only send version negotiation packets when they are at least +// 1200 bytes. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_limit_version_negotiation, + false) + +// If true, disables key share caching for QUIC key exchange +QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_no_ephemeral_key_source, false)
diff --git a/net/quic/quic_proxy_client_socket.cc b/net/quic/quic_proxy_client_socket.cc index ebcb314..de4c869 100644 --- a/net/quic/quic_proxy_client_socket.cc +++ b/net/quic/quic_proxy_client_socket.cc
@@ -86,6 +86,10 @@ return kProtoQUIC; } +void QuicProxyClientSocket::SetStreamPriority(RequestPriority priority) { + stream_->SetPriority(ConvertRequestPriorityToSpdyPriority(priority)); +} + // Sends a HEADERS frame to the proxy with a CONNECT request // for the specified endpoint. Waits for the server to send back // a HEADERS frame. OK will be returned if the status is 200.
diff --git a/net/quic/quic_proxy_client_socket.h b/net/quic/quic_proxy_client_socket.h index 45d15fcb..b9688ec 100644 --- a/net/quic/quic_proxy_client_socket.h +++ b/net/quic/quic_proxy_client_socket.h
@@ -47,6 +47,7 @@ int RestartWithAuth(CompletionOnceCallback callback) override; bool IsUsingSpdy() const override; NextProto GetProxyNegotiatedProtocol() const override; + void SetStreamPriority(RequestPriority priority) override; // StreamSocket implementation. int Connect(CompletionOnceCallback callback) override;
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc index bdcc92a..7c741911 100644 --- a/net/quic/quic_proxy_client_socket_unittest.cc +++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -299,13 +299,14 @@ } std::unique_ptr<quic::QuicReceivedPacket> ConstructConnectRequestPacket( - quic::QuicPacketNumber packet_number) { + quic::QuicPacketNumber packet_number, + RequestPriority request_priority = LOWEST) { spdy::SpdyHeaderBlock block; PopulateConnectRequestIR(&block); return client_maker_.MakeRequestHeadersPacket( packet_number, client_data_stream_id1_, kIncludeVersion, !kFin, - ConvertRequestPriorityToQuicPriority(LOWEST), std::move(block), 0, - nullptr, &header_stream_offset_); + ConvertRequestPriorityToQuicPriority(request_priority), + std::move(block), 0, nullptr, &header_stream_offset_); } std::unique_ptr<quic::QuicReceivedPacket> ConstructConnectAuthRequestPacket( @@ -769,7 +770,21 @@ EXPECT_EQ((int64_t)kLen333, sock_->GetTotalReceivedBytes()); } -// ----------- Write +TEST_P(QuicProxyClientSocketTest, SetStreamPriority) { + mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1)); + mock_quic_data_.AddWrite(SYNCHRONOUS, + ConstructConnectRequestPacket(2, HIGHEST)); + mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin)); + mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + mock_quic_data_.AddWrite( + SYNCHRONOUS, + ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); + + Initialize(); + + sock_->SetStreamPriority(HIGHEST); + AssertConnectSucceeds(); +} TEST_P(QuicProxyClientSocketTest, WriteSendsDataInDataFrame) { mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 3d411a3f..7c817c5 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -372,10 +372,24 @@ stream_requests_.erase(request_iter); } + void SetPriority(RequestPriority priority) { + if (priority_ == priority) + return; + + priority_ = priority; + if (io_state_ == STATE_RESOLVE_HOST_COMPLETE && + !host_resolution_finished_) { + DCHECK(request_); + request_->ChangeRequestPriority(priority); + } + } + const std::set<QuicStreamRequest*>& stream_requests() { return stream_requests_; } + RequestPriority priority() const { return priority_; } + bool IsHostResolutionComplete() const { return host_resolution_finished_; } private: @@ -418,7 +432,7 @@ HostResolver* host_resolver_; std::unique_ptr<HostResolver::Request> request_; const QuicSessionAliasKey key_; - const RequestPriority priority_; + RequestPriority priority_; const int cert_verify_flags_; const bool was_alternative_service_recently_broken_; const bool retry_on_alternate_network_before_handshake_; @@ -924,6 +938,11 @@ return factory_->GetTimeDelayForWaitingJob(session_key_.server_id()); } +void QuicStreamRequest::SetPriority(RequestPriority priority) { + if (factory_) + factory_->SetRequestPriority(this, priority); +} + std::unique_ptr<QuicChromiumClientSession::Handle> QuicStreamRequest::ReleaseSessionHandle() { if (!session_ || !session_->IsConnected()) @@ -1417,6 +1436,14 @@ job_iter->second->RemoveRequest(request); } +void QuicStreamFactory::SetRequestPriority(QuicStreamRequest* request, + RequestPriority priority) { + auto job_iter = active_jobs_.find(request->session_key()); + if (job_iter == active_jobs_.end()) + return; + job_iter->second->SetPriority(priority); +} + void QuicStreamFactory::CloseAllSessions(int error, quic::QuicErrorCode quic_error) { base::UmaHistogramSparse("Net.QuicSession.CloseAllSessionsError", -error);
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index ec06a48..6dcb932 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -153,6 +153,10 @@ // returns the amount of time waiting job should be delayed. base::TimeDelta GetTimeDelayForWaitingJob() const; + // If host resolution is underway, changes the priority of the host resolver + // request. + void SetPriority(RequestPriority priority); + // Releases the handle to the QUIC session retrieved as a result of Request(). std::unique_ptr<QuicChromiumClientSession::Handle> ReleaseSessionHandle(); @@ -295,6 +299,9 @@ // Cancels a pending request. void CancelRequest(QuicStreamRequest* request); + // Sets priority of a request. + void SetRequestPriority(QuicStreamRequest* request, RequestPriority priority); + // Closes all current sessions with specified network, QUIC error codes. // It sends connection close packet when closing connections. void CloseAllSessions(int error, quic::QuicErrorCode quic_error);
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 28d3611..04de076 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -8411,6 +8411,42 @@ EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } +TEST_P(QuicStreamFactoryTest, HostResolverRequestReprioritizedOnSetPriority) { + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data; + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + host_port_pair_, version_, privacy_mode_, MAXIMUM_PRIORITY, + SocketTag(), + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + + EXPECT_EQ(MAXIMUM_PRIORITY, host_resolver_->last_request_priority()); + EXPECT_EQ(MAXIMUM_PRIORITY, host_resolver_->request_priority(1)); + + QuicStreamRequest request2(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request2.Request( + host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), + /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); + EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->request_priority(2)); + + request.SetPriority(LOWEST); + EXPECT_EQ(LOWEST, host_resolver_->request_priority(1)); + EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->request_priority(2)); +} + // Passes |max_time_before_crypto_handshake_seconds| and // |max_idle_time_before_crypto_handshake_seconds| to QuicStreamFactory, then // checks that its internal quic::QuicConfig is correct.
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc index 8631afd..724bbd8 100644 --- a/net/spdy/spdy_proxy_client_socket.cc +++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -93,6 +93,10 @@ return spdy_stream_->GetNegotiatedProtocol(); } +void SpdyProxyClientSocket::SetStreamPriority(RequestPriority priority) { + spdy_stream_->SetPriority(priority); +} + std::unique_ptr<HttpStream> SpdyProxyClientSocket::CreateConnectResponseStream() { return std::make_unique<ProxyConnectRedirectHttpStream>(
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h index 6aef81f45..98948d5e 100644 --- a/net/spdy/spdy_proxy_client_socket.h +++ b/net/spdy/spdy_proxy_client_socket.h
@@ -63,6 +63,7 @@ int RestartWithAuth(CompletionOnceCallback callback) override; bool IsUsingSpdy() const override; NextProto GetProxyNegotiatedProtocol() const override; + void SetStreamPriority(RequestPriority priority) override; // StreamSocket implementation. int Connect(CompletionOnceCallback callback) override;
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index a1326fc..5354c26 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -90,7 +90,8 @@ base::span<const MockWrite> writes); void PopulateConnectRequestIR(spdy::SpdyHeaderBlock* syn_ir); void PopulateConnectReplyIR(spdy::SpdyHeaderBlock* block, const char* status); - spdy::SpdySerializedFrame ConstructConnectRequestFrame(); + spdy::SpdySerializedFrame ConstructConnectRequestFrame( + RequestPriority priority); spdy::SpdySerializedFrame ConstructConnectAuthRequestFrame(); spdy::SpdySerializedFrame ConstructConnectReplyFrame(); spdy::SpdySerializedFrame ConstructConnectAuthReplyFrame(); @@ -353,10 +354,11 @@ // Constructs a standard SPDY HEADERS frame for a CONNECT request. spdy::SpdySerializedFrame -SpdyProxyClientSocketTest::ConstructConnectRequestFrame() { +SpdyProxyClientSocketTest::ConstructConnectRequestFrame( + RequestPriority priority = LOWEST) { spdy::SpdyHeaderBlock block; PopulateConnectRequestIR(&block); - return spdy_util_.ConstructSpdyHeaders(kStreamId, std::move(block), LOWEST, + return spdy_util_.ConstructSpdyHeaders(kStreamId, std::move(block), priority, false); } @@ -533,6 +535,25 @@ ASSERT_FALSE(sock_->IsConnected()); } +TEST_P(SpdyProxyClientSocketTest, SetStreamPriority) { + spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame(HIGHEST)); + MockWrite writes[] = { + CreateMockWrite(conn, 0, SYNCHRONOUS), + }; + + spdy::SpdySerializedFrame resp(ConstructConnectReplyFrame()); + MockRead reads[] = { + CreateMockRead(resp, 1, ASYNC), + MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2), + }; + + Initialize(reads, writes); + + sock_->SetStreamPriority(HIGHEST); + + AssertConnectSucceeds(); +} + // ----------- WasEverUsed TEST_P(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) {
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index f0bee16..14e433b 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -715,6 +715,18 @@ return base::trace_event::EstimateItemMemoryUsage(url_); } +void SpdyStreamRequest::SetPriority(RequestPriority priority) { + if (priority_ == priority) + return; + + if (stream_) + stream_->SetPriority(priority); + if (session_) + session_->ChangeStreamRequestPriority(weak_ptr_factory_.GetWeakPtr(), + priority); + priority_ = priority; +} + void SpdyStreamRequest::OnRequestCompleteSuccess( const base::WeakPtr<SpdyStream>& stream) { DCHECK(session_); @@ -1622,7 +1634,7 @@ return OK; } -void SpdySession::CancelStreamRequest( +bool SpdySession::CancelStreamRequest( const base::WeakPtr<SpdyStreamRequest>& request) { DCHECK(request); RequestPriority priority = request->priority(); @@ -1653,6 +1665,20 @@ // present, should not be pending completion. DCHECK(std::find_if(it, queue->end(), RequestEquals(request)) == queue->end()); + return true; + } + return false; +} + +void SpdySession::ChangeStreamRequestPriority( + const base::WeakPtr<SpdyStreamRequest>& request, + RequestPriority priority) { + // |request->priority()| is updated by the caller after this returns. + // |request| needs to still have its old priority in order for + // CancelStreamRequest() to find it in the correct queue. + DCHECK_NE(priority, request->priority()); + if (CancelStreamRequest(request)) { + pending_create_stream_queues_[priority].push_back(request); } }
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index a04416b..9956f573 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -227,6 +227,10 @@ // set a delegate for the returned stream (except for test code). base::WeakPtr<SpdyStream> ReleaseStream(); + // Changes the priority of the stream, or changes the priority of the queued + // request in the session. + void SetPriority(RequestPriority priority); + // Returns the estimate of dynamically allocated memory in bytes. size_t EstimateMemoryUsage() const; @@ -606,8 +610,14 @@ base::WeakPtr<SpdyStream>* stream); // Called by SpdyStreamRequest to remove |request| from the stream - // creation queue. - void CancelStreamRequest(const base::WeakPtr<SpdyStreamRequest>& request); + // creation queue. Returns whether a request was removed from the queue. + bool CancelStreamRequest(const base::WeakPtr<SpdyStreamRequest>& request); + + // Removes |request| from the stream creation queue and reinserts it into the + // queue at the new |priority|. + void ChangeStreamRequestPriority( + const base::WeakPtr<SpdyStreamRequest>& request, + RequestPriority priority); // Returns the next pending stream request to process, or NULL if // there is none.
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index e03c45d..ea6a123 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -2003,6 +2003,48 @@ base::RunLoop().RunUntilIdle(); } +TEST_F(SpdySessionTest, ChangeStreamRequestPriority) { + MockRead reads[] = { + MockRead(ASYNC, ERR_IO_PENDING) // Stall forever. + }; + + StaticSocketDataProvider data(reads, base::span<MockWrite>()); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + AddSSLSocketData(); + + CreateNetworkSession(); + CreateSpdySession(); + + set_max_concurrent_streams(1); + + TestCompletionCallback callback1; + SpdyStreamRequest request1; + ASSERT_EQ(OK, request1.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, + test_url_, 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(), + NetLogWithSource(), callback2.callback(), + TRAFFIC_ANNOTATION_FOR_TESTS)); + + request1.SetPriority(HIGHEST); + request2.SetPriority(MEDIUM); + + ASSERT_EQ(0u, pending_create_stream_queue_size(HIGHEST)); + // Priority of queued request is changed. + ASSERT_EQ(1u, pending_create_stream_queue_size(MEDIUM)); + ASSERT_EQ(0u, pending_create_stream_queue_size(LOWEST)); + + base::WeakPtr<SpdyStream> stream1 = request1.ReleaseStream(); + // Priority of stream is updated if request has been fulfilled. + ASSERT_EQ(HIGHEST, stream1->priority()); +} + TEST_F(SpdySessionTest, Initialize) { MockRead reads[] = { MockRead(ASYNC, 0, 0) // EOF
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender.cc b/net/third_party/quic/core/congestion_control/bbr_sender.cc index 02b29f5..2770424 100644 --- a/net/third_party/quic/core/congestion_control/bbr_sender.cc +++ b/net/third_party/quic/core/congestion_control/bbr_sender.cc
@@ -769,16 +769,14 @@ // Slow the pacing rate in STARTUP by the bytes_lost / CWND. if (startup_rate_reduction_multiplier_ != 0 && has_ever_detected_loss && has_non_app_limited_sample_) { - if (startup_bytes_lost_ > congestion_window_) { - pacing_rate_ = BandwidthEstimate(); - } else { - pacing_rate_ = - (1 - (startup_bytes_lost_ * startup_rate_reduction_multiplier_ * - 1.0f / congestion_window_)) * - target_rate; - // Ensure the pacing rate doesn't drop below the bandwidth estimate. - pacing_rate_ = std::max(pacing_rate_, BandwidthEstimate()); - } + pacing_rate_ = + (1 - (startup_bytes_lost_ * startup_rate_reduction_multiplier_ * 1.0f / + congestion_window_)) * + target_rate; + // Ensure the pacing rate doesn't drop below the startup growth target times + // the bandwidth estimate. + pacing_rate_ = + std::max(pacing_rate_, kStartupGrowthTarget * BandwidthEstimate()); return; }
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender_test.cc b/net/third_party/quic/core/congestion_control/bbr_sender_test.cc index 9b13a9d6..71330a0 100644 --- a/net/third_party/quic/core/congestion_control/bbr_sender_test.cc +++ b/net/third_party/quic/core/congestion_control/bbr_sender_test.cc
@@ -818,7 +818,6 @@ kTestRtt + QuicTime::Delta::FromMilliseconds(200); simulator_.RunFor(0.60 * time_to_exit_probe_rtt); EXPECT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode); - EXPECT_TRUE(sender_->ExportDebugState().last_sample_is_app_limited); // Lose a packet before exiting PROBE_RTT, which puts us in packet // conservation and then continue there for a while and ensure the bandwidth // estimate doesn't decrease. @@ -1197,7 +1196,7 @@ EXPECT_EQ(original_cwnd, sender_->GetCongestionWindow()); EXPECT_GT(original_pacing_rate, sender_->PacingRate(0)); EXPECT_GE(pacing_rate, sender_->PacingRate(0)); - EXPECT_LE(sender_->BandwidthEstimate(), sender_->PacingRate(0)); + EXPECT_LE(1.25 * sender_->BandwidthEstimate(), sender_->PacingRate(0)); pacing_rate = sender_->PacingRate(0); } } @@ -1247,7 +1246,7 @@ EXPECT_EQ(original_cwnd, sender_->GetCongestionWindow()); EXPECT_GT(original_pacing_rate, sender_->PacingRate(0)); EXPECT_GE(pacing_rate, sender_->PacingRate(0)); - EXPECT_LE(sender_->BandwidthEstimate(), sender_->PacingRate(0)); + EXPECT_LE(1.25 * sender_->BandwidthEstimate(), sender_->PacingRate(0)); pacing_rate = sender_->PacingRate(0); } }
diff --git a/net/third_party/quic/core/crypto/quic_crypto_server_config.cc b/net/third_party/quic/core/crypto/quic_crypto_server_config.cc index 02cd7df..90c7a97 100644 --- a/net/third_party/quic/core/crypto/quic_crypto_server_config.cc +++ b/net/third_party/quic/core/crypto/quic_crypto_server_config.cc
@@ -1111,6 +1111,14 @@ } QuicString forward_secure_public_value; + if (GetQuicRestartFlag(quic_no_ephemeral_key_source)) { + if (ephemeral_key_source_) { + QUIC_BUG << "quic_no_ephemeral_key_source flag is on, but " + "ephemeral_key_source is present"; + } else { + QUIC_FLAG_COUNT(quic_restart_flag_quic_no_ephemeral_key_source); + } + } if (ephemeral_key_source_) { params->forward_secure_premaster_secret = ephemeral_key_source_->CalculateForwardSecureKey(
diff --git a/net/third_party/quic/core/frames/quic_message_frame.h b/net/third_party/quic/core/frames/quic_message_frame.h index 83d7808..575e154 100644 --- a/net/third_party/quic/core/frames/quic_message_frame.h +++ b/net/third_party/quic/core/frames/quic_message_frame.h
@@ -23,8 +23,8 @@ // message_id is only used on the sender side and does not get serialized on // wire. QuicMessageId message_id; - // The actual data is not owned. - QuicStringPiece message_data; + // The actual data. + QuicString message_data; }; } // namespace quic
diff --git a/net/third_party/quic/core/http/quic_spdy_client_stream.cc b/net/third_party/quic/core/http/quic_spdy_client_stream.cc index 07fc556..5f685543 100644 --- a/net/third_party/quic/core/http/quic_spdy_client_stream.cc +++ b/net/third_party/quic/core/http/quic_spdy_client_stream.cc
@@ -96,7 +96,7 @@ } } -void QuicSpdyClientStream::OnDataAvailable() { +void QuicSpdyClientStream::OnBodyAvailable() { // For push streams, visitor will not be set until the rendezvous // between server promise and client request is complete. if (visitor() == nullptr)
diff --git a/net/third_party/quic/core/http/quic_spdy_client_stream.h b/net/third_party/quic/core/http/quic_spdy_client_stream.h index f8a6dc8b..e0db425 100644 --- a/net/third_party/quic/core/http/quic_spdy_client_stream.h +++ b/net/third_party/quic/core/http/quic_spdy_client_stream.h
@@ -45,7 +45,7 @@ const QuicHeaderList& header_list) override; // QuicStream implementation called by the session when there's data for us. - void OnDataAvailable() override; + void OnBodyAvailable() override; // Serializes the headers and body, sends it to the server, and // returns the number of bytes sent.
diff --git a/net/third_party/quic/core/http/quic_spdy_server_stream_base_test.cc b/net/third_party/quic/core/http/quic_spdy_server_stream_base_test.cc index bb168b7c..8c293be 100644 --- a/net/third_party/quic/core/http/quic_spdy_server_stream_base_test.cc +++ b/net/third_party/quic/core/http/quic_spdy_server_stream_base_test.cc
@@ -22,7 +22,7 @@ StreamType type) : QuicSpdyServerStreamBase(id, session, type) {} - void OnDataAvailable() override {} + void OnBodyAvailable() override {} }; class QuicSpdyServerStreamBaseTest : public QuicTest {
diff --git a/net/third_party/quic/core/http/quic_spdy_session_test.cc b/net/third_party/quic/core/http/quic_spdy_session_test.cc index b574ec6..c845c386 100644 --- a/net/third_party/quic/core/http/quic_spdy_session_test.cc +++ b/net/third_party/quic/core/http/quic_spdy_session_test.cc
@@ -123,7 +123,7 @@ using QuicStream::CloseWriteSide; - void OnDataAvailable() override {} + void OnBodyAvailable() override {} MOCK_METHOD0(OnCanWrite, void()); MOCK_METHOD3(RetransmitStreamData, @@ -247,7 +247,6 @@ using QuicSession::closed_streams; using QuicSession::next_outgoing_stream_id; - using QuicSession::PostProcessAfterData; using QuicSession::zombie_streams; private: @@ -1153,9 +1152,6 @@ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(), QUIC_STREAM_CANCELLED, kByteOffset); session_.OnRstStream(rst_frame); - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); } @@ -1172,9 +1168,6 @@ kInitialSessionFlowControlWindowForTest / 2 - 1; QuicStreamFrame frame(stream->id(), true, kByteOffset, "."); session_.OnStreamFrame(frame); - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } EXPECT_TRUE(connection_->connected()); EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed()); @@ -1383,12 +1376,6 @@ // Create one more data streams to exceed limit of open stream. QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT")); session_.OnStreamFrame(data1); - - // Called after any new data is received by the session, and triggers the - // call to close the connection. - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } } TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) { @@ -1419,12 +1406,6 @@ session_.StreamDraining(i); EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); } - - // Called after any new data is received by the session, and triggers the call - // to close the connection. - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } } TEST_P(QuicSpdySessionTestServer, TestMaxIncomingAndOutgoingStreamsAllowed) { @@ -1491,10 +1472,6 @@ stream->Reset(QUIC_STREAM_CANCELLED); EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream)); - // Allow the session to delete the stream object. - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } EXPECT_TRUE(connection_->connected()); EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id)); EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
diff --git a/net/third_party/quic/core/http/quic_spdy_stream.cc b/net/third_party/quic/core/http/quic_spdy_stream.cc index 9a45e5b..1704504 100644 --- a/net/third_party/quic/core/http/quic_spdy_stream.cc +++ b/net/third_party/quic/core/http/quic_spdy_stream.cc
@@ -14,6 +14,7 @@ #include "net/third_party/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_logging.h" +#include "net/third_party/quic/platform/api/quic_mem_slice_storage.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" #include "net/third_party/quic/platform/api/quic_text_utils.h" @@ -265,6 +266,10 @@ CloseWriteSide(); } +void QuicSpdyStream::OnDataAvailable() { + OnBodyAvailable(); +} + void QuicSpdyStream::OnClose() { QuicStream::OnClose();
diff --git a/net/third_party/quic/core/http/quic_spdy_stream.h b/net/third_party/quic/core/http/quic_spdy_stream.h index d8436b8..53512fdf 100644 --- a/net/third_party/quic/core/http/quic_spdy_stream.h +++ b/net/third_party/quic/core/http/quic_spdy_stream.h
@@ -21,7 +21,6 @@ #include "net/third_party/quic/core/quic_stream_sequencer.h" #include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_flags.h" -#include "net/third_party/quic/platform/api/quic_mem_slice_storage.h" #include "net/third_party/quic/platform/api/quic_socket_address.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/spdy/core/spdy_framer.h" @@ -97,6 +96,13 @@ // QUIC_STREAM_NO_ERROR. void OnStreamReset(const QuicRstStreamFrame& frame) override; + // Called by the sequencer when new data is available. Decodes the data and + // calls OnBodyAvailable() to pass to the upper layer. + void OnDataAvailable() override; + + // Called in OnDataAvailable() after it finishes the decoding job. + virtual void OnBodyAvailable() = 0; + // Writes the headers contained in |header_block| to the dedicated // headers stream. virtual size_t WriteHeaders(
diff --git a/net/third_party/quic/core/http/quic_spdy_stream_test.cc b/net/third_party/quic/core/http/quic_spdy_stream_test.cc index add92f4..750dc8d4 100644 --- a/net/third_party/quic/core/http/quic_spdy_stream_test.cc +++ b/net/third_party/quic/core/http/quic_spdy_stream_test.cc
@@ -49,7 +49,7 @@ : QuicSpdyStream(id, session, BIDIRECTIONAL), should_process_data_(should_process_data) {} - void OnDataAvailable() override { + void OnBodyAvailable() override { if (!should_process_data_) { return; }
diff --git a/net/third_party/quic/core/qpack/qpack_constants.cc b/net/third_party/quic/core/qpack/qpack_constants.cc new file mode 100644 index 0000000..0975699 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_constants.cc
@@ -0,0 +1,137 @@ +// 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 "net/third_party/quic/core/qpack/qpack_constants.h" + +namespace quic { + +bool operator==(const QpackInstructionOpcode& a, + const QpackInstructionOpcode& b) { + return std::tie(a.value, a.mask) == std::tie(b.value, b.mask); +} + +const QpackInstruction* InsertWithNameReferenceInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kInsertWithNameReferenceOpcode, + kInsertWithNameReferenceOpcodeMask}; + static const QpackInstruction* const instruction = new QpackInstruction{ + *opcode, + {{QpackInstructionFieldType::kStaticBit, + kInsertWithNameReferenceStaticBit}, + {QpackInstructionFieldType::kVarint, + kInsertWithNameReferenceNameIndexPrefixLength}, + {QpackInstructionFieldType::kValue, kLiteralValuePrefixLength}}}; + return instruction; +} + +const QpackInstruction* InsertWithoutNameReferenceInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kInsertWithoutNameReferenceOpcode, + kInsertWithoutNameReferenceOpcodeMask}; + static const QpackInstruction* const instruction = new QpackInstruction{ + *opcode, + {{QpackInstructionFieldType::kName, + kInsertWithoutNameReferenceNameLengthPrefixLength}, + {QpackInstructionFieldType::kValue, kLiteralValuePrefixLength}}}; + return instruction; +} + +const QpackInstruction* DuplicateInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kDuplicateOpcode, kDuplicateOpcodeMask}; + static const QpackInstruction* const instruction = new QpackInstruction{ + *opcode, + {{QpackInstructionFieldType::kVarint, kDuplicateIndexPrefixLength}}}; + return instruction; +} + +const QpackInstruction* DynamicTableSizeUpdateInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kDynamicTableSizeUpdateOpcode, + kDynamicTableSizeUpdateOpcodeMask}; + static const QpackInstruction* const instruction = + new QpackInstruction{*opcode, + {{QpackInstructionFieldType::kVarint, + kDynamicTableSizeUpdateMaxSizePrefixLength}}}; + return instruction; +} + +const QpackLanguage* QpackEncoderStreamLanguage() { + static const QpackLanguage* const language = new QpackLanguage{ + InsertWithNameReferenceInstruction(), + InsertWithoutNameReferenceInstruction(), DuplicateInstruction(), + DynamicTableSizeUpdateInstruction()}; + return language; +} + +const QpackInstruction* QpackIndexedHeaderFieldInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kIndexedHeaderFieldOpcodeValue, + kIndexedHeaderFieldOpcodeMask}; + static const QpackInstruction* const instruction = new QpackInstruction{ + *opcode, + {{QpackInstructionFieldType::kStaticBit, kIndexedHeaderFieldStaticBit}, + {QpackInstructionFieldType::kVarint, kIndexedHeaderFieldPrefixLength}}}; + return instruction; +} + +const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kIndexedHeaderFieldPostBaseOpcodeValue, + kIndexedHeaderFieldPostBaseOpcodeMask}; + static const QpackInstruction* const instruction = + new QpackInstruction{*opcode, + {{QpackInstructionFieldType::kVarint, + kIndexedHeaderFieldPostBasePrefixLength}}}; + return instruction; +} + +const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kLiteralHeaderFieldNameReferenceOpcodeValue, + kLiteralHeaderFieldNameReferenceOpcodeMask}; + static const QpackInstruction* const instruction = new QpackInstruction{ + *opcode, + {{QpackInstructionFieldType::kStaticBit, + kLiteralHeaderFieldNameReferenceStaticBit}, + {QpackInstructionFieldType::kVarint, + kLiteralHeaderFieldNameReferencePrefixLength}, + {QpackInstructionFieldType::kValue, kLiteralValuePrefixLength}}}; + return instruction; +} + +const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kLiteralHeaderFieldPostBaseOpcodeValue, + kLiteralHeaderFieldPostBaseOpcodeMask}; + static const QpackInstruction* const instruction = new QpackInstruction{ + *opcode, + {{QpackInstructionFieldType::kVarint, + kLiteralHeaderFieldPostBasePrefixLength}, + {QpackInstructionFieldType::kValue, kLiteralValuePrefixLength}}}; + return instruction; +} + +const QpackInstruction* QpackLiteralHeaderFieldInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{kLiteralHeaderFieldOpcodeValue, + kLiteralHeaderFieldOpcodeMask}; + static const QpackInstruction* const instruction = new QpackInstruction{ + *opcode, + {{QpackInstructionFieldType::kName, kLiteralHeaderFieldPrefixLength}, + {QpackInstructionFieldType::kValue, kLiteralValuePrefixLength}}}; + return instruction; +} + +const QpackLanguage* QpackRequestStreamLanguage() { + static const QpackLanguage* const language = + new QpackLanguage{QpackIndexedHeaderFieldInstruction(), + QpackIndexedHeaderFieldPostBaseInstruction(), + QpackLiteralHeaderFieldNameReferenceInstruction(), + QpackLiteralHeaderFieldPostBaseInstruction(), + QpackLiteralHeaderFieldInstruction()}; + return language; +} + +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_constants.h b/net/third_party/quic/core/qpack/qpack_constants.h index 585577d..217e22c 100644 --- a/net/third_party/quic/core/qpack/qpack_constants.h +++ b/net/third_party/quic/core/qpack/qpack_constants.h
@@ -6,9 +6,76 @@ #define NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_CONSTANTS_H_ #include <cstdint> +#include <tuple> +#include <vector> + +#include "net/third_party/quic/platform/api/quic_export.h" +#include "net/third_party/quic/platform/api/quic_string.h" namespace quic { +// Each instruction is identified with an opcode in the first byte. +// |mask| determines which bits are part of the opcode. +// |value| is the value of these bits. (Other bits in value must be zero.) +struct QUIC_EXPORT_PRIVATE QpackInstructionOpcode { + uint8_t value; + uint8_t mask; +}; + +bool operator==(const QpackInstructionOpcode& a, + const QpackInstructionOpcode& b); + +// Possible types of an instruction field. Decoding a static bit does not +// consume the current byte. Decoding an integer or a length-prefixed string +// literal consumes all bytes containing the field value. +enum class QpackInstructionFieldType { + // A single bit indicating whether the index is static. + kStaticBit, + // An integer encoded with variable length encoding. This could be an index, + // stream ID, or maximum size. + kVarint, + // A header name or header value encoded as: + // a bit indicating whether it is Huffman encoded; + // the encoded length of the string; + // the header name or value optionally Huffman encoded. + kName, + kValue +}; + +// Each instruction field has a type and a parameter. +// The meaning of the parameter depends on the field type. +struct QUIC_EXPORT_PRIVATE QpackInstructionField { + QpackInstructionFieldType type; + // For a kStaticBit field, |param| is a mask with exactly one bit set. + // For kVarint fields, |param| is the prefix length of the integer encoding. + // For kName and kValue fields, |param| is the prefix length of the length of + // the string, and the bit immediately preceding the prefix is interpreted as + // the Huffman bit. + uint8_t param; +}; + +using QpackInstructionFields = std::vector<QpackInstructionField>; + +// A QPACK instruction consists of an opcode identifying the instruction, +// followed by a non-empty list of fields. The last field must be integer or +// string literal type to guarantee that all bytes of the instruction are +// consumed. +struct QUIC_EXPORT_PRIVATE QpackInstruction { + QpackInstruction(const QpackInstruction&) = delete; + const QpackInstruction& operator=(const QpackInstruction&) = delete; + + QpackInstructionOpcode opcode; + QpackInstructionFields fields; +}; + +// A language is a collection of instructions. The order does not matter. +// The set of instruction opcodes must cover all possible input. +using QpackLanguage = std::vector<const QpackInstruction*>; + +// Maximum length of header name and header value. This limits the amount of +// memory the peer can make the decoder allocate when sending string literals. +const size_t kStringLiteralLengthLimit = 1024 * 1024; + // TODO(bnc): Move this into HpackVarintEncoder. // The integer encoder can encode up to 2^64-1, which can take up to 10 bytes // (each carrying 7 bits) after the prefix. @@ -17,6 +84,11 @@ // Wire format defined in // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5 +// Value encoding for instructions with literal value. +const uint8_t kLiteralValueHuffmanMask = 0b10000000; +const uint8_t kLiteralValueWithoutHuffmanEncoding = 0b00000000; +const uint8_t kLiteralValuePrefixLength = 7; + // Encoder stream // 5.2.1 Insert With Name Reference @@ -25,56 +97,76 @@ const uint8_t kInsertWithNameReferenceStaticBit = 0b01000000; const uint8_t kInsertWithNameReferenceNameIndexPrefixLength = 6; +const QpackInstruction* InsertWithNameReferenceInstruction(); + // 5.2.2 Insert Without Name Reference const uint8_t kInsertWithoutNameReferenceOpcode = 0b01000000; const uint8_t kInsertWithoutNameReferenceOpcodeMask = 0b11000000; const uint8_t kInsertWithoutNameReferenceNameHuffmanBit = 0b00100000; const uint8_t kInsertWithoutNameReferenceNameLengthPrefixLength = 5; +const QpackInstruction* InsertWithoutNameReferenceInstruction(); + // 5.2.3 Duplicate const uint8_t kDuplicateOpcode = 0b00000000; const uint8_t kDuplicateOpcodeMask = 0b11100000; const uint8_t kDuplicateIndexPrefixLength = 5; +const QpackInstruction* DuplicateInstruction(); + // 5.2.4 Dynamic Table Size Update const uint8_t kDynamicTableSizeUpdateOpcode = 0b00100000; const uint8_t kDynamicTableSizeUpdateOpcodeMask = 0b11100000; const uint8_t kDynamicTableSizeUpdateMaxSizePrefixLength = 5; +const QpackInstruction* DynamicTableSizeUpdateInstruction(); + +// Description of language (set of instructions) used on the encoder stream. +const QpackLanguage* QpackEncoderStreamLanguage(); + // Request and push streams // 5.4.2.1. Indexed Header Field -const uint8_t kIndexedHeaderFieldOpcode = 0b10000000; +const uint8_t kIndexedHeaderFieldOpcodeValue = 0b10000000; const uint8_t kIndexedHeaderFieldOpcodeMask = 0b10000000; const uint8_t kIndexedHeaderFieldStaticBit = 0b01000000; const uint8_t kIndexedHeaderFieldPrefixLength = 6; +const QpackInstruction* QpackIndexedHeaderFieldInstruction(); + // 5.4.2.2. Indexed Header Field With Post-Base Index -const uint8_t kIndexedHeaderFieldPostBaseOpcode = 0b00010000; +const uint8_t kIndexedHeaderFieldPostBaseOpcodeValue = 0b00010000; const uint8_t kIndexedHeaderFieldPostBaseOpcodeMask = 0b11110000; const uint8_t kIndexedHeaderFieldPostBasePrefixLength = 4; +const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction(); + // 5.4.2.3. Literal Header Field With Name Reference -const uint8_t kLiteralHeaderFieldNameReferenceOpcode = 0b01000000; +const uint8_t kLiteralHeaderFieldNameReferenceOpcodeValue = 0b01000000; const uint8_t kLiteralHeaderFieldNameReferenceOpcodeMask = 0b11000000; const uint8_t kLiteralHeaderFieldNameReferenceStaticBit = 0b00010000; const uint8_t kLiteralHeaderFieldNameReferencePrefixLength = 4; +const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction(); + // 5.4.2.4. Literal Header Field With Post-Base Name Reference -const uint8_t kLiteralHeaderFieldPostBaseOpcode = 0b00000000; +const uint8_t kLiteralHeaderFieldPostBaseOpcodeValue = 0b00000000; const uint8_t kLiteralHeaderFieldPostBaseOpcodeMask = 0b11110000; const uint8_t kLiteralHeaderFieldPostBasePrefixLength = 3; +const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction(); + // 5.4.2.5. Literal Header Field Without Name Reference -const uint8_t kLiteralHeaderFieldOpcode = 0b00100000; +const uint8_t kLiteralHeaderFieldOpcodeValue = 0b00100000; const uint8_t kLiteralHeaderFieldOpcodeMask = 0b11100000; const uint8_t kLiteralNameHuffmanMask = 0b00001000; const uint8_t kLiteralHeaderFieldPrefixLength = 3; -// Value encoding for instructions with literal value. -const uint8_t kLiteralValueHuffmanMask = 0b10000000; -const uint8_t kLiteralValueWithoutHuffmanEncoding = 0b00000000; -const uint8_t kLiteralValuePrefixLength = 7; +const QpackInstruction* QpackLiteralHeaderFieldInstruction(); + +// Description of language (set of instructions) used on request and push +// streams. +const QpackLanguage* QpackRequestStreamLanguage(); } // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_decoder.cc b/net/third_party/quic/core/qpack/qpack_decoder.cc index b862c93..284ac35 100644 --- a/net/third_party/quic/core/qpack/qpack_decoder.cc +++ b/net/third_party/quic/core/qpack/qpack_decoder.cc
@@ -14,16 +14,11 @@ QpackDecoder::ProgressiveDecoder::ProgressiveDecoder( QpackHeaderTable* header_table, QpackDecoder::HeadersHandlerInterface* handler) - : header_table_(header_table), + : instruction_decoder_(QpackRequestStreamLanguage(), this), + header_table_(header_table), handler_(handler), - state_(State::kStart), decoding_(true), - error_detected_(false), - literal_name_(false), - literal_value_(false), - name_length_(0), - value_length_(0), - is_huffman_(false) {} + error_detected_(false) {} void QpackDecoder::ProgressiveDecoder::Decode(QuicStringPiece data) { DCHECK(decoding_); @@ -32,61 +27,7 @@ return; } - while (true) { - size_t bytes_consumed = 0; - - switch (state_) { - case State::kStart: - bytes_consumed = DoStart(data); - break; - case State::kVarintResume: - bytes_consumed = DoVarintResume(data); - break; - case State::kVarintDone: - DoVarintDone(); - break; - case State::kReadName: - bytes_consumed = DoReadName(data); - break; - case State::kDecodeName: - DoDecodeName(); - break; - case State::kValueLengthStart: - bytes_consumed = DoValueLengthStart(data); - break; - case State::kValueLengthResume: - bytes_consumed = DoValueLengthResume(data); - break; - case State::kValueLengthDone: - DoValueLengthDone(); - break; - case State::kReadValue: - bytes_consumed = DoReadValue(data); - break; - case State::kDecodeValue: - DoDecodeValue(); - break; - case State::kDone: - DoDone(); - break; - } - - if (error_detected_) { - return; - } - - DCHECK_LE(bytes_consumed, data.size()); - - data = QuicStringPiece(data.data() + bytes_consumed, - data.size() - bytes_consumed); - - // Stop processing if no more data but next state would require it. - if (data.empty() && (state_ != State::kVarintDone) && - (state_ != State::kDecodeName) && (state_ != State::kValueLengthDone) && - (state_ != State::kDecodeValue) && (state_ != State::kDone)) { - return; - } - } + instruction_decoder_.Decode(data); } void QpackDecoder::ProgressiveDecoder::EndHeaderBlock() { @@ -97,271 +38,73 @@ return; } - if (state_ == State::kStart) { + if (instruction_decoder_.AtInstructionBoundary()) { handler_->OnDecodingCompleted(); } else { OnError("Incomplete header block."); } } -size_t QpackDecoder::ProgressiveDecoder::DoStart(QuicStringPiece data) { - DCHECK(!data.empty()); - - size_t prefix_length = 0; - if ((data[0] & kIndexedHeaderFieldOpcodeMask) == kIndexedHeaderFieldOpcode) { - if ((data[0] & kIndexedHeaderFieldStaticBit) != - kIndexedHeaderFieldStaticBit) { +bool QpackDecoder::ProgressiveDecoder::OnInstructionDecoded( + const QpackInstruction* instruction) { + if (instruction == QpackIndexedHeaderFieldInstruction()) { + if (!instruction_decoder_.is_static()) { // TODO(bnc): Implement. OnError("Indexed Header Field with dynamic entry not implemented."); - return 0; + return false; } - prefix_length = kIndexedHeaderFieldPrefixLength; - literal_name_ = false; - literal_value_ = false; - } else if ((data[0] & kIndexedHeaderFieldPostBaseOpcodeMask) == - kIndexedHeaderFieldPostBaseOpcode) { + + auto entry = header_table_->LookupEntry(instruction_decoder_.varint()); + if (!entry) { + OnError("Invalid static table index."); + return false; + } + + handler_->OnHeaderDecoded(entry->name(), entry->value()); + return true; + } + + if (instruction == QpackIndexedHeaderFieldPostBaseInstruction()) { // TODO(bnc): Implement. OnError("Indexed Header Field With Post-Base Index not implemented."); - return 0; - } else if ((data[0] & kLiteralHeaderFieldNameReferenceOpcodeMask) == - kLiteralHeaderFieldNameReferenceOpcode) { - if ((data[0] & kLiteralHeaderFieldNameReferenceStaticBit) != - kLiteralHeaderFieldNameReferenceStaticBit) { + return false; + } + + if (instruction == QpackLiteralHeaderFieldNameReferenceInstruction()) { + if (!instruction_decoder_.is_static()) { // TODO(bnc): Implement. OnError( "Literal Header Field With Name Reference with dynamic entry not " "implemented."); - return 0; + return false; } - prefix_length = kLiteralHeaderFieldNameReferencePrefixLength; - literal_name_ = false; - literal_value_ = true; - } else if ((data[0] & kLiteralHeaderFieldPostBaseOpcodeMask) == - kLiteralHeaderFieldPostBaseOpcode) { + + auto entry = header_table_->LookupEntry(instruction_decoder_.varint()); + if (!entry) { + OnError( + "Invalid static table index in Literal Header Field With Name " + "Reference instruction."); + return false; + } + + handler_->OnHeaderDecoded(entry->name(), instruction_decoder_.value()); + return true; + } + + if (instruction == QpackLiteralHeaderFieldPostBaseInstruction()) { // TODO(bnc): Implement. OnError( - "Literal Header Field With Post-Base Name Reference not implemented."); - return 0; - } else { - DCHECK_EQ(kLiteralHeaderFieldOpcode, - data[0] & kLiteralHeaderFieldOpcodeMask); - - is_huffman_ = - (data[0] & kLiteralNameHuffmanMask) == kLiteralNameHuffmanMask; - prefix_length = kLiteralHeaderFieldPrefixLength; - literal_name_ = true; - literal_value_ = true; + "Literal Header Field With Post-Base Name Reference not " + "implemented."); + return false; } - http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); - http2::DecodeStatus status = - varint_decoder_.Start(data[0], prefix_length, &buffer); + DCHECK_EQ(instruction, QpackLiteralHeaderFieldInstruction()); - size_t bytes_consumed = 1 + buffer.Offset(); - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kVarintDone; - return bytes_consumed; - case http2::DecodeStatus::kDecodeInProgress: - state_ = State::kVarintResume; - return bytes_consumed; - case http2::DecodeStatus::kDecodeError: - OnError("Encoded integer too large."); - return bytes_consumed; - } -} + handler_->OnHeaderDecoded(instruction_decoder_.name(), + instruction_decoder_.value()); -size_t QpackDecoder::ProgressiveDecoder::DoVarintResume(QuicStringPiece data) { - DCHECK(!data.empty()); - - http2::DecodeBuffer buffer(data); - http2::DecodeStatus status = varint_decoder_.Resume(&buffer); - - size_t bytes_consumed = buffer.Offset(); - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kVarintDone; - return bytes_consumed; - case http2::DecodeStatus::kDecodeInProgress: - DCHECK_EQ(bytes_consumed, data.size()); - DCHECK(buffer.Empty()); - return bytes_consumed; - case http2::DecodeStatus::kDecodeError: - OnError("Encoded integer too large."); - return bytes_consumed; - } -} - -void QpackDecoder::ProgressiveDecoder::DoVarintDone() { - if (literal_name_) { - // TODO(bnc): Impose a sensible limit on length to avoid memory exhaustion - // attacks. - name_length_ = varint_decoder_.value(); - name_.clear(); - name_.reserve(name_length_); - // Do not handle empty names differently. (They are probably forbidden by - // higher layers, but it is not enforced in this class.) If there is no - // more data to read, then processing stalls, but the instruction is not - // complete without the value, so OnHeaderDecoded() could not be called yet - // anyway. - state_ = State::kReadName; - return; - } - - auto entry = header_table_->LookupEntry(varint_decoder_.value()); - if (!entry) { - OnError("Invalid static table index."); - return; - } - - if (literal_value_) { - name_.assign(entry->name().data(), entry->name().size()); - state_ = State::kValueLengthStart; - return; - } - - // Call OnHeaderDecoded() here instead of changing to State::kDone - // to prevent copying two strings. - handler_->OnHeaderDecoded(entry->name(), entry->value()); - state_ = State::kStart; -} - -size_t QpackDecoder::ProgressiveDecoder::DoReadName(QuicStringPiece data) { - DCHECK(!data.empty()); - // |name_length_| might be zero. - DCHECK_LE(name_.size(), name_length_); - - size_t bytes_consumed = std::min(name_length_ - name_.size(), data.size()); - name_.append(data.data(), bytes_consumed); - - DCHECK_LE(name_.size(), name_length_); - if (name_.size() == name_length_) { - state_ = State::kDecodeName; - } - - return bytes_consumed; -} - -void QpackDecoder::ProgressiveDecoder::DoDecodeName() { - DCHECK_EQ(name_.size(), name_length_); - - if (is_huffman_) { - huffman_decoder_.Reset(); - // HpackHuffmanDecoder::Decode() cannot perform in-place decoding. - QuicString decoded_name; - huffman_decoder_.Decode(name_, &decoded_name); - if (!huffman_decoder_.InputProperlyTerminated()) { - OnError("Error in Huffman-encoded name."); - return; - } - name_ = decoded_name; - } - - state_ = State::kValueLengthStart; -} - -size_t QpackDecoder::ProgressiveDecoder::DoValueLengthStart( - QuicStringPiece data) { - DCHECK(!data.empty()); - DCHECK(literal_value_); - - is_huffman_ = - (data[0] & kLiteralValueHuffmanMask) == kLiteralValueHuffmanMask; - - http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); - http2::DecodeStatus status = - varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); - - size_t bytes_consumed = 1 + buffer.Offset(); - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kValueLengthDone; - return bytes_consumed; - case http2::DecodeStatus::kDecodeInProgress: - state_ = State::kValueLengthResume; - return bytes_consumed; - case http2::DecodeStatus::kDecodeError: - OnError("ValueLen too large."); - return bytes_consumed; - } -} - -size_t QpackDecoder::ProgressiveDecoder::DoValueLengthResume( - QuicStringPiece data) { - DCHECK(!data.empty()); - - http2::DecodeBuffer buffer(data); - http2::DecodeStatus status = varint_decoder_.Resume(&buffer); - - size_t bytes_consumed = buffer.Offset(); - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kValueLengthDone; - return bytes_consumed; - case http2::DecodeStatus::kDecodeInProgress: - DCHECK_EQ(bytes_consumed, data.size()); - DCHECK(buffer.Empty()); - return bytes_consumed; - case http2::DecodeStatus::kDecodeError: - OnError("ValueLen too large."); - return bytes_consumed; - } -} - -void QpackDecoder::ProgressiveDecoder::DoValueLengthDone() { - value_.clear(); - // TODO(bnc): Impose a sensible limit on length to avoid memory exhaustion - // attacks. - value_length_ = varint_decoder_.value(); - - // If value is empty, skip DoReadValue() and DoDecodeValue() and jump directly - // to DoDone(). This is so that OnHeaderDecoded() is called even if there is - // no more data. - if (value_length_ == 0) { - state_ = State::kDone; - return; - } - - value_.reserve(value_length_); - state_ = State::kReadValue; -} - -size_t QpackDecoder::ProgressiveDecoder::DoReadValue(QuicStringPiece data) { - DCHECK(!data.empty()); - DCHECK_LT(0u, value_length_); - DCHECK_LT(value_.size(), value_length_); - - size_t bytes_consumed = std::min(value_length_ - value_.size(), data.size()); - value_.append(data.data(), bytes_consumed); - - DCHECK_LE(value_.size(), value_length_); - if (value_.size() == value_length_) { - state_ = State::kDecodeValue; - } - return bytes_consumed; -} - -void QpackDecoder::ProgressiveDecoder::DoDecodeValue() { - DCHECK_EQ(value_.size(), value_length_); - - if (is_huffman_) { - huffman_decoder_.Reset(); - // HpackHuffmanDecoder::Decode() cannot perform in-place decoding. - QuicString decoded_value; - huffman_decoder_.Decode(value_, &decoded_value); - if (!huffman_decoder_.InputProperlyTerminated()) { - OnError("Error in Huffman-encoded value."); - return; - } - value_ = decoded_value; - } - - state_ = State::kDone; -} - -void QpackDecoder::ProgressiveDecoder::DoDone() { - handler_->OnHeaderDecoded(name_, value_); - state_ = State::kStart; + return true; } void QpackDecoder::ProgressiveDecoder::OnError(QuicStringPiece error_message) {
diff --git a/net/third_party/quic/core/qpack/qpack_decoder.h b/net/third_party/quic/core/qpack/qpack_decoder.h index 3d8e0cb5..497d7f9 100644 --- a/net/third_party/quic/core/qpack/qpack_decoder.h +++ b/net/third_party/quic/core/qpack/qpack_decoder.h
@@ -7,9 +7,8 @@ #include <memory> -#include "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" -#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" #include "net/third_party/quic/core/qpack/qpack_header_table.h" +#include "net/third_party/quic/core/qpack/qpack_instruction_decoder.h" #include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" @@ -47,14 +46,15 @@ }; // Class to decode a single header block. - class QUIC_EXPORT_PRIVATE ProgressiveDecoder { + class QUIC_EXPORT_PRIVATE ProgressiveDecoder + : public QpackInstructionDecoder::Delegate { public: ProgressiveDecoder() = delete; ProgressiveDecoder(QpackHeaderTable* header_table, HeadersHandlerInterface* handler); ProgressiveDecoder(const ProgressiveDecoder&) = delete; ProgressiveDecoder& operator=(const ProgressiveDecoder&) = delete; - ~ProgressiveDecoder() = default; + ~ProgressiveDecoder() override = default; // Provide a data fragment to decode. void Decode(QuicStringPiece data); @@ -63,80 +63,20 @@ // through Decode(). No methods must be called afterwards. void EndHeaderBlock(); + // QpackInstructionDecoder::Delegate implementation. + bool OnInstructionDecoded(const QpackInstruction* instruction) override; + void OnError(QuicStringPiece error_message) override; + private: - enum class State { - // Every instruction starts encoding an integer on the first octet: - // either an index or the length of the name string literal. - kStart, - kVarintResume, - kVarintDone, - // This might be followed by the name as a string literal, - // optionally Huffman encoded. - kReadName, - kDecodeName, - // This might be followed by the length of the value. - kValueLengthStart, - kValueLengthResume, - kValueLengthDone, - // This might be followed by the value as a string literal, - // optionally Huffman encoded. - kReadValue, - kDecodeValue, - kDone, - }; - - // One method for each state. Some take input data and return the number of - // octets processed. Some only change internal state. - size_t DoStart(QuicStringPiece data); - size_t DoVarintResume(QuicStringPiece data); - void DoVarintDone(); - size_t DoReadName(QuicStringPiece data); - void DoDecodeName(); - size_t DoValueLengthStart(QuicStringPiece data); - size_t DoValueLengthResume(QuicStringPiece data); - void DoValueLengthDone(); - size_t DoReadValue(QuicStringPiece data); - void DoDecodeValue(); - void DoDone(); - - void OnError(QuicStringPiece error_message); - + QpackInstructionDecoder instruction_decoder_; const QpackHeaderTable* const header_table_; HeadersHandlerInterface* handler_; - State state_; - http2::HpackVarintDecoder varint_decoder_; - http2::HpackHuffmanDecoder huffman_decoder_; // True until EndHeaderBlock() is called. bool decoding_; // True if a decoding error has been detected. bool error_detected_; - - // The following variables are used to carry information between states - // within a single header field. That is, a value assigned while decoding - // one header field shall never be used for decoding subsequent header - // fields. - - // True if the header field name is encoded as a string literal. - bool literal_name_; - - // True if the header field value is encoded as a string literal. - bool literal_value_; - - // Decoded length for header name. - size_t name_length_; - - // Decoded length for header value. - size_t value_length_; - - // Whether the currently parsed string (name or value) is - // Huffman encoded. - bool is_huffman_; - - // Decoded header name and value. - QuicString name_; - QuicString value_; }; // Factory method to create a ProgressiveDecoder for decoding a header block.
diff --git a/net/third_party/quic/core/qpack/qpack_decoder_test.cc b/net/third_party/quic/core/qpack/qpack_decoder_test.cc index 9f43a39..742b92e 100644 --- a/net/third_party/quic/core/qpack/qpack_decoder_test.cc +++ b/net/third_party/quic/core/qpack/qpack_decoder_test.cc
@@ -125,9 +125,18 @@ Decode(QuicTextUtils::HexDecode("27ffffffffffffffffffff")); } -TEST_P(QpackDecoderTest, ValueLenTooLarge) { - EXPECT_CALL(handler_, - OnDecodingErrorDetected(QuicStringPiece("ValueLen too large."))); +// Name Length value can be decoded by varint decoder but exceeds 1 MB limit. +TEST_P(QpackDecoderTest, NameLenExceedsLimit) { + EXPECT_CALL(handler_, OnDecodingErrorDetected( + QuicStringPiece("String literal too long."))); + + Decode(QuicTextUtils::HexDecode("27ffff7f")); +} + +// Value Length value is too large for varint decoder to decode. +TEST_P(QpackDecoderTest, ValueLenTooLargeForVarintDecoder) { + EXPECT_CALL(handler_, OnDecodingErrorDetected( + QuicStringPiece("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("23666f6f7fffffffffffffffffffff")); } @@ -167,8 +176,8 @@ } TEST_P(QpackDecoderTest, HuffmanNameDoesNotHaveEOSPrefix) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("Error in Huffman-encoded name."))); + EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece( + "Error in Huffman-encoded string."))); // 'y' ends in 0b0 on the most significant bit of the last byte. // The remaining 7 bits must be a prefix of EOS, which is all 1s. @@ -177,7 +186,7 @@ TEST_P(QpackDecoderTest, HuffmanValueDoesNotHaveEOSPrefix) { EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece( - "Error in Huffman-encoded value."))); + "Error in Huffman-encoded string."))); // 'e' ends in 0b101, taking up the 3 most significant bits of the last byte. // The remaining 5 bits must be a prefix of EOS, which is all 1s. @@ -185,8 +194,8 @@ } TEST_P(QpackDecoderTest, HuffmanNameEOSPrefixTooLong) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("Error in Huffman-encoded name."))); + EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece( + "Error in Huffman-encoded string."))); // The trailing EOS prefix must be at most 7 bits long. Appending one octet // with value 0xff is invalid, even though 0b111111111111111 (15 bits) is a @@ -197,7 +206,7 @@ TEST_P(QpackDecoderTest, HuffmanValueEOSPrefixTooLong) { EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece( - "Error in Huffman-encoded value."))); + "Error in Huffman-encoded string."))); // The trailing EOS prefix must be at most 7 bits long. Appending one octet // with value 0xff is invalid, even though 0b1111111111111 (13 bits) is a @@ -246,6 +255,7 @@ Decode(QuicTextUtils::HexDecode("ff23ff24")); } + } // namespace } // namespace test } // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_encoder.cc b/net/third_party/quic/core/qpack/qpack_encoder.cc index eee1f9d..6c27319 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder.cc
@@ -103,7 +103,7 @@ DCHECK(HasNext()); DCHECK_NE(0u, max_encoded_bytes); - while (max_encoded_bytes > 0 && HasNext()) { + while (HasNext()) { size_t encoded_bytes = 0; switch (state_) { @@ -132,6 +132,13 @@ DCHECK_LE(encoded_bytes, max_encoded_bytes); max_encoded_bytes -= encoded_bytes; + + // Run VarintDone state (even with no more space to write left, since this + // state does not write) so that |header_list_iterator_| is incremented and + // thus HasNext() returns correct value if encoding has completed. + if (max_encoded_bytes == 0 && state_ != State::kVarintDone) { + return; + } } } @@ -148,7 +155,7 @@ literal_value_ = false; output->push_back(varint_encoder_.StartEncoding( - kIndexedHeaderFieldOpcode | kIndexedHeaderFieldStaticBit, + kIndexedHeaderFieldOpcodeValue | kIndexedHeaderFieldStaticBit, kIndexedHeaderFieldPrefixLength, index)); break; @@ -157,7 +164,7 @@ literal_value_ = true; output->push_back(varint_encoder_.StartEncoding( - kLiteralHeaderFieldNameReferenceOpcode | + kLiteralHeaderFieldNameReferenceOpcodeValue | kLiteralHeaderFieldNameReferenceStaticBit, kLiteralHeaderFieldNameReferencePrefixLength, index)); @@ -172,12 +179,12 @@ if (huffman_encoded_string_.size() < name.size()) { string_to_write_ = huffman_encoded_string_; output->push_back(varint_encoder_.StartEncoding( - kLiteralHeaderFieldOpcode | kLiteralNameHuffmanMask, + kLiteralHeaderFieldOpcodeValue | kLiteralNameHuffmanMask, kLiteralHeaderFieldPrefixLength, string_to_write_.size())); } else { string_to_write_ = name; output->push_back(varint_encoder_.StartEncoding( - kLiteralHeaderFieldOpcode, kLiteralHeaderFieldPrefixLength, + kLiteralHeaderFieldOpcodeValue, kLiteralHeaderFieldPrefixLength, string_to_write_.size())); } break;
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc index 628a2e8..45a3b8d 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc
@@ -11,376 +11,43 @@ namespace quic { QpackEncoderStreamReceiver::QpackEncoderStreamReceiver(Delegate* delegate) - : delegate_(delegate), - state_(State::kStart), - is_huffman_(false), - is_static_(false), - literal_name_(false), - name_index_(0), - name_length_(0), - value_length_(0), + : instruction_decoder_(QpackEncoderStreamLanguage(), this), + delegate_(delegate), error_detected_(false) { DCHECK(delegate_); } void QpackEncoderStreamReceiver::Decode(QuicStringPiece data) { - while (!error_detected_) { - size_t bytes_consumed = 0; - - switch (state_) { - case State::kStart: - bytes_consumed = DoStart(data); - break; - case State::kNameIndexOrLengthResume: - bytes_consumed = DoNameIndexOrLengthResume(data); - break; - case State::kNameIndexOrLengthDone: - DoNameIndexOrLengthDone(); - break; - case State::kReadName: - bytes_consumed = DoReadName(data); - break; - case State::kDecodeName: - DoDecodeName(); - break; - case State::kValueLengthStart: - bytes_consumed = DoValueLengthStart(data); - break; - case State::kValueLengthResume: - bytes_consumed = DoValueLengthResume(data); - break; - case State::kValueLengthDone: - DoValueLengthDone(); - break; - case State::kReadValue: - bytes_consumed = DoReadValue(data); - break; - case State::kDecodeValue: - DoDecodeValue(); - break; - case State::kInsertDone: - DoInsertDone(); - break; - case State::kIndexResume: - bytes_consumed = DoIndexResume(data); - break; - case State::kIndexDone: - DoIndexDone(); - break; - case State::kMaxSizeResume: - bytes_consumed = DoMaxSizeResume(data); - break; - case State::kMaxSizeDone: - DoMaxSizeDone(); - break; - } - - DCHECK_LE(bytes_consumed, data.size()); - - data = QuicStringPiece(data.data() + bytes_consumed, - data.size() - bytes_consumed); - - // Stop processing if no more data but next state would require it. - if (data.empty() && (state_ != State::kNameIndexOrLengthDone) && - (state_ != State::kDecodeName) && (state_ != State::kValueLengthDone) && - (state_ != State::kDecodeValue) && (state_ != State::kInsertDone) && - (state_ != State::kIndexDone) && (state_ != State::kMaxSizeDone)) { - return; - } - } -} - -size_t QpackEncoderStreamReceiver::DoStart(QuicStringPiece data) { - DCHECK(!data.empty()); - - size_t prefix_length; - State state_varint_in_progress; - State state_varint_done; - if ((data[0] & kInsertWithNameReferenceOpcodeMask) == - kInsertWithNameReferenceOpcode) { - is_static_ = (data[0] & kInsertWithNameReferenceStaticBit) == - kInsertWithNameReferenceStaticBit; - - prefix_length = kInsertWithNameReferenceNameIndexPrefixLength; - literal_name_ = false; - state_varint_in_progress = State::kNameIndexOrLengthResume; - state_varint_done = State::kNameIndexOrLengthDone; - } else if ((data[0] & kInsertWithoutNameReferenceOpcodeMask) == - kInsertWithoutNameReferenceOpcode) { - is_huffman_ = (data[0] & kInsertWithoutNameReferenceNameHuffmanBit) == - kInsertWithoutNameReferenceNameHuffmanBit; - prefix_length = kInsertWithoutNameReferenceNameLengthPrefixLength; - literal_name_ = true; - state_varint_in_progress = State::kNameIndexOrLengthResume; - state_varint_done = State::kNameIndexOrLengthDone; - } else if ((data[0] & kDuplicateOpcodeMask) == kDuplicateOpcode) { - prefix_length = kDuplicateIndexPrefixLength; - state_varint_in_progress = State::kIndexResume; - state_varint_done = State::kIndexDone; - } else { - DCHECK_EQ(kDynamicTableSizeUpdateOpcode, - data[0] & kDynamicTableSizeUpdateOpcodeMask); - - prefix_length = kDynamicTableSizeUpdateMaxSizePrefixLength; - state_varint_in_progress = State::kMaxSizeResume; - state_varint_done = State::kMaxSizeDone; - } - - http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); - http2::DecodeStatus status = - varint_decoder_.Start(data[0], prefix_length, &buffer); - - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = state_varint_done; - break; - case http2::DecodeStatus::kDecodeInProgress: - DCHECK(buffer.Empty()); - state_ = state_varint_in_progress; - break; - case http2::DecodeStatus::kDecodeError: - OnError("Encoded integer too large."); - break; - } - return 1 + buffer.Offset(); -} - -size_t QpackEncoderStreamReceiver::DoNameIndexOrLengthResume( - QuicStringPiece data) { - DCHECK(!data.empty()); - - http2::DecodeBuffer buffer(data); - http2::DecodeStatus status = varint_decoder_.Resume(&buffer); - - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kNameIndexOrLengthDone; - break; - case http2::DecodeStatus::kDecodeInProgress: - DCHECK(buffer.Empty()); - break; - case http2::DecodeStatus::kDecodeError: - OnError("Encoded integer too large."); - break; - } - return buffer.Offset(); -} - -void QpackEncoderStreamReceiver::DoNameIndexOrLengthDone() { - DCHECK(name_.empty()); - - if (literal_name_) { - name_length_ = varint_decoder_.value(); - name_.reserve(name_length_); - // Do not handle empty names differently. (They are probably forbidden by - // higher layers, but it is not enforced in this class.) If there is no - // more data to read, then processing stalls, but the instruction is not - // complete without the value, so OnInsertWithoutNameReference() could not - // be called yet anyway. - state_ = State::kReadName; + if (data.empty() || error_detected_) { return; } - name_index_ = varint_decoder_.value(); - state_ = State::kValueLengthStart; + instruction_decoder_.Decode(data); } -size_t QpackEncoderStreamReceiver::DoReadName(QuicStringPiece data) { - DCHECK(!data.empty()); - // |name_length_| might be zero. - DCHECK_LE(name_.size(), name_length_); - - size_t bytes_consumed = std::min(name_length_ - name_.size(), data.size()); - name_.append(data.data(), bytes_consumed); - - DCHECK_LE(name_.size(), name_length_); - if (name_.size() == name_length_) { - state_ = State::kDecodeName; +bool QpackEncoderStreamReceiver::OnInstructionDecoded( + const QpackInstruction* instruction) { + if (instruction == InsertWithNameReferenceInstruction()) { + delegate_->OnInsertWithNameReference(instruction_decoder_.is_static(), + instruction_decoder_.varint(), + instruction_decoder_.value()); + return true; } - return bytes_consumed; -} - -void QpackEncoderStreamReceiver::DoDecodeName() { - DCHECK_EQ(name_.size(), name_length_); - - if (is_huffman_) { - huffman_decoder_.Reset(); - // HpackHuffmanDecoder::Decode() cannot perform in-place decoding. - QuicString decoded_name; - huffman_decoder_.Decode(name_, &decoded_name); - if (!huffman_decoder_.InputProperlyTerminated()) { - OnError("Error in Huffman-encoded name."); - return; - } - name_ = decoded_name; + if (instruction == InsertWithoutNameReferenceInstruction()) { + delegate_->OnInsertWithoutNameReference(instruction_decoder_.name(), + instruction_decoder_.value()); + return true; } - state_ = State::kValueLengthStart; -} - -size_t QpackEncoderStreamReceiver::DoValueLengthStart(QuicStringPiece data) { - DCHECK(!data.empty()); - - is_huffman_ = - (data[0] & kLiteralValueHuffmanMask) == kLiteralValueHuffmanMask; - - http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); - http2::DecodeStatus status = - varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); - - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kValueLengthDone; - break; - case http2::DecodeStatus::kDecodeInProgress: - DCHECK(buffer.Empty()); - state_ = State::kValueLengthResume; - break; - case http2::DecodeStatus::kDecodeError: - OnError("ValueLen too large."); - break; - } - return 1 + buffer.Offset(); -} - -size_t QpackEncoderStreamReceiver::DoValueLengthResume(QuicStringPiece data) { - DCHECK(!data.empty()); - - http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); - http2::DecodeStatus status = - varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); - - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kValueLengthDone; - break; - case http2::DecodeStatus::kDecodeInProgress: - DCHECK(buffer.Empty()); - break; - case http2::DecodeStatus::kDecodeError: - OnError("ValueLen too large."); - break; - } - return 1 + buffer.Offset(); -} - -void QpackEncoderStreamReceiver::DoValueLengthDone() { - DCHECK(value_.empty()); - - value_length_ = varint_decoder_.value(); - - // If value is empty, skip DoReadValue() and DoDecodeValue() and jump directly - // to DoInsertDone(). This is so that OnInsertName*() is called even if there - // is no more data. - if (value_length_ == 0) { - state_ = State::kInsertDone; - return; + if (instruction == DuplicateInstruction()) { + delegate_->OnDuplicate(instruction_decoder_.varint()); + return true; } - value_.reserve(value_length_); - state_ = State::kReadValue; -} - -size_t QpackEncoderStreamReceiver::DoReadValue(QuicStringPiece data) { - DCHECK(!data.empty()); - DCHECK_LT(0u, value_length_); - DCHECK_LT(value_.size(), value_length_); - - size_t bytes_consumed = std::min(value_length_ - value_.size(), data.size()); - value_.append(data.data(), bytes_consumed); - - DCHECK_LE(value_.size(), value_length_); - if (value_.size() == value_length_) { - state_ = State::kDecodeValue; - } - - return bytes_consumed; -} - -void QpackEncoderStreamReceiver::DoDecodeValue() { - DCHECK_EQ(value_.size(), value_length_); - - if (is_huffman_) { - huffman_decoder_.Reset(); - // HpackHuffmanDecoder::Decode() cannot perform in-place decoding. - QuicString decoded_value; - huffman_decoder_.Decode(value_, &decoded_value); - if (!huffman_decoder_.InputProperlyTerminated()) { - OnError("Error in Huffman-encoded value."); - return; - } - value_ = decoded_value; - } - - state_ = State::kInsertDone; -} - -void QpackEncoderStreamReceiver::DoInsertDone() { - if (literal_name_) { - delegate_->OnInsertWithoutNameReference(name_, value_); - name_.clear(); - value_.clear(); - } else { - delegate_->OnInsertWithNameReference(is_static_, name_index_, value_); - value_.clear(); - } - - state_ = State::kStart; -} - -size_t QpackEncoderStreamReceiver::DoIndexResume(QuicStringPiece data) { - DCHECK(!data.empty()); - - http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); - http2::DecodeStatus status = - varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); - - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kIndexDone; - break; - case http2::DecodeStatus::kDecodeInProgress: - DCHECK(buffer.Empty()); - break; - case http2::DecodeStatus::kDecodeError: - OnError("Index too large."); - break; - } - return 1 + buffer.Offset(); -} - -void QpackEncoderStreamReceiver::DoIndexDone() { - delegate_->OnDuplicate(varint_decoder_.value()); - - state_ = State::kStart; -} - -size_t QpackEncoderStreamReceiver::DoMaxSizeResume(QuicStringPiece data) { - DCHECK(!data.empty()); - - http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); - http2::DecodeStatus status = - varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); - - switch (status) { - case http2::DecodeStatus::kDecodeDone: - state_ = State::kMaxSizeDone; - break; - case http2::DecodeStatus::kDecodeInProgress: - DCHECK(buffer.Empty()); - break; - case http2::DecodeStatus::kDecodeError: - OnError("Maximum table size too large."); - break; - } - return 1 + buffer.Offset(); -} - -void QpackEncoderStreamReceiver::DoMaxSizeDone() { - delegate_->OnDynamicTableSizeUpdate(varint_decoder_.value()); - - state_ = State::kStart; + DCHECK_EQ(instruction, DynamicTableSizeUpdateInstruction()); + delegate_->OnDynamicTableSizeUpdate(instruction_decoder_.varint()); + return true; } void QpackEncoderStreamReceiver::OnError(QuicStringPiece error_message) {
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h index 55d47440..90db8c8 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h
@@ -8,8 +8,7 @@ #include <cstddef> #include <cstdint> -#include "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" -#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" +#include "net/third_party/quic/core/qpack/qpack_instruction_decoder.h" #include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" @@ -17,7 +16,8 @@ namespace quic { // This class decodes data received on the encoder stream. -class QUIC_EXPORT_PRIVATE QpackEncoderStreamReceiver { +class QUIC_EXPORT_PRIVATE QpackEncoderStreamReceiver + : public QpackInstructionDecoder::Delegate { public: // An interface for handling instructions decoded from the encoder stream, see // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.2 @@ -51,83 +51,13 @@ // and all further data is ignored. void Decode(QuicStringPiece data); + // QpackInstructionDecoder::Delegate implementation. + bool OnInstructionDecoded(const QpackInstruction* instruction) override; + void OnError(QuicStringPiece error_message) override; + private: - enum class State { - // Identify the instruction and start decoding an integer. - kStart, - // Decode name index or name length. - kNameIndexOrLengthResume, - kNameIndexOrLengthDone, - // Read name string literal, which is optionally Huffman encoded. - kReadName, - // Optionally decode Huffman encoded name. - kDecodeName, - // Read value string length. - kValueLengthStart, - kValueLengthResume, - kValueLengthDone, - // Read value string literal, which is optionally Huffman encoded. - kReadValue, - // Optionally decode Huffman encoded value. - kDecodeValue, - // Done with insertion instruction. - kInsertDone, - // Read index to duplicate. - kIndexResume, - kIndexDone, - // Read maximum table size. - kMaxSizeResume, - kMaxSizeDone, - }; - - // One method for each state. Some take input data and return the number of - // octets processed. Some only change internal state. - size_t DoStart(QuicStringPiece data); - size_t DoNameIndexOrLengthResume(QuicStringPiece data); - void DoNameIndexOrLengthDone(); - size_t DoReadName(QuicStringPiece data); - void DoDecodeName(); - size_t DoValueLengthStart(QuicStringPiece data); - size_t DoValueLengthResume(QuicStringPiece data); - void DoValueLengthDone(); - size_t DoReadValue(QuicStringPiece data); - void DoDecodeValue(); - void DoInsertDone(); - size_t DoIndexResume(QuicStringPiece data); - void DoIndexDone(); - size_t DoMaxSizeResume(QuicStringPiece data); - void DoMaxSizeDone(); - - void OnError(QuicStringPiece error_message); - + QpackInstructionDecoder instruction_decoder_; Delegate* const delegate_; - http2::HpackVarintDecoder varint_decoder_; - http2::HpackHuffmanDecoder huffman_decoder_; - State state_; - - // True if the currently parsed string (name or value) is Huffman encoded. - bool is_huffman_; - - // True if the name index refers to the static table. - bool is_static_; - - // True if the header field value is encoded as a string literal. - bool literal_name_; - - // Decoded name index. - uint64_t name_index_; - - // Decoded length for header name. - size_t name_length_; - - // Decoded header name. - QuicString name_; - - // Decoded length for header value. - size_t value_length_; - - // Decoded header value. - QuicString value_; // True if a decoding error has been detected. bool error_detected_;
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc index 16737f570..df86c82 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
@@ -72,7 +72,8 @@ } TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceValueTooLong) { - EXPECT_CALL(*delegate(), OnErrorDetected(Eq("ValueLen too large."))); + EXPECT_CALL(*delegate(), + OnErrorDetected(QuicStringPiece("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("c57fffffffffffffffffffff")); } @@ -107,8 +108,11 @@ Decode(QuicTextUtils::HexDecode("5fffffffffffffffffffff")); } -TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReferenceValueTooLong) { - EXPECT_CALL(*delegate(), OnErrorDetected(Eq("ValueLen too large."))); +// Name Length value can be decoded by varint decoder but exceeds 1 MB limit. +TEST_F(QpackEncoderStreamReceiverTest, + InsertWithoutNameReferenceNameExceedsLimit) { + EXPECT_CALL(*delegate(), + OnErrorDetected(QuicStringPiece("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("436261727fffffffffffffffffffff")); }
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_test.cc b/net/third_party/quic/core/qpack/qpack_encoder_test.cc index 8cc733c..84c85dc 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder_test.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder_test.cc
@@ -124,6 +124,22 @@ } } +TEST_P(QpackEncoderTest, SimpleIndexed) { + spdy::SpdyHeaderBlock header_list; + header_list[":path"] = "/"; + + QpackEncoder encoder; + auto progressive_encoder = encoder.EncodeHeaderList(&header_list); + EXPECT_TRUE(progressive_encoder->HasNext()); + + // This indexed header field takes exactly one byte. + QuicString output; + progressive_encoder->Next(1, &output); + + EXPECT_EQ(QuicTextUtils::HexDecode("c1"), output); + EXPECT_FALSE(progressive_encoder->HasNext()); +} + } // namespace } // namespace test } // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_instruction_decoder.cc b/net/third_party/quic/core/qpack/qpack_instruction_decoder.cc new file mode 100644 index 0000000..b86a8a6a --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_instruction_decoder.cc
@@ -0,0 +1,287 @@ +// 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 "net/third_party/quic/core/qpack/qpack_instruction_decoder.h" + +#include "base/logging.h" +#include "net/third_party/quic/core/qpack/qpack_constants.h" + +namespace quic { + +QpackInstructionDecoder::QpackInstructionDecoder(const QpackLanguage* language, + Delegate* delegate) + : language_(language), + delegate_(delegate), + is_static_(false), + varint_(0), + is_huffman_encoded_(false), + string_length_(0), + error_detected_(false), + state_(State::kStartInstruction) {} + +void QpackInstructionDecoder::Decode(QuicStringPiece data) { + DCHECK(!data.empty()); + DCHECK(!error_detected_); + + while (true) { + size_t bytes_consumed = 0; + + switch (state_) { + case State::kStartInstruction: + DoStartInstruction(data); + break; + case State::kStartField: + DoStartField(); + break; + case State::kReadBit: + DoReadBit(data); + break; + case State::kVarintStart: + bytes_consumed = DoVarintStart(data); + break; + case State::kVarintResume: + bytes_consumed = DoVarintResume(data); + break; + case State::kVarintDone: + DoVarintDone(); + break; + case State::kReadString: + bytes_consumed = DoReadString(data); + break; + case State::kReadStringDone: + DoReadStringDone(); + break; + } + + if (error_detected_) { + return; + } + + DCHECK_LE(bytes_consumed, data.size()); + + data = QuicStringPiece(data.data() + bytes_consumed, + data.size() - bytes_consumed); + + // Stop processing if no more data but next state would require it. + if (data.empty() && (state_ != State::kStartField) && + (state_ != State::kVarintDone) && (state_ != State::kReadStringDone)) { + return; + } + } +} + +bool QpackInstructionDecoder::AtInstructionBoundary() const { + return state_ == State::kStartInstruction; +} + +void QpackInstructionDecoder::DoStartInstruction(QuicStringPiece data) { + DCHECK(!data.empty()); + + instruction_ = LookupOpcode(data[0]); + field_ = instruction_->fields.begin(); + + state_ = State::kStartField; +} + +void QpackInstructionDecoder::DoStartField() { + if (field_ == instruction_->fields.end()) { + // Completed decoding this instruction. + + if (!delegate_->OnInstructionDecoded(instruction_)) { + error_detected_ = true; + return; + } + + state_ = State::kStartInstruction; + return; + } + + switch (field_->type) { + case QpackInstructionFieldType::kStaticBit: + case QpackInstructionFieldType::kName: + case QpackInstructionFieldType::kValue: + state_ = State::kReadBit; + return; + case QpackInstructionFieldType::kVarint: + state_ = State::kVarintStart; + return; + } +} + +void QpackInstructionDecoder::DoReadBit(QuicStringPiece data) { + DCHECK(!data.empty()); + + switch (field_->type) { + case QpackInstructionFieldType::kStaticBit: { + const uint8_t bitmask = field_->param; + is_static_ = (data[0] & bitmask) == bitmask; + + ++field_; + state_ = State::kStartField; + + return; + } + case QpackInstructionFieldType::kName: + case QpackInstructionFieldType::kValue: { + const uint8_t prefix_length = field_->param; + DCHECK_GE(7, prefix_length); + const uint8_t bitmask = 1 << prefix_length; + is_huffman_encoded_ = (data[0] & bitmask) == bitmask; + + state_ = State::kVarintStart; + + return; + } + default: + DCHECK(false); + } +} + +size_t QpackInstructionDecoder::DoVarintStart(QuicStringPiece data) { + DCHECK(!data.empty()); + DCHECK(field_->type == QpackInstructionFieldType::kVarint || + field_->type == QpackInstructionFieldType::kName || + field_->type == QpackInstructionFieldType::kValue); + + http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); + http2::DecodeStatus status = + varint_decoder_.Start(data[0], field_->param, &buffer); + + size_t bytes_consumed = 1 + buffer.Offset(); + switch (status) { + case http2::DecodeStatus::kDecodeDone: + state_ = State::kVarintDone; + return bytes_consumed; + case http2::DecodeStatus::kDecodeInProgress: + state_ = State::kVarintResume; + return bytes_consumed; + case http2::DecodeStatus::kDecodeError: + OnError("Encoded integer too large."); + return bytes_consumed; + } +} + +size_t QpackInstructionDecoder::DoVarintResume(QuicStringPiece data) { + DCHECK(!data.empty()); + DCHECK(field_->type == QpackInstructionFieldType::kVarint || + field_->type == QpackInstructionFieldType::kName || + field_->type == QpackInstructionFieldType::kValue); + + http2::DecodeBuffer buffer(data); + http2::DecodeStatus status = varint_decoder_.Resume(&buffer); + + size_t bytes_consumed = buffer.Offset(); + switch (status) { + case http2::DecodeStatus::kDecodeDone: + state_ = State::kVarintDone; + return bytes_consumed; + case http2::DecodeStatus::kDecodeInProgress: + DCHECK_EQ(bytes_consumed, data.size()); + DCHECK(buffer.Empty()); + return bytes_consumed; + case http2::DecodeStatus::kDecodeError: + OnError("Encoded integer too large."); + return bytes_consumed; + } +} + +void QpackInstructionDecoder::DoVarintDone() { + DCHECK(field_->type == QpackInstructionFieldType::kVarint || + field_->type == QpackInstructionFieldType::kName || + field_->type == QpackInstructionFieldType::kValue); + + if (field_->type == QpackInstructionFieldType::kVarint) { + varint_ = varint_decoder_.value(); + + ++field_; + state_ = State::kStartField; + return; + } + + string_length_ = varint_decoder_.value(); + if (string_length_ > kStringLiteralLengthLimit) { + OnError("String literal too long."); + return; + } + + QuicString* const string = + (field_->type == QpackInstructionFieldType::kName) ? &name_ : &value_; + string->clear(); + + if (string_length_ == 0) { + ++field_; + state_ = State::kStartField; + return; + } + + string->reserve(string_length_); + + state_ = State::kReadString; +} + +size_t QpackInstructionDecoder::DoReadString(QuicStringPiece data) { + DCHECK(!data.empty()); + DCHECK(field_->type == QpackInstructionFieldType::kName || + field_->type == QpackInstructionFieldType::kValue); + + QuicString* const string = + (field_->type == QpackInstructionFieldType::kName) ? &name_ : &value_; + DCHECK_LT(string->size(), string_length_); + + size_t bytes_consumed = + std::min(string_length_ - string->size(), data.size()); + string->append(data.data(), bytes_consumed); + + DCHECK_LE(string->size(), string_length_); + if (string->size() == string_length_) { + state_ = State::kReadStringDone; + } + return bytes_consumed; +} + +void QpackInstructionDecoder::DoReadStringDone() { + DCHECK(field_->type == QpackInstructionFieldType::kName || + field_->type == QpackInstructionFieldType::kValue); + + QuicString* const string = + (field_->type == QpackInstructionFieldType::kName) ? &name_ : &value_; + DCHECK_EQ(string->size(), string_length_); + + if (is_huffman_encoded_) { + huffman_decoder_.Reset(); + // HpackHuffmanDecoder::Decode() cannot perform in-place decoding. + QuicString decoded_value; + huffman_decoder_.Decode(*string, &decoded_value); + if (!huffman_decoder_.InputProperlyTerminated()) { + OnError("Error in Huffman-encoded string."); + return; + } + *string = std::move(decoded_value); + } + + ++field_; + state_ = State::kStartField; +} + +const QpackInstruction* QpackInstructionDecoder::LookupOpcode( + uint8_t byte) const { + for (const auto* instruction : *language_) { + if ((byte & instruction->opcode.mask) == instruction->opcode.value) { + return instruction; + } + } + // |language_| should be defined such that instruction opcodes cover every + // possible input. + DCHECK(false); + return nullptr; +} + +void QpackInstructionDecoder::OnError(QuicStringPiece error_message) { + DCHECK(!error_detected_); + + error_detected_ = true; + delegate_->OnError(error_message); +} + +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_instruction_decoder.h b/net/third_party/quic/core/qpack/qpack_instruction_decoder.h new file mode 100644 index 0000000..69c4d85e --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_instruction_decoder.h
@@ -0,0 +1,143 @@ +// 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 NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_INSTRUCTION_DECODER_H_ +#define NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_INSTRUCTION_DECODER_H_ + +#include <cstddef> + +#include "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" +#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" +#include "net/third_party/quic/core/qpack/qpack_constants.h" +#include "net/third_party/quic/platform/api/quic_export.h" +#include "net/third_party/quic/platform/api/quic_string.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" + +namespace quic { + +// Generic instruction decoder class. Takes a QpackLanguage that describes a +// language, that is, a set of instruction opcodes together with a list of +// fields that follow each instruction. +class QUIC_EXPORT_PRIVATE QpackInstructionDecoder { + public: + // Delegate is notified each time an instruction is decoded or when an error + // occurs. + class QUIC_EXPORT_PRIVATE Delegate { + public: + virtual ~Delegate() = default; + + // Called when an instruction (including all its fields) is decoded. + // |instruction| points to an entry in |language|. + // Returns true if decoded fields are valid. + // Returns false otherwise, in which case QpackInstructionDecoder stops + // decoding: Delegate methods will not be called, and Decode() must not be + // called. + virtual bool OnInstructionDecoded(const QpackInstruction* instruction) = 0; + + // Called by QpackInstructionDecoder if an error has occurred. + // No more data is processed afterwards. + virtual void OnError(QuicStringPiece error_message) = 0; + }; + + // Both |*language| and |*delegate| must outlive this object. + QpackInstructionDecoder(const QpackLanguage* language, Delegate* delegate); + QpackInstructionDecoder() = delete; + QpackInstructionDecoder(const QpackInstructionDecoder&) = delete; + QpackInstructionDecoder& operator=(const QpackInstructionDecoder&) = delete; + + // Provide a data fragment to decode. Must not be called after an error has + // occurred. Must not be called with empty |data|. + void Decode(QuicStringPiece data); + + // Returns true if no decoding has taken place yet or if the last instruction + // has been entirely parsed. + bool AtInstructionBoundary() const; + + // Accessors for decoded values. Should only be called for fields that are + // part of the most recently decoded instruction, and only after |this| calls + // Delegate::OnInstructionDecoded() but before Decode() is called again. + bool is_static() const { return is_static_; } + size_t varint() const { return varint_; } + const QuicString& name() const { return name_; } + const QuicString& value() const { return value_; } + + private: + enum class State { + // Identify instruction. + kStartInstruction, + // Start decoding next field. + kStartField, + // Read a single bit. + kReadBit, + // Start reading integer. + kVarintStart, + // Resume reading integer. + kVarintResume, + // Done reading integer. + kVarintDone, + // Read string. + kReadString, + // Done reading string. + kReadStringDone + }; + + // One method for each state. Some take input data and return the number of + // octets processed. Some take input data but do have void return type + // because they not consume any bytes. Some do not take any arguments because + // they only change internal state. + void DoStartInstruction(QuicStringPiece data); + void DoStartField(); + void DoReadBit(QuicStringPiece data); + size_t DoVarintStart(QuicStringPiece data); + size_t DoVarintResume(QuicStringPiece data); + void DoVarintDone(); + size_t DoReadString(QuicStringPiece data); + void DoReadStringDone(); + + // Identify instruction based on opcode encoded in |byte|. + // Returns a pointer to an element of |*language_|. + const QpackInstruction* LookupOpcode(uint8_t byte) const; + + // Stops decoding and calls Delegate::OnError(). + void OnError(QuicStringPiece error_message); + + // Describes the language used for decoding. + const QpackLanguage* const language_; + + // The Delegate to notify of decoded instructions and errors. + Delegate* const delegate_; + + // Storage for decoded field values. + bool is_static_; + size_t varint_; + QuicString name_; + QuicString value_; + // Whether the currently decoded header name or value is Huffman encoded. + bool is_huffman_encoded_; + // Length of string being read into |name_| or |value_|. + size_t string_length_; + + // Decoder instance for decoding integers. + http2::HpackVarintDecoder varint_decoder_; + + // Decoder instance for decoding Huffman encoded strings. + http2::HpackHuffmanDecoder huffman_decoder_; + + // True if a decoding error has been detected either by + // QpackInstructionDecoder or by Delegate. + bool error_detected_; + + // Decoding state. + State state_; + + // Instruction currently being decoded. + const QpackInstruction* instruction_; + + // Field currently being decoded. + QpackInstructionFields::const_iterator field_; +}; + +} // namespace quic + +#endif // NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_INSTRUCTION_DECODER_H_
diff --git a/net/third_party/quic/core/qpack/qpack_instruction_decoder_test.cc b/net/third_party/quic/core/qpack/qpack_instruction_decoder_test.cc new file mode 100644 index 0000000..4b2e5b8 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_instruction_decoder_test.cc
@@ -0,0 +1,157 @@ +// 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 "net/third_party/quic/core/qpack/qpack_instruction_decoder.h" + +#include "base/logging.h" +#include "net/third_party/quic/core/qpack/qpack_constants.h" +#include "net/third_party/quic/platform/api/quic_test.h" +#include "net/third_party/quic/platform/api/quic_text_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::Expectation; +using ::testing::Return; +using ::testing::StrictMock; + +namespace quic { +namespace test { +namespace { + +// This instruction has two fields: a static bit and a 6-bit prefix encoded +// index. +const QpackInstruction* TestInstruction1() { + static const QpackInstruction* const instruction = []() { + auto* instruction = + new QpackInstruction{QpackInstructionOpcode{0x00, 0x80}, + {{QpackInstructionFieldType::kStaticBit, 0x40}, + {QpackInstructionFieldType::kVarint, 6}}}; + return instruction; + }(); + return instruction; +} + +// This instruction has two fields: a header name with a 6-bit prefix, and a +// header value with a 7-bit prefix, both preceded by a Huffman bit. +const QpackInstruction* TestInstruction2() { + static const QpackInstruction* const instruction = []() { + auto* instruction = + new QpackInstruction{QpackInstructionOpcode{0x80, 0x80}, + {{QpackInstructionFieldType::kName, 6}, + {QpackInstructionFieldType::kValue, 7}}}; + return instruction; + }(); + return instruction; +} + +const QpackLanguage* TestLanguage() { + static const QpackLanguage* const language = []() { + auto* language = new QpackLanguage{TestInstruction1(), TestInstruction2()}; + return language; + }(); + return language; +} + +class MockDelegate : public QpackInstructionDecoder::Delegate { + public: + MockDelegate() { + ON_CALL(*this, OnInstructionDecoded(_)).WillByDefault(Return(true)); + } + + MockDelegate(const MockDelegate&) = delete; + MockDelegate& operator=(const MockDelegate&) = delete; + ~MockDelegate() override = default; + + MOCK_METHOD1(OnInstructionDecoded, bool(const QpackInstruction* instruction)); + MOCK_METHOD1(OnError, void(QuicStringPiece error_message)); +}; + +class QpackInstructionDecoderTest : public QuicTest { + public: + QpackInstructionDecoderTest() : decoder_(TestLanguage(), &delegate_) {} + + protected: + // Decode one full instruction byte by byte. Verifies that + // AtInstructionBoundary() returns true before and after the instruction, and + // returns false in while decoding is in progress. + void DecodeInstruction(QuicStringPiece data) { + for (QuicStringPiece::size_type i = 0; i < data.size(); ++i) { + if (i == 0) { + EXPECT_TRUE(decoder_.AtInstructionBoundary()); + } else { + EXPECT_FALSE(decoder_.AtInstructionBoundary()); + } + decoder_.Decode(data.substr(i, 1)); + } + EXPECT_TRUE(decoder_.AtInstructionBoundary()); + } + + StrictMock<MockDelegate> delegate_; + QpackInstructionDecoder decoder_; +}; + +TEST_F(QpackInstructionDecoderTest, StaticBitAndIndex) { + EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1())); + DecodeInstruction(QuicTextUtils::HexDecode("7f01")); + + EXPECT_TRUE(decoder_.is_static()); + EXPECT_EQ(64u, decoder_.varint()); + + EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1())); + DecodeInstruction(QuicTextUtils::HexDecode("05")); + + EXPECT_FALSE(decoder_.is_static()); + EXPECT_EQ(5u, decoder_.varint()); +} + +TEST_F(QpackInstructionDecoderTest, NameAndValue) { + EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2())); + DecodeInstruction(QuicTextUtils::HexDecode("83666f6f03626172")); + + EXPECT_EQ("foo", decoder_.name()); + EXPECT_EQ("bar", decoder_.value()); + + EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2())); + DecodeInstruction(QuicTextUtils::HexDecode("8000")); + + EXPECT_EQ("", decoder_.name()); + EXPECT_EQ("", decoder_.value()); + + EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2())); + DecodeInstruction(QuicTextUtils::HexDecode("c294e7838c767f")); + + EXPECT_EQ("foo", decoder_.name()); + EXPECT_EQ("bar", decoder_.value()); +} + +TEST_F(QpackInstructionDecoderTest, InvalidHuffmanEncoding) { + EXPECT_CALL(delegate_, + OnError(QuicStringPiece("Error in Huffman-encoded string."))); + decoder_.Decode(QuicTextUtils::HexDecode("c1ff")); +} + +TEST_F(QpackInstructionDecoderTest, InvalidVarintEncoding) { + EXPECT_CALL(delegate_, + OnError(QuicStringPiece("Encoded integer too large."))); + decoder_.Decode(QuicTextUtils::HexDecode("ffffffffffffffffffffff")); +} + +TEST_F(QpackInstructionDecoderTest, DelegateSignalsError) { + // First instruction is valid. + Expectation first_call = + EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1())) + .WillOnce(Return(true)); + // Second instruction is invalid. Decoding must halt. + EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1())) + .After(first_call) + .WillOnce(Return(false)); + decoder_.Decode(QuicTextUtils::HexDecode("0102030405")); + + EXPECT_EQ(2u, decoder_.varint()); +} + +} // namespace +} // namespace test +} // namespace quic
diff --git a/net/third_party/quic/core/quic_buffered_packet_store.cc b/net/third_party/quic/core/quic_buffered_packet_store.cc index 78fffcbf..04b5eec 100644 --- a/net/third_party/quic/core/quic_buffered_packet_store.cc +++ b/net/third_party/quic/core/quic_buffered_packet_store.cc
@@ -106,6 +106,7 @@ undecryptable_packets_.emplace( std::make_pair(connection_id, BufferedPacketList())); undecryptable_packets_.back().second.ietf_quic = ietf_quic; + undecryptable_packets_.back().second.version = version; } CHECK(QuicContainsKey(undecryptable_packets_, connection_id)); BufferedPacketList& queue =
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc index 39968dc..5869ee7 100644 --- a/net/third_party/quic/core/quic_connection.cc +++ b/net/third_party/quic/core/quic_connection.cc
@@ -346,8 +346,6 @@ supports_release_time_(writer->SupportsReleaseTime()), release_time_into_future_(QuicTime::Delta::Zero()), donot_retransmit_old_window_updates_(false), - deprecate_post_process_after_data_( - GetQuicReloadableFlag(quic_deprecate_post_process_after_data)), no_version_negotiation_(supported_versions.size() == 1), decrypt_packets_on_key_change_( GetQuicReloadableFlag(quic_decrypt_packets_on_key_change)) { @@ -901,9 +899,6 @@ return false; } visitor_->OnStreamFrame(frame); - if (!deprecate_post_process_after_data_) { - visitor_->PostProcessAfterData(); - } stats_.stream_bytes_received += frame.data_length; should_last_packet_instigate_acks_ = true; return connected_; @@ -1153,9 +1148,6 @@ << " with error: " << QuicRstStreamErrorCodeToString(frame.error_code); visitor_->OnRstStream(frame); - if (!deprecate_post_process_after_data_) { - visitor_->PostProcessAfterData(); - } should_last_packet_instigate_acks_ = true; return connected_; } @@ -1249,9 +1241,6 @@ << " and reason: " << frame.reason_phrase; visitor_->OnGoAway(frame); - if (!deprecate_post_process_after_data_) { - visitor_->PostProcessAfterData(); - } should_last_packet_instigate_acks_ = true; return connected_; } @@ -1270,9 +1259,6 @@ << frame.stream_id << " with byte offset: " << frame.byte_offset; visitor_->OnWindowUpdateFrame(frame); - if (!deprecate_post_process_after_data_) { - visitor_->PostProcessAfterData(); - } should_last_packet_instigate_acks_ = true; return connected_; } @@ -1319,9 +1305,6 @@ QUIC_DLOG(INFO) << ENDPOINT << "BLOCKED_FRAME received for stream: " << frame.stream_id; visitor_->OnBlockedFrame(frame); - if (!deprecate_post_process_after_data_) { - visitor_->PostProcessAfterData(); - } stats_.blocked_frames_received++; should_last_packet_instigate_acks_ = true; return connected_; @@ -1826,9 +1809,6 @@ { ScopedPacketFlusher flusher(this, SEND_ACK_IF_QUEUED); visitor_->OnCanWrite(); - if (!deprecate_post_process_after_data_) { - visitor_->PostProcessAfterData(); - } } // After the visitor writes, it may have caused the socket to become write @@ -2866,9 +2846,7 @@ } void QuicConnection::SetPathDegradingAlarm() { - if (GetQuicReloadableFlag(quic_fix_path_degrading_alarm) && - perspective_ == Perspective::IS_SERVER) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_fix_path_degrading_alarm, 1, 2); + if (perspective_ == Perspective::IS_SERVER) { return; } const QuicTime::Delta delay = sent_packet_manager_.GetPathDegradingDelay(); @@ -3399,13 +3377,7 @@ } void QuicConnection::MaybeSetPathDegradingAlarm(bool acked_new_packet) { - bool has_unacked_packets = !sent_packet_manager_.unacked_packets().empty(); - if (GetQuicReloadableFlag(quic_fix_path_degrading_alarm)) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_fix_path_degrading_alarm, 2, 2); - // If there in flight packets, an ACK is expected in the future. - has_unacked_packets = sent_packet_manager_.HasInFlightPackets(); - } - if (!has_unacked_packets) { + if (!sent_packet_manager_.HasInFlightPackets()) { // There are no retransmittable packets on the wire, so it's impossible to // say if the connection has degraded. path_degrading_alarm_->Cancel();
diff --git a/net/third_party/quic/core/quic_connection.h b/net/third_party/quic/core/quic_connection.h index 2ee6d7f..1f8fd84 100644 --- a/net/third_party/quic/core/quic_connection.h +++ b/net/third_party/quic/core/quic_connection.h
@@ -150,11 +150,6 @@ // Called when the peer seems unreachable over the current path. virtual void OnPathDegrading() = 0; - // Called after OnStreamFrame, OnRstStream, OnGoAway, OnWindowUpdateFrame, - // OnBlockedFrame, and OnCanWrite to allow post-processing once the work has - // been done. - virtual void PostProcessAfterData() = 0; - // Called when the connection sends ack after // max_consecutive_num_packets_with_no_retransmittable_frames_ consecutive not // retransmittable packets sent. To instigate an ack from peer, a @@ -816,10 +811,6 @@ donot_retransmit_old_window_updates_ = value; } - bool deprecate_post_process_after_data() const { - return deprecate_post_process_after_data_; - } - // Attempts to process any queued undecryptable packets. void MaybeProcessUndecryptablePackets(); @@ -1364,9 +1355,6 @@ // quic_reloadable_flag_quic_donot_retransmit_old_window_update. bool donot_retransmit_old_window_updates_; - // Latched value of quic_reloadable_flag_quic_move_post_process_after_data. - const bool deprecate_post_process_after_data_; - // Indicates whether server connection does version negotiation. Server // connection does not support version negotiation if a single version is // provided in constructor.
diff --git a/net/third_party/quic/core/quic_connection_test.cc b/net/third_party/quic/core/quic_connection_test.cc index be4bbe8e..88aaf32 100644 --- a/net/third_party/quic/core/quic_connection_test.cc +++ b/net/third_party/quic/core/quic_connection_test.cc
@@ -51,6 +51,7 @@ using testing::DoAll; using testing::Exactly; using testing::Ge; +using testing::IgnoreResult; using testing::InSequence; using testing::Invoke; using testing::InvokeWithoutArgs; @@ -867,7 +868,6 @@ } else { EXPECT_CALL(visitor_, OnCanWrite()).Times(AnyNumber()); } - EXPECT_CALL(visitor_, PostProcessAfterData()).Times(AnyNumber()); EXPECT_CALL(visitor_, HasOpenDynamicStreams()) .WillRepeatedly(Return(false)); EXPECT_CALL(visitor_, OnCongestionWindowChange(_)).Times(AnyNumber()); @@ -6890,7 +6890,6 @@ } TEST_P(QuicConnectionTest, NoPathDegradingOnServer) { - SetQuicReloadableFlag(quic_fix_path_degrading_alarm, true); set_perspective(Perspective::IS_SERVER); QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false); @@ -6914,8 +6913,6 @@ } TEST_P(QuicConnectionTest, NoPathDegradingAfterSendingAck) { - SetQuicReloadableFlag(quic_fix_path_degrading_alarm, true); - SendAckPacketToPeer(); EXPECT_FALSE(connection_.sent_packet_manager().unacked_packets().empty()); EXPECT_FALSE(connection_.sent_packet_manager().HasInFlightPackets());
diff --git a/net/third_party/quic/core/quic_constants.h b/net/third_party/quic/core/quic_constants.h index a91c72b..1012ac2 100644 --- a/net/third_party/quic/core/quic_constants.h +++ b/net/third_party/quic/core/quic_constants.h
@@ -45,6 +45,9 @@ // Used in QUIC for congestion window computations in bytes. const QuicByteCount kDefaultTCPMSS = 1460; const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; +// The minimum size of a packet which can elicit a version negotiation packet, +// as per section 8.1 of the QUIC spec. +const QuicByteCount kMinPacketSizeForVersionNegotiation = 1200; // We match SPDY's use of 32 (since we'd compete with SPDY). const QuicPacketCount kInitialCongestionWindow = 32; @@ -200,6 +203,7 @@ const uint64_t kMaxIetfVarInt = UINT64_C(0x3fffffffffffffff); // The maximum stream id value that is supported - (2^32)-1 +// TODO(fkastenholz): Should update this to 64 bits for IETF Quic. const QuicStreamId kMaxQuicStreamId = 0xffffffff; // Number of bytes reserved for packet header type. @@ -224,10 +228,6 @@ QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd; QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd0; -// Maximum Stream ID value that the implementation supports -// TODO(fkastenholz): Should update this to 64 bits for IETF Quic. -const QuicStreamId kMaximumStreamIdSupported = 0xffffffff; - } // namespace quic #endif // NET_THIRD_PARTY_QUIC_CORE_QUIC_CONSTANTS_H_
diff --git a/net/third_party/quic/core/quic_crypto_client_handshaker.h b/net/third_party/quic/core/quic_crypto_client_handshaker.h index bfb789b..26c68a47 100644 --- a/net/third_party/quic/core/quic_crypto_client_handshaker.h +++ b/net/third_party/quic/core/quic_crypto_client_handshaker.h
@@ -51,6 +51,13 @@ // From QuicCryptoHandshaker void OnHandshakeMessage(const CryptoHandshakeMessage& message) override; + protected: + // Returns the QuicSession that this stream belongs to. + QuicSession* session() const { return session_; } + + // Send either InchoateClientHello or ClientHello message to the server. + void DoSendCHLO(QuicCryptoClientConfig::CachedState* cached); + private: // ChannelIDSourceCallbackImpl is passed as the callback method to // GetChannelIDKey. The ChannelIDSource calls this class with the result of @@ -118,9 +125,6 @@ // Start the handshake process. void DoInitialize(QuicCryptoClientConfig::CachedState* cached); - // Send either InchoateClientHello or ClientHello message to the server. - void DoSendCHLO(QuicCryptoClientConfig::CachedState* cached); - // Process REJ message from the server. void DoReceiveREJ(const CryptoHandshakeMessage* in, QuicCryptoClientConfig::CachedState* cached); @@ -159,9 +163,6 @@ // and the client config settings also allow sending a ChannelID. bool RequiresChannelID(QuicCryptoClientConfig::CachedState* cached); - // Returns the QuicSession that this stream belongs to. - QuicSession* session() const { return session_; } - QuicCryptoClientStream* stream_; QuicSession* session_;
diff --git a/net/third_party/quic/core/quic_crypto_client_stream.h b/net/third_party/quic/core/quic_crypto_client_stream.h index b04047de8..215b6c2b 100644 --- a/net/third_party/quic/core/quic_crypto_client_stream.h +++ b/net/third_party/quic/core/quic_crypto_client_stream.h
@@ -16,6 +16,7 @@ #include "net/third_party/quic/core/quic_crypto_handshaker.h" #include "net/third_party/quic/core/quic_crypto_stream.h" #include "net/third_party/quic/core/quic_server_id.h" +#include "net/third_party/quic/core/quic_session.h" #include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_string.h" @@ -162,6 +163,11 @@ QuicString chlo_hash() const; + protected: + void set_handshaker(std::unique_ptr<HandshakerDelegate> handshaker) { + handshaker_ = std::move(handshaker); + } + private: std::unique_ptr<HandshakerDelegate> handshaker_; };
diff --git a/net/third_party/quic/core/quic_crypto_server_handshaker.h b/net/third_party/quic/core/quic_crypto_server_handshaker.h index 17a3be6d..92f0bd6 100644 --- a/net/third_party/quic/core/quic_crypto_server_handshaker.h +++ b/net/third_party/quic/core/quic_crypto_server_handshaker.h
@@ -76,6 +76,17 @@ // Returns client address used to generate and validate source address token. virtual const QuicSocketAddress GetClientAddress(); + // Returns the QuicSession that this stream belongs to. + QuicSession* session() const { return session_; } + + void set_encryption_established(bool encryption_established) { + encryption_established_ = encryption_established; + } + + void set_handshake_confirmed(bool handshake_confirmed) { + handshake_confirmed_ = handshake_confirmed; + } + private: friend class test::QuicCryptoServerStreamPeer; @@ -145,9 +156,6 @@ // if |use_stateless_rejects| is true. Returns 0 otherwise. QuicConnectionId GenerateConnectionIdForReject(bool use_stateless_rejects); - // Returns the QuicSession that this stream belongs to. - QuicSession* session() const { return session_; } - // Returns the QuicTransportVersion of the connection. QuicTransportVersion transport_version() const { return session_->connection()->transport_version();
diff --git a/net/third_party/quic/core/quic_dispatcher.cc b/net/third_party/quic/core/quic_dispatcher.cc index ef32d29..84a4c91 100644 --- a/net/third_party/quic/core/quic_dispatcher.cc +++ b/net/third_party/quic/core/quic_dispatcher.cc
@@ -11,6 +11,7 @@ #include "net/third_party/quic/core/crypto/crypto_protocol.h" #include "net/third_party/quic/core/crypto/quic_random.h" #include "net/third_party/quic/core/quic_time_wait_list_manager.h" +#include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/core/stateless_rejector.h" #include "net/third_party/quic/platform/api/quic_bug_tracker.h" @@ -346,7 +347,8 @@ } if (buffered_packets_.HasChloForConnection(connection_id)) { - BufferEarlyPacket(connection_id, header.form != GOOGLE_QUIC_PACKET); + BufferEarlyPacket(connection_id, header.form != GOOGLE_QUIC_PACKET, + header.version); return false; } @@ -355,7 +357,8 @@ temporarily_buffered_connections_.end()) { // This packet was received while the a CHLO for the same connection ID was // being processed. Buffer it. - BufferEarlyPacket(connection_id, header.form != GOOGLE_QUIC_PACKET); + BufferEarlyPacket(connection_id, header.form != GOOGLE_QUIC_PACKET, + header.version); return false; } @@ -392,11 +395,17 @@ if (ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) { return true; } - // Since the version is not supported, send a version negotiation - // packet and stop processing the current packet. - time_wait_list_manager()->SendVersionNegotiationPacket( - connection_id, header.form != GOOGLE_QUIC_PACKET, - GetSupportedVersions(), current_self_address_, current_peer_address_); + if (!GetQuicReloadableFlag(quic_limit_version_negotiation) || + current_packet_->length() >= kMinPacketSizeForVersionNegotiation) { + // Since the version is not supported, send a version negotiation + // packet and stop processing the current packet. + time_wait_list_manager()->SendVersionNegotiationPacket( + connection_id, header.form != GOOGLE_QUIC_PACKET, + GetSupportedVersions(), current_self_address_, + current_peer_address_); + } else { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_limit_version_negotiation); + } return false; } version = packet_version; @@ -413,11 +422,12 @@ if (fate == kFateProcess) { // Execute stateless rejection logic to determine the packet fate, then // invoke ProcessUnauthenticatedHeaderFate. - MaybeRejectStatelessly(connection_id, header.version, header.form); + MaybeRejectStatelessly(connection_id, header.form, header.version); } else { // If the fate is already known, process it without executing stateless // rejection logic. - ProcessUnauthenticatedHeaderFate(fate, connection_id, header.form); + ProcessUnauthenticatedHeaderFate(fate, connection_id, header.form, + header.version); } return false; @@ -426,10 +436,11 @@ void QuicDispatcher::ProcessUnauthenticatedHeaderFate( QuicPacketFate fate, QuicConnectionId connection_id, - PacketHeaderFormat form) { + PacketHeaderFormat form, + ParsedQuicVersion version) { switch (fate) { case kFateProcess: { - ProcessChlo(form); + ProcessChlo(form, version); break; } case kFateTimeWait: @@ -441,8 +452,10 @@ // future packets. QUIC_DLOG(INFO) << "Adding connection ID " << connection_id << "to time-wait list."; + QUIC_CODE_COUNT(quic_reject_fate_time_wait); StatelesslyTerminateConnection( - connection_id, form, QUIC_HANDSHAKE_FAILED, "Reject connection", + connection_id, form, version, QUIC_HANDSHAKE_FAILED, + "Reject connection", quic::QuicTimeWaitListManager::SEND_STATELESS_RESET); } DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); @@ -459,7 +472,7 @@ // This packet is a non-CHLO packet which has arrived before the // corresponding CHLO, *or* this packet was received while the // corresponding CHLO was being processed. Buffer it. - BufferEarlyPacket(connection_id, form != GOOGLE_QUIC_PACKET); + BufferEarlyPacket(connection_id, form != GOOGLE_QUIC_PACKET, version); break; case kFateDrop: // Do nothing with the packet. @@ -642,9 +655,63 @@ void QuicDispatcher::StatelesslyTerminateConnection( QuicConnectionId connection_id, PacketHeaderFormat format, + ParsedQuicVersion version, QuicErrorCode error_code, const QuicString& error_details, QuicTimeWaitListManager::TimeWaitAction action) { + if (GetQuicReloadableFlag(quic_fix_reject_by_session_type)) { + if (format != IETF_QUIC_LONG_HEADER_PACKET) { + QUIC_DVLOG(1) << "Statelessly terminating " << connection_id + << " based on a non-ietf-long packet, action:" << action + << ", error_code:" << error_code + << ", error_details:" << error_details; + time_wait_list_manager_->AddConnectionIdToTimeWait( + connection_id, format != GOOGLE_QUIC_PACKET, action, + /*termination_packets=*/nullptr); + return; + } + + // If the version is known and supported by framer, send a connection close. + if (framer_.IsSupportedVersion(version)) { + QUIC_DVLOG(1) + << "Statelessly terminating " << connection_id + << " based on an ietf-long packet, which has a supported version:" + << version << ", error_code:" << error_code + << ", error_details:" << error_details; + // Set framer_ to the packet's version such that the connection close can + // be processed by the client. + ParsedQuicVersion original_version = framer_.version(); + framer_.set_version(version); + + StatelessConnectionTerminator terminator(connection_id, &framer_, + helper_.get(), + time_wait_list_manager_.get()); + // This also adds the connection to time wait list. + terminator.CloseConnection(error_code, error_details, true); + + // Restore framer_ to the original version, as if nothing changed in it. + framer_.set_version(original_version); + return; + } + + QUIC_DVLOG(1) + << "Statelessly terminating " << connection_id + << " based on an ietf-long packet, which has an unsupported version:" + << version << ", error_code:" << error_code + << ", error_details:" << error_details; + // Version is unknown or unsupported by framer, send a version negotiation + // with an empty version list, which can be understood by the client. + std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets; + termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket( + connection_id, /*ietf_quic=*/true, + ParsedQuicVersionVector{UnsupportedQuicVersion()})); + time_wait_list_manager()->AddConnectionIdToTimeWait( + connection_id, /*ietf_quic=*/true, + QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, + &termination_packets); + return; + } + if (format == IETF_QUIC_LONG_HEADER_PACKET) { // Send connection close for IETF long header packet, and this also adds // connection to time wait list. @@ -852,11 +919,13 @@ void QuicDispatcher::OnExpiredPackets( QuicConnectionId connection_id, BufferedPacketList early_arrived_packets) { + QUIC_CODE_COUNT(quic_reject_buffered_packets_expired); StatelesslyTerminateConnection( connection_id, early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET : GOOGLE_QUIC_PACKET, - QUIC_HANDSHAKE_FAILED, "Packets buffered for too long", + early_arrived_packets.version, QUIC_HANDSHAKE_FAILED, + "Packets buffered for too long", quic::QuicTimeWaitListManager::SEND_STATELESS_RESET); } @@ -917,27 +986,33 @@ } void QuicDispatcher::BufferEarlyPacket(QuicConnectionId connection_id, - bool ietf_quic) { + bool ietf_quic, + ParsedQuicVersion version) { bool is_new_connection = !buffered_packets_.HasBufferedPackets(connection_id); if (is_new_connection && !ShouldCreateOrBufferPacketForConnection(connection_id, ietf_quic)) { return; } - ParsedQuicVersion version(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); + EnqueuePacketResult rs = buffered_packets_.EnqueuePacket( connection_id, ietf_quic, *current_packet_, current_self_address_, current_peer_address_, /*is_chlo=*/false, - /*alpn=*/"", version); + /*alpn=*/"", + GetQuicReloadableFlag(quic_fix_reject_by_session_type) + ? version + : UnsupportedQuicVersion()); if (rs != EnqueuePacketResult::SUCCESS) { OnBufferPacketFailure(rs, connection_id); } } -void QuicDispatcher::ProcessChlo(quic::PacketHeaderFormat form) { +void QuicDispatcher::ProcessChlo(PacketHeaderFormat form, + ParsedQuicVersion version) { if (!accept_new_connections_) { // Don't any create new connection. + QUIC_CODE_COUNT(quic_reject_stop_accepting_new_connections); StatelesslyTerminateConnection( - current_connection_id(), form, QUIC_HANDSHAKE_FAILED, + current_connection_id(), form, version, QUIC_HANDSHAKE_FAILED, "Stop accepting new connections", quic::QuicTimeWaitListManager::SEND_STATELESS_RESET); // Time wait list will reject the packet correspondingly. @@ -1040,10 +1115,12 @@ }; void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id, - ParsedQuicVersion version, - PacketHeaderFormat form) { + + PacketHeaderFormat form, + ParsedQuicVersion version) { if (version.handshake_protocol == PROTOCOL_TLS1_3) { - ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, form); + ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, form, + version); return; // TODO(nharper): Support buffering non-ClientHello packets when using TLS. } @@ -1059,11 +1136,13 @@ config_.create_session_tag_indicators(), &alpn_extractor)) { // Buffer non-CHLO packets. - ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form); + ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form, + version); return; } current_alpn_ = alpn_extractor.ConsumeAlpn(); - ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, form); + ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, form, + version); return; } @@ -1078,19 +1157,21 @@ if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), config_.create_session_tag_indicators(), &validator)) { - ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form); + ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form, version); return; } current_alpn_ = validator.ConsumeAlpn(); if (!validator.can_accept()) { // This CHLO is prohibited by policy. + QUIC_CODE_COUNT(quic_reject_cant_accept_chlo); StatelessConnectionTerminator terminator(connection_id, &framer_, helper(), time_wait_list_manager_.get()); terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, validator.error_details(), form != GOOGLE_QUIC_PACKET); OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED); - ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, form); + ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, form, + version); return; } @@ -1167,6 +1248,7 @@ switch (rejector->state()) { case StatelessRejector::FAILED: { // There was an error processing the client hello. + QUIC_CODE_COUNT(quic_reject_error_processing_chlo); StatelessConnectionTerminator terminator(rejector->connection_id(), &framer_, helper(), time_wait_list_manager_.get()); @@ -1207,7 +1289,8 @@ fate = kFateDrop; break; } - ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id(), form); + ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id(), form, + rejector->version()); } const QuicTransportVersionVector&
diff --git a/net/third_party/quic/core/quic_dispatcher.h b/net/third_party/quic/core/quic_dispatcher.h index 1acb05e..c8bf492 100644 --- a/net/third_party/quic/core/quic_dispatcher.h +++ b/net/third_party/quic/core/quic_dispatcher.h
@@ -226,11 +226,13 @@ // Called when |connection_id| doesn't have an open connection yet, to buffer // |current_packet_| until it can be delivered to the connection. - void BufferEarlyPacket(QuicConnectionId connection_id, bool ietf_quic); + void BufferEarlyPacket(QuicConnectionId connection_id, + bool ietf_quic, + ParsedQuicVersion version); // Called when |current_packet_| is a CHLO packet. Creates a new connection // and delivers any buffered packets for that connection id. - void ProcessChlo(PacketHeaderFormat form); + void ProcessChlo(PacketHeaderFormat form, ParsedQuicVersion version); // Returns the actual client address of the current packet. // This function should only be called once per packet at the very beginning @@ -332,6 +334,7 @@ void StatelesslyTerminateConnection( QuicConnectionId connection_id, PacketHeaderFormat format, + ParsedQuicVersion version, QuicErrorCode error_code, const QuicString& error_details, QuicTimeWaitListManager::TimeWaitAction action); @@ -360,8 +363,8 @@ // fate which describes what subsequent processing should be performed on the // packets, like ValidityChecks, and invokes ProcessUnauthenticatedHeaderFate. void MaybeRejectStatelessly(QuicConnectionId connection_id, - ParsedQuicVersion version, - PacketHeaderFormat form); + PacketHeaderFormat form, + ParsedQuicVersion version); // Deliver |packets| to |session| for further processing. void DeliverPacketsToSession( @@ -372,7 +375,8 @@ // either process, buffer, or drop it. void ProcessUnauthenticatedHeaderFate(QuicPacketFate fate, QuicConnectionId connection_id, - PacketHeaderFormat form); + PacketHeaderFormat form, + ParsedQuicVersion version); // Invoked when StatelessRejector::Process completes. |first_version| is the // version of the packet which initiated the stateless reject.
diff --git a/net/third_party/quic/core/quic_dispatcher_test.cc b/net/third_party/quic/core/quic_dispatcher_test.cc index cb969816..be07953 100644 --- a/net/third_party/quic/core/quic_dispatcher_test.cc +++ b/net/third_party/quic/core/quic_dispatcher_test.cc
@@ -462,12 +462,15 @@ } TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) { + CreateTimeWaitListManager(); + SetQuicReloadableFlag(quic_limit_version_negotiation, false); QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - EXPECT_CALL(*dispatcher_, - CreateQuicSession(1, client_address, QuicStringPiece("hq"), _)) - .Times(0); + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0); + EXPECT_CALL(*time_wait_list_manager_, + SendVersionNegotiationPacket(_, _, _, _, _)) + .Times(1); QuicTransportVersion version = static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1); ParsedQuicVersion parsed_version(PROTOCOL_QUIC_CRYPTO, version); @@ -475,6 +478,27 @@ PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, 1); } +TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) { + CreateTimeWaitListManager(); + SetQuicReloadableFlag(quic_limit_version_negotiation, true); + QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); + server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); + + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0); + EXPECT_CALL(*time_wait_list_manager_, + SendVersionNegotiationPacket(_, _, _, _, _)) + .Times(0); + QuicTransportVersion version = + static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1); + ParsedQuicVersion parsed_version(PROTOCOL_QUIC_CRYPTO, version); + QuicString chlo = SerializeCHLO(); + // Truncate to 1100 bytes of payload which results in a packet just + // under 1200 bytes after framing, packet, and encryption overhead. + QuicString truncated_chlo = chlo.substr(0, 1100); + ProcessPacket(client_address, 1, true, parsed_version, truncated_chlo, + PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, 1); +} + TEST_F(QuicDispatcherTest, Shutdown) { QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
diff --git a/net/third_party/quic/core/quic_flow_controller.h b/net/third_party/quic/core/quic_flow_controller.h index fc5deab..0dfd253 100644 --- a/net/third_party/quic/core/quic_flow_controller.h +++ b/net/third_party/quic/core/quic_flow_controller.h
@@ -49,6 +49,7 @@ bool should_auto_tune_receive_window, QuicFlowControllerInterface* session_flow_controller); QuicFlowController(const QuicFlowController&) = delete; + QuicFlowController(QuicFlowController&&) = default; QuicFlowController& operator=(const QuicFlowController&) = delete; ~QuicFlowController() override {}
diff --git a/net/third_party/quic/core/quic_flow_controller_test.cc b/net/third_party/quic/core/quic_flow_controller_test.cc index b59fac99..c00fc5da 100644 --- a/net/third_party/quic/core/quic_flow_controller_test.cc +++ b/net/third_party/quic/core/quic_flow_controller_test.cc
@@ -130,6 +130,26 @@ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); } +TEST_F(QuicFlowControllerTest, Move) { + Initialize(); + + flow_controller_->AddBytesSent(send_window_ / 2); + EXPECT_FALSE(flow_controller_->IsBlocked()); + EXPECT_EQ(send_window_ / 2, flow_controller_->SendWindowSize()); + + EXPECT_TRUE( + flow_controller_->UpdateHighestReceivedOffset(1 + receive_window_ / 2)); + EXPECT_FALSE(flow_controller_->FlowControlViolation()); + EXPECT_EQ((receive_window_ / 2) - 1, + QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); + + QuicFlowController flow_controller2(std::move(*flow_controller_)); + EXPECT_EQ(send_window_ / 2, flow_controller2.SendWindowSize()); + EXPECT_FALSE(flow_controller2.FlowControlViolation()); + EXPECT_EQ((receive_window_ / 2) - 1, + QuicFlowControllerPeer::ReceiveWindowSize(&flow_controller2)); +} + TEST_F(QuicFlowControllerTest, OnlySendBlockedFrameOncePerOffset) { Initialize();
diff --git a/net/third_party/quic/core/quic_framer.cc b/net/third_party/quic/core/quic_framer.cc index eb2d698..54b50359d 100644 --- a/net/third_party/quic/core/quic_framer.cc +++ b/net/third_party/quic/core/quic_framer.cc
@@ -3236,7 +3236,7 @@ bool no_message_length, QuicMessageFrame* frame) { if (no_message_length) { - frame->message_data = reader->ReadRemainingPayload(); + frame->message_data = QuicString(reader->ReadRemainingPayload()); return true; } @@ -3245,11 +3245,15 @@ set_detailed_error("Unable to read message length"); return false; } - if (!reader->ReadStringPiece(&frame->message_data, message_length)) { + + QuicStringPiece message_piece; + if (!reader->ReadStringPiece(&message_piece, message_length)) { set_detailed_error("Unable to read message data"); return false; } + frame->message_data = QuicString(message_piece); + return true; }
diff --git a/net/third_party/quic/core/quic_session.cc b/net/third_party/quic/core/quic_session.cc index 11f3bc3..0d9259f 100644 --- a/net/third_party/quic/core/quic_session.cc +++ b/net/third_party/quic/core/quic_session.cc
@@ -90,11 +90,9 @@ if (faster_get_stream_) { QUIC_FLAG_COUNT(quic_reloadable_flag_quic_session_faster_get_stream); } - if (connection_->deprecate_post_process_after_data()) { - closed_streams_clean_up_alarm_ = - QuicWrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm( - new ClosedStreamsCleanUpDelegate(this))); - } + closed_streams_clean_up_alarm_ = + QuicWrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm( + new ClosedStreamsCleanUpDelegate(this))); } void QuicSession::Initialize() { @@ -239,9 +237,7 @@ zombie_streams_.erase(it); } - if (deprecate_post_process_after_data()) { - closed_streams_clean_up_alarm_->Cancel(); - } + closed_streams_clean_up_alarm_->Cancel(); if (visitor_) { visitor_->OnConnectionClosed(connection_->connection_id(), error, @@ -503,9 +499,7 @@ control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written); connection_->OnStreamReset(id, error); } - if (GetQuicReloadableFlag(quic_fix_reset_zombie_streams) && - error != QUIC_STREAM_NO_ERROR && QuicContainsKey(zombie_streams_, id)) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_fix_reset_zombie_streams); + if (error != QUIC_STREAM_NO_ERROR && QuicContainsKey(zombie_streams_, id)) { OnStreamDoneWaitingForAcks(id); return; } @@ -578,8 +572,7 @@ closed_streams_.push_back(std::move(it->second)); // Do not retransmit data of a closed stream. streams_with_pending_retransmission_.erase(stream_id); - if (deprecate_post_process_after_data() && - !closed_streams_clean_up_alarm_->IsSet()) { + if (!closed_streams_clean_up_alarm_->IsSet()) { closed_streams_clean_up_alarm_->Set( connection_->clock()->ApproximateNow()); } @@ -1119,11 +1112,6 @@ control_frame_manager_.WillingToWrite(); } -void QuicSession::PostProcessAfterData() { - DCHECK(!deprecate_post_process_after_data()); - closed_streams_.clear(); -} - void QuicSession::OnAckNeedsRetransmittableFrame() { flow_controller_.SendWindowUpdate(); } @@ -1182,8 +1170,7 @@ } closed_streams_.push_back(std::move(it->second)); - if (deprecate_post_process_after_data() && - !closed_streams_clean_up_alarm_->IsSet()) { + if (!closed_streams_clean_up_alarm_->IsSet()) { closed_streams_clean_up_alarm_->Set(connection_->clock()->ApproximateNow()); } zombie_streams_.erase(it); @@ -1449,9 +1436,6 @@ } void QuicSession::CleanUpClosedStreams() { - DCHECK(deprecate_post_process_after_data()); - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_deprecate_post_process_after_data, - 1, 3); closed_streams_.clear(); } @@ -1463,10 +1447,6 @@ return connection_->GetLargestMessagePayload(); } -bool QuicSession::deprecate_post_process_after_data() const { - return connection_->deprecate_post_process_after_data(); -} - void QuicSession::SendStopSending(uint16_t code, QuicStreamId stream_id) { control_frame_manager_.WriteOrBufferStopSending(code, stream_id); }
diff --git a/net/third_party/quic/core/quic_session.h b/net/third_party/quic/core/quic_session.h index f10679b2..57bce8b 100644 --- a/net/third_party/quic/core/quic_session.h +++ b/net/third_party/quic/core/quic_session.h
@@ -110,9 +110,6 @@ void OnCanWrite() override; void OnCongestionWindowChange(QuicTime /*now*/) override {} void OnConnectionMigration(AddressChangeType type) override {} - // Deletes streams that are safe to be deleted now that it's safe to do so (no - // other operations are being done on the streams at this time). - void PostProcessAfterData() override; // Adds a connection level WINDOW_UPDATE frame. void OnAckNeedsRetransmittableFrame() override; void SendPing() override; @@ -161,10 +158,10 @@ // includes the message status and message ID (valid if the write succeeds). // SendMessage flushes a message packet even it is not full. If the // application wants to bundle other data in the same packet, please consider - // adding a packet flusher around the SendMessage and/or WritevData calls. If - // a packet flusher is added, ensure the |message|'s buffer is not modified or - // deleted before exiting the flusher's scope. OnMessageAcked and - // OnMessageLost are called when a particular message gets acked or lost. + // adding a packet flusher around the SendMessage and/or WritevData calls. + // + // OnMessageAcked and OnMessageLost are called when a particular message gets + // acked or lost. // // Note that SendMessage will fail with status = MESSAGE_STATUS_BLOCKED // if connection is congestion control blocked or underlying socket is write @@ -360,8 +357,6 @@ bool session_decides_what_to_write() const; - bool deprecate_post_process_after_data() const; - const ParsedQuicVersionVector& supported_versions() const { return supported_versions_; }
diff --git a/net/third_party/quic/core/quic_session_test.cc b/net/third_party/quic/core/quic_session_test.cc index 87f4f50..422aec3 100644 --- a/net/third_party/quic/core/quic_session_test.cc +++ b/net/third_party/quic/core/quic_session_test.cc
@@ -19,6 +19,7 @@ #include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_map_util.h" +#include "net/third_party/quic/platform/api/quic_mem_slice_storage.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_str_cat.h" #include "net/third_party/quic/platform/api/quic_string.h" @@ -251,7 +252,6 @@ using QuicSession::ActivateStream; using QuicSession::closed_streams; using QuicSession::next_outgoing_stream_id; - using QuicSession::PostProcessAfterData; using QuicSession::zombie_streams; private: @@ -1063,9 +1063,6 @@ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(), QUIC_STREAM_CANCELLED, kByteOffset); session_.OnRstStream(rst_frame); - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); } @@ -1081,9 +1078,6 @@ kInitialSessionFlowControlWindowForTest / 2 - 1; QuicStreamFrame frame(stream->id(), true, kByteOffset, "."); session_.OnStreamFrame(frame); - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } EXPECT_TRUE(connection_->connected()); EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed()); @@ -1263,12 +1257,6 @@ // Create one more data streams to exceed limit of open stream. QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT")); session_.OnStreamFrame(data1); - - // Called after any new data is received by the session, and triggers the - // call to close the connection. - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } } TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpenedOutgoing) { @@ -1309,12 +1297,6 @@ session_.StreamDraining(i); EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); } - - // Called after any new data is received by the session, and triggers the call - // to close the connection. - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } } TEST_P(QuicSessionTestServer, TestMaxIncomingAndOutgoingStreamsAllowed) { @@ -1380,10 +1362,6 @@ stream->Reset(QUIC_STREAM_CANCELLED); EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream)); - // Allow the session to delete the stream object. - if (!session_.deprecate_post_process_after_data()) { - session_.PostProcessAfterData(); - } EXPECT_TRUE(connection_->connected()); EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id)); EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id)); @@ -1697,22 +1675,14 @@ EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _)); stream2->Reset(QUIC_STREAM_CANCELLED); - if (GetQuicReloadableFlag(quic_fix_reset_zombie_streams)) { - // Verify stream 2 gets closed. - EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id())); - EXPECT_TRUE(session_.IsClosedStream(stream2->id())); - EXPECT_CALL(*stream2, OnCanWrite()).Times(0); - } else { - EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream2->id())); - EXPECT_CALL(*stream2, OnCanWrite()); - } + // Verify stream 2 gets closed. + EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id())); + EXPECT_TRUE(session_.IsClosedStream(stream2->id())); + EXPECT_CALL(*stream2, OnCanWrite()).Times(0); session_.OnCanWrite(); } TEST_P(QuicSessionTestServer, CleanUpClosedStreamsAlarm) { - if (!GetQuicReloadableFlag(quic_deprecate_post_process_after_data)) { - return; - } EXPECT_FALSE( QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
diff --git a/net/third_party/quic/core/quic_stream.h b/net/third_party/quic/core/quic_stream.h index db540ec..5241a50 100644 --- a/net/third_party/quic/core/quic_stream.h +++ b/net/third_party/quic/core/quic_stream.h
@@ -43,7 +43,8 @@ class QuicSession; -class QUIC_EXPORT_PRIVATE QuicStream { +class QUIC_EXPORT_PRIVATE QuicStream + : public QuicStreamSequencer::StreamInterface { public: // This is somewhat arbitrary. It's possible, but unlikely, we will either // fail to set a priority client-side, or cancel a stream before stripping the @@ -71,6 +72,29 @@ // Not in use currently. void SetFromConfig(); + // QuicStreamSequencer::StreamInterface implementation. + QuicStreamId id() const override { return id_; } + // Called by the stream subclass after it has consumed the final incoming + // data. + void OnFinRead() override; + + // Called by the subclass or the sequencer to reset the stream from this + // end. + void Reset(QuicRstStreamErrorCode error) override; + + // Called by the subclass or the sequencer to close the entire connection from + // this end. + void CloseConnectionWithDetails(QuicErrorCode error, + const QuicString& details) override; + + // Called by the stream sequencer as bytes are consumed from the buffer. + // If the receive window has dropped below the threshold, then send a + // WINDOW_UPDATE frame. + void AddBytesConsumed(QuicByteCount bytes) override; + + // Get peer IP of the lastest packet which connection is dealing/delt with. + const QuicSocketAddress& PeerAddressOfLatestPacket() const override; + // Called by the session when a (potentially duplicate) stream frame has been // received for this stream. virtual void OnStreamFrame(const QuicStreamFrame& frame); @@ -94,24 +118,6 @@ virtual void OnConnectionClosed(QuicErrorCode error, ConnectionCloseSource source); - // Called by the stream subclass after it has consumed the final incoming - // data. - virtual void OnFinRead(); - - // Called when new data is available from the sequencer. Subclasses must - // actively retrieve the data using the sequencer's Readv() or - // GetReadableRegions() method. - virtual void OnDataAvailable() = 0; - - // Called by the subclass or the sequencer to reset the stream from this - // end. - virtual void Reset(QuicRstStreamErrorCode error); - - // Called by the subclass or the sequencer to close the entire connection from - // this end. - virtual void CloseConnectionWithDetails(QuicErrorCode error, - const QuicString& details); - spdy::SpdyPriority priority() const; // Sets priority_ to priority. This should only be called before bytes are @@ -127,8 +133,6 @@ // Number of bytes available to read. size_t ReadableBytes() const; - QuicStreamId id() const { return id_; } - QuicRstStreamErrorCode stream_error() const { return stream_error_; } QuicErrorCode connection_error() const { return connection_error_; } @@ -173,10 +177,6 @@ bool MaybeIncreaseHighestReceivedOffset(QuicStreamOffset new_offset); // Called when bytes are sent to the peer. void AddBytesSent(QuicByteCount bytes); - // Called by the stream sequencer as bytes are consumed from the buffer. - // If the receive window has dropped below the threshold, then send a - // WINDOW_UPDATE frame. - void AddBytesConsumed(QuicByteCount bytes); // Updates the flow controller's send window offset and calls OnCanWrite if // it was blocked before. @@ -209,9 +209,6 @@ // stop sending stream-level flow-control updates when this end sends FIN. virtual void StopReading(); - // Get peer IP of the lastest packet which connection is dealing/delt with. - virtual const QuicSocketAddress& PeerAddressOfLatestPacket() const; - // Sends as much of 'data' to the connection as the connection will consume, // and then buffers any remaining data in queued_data_. // If fin is true: if it is immediately passed on to the session,
diff --git a/net/third_party/quic/core/quic_stream_id_manager.cc b/net/third_party/quic/core/quic_stream_id_manager.cc index 94a9bb90..34f197c5 100644 --- a/net/third_party/quic/core/quic_stream_id_manager.cc +++ b/net/third_party/quic/core/quic_stream_id_manager.cc
@@ -186,7 +186,7 @@ // If the stream is inbound, we can increase the stream ID limit and maybe // advertise the new limit to the peer. if (actual_max_allowed_incoming_stream_id_ >= - (kMaximumStreamIdSupported - kV99StreamIdIncrement)) { + (kMaxQuicStreamId - kV99StreamIdIncrement)) { // Reached the maximum stream id value that the implementation // supports. Nothing can be done here. return;
diff --git a/net/third_party/quic/core/quic_stream_sequencer.cc b/net/third_party/quic/core/quic_stream_sequencer.cc index ead9e4a..102a0a2 100644 --- a/net/third_party/quic/core/quic_stream_sequencer.cc +++ b/net/third_party/quic/core/quic_stream_sequencer.cc
@@ -22,7 +22,7 @@ namespace quic { -QuicStreamSequencer::QuicStreamSequencer(QuicStream* quic_stream) +QuicStreamSequencer::QuicStreamSequencer(StreamInterface* quic_stream) : stream_(quic_stream), buffered_frames_(kStreamReceiveWindowLimit), close_offset_(std::numeric_limits<QuicStreamOffset>::max()),
diff --git a/net/third_party/quic/core/quic_stream_sequencer.h b/net/third_party/quic/core/quic_stream_sequencer.h index 538ccb7..ab9edc0 100644 --- a/net/third_party/quic/core/quic_stream_sequencer.h +++ b/net/third_party/quic/core/quic_stream_sequencer.h
@@ -20,14 +20,40 @@ class QuicStreamSequencerPeer; } // namespace test -class QuicStream; - // Buffers frames until we have something which can be passed // up to the next layer. class QUIC_EXPORT_PRIVATE QuicStreamSequencer { public: - explicit QuicStreamSequencer(QuicStream* quic_stream); + // Interface that thie Sequencer uses to communicate with the Stream. + class StreamInterface { + public: + virtual ~StreamInterface() = default; + + // Called when new data is available to be read from the sequencer. + virtual void OnDataAvailable() = 0; + // Called when the end of the stream has been read. + virtual void OnFinRead() = 0; + // Called when bytes have been consumed from the sequencer. + virtual void AddBytesConsumed(QuicByteCount bytes) = 0; + // TODO(rch): Clean up this interface via OnUnrecoverableError and + // remove PeerAddressOfLatestPacket(). + // Called when an error has occurred which should result in the stream + // being reset. + virtual void Reset(QuicRstStreamErrorCode error) = 0; + // Called when an error has occurred which should result in the connection + // being closed. + virtual void CloseConnectionWithDetails(QuicErrorCode error, + const QuicString& details) = 0; + + // Returns the stream id of this stream. + virtual QuicStreamId id() const = 0; + // Returns the peer address of the last packet received for this stream. + virtual const QuicSocketAddress& PeerAddressOfLatestPacket() const = 0; + }; + + explicit QuicStreamSequencer(StreamInterface* quic_stream); QuicStreamSequencer(const QuicStreamSequencer&) = delete; + QuicStreamSequencer(QuicStreamSequencer&&) = default; QuicStreamSequencer& operator=(const QuicStreamSequencer&) = delete; virtual ~QuicStreamSequencer(); @@ -131,7 +157,7 @@ bool MaybeCloseStream(); // The stream which owns this sequencer. - QuicStream* stream_; + StreamInterface* stream_; // Stores received data in offset order. QuicStreamSequencerBuffer buffered_frames_;
diff --git a/net/third_party/quic/core/quic_stream_sequencer_buffer.h b/net/third_party/quic/core/quic_stream_sequencer_buffer.h index 85db9d2a..950a347 100644 --- a/net/third_party/quic/core/quic_stream_sequencer_buffer.h +++ b/net/third_party/quic/core/quic_stream_sequencer_buffer.h
@@ -90,6 +90,7 @@ explicit QuicStreamSequencerBuffer(size_t max_capacity_bytes); QuicStreamSequencerBuffer(const QuicStreamSequencerBuffer&) = delete; + QuicStreamSequencerBuffer(QuicStreamSequencerBuffer&&) = default; QuicStreamSequencerBuffer& operator=(const QuicStreamSequencerBuffer&) = delete; ~QuicStreamSequencerBuffer();
diff --git a/net/third_party/quic/core/quic_stream_sequencer_buffer_test.cc b/net/third_party/quic/core/quic_stream_sequencer_buffer_test.cc index e42f5c61..7c14502 100644 --- a/net/third_party/quic/core/quic_stream_sequencer_buffer_test.cc +++ b/net/third_party/quic/core/quic_stream_sequencer_buffer_test.cc
@@ -127,6 +127,31 @@ EXPECT_TRUE(helper_->IsBufferAllocated()); } +TEST_F(QuicStreamSequencerBufferTest, Move) { + EXPECT_FALSE(helper_->IsBufferAllocated()); + QuicString source(1024, 'a'); + size_t written; + EXPECT_EQ(QUIC_NO_ERROR, + buffer_->OnStreamData(800, source, &written, &error_details_)); + BufferBlock* block_ptr = helper_->GetBlock(0); + for (size_t i = 0; i < source.size(); ++i) { + ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]); + } + + QuicStreamSequencerBuffer buffer2(std::move(*buffer_)); + QuicStreamSequencerBufferPeer helper2(&buffer2); + + EXPECT_FALSE(helper_->IsBufferAllocated()); + + EXPECT_EQ(2, helper2.IntervalSize()); + EXPECT_EQ(0u, helper2.ReadableBytes()); + EXPECT_EQ(1u, helper2.bytes_received().Size()); + EXPECT_EQ(800u, helper2.bytes_received().begin()->min()); + EXPECT_EQ(1824u, helper2.bytes_received().begin()->max()); + EXPECT_TRUE(helper2.CheckBufferInvariants()); + EXPECT_TRUE(helper2.IsBufferAllocated()); +} + TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInvalidSource) { // Pass in an invalid source, expects to return error. QuicStringPiece source;
diff --git a/net/third_party/quic/core/quic_stream_sequencer_test.cc b/net/third_party/quic/core/quic_stream_sequencer_test.cc index 63d9e1f..32c7ee3 100644 --- a/net/third_party/quic/core/quic_stream_sequencer_test.cc +++ b/net/third_party/quic/core/quic_stream_sequencer_test.cc
@@ -18,8 +18,6 @@ #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" #include "net/third_party/quic/platform/api/quic_test.h" -#include "net/third_party/quic/test_tools/mock_clock.h" -#include "net/third_party/quic/test_tools/quic_spdy_session_peer.h" #include "net/third_party/quic/test_tools/quic_stream_sequencer_peer.h" #include "net/third_party/quic/test_tools/quic_test_utils.h" @@ -30,17 +28,17 @@ namespace quic { namespace test { -class MockStream : public QuicStream { +class MockStream : public QuicStreamSequencer::StreamInterface { public: - MockStream(QuicSession* session, QuicStreamId id) - : QuicStream(id, session, /*is_static=*/false, BIDIRECTIONAL) {} - MOCK_METHOD0(OnFinRead, void()); MOCK_METHOD0(OnDataAvailable, void()); MOCK_METHOD2(CloseConnectionWithDetails, void(QuicErrorCode error, const QuicString& details)); MOCK_METHOD1(Reset, void(QuicRstStreamErrorCode error)); MOCK_METHOD0(OnCanWrite, void()); + MOCK_METHOD1(AddBytesConsumed, void(QuicByteCount bytes)); + + QuicStreamId id() const override { return 1; } const QuicSocketAddress& PeerAddressOfLatestPacket() const override { return peer_address_; @@ -69,33 +67,48 @@ protected: QuicStreamSequencerTest() - : connection_(new MockQuicConnection(&helper_, - &alarm_factory_, - Perspective::IS_CLIENT)), - session_(connection_), - stream_(&session_, 1), - sequencer_(new QuicStreamSequencer(&stream_)) {} + : stream_(), sequencer_(new QuicStreamSequencer(&stream_)) {} // Verify that the data in first region match with the expected[0]. bool VerifyReadableRegion(const std::vector<QuicString>& expected) { + return VerifyReadableRegion(*sequencer_, expected); + } + + // Verify that the data in each of currently readable regions match with each + // item given in |expected|. + bool VerifyReadableRegions(const std::vector<QuicString>& expected) { + return VerifyReadableRegions(*sequencer_, expected); + } + + bool VerifyIovecs(iovec* iovecs, + size_t num_iovecs, + const std::vector<QuicString>& expected) { + return VerifyIovecs(*sequencer_, iovecs, num_iovecs, expected); + } + + bool VerifyReadableRegion(const QuicStreamSequencer& sequencer, + const std::vector<QuicString>& expected) { iovec iovecs[1]; - if (sequencer_->GetReadableRegions(iovecs, 1)) { - return (VerifyIovecs(iovecs, 1, std::vector<QuicString>{expected[0]})); + if (sequencer.GetReadableRegions(iovecs, 1)) { + return (VerifyIovecs(sequencer, iovecs, 1, + std::vector<QuicString>{expected[0]})); } return false; } // Verify that the data in each of currently readable regions match with each // item given in |expected|. - bool VerifyReadableRegions(const std::vector<QuicString>& expected) { + bool VerifyReadableRegions(const QuicStreamSequencer& sequencer, + const std::vector<QuicString>& expected) { iovec iovecs[5]; size_t num_iovecs = - sequencer_->GetReadableRegions(iovecs, QUIC_ARRAYSIZE(iovecs)); - return VerifyReadableRegion(expected) && - VerifyIovecs(iovecs, num_iovecs, expected); + sequencer.GetReadableRegions(iovecs, QUIC_ARRAYSIZE(iovecs)); + return VerifyReadableRegion(sequencer, expected) && + VerifyIovecs(sequencer, iovecs, num_iovecs, expected); } - bool VerifyIovecs(iovec* iovecs, + bool VerifyIovecs(const QuicStreamSequencer& sequencer, + iovec* iovecs, size_t num_iovecs, const std::vector<QuicString>& expected) { int start_position = 0; @@ -147,10 +160,6 @@ return QuicStreamSequencerPeer::GetNumBufferedBytes(sequencer_.get()); } - MockQuicConnectionHelper helper_; - MockAlarmFactory alarm_factory_; - MockQuicConnection* connection_; - MockQuicSpdySession session_; testing::StrictMock<MockStream> stream_; std::unique_ptr<QuicStreamSequencer> sequencer_; }; @@ -158,6 +167,7 @@ // TODO(rch): reorder these tests so they build on each other. TEST_F(QuicStreamSequencerTest, RejectOldFrame) { + EXPECT_CALL(stream_, AddBytesConsumed(3)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(3); })); @@ -166,7 +176,6 @@ EXPECT_EQ(0u, NumBufferedBytes()); EXPECT_EQ(3u, sequencer_->NumBytesConsumed()); - EXPECT_EQ(3u, stream_.flow_controller()->bytes_consumed()); // Ignore this - it matches a past packet number and we should not see it // again. OnFrame(0, "def"); @@ -187,6 +196,7 @@ } TEST_F(QuicStreamSequencerTest, FullFrameConsumed) { + EXPECT_CALL(stream_, AddBytesConsumed(3)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(3); })); @@ -203,6 +213,7 @@ EXPECT_EQ(3u, NumBufferedBytes()); EXPECT_EQ(0u, sequencer_->NumBytesConsumed()); + EXPECT_CALL(stream_, AddBytesConsumed(3)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(3); })); @@ -210,6 +221,7 @@ EXPECT_EQ(0u, NumBufferedBytes()); EXPECT_EQ(3u, sequencer_->NumBytesConsumed()); + EXPECT_CALL(stream_, AddBytesConsumed(3)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(3); })); @@ -225,6 +237,7 @@ EXPECT_EQ(3u, NumBufferedBytes()); EXPECT_EQ(0u, sequencer_->NumBytesConsumed()); + EXPECT_CALL(stream_, AddBytesConsumed(3)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(3); })); @@ -251,6 +264,7 @@ } TEST_F(QuicStreamSequencerTest, PartialFrameConsumed) { + EXPECT_CALL(stream_, AddBytesConsumed(2)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(2); })); @@ -286,6 +300,7 @@ EXPECT_EQ(0u, sequencer_->NumBytesConsumed()); EXPECT_EQ(6u, sequencer_->NumBytesBuffered()); + EXPECT_CALL(stream_, AddBytesConsumed(9)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(9); })); @@ -304,6 +319,7 @@ EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(3); })); + EXPECT_CALL(stream_, AddBytesConsumed(3)); OnFinFrame(0, "abc"); EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get())); @@ -314,6 +330,7 @@ EXPECT_EQ(6u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get())); OnFrame(3, "def"); + EXPECT_CALL(stream_, AddBytesConsumed(6)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(6); })); @@ -326,6 +343,7 @@ OnFinFrame(3, ""); EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get())); + EXPECT_CALL(stream_, AddBytesConsumed(3)); EXPECT_CALL(stream_, OnDataAvailable()).WillOnce(testing::Invoke([this]() { ConsumeData(3); })); @@ -345,6 +363,7 @@ EXPECT_CALL(stream_, OnDataAvailable()); OnFrame(0, "abc"); + EXPECT_CALL(stream_, AddBytesConsumed(3)); iovec iov = {&buffer[0], 3}; int bytes_read = sequencer_->Readv(&iov, 1); EXPECT_EQ(3, bytes_read); @@ -415,11 +434,17 @@ // All frames are processed as soon as we have sequential data. // Infinite buffering, so all frames are acked right away. TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingNoBackup) { - InSequence s; EXPECT_CALL(stream_, OnDataAvailable()) .Times(AnyNumber()) .WillRepeatedly( Invoke(this, &QuicSequencerRandomTest::ReadAvailableData)); + QuicByteCount total_bytes_consumed = 0; + EXPECT_CALL(stream_, AddBytesConsumed(_)) + .Times(AnyNumber()) + .WillRepeatedly( + testing::Invoke([&total_bytes_consumed](QuicByteCount bytes) { + total_bytes_consumed += bytes; + })); while (!list_.empty()) { int index = OneToN(list_.size()) - 1; @@ -431,6 +456,7 @@ ASSERT_EQ(QUIC_ARRAYSIZE(kPayload) - 1, output_.size()); EXPECT_EQ(kPayload, output_); + EXPECT_EQ(QUIC_ARRAYSIZE(kPayload) - 1, total_bytes_consumed); } TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) { @@ -442,6 +468,13 @@ iov[1].iov_len = 5; EXPECT_CALL(stream_, OnDataAvailable()).Times(AnyNumber()); + QuicByteCount total_bytes_consumed = 0; + EXPECT_CALL(stream_, AddBytesConsumed(_)) + .Times(AnyNumber()) + .WillRepeatedly( + testing::Invoke([&total_bytes_consumed](QuicByteCount bytes) { + total_bytes_consumed += bytes; + })); while (output_.size() != QUIC_ARRAYSIZE(kPayload) - 1) { if (!list_.empty() && OneToN(2) == 1) { // Send data @@ -476,6 +509,7 @@ } EXPECT_EQ(QuicString(kPayload), output_); EXPECT_EQ(QuicString(kPayload), peeked_); + EXPECT_EQ(QUIC_ARRAYSIZE(kPayload) - 1, total_bytes_consumed); } // Same as above, just using a different method for reading. @@ -495,24 +529,24 @@ ASSERT_TRUE(VerifyReadableRegions(expected)); // Consume 1 byte. + EXPECT_CALL(stream_, AddBytesConsumed(1)); sequencer_->MarkConsumed(1); - EXPECT_EQ(1u, stream_.flow_controller()->bytes_consumed()); // Verify data. std::vector<QuicString> expected2 = {"bcdefghi"}; ASSERT_TRUE(VerifyReadableRegions(expected2)); EXPECT_EQ(8u, sequencer_->NumBytesBuffered()); // Consume 2 bytes. + EXPECT_CALL(stream_, AddBytesConsumed(2)); sequencer_->MarkConsumed(2); - EXPECT_EQ(3u, stream_.flow_controller()->bytes_consumed()); // Verify data. std::vector<QuicString> expected3 = {"defghi"}; ASSERT_TRUE(VerifyReadableRegions(expected3)); EXPECT_EQ(6u, sequencer_->NumBytesBuffered()); // Consume 5 bytes. + EXPECT_CALL(stream_, AddBytesConsumed(5)); sequencer_->MarkConsumed(5); - EXPECT_EQ(8u, stream_.flow_controller()->bytes_consumed()); // Verify data. std::vector<QuicString> expected4{"i"}; ASSERT_TRUE(VerifyReadableRegions(expected4)); @@ -550,14 +584,33 @@ std::vector<QuicString> expected = {"abcdef"}; ASSERT_TRUE(VerifyReadableRegions(expected)); + EXPECT_CALL(stream_, AddBytesConsumed(6)); sequencer_->MarkConsumed(6); } +TEST_F(QuicStreamSequencerTest, Move) { + InSequence s; + EXPECT_CALL(stream_, OnDataAvailable()); + + OnFrame(0, "abc"); + OnFrame(3, "def"); + OnFrame(6, "ghi"); + + // abcdefghi buffered. + EXPECT_EQ(9u, sequencer_->NumBytesBuffered()); + + // Peek into the data. + std::vector<QuicString> expected = {"abcdefghi"}; + ASSERT_TRUE(VerifyReadableRegions(expected)); + + QuicStreamSequencer sequencer2(std::move(*sequencer_)); + ASSERT_TRUE(VerifyReadableRegions(sequencer2, expected)); +} + TEST_F(QuicStreamSequencerTest, OverlappingFramesReceived) { // The peer should never send us non-identical stream frames which contain // overlapping byte ranges - if they do, we close the connection. - QuicStreamId id = - QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0); + QuicStreamId id = 1; QuicStreamFrame frame1(id, false, 1, QuicStringPiece("hello")); sequencer_->OnStreamFrame(frame1); @@ -570,8 +623,7 @@ } TEST_F(QuicStreamSequencerTest, DataAvailableOnOverlappingFrames) { - QuicStreamId id = - QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0); + QuicStreamId id = 1; const QuicString data(1000, '.'); // Received [0, 1000). @@ -579,6 +631,7 @@ EXPECT_CALL(stream_, OnDataAvailable()); sequencer_->OnStreamFrame(frame1); // Consume [0, 500). + EXPECT_CALL(stream_, AddBytesConsumed(500)); QuicStreamSequencerTest::ConsumeData(500); EXPECT_EQ(500u, sequencer_->NumBytesConsumed()); EXPECT_EQ(500u, sequencer_->NumBytesBuffered()); @@ -589,6 +642,7 @@ EXPECT_CALL(stream_, OnDataAvailable()).Times(0); sequencer_->OnStreamFrame(frame2); // Consume [1000, 1500). + EXPECT_CALL(stream_, AddBytesConsumed(1000)); QuicStreamSequencerTest::ConsumeData(1000); EXPECT_EQ(1500u, sequencer_->NumBytesConsumed()); EXPECT_EQ(0u, sequencer_->NumBytesBuffered()); @@ -597,6 +651,7 @@ QuicStreamFrame frame3(id, false, 1498, QuicStringPiece("hello")); EXPECT_CALL(stream_, OnDataAvailable()); sequencer_->OnStreamFrame(frame3); + EXPECT_CALL(stream_, AddBytesConsumed(3)); QuicStreamSequencerTest::ConsumeData(3); EXPECT_EQ(1503u, sequencer_->NumBytesConsumed()); EXPECT_EQ(0u, sequencer_->NumBytesBuffered()); @@ -611,8 +666,7 @@ TEST_F(QuicStreamSequencerTest, OnDataAvailableWhenReadableBytesIncrease) { sequencer_->set_level_triggered(true); - QuicStreamId id = - QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0); + QuicStreamId id = 1; // Received [0, 5). QuicStreamFrame frame1(id, false, 0, "hello"); @@ -640,10 +694,10 @@ EXPECT_CALL(stream_, OnDataAvailable()); OnFrame(0u, "abc"); QuicString actual; + EXPECT_CALL(stream_, AddBytesConsumed(3)); sequencer_->Read(&actual); EXPECT_EQ("abc", actual); EXPECT_EQ(0u, sequencer_->NumBytesBuffered()); - EXPECT_EQ(3u, stream_.flow_controller()->bytes_consumed()); } TEST_F(QuicStreamSequencerTest, ReadMultipleFramesWithMissingFrame) { @@ -653,10 +707,10 @@ OnFrame(6u, "ghi"); OnFrame(10u, "xyz"); // Byte 9 is missing. QuicString actual; + EXPECT_CALL(stream_, AddBytesConsumed(9)); sequencer_->Read(&actual); EXPECT_EQ("abcdefghi", actual); EXPECT_EQ(3u, sequencer_->NumBytesBuffered()); - EXPECT_EQ(9u, stream_.flow_controller()->bytes_consumed()); } TEST_F(QuicStreamSequencerTest, ReadAndAppendToString) { @@ -664,28 +718,35 @@ OnFrame(0u, "def"); OnFrame(3u, "ghi"); QuicString actual = "abc"; + EXPECT_CALL(stream_, AddBytesConsumed(6)); sequencer_->Read(&actual); EXPECT_EQ("abcdefghi", actual); EXPECT_EQ(0u, sequencer_->NumBytesBuffered()); - EXPECT_EQ(6u, stream_.flow_controller()->bytes_consumed()); } TEST_F(QuicStreamSequencerTest, StopReading) { EXPECT_CALL(stream_, OnDataAvailable()).Times(0); EXPECT_CALL(stream_, OnFinRead()); + EXPECT_CALL(stream_, AddBytesConsumed(0)); sequencer_->StopReading(); + EXPECT_CALL(stream_, AddBytesConsumed(3)); OnFrame(0u, "abc"); + EXPECT_CALL(stream_, AddBytesConsumed(3)); OnFrame(3u, "def"); + EXPECT_CALL(stream_, AddBytesConsumed(3)); OnFinFrame(6u, "ghi"); } TEST_F(QuicStreamSequencerTest, StopReadingWithLevelTriggered) { if (GetQuicReloadableFlag(quic_stop_reading_when_level_triggered)) { + EXPECT_CALL(stream_, AddBytesConsumed(0)); + EXPECT_CALL(stream_, AddBytesConsumed(3)).Times(3); EXPECT_CALL(stream_, OnDataAvailable()).Times(0); EXPECT_CALL(stream_, OnFinRead()); } else { + EXPECT_CALL(stream_, AddBytesConsumed(0)); EXPECT_CALL(stream_, OnDataAvailable()).Times(3); }
diff --git a/net/third_party/quic/core/quic_stream_test.cc b/net/third_party/quic/core/quic_stream_test.cc index 25092ef..9d1be8f 100644 --- a/net/third_party/quic/core/quic_stream_test.cc +++ b/net/third_party/quic/core/quic_stream_test.cc
@@ -14,6 +14,7 @@ #include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_logging.h" +#include "net/third_party/quic/platform/api/quic_mem_slice_storage.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_test.h"
diff --git a/net/third_party/quic/core/quic_versions.cc b/net/third_party/quic/core/quic_versions.cc index 8c613946..0cd476d 100644 --- a/net/third_party/quic/core/quic_versions.cc +++ b/net/third_party/quic/core/quic_versions.cc
@@ -326,5 +326,11 @@ return result; } +ParsedQuicVersion UnsupportedQuicVersion() { + static const ParsedQuicVersion kUnsupportedQuicVersion( + PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); + return kUnsupportedQuicVersion; +} + #undef RETURN_STRING_LITERAL // undef for jumbo builds } // namespace quic
diff --git a/net/third_party/quic/core/quic_versions.h b/net/third_party/quic/core/quic_versions.h index 22a613ad..37676d2 100644 --- a/net/third_party/quic/core/quic_versions.h +++ b/net/third_party/quic/core/quic_versions.h
@@ -145,6 +145,8 @@ } }; +QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion(); + QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version);
diff --git a/net/third_party/quic/core/stateless_rejector.h b/net/third_party/quic/core/stateless_rejector.h index 6904bb8..5b95feb 100644 --- a/net/third_party/quic/core/stateless_rejector.h +++ b/net/third_party/quic/core/stateless_rejector.h
@@ -56,6 +56,9 @@ static void Process(std::unique_ptr<StatelessRejector> rejector, std::unique_ptr<ProcessDoneCallback> done_cb); + // Return the version of the CHLO. + ParsedQuicVersion version() const { return version_; } + // Returns the state of the rejector after OnChlo() has been called. State state() const { return state_; }
diff --git a/net/third_party/quic/quartc/quartc_factory.cc b/net/third_party/quic/quartc/quartc_factory.cc index f2e90b5..c10a13d 100644 --- a/net/third_party/quic/quartc/quartc_factory.cc +++ b/net/third_party/quic/quartc/quartc_factory.cc
@@ -32,15 +32,12 @@ // Fixes behavior of StopReading() with level-triggered stream sequencers. SetQuicReloadableFlag(quic_stop_reading_when_level_triggered, true); - // Quartc uses zombie streams -- we close the stream for read as soon as we - // create a stream -- this makes the stream a zombie stream. b/115323618 - // revealed that closing zombie streams is problematic, and enabling this flag - // fixes it. - SetQuicReloadableFlag(quic_fix_reset_zombie_streams, true); - // Fix b/110259444. SetQuicReloadableFlag(quic_fix_spurious_ack_alarm, true); + // Enable version 45+ to enable SendMessage API. + SetQuicReloadableFlag(quic_enable_version_46, true); + std::unique_ptr<QuicConnection> quic_connection = CreateQuicConnection(perspective, writer.get());
diff --git a/net/third_party/quic/quartc/quartc_session.cc b/net/third_party/quic/quartc/quartc_session.cc index a5b2745..fdb37ba 100644 --- a/net/third_party/quic/quartc/quartc_session.cc +++ b/net/third_party/quic/quartc/quartc_session.cc
@@ -181,6 +181,80 @@ QuicStream::kDefaultPriority)); } +bool QuartcSession::SendOrQueueMessage(QuicString message) { + if (!CanSendMessage()) { + QUIC_LOG(ERROR) << "Quic session does not support SendMessage"; + return false; + } + + if (message.size() > GetLargestMessagePayload()) { + QUIC_LOG(ERROR) << "Message is too big, message_size=" << message.size() + << ", GetLargestMessagePayload=" + << GetLargestMessagePayload(); + return false; + } + + // There may be other messages in send queue, so we have to add message + // to the queue and call queue processing helper. + send_message_queue_.emplace_back(std::move(message)); + + ProcessSendMessageQueue(); + + return true; +} + +void QuartcSession::ProcessSendMessageQueue() { + while (!send_message_queue_.empty()) { + MessageResult result = SendMessage(send_message_queue_.front()); + + const size_t message_size = send_message_queue_.front().size(); + + // Handle errors. + switch (result.status) { + case MESSAGE_STATUS_SUCCESS: + QUIC_VLOG(1) << "Quartc message sent, message_id=" << result.message_id + << ", message_size=" << message_size; + break; + + // If connection is congestion controlled or not writable yet, stop + // send loop and we'll retry again when we get OnCanWrite notification. + case MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED: + case MESSAGE_STATUS_BLOCKED: + QUIC_VLOG(1) << "Quartc message not sent because connection is blocked" + << ", message will be retried later, status=" + << result.status << ", message_size=" << message_size; + + return; + + // Other errors are unexpected. We do not propagate error to Quartc, + // because writes can be delayed. + case MESSAGE_STATUS_UNSUPPORTED: + case MESSAGE_STATUS_TOO_LARGE: + case MESSAGE_STATUS_INTERNAL_ERROR: + QUIC_DLOG(DFATAL) + << "Failed to send quartc message due to unexpected error" + << ", message will not be retried, status=" << result.status + << ", message_size=" << message_size; + break; + } + + send_message_queue_.pop_front(); + } +} + +void QuartcSession::OnCanWrite() { + // TODO(b/119640244): Since we currently use messages for audio and streams + // for video, it makes sense to process queued messages first, then call quic + // core OnCanWrite, which will resend queued streams. Long term we may need + // better solution especially if quic connection is used for both data and + // media. + + // Process quartc messages that were previously blocked. + ProcessSendMessageQueue(); + + QuicSession::OnCanWrite(); +} + void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { QuicSession::OnCryptoHandshakeEvent(event); if (event == HANDSHAKE_CONFIRMED) { @@ -298,6 +372,10 @@ packet); } +void QuartcSession::OnMessageReceived(QuicStringPiece message) { + session_delegate_->OnMessageReceived(message); +} + void QuartcSession::OnProofValid( const QuicCryptoClientConfig::CachedState& cached) { // TODO(zhihuang): Handle the proof verification.
diff --git a/net/third_party/quic/quartc/quartc_session.h b/net/third_party/quic/quartc/quartc_session.h index 23cbb22..ac976d6 100644 --- a/net/third_party/quic/quartc/quartc_session.h +++ b/net/third_party/quic/quartc/quartc_session.h
@@ -5,11 +5,15 @@ #ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_SESSION_H_ #define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_SESSION_H_ +#include <memory> +#include <string> + #include "net/third_party/quic/core/quic_crypto_client_stream.h" #include "net/third_party/quic/core/quic_crypto_server_stream.h" #include "net/third_party/quic/core/quic_crypto_stream.h" #include "net/third_party/quic/core/quic_error_codes.h" #include "net/third_party/quic/core/quic_session.h" +#include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/quartc/quartc_packet_writer.h" #include "net/third_party/quic/quartc/quartc_stream.h" @@ -54,11 +58,38 @@ QuartcStream* CreateOutgoingBidirectionalStream(); + // Sends short unreliable message using quic message frame (message must fit + // in one quic packet). If connection is blocked by congestion control, + // message will be queued and resent later after receiving an OnCanWrite + // notification. + // + // Message size must be <= GetLargestMessagePayload(). + // + // Supported in quic version 45 or later. + // + // Returns false and logs error if message is too long or session does not + // support SendMessage API. Other unexpected errors during send will not be + // returned, because messages can be sent later if connection is congestion + // controlled. + bool SendOrQueueMessage(QuicString message); + + // Returns largest message payload acceptable in SendQuartcMessage. + QuicPacketLength GetLargestMessagePayload() const { + return connection()->GetLargestMessagePayload(); + } + + // Return true if transport support message frame. + bool CanSendMessage() const { + return connection()->transport_version() >= QUIC_VERSION_45; + } + void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override; // QuicConnectionVisitorInterface overrides. void OnCongestionWindowChange(QuicTime now) override; + void OnCanWrite() override; + void OnConnectionClosed(QuicErrorCode error, const QuicString& error_details, ConnectionCloseSource source) override; @@ -112,6 +143,9 @@ const QuicString& error_details, ConnectionCloseSource source) = 0; + // Called when message (sent as SendMessage) is received. + virtual void OnMessageReceived(QuicStringPiece message) = 0; + // TODO(zhihuang): Add proof verification. }; @@ -125,6 +159,8 @@ // QuicConnection. void OnTransportReceived(const char* data, size_t data_len) override; + void OnMessageReceived(QuicStringPiece message) override; + // ProofHandler overrides. void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override; @@ -134,6 +170,11 @@ void OnProofVerifyDetailsAvailable( const ProofVerifyDetails& verify_details) override; + // Returns number of queued (not sent) messages submitted by + // SendOrQueueMessage. Messages are queued if connection is congestion + // controlled. + size_t send_message_queue_size() const { return send_message_queue_.size(); } + protected: // QuicSession override. QuicStream* CreateIncomingStream(QuicStreamId id) override; @@ -147,6 +188,8 @@ void ResetStream(QuicStreamId stream_id, QuicRstStreamErrorCode error); private: + void ProcessSendMessageQueue(); + // For crypto handshake. std::unique_ptr<QuicCryptoStream> crypto_stream_; const QuicString unique_remote_server_id_; @@ -173,6 +216,11 @@ std::unique_ptr<QuicCryptoClientConfig> quic_crypto_client_config_; // Config for QUIC crypto server stream, used by the server. std::unique_ptr<QuicCryptoServerConfig> quic_crypto_server_config_; + + // Queue of pending messages sent by SendQuartcMessage that were not sent + // yet or blocked by congestion control. Messages are queued in the order + // of sent by SendOrQueueMessage(). + QuicDeque<QuicString> send_message_queue_; }; } // namespace quic
diff --git a/net/third_party/quic/quartc/quartc_session_test.cc b/net/third_party/quic/quartc/quartc_session_test.cc index 4607a7c5..f72f51f 100644 --- a/net/third_party/quic/quartc/quartc_session_test.cc +++ b/net/third_party/quic/quartc/quartc_session_test.cc
@@ -11,6 +11,7 @@ #include "net/third_party/quic/core/tls_client_handshaker.h" #include "net/third_party/quic/core/tls_server_handshaker.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" +#include "net/third_party/quic/platform/api/quic_string_utils.h" #include "net/third_party/quic/platform/api/quic_test.h" #include "net/third_party/quic/platform/api/quic_test_mem_slice_vector.h" #include "net/third_party/quic/quartc/counting_packet_filter.h" @@ -52,16 +53,26 @@ last_incoming_stream_->SetDelegate(stream_delegate_); } + void OnMessageReceived(QuicStringPiece message) override { + incoming_messages_.emplace_back(message); + } + void OnCongestionControlChange(QuicBandwidth bandwidth_estimate, QuicBandwidth pacing_rate, QuicTime::Delta latest_rtt) override {} - QuartcStream* incoming_stream() { return last_incoming_stream_; } + QuartcStream* last_incoming_stream() { return last_incoming_stream_; } + + // Returns all received messages. + const std::vector<QuicString>& incoming_messages() { + return incoming_messages_; + } bool connected() { return connected_; } private: QuartcStream* last_incoming_stream_; + std::vector<QuicString> incoming_messages_; bool connected_ = true; QuartcStream::Delegate* stream_delegate_; }; @@ -102,6 +113,9 @@ ~QuartcSessionTest() override {} void Init() { + // To enable SendMessage. + SetQuicReloadableFlag(quic_enable_version_45, true); + client_transport_ = QuicMakeUnique<simulator::SimulatedQuartcPacketTransport>( &simulator_, "client_transport", "server_transport", @@ -152,6 +166,7 @@ CreateConnection(perspective, writer.get()); QuicString remote_fingerprint_value = "value"; QuicConfig config; + return QuicMakeUnique<QuartcSession>( std::move(quic_connection), config, CurrentSupportedVersions(), remote_fingerprint_value, perspective, &simulator_, @@ -179,7 +194,7 @@ // Test handshake establishment and sending/receiving of data for two // directions. - void TestStreamConnection() { + void TestSendReceiveStreams() { ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed()); ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed()); ASSERT_TRUE(server_peer_->IsEncryptionEstablished()); @@ -204,7 +219,7 @@ // Wait for peer 2 to receive messages. ASSERT_TRUE(client_stream_delegate_->has_data()); - QuartcStream* incoming = client_session_delegate_->incoming_stream(); + QuartcStream* incoming = client_session_delegate_->last_incoming_stream(); ASSERT_TRUE(incoming); EXPECT_EQ(incoming->id(), stream_id); EXPECT_TRUE(client_peer_->HasOpenDynamicStreams()); @@ -222,6 +237,95 @@ EXPECT_EQ(server_stream_delegate_->data()[stream_id], kTestResponse); } + // Test sending/receiving of messages for two directions. + void TestSendReceiveMessage() { + ASSERT_TRUE(server_peer_->CanSendMessage()); + ASSERT_TRUE(client_peer_->CanSendMessage()); + + // Send message from peer 1 to peer 2. + ASSERT_TRUE(server_peer_->SendOrQueueMessage("Message from server")); + + // First message in each direction should not be queued. + EXPECT_EQ(server_peer_->send_message_queue_size(), 0u); + + // Wait for peer 2 to receive message. + RunTasks(); + + EXPECT_THAT(client_session_delegate_->incoming_messages(), + testing::ElementsAre("Message from server")); + + // Send message from peer 2 to peer 1. + ASSERT_TRUE(client_peer_->SendOrQueueMessage("Message from client")); + + // First message in each direction should not be queued. + EXPECT_EQ(client_peer_->send_message_queue_size(), 0u); + + // Wait for peer 1 to receive message. + RunTasks(); + + EXPECT_THAT(server_session_delegate_->incoming_messages(), + testing::ElementsAre("Message from client")); + } + + // Test for sending multiple messages that also result in queueing. + // This is one-way test, which is run in given direction. + void TestSendReceiveQueuedMessages(bool direction_from_server) { + // Send until queue_size number of messages are queued. + constexpr size_t queue_size = 10; + + ASSERT_TRUE(server_peer_->CanSendMessage()); + ASSERT_TRUE(client_peer_->CanSendMessage()); + + QuartcSession* const peer_sending = + direction_from_server ? server_peer_.get() : client_peer_.get(); + + FakeQuartcSessionDelegate* const delegate_receiving = + direction_from_server ? client_session_delegate_.get() + : server_session_delegate_.get(); + + // There should be no messages in the queue before we start sending. + EXPECT_EQ(peer_sending->send_message_queue_size(), 0u); + + // Send messages from peer 1 to peer 2 until required number of messages + // are queued in unsent message queue. + std::vector<QuicString> sent_messages; + while (peer_sending->send_message_queue_size() < queue_size) { + sent_messages.push_back( + QuicStrCat("Sending message, index=", sent_messages.size())); + ASSERT_TRUE(peer_sending->SendOrQueueMessage(sent_messages.back())); + } + + // Wait for peer 2 to receive all messages. + RunTasks(); + + EXPECT_EQ(delegate_receiving->incoming_messages(), sent_messages); + } + + // Test sending long messages: + // - message of maximum allowed length should succeed + // - message of > maximum allowed length should fail. + void TestSendLongMessage() { + ASSERT_TRUE(server_peer_->CanSendMessage()); + ASSERT_TRUE(client_peer_->CanSendMessage()); + + // Send message of maximum allowed length. + QuicString message_max_long = + QuicString(server_peer_->GetLargestMessagePayload(), 'A'); + ASSERT_TRUE(server_peer_->SendOrQueueMessage(message_max_long)); + + // Send long message which should fail. + QuicString message_too_long = + QuicString(server_peer_->GetLargestMessagePayload() + 1, 'B'); + ASSERT_FALSE(server_peer_->SendOrQueueMessage(message_too_long)); + + // Wait for peer 2 to receive message. + RunTasks(); + + // Client should only receive one message of allowed length. + EXPECT_THAT(client_session_delegate_->incoming_messages(), + testing::ElementsAre(message_max_long)); + } + // Test that client and server are not connected after handshake failure. void TestDisconnectAfterFailedHandshake() { EXPECT_TRUE(!client_session_delegate_->connected()); @@ -253,10 +357,29 @@ std::unique_ptr<FakeQuartcSessionDelegate> server_session_delegate_; }; -TEST_F(QuartcSessionTest, StreamConnection) { +TEST_F(QuartcSessionTest, SendReceiveStreams) { CreateClientAndServerSessions(); StartHandshake(); - TestStreamConnection(); + TestSendReceiveStreams(); +} + +TEST_F(QuartcSessionTest, SendReceiveMessages) { + CreateClientAndServerSessions(); + StartHandshake(); + TestSendReceiveMessage(); +} + +TEST_F(QuartcSessionTest, SendReceiveQueuedMessages) { + CreateClientAndServerSessions(); + StartHandshake(); + TestSendReceiveQueuedMessages(/*direction_from_server=*/true); + TestSendReceiveQueuedMessages(/*direction_from_server=*/false); +} + +TEST_F(QuartcSessionTest, SendMessageFails) { + CreateClientAndServerSessions(); + StartHandshake(); + TestSendLongMessage(); } TEST_F(QuartcSessionTest, PreSharedKeyHandshake) { @@ -264,7 +387,8 @@ client_peer_->SetPreSharedKey("foo"); server_peer_->SetPreSharedKey("foo"); StartHandshake(); - TestStreamConnection(); + TestSendReceiveStreams(); + TestSendReceiveMessage(); } // Test that data streams are not created before handshake.
diff --git a/net/third_party/quic/quartc/quartc_stream.cc b/net/third_party/quic/quartc/quartc_stream.cc index 37ea7fc..ce846427a 100644 --- a/net/third_party/quic/quartc/quartc_stream.cc +++ b/net/third_party/quic/quartc/quartc_stream.cc
@@ -72,12 +72,15 @@ bool fin_lost) { QuicStream::OnStreamFrameLost(offset, data_length, fin_lost); + ++total_frames_lost_; + DCHECK(delegate_); delegate_->OnBufferChanged(this); } void QuartcStream::OnCanWrite() { - if (cancel_on_loss_ && HasPendingRetransmission()) { + if (total_frames_lost_ > max_frame_retransmission_count_ && + HasPendingRetransmission()) { Reset(QUIC_STREAM_CANCELLED); return; } @@ -85,15 +88,28 @@ } bool QuartcStream::cancel_on_loss() { - return cancel_on_loss_; + return max_frame_retransmission_count_ == 0; } void QuartcStream::set_cancel_on_loss(bool cancel_on_loss) { - cancel_on_loss_ = cancel_on_loss; + if (cancel_on_loss) { + max_frame_retransmission_count_ = 0; + } else { + max_frame_retransmission_count_ = std::numeric_limits<int>::max(); + } +} + +int QuartcStream::max_frame_retransmission_count() const { + return max_frame_retransmission_count_; +} + +void QuartcStream::set_max_frame_retransmission_count( + int max_frame_retransmission_count) { + max_frame_retransmission_count_ = max_frame_retransmission_count; } QuicByteCount QuartcStream::BytesPendingRetransmission() { - if (cancel_on_loss_) { + if (total_frames_lost_ > max_frame_retransmission_count_) { return 0; // Lost bytes will never be retransmitted. } QuicByteCount bytes = 0;
diff --git a/net/third_party/quic/quartc/quartc_stream.h b/net/third_party/quic/quartc/quartc_stream.h index 2f9598da..12a1d147 100644 --- a/net/third_party/quic/quartc/quartc_stream.h +++ b/net/third_party/quic/quartc/quartc_stream.h
@@ -49,10 +49,24 @@ // Whether the stream should be cancelled instead of retransmitted on loss. // If set to true, the stream will reset itself instead of retransmitting lost - // stream frames. Defaults to false. + // stream frames. Defaults to false. Setting it to true is equivalent to + // setting |max_frame_retransmission_count| to zero. bool cancel_on_loss(); void set_cancel_on_loss(bool cancel_on_loss); + // Maximum number of stream frames which may be retransmitted. Up to this + // number of stream frames may be retransmitted. If any stream frames in + // excess of this amount would be retransmitted, the stream will reset itself. + // Setting it to zero disables retransmissions. + // + // Ideally, the stream would support a maximum retransmission count per frame, + // allowing each frame to be retransmitted up to N times. However, this + // requires complex bookkeeping (tracking retransmission count on a per-frame + // basis). This feature provides a simple way to limit retransmissions on + // streams that are expected to fit within one frame (eg. small messages). + int max_frame_retransmission_count() const; + void set_max_frame_retransmission_count(int max_frame_retransmission_count); + QuicByteCount BytesPendingRetransmission(); // Marks this stream as finished writing. Asynchronously sends a FIN and @@ -94,8 +108,11 @@ private: Delegate* delegate_ = nullptr; - // Whether the stream should cancel itself instead of retransmitting frames. - bool cancel_on_loss_ = false; + // Maximum number of frames which may be retransmitted on this stream. + int max_frame_retransmission_count_ = std::numeric_limits<int>::max(); + + // Total number of stream frames detected as lost. + int total_frames_lost_ = 0; }; } // namespace quic
diff --git a/net/third_party/quic/quartc/quartc_stream_test.cc b/net/third_party/quic/quartc/quartc_stream_test.cc index 2c8d434..731bd4b 100644 --- a/net/third_party/quic/quartc/quartc_stream_test.cc +++ b/net/third_party/quic/quartc/quartc_stream_test.cc
@@ -409,6 +409,53 @@ EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_CANCELLED); } +TEST_F(QuartcStreamTest, TestMaxRetransmissionsAbsent) { + CreateReliableQuicStream(); + + // This should be the default state. + EXPECT_EQ(stream_->max_frame_retransmission_count(), + std::numeric_limits<int>::max()); + + char message[] = "Foo bar"; + test::QuicTestMemSliceVector data({std::make_pair(message, 7)}); + stream_->WriteMemSlices(data.span(), /*fin=*/false); + + EXPECT_EQ("Foo bar", write_buffer_); + + stream_->OnStreamFrameLost(0, 7, false); + stream_->OnCanWrite(); + + EXPECT_EQ("Foo barFoo bar", write_buffer_); + EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_NO_ERROR); +} + +TEST_F(QuartcStreamTest, TestMaxRetransmissionsSet) { + CreateReliableQuicStream(); + stream_->set_max_frame_retransmission_count(2); + + char message[] = "Foo bar"; + test::QuicTestMemSliceVector data({std::make_pair(message, 7)}); + stream_->WriteMemSlices(data.span(), /*fin=*/false); + + EXPECT_EQ("Foo bar", write_buffer_); + + stream_->OnStreamFrameLost(0, 7, false); + stream_->OnCanWrite(); + + EXPECT_EQ("Foo barFoo bar", write_buffer_); + + stream_->OnStreamFrameLost(0, 7, false); + stream_->OnCanWrite(); + + EXPECT_EQ("Foo barFoo barFoo bar", write_buffer_); + + stream_->OnStreamFrameLost(0, 7, false); + stream_->OnCanWrite(); + + EXPECT_EQ("Foo barFoo barFoo bar", write_buffer_); + EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_CANCELLED); +} + TEST_F(QuartcStreamTest, TestBytesPendingRetransmission) { CreateReliableQuicStream(); stream_->set_cancel_on_loss(false);
diff --git a/net/third_party/quic/test_tools/quic_test_utils.h b/net/third_party/quic/test_tools/quic_test_utils.h index 90158df0..5e03954 100644 --- a/net/third_party/quic/test_tools/quic_test_utils.h +++ b/net/third_party/quic/test_tools/quic_test_utils.h
@@ -372,7 +372,6 @@ void(const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address)); MOCK_METHOD0(OnConfigNegotiated, void()); - MOCK_METHOD0(PostProcessAfterData, void()); MOCK_METHOD0(OnAckNeedsRetransmittableFrame, void()); MOCK_METHOD0(SendPing, void()); MOCK_CONST_METHOD0(AllowSelfAddressChange, bool());
diff --git a/net/third_party/quic/test_tools/simulator/quic_endpoint.h b/net/third_party/quic/test_tools/simulator/quic_endpoint.h index f24e30a..9224ae5 100644 --- a/net/third_party/quic/test_tools/simulator/quic_endpoint.h +++ b/net/third_party/quic/test_tools/simulator/quic_endpoint.h
@@ -102,7 +102,6 @@ void OnCongestionWindowChange(QuicTime now) override {} void OnConnectionMigration(AddressChangeType type) override {} void OnPathDegrading() override {} - void PostProcessAfterData() override {} void OnAckNeedsRetransmittableFrame() override {} void SendPing() override {} bool AllowSelfAddressChange() const override;
diff --git a/net/third_party/quic/tools/quic_simple_server_stream.cc b/net/third_party/quic/tools/quic_simple_server_stream.cc index c15dec9..d6ac2e57 100644 --- a/net/third_party/quic/tools/quic_simple_server_stream.cc +++ b/net/third_party/quic/tools/quic_simple_server_stream.cc
@@ -56,7 +56,7 @@ SendErrorResponse(); } -void QuicSimpleServerStream::OnDataAvailable() { +void QuicSimpleServerStream::OnBodyAvailable() { while (HasBytesToRead()) { struct iovec iov; if (GetReadableRegions(&iov, 1) == 0) {
diff --git a/net/third_party/quic/tools/quic_simple_server_stream.h b/net/third_party/quic/tools/quic_simple_server_stream.h index 09c3ae05..cbff606 100644 --- a/net/third_party/quic/tools/quic_simple_server_stream.h +++ b/net/third_party/quic/tools/quic_simple_server_stream.h
@@ -42,7 +42,7 @@ // QuicStream implementation called by the sequencer when there is // data (or a FIN) to be read. - void OnDataAvailable() override; + void OnBodyAvailable() override; // Make this stream start from as if it just finished parsing an incoming // request whose headers are equivalent to |push_request_headers|.
diff --git a/net/url_request/url_request_filter.cc b/net/url_request/url_request_filter.cc index 628a912..f2cf018e 100644 --- a/net/url_request/url_request_filter.cc +++ b/net/url_request/url_request_filter.cc
@@ -29,9 +29,9 @@ // When removing interceptors, DCHECK that this function returns true. bool OnMessageLoopForInterceptorRemoval() { - // Checking for a MessageLoopForIO is a best effort at determining whether the - // current thread is a networking thread. - return base::MessageLoopForIO::IsCurrent(); + // Checking for a MessageLoopCurrentForIO is a best effort at determining + // whether the current thread is a networking thread. + return base::MessageLoopCurrentForIO::IsSet(); } } // namespace
diff --git a/remoting/host/desktop_process.cc b/remoting/host/desktop_process.cc index 02989595..73ac698 100644 --- a/remoting/host/desktop_process.cc +++ b/remoting/host/desktop_process.cc
@@ -41,7 +41,7 @@ daemon_channel_handle_(std::move(daemon_channel_handle)), weak_factory_(this) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); } DesktopProcess::~DesktopProcess() {
diff --git a/remoting/host/mac/permission_utils.mm b/remoting/host/mac/permission_utils.mm index 6cb20cb..f293042 100644 --- a/remoting/host/mac/permission_utils.mm +++ b/remoting/host/mac/permission_utils.mm
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_refptr.h" #include "base/single_thread_task_runner.h" #include "base/strings/sys_string_conversions.h" @@ -22,7 +23,7 @@ constexpr NSString* kServiceScriptName = @"org.chromium.chromoting.me2me.sh"; void ShowPermissionDialog() { - NSAlert* alert = [[NSAlert alloc] init]; + base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]); [alert setMessageText:l10n_util::GetNSString( IDS_ACCESSIBILITY_PERMISSION_DIALOG_TITLE)]; [alert setInformativeText: @@ -42,13 +43,14 @@ // Increase the alert width so the title doesn't wrap and the body text is // less scrunched. Note that we only want to set a min-width, we don't // want to shrink the dialog if it is already larger than our min value. - NSRect frame = [alert.window frame]; + NSWindow* alert_window = [alert window]; + NSRect frame = [alert_window frame]; if (frame.size.width < kMinDialogWidthPx) frame.size.width = kMinDialogWidthPx; - [alert.window setFrame:frame display:YES]; + [alert_window setFrame:frame display:YES]; [alert setAlertStyle:NSAlertStyleWarning]; - [alert.window makeKeyWindow]; + [alert_window makeKeyWindow]; if ([alert runModal] == NSAlertFirstButtonReturn) { // Launch the Security and Preferences pane with Accessibility selected. [[NSWorkspace sharedWorkspace]
diff --git a/remoting/host/win/rdp_client.cc b/remoting/host/win/rdp_client.cc index e7b57d2..01a7caf 100644 --- a/remoting/host/win/rdp_client.cc +++ b/remoting/host/win/rdp_client.cc
@@ -139,7 +139,7 @@ return; } - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(!rdp_client_window_); DCHECK(!self_.get());
diff --git a/services/BUILD.gn b/services/BUILD.gn index 238f76e..86a1b09 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn
@@ -55,6 +55,7 @@ deps += [ "//services/data_decoder/public/cpp/android:safe_json_java", "//services/device:java", + "//services/media_session/public/cpp/android:media_session_java", # Some tests make network requests. "//net/android:net_java",
diff --git a/services/device/screen_orientation/screen_orientation_listener_android.cc b/services/device/screen_orientation/screen_orientation_listener_android.cc index 776a065..9927b33 100644 --- a/services/device/screen_orientation/screen_orientation_listener_android.cc +++ b/services/device/screen_orientation/screen_orientation_listener_android.cc
@@ -23,7 +23,7 @@ : listeners_count_(0) {} ScreenOrientationListenerAndroid::~ScreenOrientationListenerAndroid() { - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); if (listeners_count_ > 0) { Java_ScreenOrientationListener_startAccurateListening( base::android::AttachCurrentThread()); @@ -31,7 +31,7 @@ } void ScreenOrientationListenerAndroid::Start() { - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); ++listeners_count_; if (listeners_count_ == 1) { // Ask the ScreenOrientationListener (Java) to start accurately listening to @@ -43,7 +43,7 @@ } void ScreenOrientationListenerAndroid::Stop() { - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); DCHECK(listeners_count_ > 0); --listeners_count_; if (listeners_count_ == 0) {
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index f3a2a989..8f0f97b5 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -247,10 +247,8 @@ } } -// Populates and returns an AccountInfo object corresponding to |account_id|, -// which must be an account with a refresh token. AccountInfo IdentityManager::GetAccountInfoForAccountWithRefreshToken( - std::string account_id) const { + const std::string& account_id) const { DCHECK(HasAccountWithRefreshToken(account_id)); AccountInfo account_info =
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index c8d82f3..d126526c 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -344,7 +344,7 @@ // Populates and returns an AccountInfo object corresponding to |account_id|, // which must be an account with a refresh token. AccountInfo GetAccountInfoForAccountWithRefreshToken( - std::string account_id) const; + const std::string& account_id) const; // SigninManagerBase::Observer: void GoogleSigninSucceeded(const AccountInfo& account_info) override;
diff --git a/services/identity/public/objc/identity_manager_observer_bridge.h b/services/identity/public/objc/identity_manager_observer_bridge.h index 32c5ae65..262d6e5 100644 --- a/services/identity/public/objc/identity_manager_observer_bridge.h +++ b/services/identity/public/objc/identity_manager_observer_bridge.h
@@ -23,7 +23,10 @@ // these semantics. - (void)onPrimaryAccountSet:(const AccountInfo&)primaryAccountInfo; +- (void)onPrimaryAccountSet:(const AccountInfo&)primaryAccountInfo + withPassword:(const std::string&)password; - (void)onPrimaryAccountCleared:(const AccountInfo&)previousPrimaryAccountInfo; +- (void)onPrimaryAccountSigninFailed:(const GoogleServiceAuthError&)error; - (void)onRefreshTokenUpdatedForAccount:(const AccountInfo&)accountInfo valid:(BOOL)isValid; - (void)onRefreshTokenRemovedForAccount:(const std::string&)accountId; @@ -47,8 +50,12 @@ // IdentityManager::Observer. void OnPrimaryAccountSet(const AccountInfo& primary_account_info) override; + void OnPrimaryAccountSetWithPassword(const AccountInfo& primary_account_info, + const std::string& password) override; void OnPrimaryAccountCleared( const AccountInfo& previous_primary_account_info) override; + void OnPrimaryAccountSigninFailed( + const GoogleServiceAuthError& error) override; void OnRefreshTokenUpdatedForAccount(const AccountInfo& account_info, bool is_valid) override; void OnRefreshTokenRemovedForAccount(const std::string& account_id) override;
diff --git a/services/identity/public/objc/identity_manager_observer_bridge.mm b/services/identity/public/objc/identity_manager_observer_bridge.mm index 0f4d265..aaf0b6b 100644 --- a/services/identity/public/objc/identity_manager_observer_bridge.mm +++ b/services/identity/public/objc/identity_manager_observer_bridge.mm
@@ -28,6 +28,15 @@ } } +void IdentityManagerObserverBridge::OnPrimaryAccountSetWithPassword( + const AccountInfo& primary_account_info, + const std::string& password) { + if ([delegate_ respondsToSelector:@selector(onPrimaryAccountSet: + withPassword:)]) { + [delegate_ onPrimaryAccountSet:primary_account_info withPassword:password]; + } +} + void IdentityManagerObserverBridge::OnPrimaryAccountCleared( const AccountInfo& previous_primary_account_info) { if ([delegate_ respondsToSelector:@selector(onPrimaryAccountCleared:)]) { @@ -35,6 +44,13 @@ } } +void IdentityManagerObserverBridge::OnPrimaryAccountSigninFailed( + const GoogleServiceAuthError& error) { + if ([delegate_ respondsToSelector:@selector(onPrimaryAccountSigninFailed:)]) { + [delegate_ onPrimaryAccountSigninFailed:error]; + } +} + void IdentityManagerObserverBridge::OnRefreshTokenUpdatedForAccount( const AccountInfo& account_info, bool is_valid) {
diff --git a/services/media_session/DEPS b/services/media_session/DEPS new file mode 100644 index 0000000..b8a225f --- /dev/null +++ b/services/media_session/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+jni", + "+ui/gfx", +]
diff --git a/services/media_session/public/cpp/BUILD.gn b/services/media_session/public/cpp/BUILD.gn index 0f6b88d7..3b90b616 100644 --- a/services/media_session/public/cpp/BUILD.gn +++ b/services/media_session/public/cpp/BUILD.gn
@@ -6,15 +6,24 @@ output_name = "media_session_cpp" sources = [ + "media_metadata.cc", + "media_metadata.h", "switches.cc", "switches.h", ] deps = [ "//base", + "//ui/gfx/geometry", + "//url", ] configs += [ "//build/config/compiler:wexit_time_destructors" ] + if (is_android) { + sources += [ "media_metadata_android.cc" ] + deps += [ "android:media_session_jni_headers" ] + } + defines = [ "IS_MEDIA_SESSION_CPP_IMPL" ] }
diff --git a/services/media_session/public/cpp/OWNERS b/services/media_session/public/cpp/OWNERS new file mode 100644 index 0000000..7aebc8abb --- /dev/null +++ b/services/media_session/public/cpp/OWNERS
@@ -0,0 +1,4 @@ +per-file *_mojom_traits*.*=set noparent +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/services/media_session/public/cpp/android/BUILD.gn b/services/media_session/public/cpp/android/BUILD.gn new file mode 100644 index 0000000..c7de4d2a --- /dev/null +++ b/services/media_session/public/cpp/android/BUILD.gn
@@ -0,0 +1,22 @@ +# 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("//build/config/android/rules.gni") + +_jni_sources = + [ "java/src/org/chromium/services/media_session/MediaMetadata.java" ] + +generate_jni("media_session_jni_headers") { + sources = _jni_sources + jni_package = "media_metadata" +} + +if (current_toolchain == default_toolchain) { + android_library("media_session_java") { + deps = [ + "//base:base_java", + ] + java_files = _jni_sources + } +}
diff --git a/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java b/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java new file mode 100644 index 0000000..ce06aae --- /dev/null +++ b/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java
@@ -0,0 +1,232 @@ +// 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. + +package org.chromium.services.media_session; + +import android.graphics.Rect; +import android.support.annotation.NonNull; +import android.text.TextUtils; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +import java.util.ArrayList; +import java.util.List; + +/** + * The MediaMetadata class carries information related to a media session. It is + * the Java counterpart of media_session::MediaMetadata. + */ +@JNINamespace("media_session") +public final class MediaMetadata { + /** + * The MediaImage class carries the artwork information in MediaMetadata. It is the Java + * counterpart of media_session::MediaMetadata::MediaImage. + */ + public static final class MediaImage { + @NonNull + private String mSrc; + + private String mType; + + @NonNull + private List<Rect> mSizes = new ArrayList<Rect>(); + + /** + * Creates a new MediaImage. + */ + public MediaImage(@NonNull String src, @NonNull String type, @NonNull List<Rect> sizes) { + mSrc = src; + mType = type; + mSizes = sizes; + } + + /** + * @return The URL of this MediaImage. + */ + @NonNull + public String getSrc() { + return mSrc; + } + + /** + * @return The MIME type of this MediaImage. + */ + public String getType() { + return mType; + } + + /** + * @return The hinted sizes of this MediaImage. + */ + public List<Rect> getSizes() { + return mSizes; + } + + /** + * Sets the URL of this MediaImage. + */ + public void setSrc(@NonNull String src) { + mSrc = src; + } + + /** + * Sets the MIME type of this MediaImage. + */ + public void setType(@NonNull String type) { + mType = type; + } + + /** + * Sets the sizes of this MediaImage. + */ + public void setSizes(@NonNull List<Rect> sizes) { + mSizes = sizes; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (!(obj instanceof MediaImage)) return false; + + MediaImage other = (MediaImage) obj; + return TextUtils.equals(mSrc, other.mSrc) && TextUtils.equals(mType, other.mType) + && mSizes.equals(other.mSizes); + } + + /** + * @return The hash code of this {@link MediaImage}. The method uses the same algorithm in + * {@link java.util.List} for combinine hash values. + */ + @Override + public int hashCode() { + int result = mSrc.hashCode(); + result = 31 * result + mType.hashCode(); + result = 31 * result + mSizes.hashCode(); + return result; + } + } + + @NonNull + private String mTitle; + + @NonNull + private String mArtist; + + @NonNull + private String mAlbum; + + @NonNull + private List<MediaImage> mArtwork = new ArrayList<MediaImage>(); + + /** + * Returns the title associated with the media session. + */ + public String getTitle() { + return mTitle; + } + + /** + * Returns the artist name associated with the media session. + */ + public String getArtist() { + return mArtist; + } + + /** + * Returns the album name associated with the media session. + */ + public String getAlbum() { + return mAlbum; + } + + public List<MediaImage> getArtwork() { + return mArtwork; + } + + /** + * Sets the title associated with the media session. + * @param title The title to use for the media session. + */ + public void setTitle(@NonNull String title) { + mTitle = title; + } + + /** + * Sets the arstist name associated with the media session. + * @param arstist The artist name to use for the media session. + */ + public void setArtist(@NonNull String artist) { + mArtist = artist; + } + + /** + * Sets the album name associated with the media session. + * @param album The album name to use for the media session. + */ + public void setAlbum(@NonNull String album) { + mAlbum = album; + } + + /** + * Create a new {@link MediaImage} from the C++ code, and add it to the Metadata. + * @param src The URL of the image. + * @param type The MIME type of the image. + * @param flattenedSizes The flattened array of image sizes. In native code, it is of type + * `std::vector<gfx::Size>` before flattening. + */ + @CalledByNative + private void createAndAddMediaImage(String src, String type, int[] flattenedSizes) { + assert(flattenedSizes.length % 2) == 0; + List<Rect> sizes = new ArrayList<Rect>(); + for (int i = 0; (i + 1) < flattenedSizes.length; i += 2) { + sizes.add(new Rect(0, 0, flattenedSizes[i], flattenedSizes[i + 1])); + } + mArtwork.add(new MediaImage(src, type, sizes)); + } + + /** + * Creates a new MediaMetadata from the C++ code. This is exactly like the + * constructor below apart that it can be called by native code. + */ + @CalledByNative + private static MediaMetadata create(String title, String artist, String album) { + return new MediaMetadata(title, artist, album); + } + + /** + * Creates a new MediaMetadata. + */ + public MediaMetadata(@NonNull String title, @NonNull String artist, @NonNull String album) { + mTitle = title; + mArtist = artist; + mAlbum = album; + } + + /** + * Comparing MediaMetadata is expensive and should be used sparingly + */ + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (!(obj instanceof MediaMetadata)) return false; + + MediaMetadata other = (MediaMetadata) obj; + return TextUtils.equals(mTitle, other.mTitle) && TextUtils.equals(mArtist, other.mArtist) + && TextUtils.equals(mAlbum, other.mAlbum) && mArtwork.equals(other.mArtwork); + } + + /** + * @return The hash code of this {@link MediaMetadata}. The method uses the same algorithm in + * {@link java.util.List} for combinine hash values. + */ + @Override + public int hashCode() { + int result = mTitle.hashCode(); + result = 31 * result + mArtist.hashCode(); + result = 31 * result + mAlbum.hashCode(); + result = 31 * result + mArtwork.hashCode(); + return result; + } +}
diff --git a/services/media_session/public/cpp/media_metadata.cc b/services/media_session/public/cpp/media_metadata.cc new file mode 100644 index 0000000..79468f9 --- /dev/null +++ b/services/media_session/public/cpp/media_metadata.cc
@@ -0,0 +1,38 @@ +// 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 "services/media_session/public/cpp/media_metadata.h" + +#include <algorithm> +#include <iterator> + +namespace media_session { + +MediaMetadata::MediaImage::MediaImage() = default; + +MediaMetadata::MediaImage::MediaImage(const MediaImage& other) = default; + +MediaMetadata::MediaImage::~MediaImage() = default; + +bool MediaMetadata::MediaImage::operator==( + const MediaMetadata::MediaImage& other) const { + return src == other.src && type == other.type && sizes == other.sizes; +} + +MediaMetadata::MediaMetadata() = default; + +MediaMetadata::~MediaMetadata() = default; + +MediaMetadata::MediaMetadata(const MediaMetadata& other) = default; + +bool MediaMetadata::operator==(const MediaMetadata& other) const { + return title == other.title && artist == other.artist && + album == other.album && artwork == other.artwork; +} + +bool MediaMetadata::operator!=(const MediaMetadata& other) const { + return !(*this == other); +} + +} // namespace media_session
diff --git a/services/media_session/public/cpp/media_metadata.h b/services/media_session/public/cpp/media_metadata.h new file mode 100644 index 0000000..471737fa --- /dev/null +++ b/services/media_session/public/cpp/media_metadata.h
@@ -0,0 +1,81 @@ +// 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 SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_METADATA_H_ +#define SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_METADATA_H_ + +#include <vector> + +#include "base/component_export.h" +#include "base/strings/string16.h" +#include "build/build_config.h" +#include "ui/gfx/geometry/size.h" +#include "url/gurl.h" + +#if defined(OS_ANDROID) + +#include <jni.h> + +#include "base/android/scoped_java_ref.h" + +#endif // defined(OS_ANDROID) + +namespace media_session { + +// The MediaMetadata is a structure carrying information associated to a +// MediaSession. +struct COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaMetadata { + // Structure representing an MediaImage as per the MediaSession API, see: + // https://wicg.github.io/mediasession/#dictdef-mediaimage + struct COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaImage { + MediaImage(); + MediaImage(const MediaImage& other); + ~MediaImage(); + + bool operator==(const MediaImage& other) const; + + // MUST be a valid url. If an icon doesn't have a valid URL, it will not be + // successfully parsed, thus will not be represented in the Manifest. + GURL src; + + // Empty if the parsing failed or the field was not present. The type can be + // any string and doesn't have to be a valid image MIME type at this point. + // It is up to the consumer of the object to check if the type matches a + // supported type. + base::string16 type; + + // Empty if the parsing failed, the field was not present or empty. + // The special value "any" is represented by gfx::Size(0, 0). + std::vector<gfx::Size> sizes; + }; + + MediaMetadata(); + ~MediaMetadata(); + + MediaMetadata(const MediaMetadata& other); + + bool operator==(const MediaMetadata& other) const; + bool operator!=(const MediaMetadata& other) const; + +#if defined(OS_ANDROID) + // Creates a Java MediaMetadata instance and returns the JNI ref. + base::android::ScopedJavaLocalRef<jobject> CreateJavaObject(JNIEnv* env); +#endif + + // Title associated to the MediaSession. + base::string16 title; + + // Artist associated to the MediaSession. + base::string16 artist; + + // Album associated to the MediaSession. + base::string16 album; + + // Artwork associated to the MediaSession. + std::vector<MediaImage> artwork; +}; + +} // namespace media_session + +#endif // SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_METADATA_H_
diff --git a/services/media_session/public/cpp/media_metadata_android.cc b/services/media_session/public/cpp/media_metadata_android.cc new file mode 100644 index 0000000..346ebf2 --- /dev/null +++ b/services/media_session/public/cpp/media_metadata_android.cc
@@ -0,0 +1,60 @@ +// 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 "services/media_session/public/cpp/media_metadata.h" + +#include <string> +#include <vector> + +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "jni/MediaMetadata_jni.h" + +using base::android::ScopedJavaLocalRef; + +namespace media_session { + +namespace { + +std::vector<int> GetFlattenedSizeArray(const std::vector<gfx::Size>& sizes) { + std::vector<int> flattened_array; + flattened_array.reserve(2 * sizes.size()); + for (const auto& size : sizes) { + flattened_array.push_back(size.width()); + flattened_array.push_back(size.height()); + } + return flattened_array; +} + +} // anonymous namespace + +base::android::ScopedJavaLocalRef<jobject> MediaMetadata::CreateJavaObject( + JNIEnv* env) { + ScopedJavaLocalRef<jstring> j_title( + base::android::ConvertUTF16ToJavaString(env, title)); + ScopedJavaLocalRef<jstring> j_artist( + base::android::ConvertUTF16ToJavaString(env, artist)); + ScopedJavaLocalRef<jstring> j_album( + base::android::ConvertUTF16ToJavaString(env, album)); + + ScopedJavaLocalRef<jobject> j_metadata = + Java_MediaMetadata_create(env, j_title, j_artist, j_album); + + for (const auto& image : artwork) { + std::string src = image.src.spec(); + ScopedJavaLocalRef<jstring> j_src( + base::android::ConvertUTF8ToJavaString(env, src)); + ScopedJavaLocalRef<jstring> j_type( + base::android::ConvertUTF16ToJavaString(env, image.type)); + ScopedJavaLocalRef<jintArray> j_sizes( + base::android::ToJavaIntArray(env, GetFlattenedSizeArray(image.sizes))); + + Java_MediaMetadata_createAndAddMediaImage(env, j_metadata, j_src, j_type, + j_sizes); + } + + return j_metadata; +} + +} // namespace media_session
diff --git a/services/media_session/public/cpp/media_session.typemap b/services/media_session/public/cpp/media_session.typemap new file mode 100644 index 0000000..94b58a9 --- /dev/null +++ b/services/media_session/public/cpp/media_session.typemap
@@ -0,0 +1,22 @@ +# 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. + +mojom = "//services/media_session/public/mojom/media_session.mojom" +public_headers = [ "//services/media_session/public/cpp/media_metadata.h" ] +traits_headers = + [ "//services/media_session/public/cpp/media_session_mojom_traits.h" ] +public_deps = [ + "//services/media_session/public/cpp", +] +deps = [ + "//ui/gfx/geometry/mojo:struct_traits", +] +type_mappings = [ + "media_session.mojom.MediaImage=media_session::MediaMetadata::MediaImage", + "media_session.mojom.MediaMetadata=media_session::MediaMetadata", +] +sources = [ + "//services/media_session/public/cpp/media_session_mojom_traits.cc", + "//services/media_session/public/cpp/media_session_mojom_traits.h", +]
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.cc b/services/media_session/public/cpp/media_session_mojom_traits.cc new file mode 100644 index 0000000..067c7a2 --- /dev/null +++ b/services/media_session/public/cpp/media_session_mojom_traits.cc
@@ -0,0 +1,45 @@ +// 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 "services/media_session/public/cpp/media_session_mojom_traits.h" + +#include "mojo/public/cpp/base/string16_mojom_traits.h" +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" +#include "url/mojom/url_gurl_mojom_traits.h" + +namespace mojo { + +// static +bool StructTraits<media_session::mojom::MediaImageDataView, + media_session::MediaMetadata::MediaImage>:: + Read(media_session::mojom::MediaImageDataView data, + media_session::MediaMetadata::MediaImage* out) { + if (!data.ReadSrc(&out->src)) + return false; + if (!data.ReadType(&out->type)) + return false; + if (!data.ReadSizes(&out->sizes)) + return false; + + return true; +} + +// static +bool StructTraits<media_session::mojom::MediaMetadataDataView, + media_session::MediaMetadata>:: + Read(media_session::mojom::MediaMetadataDataView data, + media_session::MediaMetadata* out) { + if (!data.ReadTitle(&out->title)) + return false; + if (!data.ReadArtist(&out->artist)) + return false; + if (!data.ReadAlbum(&out->album)) + return false; + if (!data.ReadArtwork(&out->artwork)) + return false; + + return true; +} + +} // namespace mojo
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.h b/services/media_session/public/cpp/media_session_mojom_traits.h new file mode 100644 index 0000000..b49dfa7 --- /dev/null +++ b/services/media_session/public/cpp/media_session_mojom_traits.h
@@ -0,0 +1,63 @@ +// 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 SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_ +#define SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_ + +#include "services/media_session/public/mojom/media_session.mojom.h" + +namespace mojo { + +template <> +struct StructTraits<media_session::mojom::MediaImageDataView, + media_session::MediaMetadata::MediaImage> { + static const GURL& src( + const media_session::MediaMetadata::MediaImage& image) { + return image.src; + } + + static const base::string16& type( + const media_session::MediaMetadata::MediaImage& image) { + return image.type; + } + + static const std::vector<gfx::Size>& sizes( + const media_session::MediaMetadata::MediaImage& image) { + return image.sizes; + } + + static bool Read(media_session::mojom::MediaImageDataView data, + media_session::MediaMetadata::MediaImage* out); +}; + +template <> +struct StructTraits<media_session::mojom::MediaMetadataDataView, + media_session::MediaMetadata> { + static const base::string16& title( + const media_session::MediaMetadata& metadata) { + return metadata.title; + } + + static const base::string16& artist( + const media_session::MediaMetadata& metadata) { + return metadata.artist; + } + + static const base::string16& album( + const media_session::MediaMetadata& metadata) { + return metadata.album; + } + + static const std::vector<media_session::MediaMetadata::MediaImage>& artwork( + const media_session::MediaMetadata& metadata) { + return metadata.artwork; + } + + static bool Read(media_session::mojom::MediaMetadataDataView data, + media_session::MediaMetadata* out); +}; + +} // namespace mojo + +#endif // SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_
diff --git a/services/media_session/public/cpp/typemaps.gni b/services/media_session/public/cpp/typemaps.gni new file mode 100644 index 0000000..280e7e0 --- /dev/null +++ b/services/media_session/public/cpp/typemaps.gni
@@ -0,0 +1,5 @@ +# 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. + +typemaps = [ "//services/media_session/public/cpp/media_session.typemap" ]
diff --git a/services/media_session/public/mojom/BUILD.gn b/services/media_session/public/mojom/BUILD.gn index 21d319d..45b215a 100644 --- a/services/media_session/public/mojom/BUILD.gn +++ b/services/media_session/public/mojom/BUILD.gn
@@ -4,10 +4,7 @@ import("//mojo/public/tools/bindings/mojom.gni") -mojom_component("mojom") { - output_prefix = "media_session_public_mojom" - macro_prefix = "MEDIA_SESSION_PUBLIC_MOJOM" - +mojom("mojom") { sources = [ "audio_focus.mojom", "constants.mojom", @@ -17,5 +14,15 @@ public_deps = [ "//mojo/public/mojom/base", + "//ui/gfx/geometry/mojo", + "//url/mojom:url_mojom_gurl", ] + + # The blink variant of the Device Service mojom are depended on by the + # blink platform target. All blink variant mojoms use WTF types, which are + # part of the blink platform component. In order to avoid a dependency cycle, + # these targets must be part of that component. + export_class_attribute_blink = "BLINK_PLATFORM_EXPORT" + export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" + export_header_blink = "third_party/blink/public/platform/web_common.h" }
diff --git a/services/media_session/public/mojom/media_session.mojom b/services/media_session/public/mojom/media_session.mojom index da252ec..ba5cba6 100644 --- a/services/media_session/public/mojom/media_session.mojom +++ b/services/media_session/public/mojom/media_session.mojom
@@ -4,7 +4,10 @@ module media_session.mojom; +import "mojo/public/mojom/base/string16.mojom"; import "mojo/public/mojom/base/time.mojom"; +import "ui/gfx/geometry/mojo/geometry.mojom"; +import "url/mojom/url.mojom"; // Next MinVersion: 2 @@ -25,6 +28,23 @@ kSeekForward, }; +// Album art in MediaMetadata +// Spec: https://wicg.github.io/mediasession/ +struct MediaImage { + url.mojom.Url src; + mojo_base.mojom.String16 type; + array<gfx.mojom.Size> sizes; +}; + +// MediaMetadata +// Spec: https://wicg.github.io/mediasession/ +struct MediaMetadata { + mojo_base.mojom.String16 title; + mojo_base.mojom.String16 artist; + mojo_base.mojom.String16 album; + array<MediaImage> artwork; +}; + // Contains state information about a MediaSession. struct MediaSessionInfo { [Extensible]
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 8ba9734e..d3a0ddfc 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -157,6 +157,10 @@ #define SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION #endif +#ifndef SK_IGNORE_LINEONLY_AA_CONVEX_PATH_OPTS +#define SK_IGNORE_LINEONLY_AA_CONVEX_PATH_OPTS +#endif + // Max. verb count for paths rendered by the edge-AA tessellating path renderer. #define GR_AA_TESSELLATOR_MAX_VERB_COUNT 100
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index 17ff1580..0754f51 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -113,7 +113,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 25, @@ -204,7 +204,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 7, @@ -250,7 +250,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 7,
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 42b0c8e4..384be7e 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -31,7 +31,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -72,7 +72,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -113,7 +113,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -154,7 +154,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -197,7 +197,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 16, @@ -244,7 +244,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 16, @@ -291,7 +291,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 8, @@ -334,7 +334,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -373,7 +373,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -412,7 +412,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -453,7 +453,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -494,7 +494,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -535,7 +535,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 5, @@ -578,7 +578,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -617,7 +617,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -656,7 +656,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -696,7 +696,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 5, @@ -749,7 +749,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 19, @@ -795,7 +795,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -836,7 +836,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -877,7 +877,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -918,7 +918,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -959,7 +959,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1000,7 +1000,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1043,7 +1043,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 16, @@ -1098,7 +1098,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1137,7 +1137,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1176,7 +1176,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1215,7 +1215,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1254,7 +1254,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1293,7 +1293,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1334,7 +1334,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 26, @@ -1377,7 +1377,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1416,7 +1416,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1457,7 +1457,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 26, @@ -1500,7 +1500,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1539,7 +1539,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1578,7 +1578,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1617,7 +1617,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1656,7 +1656,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1697,7 +1697,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 26, @@ -1745,7 +1745,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1784,7 +1784,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1823,7 +1823,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1862,7 +1862,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 1, @@ -1903,7 +1903,7 @@ } ], "expiration": 7200, - "hard_timeout": 25200, + "hard_timeout": 36000, "ignore_task_failure": false, "io_timeout": 1800, "shards": 26,
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index a1c7e481..481c0e7 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -37,7 +37,6 @@ # https://crbug.com/721403 -ContextMenuBrowserTest.DataSaverOpenOrigImageInNewTab --DataReductionProxyBrowsertest.UMAMetricsRecorded # NOTE: if adding an exclusion for an existing failure (e.g. additional test for # feature X that is already not working), please add it beside the existing
diff --git a/testing/libfuzzer/clusterfuzz.md b/testing/libfuzzer/clusterfuzz.md index 8349c659..4005a2a 100644 --- a/testing/libfuzzer/clusterfuzz.md +++ b/testing/libfuzzer/clusterfuzz.md
@@ -8,7 +8,7 @@ ## Status Links * [Buildbot] - status of all libFuzzer builds. -* [ClusterFuzz Fuzzer Status] - fuzzing metrics. +* [ClusterFuzz Fuzzer Stats] - fuzzing metrics. * [Code Coverage] - code coverage of libFuzzer targets in Chrome. * [ClusterFuzz libFuzzer Logs] - individual fuzz target run logs. * [Corpus GCS Bucket] - current corpus for each fuzz target. Can be used to @@ -27,7 +27,7 @@ * Fuzzing corpus is maintained for each fuzz target in [Corpus GCS Bucket]. Once a day, the corpus is minimized to reduce number of duplicates and/or reduce effect of parasitic coverage. -* [ClusterFuzz Fuzzer Status] displays fuzzer runtime metrics as well as +* [ClusterFuzz Fuzzer Stats] displays fuzzer runtime metrics as well as provides links to crashes and coverage reports.
diff --git a/third_party/blink/public/web/web_media_player_action.h b/third_party/blink/public/web/web_media_player_action.h index 674b900b..95fd0f72 100644 --- a/third_party/blink/public/web/web_media_player_action.h +++ b/third_party/blink/public/web/web_media_player_action.h
@@ -34,20 +34,21 @@ namespace blink { struct WebMediaPlayerAction { - enum Type { - kUnknown, + enum class Type { kPlay, kMute, kLoop, kControls, kPictureInPicture, - kTypeLast = kPictureInPicture + kMaxValue = kPictureInPicture }; - Type type; - bool enable; + Type type = Type::kMaxValue; + bool enable = false; - WebMediaPlayerAction() : type(kUnknown), enable(false) {} + // The default constructor is needed for IPC. If this is moved to mojo, we may + // be able to delete it and enforce that parameters are used. + WebMediaPlayerAction() = default; WebMediaPlayerAction(Type type, bool enable) : type(type), enable(enable) {} };
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 2d787fe..40e1f65 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
@@ -2498,23 +2498,23 @@ HTMLMediaElement* media_element = ToHTMLMediaElement(node); switch (action.type) { - case WebMediaPlayerAction::kPlay: + case WebMediaPlayerAction::Type::kPlay: if (action.enable) media_element->Play(); else media_element->pause(); break; - case WebMediaPlayerAction::kMute: + case WebMediaPlayerAction::Type::kMute: media_element->setMuted(action.enable); break; - case WebMediaPlayerAction::kLoop: + case WebMediaPlayerAction::Type::kLoop: media_element->SetLoop(action.enable); break; - case WebMediaPlayerAction::kControls: + case WebMediaPlayerAction::Type::kControls: media_element->SetBooleanAttribute(html_names::kControlsAttr, action.enable); break; - case WebMediaPlayerAction::kPictureInPicture: + case WebMediaPlayerAction::Type::kPictureInPicture: DCHECK(media_element->IsHTMLVideoElement()); if (action.enable) { PictureInPictureController::From(node->GetDocument()) @@ -2524,8 +2524,6 @@ .ExitPictureInPicture(ToHTMLVideoElement(media_element), nullptr); } break; - default: - NOTREACHED(); } }
diff --git a/third_party/blink/renderer/core/timing/performance_mark.idl b/third_party/blink/renderer/core/timing/performance_mark.idl index 24439659..2dd8d60f 100644 --- a/third_party/blink/renderer/core/timing/performance_mark.idl +++ b/third_party/blink/renderer/core/timing/performance_mark.idl
@@ -25,6 +25,7 @@ // https://w3c.github.io/user-timing/#performancemark +[Exposed=(Window,Worker)] interface PerformanceMark : PerformanceEntry { [CallWith=ScriptState, RuntimeEnabled=CustomUserTiming] readonly attribute any detail; };
diff --git a/third_party/blink/renderer/core/timing/performance_measure.idl b/third_party/blink/renderer/core/timing/performance_measure.idl index b9546a6..2ee528c 100644 --- a/third_party/blink/renderer/core/timing/performance_measure.idl +++ b/third_party/blink/renderer/core/timing/performance_measure.idl
@@ -25,6 +25,7 @@ // https://w3c.github.io/user-timing/#performancemeasure +[Exposed=(Window,Worker)] interface PerformanceMeasure : PerformanceEntry { [CallWith=ScriptState, RuntimeEnabled=CustomUserTiming] readonly attribute any detail; };
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc index 8dfa49b0..1cb3c98 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -619,6 +619,17 @@ return IsActive(play_state_); } +base::Optional<double> WorkletAnimation::CurrentTime() const { + bool is_null; + double timeline_time = timeline_->currentTime(is_null); + if (is_null) + return base::nullopt; + if (timeline_->IsScrollTimeline()) + return timeline_time; + DCHECK(start_time_); + return timeline_time - start_time_->InSecondsF(); +} + void WorkletAnimation::UpdateInputState( AnimationWorkletDispatcherInput* input_state) { if (!running_on_main_thread_) { @@ -632,8 +643,8 @@ // ScrollTimeline animation doesn't require start_time_ to be set. DCHECK(start_time_ || timeline_->IsScrollTimeline()); DCHECK(last_current_time_ || !was_active); - bool is_null; - double current_time = timeline_->currentTime(is_null); + double current_time = + CurrentTime().value_or(std::numeric_limits<double>::quiet_NaN()); bool did_time_change = !last_current_time_ || current_time != last_current_time_->InSecondsF(); @@ -641,10 +652,7 @@ // is resolved, we apply the last current time to the animation if the scroll // timeline becomes newly inactive. See https://crbug.com/906050. last_current_time_ = base::TimeDelta::FromSecondsD(current_time); - if (!was_active && is_active) { - // TODO(yigu): current_time should be offset by start_time_ for animations - // with document timeline. https://crbug.com/905405. input_state->Add( {id_, std::string(animator_name_.Ascii().data(), animator_name_.length()),
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation.h b/third_party/blink/renderer/modules/animationworklet/worklet_animation.h index 015121b3..e680957 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation.h +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation.h
@@ -145,6 +145,7 @@ void SetPlayState(const Animation::AnimationPlayState& state) { play_state_ = state; } + base::Optional<double> CurrentTime() const; unsigned sequence_number_;
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc index 225c08077..e9239db 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
@@ -10,7 +10,9 @@ #include "third_party/blink/renderer/core/animation/element_animations.h" #include "third_party/blink/renderer/core/animation/keyframe_effect.h" #include "third_party/blink/renderer/core/animation/keyframe_effect_model.h" +#include "third_party/blink/renderer/core/animation/scroll_timeline.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" @@ -39,12 +41,16 @@ return KeyframeEffect::Create(element, CreateEffectModel(), timing); } -WorkletAnimation* CreateWorkletAnimation(ScriptState* script_state, - Element* element) { +WorkletAnimation* CreateWorkletAnimation( + ScriptState* script_state, + Element* element, + ScrollTimeline* scroll_timeline = nullptr) { AnimationEffectOrAnimationEffectSequence effects; AnimationEffect* effect = CreateKeyframeEffect(element); effects.SetAnimationEffect(effect); DocumentTimelineOrScrollTimeline timeline; + if (scroll_timeline) + timeline.SetScrollTimeline(scroll_timeline); scoped_refptr<SerializedScriptValue> options; ScriptState::Scope scope(script_state); @@ -95,4 +101,84 @@ EXPECT_EQ(true, style->HasCurrentOpacityAnimation()); } +TEST_F(WorkletAnimationTest, + CurrentTimeFromDocumentTimelineIsOffsetByStartTime) { + GetDocument().GetAnimationClock().ResetTimeForTesting(); + double error = base::TimeDelta::FromMicrosecondsD(1).InMillisecondsF(); + WorkletAnimationId id = worklet_animation_->GetWorkletAnimationId(); + base::TimeTicks first_ticks = + base::TimeTicks() + base::TimeDelta::FromMillisecondsD(111); + base::TimeTicks second_ticks = + base::TimeTicks() + base::TimeDelta::FromMillisecondsD(111 + 123.4); + + GetDocument().GetAnimationClock().UpdateTime(first_ticks); + DummyExceptionStateForTesting exception_state; + worklet_animation_->play(exception_state); + worklet_animation_->UpdateCompositingState(); + + std::unique_ptr<AnimationWorkletDispatcherInput> state = + std::make_unique<AnimationWorkletDispatcherInput>(); + worklet_animation_->UpdateInputState(state.get()); + // First state request sets the start time and thus current time should be 0. + std::unique_ptr<AnimationWorkletInput> input = + state->TakeWorkletState(id.scope_id); + EXPECT_NEAR(0, input->added_and_updated_animations[0].current_time, error); + state.reset(new AnimationWorkletDispatcherInput); + GetDocument().GetAnimationClock().UpdateTime(second_ticks); + worklet_animation_->UpdateInputState(state.get()); + input = state->TakeWorkletState(id.scope_id); + EXPECT_NEAR(123.4, input->updated_animations[0].current_time, error); +} + +TEST_F(WorkletAnimationTest, + CurrentTimeFromScrollTimelineNotOffsetByStartTime) { + SetBodyInnerHTML(R"HTML( + <style> + #scroller { overflow: scroll; width: 100px; height: 100px; } + #spacer { width: 200px; height: 200px; } + </style> + <div id='scroller'> + <div id ='spacer'></div> + </div> + )HTML"); + + LayoutBoxModelObject* scroller = + ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller")); + ASSERT_TRUE(scroller); + ASSERT_TRUE(scroller->HasOverflowClip()); + PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea(); + ASSERT_TRUE(scrollable_area); + scrollable_area->SetScrollOffset(ScrollOffset(0, 20), kProgrammaticScroll); + ScrollTimelineOptions* options = ScrollTimelineOptions::Create(); + DoubleOrScrollTimelineAutoKeyword time_range = + DoubleOrScrollTimelineAutoKeyword::FromDouble(100); + options->setTimeRange(time_range); + options->setScrollSource(GetElementById("scroller")); + ScrollTimeline* scroll_timeline = + ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION); + WorkletAnimation* worklet_animation = + CreateWorkletAnimation(GetScriptState(), element_, scroll_timeline); + WorkletAnimationId id = worklet_animation->GetWorkletAnimationId(); + + DummyExceptionStateForTesting exception_state; + worklet_animation->play(exception_state); + worklet_animation->UpdateCompositingState(); + + double error = base::TimeDelta::FromMicrosecondsD(1).InMillisecondsF(); + scrollable_area->SetScrollOffset(ScrollOffset(0, 40), kProgrammaticScroll); + std::unique_ptr<AnimationWorkletDispatcherInput> state = + std::make_unique<AnimationWorkletDispatcherInput>(); + worklet_animation->UpdateInputState(state.get()); + std::unique_ptr<AnimationWorkletInput> input = + state->TakeWorkletState(id.scope_id); + + EXPECT_NEAR(40, input->added_and_updated_animations[0].current_time, error); + state.reset(new AnimationWorkletDispatcherInput); + + scrollable_area->SetScrollOffset(ScrollOffset(0, 70), kProgrammaticScroll); + worklet_animation->UpdateInputState(state.get()); + input = state->TakeWorkletState(id.scope_id); + EXPECT_NEAR(70, input->updated_animations[0].current_time, error); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index f781963..ba938f7 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -262,6 +262,7 @@ visibility = [ "//components/pdf/common:interfaces_blink", "//services/device/public/mojom:mojom_blink", + "//services/media_session/public/mojom:mojom_blink", "//third_party/blink/*", "//url/mojom:url_mojom_origin_blink", "//url/mojom:url_mojom_gurl_blink",
diff --git a/third_party/blink/renderer/platform/bindings/string_resource.cc b/third_party/blink/renderer/platform/bindings/string_resource.cc index ea7f246..6ff600c 100644 --- a/third_party/blink/renderer/platform/bindings/string_resource.cc +++ b/third_party/blink/renderer/platform/bindings/string_resource.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/platform/bindings/string_resource.h" +#include <type_traits> + #include "third_party/blink/renderer/platform/bindings/v8_binding.h" namespace blink { @@ -92,11 +94,28 @@ v8::String::ExternalStringResourceBase* resource = v8_string->GetExternalStringResourceBase(&encoding); if (LIKELY(!!resource)) { + // Inheritance: + // - V8 side: v8::String::ExternalStringResourceBase + // -> v8::External{One,}ByteStringResource + // - Both: StringResource{8,16}Base inherits from the matching v8 class. + static_assert(std::is_base_of<v8::String::ExternalOneByteStringResource, + StringResource8Base>::value, + ""); + static_assert(std::is_base_of<v8::String::ExternalStringResource, + StringResource16Base>::value, + ""); + static_assert( + std::is_base_of<StringResourceBase, StringResource8Base>::value, ""); + static_assert( + std::is_base_of<StringResourceBase, StringResource16Base>::value, ""); + // Then StringResource{8,16}Base allows to go from one ancestry path to + // the other one. Even though it's empty, removing it causes UB, see + // crbug.com/909796. StringResourceBase* base; if (encoding == v8::String::ONE_BYTE_ENCODING) - base = static_cast<StringResource8*>(resource); + base = static_cast<StringResource8Base*>(resource); else - base = static_cast<StringResource16*>(resource); + base = static_cast<StringResource16Base*>(resource); return StringTraits<StringType>::FromStringResource(base); } }
diff --git a/third_party/blink/renderer/platform/bindings/string_resource.h b/third_party/blink/renderer/platform/bindings/string_resource.h index d6f50c1..7874392 100644 --- a/third_party/blink/renderer/platform/bindings/string_resource.h +++ b/third_party/blink/renderer/platform/bindings/string_resource.h
@@ -114,18 +114,40 @@ DISALLOW_COPY_AND_ASSIGN(StringResourceBase); }; -class StringResource16 final : public StringResourceBase, - public v8::String::ExternalStringResource { +// Even though StringResource{8,16}Base are effectively empty in release mode, +// they are needed as they serve as a common ancestor to Parkable and regular +// strings. +// +// See the comment in |ToBlinkString()|'s implementation for the rationale. +class StringResource16Base : public StringResourceBase, + public v8::String::ExternalStringResource { public: - explicit StringResource16(const String& string) : StringResourceBase(string) { - DCHECK(!string.Is8Bit()); - } - - explicit StringResource16(const AtomicString& string) + explicit StringResource16Base(const String& string) : StringResourceBase(string) { DCHECK(!string.Is8Bit()); } + explicit StringResource16Base(const AtomicString& string) + : StringResourceBase(string) { + DCHECK(!string.Is8Bit()); + } + + explicit StringResource16Base(const ParkableString& parkable_string) + : StringResourceBase(parkable_string) { + DCHECK(!parkable_string.Is8Bit()); + } + + DISALLOW_COPY_AND_ASSIGN(StringResource16Base); +}; + +class StringResource16 final : public StringResource16Base { + public: + explicit StringResource16(const String& string) + : StringResource16Base(string) {} + + explicit StringResource16(const AtomicString& string) + : StringResource16Base(string) {} + size_t length() const override { return plain_string_.Impl()->length(); } const uint16_t* data() const override { return reinterpret_cast<const uint16_t*>( @@ -135,34 +157,10 @@ DISALLOW_COPY_AND_ASSIGN(StringResource16); }; -class StringResource8 final : public StringResourceBase, - public v8::String::ExternalOneByteStringResource { - public: - explicit StringResource8(const String& string) : StringResourceBase(string) { - DCHECK(string.Is8Bit()); - } - - explicit StringResource8(const AtomicString& string) - : StringResourceBase(string) { - DCHECK(string.Is8Bit()); - } - - size_t length() const override { return plain_string_.Impl()->length(); } - const char* data() const override { - return reinterpret_cast<const char*>(plain_string_.Impl()->Characters8()); - } - - DISALLOW_COPY_AND_ASSIGN(StringResource8); -}; - -class ParkableStringResource16 final - : public StringResourceBase, - public v8::String::ExternalStringResource { +class ParkableStringResource16 final : public StringResource16Base { public: explicit ParkableStringResource16(const ParkableString& string) - : StringResourceBase(string) { - DCHECK(!parkable_string_.Is8Bit()); - } + : StringResource16Base(string) {} bool IsCacheable() const override { return !parkable_string_.may_be_parked(); @@ -181,14 +179,47 @@ DISALLOW_COPY_AND_ASSIGN(ParkableStringResource16); }; -class ParkableStringResource8 final - : public StringResourceBase, - public v8::String::ExternalOneByteStringResource { +class StringResource8Base : public StringResourceBase, + public v8::String::ExternalOneByteStringResource { + public: + explicit StringResource8Base(const String& string) + : StringResourceBase(string) { + DCHECK(string.Is8Bit()); + } + + explicit StringResource8Base(const AtomicString& string) + : StringResourceBase(string) { + DCHECK(string.Is8Bit()); + } + + explicit StringResource8Base(const ParkableString& parkable_string) + : StringResourceBase(parkable_string) { + DCHECK(parkable_string.Is8Bit()); + } + + DISALLOW_COPY_AND_ASSIGN(StringResource8Base); +}; + +class StringResource8 final : public StringResource8Base { + public: + explicit StringResource8(const String& string) + : StringResource8Base(string) {} + + explicit StringResource8(const AtomicString& string) + : StringResource8Base(string) {} + + size_t length() const override { return plain_string_.Impl()->length(); } + const char* data() const override { + return reinterpret_cast<const char*>(plain_string_.Impl()->Characters8()); + } + + DISALLOW_COPY_AND_ASSIGN(StringResource8); +}; + +class ParkableStringResource8 final : public StringResource8Base { public: explicit ParkableStringResource8(const ParkableString& string) - : StringResourceBase(string) { - DCHECK(parkable_string_.Is8Bit()); - } + : StringResource8Base(string) {} bool IsCacheable() const override { return !parkable_string_.may_be_parked();
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc index 8662b0d..12a4511 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
@@ -32,6 +32,7 @@ #include <memory> +#include "build/build_config.h" #include "third_party/blink/renderer/platform/fonts/font_cache.h" #include "third_party/blink/renderer/platform/fonts/font_global_context.h" #include "third_party/blink/renderer/platform/fonts/font_platform_data.h" @@ -334,11 +335,13 @@ WTF::Partitions::FastFree); } +#if !defined(OS_MACOSX) static void DeleteTypefaceStream(void* stream_asset_ptr) { SkStreamAsset* stream_asset = reinterpret_cast<SkStreamAsset*>(stream_asset_ptr); delete stream_asset; } +#endif hb_face_t* HarfBuzzFace::CreateFace() { hb_face_t* face = nullptr; @@ -347,6 +350,11 @@ ("Blink.Fonts.HarfBuzzFaceZeroCopyAccess")); SkTypeface* typeface = platform_data_->Typeface(); CHECK(typeface); + // The attempt of doing zero copy-mmaped memory access to the font blobs does + // not work efficiently on Mac, since what is returned from + // typeface->openStream is a synthesized font assembled from copying all font + // tables on Mac. See the implementation of SkTypeface_Mac::onOpenStream. +#if !defined(OS_MACOSX) int ttc_index = 0; SkStreamAsset* typeface_stream = typeface->openStream(&ttc_index); if (typeface_stream && typeface_stream->getMemoryBase()) { @@ -358,6 +366,7 @@ hb_blob_destroy); face = hb_face_create(face_blob.get(), ttc_index); } +#endif // Fallback to table copies if there is no in-memory access. if (!face) {
diff --git a/third_party/blink/renderer/platform/graphics/contiguous_container.h b/third_party/blink/renderer/platform/graphics/contiguous_container.h index dafbd72..3430f74c 100644 --- a/third_party/blink/renderer/platform/graphics/contiguous_container.h +++ b/third_party/blink/renderer/platform/graphics/contiguous_container.h
@@ -13,7 +13,6 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/compiler.h" #include "third_party/blink/renderer/platform/wtf/type_traits.h"
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_list.h b/third_party/blink/renderer/platform/graphics/paint/display_item_list.h index c45c6934..c6c87fb3 100644 --- a/third_party/blink/renderer/platform/graphics/paint/display_item_list.h +++ b/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
@@ -8,7 +8,6 @@ #include "third_party/blink/renderer/platform/graphics/contiguous_container.h" #include "third_party/blink/renderer/platform/graphics/paint/display_item.h" #include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h" -#include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" namespace blink {
diff --git a/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h b/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h index 024a318..51af360 100644 --- a/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h +++ b/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
@@ -11,7 +11,7 @@ namespace blink { -// A special DrawingDisplayItem containing hit test data. +// A special DisplayItem containing hit test data. class PLATFORM_EXPORT HitTestDisplayItem final : public DisplayItem { public: HitTestDisplayItem(const DisplayItemClient& client,
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h index 4797ec2..469ae05 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h +++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
@@ -20,7 +20,6 @@ #include "third_party/blink/renderer/platform/graphics/paint/paint_chunker.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" -#include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h"
diff --git a/third_party/blink/renderer/platform/heap/sparse_heap_bitmap.h b/third_party/blink/renderer/platform/heap/sparse_heap_bitmap.h index f8134a0..70654e7 100644 --- a/third_party/blink/renderer/platform/heap/sparse_heap_bitmap.h +++ b/third_party/blink/renderer/platform/heap/sparse_heap_bitmap.h
@@ -11,7 +11,6 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/platform/heap/blink_gc.h" #include "third_party/blink/renderer/platform/heap/heap_page.h" -#include "third_party/blink/renderer/platform/wtf/alignment.h" namespace blink {
diff --git a/third_party/blink/renderer/platform/transforms/transformation_matrix.h b/third_party/blink/renderer/platform/transforms/transformation_matrix.h index 40d7cf7..816565a 100644 --- a/third_party/blink/renderer/platform/transforms/transformation_matrix.h +++ b/third_party/blink/renderer/platform/transforms/transformation_matrix.h
@@ -34,7 +34,6 @@ #include "build/build_config.h" #include "third_party/blink/renderer/platform/geometry/float_point.h" #include "third_party/blink/renderer/platform/geometry/float_point_3d.h" -#include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace gfx {
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn index bd54b90..108a748 100644 --- a/third_party/blink/renderer/platform/wtf/BUILD.gn +++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -45,7 +45,6 @@ jumbo_component("wtf") { sources = [ "address_sanitizer.h", - "alignment.h", "allocator.cc", "allocator.h", "allocator/partition_allocator.cc",
diff --git a/third_party/blink/renderer/platform/wtf/alignment.h b/third_party/blink/renderer/platform/wtf/alignment.h deleted file mode 100644 index f4d782f..0000000 --- a/third_party/blink/renderer/platform/wtf/alignment.h +++ /dev/null
@@ -1,48 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_ALIGNMENT_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_ALIGNMENT_H_ - -#include <stdint.h> -#include "build/build_config.h" - -namespace WTF { - -#if defined(COMPILER_GCC) -#define WTF_ALIGN_OF(type) __alignof__(type) -#define WTF_ALIGNED(variable_type, variable, n) \ - variable_type variable __attribute__((__aligned__(n))) -#elif defined(COMPILER_MSVC) -#define WTF_ALIGN_OF(type) __alignof(type) -#define WTF_ALIGNED(variable_type, variable, n) \ - __declspec(align(n)) variable_type variable -#else -#error WTF_ALIGN macros need alignment control. -#endif - -template <uintptr_t mask> -inline bool IsAlignedTo(const void* pointer) { - return !(reinterpret_cast<uintptr_t>(pointer) & mask); -} - -} // namespace WTF - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_ALIGNMENT_H_
diff --git a/third_party/blink/renderer/platform/wtf/hash_table.h b/third_party/blink/renderer/platform/wtf/hash_table.h index b3fe06f..f99180d 100644 --- a/third_party/blink/renderer/platform/wtf/hash_table.h +++ b/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -26,7 +26,6 @@ #include <memory> #include "base/numerics/checked_math.h" -#include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
diff --git a/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h b/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h index 84b044c..96b56b4 100644 --- a/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h +++ b/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h
@@ -24,7 +24,6 @@ #include <stdint.h> #include "build/build_config.h" -#include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/cpu.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/text/unicode.h" @@ -117,7 +116,9 @@ const uintptr_t kMemoryAccessMask = kMemoryAccessSize - 1; size_t i = 0; - for (; i < length && !IsAlignedTo<kMemoryAccessMask>(&source[i]); ++i) { + for (; i < length && + reinterpret_cast<uintptr_t>(&source[i]) & kMemoryAccessMask; + ++i) { DCHECK(!(source[i] & 0xff00)); destination[i] = static_cast<LChar>(source[i]); } @@ -155,7 +156,7 @@ if (length >= (2 * kMemoryAccessSize) - 1) { // Prefix: align dst on 64 bits. const uintptr_t kMemoryAccessMask = kMemoryAccessSize - 1; - while (!IsAlignedTo<kMemoryAccessMask>(destination)) + while (reinterpret_cast<uintptr_t>(destination) & kMemoryAccessMask) *destination++ = static_cast<LChar>(*source++); // Vector interleaved unpack, we only store the lower 8 bits.
diff --git a/third_party/blink/renderer/platform/wtf/vector.h b/third_party/blink/renderer/platform/wtf/vector.h index 4ead5355f..1646a56b 100644 --- a/third_party/blink/renderer/platform/wtf/vector.h +++ b/third_party/blink/renderer/platform/wtf/vector.h
@@ -30,7 +30,6 @@ #include "base/macros.h" #include "base/template_util.h" #include "build/build_config.h" -#include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h" #include "third_party/blink/renderer/platform/wtf/construct_traits.h" #include "third_party/blink/renderer/platform/wtf/container_annotations.h"
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG index 8ddad89..12fdeeb46 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -358,16 +358,6 @@ crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Pass ] crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ] crbug.com/591099 virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/acquire-display-lock.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/acquire-on-no-containment-added.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/context-suspend-resume-empty.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/context-suspend-resume.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/context-two-suspend-resume.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/element-retained-by-context.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/multiple-schedules-recursive.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/multiple-schedules.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/simple-schedule-1.html [ Pass Timeout ] -crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/simple-schedule-2.html [ Pass Timeout ] crbug.com/591099 virtual/exotic-color-space/ [ Skip ] crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ] crbug.com/591099 virtual/fractional_scrolling/fast/scrolling/fractional-scroll-offset-iframe-fixed-position.html [ Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService b/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService index b26e9c8..3b51d5c09 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService +++ b/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService
@@ -1,4 +1,4 @@ -# These tests currently fail when run with --enable-features=NetworkSerivce +# These tests currently fail when run with --enable-features=NetworkService # See https://crbug.com/729849 Bug(none) http/tests/security/cors-rfc1918 [ Crash Timeout ] @@ -25,14 +25,16 @@ crbug.com/898306 http/tests/inspector-protocol/network/raw-headers-for-protected-document.js [ Failure ] crbug.com/898306 http/tests/inspector-protocol/network/security-info-on-response.js [ Failure ] -# Sheriff 2018-11-29 -crbug.com/910011 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-404.https.html [ Failure ] -crbug.com/910011 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-cache-validation.https.html [ Failure ] -crbug.com/910011 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-redirect.https.html [ Failure ] -crbug.com/910011 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-subdomain-dns-failure.https.html [ Failure ] -crbug.com/910011 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-success-with-subdomain-policy.https.html [ Failure ] -crbug.com/910011 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-success.https.html [ Failure ] -crbug.com/910011 virtual/outofblink-cors/http/tests/security/isolatedWorld/cross-origin-xhr.html [ Failure ] -crbug.com/910011 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub.html [ Failure ] -crbug.com/910011 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub.html [ Failure ] -crbug.com/910011 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub.html [ Failure ] +# Reports aren't allowed under content_shell NS +crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-404.https.html [ Failure ] +crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-cache-validation.https.html [ Failure ] +crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-redirect.https.html [ Failure ] +crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-subdomain-dns-failure.https.html [ Failure ] +crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-success-with-subdomain-policy.https.html [ Failure ] +crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-success.https.html [ Failure ] +crbug.com/910212 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub.html [ Failure ] +crbug.com/910212 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub.html [ Failure ] +crbug.com/910212 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub.html [ Failure ] + +# Uncategorized failure. +Bug(none) virtual/outofblink-cors/http/tests/security/isolatedWorld/cross-origin-xhr.html [ Failure ]
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations index 4884794..d58aca11 100644 --- a/third_party/blink/web_tests/LeakExpectations +++ b/third_party/blink/web_tests/LeakExpectations
@@ -87,6 +87,7 @@ crbug.com/862029 [ Linux ] virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-window-filter.js [ Pass Leak ] crbug.com/733494 [ Linux ] media/autoplay/document-user-activation.html [ Pass Leak ] +crbug.com/733494 [ Linux ] virtual/video-surface-layer/media/autoplay/document-user-activation.html [ Pass Leak ] ########################################################################### # WARNING: Memory leaks must be fixed asap. Sheriff is expected to revert #
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 7bd7573..76682e2 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1899,6 +1899,24 @@ # ====== Out of Blink CORS related tests END ====== + +# ====== Backdrop-filter related tests BEGIN ====== +# These are known failures - this feature is still being implemented +crbug.com/497522 css3/filters/backdrop-filter-boundary.html [ Failure ] +crbug.com/497522 css3/filters/backdrop-filter-bleeding.html [ Failure ] +crbug.com/497522 css3/filters/backdrop-filter-svg.html [ Failure ] +crbug.com/497522 css3/filters/backdrop-filter-plus-filter.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-border-radius.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-clip-rect.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-paint-order.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html [ Failure ] +# ====== Backdrop-filter related tests END ====== + + crbug.com/492664 [ Linux ] external/wpt/css/css-writing-modes/box-offsets-rel-pos-vlr-005.xht [ Failure ] crbug.com/492664 [ Linux ] external/wpt/css/css-writing-modes/box-offsets-rel-pos-vrl-004.xht [ Failure ] crbug.com/492664 [ Mac ] external/wpt/css/css-writing-modes/bidi-embed-002.html [ Failure ] @@ -2998,6 +3016,7 @@ crbug.com/893480 external/wpt/infrastructure/testdriver/actions/multiDevice.html [ Failure Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-004.html [ Failure ] crbug.com/626703 [ Mac10.13 ] external/wpt/preload/dynamic-adding-preload-imagesrcset.tentative.html [ Timeout ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-capitalize-033.html [ Failure ] crbug.com/626703 virtual/outofblink-cors/external/wpt/fetch/content-type/response.window.html [ Timeout ] @@ -4484,7 +4503,6 @@ crbug.com/873454 css3/filters/effect-reference-image-hw.html [ Failure Pass ] # Sheriff failures 2018-08-15 -crbug.com/874500 [ Mac ] media/media-ended.html [ Pass Timeout ] crbug.com/874567 [ Mac ] svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Pass Failure ] crbug.com/874837 [ Win ] ietestcenter/css3/bordersbackgrounds/background-attachment-local-scrolling.htm [ Pass Failure ] crbug.com/874866 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/modern/doubletap-to-jump-backwards-at-start.html [ Pass Timeout ] @@ -5605,6 +5623,7 @@ crbug.com/886566 http/tests/csspaint/invalidation-content-image.html [ Pass Timeout ] # Enable AnimationWorklet tests for mainthread +crbug.com/785940 [ Release ] animations/animationworklet/worklet-animation-local-time-after-duration.html [ Pass Failure ] crbug.com/887659 virtual/threaded/animations/animationworklet/worklet-animation-local-time-after-duration.html [ Failure ] # Sheriff 2018-09-25 @@ -5704,17 +5723,6 @@ # Test is flaky under load crbug.com/904389 http/tests/preload/delaying_onload_link_preload_after_discovery.html [ Failure Pass ] -# These are known failures, being implemented -crbug.com/497522 css3/filters/backdrop-filter-boundary.html [ Failure ] -crbug.com/497522 css3/filters/backdrop-filter-bleeding.html [ Failure ] -crbug.com/497522 css3/filters/backdrop-filter-svg.html [ Failure ] -crbug.com/497522 css3/filters/backdrop-filter-plus-filter.html [ Failure ] -crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html [ Failure ] -crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-border-radius.html [ Failure ] -crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-clip-rect.html [ Failure ] -crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html [ Failure ] -crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-paint-order.html [ Failure ] - #Sheriff 2018-11-14 crbug.com/905694 [ Linux ] virtual/threaded/fast/scroll-behavior/smooth-scroll/scroll-during-selection.html [ Failure Pass ] crbug.com/905772 [ Linux ] virtual/sampling-heap-profiler/inspector-protocol/memory/sampling-native-profile-partition-alloc.js [ Failure Pass ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index 8ab9701..abfe2cd 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -52849,6 +52849,18 @@ {} ] ], + "css/css-multicol/multicol-span-all-004.html": [ + [ + "/css/css-multicol/multicol-span-all-004.html", + [ + [ + "/css/css-multicol/multicol-span-all-004-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-multicol/multicol-span-all-block-sibling-003.xht": [ [ "/css/css-multicol/multicol-span-all-block-sibling-003.xht", @@ -135907,6 +135919,11 @@ {} ] ], + "css/css-multicol/multicol-span-all-004-ref.html": [ + [ + {} + ] + ], "css/css-multicol/multicol-span-all-block-sibling-3-ref.xht": [ [ {} @@ -343238,6 +343255,14 @@ "fb4a508f50a309fb44c8d653cf84d1abdb22d838", "reftest" ], + "css/css-multicol/multicol-span-all-004-ref.html": [ + "beecede21082bf18500205e274a27ca53840594e", + "support" + ], + "css/css-multicol/multicol-span-all-004.html": [ + "e9165658c11fea62e4f714fc4643f33853e95500", + "reftest" + ], "css/css-multicol/multicol-span-all-block-sibling-003.xht": [ "bd2cdd6cdab0fc15c2e16e2237f6b025230332c4", "reftest"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-004-ref.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-004-ref.html new file mode 100644 index 0000000..beecede --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-004-ref.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Multi-column Layout Test Reference: column-span:all should act like column-span:none in different block formatting context</title> + <link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + + <style> + #column { + column-count: 3; + column-rule: 6px solid; + width: 600px; + outline: 1px solid black; + } + h3 { + column-span: none; + outline: 1px solid blue; + } + </style> + + <body onload="runTest();"> + <article id="column"> + <div>block1</div> + <div style="display: inline-block;"> + <h3>non-spanner</h3> + </div> + <div style="overflow: hidden;"> + <h3>non-spanner</h3> + </div> + <div style="column-span: all; outline: 1px solid green;"> + Spanner + <h3>non-spanner in a spanner</h3> + </div> + <div>block2</div> + </article> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-004.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-004.html new file mode 100644 index 0000000..e916565 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-004.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Multi-column Layout Test: column-span:all should act like column-span:none in different block formatting context</title> + <link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + <link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span"> + <link rel="match" href="multicol-span-all-004-ref.html"> + <meta name="assert" content="This test checks a column-span:all element should act like column-span: none if it's under different block formatting context."> + + <style> + #column { + column-count: 3; + column-rule: 6px solid; + width: 600px; + outline: 1px solid black; + } + h3 { + column-span: all; + outline: 1px solid blue; + } + </style> + + <body onload="runTest();"> + <article id="column"> + <div>block1</div> + <div style="display: inline-block;"> + <h3>non-spanner</h3> + </div> + <div style="overflow: hidden;"> + <h3>non-spanner</h3> + </div> + <div style="column-span: all; outline: 1px solid green;"> + Spanner + <h3>non-spanner in a spanner</h3> + </div> + <div>block2</div> + </article> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-ref.html index 26d7715..e0c76c0 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-ref.html
@@ -6,12 +6,11 @@ <div> - <p>Expected: A green box and an overlapping black box, with a magenta<br> - overlapping region.</p> + <p>Expected: Just a single green box.</p> </div> <div class="colorbox"></div> -<div class="box2outside"></div> -<div class="box2inside"></div> + + <style> .colorbox { @@ -22,21 +21,5 @@ left: 10px; top: 100px; } -.box2outside { - background: black; - position: absolute; - width: 100px; - height: 100px; - left: 60px; - top: 150px; -} -.box2inside { - background: #ff7fff; - position: absolute; - width: 50px; - height: 50px; - left: 60px; - top: 150px; -} </style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html index e3ad8a20..4cc5f33 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html
@@ -6,8 +6,7 @@ <link rel="match" href="backdrop-filter-basic-opacity-ref.html"> <div> - <p>Expected: A green box and an overlapping black box, with a magenta<br> - overlapping region.</p> + <p>Expected: Just a single green box.</p> </div> <div class="colorbox"> <div class="filterbox"></div> @@ -29,7 +28,7 @@ left: 50px; top: 50px; backdrop-filter: invert(1); - opacity: 0.5; + opacity: 0; } </style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip-ref.html new file mode 100644 index 0000000..1fa5967 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip-ref.html
@@ -0,0 +1,48 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>backdrop-filter: Should not filter outside of clip/scroll.</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> + + + +<div style="width:600px;"> + <p>Expected: A green box, overlapping red box, and a small, inset cyan box. The<br> + cyan should not extend to the bottom/right edges of the red box.</p> +</div> + +<div id="A"> + <div id="B"> + <div id="F"></div> + <div id="T"></div> + </div> +</div> + +<style> +div { + position:absolute; + width: 200px; + height: 200px; +} +#A { + overflow:hidden; + top: 110px; + left: 10px; +} +#B { + + background:green; +} +#F { + position:fixed; + background:#f008; + top:150px; + left:50px; +} +#T { + background:#c0e3ff; + top:90px; + left:90px; + width: 110px; + height: 110px; +} +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html new file mode 100644 index 0000000..2550eb1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>backdrop-filter: Should not filter outside of clip/scroll.</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> +<link rel="match" href="backdrop-filter-fixed-clip-ref.html"> + +<div style="width:600px;"> + <p>Expected: A green box, overlapping red box, and a small, inset cyan box. The<br> + cyan should not extend to the bottom/right edges of the red box.</p> +</div> + +<div id="A"> + <div id="B"> + <div id="F"></div> + <div id="T"></div> + </div> +</div> + +<style> +div { + position:absolute; + width: 200px; + height: 200px; +} +#A { + overflow:hidden; + top: 110px; + left: 10px; +} +#B { + opacity: 0.99999; + background:green; +} +#F { + position:fixed; + background:#f008; + top:150px; + left:50px; +} +#T { + background:#fff8; + top:90px; + left:90px; + backdrop-filter:invert(1); +} +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html new file mode 100644 index 0000000..c812d1f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>backdrop-filter: Should not filter outside parent stacking context.</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> +<link rel="match" href="backdrop-filter-isolation-ref.html"> + +<div class="outside"> + <div class="stacking-context"> + <div class="filter"> + </div> + </div> +</div> + + +<style> +div { + position: absolute; + width: 100px; + height: 100px; + background: green; +} +.outside { + top: 10px; + left: 10px; +} +.stacking-context { + position: fixed; + top: 10px; + left: 130px; +} +.filter { + width: 160px; + height: 160px; + top: 30px; + left: -90px; + opacity: 0.3; + backdrop-filter: invert(1); + background: yellow; +} +</style> +
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.serviceworker-expected.txt deleted file mode 100644 index e15018b..0000000 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.serviceworker-expected.txt +++ /dev/null
@@ -1,70 +0,0 @@ -This is a testharness.js-based test. -PASS idlharness -PASS idl_test setup -PASS Partial interface Performance: original interface defined -PASS PerformanceEntry interface: existence and properties of interface object -PASS PerformanceEntry interface object length -PASS PerformanceEntry interface object name -PASS PerformanceEntry interface: existence and properties of interface prototype object -PASS PerformanceEntry interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceEntry interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceEntry interface: attribute name -PASS PerformanceEntry interface: attribute entryType -PASS PerformanceEntry interface: attribute startTime -PASS PerformanceEntry interface: attribute duration -PASS PerformanceEntry interface: operation toJSON() -PASS PerformanceObserver interface: existence and properties of interface object -PASS PerformanceObserver interface object length -PASS PerformanceObserver interface object name -PASS PerformanceObserver interface: existence and properties of interface prototype object -PASS PerformanceObserver interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceObserver interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceObserver interface: operation observe(PerformanceObserverInit) -PASS PerformanceObserver interface: operation disconnect() -PASS PerformanceObserver interface: operation takeRecords() -PASS PerformanceObserver must be primary interface of observer -PASS Stringification of observer -PASS PerformanceObserver interface: observer must inherit property "observe(PerformanceObserverInit)" with the proper type -PASS PerformanceObserver interface: calling observe(PerformanceObserverInit) on observer with too few arguments must throw TypeError -PASS PerformanceObserver interface: observer must inherit property "disconnect()" with the proper type -PASS PerformanceObserver interface: observer must inherit property "takeRecords()" with the proper type -PASS PerformanceObserverEntryList interface: existence and properties of interface object -PASS PerformanceObserverEntryList interface object length -PASS PerformanceObserverEntryList interface object name -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceObserverEntryList interface: operation getEntries() -PASS PerformanceObserverEntryList interface: operation getEntriesByType(DOMString) -PASS PerformanceObserverEntryList interface: operation getEntriesByName(DOMString, DOMString) -PASS PerformanceObserverEntryList must be primary interface of entryList -PASS Stringification of entryList -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntries()" with the proper type -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntriesByType(DOMString)" with the proper type -PASS PerformanceObserverEntryList interface: calling getEntriesByType(DOMString) on entryList with too few arguments must throw TypeError -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntriesByName(DOMString, DOMString)" with the proper type -PASS PerformanceObserverEntryList interface: calling getEntriesByName(DOMString, DOMString) on entryList with too few arguments must throw TypeError -PASS Performance interface: operation getEntries() -PASS Performance interface: operation getEntriesByType(DOMString) -PASS Performance interface: operation getEntriesByName(DOMString, DOMString) -PASS Performance interface: performance must inherit property "getEntries()" with the proper type -PASS Performance interface: performance must inherit property "getEntriesByType(DOMString)" with the proper type -PASS Performance interface: calling getEntriesByType(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "getEntriesByName(DOMString, DOMString)" with the proper type -PASS Performance interface: calling getEntriesByName(DOMString, DOMString) on performance with too few arguments must throw TypeError -FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -PASS Stringification of mark -PASS PerformanceEntry interface: mark must inherit property "name" with the proper type -PASS PerformanceEntry interface: mark must inherit property "entryType" with the proper type -PASS PerformanceEntry interface: mark must inherit property "startTime" with the proper type -PASS PerformanceEntry interface: mark must inherit property "duration" with the proper type -PASS PerformanceEntry interface: mark must inherit property "toJSON()" with the proper type -PASS Test default toJSON operation of PerformanceMark -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.sharedworker-expected.txt deleted file mode 100644 index 0e17d27..0000000 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.sharedworker-expected.txt +++ /dev/null
@@ -1,71 +0,0 @@ -This is a testharness.js-based test. -Found 67 tests; 60 PASS, 7 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS idlharness -PASS idl_test setup -PASS Partial interface Performance: original interface defined -PASS PerformanceEntry interface: existence and properties of interface object -PASS PerformanceEntry interface object length -PASS PerformanceEntry interface object name -PASS PerformanceEntry interface: existence and properties of interface prototype object -PASS PerformanceEntry interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceEntry interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceEntry interface: attribute name -PASS PerformanceEntry interface: attribute entryType -PASS PerformanceEntry interface: attribute startTime -PASS PerformanceEntry interface: attribute duration -PASS PerformanceEntry interface: operation toJSON() -PASS PerformanceObserver interface: existence and properties of interface object -PASS PerformanceObserver interface object length -PASS PerformanceObserver interface object name -PASS PerformanceObserver interface: existence and properties of interface prototype object -PASS PerformanceObserver interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceObserver interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceObserver interface: operation observe(PerformanceObserverInit) -PASS PerformanceObserver interface: operation disconnect() -PASS PerformanceObserver interface: operation takeRecords() -PASS PerformanceObserver must be primary interface of observer -PASS Stringification of observer -PASS PerformanceObserver interface: observer must inherit property "observe(PerformanceObserverInit)" with the proper type -PASS PerformanceObserver interface: calling observe(PerformanceObserverInit) on observer with too few arguments must throw TypeError -PASS PerformanceObserver interface: observer must inherit property "disconnect()" with the proper type -PASS PerformanceObserver interface: observer must inherit property "takeRecords()" with the proper type -PASS PerformanceObserverEntryList interface: existence and properties of interface object -PASS PerformanceObserverEntryList interface object length -PASS PerformanceObserverEntryList interface object name -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceObserverEntryList interface: operation getEntries() -PASS PerformanceObserverEntryList interface: operation getEntriesByType(DOMString) -PASS PerformanceObserverEntryList interface: operation getEntriesByName(DOMString, DOMString) -PASS PerformanceObserverEntryList must be primary interface of entryList -PASS Stringification of entryList -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntries()" with the proper type -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntriesByType(DOMString)" with the proper type -PASS PerformanceObserverEntryList interface: calling getEntriesByType(DOMString) on entryList with too few arguments must throw TypeError -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntriesByName(DOMString, DOMString)" with the proper type -PASS PerformanceObserverEntryList interface: calling getEntriesByName(DOMString, DOMString) on entryList with too few arguments must throw TypeError -PASS Performance interface: operation getEntries() -PASS Performance interface: operation getEntriesByType(DOMString) -PASS Performance interface: operation getEntriesByName(DOMString, DOMString) -PASS Performance interface: performance must inherit property "getEntries()" with the proper type -PASS Performance interface: performance must inherit property "getEntriesByType(DOMString)" with the proper type -PASS Performance interface: calling getEntriesByType(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "getEntriesByName(DOMString, DOMString)" with the proper type -PASS Performance interface: calling getEntriesByName(DOMString, DOMString) on performance with too few arguments must throw TypeError -FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -PASS Stringification of mark -PASS PerformanceEntry interface: mark must inherit property "name" with the proper type -PASS PerformanceEntry interface: mark must inherit property "entryType" with the proper type -PASS PerformanceEntry interface: mark must inherit property "startTime" with the proper type -PASS PerformanceEntry interface: mark must inherit property "duration" with the proper type -PASS PerformanceEntry interface: mark must inherit property "toJSON()" with the proper type -PASS Test default toJSON operation of PerformanceMark -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.worker-expected.txt deleted file mode 100644 index 0e17d27..0000000 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/idlharness.any.worker-expected.txt +++ /dev/null
@@ -1,71 +0,0 @@ -This is a testharness.js-based test. -Found 67 tests; 60 PASS, 7 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS idlharness -PASS idl_test setup -PASS Partial interface Performance: original interface defined -PASS PerformanceEntry interface: existence and properties of interface object -PASS PerformanceEntry interface object length -PASS PerformanceEntry interface object name -PASS PerformanceEntry interface: existence and properties of interface prototype object -PASS PerformanceEntry interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceEntry interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceEntry interface: attribute name -PASS PerformanceEntry interface: attribute entryType -PASS PerformanceEntry interface: attribute startTime -PASS PerformanceEntry interface: attribute duration -PASS PerformanceEntry interface: operation toJSON() -PASS PerformanceObserver interface: existence and properties of interface object -PASS PerformanceObserver interface object length -PASS PerformanceObserver interface object name -PASS PerformanceObserver interface: existence and properties of interface prototype object -PASS PerformanceObserver interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceObserver interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceObserver interface: operation observe(PerformanceObserverInit) -PASS PerformanceObserver interface: operation disconnect() -PASS PerformanceObserver interface: operation takeRecords() -PASS PerformanceObserver must be primary interface of observer -PASS Stringification of observer -PASS PerformanceObserver interface: observer must inherit property "observe(PerformanceObserverInit)" with the proper type -PASS PerformanceObserver interface: calling observe(PerformanceObserverInit) on observer with too few arguments must throw TypeError -PASS PerformanceObserver interface: observer must inherit property "disconnect()" with the proper type -PASS PerformanceObserver interface: observer must inherit property "takeRecords()" with the proper type -PASS PerformanceObserverEntryList interface: existence and properties of interface object -PASS PerformanceObserverEntryList interface object length -PASS PerformanceObserverEntryList interface object name -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object's @@unscopables property -PASS PerformanceObserverEntryList interface: operation getEntries() -PASS PerformanceObserverEntryList interface: operation getEntriesByType(DOMString) -PASS PerformanceObserverEntryList interface: operation getEntriesByName(DOMString, DOMString) -PASS PerformanceObserverEntryList must be primary interface of entryList -PASS Stringification of entryList -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntries()" with the proper type -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntriesByType(DOMString)" with the proper type -PASS PerformanceObserverEntryList interface: calling getEntriesByType(DOMString) on entryList with too few arguments must throw TypeError -PASS PerformanceObserverEntryList interface: entryList must inherit property "getEntriesByName(DOMString, DOMString)" with the proper type -PASS PerformanceObserverEntryList interface: calling getEntriesByName(DOMString, DOMString) on entryList with too few arguments must throw TypeError -PASS Performance interface: operation getEntries() -PASS Performance interface: operation getEntriesByType(DOMString) -PASS Performance interface: operation getEntriesByName(DOMString, DOMString) -PASS Performance interface: performance must inherit property "getEntries()" with the proper type -PASS Performance interface: performance must inherit property "getEntriesByType(DOMString)" with the proper type -PASS Performance interface: calling getEntriesByType(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "getEntriesByName(DOMString, DOMString)" with the proper type -PASS Performance interface: calling getEntriesByName(DOMString, DOMString) on performance with too few arguments must throw TypeError -FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -PASS Stringification of mark -PASS PerformanceEntry interface: mark must inherit property "name" with the proper type -PASS PerformanceEntry interface: mark must inherit property "entryType" with the proper type -PASS PerformanceEntry interface: mark must inherit property "startTime" with the proper type -PASS PerformanceEntry interface: mark must inherit property "duration" with the proper type -PASS PerformanceEntry interface: mark must inherit property "toJSON()" with the proper type -PASS Test default toJSON operation of PerformanceMark -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.serviceworker-expected.txt deleted file mode 100644 index a389976..0000000 --- a/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.serviceworker-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -This is a testharness.js-based test. -PASS idl_test setup -PASS Partial interface Performance: original interface defined -FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -PASS Stringification of mark -FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure must be primary interface of measure assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -PASS Stringification of measure -PASS Performance interface: operation mark(DOMString) -PASS Performance interface: operation clearMarks(DOMString) -PASS Performance interface: operation measure(DOMString, DOMString, DOMString) -PASS Performance interface: operation clearMeasures(DOMString) -PASS Performance interface: performance must inherit property "mark(DOMString)" with the proper type -PASS Performance interface: calling mark(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "clearMarks(DOMString)" with the proper type -PASS Performance interface: calling clearMarks(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "measure(DOMString, DOMString, DOMString)" with the proper type -PASS Performance interface: calling measure(DOMString, DOMString, DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "clearMeasures(DOMString)" with the proper type -PASS Performance interface: calling clearMeasures(DOMString) on performance with too few arguments must throw TypeError -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt deleted file mode 100644 index a389976..0000000 --- a/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -This is a testharness.js-based test. -PASS idl_test setup -PASS Partial interface Performance: original interface defined -FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -PASS Stringification of mark -FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure must be primary interface of measure assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -PASS Stringification of measure -PASS Performance interface: operation mark(DOMString) -PASS Performance interface: operation clearMarks(DOMString) -PASS Performance interface: operation measure(DOMString, DOMString, DOMString) -PASS Performance interface: operation clearMeasures(DOMString) -PASS Performance interface: performance must inherit property "mark(DOMString)" with the proper type -PASS Performance interface: calling mark(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "clearMarks(DOMString)" with the proper type -PASS Performance interface: calling clearMarks(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "measure(DOMString, DOMString, DOMString)" with the proper type -PASS Performance interface: calling measure(DOMString, DOMString, DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "clearMeasures(DOMString)" with the proper type -PASS Performance interface: calling clearMeasures(DOMString) on performance with too few arguments must throw TypeError -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.worker-expected.txt deleted file mode 100644 index a389976..0000000 --- a/third_party/blink/web_tests/external/wpt/user-timing/idlharness.any.worker-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -This is a testharness.js-based test. -PASS idl_test setup -PASS Partial interface Performance: original interface defined -FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing -PASS Stringification of mark -FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -FAIL PerformanceMeasure must be primary interface of measure assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing -PASS Stringification of measure -PASS Performance interface: operation mark(DOMString) -PASS Performance interface: operation clearMarks(DOMString) -PASS Performance interface: operation measure(DOMString, DOMString, DOMString) -PASS Performance interface: operation clearMeasures(DOMString) -PASS Performance interface: performance must inherit property "mark(DOMString)" with the proper type -PASS Performance interface: calling mark(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "clearMarks(DOMString)" with the proper type -PASS Performance interface: calling clearMarks(DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "measure(DOMString, DOMString, DOMString)" with the proper type -PASS Performance interface: calling measure(DOMString, DOMString, DOMString) on performance with too few arguments must throw TypeError -PASS Performance interface: performance must inherit property "clearMeasures(DOMString)" with the proper type -PASS Performance interface: calling clearMeasures(DOMString) on performance with too few arguments must throw TypeError -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index d51f8401..f4b872a 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1000,6 +1000,12 @@ getter startTime method constructor method toJSON +interface PerformanceMark : PerformanceEntry + attribute @@toStringTag + method constructor +interface PerformanceMeasure : PerformanceEntry + attribute @@toStringTag + method constructor interface PerformanceObserver attribute @@toStringTag method constructor
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png index ca06a90..540a17bf 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png +++ b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png index 721093c..ccb72df 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png +++ b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 7f9645e6..da9ddec5 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png index ca06a90..540a17bf 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png index f4466ab..57327e60 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 7f9645e6..da9ddec5 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png index ca06a90..540a17bf 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png index f4466ab..57327e60 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 7f9645e6..da9ddec5 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png index ca06a90..540a17bf 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png index f4466ab..57327e60 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 7f9645e6..da9ddec5 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png index ca06a90..540a17bf 100644 --- a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png +++ b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png index f4466ab..57327e60 100644 --- a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png +++ b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 7f9645e6..da9ddec5 100644 --- a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png index ca06a90..540a17bf 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png index f4466ab..57327e60 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 7f9645e6..da9ddec5 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png index ca06a90..540a17bf 100644 --- a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png +++ b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png index 721093c..ccb72df 100644 --- a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png +++ b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 7f9645e6..da9ddec5 100644 --- a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png index ca06a90..540a17bf 100644 --- a/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png +++ b/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png b/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png index 721093c..ccb72df 100644 --- a/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png +++ b/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-patterns-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 7f9645e6..da9ddec5 100644 --- a/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/blink/web_tests/platform/win7/virtual/gpu/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 9f4d9b7..018698b 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -858,6 +858,12 @@ getter startTime method constructor method toJSON +interface PerformanceMark : PerformanceEntry + attribute @@toStringTag + method constructor +interface PerformanceMeasure : PerformanceEntry + attribute @@toStringTag + method constructor interface PerformanceObserver attribute @@toStringTag method constructor
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 03cb022..98e617f 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -807,6 +807,12 @@ [Worker] getter startTime [Worker] method constructor [Worker] method toJSON +[Worker] interface PerformanceMark : PerformanceEntry +[Worker] attribute @@toStringTag +[Worker] method constructor +[Worker] interface PerformanceMeasure : PerformanceEntry +[Worker] attribute @@toStringTag +[Worker] method constructor [Worker] interface PerformanceObserver [Worker] attribute @@toStringTag [Worker] method constructor
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt index a2fd963..13ce35b 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -802,6 +802,12 @@ [Worker] getter startTime [Worker] method constructor [Worker] method toJSON +[Worker] interface PerformanceMark : PerformanceEntry +[Worker] attribute @@toStringTag +[Worker] method constructor +[Worker] interface PerformanceMeasure : PerformanceEntry +[Worker] attribute @@toStringTag +[Worker] method constructor [Worker] interface PerformanceObserver [Worker] attribute @@toStringTag [Worker] method constructor
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 4f087bf0..a13e529 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -920,6 +920,12 @@ [Worker] getter startTime [Worker] method constructor [Worker] method toJSON +[Worker] interface PerformanceMark : PerformanceEntry +[Worker] attribute @@toStringTag +[Worker] method constructor +[Worker] interface PerformanceMeasure : PerformanceEntry +[Worker] attribute @@toStringTag +[Worker] method constructor [Worker] interface PerformanceObserver [Worker] attribute @@toStringTag [Worker] method constructor
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index f228369..dc8118d4 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -915,6 +915,12 @@ [Worker] getter startTime [Worker] method constructor [Worker] method toJSON +[Worker] interface PerformanceMark : PerformanceEntry +[Worker] attribute @@toStringTag +[Worker] method constructor +[Worker] interface PerformanceMeasure : PerformanceEntry +[Worker] attribute @@toStringTag +[Worker] method constructor [Worker] interface PerformanceObserver [Worker] attribute @@toStringTag [Worker] method constructor
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 8b73798..6e44b0b 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -1468,7 +1468,7 @@ 'libfuzzer', 'asan', 'debug_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], 'libfuzzer_chromeos_asan_release_bot': [ - 'libfuzzer', 'asan', 'chromeos_with_codecs', 'release_bot', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'asan', 'chromeos_with_codecs', 'shared_release_bot', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], 'libfuzzer_asan_release_bot': [ 'libfuzzer', 'asan', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 5051deb..504d0f0 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -20230,6 +20230,36 @@ </description> </action> +<action name="TrustedWebActivity.DisclosureAccepted"> + <owner>peconn@chromium.org</owner> + <owner>pshmakov@chromium.org</owner> + <owner>peter@chromium.org</owner> + <description> + Recorded when a user accepts the "Running in Chrome" disclosure + seen in a Trusted Web Activity. + </description> +</action> + +<action name="TrustedWebActivity.DisclosureShown"> + <owner>peconn@chromium.org</owner> + <owner>pshmakov@chromium.org</owner> + <owner>peter@chromium.org</owner> + <description> + Recorded when a user sees the "Running in Chrome" disclosure in a + Trusted Web Activity. + </description> +</action> + +<action name="TrustedWebActivity.OpenedSettingsViaManageSpace"> + <owner>peconn@chromium.org</owner> + <owner>pshmakov@chromium.org</owner> + <owner>peter@chromium.org</owner> + <description> + Recorded when site settings are opened via "Manage Space" button + in TWA client app's settings. + </description> +</action> + <action name="UI_DevTools_Connect"> <owner>weili@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index ac69d28..ebd5bce 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -46022,6 +46022,12 @@ </int> </enum> +<enum name="SettingsNavigationSources"> + <int value="0" label="Other"/> + <int value="1" label="From TWA clear data dialog"/> + <int value="2" label="From TWA manage space activity"/> +</enum> + <enum name="SettingsResetPromptConfigError"> <int value="1" label="Config Ok"/> <int value="2" label="Missing domain_hashes param"/> @@ -49499,6 +49505,7 @@ <int value="10" label="Browser Actions"/> <int value="11" label="Webapp Actions"/> <int value="12" label="Offline Content Suggestion"/> + <int value="13" label="Sites shown in Trusted Web Activities"/> </enum> <enum name="TabBackgroundLoadStatus"> @@ -50726,6 +50733,13 @@ <int value="80" label="TRIM_MEMORY_COMPLETE"/> </enum> +<enum name="TrustedWebActivityDelegatedNotificationSmallIconFallback"> + <int value="0" label="No fallback"/> + <int value="1" label="Fallback icon mot provided"/> + <int value="2" label="Fallback for Status Bar"/> + <int value="3" label="Fallback for Status Bar and content"/> +</enum> + <enum name="UIEventType"> <int value="0" label="Unknown"/> <int value="1" label="Touch released"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index e78e53c..7a342b6 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -104618,6 +104618,17 @@ <summary>Number of retries until the final response was recorded.</summary> </histogram> +<histogram name="SingleWebsitePreferences.NavigatedFromToReset" + enum="SettingsNavigationSources" expires_after="M78"> + <owner>pshmakov@chromium.org</owner> + <owner>peconn@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Logs which way had the user navigated into settings screens when they press + "Clear and Reset" button in settings of a single website. + </summary> +</histogram> + <histogram name="SiteEngagementService.DaysSinceLastShortcutLaunch" units="days"> <owner>calamity@chromium.org</owner> @@ -115630,6 +115641,62 @@ </summary> </histogram> +<histogram name="TrustedWebActivity.ClearDataDialogOnClearAppDataAccepted" + enum="Boolean" expires_after="M78"> + <owner>pshmakov@chromium.org</owner> + <owner>peconn@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Emits true if the user went to site settings from the dialog that is shown + after a Trusted Web Activity client app has had its data cleared. + </summary> +</histogram> + +<histogram name="TrustedWebActivity.ClearDataDialogOnUninstallAccepted" + enum="Boolean" expires_after="M78"> + <owner>pshmakov@chromium.org</owner> + <owner>peconn@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Emits true if the user went to site settings from the dialog that is shown + after a Trusted Web Activity client app has been uninstalled. + </summary> +</histogram> + +<histogram name="TrustedWebActivity.DelegatedNotificationSmallIconFallback" + enum="TrustedWebActivityDelegatedNotificationSmallIconFallback" + expires_after="M78"> + <owner>pshmakov@chromium.org</owner> + <owner>peconn@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Logs which kind of fallback for notification small icon was used for Trusted + Web Activity notification delegation. + </summary> +</histogram> + +<histogram name="TrustedWebActivity.TimeInVerifiedOrigin" units="ms" + expires_after="M78"> + <owner>pshmakov@chromium.org</owner> + <owner>peconn@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Time spent in a verified origin until navigating to an unverified one or + pausing the Trusted Web Activity. + </summary> +</histogram> + +<histogram name="TrustedWebActivity.TimeOutOfVerifiedOrigin" units="ms" + expires_after="M78"> + <owner>pshmakov@chromium.org</owner> + <owner>peconn@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Time spent out of verified origins until navigating back to a verified one + or pausing the Trusted Web Activity. + </summary> +</histogram> + <histogram name="TryScroll.SlowScroll" enum="ScrollThread"> <obsolete> Deprecated 02/2016 in Issue 1741103002, and replaced by
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 0874499d..1120328 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -5677,6 +5677,13 @@ <summary> True if there was a mismatch. </summary> + <aggregation> + <history> + <statistics> + <enumeration/> + </statistics> + </history> + </aggregation> </metric> </event>
diff --git a/tools/perf/conditionally_execute b/tools/perf/conditionally_execute deleted file mode 100755 index 15e1c35b..0000000 --- a/tools/perf/conditionally_execute +++ /dev/null
@@ -1,33 +0,0 @@ -#!/usr/bin/env vpython -# Copyright 2017 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -import argparse -import os -import subprocess -import sys - - -def main(args): - parser = argparse.ArgumentParser() - parser.add_argument( - '--gyp-condition', '-c', type=str, required=True, - help=('The gyp condition that acts as the switch. If the ' - 'condition is found in environment variable GYP_DEFINES, ' - 'this will execute the target script')) - options, script_args = parser.parse_known_args() - - # Make sure that we always execute target script with python. - if 'python' not in script_args[0]: - script_args.insert(0, sys.executable) - - # A typical GYP_DEFINES string looks s.t like "foo=a bar=1 baz=c". We - # tokenize the string before doing string matching. - gyp_defines = os.environ.get('GYP_DEFINES', '').split() - if options.gyp_condition in gyp_defines: - subprocess.check_call(script_args) - return 0 - - -if __name__ == '__main__': - main(sys.argv[1:])
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 4af7ceb..3eda9b29 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -956,7 +956,10 @@ # supports swarming. It doesn't hurt. 'can_use_on_swarming_builders': True, 'expiration': 2 * 60 * 60, # 2 hours pending max - 'hard_timeout': 7 * 60 * 60, # 7 hours timeout for full suite + # TODO(crbug.com/865538): once we have plenty of windows hardwares, + # to shards perf benchmarks on Win builders, reduce this hard timeout limit + # to ~2 hrs. + 'hard_timeout': 10 * 60 * 60, # 10 hours timeout for full suite 'ignore_task_failure': False, 'io_timeout': 30 * 60, # 30 minutes 'dimension_sets': [
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py index 89c9170..693ff68 100644 --- a/tools/perf/core/perf_data_generator_unittest.py +++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -121,7 +121,7 @@ 'can_use_on_swarming_builders': True, 'expiration': 7200, 'io_timeout': 1800, - 'hard_timeout': 25200, + 'hard_timeout': 36000, 'upload_test_results': True, 'dimension_sets': [[{'os': 'SkyNet', 'pool': 'T-RIP'}]], 'shards': 1 @@ -171,7 +171,7 @@ 'can_use_on_swarming_builders': True, 'expiration': 7200, 'io_timeout': 1800, - 'hard_timeout': 25200, + 'hard_timeout': 36000, 'upload_test_results': True, 'dimension_sets': [[{'os': 'SkyNet', 'pool': 'T-RIP'}]], 'shards': 26 @@ -220,7 +220,7 @@ 'can_use_on_swarming_builders': True, 'expiration': 7200, 'io_timeout': 1800, - 'hard_timeout': 25200, + 'hard_timeout': 36000, 'upload_test_results': True, 'dimension_sets': [[{'os': 'SkyNet', 'pool': 'T-RIP'}]], 'shards': 26
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 64e36823..573a4a6 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -10,11 +10,16 @@ # Benchmark: blink_perf.bindings crbug.com/882881 [ Nexus_5 ] blink_perf.bindings/structured-clone-json-deserialize.html [ Skip ] +crbug.com/910207 [ Nexus_5X ] blink_perf.bindings/structured-clone-json-deserialize.html [ Skip ] crbug.com/882881 [ Nexus_5 ] blink_perf.bindings/structured-clone-json-serialize.html [ Skip ] +crbug.com/910207 [ Nexus_5X ] blink_perf.bindings/structured-clone-json-serialize.html [ Skip ] crbug.com/882881 [ Nexus_5 ] blink_perf.bindings/structured-clone-long-string-deserialize.html [ Skip ] +crbug.com/910207 [ Nexus_5X ] blink_perf.bindings/structured-clone-long-string-deserialize.html [ Skip ] crbug.com/893209 [ Nexus5X_Webview ] blink_perf.bindings/structured-clone-long-string-deserialize.html [ Skip ] crbug.com/882881 [ Nexus_5 ] blink_perf.bindings/structured-clone-long-string-serialize.html [ Skip ] +crbug.com/910207 [ Nexus_5X ] blink_perf.bindings/structured-clone-long-string-serialize.html [ Skip ] crbug.com/882881 [ Nexus_5 ] blink_perf.bindings/worker-structured-clone-json-roundtrip.html [ Skip ] +crbug.com/910207 [ Nexus_5X ] blink_perf.bindings/worker-structured-clone-json-roundtrip.html [ Skip ] crbug.com/882881 [ Nexus_5 ] blink_perf.bindings/worker-structured-clone-json-to-worker.html [ Skip ] crbug.com/882881 [ Nexus_5X ] blink_perf.bindings/worker-structured-clone-json-to-worker.html [ Skip ] crbug.com/882881 [ Nexus_5 ] blink_perf.bindings/worker-structured-clone-json-from-worker.html [ Skip ] @@ -38,10 +43,12 @@ # Benchmark: blink_perf.layout crbug.com/551950 [ Android_Svelte ] blink_perf.layout/* [ Skip ] crbug.com/832686 [ Nexus_5 ] blink_perf.layout/subtree-detaching.html [ Skip ] +crbug.com/910207 [ Nexus_5X ] blink_perf.layout/subtree-detaching.html [ Skip ] # Benchmark: blink_perf.paint crbug.com/574483 [ Android_Svelte ] blink_perf.paint/* [ Skip ] crbug.com/799540 [ Nexus_5 ] blink_perf.paint/* [ Skip ] +crbug.com/910207 [ Nexus_5X ] blink_perf.paint/* [ Skip ] crbug.com/859979 [ Android_Webview ] blink_perf.paint/paint-offset-changes.html [ Skip ] crbug.com/901493 [ Nexus6_Webview ] blink_perf.paint/* [ Skip ] @@ -88,6 +95,7 @@ # Benchmark: loading.mobile crbug.com/656861 [ All ] loading.mobile/G1 [ Skip ] crbug.com/857108 [ Nexus_5 ] loading.mobile/G1_3g [ Skip ] +crbug.com/910207 [ Nexus_5X ] loading.mobile/G1_3g [ Skip ] [ Nexus_5X ] loading.mobile/Hongkiat [ Skip ] [ Nexus_5X ] loading.mobile/Dramaq [ Skip ] crbug.com/859597 [ All ] loading.mobile/Bradesco_3g [ Skip ] @@ -105,8 +113,10 @@ crbug.com/859597 [ All ] loading.mobile/YahooNews_3g [ Skip ] crbug.com/859597 [ Nexus_5 ] loading.mobile/FlipBoard_cold_3g [ Skip ] crbug.com/862663 [ Nexus_5 ] loading.mobile/GoogleBrazil_3g [ Skip ] +crbug.com/910207 [ Nexus_5X ] loading.mobile/GoogleBrazil_3g [ Skip ] crbug.com/862663 [ Nexus_5 ] loading.mobile/GoogleIndonesia_3g [ Skip ] crbug.com/862663 [ Nexus_5 ] loading.mobile/GoogleRedirectToGoogleJapan_3g [ Skip ] +crbug.com/910207 [ Nexus_5X ] loading.mobile/GoogleRedirectToGoogleJapan_3g [ Skip ] crbug.com/859597 [ Nexus_5X ] loading.mobile/FlipBoard_cold_3g [ Skip ] crbug.com/859597 [ Nexus_5 ] loading.mobile/Hongkiat_3g [ Skip ] crbug.com/859597 [ Nexus_5X ] loading.mobile/Hongkiat_3g [ Skip ] @@ -166,6 +176,7 @@ crbug.com/785286 [ Android_Webview ] rendering.mobile/smash_cat [ Skip ] crbug.com/785286 [ Android_Webview ] rendering.mobile/effect_games [ Skip ] crbug.com/364248 [ Nexus_5 ] rendering.mobile/geo_apis [ Skip ] +crbug.com/910207 [ Nexus_5X ] rendering.mobile/geo_apis [ Skip ] crbug.com/825234 [ Android_Webview ] rendering.mobile/bouncing_balls_shadow [ Skip ] crbug.com/350692 [ All ] rendering.mobile/microsoft_performance [ Skip ] crbug.com/755556 [ Android ] rendering.mobile/balls_css_key_frame_animations_composited_transform [ Skip ] @@ -204,6 +215,7 @@ crbug.com/893197 [ Nexus_5X ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ] crbug.com/865400 [ Pixel_2 ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ] crbug.com/874935 [ Nexus_5 ] rendering.mobile/yahoo_news_2018 [ Skip ] +crbug.com/910207 [ Nexus_5X ] rendering.mobile/yahoo_news_2018 [ Skip ] crbug.com/901526 [ All ] rendering.mobile/microsoft_fireflies [ Skip ] # Benchmark: rasterize_and_record_micro.top_25 @@ -212,8 +224,9 @@ crbug.com/873011 [ Android_Webview ] rasterize_and_record_micro.top_25/file://static_top_25/yahoonews.html [ Skip ] crbug.com/865400 [ Pixel_2 ] rasterize_and_record_micro.top_25/file://static_top_25/yahoonews.html [ Skip ] crbug.com/865400 [ Nexus_5 ] rasterize_and_record_micro.top_25/file://static_top_25/yahoonews.html [ Skip ] -crbug.com/892223 [ Nexus_5 ] rasterize_and_record_micro.top_25/file://static_top_25/yahoogames.html [ Skip ] crbug.com/865400 [ Nexus_5X ] rasterize_and_record_micro.top_25/file://static_top_25/yahoonews.html [ Skip ] +crbug.com/892223 [ Nexus_5 ] rasterize_and_record_micro.top_25/file://static_top_25/yahoogames.html [ Skip ] +crbug.com/910207 [ Nexus_5X ] rasterize_and_record_micro.top_25/file://static_top_25/yahoogames.html [ Skip ] crbug.com/875878 [ Nexus6_Webview ] rasterize_and_record_micro.top_25/file://static_top_25/yahoogames.html [ Skip ] # Benchmark: startup.mobile @@ -271,10 +284,13 @@ crbug.com/657433 [ Android ] system_health.memory_mobile/load:tools:gmail [ Skip ] crbug.com/708300 [ Android ] system_health.memory_mobile/browse:shopping:flipkart [ Skip ] crbug.com/784400 [ Nexus_5 ] system_health.memory_mobile/background:tools:gmail [ Skip ] +crbug.com/910207 [ Nexus_5X ] system_health.memory_mobile/background:tools:gmail [ Skip ] crbug.com/780779 [ Nexus_5 ] system_health.memory_mobile/browse:social:facebook [ Skip ] +crbug.com/910207 [ Nexus_5X ] system_health.memory_mobile/browse:social:facebook [ Skip ] crbug.com/738854 [ Nexus_5X ] system_health.memory_mobile/load:tools:drive [ Skip ] crbug.com/738854 [ Android_Webview ] system_health.memory_mobile/load:tools:drive [ Skip ] crbug.com/834905 [ Nexus_5 ] system_health.memory_mobile/browse:social:pinterest_infinite_scroll [ Skip ] +crbug.com/910207 [ Nexus_5X ] system_health.memory_mobile/browse:social:pinterest_infinite_scroll [ Skip ] crbug.com/843547 [ Android_Go ] system_health.memory_mobile/background:news:nytimes [ Skip ] crbug.com/852888 [ Nexus_5X ] system_health.memory_mobile/background:news:nytimes [ Skip ] crbug.com/859500 [ Nexus_5X ] system_health.memory_mobile/browse:social:tumblr_infinite_scroll [ Skip ] @@ -334,6 +350,7 @@ [ Android_Webview ] v8.browsing_mobile/browse:chrome:omnibox [ Skip ] [ Android_Webview ] v8.browsing_mobile/browse:chrome:newtab [ Skip ] crbug.com/815175 [ Nexus_5 ] v8.browsing_mobile/browse:chrome:newtab [ Skip ] +crbug.com/910207 [ Nexus_5X ] v8.browsing_mobile/browse:chrome:newtab [ Skip ] crbug.com/853212 [ Android_Webview ] v8.browsing_mobile/browse:media:youtube [ Skip ] crbug.com/853212 [ Android_Webview ] v8.browsing_mobile/browse:news:cnn [ Skip ] crbug.com/877648 [ Android_Go ] v8.browsing_mobile/browse:news:toi [ Skip ] @@ -347,6 +364,7 @@ [ Android_Webview ] v8.browsing_mobile-future/browse:chrome:omnibox [ Skip ] [ Android_Webview ] v8.browsing_mobile-future/browse:chrome:newtab [ Skip ] crbug.com/803465 [ Nexus_5 ] v8.browsing_mobile-future/browse:chrome:newtab [ Skip ] +crbug.com/910207 [ Nexus_5X ] v8.browsing_mobile-future/browse:chrome:newtab [ Skip ] crbug.com/799080 [ Nexus_5X Android_Webview ] v8.browsing_mobile-future/browse:social:facebook [ Skip ] crbug.com/799080 [ Nexus_5X Android_Webview ] v8.browsing_mobile-future/browse:social:facebook [ Skip ] crbug.com/875159 [ Win_10 ] v8.browsing_desktop-future/browse:social:facebook_infinite_scroll [ Skip ]
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc index e49dd8c..f5d2e406 100644 --- a/ui/base/clipboard/clipboard_win.cc +++ b/ui/base/clipboard/clipboard_win.cc
@@ -422,7 +422,7 @@ // ClipboardWin implementation. ClipboardWin::ClipboardWin() { - if (base::MessageLoopForUI::IsCurrent()) + if (base::MessageLoopCurrentForUI::IsSet()) clipboard_owner_.reset(new base::win::MessageWindow()); }
diff --git a/ui/base/ime/win/tsf_bridge.cc b/ui/base/ime/win/tsf_bridge.cc index b5b1ba2..eab3ad63 100644 --- a/ui/base/ime/win/tsf_bridge.cc +++ b/ui/base/ime/win/tsf_bridge.cc
@@ -131,7 +131,7 @@ TSFBridgeImpl::TSFBridgeImpl() = default; TSFBridgeImpl::~TSFBridgeImpl() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); if (!IsInitialized()) return; for (TSFDocumentMap::iterator it = tsf_document_map_.begin(); @@ -151,7 +151,7 @@ } bool TSFBridgeImpl::Initialize() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); if (client_id_ != TF_CLIENTID_NULL) { DVLOG(1) << "Already initialized."; return false; @@ -202,7 +202,7 @@ } void TSFBridgeImpl::OnTextInputTypeChanged(const TextInputClient* client) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(IsInitialized()); if (client != client_) { @@ -229,7 +229,7 @@ } bool TSFBridgeImpl::CancelComposition() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(IsInitialized()); TSFDocument* document = GetAssociatedDocument(); @@ -242,7 +242,7 @@ } bool TSFBridgeImpl::ConfirmComposition() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(IsInitialized()); TSFDocument* document = GetAssociatedDocument(); @@ -256,7 +256,7 @@ void TSFBridgeImpl::SetFocusedClient(HWND focused_window, TextInputClient* client) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(client); DCHECK(IsInitialized()); if (attached_window_handle_ != focused_window) @@ -276,7 +276,7 @@ } void TSFBridgeImpl::RemoveFocusedClient(TextInputClient* client) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(IsInitialized()); if (client_ != client) return; @@ -296,7 +296,7 @@ } Microsoft::WRL::ComPtr<ITfThreadMgr> TSFBridgeImpl::GetThreadManager() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); DCHECK(IsInitialized()); return thread_manager_; } @@ -492,7 +492,7 @@ // static void TSFBridge::Initialize() { - if (!base::MessageLoopForUI::IsCurrent()) { + if (!base::MessageLoopCurrentForUI::IsSet()) { DVLOG(1) << "Do not use TSFBridge without UI thread."; return; } @@ -509,7 +509,7 @@ // static TSFBridge* TSFBridge::ReplaceForTesting(TSFBridge* bridge) { - if (!base::MessageLoopForUI::IsCurrent()) { + if (!base::MessageLoopCurrentForUI::IsSet()) { DVLOG(1) << "Do not use TSFBridge without UI thread."; return nullptr; } @@ -520,7 +520,7 @@ // static void TSFBridge::Shutdown() { - if (!base::MessageLoopForUI::IsCurrent()) { + if (!base::MessageLoopCurrentForUI::IsSet()) { DVLOG(1) << "Do not use TSFBridge without UI thread."; } TSFBridgeImpl* delegate = static_cast<TSFBridgeImpl*>(TSFBridgeTLS().Get()); @@ -530,7 +530,7 @@ // static TSFBridge* TSFBridge::GetInstance() { - if (!base::MessageLoopForUI::IsCurrent()) { + if (!base::MessageLoopCurrentForUI::IsSet()) { DVLOG(1) << "Do not use TSFBridge without UI thread."; return nullptr; }
diff --git a/ui/base/ime/win/tsf_input_scope.cc b/ui/base/ime/win/tsf_input_scope.cc index d11c2073..2c0db97 100644 --- a/ui/base/ime/win/tsf_input_scope.cc +++ b/ui/base/ime/win/tsf_input_scope.cc
@@ -158,7 +158,7 @@ } // namespace void InitializeTsfForInputScopes() { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); // Thread safety is not required because this function is under UI thread. if (!g_get_proc_done) { g_get_proc_done = true;
diff --git a/ui/base/material_design/material_design_controller.cc b/ui/base/material_design/material_design_controller.cc index 2389ee9..e9700d21 100644 --- a/ui/base/material_design/material_design_controller.cc +++ b/ui/base/material_design/material_design_controller.cc
@@ -75,7 +75,7 @@ // Win 10+ uses dynamic mode by default and checks the current tablet mode // state to determine whether to start in touch mode. automatic_touch_ui_ = true; - if (base::MessageLoopForUI::IsCurrent() && + if (base::MessageLoopCurrentForUI::IsSet() && !GetInstance()->singleton_hwnd_observer_) { GetInstance()->singleton_hwnd_observer_ = std::make_unique<gfx::SingletonHwndObserver>(
diff --git a/ui/base/test/scoped_fake_nswindow_fullscreen.mm b/ui/base/test/scoped_fake_nswindow_fullscreen.mm index 1b5fd3c1..977c011 100644 --- a/ui/base/test/scoped_fake_nswindow_fullscreen.mm +++ b/ui/base/test/scoped_fake_nswindow_fullscreen.mm
@@ -106,7 +106,7 @@ [[NSNotificationCenter defaultCenter] postNotificationName:NSWindowWillStartLiveResizeNotification object:window]; - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&Impl::FinishEnterFullscreen, base::Unretained(this), fullscreen_content_size)); @@ -145,7 +145,7 @@ postNotificationName:NSWindowWillExitFullScreenNotification object:window_]; - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&Impl::FinishExitFullscreen, base::Unretained(this)));
diff --git a/ui/base/test/ui_controls_mac.mm b/ui/base/test/ui_controls_mac.mm index f498fbe..34f3ef9 100644 --- a/ui/base/test/ui_controls_mac.mm +++ b/ui/base/test/ui_controls_mac.mm
@@ -265,7 +265,7 @@ bool command, base::OnceClosure task) { CHECK(g_ui_controls_enabled); - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); std::vector<NSEvent*> events; SynthesizeKeyEventsSequence(window.GetNativeNSWindow(), key, control, shift,
diff --git a/ui/gfx/animation/animation_mac.mm b/ui/gfx/animation/animation_mac.mm index e3f1b1f..99a841c 100644 --- a/ui/gfx/animation/animation_mac.mm +++ b/ui/gfx/animation/animation_mac.mm
@@ -15,8 +15,8 @@ bool Animation::ScrollAnimationsEnabledBySystem() { // Because of sandboxing, OS settings should only be queried from the browser // process. - DCHECK(base::MessageLoopForUI::IsCurrent() || - base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet() || + base::MessageLoopCurrentForIO::IsSet()); bool enabled = false; id value = nil;
diff --git a/ui/gfx/font_fallback_win.cc b/ui/gfx/font_fallback_win.cc index 4d64f62c..3da6eee 100644 --- a/ui/gfx/font_fallback_win.cc +++ b/ui/gfx/font_fallback_win.cc
@@ -306,7 +306,7 @@ // browser process because we can use the shared system fallback, but in the // renderer this can cause hangs. Code that needs font fallback in the // renderer should instead use the font proxy. - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); // Check that we have at least as much text as was claimed. If we have less // text than expected then DirectWrite will become confused and crash. This
diff --git a/ui/gfx/win/singleton_hwnd.cc b/ui/gfx/win/singleton_hwnd.cc index 7d3aa6e..d97adfa 100644 --- a/ui/gfx/win/singleton_hwnd.cc +++ b/ui/gfx/win/singleton_hwnd.cc
@@ -27,7 +27,7 @@ } SingletonHwnd::SingletonHwnd() { - if (!base::MessageLoopForUI::IsCurrent()) { + if (!base::MessageLoopCurrentForUI::IsSet()) { // Creating this window in (e.g.) a renderer inhibits shutdown on // Windows. See http://crbug.com/230122 and http://crbug.com/236039. return;
diff --git a/ui/ozone/platform/drm/gpu/drm_device.cc b/ui/ozone/platform/drm/gpu/drm_device.cc index 8da7993..1ad207b 100644 --- a/ui/ozone/platform/drm/gpu/drm_device.cc +++ b/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -205,19 +205,19 @@ private: void Register() { - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor( fd_, true, base::MessagePumpForIO::WATCH_READ, &controller_, this); } void Unregister() { - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); controller_.StopWatchingFileDescriptor(); } // base::MessagePumpLibevent::FdWatcher overrides: void OnFileCanReadWithoutBlocking(int fd) override { - DCHECK(base::MessageLoopForIO::IsCurrent()); + DCHECK(base::MessageLoopCurrentForIO::IsSet()); TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd); if (!ProcessDrmEvent(
diff --git a/ui/ozone/platform/wayland/wayland_connection.cc b/ui/ozone/platform/wayland/wayland_connection.cc index ead0cf3..72c8d8b 100644 --- a/ui/ozone/platform/wayland/wayland_connection.cc +++ b/ui/ozone/platform/wayland/wayland_connection.cc
@@ -98,7 +98,7 @@ DCHECK(display_); wl_display_flush(display_.get()); - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); if (!base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor( wl_display_get_fd(display_.get()), true, base::MessagePumpLibevent::WATCH_READ, &controller_, this)) @@ -111,7 +111,7 @@ void WaylandConnection::ScheduleFlush() { if (scheduled_flush_ || !watching_) return; - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&WaylandConnection::Flush, base::Unretained(this))); @@ -176,7 +176,7 @@ const std::vector<uint64_t>& modifiers, uint32_t planes_count, uint32_t buffer_id) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); if (!buffer_manager_->CreateBuffer(std::move(file), width, height, strides, offsets, format, modifiers, planes_count, buffer_id)) { @@ -185,7 +185,7 @@ } void WaylandConnection::DestroyZwpLinuxDmabuf(uint32_t buffer_id) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); if (!buffer_manager_->DestroyBuffer(buffer_id)) { TerminateGpuProcess(buffer_manager_->error_message()); } @@ -196,7 +196,7 @@ uint32_t buffer_id, const gfx::Rect& damage_region, ScheduleBufferSwapCallback callback) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); if (!buffer_manager_->ScheduleBufferSwap(widget, buffer_id, damage_region, std::move(callback))) { TerminateGpuProcess(buffer_manager_->error_message());
diff --git a/ui/snapshot/screenshot_grabber.cc b/ui/snapshot/screenshot_grabber.cc index 73b56dd..285fd0c 100644 --- a/ui/snapshot/screenshot_grabber.cc +++ b/ui/snapshot/screenshot_grabber.cc
@@ -73,7 +73,7 @@ void ScreenshotGrabber::TakeScreenshot(gfx::NativeWindow window, const gfx::Rect& rect, ScreenshotCallback callback) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); last_screenshot_timestamp_ = base::TimeTicks::Now(); bool is_partial = true; @@ -106,7 +106,7 @@ bool is_partial, ScreenshotCallback callback, scoped_refptr<base::RefCountedMemory> png_data) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); #if defined(USE_AURA) cursor_hider_.reset();
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc index 03d48a06..8cce8de 100644 --- a/ui/views/controls/menu/menu_controller_unittest.cc +++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -329,7 +329,7 @@ set_views_delegate(std::move(views_delegate)); ViewsTestBase::SetUp(); Init(); - ASSERT_TRUE(base::MessageLoopForUI::IsCurrent()); + ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet()); } void TearDown() override {
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc index 1bfea071..6c63283 100644 --- a/ui/views/controls/textfield/textfield_model.cc +++ b/ui/views/controls/textfield/textfield_model.cc
@@ -270,7 +270,7 @@ // the default kill ring size of 1 (i.e. a single buffer) is assumed. base::string16* GetKillBuffer() { static base::NoDestructor<base::string16> kill_buffer; - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); return kill_buffer.get(); }
diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc index d6b086c1..e65fba7 100644 --- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc +++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
@@ -73,7 +73,7 @@ } uint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) { - DCHECK(base::MessageLoopForUI::IsCurrent()); + DCHECK(base::MessageLoopCurrentForUI::IsSet()); // This method processes all events while the move loop is active. if (!in_move_loop_)