diff --git a/DEPS b/DEPS index cf6e622..ef1c612 100644 --- a/DEPS +++ b/DEPS
@@ -40,7 +40,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '47238c79c4dd61c8770f45fc36d0cdbaea00b3e2', + 'skia_revision': 'ad8da8ea990d22fa717ec1ae7c3ad628d74682b8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '00d2ad12fa9d37581fd12d2ea5ea702c9e2e2e16', + 'pdfium_revision': 'fdc3acb42a7983053c53d1445c62654d7ef6b3b2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -72,7 +72,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': 'a4cb62f0ae6566068aef0742eb1cd46227d7dffd', + 'boringssl_revision': 'ca9e8f52f1631fa4906a0d44abdeb55f80fe026d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -166,7 +166,7 @@ Var('chromium_git') + '/external/leveldb.git' + '@' + '8415f00eeedd96934d3578572d3802900e61a556', 'src/third_party/snappy/src': - Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + '513df5fb5a2d51146f409141f9eb8736935cc486', + Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + '77c12adc192ac6620a0f0d340c99149ec56a97a3', 'src/tools/gyp': Var('chromium_git') + '/external/gyp.git' + '@' + 'd61a9397e668fa9843c4aa7da9e79460fe590bfb', @@ -406,7 +406,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': - Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '87d717a9e67756a26a49c4c23592d88760d11a5a', + Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '76e7c48dc3be8c24683f55e64ac28e0a7eaa303b', # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite':
diff --git a/android_webview/tools/PRESUBMIT.py b/android_webview/tools/PRESUBMIT.py index 935205d..59225c6 100644 --- a/android_webview/tools/PRESUBMIT.py +++ b/android_webview/tools/PRESUBMIT.py
@@ -12,11 +12,7 @@ """ checks = [] checks.extend(input_api.canned_checks.GetPylint( - input_api, output_api, pylintrc='pylintrc', - # TODO: lint these and eliminate the blacklist. - black_list=[ - r'webview_repack_locales.py', - ])) + input_api, output_api, pylintrc='pylintrc')) return input_api.RunTests(checks, False)
diff --git a/android_webview/tools/webview_repack_locales.py b/android_webview/tools/webview_repack_locales.py deleted file mode 100755 index 5fe3e6b..0000000 --- a/android_webview/tools/webview_repack_locales.py +++ /dev/null
@@ -1,111 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Helper script to rename paks for a list of locales for the Android WebView. - -Gyp doesn't have any built-in looping capability, so this just provides a way to -loop over a list of locales when renaming pak files. Based on -chrome/tools/build/repack_locales.py -""" - -import optparse -import os -import shutil -import sys - -# Prepend the grit module from the source tree so it takes precedence over other -# grit versions that might present in the search path. -sys.path.insert(1, os.path.join(os.path.dirname(__file__), '..', '..', - 'tools', 'grit')) -from grit.format import data_pack - -def calc_output(locale): - """Determine the file that will be generated for the given locale.""" - return os.path.join(PRODUCT_DIR, 'android_webview_assets', - 'locales', locale + '.pak') - -def calc_inputs(locale): - """Determine the files that need processing for the given locale.""" - inputs = [] - - inputs.append(os.path.join(SHARE_INT_DIR, 'content', 'app', 'strings', - 'content_strings_%s.pak' % locale)) - inputs.append(os.path.join(SHARE_INT_DIR, 'android_webview', - 'aw_strings_%s.pak' % locale)) - inputs.append(os.path.join(SHARE_INT_DIR, 'android_webview', - 'components_strings_%s.pak' % locale)) - return inputs - -def list_outputs(locales): - """Returns the names of files that will be generated for the given locales. - - This is to provide gyp the list of output files, so build targets can - properly track what needs to be built. - """ - outputs = [] - for locale in locales: - outputs.append(calc_output(locale)) - # Quote each element so filename spaces don't mess up gyp's attempt to parse - # it into a list. - return " ".join(['"%s"' % x for x in outputs]) - -def list_inputs(locales): - """Returns the names of files that will be processed for the given locales. - - This is to provide gyp the list of input files, so build targets can properly - track their prerequisites. - """ - inputs = [] - for locale in locales: - inputs += calc_inputs(locale) - # Quote each element so filename spaces don't mess up gyp's attempt to parse - # it into a list. - return " ".join(['"%s"' % x for x in inputs]) - -def repack_locales(locales): - """ Loop over and repack the given locales.""" - for locale in locales: - inputs = [] - inputs += calc_inputs(locale) - output = calc_output(locale) - data_pack.DataPack.RePack(output, inputs) - -def DoMain(argv): - global SHARE_INT_DIR - global PRODUCT_DIR - - parser = optparse.OptionParser("usage: %prog [options] locales") - parser.add_option("-i", action="store_true", dest="inputs", default=False, - help="Print the expected input file list, then exit.") - parser.add_option("-o", action="store_true", dest="outputs", default=False, - help="Print the expected output file list, then exit.") - parser.add_option("-p", action="store", dest="product_dir", - help="Product build files output directory.") - parser.add_option("-s", action="store", dest="share_int_dir", - help="Shared intermediate build files output directory.") - options, locales = parser.parse_args(argv) - if not locales: - parser.error('Please specify at least one locale to process.\n') - - print_inputs = options.inputs - print_outputs = options.outputs - SHARE_INT_DIR = options.share_int_dir - PRODUCT_DIR = options.product_dir - - if print_inputs and print_outputs: - parser.error('Please specify only one of "-i" or "-o".\n') - - if print_inputs: - return list_inputs(locales) - - if print_outputs: - return list_outputs(locales) - - return repack_locales(locales) - -if __name__ == '__main__': - results = DoMain(sys.argv[1:]) - if results: - print results
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index 724766b..a782a63 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -97,12 +97,16 @@ } void AppListButton::OnAppListShown() { + // Set |last_event_is_back_event_| false to drop ink on the app list circle. + last_event_is_back_event_ = false; AnimateInkDrop(views::InkDropState::ACTIVATED, nullptr); is_showing_app_list_ = true; shelf_->UpdateAutoHideState(); } void AppListButton::OnAppListDismissed() { + // Set |last_event_is_back_event_| false to drop ink on the app list circle. + last_event_is_back_event_ = false; AnimateInkDrop(views::InkDropState::DEACTIVATED, nullptr); is_showing_app_list_ = false; shelf_->UpdateAutoHideState();
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 9896cb5..cf9455fe 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -2713,8 +2713,7 @@ EXPECT_THAT(app_list_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::ACTION_TRIGGERED)); - // Verify when we leave tablet mode, the bounds should return to be the same - // as they were before we entered tablet mode. + // Verify that the bounds after leaving tablet mode match the original bounds. Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false); test_api_->RunMessageLoopUntilAnimationsDone(); new_bounds = app_list_button_->GetBoundsInScreen();
diff --git a/base/BUILD.gn b/base/BUILD.gn index cd2b0f2..72bec6ba 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2668,6 +2668,15 @@ "test/android/javatests/src/org/chromium/base/test/SetUpStatement.java", "test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java", "test/android/javatests/src/org/chromium/base/test/TestTraceEvent.java", + "test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java", + "test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java", + "test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java", + "test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java", + "test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java", + "test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java", + "test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java", + "test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java", + "test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java", "test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java", "test/android/javatests/src/org/chromium/base/test/util/AnnotationProcessor.java", "test/android/javatests/src/org/chromium/base/test/util/CallbackHelper.java", @@ -2726,6 +2735,10 @@ "test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java", "test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java", "test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java", + "test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java", + "test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java", + "test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java", + "test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java", ] deps = [ ":base_java",
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h index 9dd087d..365c2b9 100644 --- a/base/memory/discardable_shared_memory.h +++ b/base/memory/discardable_shared_memory.h
@@ -69,6 +69,13 @@ // Returns a shared memory handle for this DiscardableSharedMemory object. SharedMemoryHandle handle() const { return shared_memory_.handle(); } + // Returns an ID for the shared memory region. This is ID of the mapped region + // consistent across all processes and is valid as long as the region is not + // unmapped. + const UnguessableToken& mapped_id() const { + return shared_memory_.mapped_id(); + } + // Locks a range of memory so that it will not be purged by the system. // The range of memory must be unlocked. The result of trying to lock an // already locked range is undefined. |offset| and |length| must both be
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java b/base/test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java new file mode 100644 index 0000000..99b8d2e --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java
@@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.test.params; + +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; + +import org.chromium.base.test.BaseJUnit4ClassRunner; + +import java.util.List; + +/** + * Class runner delegate that extends BaseJUnit4ClassRunner + */ +public final class BaseJUnit4RunnerDelegate + extends BaseJUnit4ClassRunner implements ParameterizedRunnerDelegate { + private ParameterizedRunnerDelegateCommon mDelegateCommon; + + public BaseJUnit4RunnerDelegate(Class<?> klass, + ParameterizedRunnerDelegateCommon delegateCommon) throws InitializationError { + super(klass); + mDelegateCommon = delegateCommon; + } + + @Override + public void collectInitializationErrors(List<Throwable> errors) { + ParameterizedRunnerDelegateCommon.collectInitializationErrors(errors); + } + + @Override + public List<FrameworkMethod> computeTestMethods() { + return mDelegateCommon.computeTestMethods(); + } + + @Override + public Object createTest() { + return mDelegateCommon.createTest(); + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java b/base/test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java new file mode 100644 index 0000000..427232dd --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java
@@ -0,0 +1,40 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.test.params; + +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; + +import java.util.List; + +/** + * Parameterized class runner delegate that extends BlockJUnit4ClassRunner + */ +public final class BlockJUnit4RunnerDelegate + extends BlockJUnit4ClassRunner implements ParameterizedRunnerDelegate { + private ParameterizedRunnerDelegateCommon mDelegateCommon; + + public BlockJUnit4RunnerDelegate(Class<?> klass, + ParameterizedRunnerDelegateCommon delegateCommon) throws InitializationError { + super(klass); + mDelegateCommon = delegateCommon; + } + + @Override + public void collectInitializationErrors(List<Throwable> errors) { + ParameterizedRunnerDelegateCommon.collectInitializationErrors(errors); + } + + @Override + public List<FrameworkMethod> computeTestMethods() { + return mDelegateCommon.computeTestMethods(); + } + + @Override + public Object createTest() { + return mDelegateCommon.createTest(); + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java new file mode 100644 index 0000000..b1daadd0 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java
@@ -0,0 +1,58 @@ +// 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. + +package org.chromium.base.test.params; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotations for Parameterized Tests + */ +public class ParameterAnnotations { + /** + * Annotation for test methods to indicate associated List<ParameterSet> + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface UseMethodParameter { + String value(); + } + + /** + * Annotation for static field of a `List<ParameterSet>` for entire test class + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface ClassParameter {} + + /** + * Annotation for static field of a `List<ParameterSet>` for certain test methods + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface MethodParameter { + String value(); + } + + /** + * Annotation for static field of a `List<ParameterSet>` of TestRule + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface RuleParameter {} + + /** + * Annotation for test class, it specifies which ParameterizeRunnerDelegate to use. + * + * The default ParameterizedRunnerDelegate is BaseJUnit4RunnerDelegate.class + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface UseRunnerDelegate { + Class<? extends ParameterizedRunnerDelegate> value(); + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java new file mode 100644 index 0000000..b38fb400 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java
@@ -0,0 +1,128 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.test.params; + +import org.junit.Assert; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; + +/** + * A set of parameters for one *SINGLE* test method or test class constructor. + * + * For example, <code>new ParameterSet().value("a", "b")</code> is intended for + * a test method/constructor that takes in two string as arguments. + * <code>public void testSimple(String a, String b) {...}</code> + * or + * <code>public MyTestClass(String a, String b) {...}</code> + * + * To parameterize testSimple or MyTestClass's tests, create multiple ParameterSets + * <code> + * static List<ParameterSet> sAllParameterSets = new ArrayList<>(); + * static { + * sAllParameterSets.add(new ParameterSet().value("a", "b"); + * sAllParameterSets.add(new ParameterSet().value("c", "d"); + * } + */ +public class ParameterSet { + private List<Object> mValues; + private String mName; + + public ParameterSet() {} + + public ParameterSet value(Object firstArg, Object... objects) { + List<Object> parameterList = new ArrayList<Object>(); + parameterList.add(firstArg); + parameterList.addAll(Arrays.asList(objects)); + Assert.assertTrue( + "Can not create ParameterSet with no parameters", parameterList.size() != 0); + mValues = validateAndCopy(parameterList); + return this; + } + + public ParameterSet name(String name) { + mName = name; + return this; + } + + @Override + public String toString() { + if (mValues == null) { + return "null"; + } + return Arrays.toString(mValues.toArray()); + } + + private List<Object> validateAndCopy(List<Object> values) { + List<Object> tempValues = new ArrayList<>(); + for (Object o : values) { + if (o == null) { + tempValues.add(null); + } else { + if (o.getClass().isPrimitive() || ACCEPTABLE_TYPES.contains(o.getClass()) + || o instanceof Callable) { + tempValues.add(o); + } else { + // TODO(yolandyan): maybe come up with way to support + // complex object while handling immutability at the + // same time + throw new IllegalArgumentException("Type \"%s\" is not supported in" + + " parameterized testing at this time. Accepted types include" + + " all primitive types along with " + + Arrays.toString(ACCEPTABLE_TYPES.toArray( + new String[ACCEPTABLE_TYPES.size()]))); + } + } + } + return Collections.unmodifiableList(tempValues); + } + + String getName() { + if (mName == null) { + return ""; + } + return mName; + } + + List<Object> getValues() { + return mValues; + } + + int size() { + return mValues.size(); + } + + private static final Set<Class<?>> ACCEPTABLE_TYPES = getAcceptableTypes(); + + /** + * Any immutable class is acceptable. + */ + private static Set<Class<?>> getAcceptableTypes() { + Set<Class<?>> ret = new HashSet<Class<?>>(); + ret.add(Boolean.class); + ret.add(Byte.class); + ret.add(Character.class); + ret.add(Class.class); + ret.add(Double.class); + ret.add(File.class); + ret.add(Float.class); + ret.add(Integer.class); + ret.add(Long.class); + ret.add(Short.class); + ret.add(String.class); + ret.add(URI.class); + ret.add(URL.class); + ret.add(Void.class); + return ret; + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java new file mode 100644 index 0000000..f3333b5 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java
@@ -0,0 +1,94 @@ +// 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. + +package org.chromium.base.test.params; + +import org.junit.runners.model.FrameworkMethod; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Custom FrameworkMethod that includes a {@code ParameterSet} that + * represents the parameters for this test method + */ +public class ParameterizedFrameworkMethod extends FrameworkMethod { + private ParameterSet mParameterSet; + private String mName; + + public ParameterizedFrameworkMethod( + Method method, ParameterSet parameterSet, String classParameterSetName) { + super(method); + mParameterSet = parameterSet; + String postFix = ""; + if (classParameterSetName != null && !classParameterSetName.isEmpty()) { + postFix += "_" + classParameterSetName; + } + if (parameterSet != null && !parameterSet.getName().isEmpty()) { + postFix += "_" + parameterSet.getName(); + } + mName = postFix.isEmpty() ? method.getName() : method.getName() + "_" + postFix; + } + + @Override + public String getName() { + return mName; + } + + @Override + public Object invokeExplosively(Object target, Object... params) throws Throwable { + if (mParameterSet != null) { + return super.invokeExplosively(target, mParameterSet.getValues().toArray()); + } + return super.invokeExplosively(target, params); + } + + static List<FrameworkMethod> wrapAllFrameworkMethods( + Collection<FrameworkMethod> frameworkMethods, String classParameterSetName) { + List<FrameworkMethod> results = new ArrayList<>(); + for (FrameworkMethod frameworkMethod : frameworkMethods) { + results.add(new ParameterizedFrameworkMethod( + frameworkMethod.getMethod(), null, classParameterSetName)); + } + return results; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ParameterizedFrameworkMethod) { + ParameterizedFrameworkMethod method = (ParameterizedFrameworkMethod) obj; + return super.equals(obj) && method.getParameterSet().equals(getParameterSet()) + && method.getName().equals(getName()); + } + return false; + } + + /** + * Override hashCode method to distinguish two ParameterizedFrameworkmethod with same + * Method object. + */ + @Override + public int hashCode() { + int result = 17; + result = 31 * result + super.hashCode(); + result = 31 * result + getName().hashCode(); + if (getParameterSet() != null) { + result = 31 * result + getParameterSet().hashCode(); + } + return result; + } + + Annotation[] getTestAnnotations() { + // TODO(yolandyan): add annotation from the ParameterSet, enable + // test writing to add SkipCheck for an individual parameter + return getMethod().getAnnotations(); + } + + public ParameterSet getParameterSet() { + return mParameterSet; + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java new file mode 100644 index 0000000..a72c696 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java
@@ -0,0 +1,239 @@ +// 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. + +package org.chromium.base.test.params; + +import org.junit.Test; +import org.junit.runner.Runner; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.Suite; +import org.junit.runners.model.FrameworkField; +import org.junit.runners.model.TestClass; + +import org.chromium.base.test.params.ParameterAnnotations.ClassParameter; +import org.chromium.base.test.params.ParameterAnnotations.MethodParameter; +import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; +import org.chromium.base.test.params.ParameterizedRunnerDelegateFactory.ParameterizedRunnerDelegateInstantiationException; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * ParameterizedRunner generates a list of runners for each of class parameter set in a test class. + * + * ParameterizedRunner looks for {@code @ClassParameter} annotation in test class and + * generates a list of ParameterizedRunnerDelegate runners for each ParameterSet. The class + * runner also looks for {@code @MethodParameter} annotation, and creates a map that maps Strings + * value(tag) to ParameterSet List. + */ +public final class ParameterizedRunner extends Suite { + private static final String TAG = "cr_ParameterizedRunner"; + private final List<Runner> mRunners; + + /** + * Create a ParameterizedRunner to run test class + * + * @param klass the Class of the test class, test class should be atomic + * (extends only Object) + */ + public ParameterizedRunner(Class<?> klass) throws Throwable { + super(klass, Collections.<Runner>emptyList()); // pass in empty list of runners + validate(); + mRunners = createRunners(getTestClass()); + } + + @Override + protected List<Runner> getChildren() { + return mRunners; + } + + /** + * ParentRunner calls collectInitializationErrors() to check for errors in Test class. + * Parameterized tests are written in unconventional ways, therefore, this method is + * overridden and validation is done seperately. + */ + @Override + protected void collectInitializationErrors(List<Throwable> errors) { + // Do not call super collectInitializationErrors + } + + private void validate() throws Throwable { + validateNoNonStaticInnerClass(); + validateOnlyOneConstructor(); + validateInstanceMethods(); + validateOnlyOneClassParameterField(); + validateAtLeastOneParameterSetField(); + } + + private void validateNoNonStaticInnerClass() throws Exception { + if (getTestClass().isANonStaticInnerClass()) { + throw new Exception("The inner class " + getTestClass().getName() + " is not static."); + } + } + + private void validateOnlyOneConstructor() throws Exception { + if (!hasOneConstructor()) { + throw new Exception("Test class should have exactly one public constructor"); + } + } + + private boolean hasOneConstructor() { + return getTestClass().getJavaClass().getConstructors().length == 1; + } + + private void validateOnlyOneClassParameterField() { + if (getTestClass().getAnnotatedFields(ClassParameter.class).size() > 1) { + throw new IllegalParameterArgumentException( + "%s class has more than one @ClassParameter, only one is allowed"); + } + } + + private void validateAtLeastOneParameterSetField() { + if (getTestClass().getAnnotatedFields(ClassParameter.class).isEmpty() + && getTestClass().getAnnotatedFields(MethodParameter.class).isEmpty()) { + throw new IllegalArgumentException(String.format(Locale.getDefault(), + "%s has no field annotated with @ClassParameter or @MethodParameter field, " + + "it should not use ParameterizedRunner", + getTestClass().getName())); + } + } + + private void validateInstanceMethods() throws Exception { + if (getTestClass().getAnnotatedMethods(Test.class).size() == 0) { + throw new Exception("No runnable methods"); + } + } + + /** + * Return a list of runner delegates through ParameterizedRunnerDelegateFactory. + * + * For class parameter set: each class can only have one list of class parameter sets. + * Each parameter set will be used to create one runner. + * + * For method parameter set: a single list method parameter sets is associated with + * a string tag, an immutable map of string to parameter set list will be created and + * passed into factory for each runner delegate to create multiple tests. only one + * Runner will be created for a method that uses @MethodParameter, regardless of the + * number of ParameterSets in the associated list. + * + * @return a list of runners + * @throws ParameterizedTestInstantiationException if the test class is malformed. + * @throws ParameterizedRunnerDelegateInstantiationException if runner delegate can not + * be instantiated with constructor reflectively + * @throws IllegalAccessError if the field in tests are not accessible + */ + static List<Runner> createRunners(TestClass testClass) + throws IllegalAccessException, ParameterizedTestInstantiationException, + ParameterizedRunnerDelegateInstantiationException { + List<ParameterSet> classParameterSetList; + if (testClass.getAnnotatedFields(ClassParameter.class).isEmpty()) { + classParameterSetList = new ArrayList<>(); + classParameterSetList.add(null); + } else { + classParameterSetList = getParameterSetList( + testClass.getAnnotatedFields(ClassParameter.class).get(0), testClass); + validateWidth(classParameterSetList); + } + + Class<? extends ParameterizedRunnerDelegate> runnerDelegateClass = + getRunnerDelegateClass(testClass); + ParameterizedRunnerDelegateFactory factory = new ParameterizedRunnerDelegateFactory(); + Map<String, List<ParameterSet>> tagToMethodParameterSetList = + Collections.unmodifiableMap(generateMethodParameterMap(testClass)); + List<Runner> runnersForTestClass = new ArrayList<>(); + for (ParameterSet classParameterSet : classParameterSetList) { + BlockJUnit4ClassRunner runner = (BlockJUnit4ClassRunner) factory.createRunner( + testClass, classParameterSet, tagToMethodParameterSetList, runnerDelegateClass); + runnersForTestClass.add(runner); + } + return runnersForTestClass; + } + + /** + * Returns a map between MethodParameter tags and corresponding ParameterSetLists. + */ + static Map<String, List<ParameterSet>> generateMethodParameterMap(TestClass testClass) + throws IllegalAccessException { + Map<String, List<ParameterSet>> result = new HashMap<>(); + for (FrameworkField field : testClass.getAnnotatedFields(MethodParameter.class)) { + List<ParameterSet> parameterSetList = getParameterSetList(field, testClass); + validateWidth(parameterSetList); + result.put(field.getAnnotation(MethodParameter.class).value(), parameterSetList); + } + return result; + } + + /** + * Return an unmodifiable list of ParameterSet through a FrameworkField + */ + static List<ParameterSet> getParameterSetList(FrameworkField field, TestClass testClass) + throws IllegalAccessException { + field.getField().setAccessible(true); + if (!Modifier.isStatic(field.getField().getModifiers())) { + throw new IllegalParameterArgumentException(String.format(Locale.getDefault(), + "ParameterSetList fields must be static, this field %s in %s is not", + field.getName(), testClass.getName())); + } + if (!(field.get(testClass.getJavaClass()) instanceof List)) { + throw new IllegalArgumentException(String.format(Locale.getDefault(), + "Fields with @ClassParameter or @MethodParameter annotations must be an" + + " instance of List, this field %s in %s is not list", + field.getName(), testClass.getName())); + } + @SuppressWarnings("unchecked") // checked above + List<ParameterSet> result = (List<ParameterSet>) field.get(testClass.getJavaClass()); + return Collections.unmodifiableList(result); + } + + static void validateWidth(List<ParameterSet> parameterSetList) { + int lastSize = -1; + for (ParameterSet set : parameterSetList) { + if (lastSize == -1 || set.size() == lastSize) { + lastSize = set.size(); + } else { + throw new IllegalParameterArgumentException(String.format(Locale.getDefault(), + "All ParameterSets in a list of ParameterSet must have equal" + + " length. The current ParameterSet (%s) contains %d parameters," + + " while previous ParameterSet contains %d parameters", + Arrays.toString(set.getValues().toArray()), set.size(), lastSize)); + } + } + } + + /** + * Get the runner delegate class for the test class if {@code @UseRunnerDelegate} is used. + * The default runner delegate is BaseJUnit4RunnerDelegate.class + */ + private static Class<? extends ParameterizedRunnerDelegate> getRunnerDelegateClass( + TestClass testClass) { + if (testClass.getAnnotation(UseRunnerDelegate.class) != null) { + return testClass.getAnnotation(UseRunnerDelegate.class).value(); + } + return BaseJUnit4RunnerDelegate.class; + } + + static class IllegalParameterArgumentException extends IllegalArgumentException { + public IllegalParameterArgumentException(String msg) { + super(msg); + } + } + + static class ParameterizedTestInstantiationException extends Exception { + ParameterizedTestInstantiationException( + TestClass testClass, String parameterSetString, Exception e) { + super(String.format( + "Test class %s can not be initiated, the provided parameters are %s," + + " the required parameter types are %s", + testClass.getJavaClass().toString(), parameterSetString, + Arrays.toString(testClass.getOnlyConstructor().getParameterTypes())), + e); + } + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java new file mode 100644 index 0000000..9b755fe --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java
@@ -0,0 +1,34 @@ +// 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. + +package org.chromium.base.test.params; + +import org.junit.runners.model.FrameworkMethod; + +import java.util.List; + +/** + * This interface defines the methods that needs to be overriden for a Runner to + * be used by ParameterizedRunner to generate individual runners for parameters. + * + * To create a ParameterizedRunnerDelegate, extends from any BlockJUnit4Runner + * children class. You can copy all the implementation from + * org.chromium.base.test.params.BaseJUnit4RunnerDelegate. + */ +public interface ParameterizedRunnerDelegate { + /** + * Override to use DelegateCommon's implementation + */ + void collectInitializationErrors(List<Throwable> errors); + + /** + * Override to use DelegateCommon's implementation + */ + List<FrameworkMethod> computeTestMethods(); + + /** + * Override to use DelegateCommon's implementation + */ + Object createTest(); +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java new file mode 100644 index 0000000..5e43dc121 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java
@@ -0,0 +1,42 @@ +// 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. + +package org.chromium.base.test.params; + +import org.junit.runners.model.FrameworkMethod; + +import java.util.List; + +/** + * Parameterized runner delegate common that implements method that needed to be + * delegated for parameterization purposes + */ +public final class ParameterizedRunnerDelegateCommon { + private final List<FrameworkMethod> mParameterizedFrameworkMethodList; + private final Object mTest; + + public ParameterizedRunnerDelegateCommon( + Object test, List<FrameworkMethod> parameterizedFrameworkMethods) { + mTest = test; + mParameterizedFrameworkMethodList = parameterizedFrameworkMethods; + } + + /** + * Do not do any validation here because running the default class runner's + * collectInitializationErrors fail due to the overridden computeTestMethod relying on a local + * member variable + * + * The validation needed for parameterized tests is already done by ParameterizedRunner. + */ + public static void collectInitializationErrors( + @SuppressWarnings("unused") List<Throwable> errors) {} + + public List<FrameworkMethod> computeTestMethods() { + return mParameterizedFrameworkMethodList; + } + + public Object createTest() { + return mTest; + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java new file mode 100644 index 0000000..eaf6873 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java
@@ -0,0 +1,156 @@ +// 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. + +package org.chromium.base.test.params; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.TestClass; + +import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter; +import org.chromium.base.test.params.ParameterizedRunner.ParameterizedTestInstantiationException; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Factory to generate delegate class runners for ParameterizedRunner + */ +public class ParameterizedRunnerDelegateFactory { + /** + * Create a runner that implements ParameterizedRunner and extends BlockJUnit4ClassRunner + * + * @param testClass the TestClass object for current test class + * @param classParameterSet A parameter set for test constructor arguments + * @param testMethodToParameterSetListMap maps annotation tag to list of parameter set + * @param parameterizedRunnerDelegateClass the parameterized runner delegate class specified + * through {@code @UseRunnerDelegate} + */ + <T extends ParameterizedRunnerDelegate> T createRunner(TestClass testClass, + ParameterSet classParameterSet, + Map<String, List<ParameterSet>> testMethodToParameterSetListMap, + Class<T> parameterizedRunnerDelegateClass) + throws ParameterizedTestInstantiationException, + ParameterizedRunnerDelegateInstantiationException { + String testMethodPostfix = classParameterSet == null ? null : classParameterSet.getName(); + List<FrameworkMethod> unmodifiableFrameworkMethodList = + generateUnmodifiableFrameworkMethodList( + testClass, testMethodToParameterSetListMap, testMethodPostfix); + Object test = createTest(testClass, classParameterSet); + ParameterizedRunnerDelegateCommon delegateCommon = + new ParameterizedRunnerDelegateCommon(test, unmodifiableFrameworkMethodList); + try { + T runnerDelegate = parameterizedRunnerDelegateClass + .getDeclaredConstructor( + Class.class, ParameterizedRunnerDelegateCommon.class) + .newInstance(testClass.getJavaClass(), delegateCommon); + return runnerDelegate; + } catch (Exception e) { + throw new ParameterizedRunnerDelegateInstantiationException( + parameterizedRunnerDelegateClass.toString(), e); + } + } + + /** + * Match test methods annotated by @UseMethodParameter(X) with + * ParameterSetList annotated by @MethodParameter(X) + * + * @param testClass a {@code TestClass} that wraps around the actual java + * test class + * @param tagToParameterSetList A map of String tags to ParameterSetList + * @param postFix a name postfix for each test + * @return a list of ParameterizedFrameworkMethod + */ + static List<FrameworkMethod> generateUnmodifiableFrameworkMethodList(TestClass testClass, + Map<String, List<ParameterSet>> tagToParameterSetList, String postFix) { + // A Map that maps string tag X to a list of test framework methods that are + // annotated with @UseMethodParameter(X) + Map<String, List<FrameworkMethod>> tagToListOfFrameworkMethod = new HashMap<>(); + + // Represent the list of all ParameterizedFrameworkMethod in this test class + List<FrameworkMethod> returnList = new ArrayList<>(); + + // Create tagToListOfFrameworkMethod + for (FrameworkMethod method : testClass.getAnnotatedMethods(Test.class)) { + // If test method is not parameterized (does not have + // UseMethodParameter annotation) + if (!method.getMethod().isAnnotationPresent(UseMethodParameter.class)) { + returnList.add(new ParameterizedFrameworkMethod(method.getMethod(), null, postFix)); + } else { + String currentGroup = method.getAnnotation(UseMethodParameter.class).value(); + if (tagToListOfFrameworkMethod.get(currentGroup) == null) { + List<FrameworkMethod> list = new ArrayList<>(); + list.add(method); + tagToListOfFrameworkMethod.put(currentGroup, list); + } else { + tagToListOfFrameworkMethod.get(currentGroup).add(method); + } + } + } + + Assert.assertArrayEquals( + "All parameters used by must be defined, and all defined parameters must be used.", + tagToParameterSetList.keySet().toArray(), + tagToListOfFrameworkMethod.keySet().toArray()); + + // Loop through each of the tags and create all the parameterized framework + // methods for every method parameter set in the method parameter set list + // annotated with that tag + for (Entry<String, List<ParameterSet>> entry : tagToParameterSetList.entrySet()) { + String tagString = entry.getKey(); + List<ParameterSet> parameterSetList = entry.getValue(); + for (FrameworkMethod method : tagToListOfFrameworkMethod.get(tagString)) { + for (ParameterSet set : parameterSetList) { + if (set.getValues() == null) { + throw new IllegalArgumentException( + "No parameter is added to method ParameterSet"); + } + returnList.add( + new ParameterizedFrameworkMethod(method.getMethod(), set, postFix)); + } + } + } + return Collections.unmodifiableList(returnList); + } + + /** + * Create a test object using the list of class parameter set + * + * @param testClass the {@link TestClass} object for current test class + * @param classParameterSet the parameter set needed for the test class constructor + */ + static Object createTest(TestClass testClass, ParameterSet classParameterSet) + throws ParameterizedTestInstantiationException { + try { + if (classParameterSet == null) { + return testClass.getOnlyConstructor().newInstance(); + } + return testClass.getOnlyConstructor().newInstance( + classParameterSet.getValues().toArray()); + } catch (Exception e) { + String parameterSetString = + classParameterSet == null ? "null" : classParameterSet.toString(); + throw new ParameterizedTestInstantiationException(testClass, parameterSetString, e); + } + } + + /** + * Exception caused by instantiating the provided Runner delegate + * Potentially caused by not overriding collecInitializationErrors() method + * to be empty + */ + public static class ParameterizedRunnerDelegateInstantiationException extends Exception { + private ParameterizedRunnerDelegateInstantiationException( + String runnerDelegateClass, Exception e) { + super(String.format("Current class runner delegate %s can not be instantiated.", + runnerDelegateClass), + e); + } + } +}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java new file mode 100644 index 0000000..9745975 --- /dev/null +++ b/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java
@@ -0,0 +1,78 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.test.params; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.params.ParameterAnnotations.ClassParameter; +import org.chromium.base.test.params.ParameterAnnotations.MethodParameter; +import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter; +import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; + +import java.util.ArrayList; +import java.util.List; + +/** + * Example test that uses ParamRunner + */ +@RunWith(ParameterizedRunner.class) +@UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) +public class ExampleParameterizedTest { + @ClassParameter + private static List<ParameterSet> sClassParams = new ArrayList<>(); + + static { + sClassParams.add(new ParameterSet().value("hello", "world").name("HelloWorld")); + sClassParams.add(new ParameterSet().value("Xxxx", "Yyyy").name("XxxxYyyy")); + sClassParams.add(new ParameterSet().value("aa", "yy").name("AaYy")); + } + + @MethodParameter("A") + private static List<ParameterSet> sMethodParamA = new ArrayList<>(); + + static { + sMethodParamA.add(new ParameterSet().value(1, 2).name("OneTwo")); + sMethodParamA.add(new ParameterSet().value(2, 3).name("TwoThree")); + sMethodParamA.add(new ParameterSet().value(3, 4).name("ThreeFour")); + } + + @MethodParameter("B") + private static List<ParameterSet> sMethodParamB = new ArrayList<>(); + + static { + sMethodParamB.add(new ParameterSet().value("a", "b").name("Ab")); + sMethodParamB.add(new ParameterSet().value("b", "c").name("Bc")); + sMethodParamB.add(new ParameterSet().value("c", "d").name("Cd")); + sMethodParamB.add(new ParameterSet().value("d", "e").name("De")); + } + + private String mStringA; + private String mStringB; + + public ExampleParameterizedTest(String a, String b) { + mStringA = a; + mStringB = b; + } + + @Test + public void testSimple() { + Assert.assertEquals( + "A and B string length aren't equal", mStringA.length(), mStringB.length()); + } + + @Test + @UseMethodParameter("A") + public void testWithOnlyA(int intA, int intB) { + Assert.assertTrue(intA + 1 == intB); + } + + @Test + @UseMethodParameter("B") + public void testWithOnlyB(String a, String b) { + Assert.assertTrue(a != b); + } +}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java new file mode 100644 index 0000000..3be81a92 --- /dev/null +++ b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java
@@ -0,0 +1,191 @@ +// 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. + +package org.chromium.base.test.params; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.TestClass; + +import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter; +import org.chromium.base.test.params.ParameterizedRunner.ParameterizedTestInstantiationException; +import org.chromium.base.test.params.ParameterizedRunnerDelegateFactory.ParameterizedRunnerDelegateInstantiationException; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Test for org.chromium.base.test.params.ParameterizedRunnerDelegateFactory + */ +@RunWith(BlockJUnit4ClassRunner.class) +public class ParameterizedRunnerDelegateFactoryTest { + /** + * This RunnerDelegate calls `super.collectInitializationErrors()` and would + * cause BlockJUnit4ClassRunner to validate test classes. + */ + public static class BadExampleRunnerDelegate + extends BlockJUnit4ClassRunner implements ParameterizedRunnerDelegate { + public static class LalaTestClass {} + + private final List<FrameworkMethod> mParameterizedFrameworkMethodList; + + BadExampleRunnerDelegate(Class<?> klass, + List<FrameworkMethod> parameterizedFrameworkMethods) throws InitializationError { + super(klass); + mParameterizedFrameworkMethodList = parameterizedFrameworkMethods; + } + + @Override + public void collectInitializationErrors(List<Throwable> errors) { + super.collectInitializationErrors(errors); // This is wrong!! + } + + @Override + public List<FrameworkMethod> computeTestMethods() { + return mParameterizedFrameworkMethodList; + } + + @Override + public Object createTest() { + return null; + } + } + + static class BadTestClassWithMoreThanOneConstructor { + public BadTestClassWithMoreThanOneConstructor() {} + @SuppressWarnings("unused") + public BadTestClassWithMoreThanOneConstructor(String argument) {} + } + + static class TestClassConstructorWithTwoArguments { + @SuppressWarnings("unused") + public TestClassConstructorWithTwoArguments(int a, int b) {} + } + + static class ExampleTestClass { + @SuppressWarnings("unused") + @UseMethodParameter("A") + @Test + public void testA(String a) {} + + @SuppressWarnings("unused") + @UseMethodParameter("B") + @Test + public void testB(int b) {} + + @Test + public void testByMyself() {} + } + + /** + * This test validates ParameterizedRunnerDelegateFactory throws exception when + * a runner delegate does not override the collectInitializationErrors method. + */ + @Test(expected = ParameterizedRunnerDelegateInstantiationException.class) + public void testBadRunnerDelegateWithIncorrectValidationCall() throws Throwable { + ParameterizedRunnerDelegateFactory factory = new ParameterizedRunnerDelegateFactory(); + TestClass testClass = new TestClass(BadExampleRunnerDelegate.LalaTestClass.class); + factory.createRunner( + testClass, null, Collections.emptyMap(), BadExampleRunnerDelegate.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateTestWithMoreThanOneConstructor() throws Throwable { + TestClass testClass = new TestClass(BadTestClassWithMoreThanOneConstructor.class); + ParameterizedRunnerDelegateFactory.createTest(testClass, new ParameterSet()); + } + + @Test(expected = ParameterizedTestInstantiationException.class) + public void testCreateTestWithIncorrectArguments() throws Throwable { + TestClass testClass = new TestClass(TestClassConstructorWithTwoArguments.class); + ParameterSet pSet = new ParameterSet().value(1, 2, 3); + ParameterizedRunnerDelegateFactory.createTest(testClass, pSet); + } + + @Test + public void testGenerateParameterizedFrameworkMethod() throws Throwable { + Map<String, List<ParameterSet>> map = new HashMap<>(); + List<ParameterSet> listA = new ArrayList<>(); + listA.add(new ParameterSet().value("a").name("testWithValue_a")); + listA.add(new ParameterSet().value("b").name("testWithValue_b")); + + List<ParameterSet> listB = new ArrayList<>(); + listB.add(new ParameterSet().value(1).name("testWithValue_1")); + listB.add(new ParameterSet().value(2).name("testWithValue_2")); + listB.add(new ParameterSet().value(3).name("testWithValue_3")); + map.put("A", listA); + map.put("B", listB); + + List<FrameworkMethod> methods = + ParameterizedRunnerDelegateFactory.generateUnmodifiableFrameworkMethodList( + new TestClass(ExampleTestClass.class), map, ""); + + Assert.assertEquals(methods.size(), 6); + + Map<String, Method> expectedTests = new HashMap<>(); + Method testMethodA = ExampleTestClass.class.getDeclaredMethod("testA", String.class); + Method testMethodB = ExampleTestClass.class.getDeclaredMethod("testB", int.class); + Method testMethodByMyself = ExampleTestClass.class.getDeclaredMethod("testByMyself"); + expectedTests.put("testA__testWithValue_a", testMethodA); + expectedTests.put("testA__testWithValue_b", testMethodA); + expectedTests.put("testB__testWithValue_1", testMethodB); + expectedTests.put("testB__testWithValue_2", testMethodB); + expectedTests.put("testB__testWithValue_3", testMethodB); + expectedTests.put("testByMyself", testMethodByMyself); + for (FrameworkMethod method : methods) { + Assert.assertNotNull(expectedTests.get(method.getName())); + Assert.assertEquals(expectedTests.get(method.getName()), method.getMethod()); + expectedTests.remove(method.getName()); + } + Assert.assertTrue(expectedTests.isEmpty()); + } + + @Test(expected = IllegalArgumentException.class) + public void testEmptyParameterSet() { + Map<String, List<ParameterSet>> map = new HashMap<>(); + List<ParameterSet> listA = new ArrayList<>(); + listA.add(new ParameterSet().value("a").name("testWithValue_a")); + List<ParameterSet> listB = new ArrayList<>(); + listB.add(new ParameterSet()); //Empty parameter set + map.put("A", listA); + map.put("B", listB); + ParameterizedRunnerDelegateFactory.generateUnmodifiableFrameworkMethodList( + new TestClass(ExampleTestClass.class), map, ""); + } + + @Test(expected = AssertionError.class) + public void testMissingParameterSet() { + Map<String, List<ParameterSet>> map = new HashMap<>(); + List<ParameterSet> listA = new ArrayList<>(); + listA.add(new ParameterSet().value("a").name("testWithValue_a")); + map.put("A", listA); + //Missing ParameterSet list under group "B" + ParameterizedRunnerDelegateFactory.generateUnmodifiableFrameworkMethodList( + new TestClass(ExampleTestClass.class), map, ""); + } + + @Test(expected = AssertionError.class) + public void testMissingTestMethod() { + Map<String, List<ParameterSet>> map = new HashMap<>(); + List<ParameterSet> listA = new ArrayList<>(); + listA.add(new ParameterSet().value("a").name("testWithValue_a")); + List<ParameterSet> listB = new ArrayList<>(); + listB.add(new ParameterSet().value(1).name("testWithValue_1")); + List<ParameterSet> listC = new ArrayList<>(); + listC.add(new ParameterSet().value(10).name("extra")); + map.put("A", listA); + map.put("B", listB); + map.put("C", listC); + ParameterizedRunnerDelegateFactory.generateUnmodifiableFrameworkMethodList( + new TestClass(ExampleTestClass.class), map, ""); + } +}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java new file mode 100644 index 0000000..40978a7 --- /dev/null +++ b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java
@@ -0,0 +1,201 @@ +// 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. + +package org.chromium.base.test.params; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runner.Runner; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.TestClass; + +import org.chromium.base.test.params.ParameterAnnotations.ClassParameter; +import org.chromium.base.test.params.ParameterAnnotations.MethodParameter; +import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter; +import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; +import org.chromium.base.test.params.ParameterizedRunner.IllegalParameterArgumentException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Test for org.chromium.base.test.params.ParameterizedRunner + */ +@RunWith(BlockJUnit4ClassRunner.class) +public class ParameterizedRunnerTest { + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class TestClassWithPrivateParameterSetList { + @ClassParameter + private static List<ParameterSet> sClassParams = new ArrayList<>(); + + static { + sClassParams.add(new ParameterSet().value(1)); + sClassParams.add(new ParameterSet().value(2)); + } + + @MethodParameter("A") + private static List<ParameterSet> sMethodParamA = new ArrayList<>(); + + static { + sMethodParamA.add(new ParameterSet().value("a", "b")); + } + + public TestClassWithPrivateParameterSetList(int x) {} + + @Test + @UseMethodParameter("A") + public void test(String a, String b) {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class TestClassWithDefaultParameterSetList { + @ClassParameter + static List<ParameterSet> sClassParams = new ArrayList<>(); + + static { + sClassParams.add(new ParameterSet().value(1, 2)); + } + + @MethodParameter("A") + static List<ParameterSet> sMethodParamA = new ArrayList<>(); + + static { + sMethodParamA.add(new ParameterSet().value(null)); + } + + public TestClassWithDefaultParameterSetList(int a, int b) {} + + @Test + @UseMethodParameter("A") + public void test(String x) {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class BadTestClassWithMoreThanOneConstructor { + @ClassParameter + static List<ParameterSet> sClassParams = new ArrayList<>(); + + public BadTestClassWithMoreThanOneConstructor() {} + + public BadTestClassWithMoreThanOneConstructor(String x) {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class BadTestClassWithNonListParameters { + @ClassParameter + static String[] sMethodParamA = {"1", "2"}; + + @Test + public void test() {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class BadTestClassWithoutNeedForParameterization { + @Test + public void test() {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class BadTestClassWithNonStaticParameterSetList { + @ClassParameter + public List<ParameterSet> sClassParams = new ArrayList<>(); + + @Test + public void test() {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class BadTestClassWithMissingMethodParameter { + @MethodParameter("A") + private static List<ParameterSet> sParameterSetListA = new ArrayList<>(); + + @MethodParameter("B") + private static List<ParameterSet> sParameterSetListB = new ArrayList<>(); + + @Test + @UseMethodParameter("A") + public void testA() {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class BadTestClassWithMultipleClassParameter { + @ClassParameter + private static List<ParameterSet> sParamA = new ArrayList<>(); + + @ClassParameter + private static List<ParameterSet> sParamB = new ArrayList<>(); + } + + @Test + public void testPrivateAccessible() throws Throwable { + TestClass testClass = new TestClass(TestClassWithPrivateParameterSetList.class); + List<Runner> runners = ParameterizedRunner.createRunners(testClass); + Assert.assertEquals(runners.size(), 2); + Map<String, List<ParameterSet>> generatedMap = + ParameterizedRunner.generateMethodParameterMap(testClass); + Assert.assertEquals(generatedMap.keySet().size(), 1); + Assert.assertTrue(generatedMap.keySet().contains("A")); + Assert.assertEquals(generatedMap.get("A").size(), 1); + } + + @Test + public void testDefaultAccessible() throws Throwable { + TestClass testClass = new TestClass(TestClassWithDefaultParameterSetList.class); + List<Runner> runners = ParameterizedRunner.createRunners(testClass); + Assert.assertEquals(runners.size(), 1); + Map<String, List<ParameterSet>> generatedMap = + ParameterizedRunner.generateMethodParameterMap(testClass); + Assert.assertEquals(generatedMap.keySet().size(), 1); + Assert.assertTrue(generatedMap.keySet().contains("A")); + Assert.assertEquals(generatedMap.get("A").size(), 1); + } + + @Test(expected = ParameterizedRunner.IllegalParameterArgumentException.class) + public void testUnequalWidthParameterSetList() { + List<ParameterSet> paramList = new ArrayList<>(); + paramList.add(new ParameterSet().value(1, 2)); + paramList.add(new ParameterSet().value(3, 4, 5)); + ParameterizedRunner.validateWidth(paramList); + } + + @Test(expected = ParameterizedRunner.IllegalParameterArgumentException.class) + public void testUnequalWidthParameterSetListWithNull() { + List<ParameterSet> paramList = new ArrayList<>(); + paramList.add(new ParameterSet().value(null)); + paramList.add(new ParameterSet().value(1, 2)); + ParameterizedRunner.validateWidth(paramList); + } + + @Test(expected = IllegalArgumentException.class) + public void testBadClassWithNonListParameters() throws Throwable { + ParameterizedRunner runner = + new ParameterizedRunner(BadTestClassWithNonListParameters.class); + } + + @Test(expected = IllegalParameterArgumentException.class) + public void testBadClassWithNonStaticParameterSetList() throws Throwable { + ParameterizedRunner runner = + new ParameterizedRunner(BadTestClassWithNonStaticParameterSetList.class); + } + + @Test(expected = AssertionError.class) + public void testBadClassWithMissingMethodParameter() throws Throwable { + ParameterizedRunner runner = + new ParameterizedRunner(BadTestClassWithMissingMethodParameter.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testBadClassWithoutNeedForParameterization() throws Throwable { + ParameterizedRunner runner = + new ParameterizedRunner(BadTestClassWithoutNeedForParameterization.class); + } + + @Test(expected = Exception.class) + public void testBadClassWithMoreThanOneConstructor() throws Throwable { + ParameterizedRunner runner = + new ParameterizedRunner(BadTestClassWithMoreThanOneConstructor.class); + } +}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java new file mode 100644 index 0000000..7072757 --- /dev/null +++ b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java
@@ -0,0 +1,197 @@ +// 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. + +package org.chromium.base.test.params; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runner.Runner; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.TestClass; + +import org.chromium.base.test.params.ParameterAnnotations.ClassParameter; +import org.chromium.base.test.params.ParameterAnnotations.MethodParameter; +import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter; +import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * Test for verify the names and test method Description works properly + */ +@RunWith(BlockJUnit4ClassRunner.class) +public class ParameterizedTestNameTest { + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class TestClassWithClassParameterAppendName { + @ClassParameter + static List<ParameterSet> sAllName = new ArrayList<>(); + static { + sAllName.add(new ParameterSet().value("hello").name("Hello")); + sAllName.add(new ParameterSet().value("world").name("World")); + } + + public TestClassWithClassParameterAppendName(String a) {} + + @Test + public void test() {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class TestClassWithClassParameterDefaultName { + @ClassParameter + static List<ParameterSet> sAllName = new ArrayList<>(); + static { + sAllName.add(new ParameterSet().value("hello")); + sAllName.add(new ParameterSet().value("world")); + } + + public TestClassWithClassParameterDefaultName(String a) {} + + @Test + public void test() {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class TestClassWithMethodParameter { + @MethodParameter("A") + static List<ParameterSet> sAppendName = new ArrayList<>(); + static { + sAppendName.add(new ParameterSet().value("hello").name("Hello")); + sAppendName.add(new ParameterSet().value("world").name("World")); + } + + @MethodParameter("B") + static List<ParameterSet> sDefaultName = new ArrayList<>(); + static { + sDefaultName.add(new ParameterSet().value("hello")); + sDefaultName.add(new ParameterSet().value("world")); + } + + @UseMethodParameter("A") + @Test + public void test(String a) {} + + @UseMethodParameter("B") + @Test + public void testDefaultName(String b) {} + } + + @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) + public static class TestClassWithMixedParameter { + @ClassParameter + static List<ParameterSet> sAllName = new ArrayList<>(); + static { + sAllName.add(new ParameterSet().value("hello").name("Hello")); + sAllName.add(new ParameterSet().value("world").name("World")); + } + + @MethodParameter("A") + static List<ParameterSet> sAppendName = new ArrayList<>(); + static { + sAppendName.add(new ParameterSet().value("1").name("A")); + sAppendName.add(new ParameterSet().value("2").name("B")); + } + + public TestClassWithMixedParameter(String a) {} + + @UseMethodParameter("A") + @Test + public void testA(String a) {} + + @Test + public void test() {} + } + + @Test + public void testClassParameterAppendName() throws Throwable { + List<Runner> runners = ParameterizedRunner.createRunners( + new TestClass(TestClassWithClassParameterAppendName.class)); + List<String> expectedTestNames = + new LinkedList<String>(Arrays.asList(new String[] {"test__Hello", "test__World"})); + List<String> computedMethodNames = new ArrayList<>(); + for (Runner r : runners) { + BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r; + for (FrameworkMethod method : castedRunner.computeTestMethods()) { + computedMethodNames.add(method.getName()); + Assert.assertTrue("This test name is not expected: " + method.getName(), + expectedTestNames.contains(method.getName())); + expectedTestNames.remove(method.getName()); + method.getName(); + } + } + Assert.assertTrue( + String.format( + "These names were provided: %s, these expected names are not found: %s", + Arrays.toString(computedMethodNames.toArray()), + Arrays.toString(expectedTestNames.toArray())), + expectedTestNames.isEmpty()); + } + + @Test + public void testClassParameterDefaultName() throws Throwable { + List<Runner> runners = ParameterizedRunner.createRunners( + new TestClass(TestClassWithClassParameterDefaultName.class)); + List<String> expectedTestNames = + new LinkedList<String>(Arrays.asList(new String[] {"test", "test"})); + for (Runner r : runners) { + @SuppressWarnings("unchecked") + BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r; + for (FrameworkMethod method : castedRunner.computeTestMethods()) { + Assert.assertTrue("This test name is not expected: " + method.getName(), + expectedTestNames.contains(method.getName())); + expectedTestNames.remove(method.getName()); + method.getName(); + } + } + Assert.assertTrue("These expected names are not found: " + + Arrays.toString(expectedTestNames.toArray()), + expectedTestNames.isEmpty()); + } + + @Test + public void testMethodParameter() throws Throwable { + List<Runner> runners = ParameterizedRunner.createRunners( + new TestClass(TestClassWithMethodParameter.class)); + List<String> expectedTestNames = new LinkedList<String>(Arrays.asList( + new String[] {"test__Hello", "test__World", "testDefaultName", "testDefaultName"})); + for (Runner r : runners) { + BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r; + for (FrameworkMethod method : castedRunner.computeTestMethods()) { + Assert.assertTrue("This test name is not expected: " + method.getName(), + expectedTestNames.contains(method.getName())); + expectedTestNames.remove(method.getName()); + method.getName(); + } + } + Assert.assertTrue("These expected names are not found: " + + Arrays.toString(expectedTestNames.toArray()), + expectedTestNames.isEmpty()); + } + + @Test + public void testMixedParameterTestA() throws Throwable { + List<Runner> runners = + ParameterizedRunner.createRunners(new TestClass(TestClassWithMixedParameter.class)); + List<String> expectedTestNames = new LinkedList<String>( + Arrays.asList(new String[] {"testA__Hello_A", "testA__World_A", "testA__Hello_B", + "testA__World_B", "test__Hello", "test__World"})); + for (Runner r : runners) { + BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r; + for (FrameworkMethod method : castedRunner.computeTestMethods()) { + Assert.assertTrue("This test name is not expected: " + method.getName(), + expectedTestNames.contains(method.getName())); + expectedTestNames.remove(method.getName()); + method.getName(); + } + } + Assert.assertTrue("These expected names are not found: " + + Arrays.toString(expectedTestNames.toArray()), + expectedTestNames.isEmpty()); + } +}
diff --git a/base/threading/sequenced_task_runner_handle.cc b/base/threading/sequenced_task_runner_handle.cc index 6bb11dc..19e995f 100644 --- a/base/threading/sequenced_task_runner_handle.cc +++ b/base/threading/sequenced_task_runner_handle.cc
@@ -54,8 +54,8 @@ // Note if you hit this: the problem isn't the lack of a |pool|, it's the lack // of a sequenced context above. The |pool| is just the last desperate attempt // at finding such a context from the deprecated SequencedWorkerPool. - DCHECK(pool) << "Error: This caller requires a sequenced context (i.e. the " - "current task needs to run from a SequencedTaskRunner)."; + CHECK(pool) << "Error: This caller requires a sequenced context (i.e. the " + "current task needs to run from a SequencedTaskRunner)."; SequencedWorkerPool::SequenceToken sequence_token = SequencedWorkerPool::GetSequenceTokenForCurrentThread(); DCHECK(sequence_token.IsValid());
diff --git a/base/threading/thread_task_runner_handle.cc b/base/threading/thread_task_runner_handle.cc index d71cabb..8bc1014 100644 --- a/base/threading/thread_task_runner_handle.cc +++ b/base/threading/thread_task_runner_handle.cc
@@ -25,7 +25,9 @@ // static scoped_refptr<SingleThreadTaskRunner> ThreadTaskRunnerHandle::Get() { ThreadTaskRunnerHandle* current = lazy_tls_ptr.Pointer()->Get(); - DCHECK(current); + CHECK(current) << "Error: This caller requires a single-threaded context " + "(i.e. the current task needs to run from a " + "SingleThreadTaskRunner)."; return current->task_runner_; }
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index 3bc927a..807ee3c 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -60,14 +60,9 @@ public: ScopedImageFlags(ImageProvider* image_provider, const PaintFlags& flags, - const SkMatrix& ctm) - : decoded_flags_(flags) { + const SkMatrix& ctm) { DCHECK(IsImageShader(flags)); - // Remove the original shader from the flags. In case we fail to decode the - // image, the shader should be removed. - decoded_flags_.setShader(nullptr); - const PaintImage& paint_image = flags.getShader()->paint_image(); SkMatrix matrix = flags.getShader()->GetLocalMatrix(); @@ -94,18 +89,21 @@ PaintImage decoded_paint_image = PaintImageBuilder(std::move(paint_image)) .set_image(std::move(sk_image)) .TakePaintImage(); - decoded_flags_.setFilterQuality(decoded_image.filter_quality()); - decoded_flags_.setShader( + decoded_flags_.emplace(flags); + decoded_flags_.value().setFilterQuality(decoded_image.filter_quality()); + decoded_flags_.value().setShader( PaintShader::MakeImage(decoded_paint_image, flags.getShader()->tx(), flags.getShader()->ty(), &matrix)); } - PaintFlags* decoded_flags() { return &decoded_flags_; } + PaintFlags* decoded_flags() { + return decoded_flags_ ? &decoded_flags_.value() : nullptr; + } ~ScopedImageFlags() = default; private: - PaintFlags decoded_flags_; + base::Optional<PaintFlags> decoded_flags_; ImageProvider::ScopedDecodedDrawImage scoped_decoded_draw_image_; DISALLOW_COPY_AND_ASSIGN(ScopedImageFlags); @@ -131,6 +129,10 @@ scoped_flags.emplace(params.image_provider, flags_op->flags, canvas->getTotalMatrix()); decoded_flags = scoped_flags.value().decoded_flags(); + + // If we failed to decode the flags, skip the op. + if (!decoded_flags) + return; } if (!decoded_flags->SupportsFoldingAlpha()) { @@ -1837,7 +1839,12 @@ if (flags_op && IsImageShader(flags_op->flags)) { ScopedImageFlags scoped_flags(image_provider, flags_op->flags, canvas->getTotalMatrix()); - flags_op->RasterWithFlags(canvas, scoped_flags.decoded_flags(), params); + + // Only rasterize the op if we successfully decoded the image. + if (scoped_flags.decoded_flags()) { + flags_op->RasterWithFlags(canvas, scoped_flags.decoded_flags(), + params); + } continue; } }
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 2c4ead41..6eef674 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -2821,6 +2821,8 @@ class MockImageProvider : public ImageProvider { public: MockImageProvider() = default; + explicit MockImageProvider(bool fail_all_decodes) + : fail_all_decodes_(fail_all_decodes) {} MockImageProvider(std::vector<SkSize> src_rect_offset, std::vector<SkSize> scale, std::vector<SkFilterQuality> quality) @@ -2832,6 +2834,9 @@ const SkRect& src_rect, SkFilterQuality filter_quality, const SkMatrix& matrix) override { + if (fail_all_decodes_) + return ScopedDecodedDrawImage(); + SkBitmap bitmap; bitmap.allocN32Pixels(10, 10); sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); @@ -2845,6 +2850,7 @@ std::vector<SkSize> scale_; std::vector<SkFilterQuality> quality_; size_t index_ = 0; + bool fail_all_decodes_ = false; }; TEST(PaintOpBufferTest, SkipsOpsOutsideClip) { @@ -2884,6 +2890,26 @@ buffer.Playback(&canvas, &image_provider); } +TEST(PaintOpBufferTest, SkipsOpsWithFailedDecodes) { + MockImageProvider image_provider(true); + PaintOpBuffer buffer; + + PaintFlags flags; + PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10)); + buffer.push<DrawImageOp>(paint_image, 105.0f, 105.0f, &flags); + PaintFlags image_flags; + image_flags.setShader( + PaintShader::MakeImage(paint_image, SkShader::TileMode::kRepeat_TileMode, + SkShader::TileMode::kRepeat_TileMode, nullptr)); + buffer.push<DrawRectOp>(SkRect::MakeXYWH(110, 110, 100, 100), image_flags); + buffer.push<DrawColorOp>(SK_ColorRED, SkBlendMode::kSrcOver); + + testing::StrictMock<MockCanvas> canvas; + testing::Sequence s; + EXPECT_CALL(canvas, OnDrawPaintWithColor(_)).InSequence(s); + buffer.Playback(&canvas, &image_provider); +} + MATCHER(NonLazyImage, "") { return !arg->isLazyGenerated(); }
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 00903c8..ad5557d 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -553,11 +553,7 @@ bool element_id_collision_detected = existing_layer && existing_layer != layer; - // TODO(pdr): Remove this suppression and always check for id collisions. - // This is a temporary suppression for SPV2 which generates unnecessary - // layers that collide. Remove once crbug.com/693693 is fixed. - if (!settings().use_layer_lists) - DCHECK(!element_id_collision_detected); + DCHECK(!element_id_collision_detected); #endif element_layers_map_[element_id] = layer->id();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index a460ba0..49b623a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -529,9 +529,6 @@ urlFocusChangedCallback); mFindToolbarManager = new FindToolbarManager( this, mToolbarManager.getActionModeController().getActionModeCallback()); - if (getContextualSearchManager() != null) { - getContextualSearchManager().setFindToolbarManager(mFindToolbarManager); - } mAppMenuHandler.addObserver(new AppMenuObserver() { @Override public void onMenuVisibilityChanged(boolean isVisible) { @@ -786,6 +783,9 @@ if (isContextualSearchAllowed() && ContextualSearchFieldTrial.isEnabled()) { mContextualSearchManager = new ContextualSearchManager(this, this); + if (mFindToolbarManager != null) { + mContextualSearchManager.setFindToolbarManager(mFindToolbarManager); + } } if (ReaderModeManager.isEnabled(this)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/OWNERS new file mode 100644 index 0000000..62b0cec --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/OWNERS
@@ -0,0 +1,4 @@ +yusufo@chromium.org + +# COMPONENT: UI>Browser>Mobile>CustomTabs +# OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java new file mode 100644 index 0000000..21698f9 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java
@@ -0,0 +1,71 @@ +// 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. + +package org.chromium.chrome.browser.download; + +import android.app.Notification; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.support.annotation.Nullable; + +import org.chromium.chrome.browser.AppHooks; + +/** + * Keep-alive foreground service for downloads. + */ +public class DownloadForegroundService extends Service { + private final IBinder mBinder = new LocalBinder(); + + /** + * Start the foreground service with this given context. + * @param context The context used to start service. + */ + public static void startDownloadForegroundService(Context context) { + AppHooks.get().startForegroundService(new Intent(context, DownloadForegroundService.class)); + } + + /** + * Update the foreground service to be pinned to a different notification. + * @param notificationId The id of the new notification to be pinned to. + * @param notification The new notification to be pinned to. + */ + public void startOrUpdateForegroundService(int notificationId, Notification notification) { + // TODO(jming): Make sure there is not weird UI in switching the pinned notification. + startForeground(notificationId, notification); + } + + /** + * Stop the foreground service that is running. + * @param isComplete If the download has been complete and, therefore, if its notification + * should be killed. + */ + public void stopDownloadForegroundService(boolean isComplete) { + // TODO(jming): Check to make sure the notification does not get killed. + stopForeground(isComplete /* killNotification */); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // This should restart service after Chrome gets killed (except for Android 4.4.2). + return START_STICKY; + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + /** + * Class for clients to access. + */ + public class LocalBinder extends Binder { + DownloadForegroundService getService() { + return DownloadForegroundService.this; + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java new file mode 100644 index 0000000..a7a3684 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java
@@ -0,0 +1,220 @@ +// 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. + +package org.chromium.chrome.browser.download; + +import static org.chromium.chrome.browser.download.DownloadSnackbarController.INVALID_NOTIFICATION_ID; + +import android.app.Notification; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; + +import org.chromium.base.ContextUtils; +import org.chromium.base.Log; +import org.chromium.base.VisibleForTesting; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * Manager to stop and start the foreground service associated with downloads. + */ +public class DownloadForegroundServiceManager { + public enum DownloadStatus { START, PAUSE, RESUME, CANCEL, COMPLETE } + private static class DownloadUpdate { + int mNotificationId; + Notification mNotification; + DownloadStatus mDownloadStatus; + Context mContext; + + DownloadUpdate(int notificationId, Notification notification, DownloadStatus downloadStatus, + Context context) { + mNotificationId = notificationId; + mNotification = notification; + mDownloadStatus = downloadStatus; + mContext = context; + } + } + + private static final String TAG = "DownloadFgSManager"; + + @VisibleForTesting + final Map<Integer, DownloadUpdate> mDownloadUpdateQueue = new HashMap<>(); + + private int mPinnedNotificationId = INVALID_NOTIFICATION_ID; + + // This is true when context.bindService has been called and before context.unbindService. + private boolean mIsServiceBound; + // This is non-null when onServiceConnected has been called (aka service is active). + private DownloadForegroundService mBoundService; + + public DownloadForegroundServiceManager() {} + + public void updateDownloadStatus(Context context, DownloadStatus downloadStatus, + int notificationId, Notification notification) { + mDownloadUpdateQueue.put(notificationId, + new DownloadUpdate(notificationId, notification, downloadStatus, context)); + processDownloadUpdateQueue(false /* not isProcessingPending */); + } + + /** + * Process the notification queue for all cases and initiate any needed actions. + * In the happy path, the logic should be: + * bindAndStartService -> startOrUpdateForegroundService -> stopAndUnbindService. + * @param isProcessingPending Whether the call was made to process pending notifications that + * have accumulated in the queue during the startup process or if it + * was made based on during a basic update. + */ + @VisibleForTesting + void processDownloadUpdateQueue(boolean isProcessingPending) { + DownloadUpdate downloadUpdate = findInterestingDownloadUpdate(); + if (downloadUpdate == null) return; + + // When nothing has been initialized, just bind the service. + if (!mIsServiceBound) { + // If the download update is not active at the onset, don't even start the service! + if (!isActive(downloadUpdate.mDownloadStatus)) { + cleanDownloadUpdateQueue(); + return; + } + startAndBindService(downloadUpdate.mContext); + return; + } + + // Skip everything that happens while waiting for startup. + if (mBoundService == null) return; + + // In the pending case, start foreground with specific notificationId and notification. + if (isProcessingPending) { + startOrUpdateForegroundService( + downloadUpdate.mNotificationId, downloadUpdate.mNotification); + } + + // If the selected downloadUpdate is not active, there are no active downloads left. + // Stop the foreground service. + // In the pending case, this will stop the foreground immediately after it was started. + if (!isActive(downloadUpdate.mDownloadStatus)) { + stopAndUnbindService(downloadUpdate.mDownloadStatus == DownloadStatus.COMPLETE); + cleanDownloadUpdateQueue(); + return; + } + + // Make sure the pinned notification is still active, if not, update. + if (mDownloadUpdateQueue.get(mPinnedNotificationId) == null + || !isActive(mDownloadUpdateQueue.get(mPinnedNotificationId).mDownloadStatus)) { + startOrUpdateForegroundService( + downloadUpdate.mNotificationId, downloadUpdate.mNotification); + } + + // Clear out inactive download updates in queue if there is at least one active download. + cleanDownloadUpdateQueue(); + } + + /** Helper code to process download update queue. */ + + @Nullable + private DownloadUpdate findInterestingDownloadUpdate() { + Iterator<Map.Entry<Integer, DownloadUpdate>> entries = + mDownloadUpdateQueue.entrySet().iterator(); + while (entries.hasNext()) { + Map.Entry<Integer, DownloadUpdate> entry = entries.next(); + // Return an active entry if possible. + if (isActive(entry.getValue().mDownloadStatus)) return entry.getValue(); + // If there are no active entries, just return the last entry. + if (!entries.hasNext()) return entry.getValue(); + } + // If there's no entries, return null. + return null; + } + + private boolean isActive(DownloadStatus downloadStatus) { + return downloadStatus == DownloadStatus.START || downloadStatus == DownloadStatus.RESUME; + } + + private void cleanDownloadUpdateQueue() { + Iterator<Map.Entry<Integer, DownloadUpdate>> entries = + mDownloadUpdateQueue.entrySet().iterator(); + while (entries.hasNext()) { + Map.Entry<Integer, DownloadUpdate> entry = entries.next(); + // Remove entry that is not active. + if (!isActive(entry.getValue().mDownloadStatus)) entries.remove(); + } + } + + /** Helper code to bind service. */ + + @VisibleForTesting + void startAndBindService(Context context) { + mIsServiceBound = true; + startAndBindServiceInternal(context); + } + + @VisibleForTesting + void startAndBindServiceInternal(Context context) { + DownloadForegroundService.startDownloadForegroundService(context); + ContextUtils.getApplicationContext().bindService( + new Intent(ContextUtils.getApplicationContext(), DownloadForegroundService.class), + mConnection, Context.BIND_AUTO_CREATE); + } + + private final ServiceConnection mConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + if (!(service instanceof DownloadForegroundService.LocalBinder)) { + Log.w(TAG, + "Not from DownloadNotificationService, do not connect." + + " Component name: " + className); + return; + } + mBoundService = ((DownloadForegroundService.LocalBinder) service).getService(); + processDownloadUpdateQueue(true /* isProcessingPending */); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + mBoundService = null; + } + }; + + /** Helper code to start or update foreground service. */ + + @VisibleForTesting + void startOrUpdateForegroundService(int notificationId, Notification notification) { + if (mBoundService != null && notificationId != INVALID_NOTIFICATION_ID + && notification != null) { + mPinnedNotificationId = notificationId; + mBoundService.startOrUpdateForegroundService(notificationId, notification); + } + } + + /** Helper code to stop and unbind service. */ + + @VisibleForTesting + void stopAndUnbindService(boolean isComplete) { + mIsServiceBound = false; + if (mBoundService != null) { + stopAndUnbindServiceInternal(isComplete); + mBoundService = null; + } + } + + @VisibleForTesting + void stopAndUnbindServiceInternal(boolean isComplete) { + mBoundService.stopDownloadForegroundService(isComplete); + ContextUtils.getApplicationContext().unbindService(mConnection); + } + + /** Helper code for testing. */ + + @VisibleForTesting + void setBoundService(DownloadForegroundService service) { + mBoundService = service; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java index f294aac..c6848b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java
@@ -91,7 +91,8 @@ .createChromeNotificationBuilder( true /* preferCompat */, ChannelDefinitions.CHANNEL_ID_DOWNLOADS) .setLocalOnly(true) - .setGroup(NotificationConstants.GROUP_DOWNLOADS); + .setGroup(NotificationConstants.GROUP_DOWNLOADS) + .setAutoCancel(true); String contentText; int iconId; @@ -222,6 +223,8 @@ downloadUpdate.getContentId().namespace); intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_ID, downloadUpdate.getNotificationId()); + DownloadUtils.setOriginalUrlAndReferralExtraToIntent(intent, + downloadUpdate.getOriginalUrl(), downloadUpdate.getReferrer()); } else { intent = buildActionIntent(context, ACTION_DOWNLOAD_OPEN, downloadUpdate.getContentId(), false); @@ -269,7 +272,9 @@ downloadUpdate.getFileName(), MAX_FILE_NAME_LENGTH)); } if (downloadUpdate.getIcon() != null) builder.setLargeIcon(downloadUpdate.getIcon()); - if (!downloadUpdate.getIsTransient() && downloadUpdate.getNotificationId() != -1) { + if (!downloadUpdate.getIsTransient() && downloadUpdate.getNotificationId() != -1 + && downloadStatus != DownloadStatus.SUCCESSFUL + && downloadStatus != DownloadStatus.FAILED) { Intent downloadHomeIntent = buildActionIntent(context, ACTION_NOTIFICATION_CLICKED, null, false); builder.setContentIntent(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java index d7c25ae..60bf46c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -895,6 +895,8 @@ .setIsOpenable(isOpenable) .setIcon(icon) .setNotificationId(notificationId) + .setOriginalUrl(originalUrl) + .setReferrer(referrer) .build(); Notification notification = DownloadNotificationFactory.buildNotification( mContext, DownloadNotificationFactory.DownloadStatus.SUCCESSFUL, downloadUpdate);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUpdate.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUpdate.java index 1ab3439..47dbb2d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUpdate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUpdate.java
@@ -25,7 +25,9 @@ private final boolean mIsSupportedMimeType; private final boolean mIsTransient; private final int mNotificationId; + private final String mOriginalUrl; private final Progress mProgress; + private final String mReferrer; private final long mStartTime; private final long mSystemDownloadId; private final long mTimeRemainingInMillis; @@ -42,7 +44,9 @@ this.mIsSupportedMimeType = builder.mIsSupportedMimeType; this.mIsTransient = builder.mIsTransient; this.mNotificationId = builder.mNotificationId; + this.mOriginalUrl = builder.mOriginalUrl; this.mProgress = builder.mProgress; + this.mReferrer = builder.mReferrer; this.mStartTime = builder.mStartTime; this.mSystemDownloadId = builder.mSystemDownloadId; this.mTimeRemainingInMillis = builder.mTimeRemainingInMillis; @@ -92,10 +96,18 @@ return mNotificationId; } + public String getOriginalUrl() { + return mOriginalUrl; + } + public Progress getProgress() { return mProgress; } + public String getReferrer() { + return mReferrer; + } + public long getStartTime() { return mStartTime; } @@ -123,7 +135,9 @@ private boolean mIsSupportedMimeType; private boolean mIsTransient; private int mNotificationId = -1; + private String mOriginalUrl; private Progress mProgress; + private String mReferrer; private long mStartTime; private long mSystemDownloadId = -1; private long mTimeRemainingInMillis; @@ -183,11 +197,21 @@ return this; } + public Builder setOriginalUrl(String originalUrl) { + this.mOriginalUrl = originalUrl; + return this; + } + public Builder setProgress(Progress progress) { this.mProgress = progress; return this; } + public Builder setReferrer(String referrer) { + this.mReferrer = referrer; + return this; + } + public Builder setStartTime(long startTime) { this.mStartTime = startTime; return this;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java index a2dca7f1..6a2dbb5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java
@@ -92,4 +92,6 @@ // For example, 'Web:chromium.org' for a notification from chromium.org. static final String GROUP_WEB_PREFIX = "Web:"; + // Default notificationId until it has been set. + public static final int DEFAULT_NOTIFICATION_ID = -1; }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 12e9c24b..7150fed 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -327,6 +327,8 @@ "java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java", "java/src/org/chromium/chrome/browser/download/DownloadBroadcastReceiver.java", "java/src/org/chromium/chrome/browser/download/DownloadController.java", + "java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java", + "java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java", "java/src/org/chromium/chrome/browser/download/DownloadInfo.java", "java/src/org/chromium/chrome/browser/download/DownloadItem.java", "java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java", @@ -1429,6 +1431,7 @@ "javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java", "javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java", "javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java", + "javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java", "javatests/src/org/chromium/chrome/browser/download/DownloadTest.java", "javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java", "javatests/src/org/chromium/chrome/browser/download/DownloadUtilsTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index 005a8e32..f9d50e2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -64,11 +64,13 @@ import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelUtils; +import org.chromium.chrome.browser.widget.findinpage.FindToolbar; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeRestriction; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.FullscreenTestUtils; +import org.chromium.chrome.test.util.MenuUtils; import org.chromium.chrome.test.util.OmniboxTestUtils; import org.chromium.components.navigation_interception.NavigationParams; import org.chromium.content.browser.ContentViewCore; @@ -3107,4 +3109,35 @@ ContextualSearchInternalStateControllerWrapper.EXPECTED_LONGPRESS_SEQUENCE, internalStateControllerWrapper.getFinishedStates()); } + + @Test + @SmallTest + @Feature({"ContextualSearch"}) + public void testLongPressHidesFindInPageOverlay() throws Exception { + MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(), + mActivityTestRule.getActivity(), R.id.find_in_page_id); + + CriteriaHelper.pollUiThread(new Criteria() { + @Override + public boolean isSatisfied() { + FindToolbar findToolbar = + (FindToolbar) mActivityTestRule.getActivity().findViewById( + R.id.find_toolbar); + return findToolbar != null && findToolbar.isShown() && !findToolbar.isAnimating(); + } + }); + + KeyUtils.singleKeyEventView(InstrumentationRegistry.getInstrumentation(), + mActivityTestRule.getActivity().findViewById(R.id.find_query), KeyEvent.KEYCODE_T); + + View findToolbar = mActivityTestRule.getActivity().findViewById(R.id.find_toolbar); + Assert.assertTrue(findToolbar.isShown()); + + longPressNode("states"); + + waitForPanelToPeek(); + Assert.assertFalse( + "Find Toolbar should no longer be shown once Contextual Search Panel appeared", + findToolbar.isShown()); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java new file mode 100644 index 0000000..39e47e96 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java
@@ -0,0 +1,271 @@ +// 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. + +package org.chromium.chrome.browser.download; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import static org.chromium.chrome.browser.download.DownloadForegroundServiceManager.DownloadStatus; +import static org.chromium.chrome.browser.notifications.NotificationConstants.DEFAULT_NOTIFICATION_ID; + +import android.app.Notification; +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.AdvancedMockContext; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.notifications.NotificationBuilderFactory; +import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; + +/** + * Test for DownloadForegroundServiceManager. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +public final class DownloadForegroundServiceManagerTest { + private static final int FAKE_DOWNLOAD_1 = 111; + private static final int FAKE_DOWNLOAD_2 = 222; + private static final int FAKE_DOWNLOAD_3 = 333; + private static final String FAKE_NOTIFICATION_CHANNEL = "DownloadForegroundServiceManagerTest"; + + private MockDownloadForegroundServiceManager mDownloadServiceManager; + private Notification mNotification; + private Context mContext; + + /** + * Implementation of DownloadServiceManager for testing purposes. + * Generally mimics behavior of DownloadForegroundServiceManager except: + * - Tracks a few variables for testing purposes (mIsServiceBound, mUpdateNotificationId, etc). + * - Does not actually execute code related to starting and stopping the service + * (startAndBindServiceInternal, etc) to not have have to handle test service lifecycle. + */ + public static class MockDownloadForegroundServiceManager + extends DownloadForegroundServiceManager { + private boolean mIsServiceBound; + private int mUpdatedNotificationId = DEFAULT_NOTIFICATION_ID; + private boolean mIsNotificationKilled; + + public MockDownloadForegroundServiceManager() {} + + @Override + void startAndBindService(Context context) { + mIsServiceBound = true; + super.startAndBindService(context); + } + + @Override + void startAndBindServiceInternal(Context context) {} + + @Override + void stopAndUnbindService(boolean isComplete) { + mIsNotificationKilled = isComplete; + mIsServiceBound = false; + super.stopAndUnbindService(isComplete); + } + + @Override + void stopAndUnbindServiceInternal(boolean isComplete) {} + + @Override + void startOrUpdateForegroundService(int notificationId, Notification notification) { + mUpdatedNotificationId = notificationId; + super.startOrUpdateForegroundService(notificationId, notification); + } + } + + /** + * Implementation of DownloadForegroundService for testing. + * Does not implement startOrUpdateForegroundService to avoid test service lifecycle. + */ + public static class MockDownloadForegroundService extends DownloadForegroundService { + @Override + public void startOrUpdateForegroundService(int notificationId, Notification notification) {} + } + + /** + * Call for testing that mimics the onServiceConnected call in mConnection that ensures the + * mBoundService is non-null and the pending queue is processed. + */ + private void onServiceConnected() { + mDownloadServiceManager.setBoundService(new MockDownloadForegroundService()); + mDownloadServiceManager.processDownloadUpdateQueue(true /* isProcessingPending */); + } + + @Before + public void setUp() throws Exception { + mContext = new AdvancedMockContext( + InstrumentationRegistry.getInstrumentation().getTargetContext()); + mDownloadServiceManager = new MockDownloadForegroundServiceManager(); + + mNotification = + NotificationBuilderFactory + .createChromeNotificationBuilder( + true /* preferCompat */, ChannelDefinitions.CHANNEL_ID_DOWNLOADS) + .setSmallIcon(org.chromium.chrome.R.drawable.ic_file_download_white_24dp) + .setContentTitle(FAKE_NOTIFICATION_CHANNEL) + .setContentText(FAKE_NOTIFICATION_CHANNEL) + .build(); + } + + @Test + @SmallTest + @Feature({"Download"}) + public void testBasicStartAndStop() { + // Service starts and stops with addition and removal of one active download. + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_1, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + onServiceConnected(); + + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.COMPLETE, FAKE_DOWNLOAD_1, mNotification); + assertFalse(mDownloadServiceManager.mIsServiceBound); + + // Service does not get affected by addition of inactive download. + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_1, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + onServiceConnected(); + + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.PAUSE, FAKE_DOWNLOAD_2, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + + // Service continues as long as there is at least one active download. + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_3, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.PAUSE, FAKE_DOWNLOAD_1, mNotification); + assertEquals(FAKE_DOWNLOAD_3, mDownloadServiceManager.mUpdatedNotificationId); + assertTrue(mDownloadServiceManager.mIsServiceBound); + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.COMPLETE, FAKE_DOWNLOAD_3, mNotification); + assertFalse(mDownloadServiceManager.mIsServiceBound); + } + + @Test + @SmallTest + @Feature({"Download"}) + public void testDelayedStartStop() { + // Calls to start and stop service. + assertFalse(mDownloadServiceManager.mIsServiceBound); + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_1, mNotification); + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.COMPLETE, FAKE_DOWNLOAD_1, mNotification); + + assertTrue(mDownloadServiceManager.mIsServiceBound); + + // Service actually starts, should be shut down immediately. + onServiceConnected(); + assertFalse(mDownloadServiceManager.mIsServiceBound); + } + + @Test + @SmallTest + @Feature({"Download"}) + public void testDelayedStartStopStart() { + // Calls to start and stop and start service. + assertFalse(mDownloadServiceManager.mIsServiceBound); + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_1, mNotification); + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.COMPLETE, FAKE_DOWNLOAD_1, mNotification); + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_2, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + + // Service actually starts, continues and is pinned to second download. + onServiceConnected(); + assertTrue(mDownloadServiceManager.mIsServiceBound); + assertEquals(FAKE_DOWNLOAD_2, mDownloadServiceManager.mUpdatedNotificationId); + + // Make sure service is able to be shut down. + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.COMPLETE, FAKE_DOWNLOAD_2, mNotification); + assertFalse(mDownloadServiceManager.mIsServiceBound); + } + + @Test + @SmallTest + @Feature({"Download"}) + public void testIsNotificationKilled() { + // Service starts and is paused, is not complete, so notification not killed. + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_1, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + onServiceConnected(); + + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.PAUSE, FAKE_DOWNLOAD_1, mNotification); + assertFalse(mDownloadServiceManager.mIsServiceBound); + assertFalse(mDownloadServiceManager.mIsNotificationKilled); + + // Service restarts and then completes, so notification is killed. + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.RESUME, FAKE_DOWNLOAD_1, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + onServiceConnected(); + + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.COMPLETE, FAKE_DOWNLOAD_1, mNotification); + assertFalse(mDownloadServiceManager.mIsServiceBound); + assertTrue(mDownloadServiceManager.mIsNotificationKilled); + } + + @Test + @SmallTest + @Feature({"Download"}) + public void testStopInitiallyAndCleanQueue() { + // First call is a download being cancelled. + assertFalse(mDownloadServiceManager.mIsServiceBound); + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.CANCEL, FAKE_DOWNLOAD_1, mNotification); + + // Make sure that nothing gets called, service is still not bound, and queue is empty. + assertFalse(mDownloadServiceManager.mIsServiceBound); + assertTrue(mDownloadServiceManager.mDownloadUpdateQueue.isEmpty()); + + // Start next two downloads. + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_2, mNotification); + assertEquals(1, mDownloadServiceManager.mDownloadUpdateQueue.size()); + assertTrue(mDownloadServiceManager.mIsServiceBound); + onServiceConnected(); + + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.START, FAKE_DOWNLOAD_3, mNotification); + assertEquals(2, mDownloadServiceManager.mDownloadUpdateQueue.size()); + assertTrue(mDownloadServiceManager.mIsServiceBound); + + // Queue is cleaned as each download becomes inactive (paused or complete). + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.PAUSE, FAKE_DOWNLOAD_2, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + assertEquals(1, mDownloadServiceManager.mDownloadUpdateQueue.size()); + + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.RESUME, FAKE_DOWNLOAD_2, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + assertEquals(2, mDownloadServiceManager.mDownloadUpdateQueue.size()); + + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.COMPLETE, FAKE_DOWNLOAD_2, mNotification); + assertTrue(mDownloadServiceManager.mIsServiceBound); + assertEquals(1, mDownloadServiceManager.mDownloadUpdateQueue.size()); + + mDownloadServiceManager.updateDownloadStatus( + mContext, DownloadStatus.COMPLETE, FAKE_DOWNLOAD_3, mNotification); + assertTrue(mDownloadServiceManager.mDownloadUpdateQueue.isEmpty()); + assertFalse(mDownloadServiceManager.mIsServiceBound); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java index 5731a1ff..f9d4d81 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
@@ -247,7 +247,7 @@ @Test @MediumTest @Feature({"Webapps"}) - public void testWebappRequiresValidMac() { + public void testWebappRequiresValidMac() throws Exception { // Try to start a WebappActivity. Fail because the Intent is insecure. fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, false); CriteriaHelper.pollUiThread(new Criteria() {
diff --git a/chrome/app/chrome_manifest.json b/chrome/app/chrome_manifest.json index 6c0181a5..659767d 100644 --- a/chrome/app/chrome_manifest.json +++ b/chrome/app/chrome_manifest.json
@@ -11,6 +11,9 @@ ], "mash:launchable": [ "mash::mojom::Launchable" + ], + "renderer": [ + "startup_metric_utils::mojom::StartupMetricHost" ] }, "requires": {
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd index 897a3c7..a9754a6 100644 --- a/chrome/app/resources/locale_settings.grd +++ b/chrome/app/resources/locale_settings.grd
@@ -201,9 +201,6 @@ <message name="IDS_IMPORTLOCK_DIALOG_WIDTH_CHARS" use_name_for_id="true"> 50 </message> - <message name="IDS_IMPORTLOCK_DIALOG_HEIGHT_LINES" use_name_for_id="true"> - 8 - </message> <!-- The URL for the the Welcome to Chrome page shown on first run. --> <message name="IDS_WELCOME_PAGE_URL" translateable="false">
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index df27f4c6..e8262fd 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -111,7 +111,11 @@ } if (is_chromeos) { - icons += [ "arc_migrate_encryption_notification.icon" ] + icons += [ + "arc_migrate_encryption_notification.icon", + "warning_badge_circle.1x.icon", + "warning_badge_circle.icon", + ] } }
diff --git a/chrome/app/vector_icons/warning_badge_circle.1x.icon b/chrome/app/vector_icons/warning_badge_circle.1x.icon new file mode 100644 index 0000000..f1a8abc --- /dev/null +++ b/chrome/app/vector_icons/warning_badge_circle.1x.icon
@@ -0,0 +1,23 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 40, +MOVE_TO, 32.93f, 26, +CUBIC_TO, 29.11f, 26, 26, 29.11f, 26, 32.95f, +R_CUBIC_TO, 0, 3.83f, 3.11f, 6.95f, 6.93f, 6.95f, +R_CUBIC_TO, 3.83f, 0, 6.93f, -3.11f, 6.93f, -6.94f, +CUBIC_TO_SHORTHAND, 36.76f, 26, 32.93f, 26, +CLOSE, +NEW_PATH, +PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF, +MOVE_TO, 33.5f, 36.04f, +H_LINE_TO, 32, +V_LINE_TO, 34.5f, +R_H_LINE_TO, 1.5f, +MOVE_TO, 33.5f, 33.5f, +H_LINE_TO, 32, +V_LINE_TO, 30, +R_H_LINE_TO, 1.5f, +CLOSE, +END
diff --git a/chrome/app/vector_icons/warning_badge_circle.icon b/chrome/app/vector_icons/warning_badge_circle.icon new file mode 100644 index 0000000..e7418ee10 --- /dev/null +++ b/chrome/app/vector_icons/warning_badge_circle.icon
@@ -0,0 +1,23 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 80, +MOVE_TO, 65.87f, 52, +CUBIC_TO, 58.21f, 52, 52, 58.22f, 52, 65.89f, +R_CUBIC_TO, 0, 7.67f, 6.21f, 13.89f, 13.87f, 13.89f, +R_CUBIC_TO, 7.65f, 0, 13.87f, -6.22f, 13.87f, -13.89f, +R_CUBIC_TO, 0, -7.67f, -6.21f, -13.89f, -13.87f, -13.89f, +CLOSE, +NEW_PATH, +PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF, +MOVE_TO, 67, 72.09f, +R_H_LINE_TO, -3, +V_LINE_TO, 69, +R_H_LINE_TO, 3, +MOVE_TO, 67, 67, +R_H_LINE_TO, -3, +R_V_LINE_TO, -7, +R_H_LINE_TO, 3, +CLOSE, +END
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 889fe37..b1f3d01 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -234,6 +234,8 @@ "chrome_notification_types.h", "chrome_quota_permission_context.cc", "chrome_quota_permission_context.h", + "chrome_service.cc", + "chrome_service.h", "command_observer.h", "command_updater.cc", "command_updater.h",
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc index 90172b82..5bf9c27 100644 --- a/chrome/browser/browser_process_platform_part_chromeos.cc +++ b/chrome/browser/browser_process_platform_part_chromeos.cc
@@ -27,11 +27,7 @@ #include "chrome/browser/lifetime/keep_alive_types.h" #include "chrome/browser/lifetime/scoped_keep_alive.h" #include "chrome/browser/prefs/active_profile_pref_service.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/ash_util.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chromeos/geolocation/simple_geolocation_provider.h" @@ -39,7 +35,6 @@ #include "components/session_manager/core/session_manager.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/discardable_shared_memory_manager.h" -#include "mash/public/interfaces/launchable.mojom.h" #include "services/preferences/public/interfaces/preferences.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -57,82 +52,6 @@ #endif namespace { -// Packaged service implementation used to expose miscellaneous application -// control features. This is a singleton service which runs on the main thread -// and never stops. -class ChromeServiceChromeOS : public service_manager::Service, - public mash::mojom::Launchable { - public: - ChromeServiceChromeOS() { -#if defined(USE_OZONE) - input_device_controller_.AddInterface(&interfaces_); -#endif - interfaces_.AddInterface<mash::mojom::Launchable>( - base::Bind(&ChromeServiceChromeOS::Create, base::Unretained(this))); - } - ~ChromeServiceChromeOS() override {} - - static std::unique_ptr<service_manager::Service> CreateService() { - return base::MakeUnique<ChromeServiceChromeOS>(); - } - - private: - void CreateNewWindowImpl(bool is_incognito) { - Profile* profile = ProfileManager::GetActiveUserProfile(); - chrome::NewEmptyWindow(is_incognito ? profile->GetOffTheRecordProfile() - : profile); - } - - // service_manager::Service: - void OnBindInterface(const service_manager::BindSourceInfo& remote_info, - const std::string& name, - mojo::ScopedMessagePipeHandle handle) override { - interfaces_.BindInterface(name, std::move(handle), remote_info); - } - - // mash::mojom::Launchable: - void Launch(uint32_t what, mash::mojom::LaunchMode how) override { - bool is_incognito; - switch (what) { - case mash::mojom::kWindow: - is_incognito = false; - break; - case mash::mojom::kIncognitoWindow: - is_incognito = true; - break; - default: - NOTREACHED(); - } - - bool reuse = how != mash::mojom::LaunchMode::MAKE_NEW; - if (reuse) { - Profile* profile = ProfileManager::GetActiveUserProfile(); - Browser* browser = chrome::FindTabbedBrowser( - is_incognito ? profile->GetOffTheRecordProfile() : profile, false); - if (browser) { - browser->window()->Show(); - return; - } - } - - CreateNewWindowImpl(is_incognito); - } - - void Create(mash::mojom::LaunchableRequest request, - const service_manager::BindSourceInfo& source_info) { - bindings_.AddBinding(this, std::move(request)); - } - - service_manager::BinderRegistryWithArgs< - const service_manager::BindSourceInfo&> - interfaces_; - mojo::BindingSet<mash::mojom::Launchable> bindings_; -#if defined(USE_OZONE) - ui::InputDeviceController input_device_controller_; -#endif - - DISALLOW_COPY_AND_ASSIGN(ChromeServiceChromeOS); -}; std::unique_ptr<service_manager::Service> CreateEmbeddedUIService( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, @@ -268,13 +187,6 @@ content::ContentBrowserClient::StaticServiceMap* services) { { service_manager::EmbeddedServiceInfo info; - info.factory = base::Bind(&ChromeServiceChromeOS::CreateService); - info.task_runner = base::ThreadTaskRunnerHandle::Get(); - services->insert(std::make_pair(chromeos::kChromeServiceName, info)); - } - - { - service_manager::EmbeddedServiceInfo info; info.factory = base::Bind([] { return std::unique_ptr<service_manager::Service>( base::MakeUnique<ActiveProfilePrefService>());
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index aef9739..c9312f8 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -40,6 +40,7 @@ #include "chrome/browser/cache_stats_recorder.h" #include "chrome/browser/chrome_content_browser_client_parts.h" #include "chrome/browser/chrome_quota_permission_context.h" +#include "chrome/browser/chrome_service.h" #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/tab_specific_content_settings.h" @@ -110,6 +111,7 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/constants.mojom.h" #include "chrome/common/env_vars.h" #include "chrome/common/features.h" #include "chrome/common/logging_chrome.h" @@ -157,7 +159,6 @@ #include "components/security_interstitials/core/ssl_error_ui.h" #include "components/signin/core/common/profile_management_switches.h" #include "components/spellcheck/spellcheck_build_features.h" -#include "components/startup_metric_utils/browser/startup_metric_host_impl.h" #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" #include "components/task_scheduler_util/browser/initialization.h" #include "components/task_scheduler_util/common/variations_util.h" @@ -2858,9 +2859,6 @@ content::BrowserThread::GetTaskRunnerForThread( content::BrowserThread::UI); registry->AddInterface( - base::Bind(&startup_metric_utils::StartupMetricHostImpl::Create), - ui_task_runner); - registry->AddInterface( base::Bind(&BudgetServiceImpl::Create, render_process_host->GetID()), ui_task_runner); #if BUILDFLAG(ENABLE_SPELLCHECK) @@ -2987,6 +2985,11 @@ void ChromeContentBrowserClient::RegisterInProcessServices( StaticServiceMap* services) { + { + service_manager::EmbeddedServiceInfo info; + info.factory = base::Bind(&ChromeService::Create); + services->insert(std::make_pair(chrome::mojom::kServiceName, info)); + } if (g_browser_process->pref_service_factory()) { service_manager::EmbeddedServiceInfo info; info.factory =
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json index 128b9b6a..b6a631e 100644 --- a/chrome/browser/chrome_content_browser_manifest_overlay.json +++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -17,7 +17,6 @@ "safe_browsing::mojom::SafeBrowsing", "spellcheck::mojom::SpellCheckHost", "spellcheck::mojom::SpellCheckPanelHost", - "startup_metric_utils::mojom::StartupMetricHost", "translate::mojom::ContentTranslateDriver" ], "url_keyed_metrics": [
diff --git a/chrome/browser/chrome_content_renderer_manifest_overlay.json b/chrome/browser/chrome_content_renderer_manifest_overlay.json index 9179941..770cae6 100644 --- a/chrome/browser/chrome_content_renderer_manifest_overlay.json +++ b/chrome/browser/chrome_content_renderer_manifest_overlay.json
@@ -9,6 +9,9 @@ "spellcheck::mojom::SpellChecker", "profiling::mojom::MemlogClient" ] + }, + "requires": { + "chrome": [ "renderer" ] } }, "navigation:frame": {
diff --git a/chrome/browser/chrome_service.cc b/chrome/browser/chrome_service.cc new file mode 100644 index 0000000..372235e --- /dev/null +++ b/chrome/browser/chrome_service.cc
@@ -0,0 +1,33 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chrome_service.h" + +#include "components/startup_metric_utils/browser/startup_metric_host_impl.h" + +// static +std::unique_ptr<service_manager::Service> ChromeService::Create() { + return base::MakeUnique<ChromeService>(); +} + +ChromeService::ChromeService() { +#if defined(USE_OZONE) + input_device_controller_.AddInterface(®istry_); +#endif +#if defined(OS_CHROMEOS) + registry_.AddInterface( + base::Bind(&chromeos::Launchable::Bind, base::Unretained(&launchable_))); +#endif + registry_.AddInterface( + base::Bind(&startup_metric_utils::StartupMetricHostImpl::Create)); +} + +ChromeService::~ChromeService() {} + +void ChromeService::OnBindInterface( + const service_manager::BindSourceInfo& remote_info, + const std::string& name, + mojo::ScopedMessagePipeHandle handle) { + registry_.TryBindInterface(name, &handle); +}
diff --git a/chrome/browser/chrome_service.h b/chrome/browser/chrome_service.h new file mode 100644 index 0000000..ffc1f9f6 --- /dev/null +++ b/chrome/browser/chrome_service.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROME_SERVICE_H_ +#define CHROME_BROWSER_CHROME_SERVICE_H_ + +#include "services/service_manager/public/cpp/binder_registry.h" +#include "services/service_manager/public/cpp/service.h" + +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/launchable.h" +#endif +#if defined(USE_OZONE) +#include "services/ui/public/cpp/input_devices/input_device_controller.h" +#endif + +class ChromeService : public service_manager::Service { + public: + ChromeService(); + ~ChromeService() override; + + static std::unique_ptr<service_manager::Service> Create(); + + private: + // service_manager::Service: + void OnBindInterface(const service_manager::BindSourceInfo& remote_info, + const std::string& name, + mojo::ScopedMessagePipeHandle handle) override; + + service_manager::BinderRegistry registry_; + +#if defined(OS_CHROMEOS) + chromeos::Launchable launchable_; +#endif +#if defined(USE_OZONE) + ui::InputDeviceController input_device_controller_; +#endif + + DISALLOW_COPY_AND_ASSIGN(ChromeService); +}; + +#endif // CHROME_BROWSER_CHROME_SERVICE_H_
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 15bad25..1c1fe0f 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -11,6 +11,7 @@ import("//ui/ozone/ozone.gni") assert(is_chromeos) +assert(use_ozone) source_set("chromeos") { assert(enable_extensions, "ChromeOS Chrome has to be built with extensions") @@ -768,6 +769,8 @@ "input_method/mode_indicator_controller.h", "language_preferences.cc", "language_preferences.h", + "launchable.cc", + "launchable.h", "launcher_search_provider/error_reporter.cc", "launcher_search_provider/error_reporter.h", "launcher_search_provider/launcher_search_provider_service.cc",
diff --git a/chrome/browser/chromeos/arc/arc_support_host.cc b/chrome/browser/chromeos/arc/arc_support_host.cc index 39a22dd..31e917f 100644 --- a/chrome/browser/chromeos/arc/arc_support_host.cc +++ b/chrome/browser/chromeos/arc/arc_support_host.cc
@@ -462,13 +462,14 @@ DCHECK(message_host_); auto loadtime_data = base::MakeUnique<base::DictionaryValue>(); - base::string16 device_name = ash::GetChromeOSDeviceName(); loadtime_data->SetString( - "greetingHeader", - l10n_util::GetStringFUTF16(IDS_ARC_OPT_IN_DIALOG_HEADER, device_name)); - loadtime_data->SetString("greetingDescription", - l10n_util::GetStringFUTF16( - IDS_ARC_OPT_IN_DIALOG_DESCRIPTION, device_name)); + "greetingHeader", l10n_util::GetStringUTF16(IDS_ARC_OOBE_TERMS_HEADING)); + loadtime_data->SetString( + "loadingDescription", + l10n_util::GetStringUTF16(IDS_ARC_OPT_IN_DIALOG_PROGRESS_LSO)); + loadtime_data->SetString( + "greetingDescription", + l10n_util::GetStringUTF16(IDS_ARC_OOBE_TERMS_DESCRIPTION)); loadtime_data->SetString( "buttonAgree", l10n_util::GetStringUTF16(IDS_ARC_OPT_IN_DIALOG_BUTTON_AGREE));
diff --git a/chrome/browser/chromeos/launchable.cc b/chrome/browser/chromeos/launchable.cc new file mode 100644 index 0000000..c3d3701 --- /dev/null +++ b/chrome/browser/chromeos/launchable.cc
@@ -0,0 +1,54 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/launchable.h" + +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window.h" + +namespace chromeos { + +Launchable::Launchable() {} +Launchable::~Launchable() {} + +void Launchable::Bind(mash::mojom::LaunchableRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void Launchable::Launch(uint32_t what, mash::mojom::LaunchMode how) { + bool is_incognito; + switch (what) { + case mash::mojom::kWindow: + is_incognito = false; + break; + case mash::mojom::kIncognitoWindow: + is_incognito = true; + break; + default: + NOTREACHED(); + } + + bool reuse = how != mash::mojom::LaunchMode::MAKE_NEW; + if (reuse) { + Profile* profile = ProfileManager::GetActiveUserProfile(); + Browser* browser = chrome::FindTabbedBrowser( + is_incognito ? profile->GetOffTheRecordProfile() : profile, false); + if (browser) { + browser->window()->Show(); + return; + } + } + + CreateNewWindowImpl(is_incognito); +} + +void Launchable::CreateNewWindowImpl(bool is_incognito) { + Profile* profile = ProfileManager::GetActiveUserProfile(); + chrome::NewEmptyWindow(is_incognito ? profile->GetOffTheRecordProfile() + : profile); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/launchable.h b/chrome/browser/chromeos/launchable.h new file mode 100644 index 0000000..08ec105 --- /dev/null +++ b/chrome/browser/chromeos/launchable.h
@@ -0,0 +1,34 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LAUNCHABLE_H_ +#define CHROME_BROWSER_CHROMEOS_LAUNCHABLE_H_ + +#include "base/macros.h" +#include "mash/public/interfaces/launchable.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" + +namespace chromeos { + +class Launchable : public mash::mojom::Launchable { + public: + Launchable(); + ~Launchable() override; + + void Bind(mash::mojom::LaunchableRequest request); + + private: + // mash::mojom::Launchable: + void Launch(uint32_t what, mash::mojom::LaunchMode how) override; + + void CreateNewWindowImpl(bool is_incognito); + + mojo::BindingSet<mash::mojom::Launchable> bindings_; + + DISALLOW_COPY_AND_ASSIGN(Launchable); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LAUNCHABLE_H_
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc index 54b6f10..92181d0 100644 --- a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc +++ b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc
@@ -206,7 +206,9 @@ action_data->action_type = extensions::api::app_runtime::ActionType::ACTION_TYPE_NEW_NOTE; action_data->is_lock_screen_action = base::MakeUnique<bool>(true); - + action_data->restore_last_action_state = + base::MakeUnique<bool>(primary_profile_->GetPrefs()->GetBoolean( + prefs::kRestoreLastLockScreenNote)); apps::LaunchPlatformAppWithAction(lock_screen_profile_, app, std::move(action_data), base::FilePath()); return true;
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc index 22a1eb3..4ff90d6e 100644 --- a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc
@@ -88,9 +88,14 @@ ASSERT_TRUE(launch_data->action_data); EXPECT_EQ(extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE, launch_data->action_data->action_type); + ASSERT_TRUE(launch_data->action_data->is_lock_screen_action); EXPECT_TRUE(*launch_data->action_data->is_lock_screen_action); + ASSERT_TRUE(launch_data->action_data->restore_last_action_state); + EXPECT_EQ(expect_restore_action_state_, + *launch_data->action_data->restore_last_action_state); + launched_apps_.push_back(extension_id); } @@ -100,9 +105,14 @@ void ClearLaunchedApps() { launched_apps_.clear(); } + void set_expect_restore_action_state(bool expect_restore_action_state) { + expect_restore_action_state_ = expect_restore_action_state; + } + private: std::vector<std::string> launched_apps_; content::BrowserContext* context_; + bool expect_restore_action_state_ = true; DISALLOW_COPY_AND_ASSIGN(TestEventRouter); }; @@ -1020,6 +1030,40 @@ EXPECT_TRUE(event_router->launched_apps().empty()); } +TEST_P(LockScreenAppManagerImplTest, LaunchAppWithFalseRestoreLastActionState) { + TestEventRouter* event_router = static_cast<TestEventRouter*>( + extensions::EventRouterFactory::GetInstance()->SetTestingFactoryAndUse( + lock_screen_profile()->GetOriginalProfile(), + &TestEventRouterFactoryFunction)); + ASSERT_TRUE(event_router); + + event_router->set_expect_restore_action_state(false); + profile()->GetPrefs()->SetBoolean(prefs::kRestoreLastLockScreenNote, false); + + scoped_refptr<const extensions::Extension> note_taking_app = + AddTestAppWithLockScreenSupport( + profile(), chromeos::NoteTakingHelper::kProdKeepExtensionId, "1.0", + true /* enable_on_lock_screen */); + + InitializeAndStartAppManager(profile()); + RunExtensionServiceTaskRunner(lock_screen_profile()); + + ASSERT_EQ(chromeos::NoteTakingHelper::kProdKeepExtensionId, + app_manager()->GetNoteTakingAppId()); + + EXPECT_TRUE(app_manager()->LaunchNoteTaking()); + + ASSERT_EQ(1u, event_router->launched_apps().size()); + EXPECT_EQ(chromeos::NoteTakingHelper::kProdKeepExtensionId, + event_router->launched_apps()[0]); + event_router->ClearLaunchedApps(); + + app_manager()->Stop(); + + EXPECT_FALSE(app_manager()->LaunchNoteTaking()); + EXPECT_TRUE(event_router->launched_apps().empty()); +} + TEST_P(LockScreenAppManagerImplTest, LaunchAppWhenNoLockScreenApp) { TestEventRouter* event_router = static_cast<TestEventRouter*>( extensions::EventRouterFactory::GetInstance()->SetTestingFactoryAndUse(
diff --git a/chrome/browser/chromeos/lock_screen_apps/note_taking_browsertest.cc b/chrome/browser/chromeos/lock_screen_apps/note_taking_browsertest.cc index 752bf4b0..31855376 100644 --- a/chrome/browser/chromeos/lock_screen_apps/note_taking_browsertest.cc +++ b/chrome/browser/chromeos/lock_screen_apps/note_taking_browsertest.cc
@@ -208,3 +208,47 @@ extensions::ResultCatcher catcher; ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); } + +IN_PROC_BROWSER_TEST_F(LockScreenNoteTakingTest, AppLaunchActionDataParams) { + ASSERT_TRUE(lock_screen_apps::StateController::IsEnabled()); + + scoped_refptr<const extensions::Extension> app = LoadExtension( + test_data_dir_.AppendASCII("lock_screen_apps/app_launch_action_data")); + ASSERT_TRUE(app); + ASSERT_TRUE(EnableLockScreenAppLaunch(app->id())); + + extensions::ResultCatcher catcher; + + lock_screen_apps::StateController::Get()->RequestNewLockScreenNote(); + ASSERT_EQ(ash::mojom::TrayActionState::kLaunching, + lock_screen_apps::StateController::Get()->GetLockScreenNoteState()); + + ExtensionTestMessageListener expected_action_data("getExpectedActionData", + true /* will_reply */); + + ASSERT_TRUE(expected_action_data.WaitUntilSatisfied()); + expected_action_data.Reply(R"({"actionType": "new_note", + "isLockScreenAction": true, + "restoreLastActionState": true})"); + ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); + expected_action_data.Reset(); + + // Reset the lock screen app state by resetting screen lock, so the app is + // launchable again. + session_manager::SessionManager::Get()->SetSessionState( + session_manager::SessionState::ACTIVE); + session_manager::SessionManager::Get()->SetSessionState( + session_manager::SessionState::LOCKED); + + profile()->GetPrefs()->SetBoolean(prefs::kRestoreLastLockScreenNote, false); + + lock_screen_apps::StateController::Get()->RequestNewLockScreenNote(); + ASSERT_EQ(ash::mojom::TrayActionState::kLaunching, + lock_screen_apps::StateController::Get()->GetLockScreenNoteState()); + + ASSERT_TRUE(expected_action_data.WaitUntilSatisfied()); + expected_action_data.Reply(R"({"actionType": "new_note", + "isLockScreenAction": true, + "restoreLastActionState": false})"); + ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); +}
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc index 89e19b5..8f376eb 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -64,7 +64,6 @@ #include "content/public/common/service_manager_connection.h" #include "crypto/sha2.h" #include "services/service_manager/public/cpp/connector.h" -#include "ui/gfx/color_analysis.h" #include "url/gurl.h" using content::BrowserThread; @@ -204,7 +203,6 @@ // A helper to set the wallpaper image for Classic Ash and Mash. void SetWallpaper(const gfx::ImageSkia& image, wallpaper::WallpaperInfo info) { - WallpaperManager::Get()->CalculateProminentColor(image); if (ash_util::IsRunningInMash()) { // In mash, connect to the WallpaperController interface via mojo. service_manager::Connector* connector = @@ -397,10 +395,6 @@ WallpaperManager::~WallpaperManager() { show_user_name_on_signin_subscription_.reset(); device_wallpaper_image_subscription_.reset(); - if (color_calculator_) { - color_calculator_->RemoveObserver(this); - color_calculator_.reset(); - } user_manager::UserManager::Get()->RemoveSessionStateObserver(this); weak_factory_.InvalidateWeakPtrs(); } @@ -424,11 +418,6 @@ wallpaper_manager = nullptr; } -// static -bool WallpaperManager::HasInstance() { - return wallpaper_manager != nullptr; -} - bool WallpaperManager::IsPendingWallpaper(uint32_t image_id) { for (size_t i = 0; i < loading_.size(); ++i) { if (loading_[i]->GetImageId() == image_id) { @@ -438,32 +427,6 @@ return false; } -void WallpaperManager::CalculateProminentColor(const gfx::ImageSkia& image) { - // Cancel in-flight color calculations, if any. - if (color_calculator_) { - color_calculator_->RemoveObserver(this); - color_calculator_.reset(); - } - - // TODO(wzang): the color fetching should go through ash::WallpaperController. - // See crbug.com/733709. - std::vector<color_utils::ColorProfile> color_profiles; - color_profiles.emplace_back(color_utils::LumaRange::DARK, - color_utils::SaturationRange::MUTED); - color_calculator_ = base::MakeUnique<wallpaper::WallpaperColorCalculator>( - image, color_profiles, task_runner_); - color_calculator_->AddObserver(this); - if (!color_calculator_->StartCalculation()) { - color_calculator_->RemoveObserver(this); - color_calculator_.reset(); - if (!prominent_color_.has_value()) - return; - prominent_color_.reset(); - for (auto& observer : observers_) - observer.OnWallpaperColorsChanged(); - } -} - WallpaperManager::WallpaperResolution WallpaperManager::GetAppropriateResolution() { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -961,20 +924,6 @@ user_manager::UserManager::Get()->GetActiveUser()->username_hash()); } -void WallpaperManager::OnColorCalculationComplete() { - size_t num_of_calculation = color_calculator_->prominent_colors().size(); - DCHECK_EQ(1u, num_of_calculation); - SkColor color = color_calculator_->prominent_colors()[num_of_calculation - 1]; - color_calculator_->RemoveObserver(this); - color_calculator_.reset(); - if (prominent_color_ == color) - return; - prominent_color_ = color; - - for (auto& observer : observers_) - observer.OnWallpaperColorsChanged(); -} - // WallpaperManager, private: -------------------------------------------------- WallpaperManager::WallpaperManager()
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h index 89e51b75..3de3f1e 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h
@@ -17,8 +17,6 @@ #include "chrome/browser/chromeos/customization/customization_wallpaper_downloader.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "components/user_manager/user_manager.h" -#include "components/wallpaper/wallpaper_color_calculator.h" -#include "components/wallpaper/wallpaper_color_calculator_observer.h" #include "components/wallpaper/wallpaper_manager_base.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -44,8 +42,7 @@ public content::NotificationObserver, public user_manager::UserManager::UserSessionStateObserver, public wm::ActivationChangeObserver, - public aura::WindowObserver, - public wallpaper::WallpaperColorCalculatorObserver { + public aura::WindowObserver { public: class PendingWallpaper; @@ -61,23 +58,10 @@ // WallpaperManager to remove any observers it has registered. static void Shutdown(); - // Checks whether the instance exists. In general, please refrain from using - // this function. Use Get() directly when needing to access the singleton. - // TODO(crbug.com/733709): Remove this function when color calculation for - // login screen is moved elsewhere. - static bool HasInstance(); - // Returns if the image is in the pending list. |image_id| can be obtained // from gfx::ImageSkia by using WallpaperResizer::GetImageId(). bool IsPendingWallpaper(uint32_t image_id); - // Calculates a prominent color based on the wallpaper image and notifies - // |observers_| of the value. An existing calculation in progress (if any) - // will be destroyed first. - void CalculateProminentColor(const gfx::ImageSkia& image); - - base::Optional<SkColor> prominent_color() const { return prominent_color_; } - // wallpaper::WallpaperManagerBase: WallpaperResolution GetAppropriateResolution() override; void AddObservers() override; @@ -133,9 +117,6 @@ // aura::WindowObserver: void OnWindowDestroying(aura::Window* window) override; - // wallpaper::WallpaperColorCalculatorObserver: - void OnColorCalculationComplete() override; - private: friend class TestApi; friend class WallpaperManagerBrowserTest; @@ -261,14 +242,6 @@ activation_client_observer_; ScopedObserver<aura::Window, aura::WindowObserver> window_observer_; - // The prominent color extracted from the current wallpaper. It doesn't have - // value if color extraction fails. - base::Optional<SkColor> prominent_color_; - - // TODO(crbug.com/733709): Remove color calculation here when the old signin - // screen implementation is deprecated. - std::unique_ptr<wallpaper::WallpaperColorCalculator> color_calculator_; - base::WeakPtrFactory<WallpaperManager> weak_factory_; DISALLOW_COPY_AND_ASSIGN(WallpaperManager);
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc index af2154e2..fed8052 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc
@@ -625,6 +625,7 @@ DISALLOW_COPY_AND_ASSIGN(TestObserver); }; +// TODO: test is flaky. http://crbug.com/691548. IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, DISABLED_DisplayChange) { TestObserver observer(WallpaperManager::Get());
diff --git a/chrome/browser/chromeos/net/tether_notification_presenter.cc b/chrome/browser/chromeos/net/tether_notification_presenter.cc index deaa8842..8b879cd 100644 --- a/chrome/browser/chromeos/net/tether_notification_presenter.cc +++ b/chrome/browser/chromeos/net/tether_notification_presenter.cc
@@ -9,6 +9,7 @@ #include "base/memory/ptr_util.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" @@ -16,6 +17,9 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia_operations.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/gfx/vector_icon_types.h" #include "ui/message_center/message_center.h" #include "ui/message_center/notification_types.h" #include "ui/message_center/notifier_settings.h" @@ -55,35 +59,51 @@ return std::min(std::max(normalized_signal_strength, 0), 4); } +std::unique_ptr<message_center::Notification> CreateNotificationWithBadge( + const std::string& id, + const base::string16& title, + const base::string16& message, + const message_center::RichNotificationData& rich_notification_data, + int signal_strength, + const gfx::VectorIcon& badge) { + gfx::ImageSkia icon = gfx::CanvasImageSource::MakeImageSkia< + ash::network_icon::SignalStrengthImageSource>( + ash::network_icon::BARS, gfx::kGoogleBlue500, kTetherSignalIconSize, + GetNormalizedSignalStrength(signal_strength)); + + if (!badge.is_empty()) { + gfx::ImageSkia badge_icon = gfx::CreateVectorIcon( + badge, kTetherSignalIconSize.height(), gfx::kGoogleRed700); + icon = gfx::ImageSkiaOperations::CreateIconWithBadge(icon, badge_icon); + } + + auto notification = base::MakeUnique<message_center::Notification>( + message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE, id, title, + message, gfx::Image(icon), base::string16() /* display_source */, + GURL() /* origin_url */, + message_center::NotifierId( + message_center::NotifierId::NotifierType::SYSTEM_COMPONENT, + ash::system_notifier::kNotifierTether), + rich_notification_data, nullptr); + notification->SetSystemPriority(); + return notification; +} + std::unique_ptr<message_center::Notification> CreateNotification( const std::string& id, const base::string16& title, const base::string16& message, - const message_center::RichNotificationData rich_notification_data, + const message_center::RichNotificationData& rich_notification_data, int signal_strength) { - auto source = base::MakeUnique<ash::network_icon::SignalStrengthImageSource>( - ash::network_icon::BARS, gfx::kGoogleBlue500, kTetherSignalIconSize, - GetNormalizedSignalStrength(signal_strength)); - std::unique_ptr<message_center::Notification> notification = - base::MakeUnique<message_center::Notification>( - message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE, id, title, - message, - gfx::Image(gfx::ImageSkia(std::move(source), kTetherSignalIconSize)), - base::string16() /* display_source */, GURL() /* origin_url */, - message_center::NotifierId( - message_center::NotifierId::NotifierType::SYSTEM_COMPONENT, - ash::system_notifier::kNotifierTether), - rich_notification_data, nullptr); - notification->SetSystemPriority(); - return notification; + return CreateNotificationWithBadge(id, title, message, rich_notification_data, + signal_strength, gfx::VectorIcon()); } std::unique_ptr<message_center::Notification> CreateNotificationWithMediumSignalStrengthIcon(const std::string& id, const base::string16& title, const base::string16& message) { - return CreateNotification(id, title, message, - message_center::RichNotificationData(), + return CreateNotification(id, title, message, {} /* rich_notification_data */, kMediumSignalStrength); } @@ -192,12 +212,14 @@ PA_LOG(INFO) << "Displaying \"connection attempt failed\" notification. " << "Notification ID = " << kActiveHostNotificationId; - ShowNotification(CreateNotificationWithMediumSignalStrengthIcon( + ShowNotification(CreateNotificationWithBadge( kActiveHostNotificationId, l10n_util::GetStringUTF16( IDS_TETHER_NOTIFICATION_CONNECTION_FAILED_TITLE), l10n_util::GetStringUTF16( - IDS_TETHER_NOTIFICATION_CONNECTION_FAILED_MESSAGE))); + IDS_TETHER_NOTIFICATION_CONNECTION_FAILED_MESSAGE), + {} /* rich_notification_data */, kMediumSignalStrength, + kWarningBadgeCircleIcon)); } void TetherNotificationPresenter::RemoveConnectionToHostFailedNotification() {
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index a9dc62b..c88005e 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -321,6 +321,7 @@ registry->RegisterBooleanPref(prefs::kNoteTakingAppEnabledOnLockScreen, false); registry->RegisterListPref(prefs::kNoteTakingAppsLockScreenWhitelist); + registry->RegisterBooleanPref(prefs::kRestoreLastLockScreenNote, true); // We don't sync wake-on-wifi related prefs because they are device specific. registry->RegisterBooleanPref(prefs::kWakeOnWifiDarkConnect, true);
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc index d316dde..533dd3d 100644 --- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc +++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
@@ -342,7 +342,7 @@ int render_process_id, int render_frame_id, const GURL& gurl, - bool is_same_page_navigation, + bool is_same_document_navigation, uint32_t page_transition, base::TimeTicks time) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -414,7 +414,7 @@ main_frame_it->second.data_use_recorder; old_frame_entry->set_page_transition(page_transition); - if (is_same_page_navigation) { + if (is_same_document_navigation) { std::vector<net::URLRequest*> pending_url_requests; entry->GetPendingURLRequests(&pending_url_requests); for (net::URLRequest* request : pending_url_requests) {
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h index eb9acad..7e629f4 100644 --- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h +++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h
@@ -96,7 +96,7 @@ void DidFinishMainFrameNavigation(int render_process_id, int render_frame_id, const GURL& gurl, - bool is_same_page_navigation, + bool is_same_document_navigation, uint32_t page_transition, base::TimeTicks time);
diff --git a/chrome/browser/dom_distiller/tab_utils_android.cc b/chrome/browser/dom_distiller/tab_utils_android.cc index d070eec..139c352 100644 --- a/chrome/browser/dom_distiller/tab_utils_android.cc +++ b/chrome/browser/dom_distiller/tab_utils_android.cc
@@ -61,9 +61,9 @@ // and pastes it into another program, that program may think the URL ends at // the space. return base::android::ConvertUTF16ToJavaString( - env, url_formatter::FormatUrl( - url, url_formatter::kFormatUrlOmitAll, - net::UnescapeRule::NORMAL, nullptr, nullptr, nullptr)); + env, url_formatter::FormatUrl(url, url_formatter::kFormatUrlOmitDefaults, + net::UnescapeRule::NORMAL, nullptr, nullptr, + nullptr)); } // Returns true if the distiller experiment is set to use any heuristic other
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 3ae7339..882be39 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -287,6 +287,8 @@ settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[chromeos::kAttestationForContentProtectionEnabled] = settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[prefs::kRestoreLastLockScreenNote] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; // Bluetooth & Internet settings. (*s_whitelist)[chromeos::kAllowBluetooth] =
diff --git a/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc b/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc index eba03820..34c2ace 100644 --- a/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc +++ b/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc
@@ -71,6 +71,7 @@ } void SetUpOnMainThread() override { + in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); extensions::PlatformAppBrowserTest::SetUpOnMainThread(); ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.cc b/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.cc index e30909b..342af30 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.cc +++ b/chrome/browser/offline_pages/prefetch/prefetch_importer_impl.cc
@@ -53,12 +53,22 @@ base::FilePath dest_path = archives_dir.Append(base::GenerateGUID()).AddExtension(kMHTMLExtension); + // For PrefetchArchiveInfo, |url| is the original URL while + // |final_archived_url| is the last committed URL which is set to empty when + // there is no redirect. + // + // For OfflinePageItem, |url| is the last committed URL while |original_url| + // is the original URL which is set to empty when there is no redirect. + // + // So when |PrefetchArchiveInfo.final_archived_url| is empty, + // |PrefetchArchiveInfo.url| denotes the sole URL which should be passed to + // |OfflinePageItem.url|. Otherwise, we should switch the urls for + // OfflinePageItem. GURL url, original_url; - if (archive.url != archive.final_archived_url) { - url = archive.final_archived_url; - original_url = archive.url; - } else { + if (archive.final_archived_url.is_empty()) { url = archive.url; + } else { + url = archive.final_archived_url; original_url = archive.url; } OfflinePageItem offline_page(url, archive.offline_id, archive.client_id,
diff --git a/chrome/browser/resources/chromeos/arc_support/background.js b/chrome/browser/resources/chromeos/arc_support/background.js index 91d507f4..38ae532 100644 --- a/chrome/browser/resources/chromeos/arc_support/background.js +++ b/chrome/browser/resources/chromeos/arc_support/background.js
@@ -43,13 +43,13 @@ * Host window inner default width. * @const {number} */ -var INNER_WIDTH = 960; +var INNER_WIDTH = 768; /** * Host window inner default height. * @const {number} */ -var INNER_HEIGHT = 687; +var INNER_HEIGHT = 640; /** @@ -85,6 +85,8 @@ this.checkbox_ = container.querySelector('.checkbox-option'); this.label_ = container.querySelector('.checkbox-text'); + this.label_.addEventListener( + 'click', () => this.onLabelClicked(this.label_)); var learnMoreLink = this.label_.querySelector(learnMoreLinkId); if (learnMoreLink) { @@ -133,8 +135,19 @@ /** * Called when the "Learn More" link is clicked. */ - onLearnMoreLinkClicked() { + onLearnMoreLinkClicked(event) { showTextOverlay(this.learnMoreContent_); + event.stopPropagation(); + } + + /** + * Called when preference label is clicked. Toggle the sibling checkbox. + */ + onLabelClicked(label) { + var checkbox = label.previousElementSibling; + if (checkbox && !checkbox.hidden) { + checkbox.checked = !checkbox.checked; + } } } @@ -191,7 +204,7 @@ /** Called when "settings" link is clicked. */ onSettingsLinkClicked(event) { chrome.browser.openTab({'url': 'chrome://settings'}, function() {}); - event.preventDefault(); + event.stopPropagation(); } } @@ -247,6 +260,7 @@ var scriptSetCountryCode = 'document.countryCode = \'' + countryCode.toLowerCase() + '\';'; + scriptSetCountryCode += 'document.viewMode = \'large-view\';'; this.termsView_.addContentScripts([ { name: 'preProcess', @@ -274,7 +288,6 @@ // On managed case, do not show TermsOfService section. Note that the // checkbox for the prefereces are still visible. var visibility = isManaged ? 'hidden' : 'visible'; - container.querySelector('#terms-title').style.visibility = visibility; container.querySelector('#terms-container').style.visibility = visibility; // Set event handler for buttons.
diff --git a/chrome/browser/resources/chromeos/arc_support/images/error_image.png b/chrome/browser/resources/chromeos/arc_support/images/error_image.png new file mode 100644 index 0000000..56a1cfd0 --- /dev/null +++ b/chrome/browser/resources/chromeos/arc_support/images/error_image.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/arc_support/main.css b/chrome/browser/resources/chromeos/arc_support/main.css index 147f2f3..aefc31d5 100644 --- a/chrome/browser/resources/chromeos/arc_support/main.css +++ b/chrome/browser/resources/chromeos/arc_support/main.css
@@ -13,6 +13,26 @@ width: 100%; } +.header { + color: rgba(0, 0, 0, 0.87); + font-family: Roboto, sans-serif; + padding: 64px 64px 0 64px; +} + +h1.title { + color: rgba(0, 0, 0, 0.87); + font-size: 28px; + font-weight: normal; + margin: 36px 0 0 0; /* = 64 - font height*/ +} + +.subtitle { + color: rgba(0, 0, 0, 0.87); + font-size: 13px; + margin: 23px 0 0 0; /* = 40 - 4 (adjustment) - line-height */ + padding-left: 64px; +} + ::-webkit-scrollbar { background: transparent; height: 4px; @@ -31,11 +51,12 @@ #arc-support { flex: auto; overflow: hidden; - width: 960px; + width: 100%; } #terms-view { - width: 640px; + display: block; + margin: auto; } .bubble-button > div { @@ -55,27 +76,30 @@ margin: 26px 18px 0 26px; } -.checkbox-option { - height: 12px; - margin: 0; - padding: 0; - width: 12px; +#button-retry, +#button-agree { + -webkit-margin-end: 18px; } .checkbox-text { color: rgba(0, 0, 0, 0.54); - font-size: 10px; + font-size: 13px; font-weight: 400; line-height: 16px; margin: 0; - padding: 0; } .content { - /* Default window inner height (687px) minus image caption height (300px) */ - height: 387px; + /* height plus padding equals 360px, which is app height (640px) minus icon + * header (96px), greeting header (64px), subtitle (40px) and bottom (80px). + */ + height: 338px; margin: 0; - padding: 0; + padding: 0 64px 12px 64px; +} + +.subcontentcontainer { + padding: 0 20px; } .controlled-setting-indicator { @@ -91,7 +115,13 @@ display: block; height: 300px; padding: 0; - width: 960px; + width: 100%; +} + +.error-image { + display: block; + margin: auto; + padding: 60px 0 0 0; } .icon-header { @@ -139,7 +169,7 @@ .section { display: flex; flex-direction: column; - text-align: center; + text-align: start; } .section-active-directory-auth { @@ -152,15 +182,17 @@ border: 1px solid #e6e6e6; color: rgba(0, 0, 0, 0.54); flex: auto; - height: 380px; + height: 333px; margin: 40px 64px 0 auto; overflow: hidden; } .section-buttons { - margin: auto; - padding: 16px 0 24px 0; - width: 640px; + box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.14); + height: 80px; + padding: 0; + z-index: 1; + width: 100% } .section-active-directory-auth-buttons { @@ -174,34 +206,16 @@ .section-checkbox-container { margin: auto; - padding: 8px 0 0 0; - text-align: left; - width: 640px; -} - -.section-checkbox-container > input[type='checkbox'] { - flex-shrink: 0; - margin: 0 8px 0 0; + padding-top: 16px; + width: 100%; } .section-terms { - border: 1px solid #e6e6e6; - color: rgba(0, 0, 0, 0.54); + border: 1px solid #d9d9d9; + box-sizing: border-box; flex: auto; - margin: 0 auto 8px auto; - overflow: hidden; + margin: 40px 0 0 0; padding: 0; - width: 640px; -} - -.text-desc { - color: rgba(0, 0, 0, 0.54); - font-size: 18px; - font-weight: 300; - line-height: 24px; - margin: auto; - padding: 16px 0 0 0; - width: 640px; } .text-active-directory-auth-title { @@ -225,32 +239,12 @@ padding: 11px 0 40px 0; } -.text-terms-title { - color: rgba(0, 0, 0, 0.54); - font-size: 10px; - font-weight: 500; - margin: auto; - padding: 10px 0 8px 0; - text-align: left; - width: 640px; -} - -.text-title { - color: rgba(0, 0, 0, 0.87); - font-size: 30px; - font-weight: 300; - line-height: 32px; - margin: auto; - padding: 4px 0 0 0; - width: 800px; -} - a:link { - color: rgb(51, 103, 214); + color: rgb(66, 133, 244); text-decoration: none; } a:visited { - color: rgb(51, 103, 214); + color: rgb(66, 133, 244); text-decoration: none; }
diff --git a/chrome/browser/resources/chromeos/arc_support/main.html b/chrome/browser/resources/chromeos/arc_support/main.html index e6552176..d6050e4d 100644 --- a/chrome/browser/resources/chromeos/arc_support/main.html +++ b/chrome/browser/resources/chromeos/arc_support/main.html
@@ -8,11 +8,18 @@ <link rel="stylesheet" href="chrome://resources/css/overlay.css"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> + <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <style is="custom-style" include="iron-flex iron-flex-alignment"> paper-button { - font-size: 13px; + border-radius: 2px; + border-style: solid; + border-width: 2px; + font: Roboto, sans-serif; + font-size: 12px; font-weight: 500; - padding: 9px 16px 8px 16px; + height: 32px; /* = 28px + 2 * 2px border */ + padding: 0 16px 0 16px; + text-transform: none; } paper-button.blue { background: rgb(66, 133, 244); @@ -20,7 +27,17 @@ } paper-button.white { background: white; - color: rgb(66, 133, 244); + border-color: rgba(0, 0, 0, 0.1); + color: rgba(0, 0, 0, 0.54); + } + paper-button[focused] { + border-color: rgba(66, 133, 244, 0.4); /* #4284f4 */ + } + paper-checkbox { + --paper-checkbox-size: 12px; + --paper-checkbox-checked-color: rgb(66, 133, 244); /* #4285f4 */ + --paper-checkbox-label-spacing: 20px; + --paper-checkbox-vertical-align: top; } </style> <link rel="stylesheet" href="main.css"> @@ -39,11 +56,14 @@ </head> <body> <div id="terms" class="section"> - <img class="image-header" src="images/header.png"> + <div class="header"> + <img class="icon-header" src="icon/playstore.svg"> + <h1 class="title" i18n-content="greetingHeader"></h1> + </div> <div class="scrollable" id="terms-of-service-loading"> + <p class="subtitle" i18n-content="progressLsoLoading"> + </p> <div class="content"> - <p class="text-title" i18n-content="greetingHeader"></p> - <p class="text-desc" i18n-content="greetingDescription"></p> <div class="progress-container"> <div class="progress-primary"></div> <div class="progress-secondary"></div> @@ -51,46 +71,50 @@ </div> </div> <div class="scrollable" id="terms-of-service-content" hidden> + <p class="subtitle" i18n-content="greetingDescription"> + </p> <div class="content section-flex"> - <p class="text-title" i18n-content="greetingHeader"></p> - <p class="text-desc" i18n-content="greetingDescription"></p> - <p class="text-terms-title" id="terms-title" - i18n-content="termsOfService"></p> <div class="section-terms" id="terms-container"> <webview id="terms-view" partition="persist:arc_support"></webview> + </div>` + <div class="subcontentcontainer"> + <div> + <a class="checkbox-text" id="privacy-policy-link" + href="#" i18n-content="privacyPolicyLink"></a> + </div> + <div id="metrics-preference"> + <label class="layout horizontal section-checkbox-container"> + <paper-checkbox class="checkbox-option"> + </paper-checkbox> + <p class="checkbox-text"></p> + </label> + </div> + <div id="backup-restore-preference"> + <label class="layout horizontal section-checkbox-container"> + <paper-checkbox class="checkbox-option"> + </paper-checkbox> + <p class="checkbox-text" + i18n-values=".innerHTML:textBackupRestore"></p> + </label> + </div> + <div id="location-service-preference"> + <label class="layout horizontal section-checkbox-container"> + <paper-checkbox class="checkbox-option"> + </paper-checkbox> + <p class="checkbox-text" + i18n-values=".innerHTML:textLocationService"></p> + </label> + </div> </div> - <div id="metrics-preference"> - <label class="layout horizontal section-checkbox-container"> - <input type="checkbox" class="checkbox-option"> - <p class="checkbox-text"></p> - </label> - </div> - <div id="backup-restore-preference"> - <label class="layout horizontal section-checkbox-container"> - <input type="checkbox" class="checkbox-option"> - <p class="checkbox-text" - i18n-values=".innerHTML:textBackupRestore"></p> - </label> - </div> - <div id="location-service-preference"> - <label class="layout horizontal section-checkbox-container"> - <input type="checkbox" class="checkbox-option"> - <p class="checkbox-text" - i18n-values=".innerHTML:textLocationService"></p> - </label> - </div> - <div class="layout horizontal center end-justified section-buttons"> - <a class="checkbox-text" id="privacy-policy-link" - href="#" i18n-content="privacyPolicyLink"></a> - <div class="flex"></div> - <paper-button class="white" id="button-cancel" - i18n-content="buttonCancel"> - </paper-button> - <div class="button-separator"></div> - <paper-button class="blue" id="button-agree" - i18n-content="buttonAgree"> - </paper-button> - </div> + </div> + <div class="layout horizontal center end-justified section-buttons"> + <div class="flex"></div> + <paper-button class="white" id="button-cancel" + i18n-content="buttonCancel"> + </paper-button> + <div class="button-separator"></div> + <paper-button class="blue" id="button-agree" i18n-content="buttonAgree"> + </paper-button> </div> </div> </div> @@ -135,29 +159,38 @@ <webview id="arc-support" partition="persist:arc_support"></webview> </div> <div id="arc-loading" class="section" hidden> - <img class="image-header" src="images/header.png"> + <div class="header"> + <img class="icon-header" src="icon/playstore.svg"> + <h1 class="title" i18n-content="greetingHeader"></h1> + </div> <div class="scrollable"> + <p class="subtitle" i18n-content="progressAndroidLoading" + aria-live="polite"> + </p> <div class="content"> <div class="progress-container"> <div class="progress-primary"></div> <div class="progress-secondary"></div> </div> - <p class="text-status" i18n-content="progressAndroidLoading" - aria-live="polite"></p> </div> </div> </div> <div id="error" class="section" hidden> - <img class="image-header" src="images/header.png"> + <div class="header"> + <img class="icon-header" src="icon/playstore.svg"> + <h1 class="title" i18n-content="greetingHeader"></h1> + </div> <div class="scrollable"> + <p class="subtitle" id="error-message" aria-live="polite"></p> <div class="content"> - <div class="progress-container"> - <div class="progress-primary red"></div> - </div> - <p class="text-status" id="error-message" aria-live="polite"></p> - <paper-button class="blue" id="button-send-feedback" + <img class="error-image" src="images/error_image.png"> + </div> + <div class="layout horizontal center end-justified section-buttons"> + <div class="flex"></div> + <paper-button class="white" id="button-send-feedback" i18n-content="buttonSendFeedback"> </paper-button> + <div class="button-separator"></div> <paper-button class="blue" id="button-retry" i18n-content="buttonRetry"> </paper-button> </div> @@ -173,8 +206,9 @@ <div class="action-area"> <div class="action-area-right"> <div class="button-strip"> - <button id="overlay-close" i18n-content="overlayClose"> - </button> + <paper-button class ="blue" id="overlay-close" + i18n-content="overlayClose"> + </paper-button> </div> </div> </div>
diff --git a/chrome/browser/resources/chromeos/arc_support/progressbar.css b/chrome/browser/resources/chromeos/arc_support/progressbar.css index b7dee84..7a911af 100644 --- a/chrome/browser/resources/chromeos/arc_support/progressbar.css +++ b/chrome/browser/resources/chromeos/arc_support/progressbar.css
@@ -5,18 +5,18 @@ .progress-container { display: block; height: 4px; - margin: auto; + margin: 40px 0 0 0; overflow: hidden; - padding: 112px 0 0 0; + padding: 0; position: relative; - width: 360px; + width: 100%; } .progress-primary, .progress-secondary { height: 4px; position: absolute; - width: 360px; + width: 100%; } .progress-primary {
diff --git a/chrome/browser/resources/chromeos/emulator/device_emulator.html b/chrome/browser/resources/chromeos/emulator/device_emulator.html index cb4ba431d..c64c78398 100644 --- a/chrome/browser/resources/chromeos/emulator/device_emulator.html +++ b/chrome/browser/resources/chromeos/emulator/device_emulator.html
@@ -2,8 +2,9 @@ <head> <meta charset="utf-8"> <title>Device Emulator</title> - <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html"> + + <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="device_emulator_pages.html">
diff --git a/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html b/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html index 6cbb107..00522d0 100644 --- a/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html +++ b/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html
@@ -1,5 +1,6 @@ -<link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animated-pages.html">
diff --git a/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.html b/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.html index 672c89e..86dfeba 100644 --- a/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.html +++ b/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.html
@@ -1,6 +1,7 @@ -<link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/html/md_select_css.html"> + <dom-module id="oobe-i18n-dropdown"> <template> <link rel="stylesheet" href="oobe_i18n_dropdown.css">
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index a1be081..790e53c 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -141,6 +141,7 @@ <include name="IDR_ARC_SUPPORT_MAIN" file="chromeos/arc_support/main.html" allowexternalscript="true" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_ICON_48" file="chromeos/arc_support/icon/48.png" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_ICON_96" file="chromeos/arc_support/icon/96.png" type="BINDATA" /> + <include name="IDR_ARC_SUPPORT_ICON_ERROER_IMAGE" file="chromeos/arc_support/images/error_image.png" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_ICON_HEADER" file="chromeos/arc_support/images/header.png" type="BINDATA" /> </if> <if expr="enable_plugins">
diff --git a/chrome/browser/resources/md_history/history_item.html b/chrome/browser/resources/md_history/history_item.html index 982ab92b..0bb3bbe6 100644 --- a/chrome/browser/resources/md_history/history_item.html +++ b/chrome/browser/resources/md_history/history_item.html
@@ -1,6 +1,7 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_row.html"> -<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> <link rel="import" href="chrome://resources/html/icon.html">
diff --git a/chrome/browser/resources/md_history/synced_device_card.html b/chrome/browser/resources/md_history/synced_device_card.html index 6aa1c74..9e80d9b8 100644 --- a/chrome/browser/resources/md_history/synced_device_card.html +++ b/chrome/browser/resources/md_history/synced_device_card.html
@@ -1,6 +1,7 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_row.html"> -<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
diff --git a/chrome/browser/resources/md_user_manager/control_bar.html b/chrome/browser/resources/md_user_manager/control_bar.html index 8c3319f..2797919 100644 --- a/chrome/browser/resources/md_user_manager/control_bar.html +++ b/chrome/browser/resources/md_user_manager/control_bar.html
@@ -1,7 +1,8 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="/profile_browser_proxy.html"> <link rel="import" href="/shared_styles.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
diff --git a/chrome/browser/resources/md_user_manager/error_dialog.html b/chrome/browser/resources/md_user_manager/error_dialog.html index 45d2229..a55ec1bf 100644 --- a/chrome/browser/resources/md_user_manager/error_dialog.html +++ b/chrome/browser/resources/md_user_manager/error_dialog.html
@@ -1,6 +1,7 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="/shared_styles.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> -<link rel="import" href="chrome://resources/html/polymer.html"> <dom-module id="error-dialog"> <template>
diff --git a/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html b/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html index eebb7b1e..2547500 100644 --- a/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html +++ b/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html
@@ -1,6 +1,7 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="/icons.html"> <link rel="import" href="/shared_styles.html"> -<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
diff --git a/chrome/browser/resources/md_user_manager/user_manager_pages.html b/chrome/browser/resources/md_user_manager/user_manager_pages.html index f438e76..10f655aa 100644 --- a/chrome/browser/resources/md_user_manager/user_manager_pages.html +++ b/chrome/browser/resources/md_user_manager/user_manager_pages.html
@@ -1,7 +1,8 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="/create_profile.html"> <link rel="import" href="/supervised_user_create_confirm.html"> <link rel="import" href="/supervised_user_learn_more.html"> -<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-in-animation.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-out-animation.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
diff --git a/chrome/browser/resources/net_internals/hsts_view.js b/chrome/browser/resources/net_internals/hsts_view.js index be6a08d..52da7a3 100644 --- a/chrome/browser/resources/net_internals/hsts_view.js +++ b/chrome/browser/resources/net_internals/hsts_view.js
@@ -177,9 +177,9 @@ // These numbers must match those in // TransportSecurityState::STSState::UpgradeMode. if (m == 0) { - return 'STRICT'; + return 'FORCE_HTTPS'; } else if (m == 1) { - return 'OPPORTUNISTIC'; + return 'DEFAULT'; } else { return 'UNKNOWN'; }
diff --git a/chrome/browser/resources/settings/device_page/stylus.html b/chrome/browser/resources/settings/device_page/stylus.html index 3b8978d..b0ace6a 100644 --- a/chrome/browser/resources/settings/device_page/stylus.html +++ b/chrome/browser/resources/settings/device_page/stylus.html
@@ -27,6 +27,10 @@ cr-policy-indicator { padding: 0 var(--cr-controlled-by-spacing); } + + #note-taking-app-lock-screen-settings { + padding: 0 var(--settings-box-row-padding); + } </style> <div class="settings-box continuation"> @@ -75,29 +79,6 @@ </div> </div> - <template is="dom-if" if="[[supportsLockScreen_(selectedApp_)]]"> - <div class="settings-box"> - <div id="lock-screen-toggle-label" class="start" - actionable$="[[!disallowedOnLockScreenByPolicy_(selectedApp_)]]" - on-tap="toggleLockScreenSupport_"> - $i18n{stylusNoteTakingAppEnabledOnLockScreen} - </div> - <template is="dom-if" - if="[[disallowedOnLockScreenByPolicy_(selectedApp_)]]"> - <cr-policy-indicator - id="enable-app-on-lock-screen-policy-indicator" - indicator-type="[[userPolicyIndicator_]]"> - </cr-policy-indicator> - </template> - <paper-toggle-button id="enable-app-on-lock-screen-toggle" - aria-labelledby="lock-screen-toggle-label" - disabled="[[disallowedOnLockScreenByPolicy_(selectedApp_)]]" - checked="[[lockScreenSupportEnabled_(selectedApp_)]]" - on-change="toggleLockScreenSupport_"> - </paper-toggle-button> - </div> - </template> - <!-- TODO(scottchen): Make a proper a[href].settings-box with icon-external (see: https://crbug.com/684005)--> <div class="settings-box two-line" on-tap="onFindAppsTap_" actionable @@ -113,6 +94,42 @@ aria-describedby="stylusFindMoreAppsSecondary"></button> </div> + <template is="dom-if" if="[[supportsLockScreen_(selectedApp_)]]"> + <div id="note-taking-app-lock-screen-settings"> + <h2>$i18n{stylusNoteTakingAppLockScreenSettingsHeader}</h2> + + <div class="settings-box first"> + <div id="lock-screen-toggle-label" class="start" + actionable$="[[!disallowedOnLockScreenByPolicy_(selectedApp_)]]" + on-tap="toggleLockScreenSupport_"> + $i18n{stylusNoteTakingAppEnabledOnLockScreen} + </div> + <template is="dom-if" + if="[[disallowedOnLockScreenByPolicy_(selectedApp_)]]"> + <cr-policy-indicator + id="enable-app-on-lock-screen-policy-indicator" + indicator-type="[[userPolicyIndicator_]]"> + </cr-policy-indicator> + </template> + <paper-toggle-button id="enable-app-on-lock-screen-toggle" + aria-labelledby="lock-screen-toggle-label" + disabled="[[disallowedOnLockScreenByPolicy_(selectedApp_)]]" + checked="[[lockScreenSupportEnabled_(selectedApp_)]]" + on-change="toggleLockScreenSupport_"> + </paper-toggle-button> + </div> + + <template is="dom-if" if="[[lockScreenSupportEnabled_(selectedApp_)]]"> + <div class="settings-box"> + <settings-toggle-button id="keep-last-note-on-lock-screen-toggle" + pref="{{prefs.settings.restore_last_lock_screen_note}}" + label="$i18n{stylusNoteTakingAppKeepsLastNoteOnLockScreen}"> + </settings-toggle-button> + </div> + </template> + </div> + </template> + </template> <script src="stylus.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.html b/chrome/browser/resources/settings/internet_page/internet_config.html index 92d222e..6c2a1f2 100644 --- a/chrome/browser/resources/settings/internet_page/internet_config.html +++ b/chrome/browser/resources/settings/internet_page/internet_config.html
@@ -1,7 +1,8 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html"> <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
diff --git a/chrome/browser/resources/welcome/welcome.html b/chrome/browser/resources/welcome/welcome.html index 198ea7df..b2b6c11 100644 --- a/chrome/browser/resources/welcome/welcome.html +++ b/chrome/browser/resources/welcome/welcome.html
@@ -4,8 +4,9 @@ <meta charset="utf-8"> <title>$i18n{headerText}</title> - <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html"> + + <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
diff --git a/chrome/browser/resources/welcome/win10/inline.html b/chrome/browser/resources/welcome/win10/inline.html index ff53572..fa5e6ac 100644 --- a/chrome/browser/resources/welcome/win10/inline.html +++ b/chrome/browser/resources/welcome/win10/inline.html
@@ -4,11 +4,12 @@ <meta charset="utf-8"> <title>$i18n{headerText}</title> + <link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/action_link_css.html"> - <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
diff --git a/chrome/browser/resources/welcome/win10/sectioned.html b/chrome/browser/resources/welcome/win10/sectioned.html index 565c0e7..13b7ff6 100644 --- a/chrome/browser/resources/welcome/win10/sectioned.html +++ b/chrome/browser/resources/welcome/win10/sectioned.html
@@ -4,9 +4,10 @@ <meta charset="utf-8"> <title>$i18n{headerText}</title> + <link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/cr.html"> - <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
diff --git a/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc b/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc index 643aa0a..1ec77ea 100644 --- a/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc +++ b/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc
@@ -46,7 +46,6 @@ case ScreenlockState::INACTIVE: return proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE; case ScreenlockState::PASSWORD_REAUTH: - case ScreenlockState::PASSWORD_REQUIRED_FOR_LOGIN: return proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_HARDLOCKED; } @@ -83,8 +82,6 @@ return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_INSTRUCTIONS; case ScreenlockState::PASSWORD_REAUTH: return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PASSWORD_REAUTH; - case ScreenlockState::PASSWORD_REQUIRED_FOR_LOGIN: - return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PASSWORD_REQUIRED_FOR_LOGIN; } NOTREACHED(); @@ -97,8 +94,7 @@ state == ScreenlockState::NO_BLUETOOTH || state == ScreenlockState::PHONE_UNSUPPORTED || state == ScreenlockState::RSSI_TOO_LOW || - state == ScreenlockState::PHONE_LOCKED_AND_RSSI_TOO_LOW || - state == ScreenlockState::PASSWORD_REQUIRED_FOR_LOGIN); + state == ScreenlockState::PHONE_LOCKED_AND_RSSI_TOO_LOW); } // Returns true iff the |state| corresponds to a locked remote device. @@ -319,6 +315,10 @@ } else if (hardlock_state_ == LOGIN_FAILED) { tooltip = l10n_util::GetStringUTF16( IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_LOGIN_FAILURE); + } else if (hardlock_state_ == PASSWORD_REQUIRED_FOR_LOGIN) { + tooltip = l10n_util::GetStringFUTF16( + IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PASSWORD_REQUIRED_FOR_LOGIN, + device_name); } else { LOG(ERROR) << "Unknown hardlock state " << hardlock_state_; }
diff --git a/chrome/browser/signin/easy_unlock_screenlock_state_handler.h b/chrome/browser/signin/easy_unlock_screenlock_state_handler.h index a0eca32b..3fa33f0 100644 --- a/chrome/browser/signin/easy_unlock_screenlock_state_handler.h +++ b/chrome/browser/signin/easy_unlock_screenlock_state_handler.h
@@ -28,6 +28,7 @@ // failure. Reset when screen is unlocked. PAIRING_ADDED = 1 << 4, // Similar to PAIRING_CHANGED when it happens // on a new Chromebook. + PASSWORD_REQUIRED_FOR_LOGIN = 1 << 5, // Login must be done with a password }; // |account_id|: The account id of the user associated with the profile to
diff --git a/chrome/browser/signin/easy_unlock_service.cc b/chrome/browser/signin/easy_unlock_service.cc index 5200585..535f69c 100644 --- a/chrome/browser/signin/easy_unlock_service.cc +++ b/chrome/browser/signin/easy_unlock_service.cc
@@ -381,31 +381,6 @@ return false; } -void EasyUnlockService::ShowInitialUserState() { - if (!GetScreenlockStateHandler()) - return; - - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery) && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - proximity_auth::switches::kEnableChromeOSLogin)) { - UpdateScreenlockState(ScreenlockState::PASSWORD_REQUIRED_FOR_LOGIN); - return; - } - - EasyUnlockScreenlockStateHandler::HardlockState state; - bool has_persisted_state = GetPersistedHardlockState(&state); - if (!has_persisted_state) - return; - - if (state == EasyUnlockScreenlockStateHandler::NO_HARDLOCK) { - // Show connecting icon early when there is a persisted non hardlock state. - UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING); - } else { - screenlock_state_handler_->MaybeShowHardlockUI(); - } -} - EasyUnlockScreenlockStateHandler* EasyUnlockService::GetScreenlockStateHandler() { if (!IsAllowed()) @@ -679,8 +654,10 @@ void EasyUnlockService::SetScreenlockHardlockedState( EasyUnlockScreenlockStateHandler::HardlockState state) { - if (screenlock_state_handler_) + if (GetScreenlockStateHandler()) { screenlock_state_handler_->SetHardlockState(state); + screenlock_state_handler_->MaybeShowHardlockUI(); + } if (state != EasyUnlockScreenlockStateHandler::NO_HARDLOCK) auth_attempt_.reset(); } @@ -703,17 +680,6 @@ void EasyUnlockService::OnBluetoothAdapterPresentChanged() { UpdateAppState(); - - // On device boot, we can't show the initial user state until Bluetooth is - // detected to be present. - if (GetType() == TYPE_SIGNIN && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery) && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - proximity_auth::switches::kEnableChromeOSLogin)) { - ShowInitialUserState(); - return; - } } void EasyUnlockService::SetHardlockStateForUser( @@ -727,12 +693,9 @@ // Disallow setting the hardlock state if the password is currently being // forced. - if (!screenlock_state_handler_ || - screenlock_state_handler_->state() == - proximity_auth::ScreenlockState::PASSWORD_REAUTH || - screenlock_state_handler_->state() == - proximity_auth::ScreenlockState::PASSWORD_REQUIRED_FOR_LOGIN) { - PA_LOG(INFO) << "Hardlock state can't be set when password is forced."; + if (GetScreenlockStateHandler() && + GetScreenlockStateHandler()->state() == + proximity_auth::ScreenlockState::PASSWORD_REAUTH) { return; } @@ -762,6 +725,8 @@ return PASSWORD_ENTRY_LOGIN_FAILED; case EasyUnlockScreenlockStateHandler::PAIRING_ADDED: return PASSWORD_ENTRY_PAIRING_ADDED; + case EasyUnlockScreenlockStateHandler::PASSWORD_REQUIRED_FOR_LOGIN: + return PASSWORD_ENTRY_REQUIRED_FOR_LOGIN; } } else if (!screenlock_state_handler()) { return PASSWORD_ENTRY_NO_SCREENLOCK_STATE_HANDLER; @@ -791,8 +756,6 @@ return PASSWORD_ENTRY_WITH_AUTHENTICATED_PHONE; case ScreenlockState::PASSWORD_REAUTH: return PASSWORD_ENTRY_FORCED_REAUTH; - case ScreenlockState::PASSWORD_REQUIRED_FOR_LOGIN: - return PASSWORD_ENTRY_REQUIRED_FOR_LOGIN; } } @@ -807,6 +770,11 @@ proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery)) return; + if (remote_devices.size() == 0) { + proximity_auth_system_.reset(); + return; + } + if (!proximity_auth_system_) { PA_LOG(INFO) << "Creating ProximityAuthSystem."; proximity_auth_system_.reset(new proximity_auth::ProximityAuthSystem(
diff --git a/chrome/browser/signin/easy_unlock_service.h b/chrome/browser/signin/easy_unlock_service.h index 01807a8..ae296027 100644 --- a/chrome/browser/signin/easy_unlock_service.h +++ b/chrome/browser/signin/easy_unlock_service.h
@@ -171,10 +171,6 @@ bool GetPersistedHardlockState( EasyUnlockScreenlockStateHandler::HardlockState* state) const; - // Shows the hardlock or connecting state as initial UI before cryptohome - // keys checking and state update from the app. - void ShowInitialUserState(); - // Updates the user pod on the signin/lock screen for the user associated with // the service to reflect the provided screenlock state. bool UpdateScreenlockState(proximity_auth::ScreenlockState state); @@ -253,6 +249,9 @@ // Called when the local device resumes after a suspend. virtual void OnSuspendDoneInternal() = 0; + // Called when the state of the Bluetooth adapter changes. + virtual void OnBluetoothAdapterPresentChanged(); + // KeyedService override: void Shutdown() override; @@ -323,9 +322,6 @@ // Unlock gets disabled. EasyUnlockScreenlockStateHandler* GetScreenlockStateHandler(); - // Callback when Bluetooth adapter present state changes. - void OnBluetoothAdapterPresentChanged(); - #if defined(OS_CHROMEOS) // Callback for get key operation from CheckCryptohomeKeysAndMaybeHardlock. void OnCryptohomeKeysFetchedForChecking(
diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc index b46615b..76783fc7 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.cc +++ b/chrome/browser/signin/easy_unlock_service_regular.cc
@@ -615,6 +615,9 @@ public_keys_after_sync.insert(device_info.public_key()); } + if (public_keys_after_sync.empty()) + ClearPermitAccess(); + if (public_keys_before_sync == public_keys_after_sync) return; @@ -651,18 +654,20 @@ void EasyUnlockServiceRegular::OnScreenDidUnlock( proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { - bool is_lock_screen = - screen_type == proximity_auth::ScreenlockBridge::LockHandler::LOCK_SCREEN; - if (!will_unlock_using_easy_unlock_ && pref_manager_ && - (is_lock_screen || !base::CommandLine::ForCurrentProcess()->HasSwitch( - proximity_auth::switches::kEnableChromeOSLogin))) { + base::CommandLine::ForCurrentProcess()->HasSwitch( + proximity_auth::switches::kEnableForcePasswordReauth)) { // If a password was used, then record the current timestamp. This timestamp // is used to enforce password reauths after a certain time has elapsed. + // Note: This code path is also triggered by the login flow. pref_manager_->SetLastPasswordEntryTimestampMs( base::Time::Now().ToJavaTime()); } + // Do not process events for the login screen. + if (screen_type != proximity_auth::ScreenlockBridge::LockHandler::LOCK_SCREEN) + return; + // If we tried to load remote devices (e.g. after a sync) while the screen was // locked, we can now load the new remote devices. // Note: This codepath may be reachable when the login screen unlocks. @@ -684,10 +689,6 @@ } } - // Do not process events for the login screen. - if (!is_lock_screen) - return; - // Only record metrics for users who have enabled the feature. if (IsEnabled()) { EasyUnlockAuthEvent event = will_unlock_using_easy_unlock_ @@ -723,9 +724,15 @@ EasyUnlockService::ResetLocalStateForUser(GetAccountId()); SetRemoteDevices(base::ListValue()); SetProximityAuthDevices(GetAccountId(), cryptauth::RemoteDeviceList()); - SetTurnOffFlowStatus(IDLE); - ReloadAppAndLockScreen(); pref_manager_->SetIsEasyUnlockEnabled(false); + SetTurnOffFlowStatus(IDLE); + pref_manager_->SetIsEasyUnlockEnabled(false); + ResetScreenlockState(); + + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery)) { + ReloadAppAndLockScreen(); + } } void EasyUnlockServiceRegular::OnToggleEasyUnlockApiFailed(
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc index 21913bd..2894e4c 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/chromeos/login/session/user_session_manager.h" #include "chrome/browser/signin/easy_unlock_app_manager.h" #include "chrome/browser/signin/easy_unlock_metrics.h" +#include "chrome/common/pref_names.h" #include "chromeos/login/auth/user_context.h" #include "chromeos/tpm/tpm_token_loader.h" #include "components/cryptauth/remote_device.h" @@ -31,6 +32,8 @@ #include "components/proximity_auth/proximity_auth_local_state_pref_manager.h" #include "components/proximity_auth/switches.h" +using proximity_auth::ScreenlockState; + namespace { // The maximum allowed backoff interval when waiting for cryptohome to start. @@ -380,6 +383,10 @@ // Ignored. } +void EasyUnlockServiceSignin::OnBluetoothAdapterPresentChanged() { + OnFocusedUserChanged(account_id_); +} + void EasyUnlockServiceSignin::OnScreenDidLock( proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { // In production code, the screen type should always be the signin screen; but @@ -389,7 +396,7 @@ return; // Update initial UI is when the account picker on login screen is ready. - ShowInitialUserState(); + ShowInitialUserPodState(); user_pod_last_focused_timestamp_ = base::TimeTicks::Now(); } @@ -412,12 +419,17 @@ return; // Setting or clearing the account_id may changed |IsAllowed| value, so in - // these - // cases update the app state. Otherwise, it's enough to notify the app the - // user data has been updated. + // these cases update the app state. Otherwise, it's enough to notify the app + // the user data has been updated. const bool should_update_app_state = (account_id_ != account_id); account_id_ = account_id; + pref_manager_->SetActiveUser(account_id); user_pod_last_focused_timestamp_ = base::TimeTicks::Now(); + SetProximityAuthDevices(account_id_, cryptauth::RemoteDeviceList()); + ResetScreenlockState(); + + if (!IsAllowed() || !IsEnabled()) + return; ResetScreenlockState(); @@ -425,15 +437,13 @@ if (!IsAllowed() || !IsEnabled()) return; - ShowInitialUserState(); + ShowInitialUserPodState(); - // ShowInitialUserState() will display a tooltip explaining that the user must - // enter their password. We will skip the entire login code path unless the - // --enable-chromeos-login flag is enabled. - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery) && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - proximity_auth::switches::kEnableChromeOSLogin)) { + // If there is a hardlock, then there is no point in loading the devices. + EasyUnlockScreenlockStateHandler::HardlockState hardlock_state; + if (GetPersistedHardlockState(&hardlock_state) && + hardlock_state != EasyUnlockScreenlockStateHandler::NO_HARDLOCK) { + PA_LOG(INFO) << "Hardlock present, skipping remaining login flow."; return; } @@ -448,11 +458,7 @@ // Start loading TPM system token. // The system token will be needed to sign a nonce using TPM private key // during the sign-in protocol. - EasyUnlockScreenlockStateHandler::HardlockState hardlock_state; - if (GetPersistedHardlockState(&hardlock_state) && - hardlock_state != EasyUnlockScreenlockStateHandler::NO_PAIRING) { - chromeos::TPMTokenLoader::Get()->EnsureStarted(); - } + chromeos::TPMTokenLoader::Get()->EnsureStarted(); } void EasyUnlockServiceSignin::LoggedInStateChanged() { @@ -518,6 +524,12 @@ if (account_id == account_id_) NotifyUserUpdated(); + // The code below delegates EasyUnlock processing to the native + // implementation. Skip if the app is used instead. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery)) + return; + if (devices.empty()) return; @@ -571,3 +583,22 @@ return nullptr; return it->second.get(); } + +void EasyUnlockServiceSignin::ShowInitialUserPodState() { + if (!IsAllowed() || !IsEnabled()) + return; + + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + proximity_auth::switches::kDisableBluetoothLowEnergyDiscovery) && + !pref_manager_->IsChromeOSLoginEnabled()) { + // Show a hardlock state if the user has not enabled the login flow. + SetHardlockStateForUser( + account_id_, + EasyUnlockScreenlockStateHandler::PASSWORD_REQUIRED_FOR_LOGIN); + } else { + // This UI is simply a placeholder until the RemoteDevices are loaded from + // cryptohome and the ProximityAuthSystem is started. Hardlock states are + // automatically taken into account. + UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING); + } +}
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h index 09bdd79..348cef5f 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h
@@ -109,6 +109,7 @@ bool IsEnabled() const override; void OnWillFinalizeUnlock(bool success) override; void OnSuspendDoneInternal() override; + void OnBluetoothAdapterPresentChanged() override; // proximity_auth::ScreenlockBridge::Observer implementation: void OnScreenDidLock(proximity_auth::ScreenlockBridge::LockHandler::ScreenType @@ -134,6 +135,10 @@ // Otherwise, returns NULL. const UserData* FindLoadedDataForCurrentUser() const; + // Shows the hardlock or connecting state as initial UI before cryptohome + // keys checking and state update from the app. + void ShowInitialUserPodState(); + // User id of the user currently associated with the service. AccountId account_id_;
diff --git a/chrome/browser/ui/ash/accelerator_controller_browsertest.cc b/chrome/browser/ui/ash/accelerator_controller_browsertest.cc deleted file mode 100644 index dc0de25a..0000000 --- a/chrome/browser/ui/ash/accelerator_controller_browsertest.cc +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/accelerators/accelerator_controller.h" - -#include "ash/shell.h" -#include "ash/wm/window_state.h" -#include "build/build_config.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "ui/events/test/event_generator.h" - -#if defined(USE_X11) -#include "ui/events/test/events_test_utils_x11.h" -#endif - -#if defined(USE_X11) -typedef InProcessBrowserTest AcceleratorControllerBrowserTest; - -// Test that pressing and holding Alt+ toggles the maximized state exactly once. -// This test is a browser test to test that the EF_IS_REPEAT flag is correctly -// passed down to AcceleratorController (via a conversion to WebInputEvent). -// See crbug.com/434743 -IN_PROC_BROWSER_TEST_F(AcceleratorControllerBrowserTest, - RepeatedToggleMaximizeViaAccelerator) { - ASSERT_TRUE(ash::Shell::HasInstance()) << "No Instance"; - AddTabAtIndex(0, - GURL("data:text/html;base64,<html></html>"), - ui::PAGE_TRANSITION_TYPED); - browser()->window()->Show(); - - ui::Accelerator accelerator(ui::VKEY_OEM_PLUS, ui::EF_ALT_DOWN); - ash::AcceleratorController* accelerator_controller = - ash::Shell::Get()->accelerator_controller(); - ASSERT_TRUE(accelerator_controller->IsRegistered(accelerator)); - - ash::wm::WindowState* window_state = ash::wm::GetActiveWindowState(); - EXPECT_FALSE(window_state->IsMaximized()); - - ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow()); - generator.PressKey(ui::VKEY_OEM_PLUS, ui::EF_ALT_DOWN); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.PressKey(ui::VKEY_OEM_PLUS, ui::EF_ALT_DOWN); - - generator.ReleaseKey(ui::VKEY_OEM_PLUS, ui::EF_ALT_DOWN); - EXPECT_TRUE(window_state->IsMaximized()); -} -#endif
diff --git a/chrome/browser/ui/ash/ash_init.cc b/chrome/browser/ui/ash/ash_init.cc index d2e58288..64fa94e 100644 --- a/chrome/browser/ui/ash/ash_init.cc +++ b/chrome/browser/ui/ash/ash_init.cc
@@ -18,7 +18,6 @@ #include "ash/shell_port_classic.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" -#include "base/sys_info.h" #include "base/task_scheduler/post_task.h" #include "base/threading/sequenced_worker_pool.h" #include "build/build_config.h" @@ -42,10 +41,6 @@ #include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window_tree_host.h" -#if defined(USE_X11) -#include "ui/base/x/x11_util.h" // nogncheck -#endif - namespace { void CreateClassicShell() { @@ -91,17 +86,6 @@ } // namespace AshInit::AshInit() { -#if defined(USE_X11) - if (base::SysInfo::IsRunningOnChromeOS()) { - // Mus only runs on ozone. - DCHECK_NE(ash::Config::MUS, chromeos::GetAshConfig()); - // Hides the cursor outside of the Aura root window. The cursor will be - // drawn within the Aura root window, and it'll remain hidden after the - // Aura window is closed. - ui::HideHostCursor(); - } -#endif - // Hide the mouse cursor completely at boot. if (!chromeos::LoginState::Get()->IsUserLoggedIn()) ash::Shell::set_initially_hide_cursor(true);
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index 04a9dba5..588e18d5 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -75,15 +75,12 @@ #include "content/public/browser/notification_service.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/url_constants.h" +#include "services/ui/public/cpp/input_devices/input_device_controller_client.h" #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "url/url_constants.h" -#if defined(USE_OZONE) -#include "services/ui/public/cpp/input_devices/input_device_controller_client.h" -#endif - using chromeos::AccessibilityManager; namespace { @@ -615,12 +612,10 @@ return base::WrapUnique(chromeos::CreateWallpaperDelegate()); } -#if defined(USE_OZONE) ui::InputDeviceControllerClient* ChromeShellDelegate::GetInputDeviceControllerClient() { return g_browser_process->platform_part()->GetInputDeviceControllerClient(); } -#endif void ChromeShellDelegate::Observe(int type, const content::NotificationSource& source,
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h index 4cae06d..7509cfa 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.h +++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -61,9 +61,7 @@ void UpdateTouchscreenStatusFromPrefs() override; void ToggleTouchpad() override; void SuspendMediaSessions() override; -#if defined(USE_OZONE) ui::InputDeviceControllerClient* GetInputDeviceControllerClient() override; -#endif // content::NotificationObserver override: void Observe(int type,
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils.cc b/chrome/browser/ui/bookmarks/bookmark_utils.cc index e3cfeb3..905d186 100644 --- a/chrome/browser/ui/bookmarks/bookmark_utils.cc +++ b/chrome/browser/ui/bookmarks/bookmark_utils.cc
@@ -131,7 +131,7 @@ // important not to drop any username/password, or unescape anything that // changes the URL's meaning. url_formatter::FormatUrlTypes format_types = - url_formatter::kFormatUrlOmitAll & + url_formatter::kFormatUrlOmitDefaults & ~url_formatter::kFormatUrlOmitUsernamePassword; // If username is present, we must not omit the scheme because FixupURL() will
diff --git a/chrome/browser/ui/views/importer/import_lock_dialog_view.cc b/chrome/browser/ui/views/importer/import_lock_dialog_view.cc index ff4e860..2b0380e 100644 --- a/chrome/browser/ui/views/importer/import_lock_dialog_view.cc +++ b/chrome/browser/ui/views/importer/import_lock_dialog_view.cc
@@ -19,7 +19,9 @@ #include "chrome/grit/locale_settings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_features.h" +#include "ui/views/border.h" #include "ui/views/controls/label.h" +#include "ui/views/layout/fill_layout.h" #include "ui/views/widget/widget.h" using base::UserMetricsAction; @@ -45,13 +47,16 @@ ImportLockDialogView::ImportLockDialogView( const base::Callback<void(bool)>& callback) - : description_label_(NULL), - callback_(callback) { - description_label_ = new views::Label( - l10n_util::GetStringUTF16(IDS_IMPORTER_LOCK_TEXT)); - description_label_->SetMultiLine(true); - description_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - AddChildView(description_label_); + : callback_(callback) { + SetLayoutManager(new views::FillLayout()); + views::Label* description_label = + new views::Label(l10n_util::GetStringUTF16(IDS_IMPORTER_LOCK_TEXT)); + description_label->SetBorder( + views::CreateEmptyBorder(ChromeLayoutProvider::Get()->GetInsetsMetric( + views::INSETS_DIALOG_CONTENTS))); + description_label->SetMultiLine(true); + description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + AddChildView(description_label); chrome::RecordDialogCreation(chrome::DialogIdentifier::IMPORT_LOCK); } @@ -59,16 +64,9 @@ } gfx::Size ImportLockDialogView::CalculatePreferredSize() const { - return gfx::Size(views::Widget::GetLocalizedContentsSize( - IDS_IMPORTLOCK_DIALOG_WIDTH_CHARS, - IDS_IMPORTLOCK_DIALOG_HEIGHT_LINES)); -} - -void ImportLockDialogView::Layout() { - gfx::Rect bounds(GetLocalBounds()); - const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - bounds.Inset(provider->GetInsetsMetric(views::INSETS_DIALOG_CONTENTS)); - description_label_->SetBoundsRect(bounds); + const int width = views::Widget::GetLocalizedContentsWidth( + IDS_IMPORTLOCK_DIALOG_WIDTH_CHARS); + return gfx::Size(width, GetHeightForWidth(width)); } base::string16 ImportLockDialogView::GetDialogButtonLabel( @@ -82,13 +80,17 @@ } bool ImportLockDialogView::Accept() { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback_, true)); + if (callback_) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback_, true)); + } return true; } bool ImportLockDialogView::Cancel() { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback_, false)); + if (callback_) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback_, false)); + } return true; }
diff --git a/chrome/browser/ui/views/importer/import_lock_dialog_view.h b/chrome/browser/ui/views/importer/import_lock_dialog_view.h index 2ca8f826..b85ddc9 100644 --- a/chrome/browser/ui/views/importer/import_lock_dialog_view.h +++ b/chrome/browser/ui/views/importer/import_lock_dialog_view.h
@@ -8,14 +8,8 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "ui/views/view.h" #include "ui/views/window/dialog_delegate.h" -namespace views { -class Label; -} - // ImportLockDialogView asks the user to shut down Firefox before starting the // profile import. class ImportLockDialogView : public views::DialogDelegateView { @@ -29,7 +23,6 @@ // views::View: gfx::Size CalculatePreferredSize() const override; - void Layout() override; // views::DialogDelegate: base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; @@ -38,8 +31,6 @@ bool Cancel() override; private: - views::Label* description_label_; - // Called with the result of the dialog. base::Callback<void(bool)> callback_;
diff --git a/chrome/browser/ui/views/importer/import_lock_dialog_view_browsertest.cc b/chrome/browser/ui/views/importer/import_lock_dialog_view_browsertest.cc new file mode 100644 index 0000000..766cc793 --- /dev/null +++ b/chrome/browser/ui/views/importer/import_lock_dialog_view_browsertest.cc
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/importer/import_lock_dialog_view.h" + +#include <string> + +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" + +class ImportLockDialogViewBrowserTest : public DialogBrowserTest { + public: + ImportLockDialogViewBrowserTest() {} + + // DialogBrowserTest: + void ShowDialog(const std::string& name) override { + gfx::NativeWindow native_window = browser()->window()->GetNativeWindow(); + ImportLockDialogView::Show(native_window, base::Callback<void(bool)>()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ImportLockDialogViewBrowserTest); +}; + +// Invokes a dialog that implores the user to close Firefox before trying to +// import data. See test_browser_dialog.h. +IN_PROC_BROWSER_TEST_F(ImportLockDialogViewBrowserTest, InvokeDialog_default) { + RunDialog(); +}
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index 72e84d0..ccefe00 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -8,7 +8,6 @@ #include <memory> -#include "ash/wm/screen_dimmer.h" #include "base/command_line.h" #include "base/logging.h" #include "base/macros.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index adcbea8b..89c8f21 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -16,6 +16,7 @@ #include "ash/shell.h" #include "ash/shutdown_reason.h" #include "ash/system/devicetype_utils.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/i18n/number_formatting.h" #include "base/location.h" @@ -54,6 +55,7 @@ #include "chrome/browser/chromeos/login/ui/login_feedback.h" #include "chrome/browser/chromeos/login/ui/webui_login_display.h" #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" +#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/device_local_account.h" @@ -103,6 +105,7 @@ #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/chromeos/input_method_util.h" #include "ui/base/webui/web_ui_util.h" +#include "ui/gfx/color_analysis.h" #include "ui/gfx/color_utils.h" namespace { @@ -132,6 +135,12 @@ const char kLaunchRequestedLockScreenApps[] = "LOCK_SCREEN_APPS_STATE.LAUNCH_REQUESTED"; +ash::WallpaperController* GetWallpaperController() { + if (!ash::Shell::HasInstance()) + return nullptr; + return ash::Shell::Get()->wallpaper_controller(); +} + class CallOnReturn { public: explicit CallOnReturn(const base::Closure& callback) @@ -284,8 +293,9 @@ touch_view_manager_ptr_->AddObserver(std::move(observer)); if (lock_screen_apps::StateController::IsEnabled()) lock_screen_apps_observer_.Add(lock_screen_apps::StateController::Get()); - if (WallpaperManager::HasInstance()) - WallpaperManager::Get()->AddObserver(this); + ash::WallpaperController* wallpaper_controller = GetWallpaperController(); + DCHECK(wallpaper_controller); + wallpaper_controller->AddObserver(this); } SigninScreenHandler::~SigninScreenHandler() { @@ -305,8 +315,9 @@ network_state_informer_->RemoveObserver(this); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(nullptr); proximity_auth::ScreenlockBridge::Get()->SetFocusedUser(EmptyAccountId()); - if (WallpaperManager::HasInstance()) - WallpaperManager::Get()->RemoveObserver(this); + ash::WallpaperController* wallpaper_controller = GetWallpaperController(); + if (wallpaper_controller) + wallpaper_controller->RemoveObserver(this); } void SigninScreenHandler::DeclareLocalizedValues( @@ -865,8 +876,17 @@ gaia_screen_handler_->ReloadGaia(force_reload); } -void SigninScreenHandler::SetSigninScreenColors(SkColor dark_muted_color) { - // The dark muted color should have 100% opacity. +void SigninScreenHandler::UpdateAccountPickerColors() { + color_utils::ColorProfile color_profile(color_utils::LumaRange::DARK, + color_utils::SaturationRange::MUTED); + ash::WallpaperController* wallpaper_controller = GetWallpaperController(); + SkColor dark_muted_color = + wallpaper_controller + ? wallpaper_controller->GetProminentColor(color_profile) + : ash::login_constants::kDefaultBaseColor; + if (dark_muted_color == ash::WallpaperController::kInvalidColor) + dark_muted_color = ash::login_constants::kDefaultBaseColor; + dark_muted_color = SkColorSetA(dark_muted_color, 0xFF); SkColor base_color = color_utils::GetResultingPaintColor( SkColorSetA(ash::login_constants::kDefaultBaseColor, @@ -920,13 +940,11 @@ } void SigninScreenHandler::OnWallpaperColorsChanged() { - base::Optional<SkColor> color = WallpaperManager::Get()->prominent_color(); - // If color extraction fails, use transparent as default. - if (!color.has_value()) - color = SK_ColorTRANSPARENT; - SetSigninScreenColors(color.value()); + UpdateAccountPickerColors(); } +void SigninScreenHandler::OnWallpaperDataChanged() {} + void SigninScreenHandler::ClearAndEnablePassword() { core_oobe_view_->ResetSignInUI(false); } @@ -1290,6 +1308,9 @@ OnLockScreenNoteStateChanged( lock_screen_apps::StateController::Get()->GetLockScreenNoteState()); } + // Color calculation of the first wallpaper may have completed before the + // instance is initialized, so make sure the colors are properly updated. + UpdateAccountPickerColors(); if (delegate_) delegate_->OnSigninScreenReady(); }
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index 5532adf..6c2cad97 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -11,6 +11,7 @@ #include <string> #include "ash/public/interfaces/touch_view.mojom.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "base/callback.h" #include "base/compiler_specific.h" #include "base/containers/hash_tables.h" @@ -22,7 +23,6 @@ #include "chrome/browser/chromeos/login/screens/error_screen.h" #include "chrome/browser/chromeos/login/signin_specifics.h" #include "chrome/browser/chromeos/login/ui/login_display.h" -#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/ui/webui/chromeos/login/base_webui_handler.h" #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h" @@ -241,7 +241,7 @@ public ash::mojom::TouchViewObserver, public lock_screen_apps::StateObserver, public OobeUI::Observer, - public wallpaper::WallpaperManagerBase::Observer { + public ash::WallpaperControllerObserver { public: SigninScreenHandler( const scoped_refptr<NetworkStateInformer>& network_state_informer, @@ -275,12 +275,13 @@ // Required Local State preferences. static void RegisterPrefs(PrefRegistrySimple* registry); - // OobeUI::Observer implemetation. + // OobeUI::Observer implementation: void OnCurrentScreenChanged(OobeScreen current_screen, OobeScreen new_screen) override; - // wallpaper::WallpaperManagerBase::Observer implementation. + // ash::WallpaperControllerObserver implementation: void OnWallpaperColorsChanged() override; + void OnWallpaperDataChanged() override; void SetFocusPODCallbackForTesting(base::Closure callback); @@ -319,9 +320,9 @@ NetworkError::ErrorReason reason); void ReloadGaia(bool force_reload); - // Sets signin screen overlay colors based on the wallpaper color extraction - // results. - void SetSigninScreenColors(SkColor dm_color); + // Updates the color of the scrollable container on account picker screen, + // based on wallpaper color extraction results. + void UpdateAccountPickerColors(); // BaseScreenHandler implementation: void DeclareLocalizedValues(
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index 2dd152a5..2d8a809f 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -649,7 +649,7 @@ AllowJavascript(); CHECK_EQ(2U, args->GetSize()); std::string callback_id; - DCHECK(args->GetString(0, &callback_id)); + CHECK(args->GetString(0, &callback_id)); std::string printer_id; CHECK(args->GetString(1, &printer_id));
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 5e54afaa..e6f86a8 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
@@ -607,6 +607,10 @@ {"stylusNoteTakingApp", IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_LABEL}, {"stylusNoteTakingAppEnabledOnLockScreen", IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_LOCK_SCREEN_CHECKBOX}, + {"stylusNoteTakingAppKeepsLastNoteOnLockScreen", + IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_KEEP_LATEST_NOTE}, + {"stylusNoteTakingAppLockScreenSettingsHeader", + IDS_SETTINGS_STYLUS_LOCK_SCREEN_NOTES_TITLE}, {"stylusNoteTakingAppNoneAvailable", IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_NONE_AVAILABLE}, {"stylusNoteTakingAppWaitingForAndroid",
diff --git a/chrome/browser/vr/elements/url_bar_texture.cc b/chrome/browser/vr/elements/url_bar_texture.cc index 949e4e1..e225c92 100644 --- a/chrome/browser/vr/elements/url_bar_texture.cc +++ b/chrome/browser/vr/elements/url_bar_texture.cc
@@ -330,9 +330,10 @@ const gfx::Rect& bounds) { url::Parsed parsed; - url_formatter::FormatUrlTypes format_types = url_formatter::kFormatUrlOmitAll; + url_formatter::FormatUrlTypes format_types = + url_formatter::kFormatUrlOmitDefaults; if (state_.offline_page) - format_types |= url_formatter::kFormatUrlExperimentalOmitHTTPS; + format_types |= url_formatter::kFormatUrlOmitHTTPS; const base::string16 text = url_formatter::FormatUrl( state_.gurl, format_types, net::UnescapeRule::NORMAL, &parsed, nullptr, nullptr);
diff --git a/chrome/browser/vr/elements/url_bar_texture_unittest.cc b/chrome/browser/vr/elements/url_bar_texture_unittest.cc index d41b4ce..f8a4c1f 100644 --- a/chrome/browser/vr/elements/url_bar_texture_unittest.cc +++ b/chrome/browser/vr/elements/url_bar_texture_unittest.cc
@@ -77,7 +77,7 @@ size_t GetNumberOfFontFallbacksForURL(const GURL& gurl) { url::Parsed parsed; const base::string16 text = url_formatter::FormatUrl( - gurl, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::NORMAL, + gurl, url_formatter::kFormatUrlOmitDefaults, net::UnescapeRule::NORMAL, &parsed, nullptr, nullptr); gfx::Size texture_size = GetPreferredTextureSize(kUrlWidthPixels); @@ -138,7 +138,7 @@ GURL url(base::UTF8ToUTF16(url_string)); url::Parsed parsed; const base::string16 formatted_url = url_formatter::FormatUrl( - url, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::NORMAL, + url, url_formatter::kFormatUrlOmitDefaults, net::UnescapeRule::NORMAL, &parsed, nullptr, nullptr); EXPECT_EQ(formatted_url, base::UTF8ToUTF16(expected_string)); TestUrlBarTexture::TestUrlStyling(
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index f329273a..ddc13be0 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -672,6 +672,7 @@ mojom("mojo_bindings") { sources = [ "cache_stats_recorder.mojom", + "constants.mojom", "file_patcher.mojom", "image_context_menu_renderer.mojom", "insecure_content_renderer.mojom",
diff --git a/chrome/common/constants.mojom b/chrome/common/constants.mojom new file mode 100644 index 0000000..83904dc --- /dev/null +++ b/chrome/common/constants.mojom
@@ -0,0 +1,7 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module chrome.mojom; + +const string kServiceName = "chrome";
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index b521f46..6719125 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -730,6 +730,11 @@ const char kNoteTakingAppsLockScreenWhitelist[] = "settings.note_taking_apps_lock_screen_whitelist"; +// Whether the preferred note taking app should be requested to restore the last +// note created on lock screen when launched on lock screen. +const char kRestoreLastLockScreenNote[] = + "settings.restore_last_lock_screen_note"; + // A boolean pref indicating whether user activity has been observed in the // current session already. The pref is used to restore information about user // activity after browser crashes.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index f9e7d8a1..0bfb05b 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -264,6 +264,7 @@ extern const char kNoteTakingAppId[]; extern const char kNoteTakingAppEnabledOnLockScreen[]; extern const char kNoteTakingAppsLockScreenWhitelist[]; +extern const char kRestoreLastLockScreenNote[]; extern const char kSessionUserActivitySeen[]; extern const char kSessionStartTime[]; extern const char kSessionLengthLimit[];
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index eaf33c7d..819196e 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -27,6 +27,7 @@ #include "chrome/common/chrome_isolated_world_ids.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/constants.mojom.h" #include "chrome/common/crash_keys.h" #include "chrome/common/features.h" #include "chrome/common/pause_tabs_field_trial.h" @@ -397,7 +398,7 @@ { startup_metric_utils::mojom::StartupMetricHostPtr startup_metric_host; - thread->GetConnector()->BindInterface(content::mojom::kBrowserServiceName, + thread->GetConnector()->BindInterface(chrome::mojom::kServiceName, &startup_metric_host); startup_metric_host->RecordRendererMainEntryTime(main_entry_time_); }
diff --git a/chrome/renderer/extensions/webstore_bindings.cc b/chrome/renderer/extensions/webstore_bindings.cc index a2d1ee4..d7b1534 100644 --- a/chrome/renderer/extensions/webstore_bindings.cc +++ b/chrome/renderer/extensions/webstore_bindings.cc
@@ -243,4 +243,14 @@ return false; } +void WebstoreBindings::Invalidate() { + // We should close all mojo pipes when we invalidate the WebstoreBindings + // object and before its associated v8::context is destroyed. This is to + // ensure there are no mojo calls that try to access the v8::context after its + // destruction. + inline_installer_.reset(); + install_progress_listener_bindings_.CloseAllBindings(); + ObjectBackedNativeHandler::Invalidate(); +} + } // namespace extensions
diff --git a/chrome/renderer/extensions/webstore_bindings.h b/chrome/renderer/extensions/webstore_bindings.h index 09c5dacb..9c6e616 100644 --- a/chrome/renderer/extensions/webstore_bindings.h +++ b/chrome/renderer/extensions/webstore_bindings.h
@@ -51,6 +51,9 @@ std::string* webstore_item_id, std::string* error); + // ObjectBackedNativeHandler: + void Invalidate() override; + mojom::InlineInstallerAssociatedPtr inline_installer_; mojo::BindingSet<mojom::InlineInstallProgressListener>
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 9df6bbc..780ebd46 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2028,7 +2028,6 @@ "../browser/chromeos/input_method/textinput_test_helper.cc", "../browser/chromeos/input_method/textinput_test_helper.h", "../browser/ui/ash/accelerator_commands_browsertest.cc", - "../browser/ui/ash/accelerator_controller_browsertest.cc", "../browser/ui/ash/app_list/app_list_controller_ash_browsertest.cc", "../browser/ui/ash/chrome_new_window_client_browsertest.cc", "../browser/ui/ash/keyboard_controller_browsertest.cc", @@ -2074,6 +2073,7 @@ "../browser/ui/views/external_protocol_dialog_browsertest.cc", "../browser/ui/views/frame/browser_non_client_frame_view_browsertest_win.cc", "../browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc", + "../browser/ui/views/importer/import_lock_dialog_view_browsertest.cc", "../browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc", "../browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc", "../browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestBase.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestBase.java index 66ea342..c9293422 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestBase.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestBase.java
@@ -12,6 +12,8 @@ import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.test.util.browser.tabmodel.document.MockStorageDelegate; +import java.util.concurrent.TimeoutException; + /** * Base for testing and interacting with multiple Activities (e.g. Document or Webapp Activities). */ @@ -47,7 +49,8 @@ /** * See {@link #waitForFullLoad(ChromeActivity,String,boolean)}. */ - protected void waitForFullLoad(final ChromeActivity activity, final String expectedTitle) { + protected void waitForFullLoad(final ChromeActivity activity, final String expectedTitle) + throws InterruptedException, TimeoutException { mTestCommon.waitForFullLoad(activity, expectedTitle); } }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestCommon.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestCommon.java index f38a7e8..9fec70d 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestCommon.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestCommon.java
@@ -8,21 +8,18 @@ import android.content.Context; import android.text.TextUtils; -import org.chromium.base.Log; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModel; -import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; +import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelSelector; import org.chromium.chrome.test.util.ApplicationTestUtils; import org.chromium.chrome.test.util.browser.tabmodel.document.MockStorageDelegate; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; // TODO(yolandyan): move this class to its test rule once JUnit4 migration is over final class MultiActivityTestCommon { @@ -53,8 +50,10 @@ RecordHistogram.setDisabledForTests(false); } - void waitForFullLoad(final ChromeActivity activity, final String expectedTitle) { + void waitForFullLoad(final ChromeActivity activity, final String expectedTitle) + throws InterruptedException, TimeoutException { waitForTabCreation(activity); + ApplicationTestUtils.assertWaitForPageScaleFactorMatch(activity, 0.5f); final Tab tab = activity.getActivityTab(); assert tab != null; @@ -69,22 +68,15 @@ }); } - private void waitForTabCreation(final ChromeActivity activity) { - final CountDownLatch latch = new CountDownLatch(1); - activity.getTabModelSelector().addObserver(new TabModelSelectorObserver() { - public void onChange() {} + private void waitForTabCreation(ChromeActivity activity) + throws InterruptedException, TimeoutException { + final CallbackHelper newTabCreatorHelper = new CallbackHelper(); + activity.getTabModelSelector().addObserver(new EmptyTabModelSelectorObserver() { public void onNewTabCreated(Tab tab) { - latch.countDown(); + newTabCreatorHelper.notifyCalled(); } - public void onTabModelSelected(TabModel newModel, TabModel oldModel) {} - public void onTabStateInitialized() {} - }); - try { - latch.await(CallbackHelper.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Log.w(TAG, "CountDownLatch interrupted. The test may fail."); - } + newTabCreatorHelper.waitForCallback(0); } public interface MultiActivityTestCommonCallback { Instrumentation getInstrumentation(); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestRule.java index d5800e4..c332fed 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestRule.java
@@ -16,6 +16,8 @@ import org.chromium.chrome.test.MultiActivityTestCommon.MultiActivityTestCommonCallback; import org.chromium.chrome.test.util.browser.tabmodel.document.MockStorageDelegate; +import java.util.concurrent.TimeoutException; + /** Custom TestRule for MultiActivity Tests. */ public class MultiActivityTestRule implements TestRule, MultiActivityTestCommonCallback { private final MultiActivityTestCommon mTestCommon; @@ -32,7 +34,8 @@ return mTestCommon.mContext; } - public void waitForFullLoad(final ChromeActivity activity, final String expectedTitle) { + public void waitForFullLoad(final ChromeActivity activity, final String expectedTitle) + throws InterruptedException, TimeoutException { mTestCommon.waitForFullLoad(activity, expectedTitle); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java index de3b67e0..4184339 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java
@@ -210,6 +210,6 @@ "Expecting scale factor of: " + expectedScale + ", got: " + scale); return Math.abs(scale - expectedScale) < FLOAT_EPSILON; } - }, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL, CriteriaHelper.DEFAULT_POLLING_INTERVAL); + }); } }
diff --git a/chrome/test/data/extensions/lock_screen_apps/app_launch_action_data/background.js b/chrome/test/data/extensions/lock_screen_apps/app_launch_action_data/background.js new file mode 100644 index 0000000..d3597c4b --- /dev/null +++ b/chrome/test/data/extensions/lock_screen_apps/app_launch_action_data/background.js
@@ -0,0 +1,19 @@ +// 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. + +chrome.app.runtime.onLaunched.addListener(function(launchData) { + // Tests that the received launch data contains the action data object that + // matches the test expectation. + chrome.test.runTests([ + function compareActionData() { + chrome.test.assertTrue(!!launchData.actionData); + + chrome.test.sendMessage( + 'getExpectedActionData', + chrome.test.callbackPass(function(actionData) { + chrome.test.assertEq(JSON.parse(actionData), launchData.actionData); + })); + } + ]); +});
diff --git a/chrome/test/data/extensions/lock_screen_apps/app_launch_action_data/manifest.json b/chrome/test/data/extensions/lock_screen_apps/app_launch_action_data/manifest.json new file mode 100644 index 0000000..9a8fd29 --- /dev/null +++ b/chrome/test/data/extensions/lock_screen_apps/app_launch_action_data/manifest.json
@@ -0,0 +1,16 @@ +{ + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA02u2EolNQq2mp/jmpE6tlctinxHNThc5FIsleGtPWsyCOxndLPlNqUKnXpAzllyUahwqtP+hYeYStiq3+0pcSEz4i9dGBF/DRKZ09LvKiDQB26Xvb8+IDxlqwe4Z/z9yQLB7xyg977z5Xi09DMVEtUfyuJTvtWQMcTpwyh5dEhK/F8R/lPrzmMU9bvidzRtruLuXd/DyQOPpNqSQTbN3Tg3dD4xDO54N+4ld8Pot6Nob0P0Yn/wm4c6Ct+5qwESaMP3C3WIIRDJ41rU4RgRSioxEYSdTtyrnO2qSK6KVKEFDmRp5hMxOn0r7C3CsdwMVMS3FXctjNia+1M3/2AMn/wIDAQAB", + "name": "Test lock screen app", + "version": "0.1", + "manifest_version": 2, + "permissions": ["lockScreen"], + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "action_handlers": [{ + "action": "new_note", + "enabled_on_lock_screen": true + }] +}
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js index 5e40c85..28003b2 100644 --- a/chrome/test/data/webui/settings/device_page_tests.js +++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -247,6 +247,11 @@ value: false, }, }, + restore_last_lock_screen_note: { + key: 'settings.restore_last_lock_screen_note', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: true, + }, touchpad: { enable_tap_to_click: { key: 'settings.touchpad.enable_tap_to_click', @@ -1095,23 +1100,34 @@ }; } - /** - * @return {Element | undefined} - */ + /** @return {?Element} */ + function noteTakingAppLockScreenSettings() { + return stylusPage.$$('#note-taking-app-lock-screen-settings'); + } + + /** @return {?Element} */ function enableAppOnLockScreenToggle() { return stylusPage.$$('#enable-app-on-lock-screen-toggle'); } + /** @return {?Element} */ function enableAppOnLockScreenPolicyIndicator() { return stylusPage.$$("#enable-app-on-lock-screen-policy-indicator"); } + /** @return {?Element} */ function enableAppOnLockScreenToggleLabel() { return stylusPage.$$('#lock-screen-toggle-label'); } + /** @return {?Element} */ + function keepLastNoteOnLockScreenToggle() { + return stylusPage.$$('#keep-last-note-on-lock-screen-toggle'); + } + /** - * @param {Element|undefined} element + * @param {?Element} element + * @return {boolean} */ function isVisible(element) { return !!element && element.offsetWidth > 0 && element.offsetHeight > 0; @@ -1213,6 +1229,7 @@ }); test('enabled-on-lock-screen', function() { + expectFalse(isVisible(noteTakingAppLockScreenSettings())); expectFalse(isVisible(enableAppOnLockScreenToggle())); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1222,6 +1239,7 @@ stylusPage.async(resolve); }).then(function() { Polymer.dom.flush(); + expectFalse(isVisible(noteTakingAppLockScreenSettings())); expectFalse(isVisible(enableAppOnLockScreenToggle())); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1231,6 +1249,7 @@ return new Promise(function(resolve) {stylusPage.async(resolve);}); }).then(function() { Polymer.dom.flush(); + expectFalse(isVisible(noteTakingAppLockScreenSettings())); expectFalse(isVisible(enableAppOnLockScreenToggle())); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1240,6 +1259,7 @@ return new Promise(function(resolve) { stylusPage.async(resolve); }); }).then(function() { Polymer.dom.flush(); + expectFalse(isVisible(noteTakingAppLockScreenSettings())); expectFalse(isVisible(enableAppOnLockScreenToggle())); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1252,6 +1272,7 @@ return new Promise(function(resolve) { stylusPage.async(resolve); }); }).then(function() { Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); assert(isVisible(enableAppOnLockScreenToggle())); expectFalse(enableAppOnLockScreenToggle().checked); @@ -1264,6 +1285,7 @@ return new Promise(function(resolve) { stylusPage.async(resolve); }); }).then(function() { Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); assert(isVisible(enableAppOnLockScreenToggle())); expectTrue(enableAppOnLockScreenToggle().checked); @@ -1277,6 +1299,7 @@ return new Promise(function(resolve) { stylusPage.async(resolve); }); }).then(function() { Polymer.dom.flush(); + expectFalse(isVisible(noteTakingAppLockScreenSettings())); expectFalse(isVisible(enableAppOnLockScreenToggle())); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); }); @@ -1291,6 +1314,7 @@ }).then(function() { Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); assert(isVisible(enableAppOnLockScreenToggle())); expectFalse(enableAppOnLockScreenToggle().checked); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1302,6 +1326,7 @@ return new Promise(function(resolve) { stylusPage.async(resolve); }); }).then(function() { Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); assert(isVisible(enableAppOnLockScreenToggle())); expectTrue(enableAppOnLockScreenToggle().checked); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1313,6 +1338,7 @@ return new Promise(function(resolve) { stylusPage.async(resolve); }); }).then(function() { Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); assert(isVisible(enableAppOnLockScreenToggle())); expectFalse(enableAppOnLockScreenToggle().checked); expectFalse(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1410,6 +1436,7 @@ stylusPage.async(resolve); }).then(function() { Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); assert(isVisible(enableAppOnLockScreenToggle())); expectFalse(enableAppOnLockScreenToggle().checked); expectTrue(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1430,6 +1457,7 @@ return new Promise(function(resolve) { stylusPage.async(resolve); }); }).then(function() { Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); assert(isVisible(enableAppOnLockScreenToggle())); expectFalse(enableAppOnLockScreenToggle().checked); expectTrue(isVisible(enableAppOnLockScreenPolicyIndicator())); @@ -1438,6 +1466,52 @@ browserProxy.getPreferredAppLockScreenState()); }); }); + + test('keep-last-note-on-lock-screen', function() { + return new Promise(function(resolve) { + browserProxy.setNoteTakingApps([ + entry('n1', 'v1', true, LockScreenSupport.NOT_SUPPORTED), + entry('n2', 'v2', false, LockScreenSupport.SUPPORTED) + ]); + stylusPage.async(resolve); + }).then(function() { + Polymer.dom.flush(); + expectFalse(isVisible(noteTakingAppLockScreenSettings())); + expectFalse(isVisible(keepLastNoteOnLockScreenToggle())); + + browserProxy.setNoteTakingApps([ + entry('n1', 'v1', false, LockScreenSupport.NOT_SUPPORTED), + entry('n2', 'v2', true, LockScreenSupport.SUPPORTED) + ]); + return new Promise(function(resolve) { stylusPage.async(resolve); }); + }).then(function() { + Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); + expectFalse(isVisible(keepLastNoteOnLockScreenToggle())); + + browserProxy.setNoteTakingApps([ + entry('n2', 'v2', true, LockScreenSupport.ENABLED), + ]); + return new Promise(function(resolve) { stylusPage.async(resolve); }); + }).then(function() { + Polymer.dom.flush(); + expectTrue(isVisible(noteTakingAppLockScreenSettings())); + assert(isVisible(keepLastNoteOnLockScreenToggle())); + expectTrue(keepLastNoteOnLockScreenToggle().checked); + + // Clicking the toggle updates the pref value. + MockInteractions.tap(keepLastNoteOnLockScreenToggle().$$('#control')); + expectFalse(keepLastNoteOnLockScreenToggle().checked); + + expectFalse( + devicePage.prefs.settings.restore_last_lock_screen_note.value); + + // Changing the pref value updates the toggle. + devicePage.set( + 'prefs.settings.restore_last_lock_screen_note.value', true); + expectTrue(keepLastNoteOnLockScreenToggle().checked); + }); + }); }); });
diff --git a/chrome/tools/build/repack_locales.py b/chrome/tools/build/repack_locales.py deleted file mode 100755 index 2b85547..0000000 --- a/chrome/tools/build/repack_locales.py +++ /dev/null
@@ -1,299 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 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. - -"""Helper script to repack paks for a list of locales. - -Gyp doesn't have any built-in looping capability, so this just provides a way to -loop over a list of locales when repacking pak files, thus avoiding a -proliferation of mostly duplicate, cut-n-paste gyp actions. -""" - -import optparse -import os -import sys - -# Prepend the grit module from the source tree so it takes precedence over other -# grit versions that might present in the search path. -sys.path.insert(1, os.path.join(os.path.dirname(__file__), '..', '..', '..', - 'tools', 'grit')) -from grit.format import data_pack - -# The gyp "branding" variable. -BRANDING = None - -# Some build paths defined by gyp. -GRIT_DIR = None -SHARE_INT_DIR = None -INT_DIR = None - -# The target platform. If it is not defined, sys.platform will be used. -OS = None - -# Note that OS is normally set to 'linux' when building for chromeos. -CHROMEOS = False - -USE_ASH = False -ENABLE_EXTENSIONS = False - -WHITELIST = None - -# Extra input files. -EXTRA_INPUT_FILES = [] - -class Usage(Exception): - def __init__(self, msg): - self.msg = msg - - -def calc_output(locale): - """Determine the file that will be generated for the given locale.""" - #e.g. '<(INTERMEDIATE_DIR)/repack/da.pak', - # For Fake Bidi, generate it at a fixed path so that tests can safely - # reference it. - if locale == 'fake-bidi': - return '%s/%s.pak' % (INT_DIR, locale) - if OS == 'mac' or OS == 'ios': - # For Cocoa to find the locale at runtime, it needs to use '_' instead - # of '-' (http://crbug.com/20441). Also, 'en-US' should be represented - # simply as 'en' (http://crbug.com/19165, http://crbug.com/25578). - if locale == 'en-US': - locale = 'en' - return '%s/repack/%s.lproj/locale.pak' % (INT_DIR, locale.replace('-', '_')) - else: - return os.path.join(INT_DIR, 'repack', locale + '.pak') - - -def calc_inputs(locale): - """Determine the files that need processing for the given locale.""" - inputs = [] - - #e.g. '<(grit_out_dir)/generated_resources_da.pak' - inputs.append(os.path.join(GRIT_DIR, 'generated_resources_%s.pak' % locale)) - - #e.g. '<(grit_out_dir)/locale_settings_da.pak' - inputs.append(os.path.join(GRIT_DIR, 'locale_settings_%s.pak' % locale)) - - #e.g. '<(grit_out_dir)/platform_locale_settings_da.pak' - inputs.append(os.path.join(GRIT_DIR, - 'platform_locale_settings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/components/strings/ - # components_locale_settings_da.pak', - inputs.append(os.path.join(SHARE_INT_DIR, 'components', 'strings', - 'components_locale_settings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/components/strings/ - # components_strings_da.pak', - inputs.append(os.path.join(SHARE_INT_DIR, 'components', 'strings', - 'components_strings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/components/strings/ - # components_chromium_strings_da.pak' - # or - # '<(SHARED_INTERMEDIATE_DIR)/components/strings/ - # components_google_chrome_strings_da.pak', - inputs.append(os.path.join(SHARE_INT_DIR, 'components', 'strings', - 'components_%s_strings_%s.pak' % (BRANDING, locale))) - - if USE_ASH: - #e.g. '<(SHARED_INTERMEDIATE_DIR)/ash/strings/ash_strings_da.pak', - inputs.append(os.path.join(SHARE_INT_DIR, 'ash', 'strings', - 'ash_strings_%s.pak' % locale)) - - if CHROMEOS: - inputs.append(os.path.join(SHARE_INT_DIR, 'ui', 'chromeos', 'strings', - 'ui_chromeos_strings_%s.pak' % locale)) - inputs.append(os.path.join(SHARE_INT_DIR, 'remoting', 'resources', - '%s.pak' % locale)) - - if OS != 'ios': - #e.g. - # '<(SHARED_INTERMEDIATE_DIR)/content/app/strings/content_strings_da.pak' - inputs.append(os.path.join(SHARE_INT_DIR, 'content', 'app', 'strings', - 'content_strings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/device/bluetooth/strings/ - # bluetooth_strings_da.pak', - inputs.append(os.path.join(SHARE_INT_DIR, 'device', 'bluetooth', 'strings', - 'bluetooth_strings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/ui/strings/ui_strings_da.pak', - inputs.append(os.path.join(SHARE_INT_DIR, 'ui', 'strings', - 'ui_strings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/ui/strings/app_locale_settings_da.pak', - inputs.append(os.path.join(SHARE_INT_DIR, 'ui', 'strings', - 'app_locale_settings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/third_party/libaddressinput/ - # address_input_strings_da.pak', - inputs.append(os.path.join(SHARE_INT_DIR, 'third_party', 'libaddressinput', - 'address_input_strings_%s.pak' % locale)) - - else: - #e.g. '<(SHARED_INTERMEDIATE_DIR)/ios/chrome/ios_locale_settings_da.pak' - inputs.append(os.path.join(SHARE_INT_DIR, 'ios', 'chrome', - 'ios_locale_settings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/ios/chrome/ios_strings_da.pak' - inputs.append(os.path.join(SHARE_INT_DIR, 'ios', 'chrome', - 'ios_strings_%s.pak' % locale)) - - #e.g. '<(SHARED_INTERMEDIATE_DIR)/ios/chrome/ios_chromium_strings_da.pak' - # or '<(SHARED_INTERMEDIATE_DIR)/ios/chrome/ - # ios_google_chrome_strings_da.pak' - inputs.append(os.path.join(SHARE_INT_DIR, 'ios', 'chrome', - 'ios_%s_strings_%s.pak' % (BRANDING, locale))) - - if ENABLE_EXTENSIONS: - # For example: - # '<(SHARED_INTERMEDIATE_DIR)/extensions/strings/extensions_strings_da.pak - # TODO(jamescook): When Android stops building extensions code move this - # to the OS != 'ios' and OS != 'android' section below. - inputs.append(os.path.join(SHARE_INT_DIR, 'extensions', 'strings', - 'extensions_strings_%s.pak' % locale)) - - #e.g. '<(grit_out_dir)/google_chrome_strings_da.pak' - # or - # '<(grit_out_dir)/chromium_strings_da.pak' - inputs.append(os.path.join( - GRIT_DIR, '%s_strings_%s.pak' % (BRANDING, locale))) - - # Add any extra input files. - for extra_file in EXTRA_INPUT_FILES: - inputs.append('%s_%s.pak' % (extra_file, locale)) - - return inputs - - -def list_outputs(locales): - """Returns the names of files that will be generated for the given locales. - - This is to provide gyp the list of output files, so build targets can - properly track what needs to be built. - """ - outputs = [] - for locale in locales: - outputs.append(calc_output(locale)) - # Quote each element so filename spaces don't mess up gyp's attempt to parse - # it into a list. - return " ".join(['"%s"' % x for x in outputs]) - - -def list_inputs(locales): - """Returns the names of files that will be processed for the given locales. - - This is to provide gyp the list of input files, so build targets can properly - track their prerequisites. - """ - inputs = [] - for locale in locales: - inputs += calc_inputs(locale) - # Quote each element so filename spaces don't mess up gyp's attempt to parse - # it into a list. - return " ".join(['"%s"' % x for x in inputs]) - - -def repack_locales(locales): - """ Loop over and repack the given locales.""" - for locale in locales: - inputs = [] - inputs += calc_inputs(locale) - output = calc_output(locale) - data_pack.DataPack.RePack(output, inputs, whitelist_file=WHITELIST) - - -def DoMain(argv): - global BRANDING - global GRIT_DIR - global SHARE_INT_DIR - global INT_DIR - global OS - global CHROMEOS - global USE_ASH - global WHITELIST - global ENABLE_AUTOFILL_DIALOG - global ENABLE_EXTENSIONS - global EXTRA_INPUT_FILES - - parser = optparse.OptionParser("usage: %prog [options] locales") - parser.add_option("-i", action="store_true", dest="inputs", default=False, - help="Print the expected input file list, then exit.") - parser.add_option("-o", action="store_true", dest="outputs", default=False, - help="Print the expected output file list, then exit.") - parser.add_option("-g", action="store", dest="grit_dir", - help="GRIT build files output directory.") - parser.add_option("-x", action="store", dest="int_dir", - help="Intermediate build files output directory.") - parser.add_option("-s", action="store", dest="share_int_dir", - help="Shared intermediate build files output directory.") - parser.add_option("-b", action="store", dest="branding", - help="Branding type of this build.") - parser.add_option("-e", action="append", dest="extra_input", default=[], - help="Full path to an extra input pak file without the\ - locale suffix and \".pak\" extension.") - parser.add_option("-p", action="store", dest="os", - help="The target OS. (e.g. mac, linux, win, etc.)") - parser.add_option("--use-ash", action="store", dest="use_ash", - help="Whether to include ash strings") - parser.add_option("--chromeos", action="store", - help="Whether building for Chrome OS") - parser.add_option("--whitelist", action="store", help="Full path to the " - "whitelist used to filter output pak file resource IDs") - parser.add_option("--enable-autofill-dialog", action="store", - dest="enable_autofill_dialog", - help="Whether to include strings for autofill dialog") - parser.add_option("--enable-extensions", action="store", - dest="enable_extensions", - help="Whether to include strings for extensions") - options, locales = parser.parse_args(argv) - - if not locales: - parser.error('Please specificy at least one locale to process.\n') - - print_inputs = options.inputs - print_outputs = options.outputs - GRIT_DIR = options.grit_dir - INT_DIR = options.int_dir - SHARE_INT_DIR = options.share_int_dir - BRANDING = options.branding - EXTRA_INPUT_FILES = options.extra_input - OS = options.os - CHROMEOS = options.chromeos == '1' - USE_ASH = options.use_ash == '1' - WHITELIST = options.whitelist - ENABLE_AUTOFILL_DIALOG = options.enable_autofill_dialog == '1' - ENABLE_EXTENSIONS = options.enable_extensions == '1' - - if not OS: - if sys.platform == 'darwin': - OS = 'mac' - elif sys.platform.startswith('linux'): - OS = 'linux' - elif sys.platform in ('cygwin', 'win32'): - OS = 'win' - else: - OS = sys.platform - - if not (GRIT_DIR and INT_DIR and SHARE_INT_DIR): - parser.error('Please specify all of "-g" and "-x" and "-s".\n') - if print_inputs and print_outputs: - parser.error('Please specify only one of "-i" or "-o".\n') - # Need to know the branding, unless we're just listing the outputs. - if not print_outputs and not BRANDING: - parser.error('Please specify "-b" to determine the input files.\n') - - if print_inputs: - return list_inputs(locales) - - if print_outputs: - return list_outputs(locales) - - return repack_locales(locales) - -if __name__ == '__main__': - results = DoMain(sys.argv[1:]) - if results: - print results
diff --git a/chromecast/media/service/cast_mojo_media_client.cc b/chromecast/media/service/cast_mojo_media_client.cc index d46196a..468a40e 100644 --- a/chromecast/media/service/cast_mojo_media_client.cc +++ b/chromecast/media/service/cast_mojo_media_client.cc
@@ -78,7 +78,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, ::media::AudioRendererSink* audio_renderer_sink, ::media::VideoRendererSink* video_renderer_sink, - const ::media::RequestOverlayInfoCB& request_overlay_info_cb) final { + const ::media::RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) final { DCHECK(audio_renderer_sink); DCHECK(!video_renderer_sink); return base::MakeUnique<CastRenderer>(
diff --git a/components/cryptauth/cryptauth_enrollment_manager.cc b/components/cryptauth/cryptauth_enrollment_manager.cc index 8381de24..53303471 100644 --- a/components/cryptauth/cryptauth_enrollment_manager.cc +++ b/components/cryptauth/cryptauth_enrollment_manager.cc
@@ -42,6 +42,14 @@ // registration. const char kDeviceSoftwarePackage[] = "com.google.chrome.cryptauth"; +std::unique_ptr<SyncScheduler> CreateSyncScheduler( + SyncScheduler::Delegate* delegate) { + return base::MakeUnique<SyncSchedulerImpl>( + delegate, base::TimeDelta::FromDays(kEnrollmentRefreshPeriodDays), + base::TimeDelta::FromMinutes(kEnrollmentBaseRecoveryPeriodMinutes), + kEnrollmentMaxJitterRatio, "CryptAuth Enrollment"); +} + } // namespace CryptAuthEnrollmentManager::CryptAuthEnrollmentManager( @@ -57,6 +65,7 @@ device_info_(device_info), gcm_manager_(gcm_manager), pref_service_(pref_service), + scheduler_(CreateSyncScheduler(this /* delegate */)), weak_ptr_factory_(this) {} CryptAuthEnrollmentManager::~CryptAuthEnrollmentManager() { @@ -89,7 +98,6 @@ base::TimeDelta elapsed_time_since_last_sync = clock_->Now() - last_successful_enrollment; - scheduler_ = CreateSyncScheduler(); scheduler_->Start(elapsed_time_since_last_sync, is_recovering_from_failure ? SyncScheduler::Strategy::AGGRESSIVE_RECOVERY @@ -159,14 +167,6 @@ observer.OnEnrollmentFinished(success); } -std::unique_ptr<SyncScheduler> -CryptAuthEnrollmentManager::CreateSyncScheduler() { - return base::MakeUnique<SyncSchedulerImpl>( - this, base::TimeDelta::FromDays(kEnrollmentRefreshPeriodDays), - base::TimeDelta::FromMinutes(kEnrollmentBaseRecoveryPeriodMinutes), - kEnrollmentMaxJitterRatio, "CryptAuth Enrollment"); -} - std::string CryptAuthEnrollmentManager::GetUserPublicKey() const { std::string public_key; if (!base::Base64UrlDecode( @@ -189,6 +189,11 @@ return private_key; } +void CryptAuthEnrollmentManager::SetSyncSchedulerForTest( + std::unique_ptr<SyncScheduler> sync_scheduler) { + scheduler_ = std::move(sync_scheduler); +} + void CryptAuthEnrollmentManager::OnGCMRegistrationResult(bool success) { if (!sync_request_) return;
diff --git a/components/cryptauth/cryptauth_enrollment_manager.h b/components/cryptauth/cryptauth_enrollment_manager.h index ce4c9da7..8bd187a 100644 --- a/components/cryptauth/cryptauth_enrollment_manager.h +++ b/components/cryptauth/cryptauth_enrollment_manager.h
@@ -116,8 +116,7 @@ virtual std::string GetUserPrivateKey() const; protected: - // Creates a new SyncScheduler instance. Exposed for testing. - virtual std::unique_ptr<SyncScheduler> CreateSyncScheduler(); + void SetSyncSchedulerForTest(std::unique_ptr<SyncScheduler> sync_scheduler); private: // CryptAuthGCMManager::Observer:
diff --git a/components/cryptauth/cryptauth_enrollment_manager_unittest.cc b/components/cryptauth/cryptauth_enrollment_manager_unittest.cc index 7a98f86d..d0a4920 100644 --- a/components/cryptauth/cryptauth_enrollment_manager_unittest.cc +++ b/components/cryptauth/cryptauth_enrollment_manager_unittest.cc
@@ -112,15 +112,12 @@ gcm_manager, pref_service), scoped_sync_scheduler_(new NiceMock<MockSyncScheduler>()), - weak_sync_scheduler_factory_(scoped_sync_scheduler_.get()) {} + weak_sync_scheduler_factory_(scoped_sync_scheduler_) { + SetSyncSchedulerForTest(base::WrapUnique(scoped_sync_scheduler_)); + } ~TestCryptAuthEnrollmentManager() override {} - std::unique_ptr<SyncScheduler> CreateSyncScheduler() override { - EXPECT_TRUE(scoped_sync_scheduler_); - return std::move(scoped_sync_scheduler_); - } - base::WeakPtr<MockSyncScheduler> GetSyncScheduler() { return weak_sync_scheduler_factory_.GetWeakPtr(); } @@ -128,7 +125,7 @@ private: // Ownership is passed to |CryptAuthEnrollmentManager| super class when // |CreateSyncScheduler()| is called. - std::unique_ptr<MockSyncScheduler> scoped_sync_scheduler_; + NiceMock<MockSyncScheduler>* scoped_sync_scheduler_; // Stores the pointer of |scoped_sync_scheduler_| after ownership is passed to // the super class.
diff --git a/components/discardable_memory/common/discardable_shared_memory_heap.cc b/components/discardable_memory/common/discardable_shared_memory_heap.cc index 7eacbee..58f4182 100644 --- a/components/discardable_memory/common/discardable_shared_memory_heap.cc +++ b/components/discardable_memory/common/discardable_shared_memory_heap.cc
@@ -427,22 +427,16 @@ ->GetTracingProcessId(); base::trace_event::MemoryAllocatorDumpGuid shared_segment_guid = GetSegmentGUIDForTracing(tracing_process_id, segment_id); - // TODO(ssid): Make this weak once the GUID created is consistent - // crbug.com/661257. - pmd->CreateSharedGlobalAllocatorDump(shared_segment_guid); - - // The size is added to the global dump so that it gets propagated to both the - // dumps associated. - pmd->GetSharedGlobalAllocatorDump(shared_segment_guid) - ->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - allocated_objects_size_in_bytes); // By creating an edge with a higher |importance| (w.r.t. browser-side dumps) // the tracing UI will account the effective size of the segment to the // client. const int kImportance = 2; - pmd->AddOwnershipEdge(segment_dump->guid(), shared_segment_guid, kImportance); + auto shared_memory_guid = shared_memory->mapped_id(); + segment_dump->AddString("id", "hash", shared_memory_guid.ToString()); + pmd->CreateWeakSharedMemoryOwnershipEdge(segment_dump->guid(), + shared_segment_guid, + shared_memory_guid, kImportance); } // static
diff --git a/components/discardable_memory/service/discardable_shared_memory_manager.cc b/components/discardable_memory/service/discardable_shared_memory_manager.cc index aca8774..282e28d 100644 --- a/components/discardable_memory/service/discardable_shared_memory_manager.cc +++ b/components/discardable_memory/service/discardable_shared_memory_manager.cc
@@ -302,7 +302,8 @@ if (!segment->memory()->mapped_size()) continue; - // The "size" will be inherited form the shared global dump. + // TODO(ssid): The "size" should be inherited from the shared memory dump, + // crbug.com/661257. std::string dump_name = base::StringPrintf( "discardable/process_%x/segment_%d", client_id, segment_id); base::trace_event::MemoryAllocatorDump* dump = @@ -327,24 +328,12 @@ base::trace_event::MemoryAllocatorDumpGuid shared_segment_guid = DiscardableSharedMemoryHeap::GetSegmentGUIDForTracing( client_tracing_id, segment_id); - pmd->CreateSharedGlobalAllocatorDump(shared_segment_guid); - pmd->AddOwnershipEdge(dump->guid(), shared_segment_guid); -#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) - if (args.level_of_detail == - base::trace_event::MemoryDumpLevelOfDetail::DETAILED) { - size_t resident_size = - base::trace_event::ProcessMemoryDump::CountResidentBytes( - segment->memory()->memory(), segment->memory()->mapped_size()); - - // This is added to the global dump since it has to be attributed to - // both the allocator dumps involved. - pmd->GetSharedGlobalAllocatorDump(shared_segment_guid) - ->AddScalar("resident_size", - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - static_cast<uint64_t>(resident_size)); - } -#endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) + auto shared_memory_guid = segment->memory()->mapped_id(); + dump->AddString("id", "hash", shared_memory_guid.ToString()); + pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_segment_guid, + shared_memory_guid, + 0 /* importance */); } } return true;
diff --git a/components/network_session_configurator/browser/network_session_configurator.cc b/components/network_session_configurator/browser/network_session_configurator.cc index e3b19f3..d601712 100644 --- a/components/network_session_configurator/browser/network_session_configurator.cc +++ b/components/network_session_configurator/browser/network_session_configurator.cc
@@ -150,6 +150,17 @@ return net::ParseQuicConnectionOptions(it->second); } +net::QuicTagVector GetQuicClientConnectionOptions( + const VariationParameters& quic_trial_params) { + VariationParameters::const_iterator it = + quic_trial_params.find("client_connection_options"); + if (it == quic_trial_params.end()) { + return net::QuicTagVector(); + } + + return net::ParseQuicConnectionOptions(it->second); +} + bool ShouldForceHolBlocking(const VariationParameters& quic_trial_params) { return base::LowerCaseEqualsASCII( GetVariationParam(quic_trial_params, "force_hol_blocking"), "true"); @@ -260,6 +271,8 @@ params->quic_force_hol_blocking = ShouldForceHolBlocking(quic_trial_params); params->quic_connection_options = GetQuicConnectionOptions(quic_trial_params); + params->quic_client_connection_options = + GetQuicClientConnectionOptions(quic_trial_params); params->quic_close_sessions_on_ip_change = ShouldQuicCloseSessionsOnIpChange(quic_trial_params); int idle_connection_timeout_seconds =
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc index 0697046..eeaf0c1f 100644 --- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -89,6 +89,7 @@ EXPECT_FALSE(params_.retry_without_alt_svc_on_quic_errors); EXPECT_EQ(1350u, params_.quic_max_packet_length); EXPECT_EQ(net::QuicTagVector(), params_.quic_connection_options); + EXPECT_EQ(net::QuicTagVector(), params_.quic_client_connection_options); EXPECT_FALSE(params_.enable_server_push_cancellation); EXPECT_FALSE(params_.quic_close_sessions_on_ip_change); EXPECT_EQ(net::kIdleConnectionTimeoutSeconds, @@ -350,6 +351,21 @@ EXPECT_EQ(options, params_.quic_connection_options); } +TEST_F(NetworkSessionConfiguratorTest, + QuicClientConnectionOptionsFromFieldTrialParams) { + std::map<std::string, std::string> field_trial_params; + field_trial_params["client_connection_options"] = "TBBR,1RTT"; + variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); + base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); + + ParseFieldTrials(); + + net::QuicTagVector options; + options.push_back(net::kTBBR); + options.push_back(net::k1RTT); + EXPECT_EQ(options, params_.quic_client_connection_options); +} + TEST_F(NetworkSessionConfiguratorTest, Http2SettingsFromFieldTrialParams) { std::map<std::string, std::string> field_trial_params; field_trial_params["http2_settings"] = "7:1234,25:5678";
diff --git a/components/offline_pages/core/prefetch/download_completed_task.cc b/components/offline_pages/core/prefetch/download_completed_task.cc index d5b83a8..1c578e574 100644 --- a/components/offline_pages/core/prefetch/download_completed_task.cc +++ b/components/offline_pages/core/prefetch/download_completed_task.cc
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/files/file_path.h" #include "base/logging.h" +#include "components/offline_pages/core/prefetch/prefetch_dispatcher.h" #include "components/offline_pages/core/prefetch/prefetch_types.h" #include "components/offline_pages/core/prefetch/store/prefetch_store.h" #include "sql/connection.h" @@ -55,9 +56,11 @@ } // namespace DownloadCompletedTask::DownloadCompletedTask( + PrefetchDispatcher* prefetch_dispatcher, PrefetchStore* prefetch_store, const PrefetchDownloadResult& download_result) - : prefetch_store_(prefetch_store), + : prefetch_dispatcher_(prefetch_dispatcher), + prefetch_store_(prefetch_store), download_result_(download_result), weak_ptr_factory_(this) { DCHECK(!download_result_.download_id.empty()); @@ -71,36 +74,22 @@ base::BindOnce(&UpdatePrefetchItemOnDownloadSuccessSync, download_result_.download_id, download_result_.file_path, download_result_.file_size), - base::BindOnce(&DownloadCompletedTask::OnDownloadSuccessUpdated, + base::BindOnce(&DownloadCompletedTask::OnPrefetchItemUpdated, weak_ptr_factory_.GetWeakPtr())); } else { prefetch_store_->Execute( base::BindOnce(&UpdatePrefetchItemOnDownloadErrorSync, download_result_.download_id), - base::BindOnce(&DownloadCompletedTask::OnDownloadErrorUpdated, + base::BindOnce(&DownloadCompletedTask::OnPrefetchItemUpdated, weak_ptr_factory_.GetWeakPtr())); } } -void DownloadCompletedTask::OnDownloadSuccessUpdated(bool success) { +void DownloadCompletedTask::OnPrefetchItemUpdated(bool success) { // No further action can be done if the database fails to be updated. The // cleanup task should eventually kick in to clean this up. - if (success) { - // TODO(jianli): Calls SchedulePipelineProcessing to process the download. - NOTIMPLEMENTED(); - } - - TaskComplete(); -} - -void DownloadCompletedTask::OnDownloadErrorUpdated(bool success) { - // No further action can be done if the database fails to be updated. The - // cleanup task should eventually kick in to clean this up. - if (success) { - // TODO(jianli): Calls SchedulePipelineProcessing to process the item in - // finished error state. - NOTIMPLEMENTED(); - } + if (success) + prefetch_dispatcher_->SchedulePipelineProcessing(); TaskComplete(); }
diff --git a/components/offline_pages/core/prefetch/download_completed_task.h b/components/offline_pages/core/prefetch/download_completed_task.h index 6a99692..118713c 100644 --- a/components/offline_pages/core/prefetch/download_completed_task.h +++ b/components/offline_pages/core/prefetch/download_completed_task.h
@@ -11,21 +11,23 @@ #include "components/offline_pages/core/task.h" namespace offline_pages { +class PrefetchDispatcher; class PrefetchStore; // Task that responses to the completed download. class DownloadCompletedTask : public Task { public: - DownloadCompletedTask(PrefetchStore* prefetch_store, + DownloadCompletedTask(PrefetchDispatcher* prefetch_dispatcher, + PrefetchStore* prefetch_store, const PrefetchDownloadResult& download_result); ~DownloadCompletedTask() override; void Run() override; private: - void OnDownloadSuccessUpdated(bool success); - void OnDownloadErrorUpdated(bool success); + void OnPrefetchItemUpdated(bool success); + PrefetchDispatcher* prefetch_dispatcher_; // Outlives this class. PrefetchStore* prefetch_store_; // Outlives this class. PrefetchDownloadResult download_result_;
diff --git a/components/offline_pages/core/prefetch/download_completed_task_unittest.cc b/components/offline_pages/core/prefetch/download_completed_task_unittest.cc index 1b4497f..a70258bd 100644 --- a/components/offline_pages/core/prefetch/download_completed_task_unittest.cc +++ b/components/offline_pages/core/prefetch/download_completed_task_unittest.cc
@@ -15,6 +15,7 @@ #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/store/prefetch_store_utils.h" +#include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h" #include "sql/connection.h" #include "sql/statement.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,11 +42,13 @@ void PumpLoop(); PrefetchStore* store() { return store_test_util_.store(); } + TestPrefetchDispatcher* dispatcher() { return &dispatcher_; } PrefetchStoreTestUtil* store_util() { return &store_test_util_; } private: scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; + TestPrefetchDispatcher dispatcher_; PrefetchStoreTestUtil store_test_util_; }; @@ -86,7 +89,7 @@ TEST_F(DownloadCompletedTaskTest, UpdateItemOnDownloadSuccess) { PrefetchDownloadResult download_result(kTestGUID, kTestFilePath, kTestFileSize); - DownloadCompletedTask task(store(), download_result); + DownloadCompletedTask task(dispatcher(), store(), download_result); task.Run(); PumpLoop(); @@ -102,7 +105,7 @@ PrefetchDownloadResult download_result; download_result.download_id = kTestGUID; download_result.success = false; - DownloadCompletedTask task(store(), download_result); + DownloadCompletedTask task(dispatcher(), store(), download_result); task.Run(); PumpLoop(); @@ -118,7 +121,7 @@ TEST_F(DownloadCompletedTaskTest, NoUpdateOnMismatchedDownloadSuccess) { PrefetchDownloadResult download_result(kTestGUID2, kTestFilePath, kTestFileSize); - DownloadCompletedTask task(store(), download_result); + DownloadCompletedTask task(dispatcher(), store(), download_result); task.Run(); PumpLoop(); @@ -136,7 +139,7 @@ PrefetchDownloadResult download_result; download_result.download_id = kTestGUID2; download_result.success = false; - DownloadCompletedTask task(store(), download_result); + DownloadCompletedTask task(dispatcher(), store(), download_result); task.Run(); PumpLoop();
diff --git a/components/offline_pages/core/prefetch/import_archives_task.cc b/components/offline_pages/core/prefetch/import_archives_task.cc index 1de35ca1..253c80e8 100644 --- a/components/offline_pages/core/prefetch/import_archives_task.cc +++ b/components/offline_pages/core/prefetch/import_archives_task.cc
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/files/file_path.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "components/offline_pages/core/prefetch/prefetch_types.h" #include "components/offline_pages/core/prefetch/store/prefetch_store.h" #include "sql/connection.h" @@ -18,7 +19,8 @@ namespace offline_pages { namespace { -std::vector<PrefetchArchiveInfo> GetArchivesSync(sql::Connection* db) { +std::unique_ptr<std::vector<PrefetchArchiveInfo>> GetArchivesSync( + sql::Connection* db) { static const char kSql[] = "SELECT offline_id, client_namespace, client_id, requested_url," " final_archived_url, title, file_path, file_size" @@ -27,7 +29,7 @@ sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt(0, static_cast<int>(PrefetchItemState::DOWNLOADED)); - std::vector<PrefetchArchiveInfo> archives; + std::unique_ptr<std::vector<PrefetchArchiveInfo>> archives; while (statement.Step()) { PrefetchArchiveInfo archive; archive.offline_id = statement.ColumnInt64(0); @@ -39,7 +41,9 @@ archive.file_path = base::FilePath::FromUTF8Unsafe(statement.ColumnString(6)); archive.file_size = statement.ColumnInt64(7); - archives.push_back(archive); + if (!archives) + archives = base::MakeUnique<std::vector<PrefetchArchiveInfo>>(); + archives->push_back(archive); } return archives; @@ -58,23 +62,24 @@ return statement.Run(); } -std::vector<PrefetchArchiveInfo> GetArchivesAndUpdateToImportingStateSync( - sql::Connection* db) { +std::unique_ptr<std::vector<PrefetchArchiveInfo>> +GetArchivesAndUpdateToImportingStateSync(sql::Connection* db) { sql::Transaction transaction(db); if (!transaction.Begin()) - return std::vector<PrefetchArchiveInfo>(); + return nullptr; - std::vector<PrefetchArchiveInfo> archives = GetArchivesSync(db); - if (archives.empty()) - return std::vector<PrefetchArchiveInfo>(); + std::unique_ptr<std::vector<PrefetchArchiveInfo>> archives = + GetArchivesSync(db); + if (!archives) + return nullptr; - for (const auto& archive : archives) { + for (const auto& archive : *archives) { if (!UpdateToImportingStateSync(archive.offline_id, db)) - return std::vector<PrefetchArchiveInfo>(); + return nullptr; } if (!transaction.Commit()) - return std::vector<PrefetchArchiveInfo>(); + return nullptr; return archives; } @@ -97,9 +102,11 @@ } void ImportArchivesTask::OnArchivesRetrieved( - std::vector<PrefetchArchiveInfo> archives) { - for (const auto& archive : archives) - prefetch_importer_->ImportArchive(archive); + std::unique_ptr<std::vector<PrefetchArchiveInfo>> archives) { + if (archives) { + for (const auto& archive : *archives) + prefetch_importer_->ImportArchive(archive); + } TaskComplete(); }
diff --git a/components/offline_pages/core/prefetch/import_archives_task.h b/components/offline_pages/core/prefetch/import_archives_task.h index c661297e..96496219 100644 --- a/components/offline_pages/core/prefetch/import_archives_task.h +++ b/components/offline_pages/core/prefetch/import_archives_task.h
@@ -26,7 +26,8 @@ void Run() override; private: - void OnArchivesRetrieved(std::vector<PrefetchArchiveInfo> archive); + void OnArchivesRetrieved( + std::unique_ptr<std::vector<PrefetchArchiveInfo>> archive); PrefetchStore* prefetch_store_; // Outlives this class. PrefetchImporter* prefetch_importer_; // Outlives this class.
diff --git a/components/offline_pages/core/prefetch/import_completed_task.cc b/components/offline_pages/core/prefetch/import_completed_task.cc index cd806d00..1622b67 100644 --- a/components/offline_pages/core/prefetch/import_completed_task.cc +++ b/components/offline_pages/core/prefetch/import_completed_task.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" +#include "components/offline_pages/core/prefetch/prefetch_dispatcher.h" #include "components/offline_pages/core/prefetch/prefetch_types.h" #include "components/offline_pages/core/prefetch/store/prefetch_store.h" #include "sql/connection.h" @@ -37,10 +38,13 @@ } // namespace -ImportCompletedTask::ImportCompletedTask(PrefetchStore* prefetch_store, - int64_t offline_id, - bool success) - : prefetch_store_(prefetch_store), +ImportCompletedTask::ImportCompletedTask( + PrefetchDispatcher* prefetch_dispatcher, + PrefetchStore* prefetch_store, + int64_t offline_id, + bool success) + : prefetch_dispatcher_(prefetch_dispatcher), + prefetch_store_(prefetch_store), offline_id_(offline_id), success_(success), weak_ptr_factory_(this) {} @@ -57,11 +61,8 @@ void ImportCompletedTask::OnStateUpdatedToFinished(bool success) { // No further action can be done if the database fails to be updated. The // cleanup task should eventually kick in to clean this up. - if (success) { - // TODO(jianli): Calls SchedulePipelineProcessing to process the finished - // item. - NOTIMPLEMENTED(); - } + if (success) + prefetch_dispatcher_->SchedulePipelineProcessing(); TaskComplete(); }
diff --git a/components/offline_pages/core/prefetch/import_completed_task.h b/components/offline_pages/core/prefetch/import_completed_task.h index fc4e427..a2ff66f7 100644 --- a/components/offline_pages/core/prefetch/import_completed_task.h +++ b/components/offline_pages/core/prefetch/import_completed_task.h
@@ -11,12 +11,14 @@ #include "components/offline_pages/core/task.h" namespace offline_pages { +class PrefetchDispatcher; class PrefetchStore; // Task that responses to the completed import. class ImportCompletedTask : public Task { public: - ImportCompletedTask(PrefetchStore* prefetch_store, + ImportCompletedTask(PrefetchDispatcher* prefetch_dispatcher, + PrefetchStore* prefetch_store, int64_t offline_id, bool success); ~ImportCompletedTask() override; @@ -26,6 +28,7 @@ private: void OnStateUpdatedToFinished(bool success); + PrefetchDispatcher* prefetch_dispatcher_; // Outlives this class. PrefetchStore* prefetch_store_; // Outlives this class. int64_t offline_id_; bool success_;
diff --git a/components/offline_pages/core/prefetch/import_completed_task_unittest.cc b/components/offline_pages/core/prefetch/import_completed_task_unittest.cc index ff3220b0..ee77855 100644 --- a/components/offline_pages/core/prefetch/import_completed_task_unittest.cc +++ b/components/offline_pages/core/prefetch/import_completed_task_unittest.cc
@@ -17,6 +17,7 @@ #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/store/prefetch_store_utils.h" +#include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h" #include "sql/connection.h" #include "sql/statement.h" #include "testing/gtest/include/gtest/gtest.h" @@ -39,11 +40,13 @@ void PumpLoop(); PrefetchStore* store() { return store_test_util_.store(); } + TestPrefetchDispatcher* dispatcher() { return &dispatcher_; } PrefetchStoreTestUtil* store_util() { return &store_test_util_; } private: scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; + TestPrefetchDispatcher dispatcher_; PrefetchStoreTestUtil store_test_util_; }; @@ -80,7 +83,7 @@ } TEST_F(ImportCompletedTaskTest, ImportSuccess) { - ImportCompletedTask task(store(), kTestOfflineID, true); + ImportCompletedTask task(dispatcher(), store(), kTestOfflineID, true); task.Run(); PumpLoop(); @@ -91,7 +94,7 @@ } TEST_F(ImportCompletedTaskTest, ImportError) { - ImportCompletedTask task(store(), kTestOfflineID, false); + ImportCompletedTask task(dispatcher(), store(), kTestOfflineID, false); task.Run(); PumpLoop(); @@ -102,7 +105,7 @@ } TEST_F(ImportCompletedTaskTest, NoUpdateOnMismatchedImportSuccess) { - ImportCompletedTask task(store(), kTestOfflineID2, true); + ImportCompletedTask task(dispatcher(), store(), kTestOfflineID2, true); task.Run(); PumpLoop(); @@ -117,7 +120,7 @@ } TEST_F(ImportCompletedTaskTest, NoUpdateOnMismatchedImportError) { - ImportCompletedTask task(store(), kTestOfflineID2, false); + ImportCompletedTask task(dispatcher(), store(), kTestOfflineID2, false); task.Run(); PumpLoop();
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc index 09b2698..f1f5aac 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -188,9 +188,9 @@ "Download size: " + std::to_string(download_result.file_size)); } - PrefetchStore* prefetch_store = service_->GetPrefetchStore(); - task_queue_.AddTask( - base::MakeUnique<DownloadCompletedTask>(prefetch_store, download_result)); + task_queue_.AddTask(base::MakeUnique<DownloadCompletedTask>( + service_->GetPrefetchDispatcher(), service_->GetPrefetchStore(), + download_result)); } void PrefetchDispatcherImpl::ImportCompleted(int64_t offline_id, bool success) { @@ -201,9 +201,9 @@ std::to_string(offline_id) + (success ? "succeeded" : "failed")); - PrefetchStore* prefetch_store = service_->GetPrefetchStore(); task_queue_.AddTask(base::MakeUnique<ImportCompletedTask>( - prefetch_store, offline_id, success)); + service_->GetPrefetchDispatcher(), service_->GetPrefetchStore(), + offline_id, success)); } void PrefetchDispatcherImpl::LogRequestResult(
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc index e2e09bd..9e5b266 100644 --- a/components/omnibox/browser/autocomplete_match.cc +++ b/components/omnibox/browser/autocomplete_match.cc
@@ -492,12 +492,12 @@ bool preserve_scheme, bool preserve_subdomain, bool preserve_after_host) { - auto format_types = url_formatter::kFormatUrlOmitAll; + auto format_types = url_formatter::kFormatUrlOmitDefaults; if (preserve_scheme) { format_types &= ~url_formatter::kFormatUrlOmitHTTP; } else if (base::FeatureList::IsEnabled( omnibox::kUIExperimentHideSuggestionUrlScheme)) { - format_types |= url_formatter::kFormatUrlExperimentalOmitHTTPS; + format_types |= url_formatter::kFormatUrlOmitHTTPS; } if (!preserve_subdomain &&
diff --git a/components/omnibox/browser/history_quick_provider.cc b/components/omnibox/browser/history_quick_provider.cc index a65f478..4859f054 100644 --- a/components/omnibox/browser/history_quick_provider.cc +++ b/components/omnibox/browser/history_quick_provider.cc
@@ -202,7 +202,7 @@ size_t inline_autocomplete_offset = URLPrefix::GetInlineAutocompleteOffset( autocomplete_input_.text(), FixupUserInput(autocomplete_input_).second, false, base::UTF8ToUTF16(info.url().spec())); - auto fill_into_edit_format_types = url_formatter::kFormatUrlOmitAll; + auto fill_into_edit_format_types = url_formatter::kFormatUrlOmitDefaults; if (history_match.match_in_scheme) fill_into_edit_format_types &= ~url_formatter::kFormatUrlOmitHTTP; match.fill_into_edit =
diff --git a/components/omnibox/browser/history_url_provider.cc b/components/omnibox/browser/history_url_provider.cc index 7ea13a7..d183a30 100644 --- a/components/omnibox/browser/history_url_provider.cc +++ b/components/omnibox/browser/history_url_provider.cc
@@ -573,7 +573,8 @@ DCHECK(!(trim_http && AutocompleteInput::HasHTTPScheme(input.text()))); base::string16 display_string(url_formatter::FormatUrl( destination_url, - url_formatter::kFormatUrlOmitAll & ~url_formatter::kFormatUrlOmitHTTP, + url_formatter::kFormatUrlOmitDefaults & + ~url_formatter::kFormatUrlOmitHTTP, net::UnescapeRule::SPACES, nullptr, nullptr, nullptr)); const size_t offset = trim_http ? TrimHttpPrefix(&display_string) : 0; match.fill_into_edit = @@ -1169,7 +1170,7 @@ size_t inline_autocomplete_offset = history_match.input_location + params.input.text().length(); - auto fill_into_edit_format_types = url_formatter::kFormatUrlOmitAll; + auto fill_into_edit_format_types = url_formatter::kFormatUrlOmitDefaults; if (!params.trim_http || history_match.match_in_scheme) fill_into_edit_format_types &= ~url_formatter::kFormatUrlOmitHTTP; match.fill_into_edit =
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc index 9a1e5253..24da9c36 100644 --- a/components/omnibox/browser/search_provider.cc +++ b/components/omnibox/browser/search_provider.cc
@@ -1455,7 +1455,7 @@ bool trim_http = !AutocompleteInput::HasHTTPScheme(input) && (!prefix || (match_start != 0)); const url_formatter::FormatUrlTypes format_types = - url_formatter::kFormatUrlOmitAll & + url_formatter::kFormatUrlOmitDefaults & ~(trim_http ? 0 : url_formatter::kFormatUrlOmitHTTP); size_t inline_autocomplete_offset = (prefix == NULL) ?
diff --git a/components/omnibox/browser/search_suggestion_parser.cc b/components/omnibox/browser/search_suggestion_parser.cc index 7f73f13..21e18f2 100644 --- a/components/omnibox/browser/search_suggestion_parser.cc +++ b/components/omnibox/browser/search_suggestion_parser.cc
@@ -245,7 +245,7 @@ formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning( url, url_formatter::FormatUrl(url, - url_formatter::kFormatUrlOmitAll & + url_formatter::kFormatUrlOmitDefaults & ~url_formatter::kFormatUrlOmitHTTP, net::UnescapeRule::SPACES, nullptr,
diff --git a/components/proximity_auth/screenlock_state.h b/components/proximity_auth/screenlock_state.h index b7e76000..8bee198 100644 --- a/components/proximity_auth/screenlock_state.h +++ b/components/proximity_auth/screenlock_state.h
@@ -44,8 +44,6 @@ // The user must reauthenticate using their password because a sufficient time // has elapsed since their last password entry. PASSWORD_REAUTH, - // A password is required on the login screen. - PASSWORD_REQUIRED_FOR_LOGIN, }; } // namespace proximity_auth
diff --git a/components/proximity_auth/switches.cc b/components/proximity_auth/switches.cc index 668fcc5b..9d08bcc0 100644 --- a/components/proximity_auth/switches.cc +++ b/components/proximity_auth/switches.cc
@@ -11,10 +11,6 @@ const char kDisableBluetoothLowEnergyDiscovery[] = "disable-proximity-auth-bluetooth-low-energy-discovery"; -// Enables the use of EasyUnlock to log into the Chromebook. -extern const char kEnableChromeOSLogin[] = - "enable-proximity-auth-chromeos-login"; - // Enables forcing the user to reauth with their password after X hours (e.g. // 20) without password entry. const char kEnableForcePasswordReauth[] = "force-password-reauth";
diff --git a/components/proximity_auth/switches.h b/components/proximity_auth/switches.h index 55854515..70ed565 100644 --- a/components/proximity_auth/switches.h +++ b/components/proximity_auth/switches.h
@@ -9,7 +9,6 @@ namespace switches { extern const char kDisableBluetoothLowEnergyDiscovery[]; -extern const char kEnableChromeOSLogin[]; extern const char kEnableForcePasswordReauth[]; extern const char kForceLoadEasyUnlockAppInTests[];
diff --git a/components/security_state/core/security_state.cc b/components/security_state/core/security_state.cc index 5475e7f3..2dcd0d3 100644 --- a/components/security_state/core/security_state.cc +++ b/components/security_state/core/security_state.cc
@@ -221,7 +221,10 @@ bool used_policy_installed_certificate, const IsOriginSecureCallback& is_origin_secure_callback, SecurityInfo* security_info) { - MarkHttpStatus mark_http_as; + // |mark_http_as| will be updated to the value specified by the + // field trial or command-line in |GetSecurityLevelForNonSecureFieldTrial| + // if that function is reached. + MarkHttpStatus mark_http_as = HTTP_SHOW_WARNING_ON_SENSITIVE_FIELDS; if (!visible_security_state.connection_info_initialized) { *security_info = SecurityInfo();
diff --git a/components/toolbar/toolbar_model_impl.cc b/components/toolbar/toolbar_model_impl.cc index 6e275ef..13b7676 100644 --- a/components/toolbar/toolbar_model_impl.cc +++ b/components/toolbar/toolbar_model_impl.cc
@@ -45,7 +45,7 @@ const base::string16 formatted_text = delegate_->FormattedStringWithEquivalentMeaning( url, url_formatter::FormatUrl( - url, url_formatter::kFormatUrlOmitAll, + url, url_formatter::kFormatUrlOmitDefaults, net::UnescapeRule::NORMAL, nullptr, prefix_end, nullptr)); if (formatted_text.length() <= max_url_display_chars_) return formatted_text;
diff --git a/components/url_formatter/elide_url.cc b/components/url_formatter/elide_url.cc index 984de31..87f8852 100644 --- a/components/url_formatter/elide_url.cc +++ b/components/url_formatter/elide_url.cc
@@ -154,8 +154,8 @@ // Get a formatted string and corresponding parsing of the url. url::Parsed parsed; const base::string16 url_string = url_formatter::FormatUrl( - url, url_formatter::kFormatUrlOmitAll, - net::UnescapeRule::SPACES, &parsed, nullptr, nullptr); + url, url_formatter::kFormatUrlOmitDefaults, net::UnescapeRule::SPACES, + &parsed, nullptr, nullptr); if (available_pixel_width <= 0) return url_string;
diff --git a/components/url_formatter/url_formatter.cc b/components/url_formatter/url_formatter.cc index 461bc79..abfb716f 100644 --- a/components/url_formatter/url_formatter.cc +++ b/components/url_formatter/url_formatter.cc
@@ -405,12 +405,13 @@ const FormatUrlType kFormatUrlOmitUsernamePassword = 1 << 0; const FormatUrlType kFormatUrlOmitHTTP = 1 << 1; const FormatUrlType kFormatUrlOmitTrailingSlashOnBareHostname = 1 << 2; -const FormatUrlType kFormatUrlOmitAll = +const FormatUrlType kFormatUrlOmitHTTPS = 1 << 3; +const FormatUrlType kFormatUrlExperimentalElideAfterHost = 1 << 4; +const FormatUrlType kFormatUrlExperimentalOmitTrivialSubdomains = 1 << 5; + +const FormatUrlType kFormatUrlOmitDefaults = kFormatUrlOmitUsernamePassword | kFormatUrlOmitHTTP | kFormatUrlOmitTrailingSlashOnBareHostname; -const FormatUrlType kFormatUrlExperimentalElideAfterHost = 1 << 3; -const FormatUrlType kFormatUrlExperimentalOmitHTTPS = 1 << 4; -const FormatUrlType kFormatUrlExperimentalOmitTrivialSubdomains = 1 << 5; base::string16 FormatUrl(const GURL& url, FormatUrlTypes format_types, @@ -604,7 +605,7 @@ !base::StartsWith(url.host(), kFTP, base::CompareCase::SENSITIVE) && (((format_types & kFormatUrlOmitHTTP) && url.SchemeIs(url::kHttpScheme)) || - ((format_types & kFormatUrlExperimentalOmitHTTPS) && + ((format_types & kFormatUrlOmitHTTPS) && url.SchemeIs(url::kHttpsScheme))); // If we need to strip out schemes do it after the fact.
diff --git a/components/url_formatter/url_formatter.h b/components/url_formatter/url_formatter.h index a44f60eeb..32e095e 100644 --- a/components/url_formatter/url_formatter.h +++ b/components/url_formatter/url_formatter.h
@@ -51,21 +51,21 @@ // meaningful for non-file "standard" URLs. extern const FormatUrlType kFormatUrlOmitTrailingSlashOnBareHostname; -// Convenience for omitting all unecessary types. Does not include experimental -// flags below. -extern const FormatUrlType kFormatUrlOmitAll; +// If the scheme is 'https://', it's removed. Not in kFormatUrlOmitDefaults. +extern const FormatUrlType kFormatUrlOmitHTTPS; // Replaces the path, query, and ref with an ellipsis. Experimental and not in -// kFormatUrlOmitAll. +// kFormatUrlOmitDefaults. extern const FormatUrlType kFormatUrlExperimentalElideAfterHost; -// If the scheme is 'https://', it's removed. Experimental and not in -// kFormatUrlOmitAll. -extern const FormatUrlType kFormatUrlExperimentalOmitHTTPS; - -// Omits some trivially informative subdomains such as "www" or "m". +// Omits some trivially informative subdomains such as "www" or "m". Not in +// kFormatUrlOmitDefaults. extern const FormatUrlType kFormatUrlExperimentalOmitTrivialSubdomains; +// Convenience for omitting all unecessary types. Does not include HTTPS scheme +// removal, or experimental flags. +extern const FormatUrlType kFormatUrlOmitDefaults; + // Creates a string representation of |url|. The IDN host name is turned to // Unicode if the Unicode representation is deemed safe. |format_type| is a // bitmask of FormatUrlTypes, see it for details. |unescape_rules| defines how @@ -125,11 +125,12 @@ base::OffsetAdjuster::Adjustments* adjustments); // This is a convenience function for FormatUrl() with -// format_types = kFormatUrlOmitAll and unescape = SPACES. This is the typical -// set of flags for "URLs to display to the user". You should be cautious about -// using this for URLs which will be parsed or sent to other applications. +// format_types = kFormatUrlOmitDefaults and unescape = SPACES. This is the +// typical set of flags for "URLs to display to the user". You should be +// cautious about using this for URLs which will be parsed or sent to other +// applications. inline base::string16 FormatUrl(const GURL& url) { - return FormatUrl(url, kFormatUrlOmitAll, net::UnescapeRule::SPACES, + return FormatUrl(url, kFormatUrlOmitDefaults, net::UnescapeRule::SPACES, nullptr, nullptr, nullptr); }
diff --git a/components/url_formatter/url_formatter_unittest.cc b/components/url_formatter/url_formatter_unittest.cc index 49f03f1..6cc9b19 100644 --- a/components/url_formatter/url_formatter_unittest.cc +++ b/components/url_formatter/url_formatter_unittest.cc
@@ -828,11 +828,12 @@ {"omit http", "http://www.google.com/", kFormatUrlOmitHTTP, net::UnescapeRule::NORMAL, L"www.google.com/", 0}, - {"omit http on bare scheme", "http://", kFormatUrlOmitAll, + {"omit http on bare scheme", "http://", kFormatUrlOmitDefaults, net::UnescapeRule::NORMAL, L"", 0}, {"omit http with user name", "http://user@example.com/foo", - kFormatUrlOmitAll, net::UnescapeRule::NORMAL, L"example.com/foo", 0}, + kFormatUrlOmitDefaults, net::UnescapeRule::NORMAL, L"example.com/foo", + 0}, {"omit http with https", "https://www.google.com/", kFormatUrlOmitHTTP, net::UnescapeRule::NORMAL, L"https://www.google.com/", 8}, @@ -873,66 +874,66 @@ // view-source should omit http and trailing slash where non-view-source // would. - {"view-source omit http", "view-source:http://a.b/c", kFormatUrlOmitAll, - net::UnescapeRule::NORMAL, L"view-source:a.b/c", 12}, + {"view-source omit http", "view-source:http://a.b/c", + kFormatUrlOmitDefaults, net::UnescapeRule::NORMAL, L"view-source:a.b/c", + 12}, {"view-source omit http starts with ftp.", "view-source:http://ftp.b/c", - kFormatUrlOmitAll, net::UnescapeRule::NORMAL, + kFormatUrlOmitDefaults, net::UnescapeRule::NORMAL, L"view-source:http://ftp.b/c", 19}, {"view-source omit slash when it's the entire path", - "view-source:http://a.b/", kFormatUrlOmitAll, net::UnescapeRule::NORMAL, - L"view-source:a.b", 12}, + "view-source:http://a.b/", kFormatUrlOmitDefaults, + net::UnescapeRule::NORMAL, L"view-source:a.b", 12}, // -------- elide after host -------- {"elide after host but still strip trailing slashes", "http://google.com/", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com", 0}, {"elide after host in simple filename-only case", "http://google.com/foo", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, {"elide after host in directory and file case", "http://google.com/ab/cd", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, {"elide after host with query only", "http://google.com/?foo=bar", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, {"elide after host with ref only", "http://google.com/#foobar", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, {"elide after host with path and query only", "http://google.com/foo?a=b", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, {"elide after host with path and ref only", "http://google.com/foo#c", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, {"elide after host with query and ref only", "http://google.com/?a=b#c", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, {"elide after host with path, query and ref", "http://google.com/foo?a=b#c", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, {"elide after host with repeated delimiters (sanity check)", "http://google.com////???####", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, net::UnescapeRule::NORMAL, L"google.com/\x2026\x0000", 0}, // -------- omit https -------- - {"omit https", "https://www.google.com/", kFormatUrlExperimentalOmitHTTPS, + {"omit https", "https://www.google.com/", kFormatUrlOmitHTTPS, net::UnescapeRule::NORMAL, L"www.google.com/", 0}, {"omit https but do not omit http", "http://www.google.com/", - kFormatUrlExperimentalOmitHTTPS, net::UnescapeRule::NORMAL, + kFormatUrlOmitHTTPS, net::UnescapeRule::NORMAL, L"http://www.google.com/", 7}, {"omit https, username, and password", "https://user:password@example.com/foo", - kFormatUrlOmitAll | kFormatUrlExperimentalOmitHTTPS, - net::UnescapeRule::NORMAL, L"example.com/foo", 0}, + kFormatUrlOmitDefaults | kFormatUrlOmitHTTPS, net::UnescapeRule::NORMAL, + L"example.com/foo", 0}, {"omit https, but preserve user name and password", - "https://user:password@example.com/foo", kFormatUrlExperimentalOmitHTTPS, + "https://user:password@example.com/foo", kFormatUrlOmitHTTPS, net::UnescapeRule::NORMAL, L"user:password@example.com/foo", 14}, {"omit https should not affect hosts starting with ftp.", - "https://ftp.google.com/", - kFormatUrlOmitHTTP | kFormatUrlExperimentalOmitHTTPS, + "https://ftp.google.com/", kFormatUrlOmitHTTP | kFormatUrlOmitHTTPS, net::UnescapeRule::NORMAL, L"https://ftp.google.com/", 8}, // -------- omit trivial subdomains -------- @@ -1324,36 +1325,41 @@ 0, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 0, kNpos, kNpos, kNpos, kNpos, 0, 1, 2, 3, 4, 5, 6, 7 }; - CheckAdjustedOffsets("http://user@foo.com/", kFormatUrlOmitAll, + CheckAdjustedOffsets("http://user@foo.com/", kFormatUrlOmitDefaults, net::UnescapeRule::NORMAL, omit_all_offsets); const size_t elide_after_host_offsets[] = { 0, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 0, 1, 2, 3, 4, 5, 6, 7, 8, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 9}; - CheckAdjustedOffsets("http://foo.com/abcdefg", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, - net::UnescapeRule::NORMAL, elide_after_host_offsets); - CheckAdjustedOffsets("http://foo.com/abc/def", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, - net::UnescapeRule::NORMAL, elide_after_host_offsets); - CheckAdjustedOffsets("http://foo.com/abc?a=b", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, - net::UnescapeRule::NORMAL, elide_after_host_offsets); - CheckAdjustedOffsets("http://foo.com/abc#def", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, - net::UnescapeRule::NORMAL, elide_after_host_offsets); - CheckAdjustedOffsets("http://foo.com/a?a=b#f", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, - net::UnescapeRule::NORMAL, elide_after_host_offsets); - CheckAdjustedOffsets("http://foo.com//??###", - kFormatUrlOmitAll | kFormatUrlExperimentalElideAfterHost, - net::UnescapeRule::NORMAL, elide_after_host_offsets); + CheckAdjustedOffsets( + "http://foo.com/abcdefg", + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, + net::UnescapeRule::NORMAL, elide_after_host_offsets); + CheckAdjustedOffsets( + "http://foo.com/abc/def", + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, + net::UnescapeRule::NORMAL, elide_after_host_offsets); + CheckAdjustedOffsets( + "http://foo.com/abc?a=b", + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, + net::UnescapeRule::NORMAL, elide_after_host_offsets); + CheckAdjustedOffsets( + "http://foo.com/abc#def", + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, + net::UnescapeRule::NORMAL, elide_after_host_offsets); + CheckAdjustedOffsets( + "http://foo.com/a?a=b#f", + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, + net::UnescapeRule::NORMAL, elide_after_host_offsets); + CheckAdjustedOffsets( + "http://foo.com//??###", + kFormatUrlOmitDefaults | kFormatUrlExperimentalElideAfterHost, + net::UnescapeRule::NORMAL, elide_after_host_offsets); const size_t omit_https_offsets[] = { 0, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; - CheckAdjustedOffsets("https://www.google.com/", - kFormatUrlExperimentalOmitHTTPS, + CheckAdjustedOffsets("https://www.google.com/", kFormatUrlOmitHTTPS, net::UnescapeRule::NORMAL, omit_https_offsets); const size_t omit_https_with_auth_offsets[] = { @@ -1361,7 +1367,7 @@ kNpos, kNpos, kNpos, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; CheckAdjustedOffsets("https://u:p@www.google.com/", - kFormatUrlOmitAll | kFormatUrlExperimentalOmitHTTPS, + kFormatUrlOmitDefaults | kFormatUrlOmitHTTPS, net::UnescapeRule::NORMAL, omit_https_with_auth_offsets); const size_t strip_trivial_subdomains_offsets_1[] = {
diff --git a/components/wallpaper/wallpaper_manager_base.h b/components/wallpaper/wallpaper_manager_base.h index 934b45a..ab761cc 100644 --- a/components/wallpaper/wallpaper_manager_base.h +++ b/components/wallpaper/wallpaper_manager_base.h
@@ -167,9 +167,6 @@ virtual ~Observer() {} // Notified when the wallpaper animation finishes. virtual void OnWallpaperAnimationFinished(const AccountId& account_id) {} - // Notified when the wallpaper is updated and the color calculation results - // change. - virtual void OnWallpaperColorsChanged() {} // Notified when the wallpaper is updated. virtual void OnUpdateWallpaperForTesting() {} // Notified when the wallpaper pending list is empty.
diff --git a/components/web_contents_delegate_android/web_contents_delegate_android.cc b/components/web_contents_delegate_android/web_contents_delegate_android.cc index df91a2a..326dbf6 100644 --- a/components/web_contents_delegate_android/web_contents_delegate_android.cc +++ b/components/web_contents_delegate_android/web_contents_delegate_android.cc
@@ -28,6 +28,7 @@ using base::android::AttachCurrentThread; using base::android::ConvertUTF8ToJavaString; using base::android::ConvertUTF16ToJavaString; +using base::android::JavaRef; using base::android::ScopedJavaLocalRef; using content::ColorChooser; using content::RenderWidgetHostView; @@ -302,8 +303,8 @@ void WebContentsDelegateAndroid::HandleKeyboardEvent( WebContents* source, const content::NativeWebKeyboardEvent& event) { - jobject key_event = event.os_event; - if (key_event) { + const JavaRef<jobject>& key_event = event.os_event; + if (!key_event.is_null()) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env); if (obj.is_null())
diff --git a/content/browser/appcache/appcache_subresource_url_factory.cc b/content/browser/appcache/appcache_subresource_url_factory.cc index ce746e15..3b61b9d1 100644 --- a/content/browser/appcache/appcache_subresource_url_factory.cc +++ b/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -23,13 +23,11 @@ // Implements the URLLoaderFactory mojom for AppCache requests. AppCacheSubresourceURLFactory::AppCacheSubresourceURLFactory( - mojom::URLLoaderFactoryRequest request, URLLoaderFactoryGetter* default_url_loader_factory_getter, base::WeakPtr<AppCacheHost> host) - : binding_(this, std::move(request)), - default_url_loader_factory_getter_(default_url_loader_factory_getter), + : default_url_loader_factory_getter_(default_url_loader_factory_getter), appcache_host_(host) { - binding_.set_connection_error_handler( + bindings_.set_connection_error_handler( base::Bind(&AppCacheSubresourceURLFactory::OnConnectionError, base::Unretained(this))); } @@ -37,17 +35,18 @@ AppCacheSubresourceURLFactory::~AppCacheSubresourceURLFactory() {} // static -AppCacheSubresourceURLFactory* -AppCacheSubresourceURLFactory::CreateURLLoaderFactory( +void AppCacheSubresourceURLFactory::CreateURLLoaderFactory( URLLoaderFactoryGetter* default_url_loader_factory_getter, base::WeakPtr<AppCacheHost> host, mojom::URLLoaderFactoryPtr* loader_factory) { mojom::URLLoaderFactoryRequest request = mojo::MakeRequest(loader_factory); - // This instance will get deleted when the client drops the connection. + // This instance is effectively reference counted by the number of pipes open + // to it and will get deleted when all clients drop their connections. // Please see OnConnectionError() for details. - return new AppCacheSubresourceURLFactory( - std::move(request), default_url_loader_factory_getter, host); + auto* impl = new AppCacheSubresourceURLFactory( + default_url_loader_factory_getter, host); + impl->Clone(std::move(request)); } void AppCacheSubresourceURLFactory::CreateLoaderAndStart( @@ -98,15 +97,14 @@ } } -void AppCacheSubresourceURLFactory::SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) { - NOTREACHED(); +void AppCacheSubresourceURLFactory::Clone( + mojom::URLLoaderFactoryRequest request) { + bindings_.AddBinding(this, std::move(request)); } void AppCacheSubresourceURLFactory::OnConnectionError() { - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); + if (bindings_.empty()) + delete this; } void AppCacheSubresourceURLFactory::NotifyError( @@ -117,4 +115,4 @@ client->OnComplete(request_result); } -} // namespace content \ No newline at end of file +} // namespace content
diff --git a/content/browser/appcache/appcache_subresource_url_factory.h b/content/browser/appcache/appcache_subresource_url_factory.h index 2b7a46a4..712cc375 100644 --- a/content/browser/appcache/appcache_subresource_url_factory.h +++ b/content/browser/appcache/appcache_subresource_url_factory.h
@@ -9,7 +9,7 @@ #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" #include "content/public/common/url_loader_factory.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/binding_set.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/gurl.h" @@ -32,9 +32,7 @@ // 2. The |host| parameter contains the appcache host instance. This is used // to create the AppCacheRequestHandler instances for handling subresource // requests. - // Returns the AppCacheSubresourceURLFactory instance. The URLLoaderFactoryPtr - // is returned in the |loader_factory| parameter. - static AppCacheSubresourceURLFactory* CreateURLLoaderFactory( + static void CreateURLLoaderFactory( URLLoaderFactoryGetter* factory_getter, base::WeakPtr<AppCacheHost> host, mojom::URLLoaderFactoryPtr* loader_factory); @@ -48,16 +46,12 @@ mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override; - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override; + void Clone(mojom::URLLoaderFactoryRequest request) override; private: friend class AppCacheNetworkServiceBrowserTest; - AppCacheSubresourceURLFactory(mojom::URLLoaderFactoryRequest request, - URLLoaderFactoryGetter* factory_getter, + AppCacheSubresourceURLFactory(URLLoaderFactoryGetter* factory_getter, base::WeakPtr<AppCacheHost> host); void OnConnectionError(); @@ -66,8 +60,8 @@ // actual error. void NotifyError(mojom::URLLoaderClientPtr client, int error_code); - // Mojo binding. - mojo::Binding<mojom::URLLoaderFactory> binding_; + // Mojo bindings. + mojo::BindingSet<mojom::URLLoaderFactory> bindings_; // Used to retrieve the network service factory to pass unhandled requests to // the network service.
diff --git a/content/browser/blob_storage/blob_url_loader_factory.cc b/content/browser/blob_storage/blob_url_loader_factory.cc index 12350f1..a9406a33 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.cc +++ b/content/browser/blob_storage/blob_url_loader_factory.cc
@@ -415,11 +415,8 @@ std::move(blob_handle), file_system_context_.get()); } -void BlobURLLoaderFactory::SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) { - NOTREACHED(); +void BlobURLLoaderFactory::Clone(mojom::URLLoaderFactoryRequest request) { + loader_factory_bindings_.AddBinding(this, std::move(request)); } } // namespace content
diff --git a/content/browser/blob_storage/blob_url_loader_factory.h b/content/browser/blob_storage/blob_url_loader_factory.h index a8ae752b..11a2af8f 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.h +++ b/content/browser/blob_storage/blob_url_loader_factory.h
@@ -59,10 +59,7 @@ mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override; - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override; + void Clone(mojom::URLLoaderFactoryRequest request) override; private: friend class base::DeleteHelper<BlobURLLoaderFactory>;
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc index ceb36a8..dc2e8f71 100644 --- a/content/browser/devtools/protocol/input_handler.cc +++ b/content/browser/devtools/protocol/input_handler.cc
@@ -396,11 +396,7 @@ input_queued_ = false; pending_mouse_callbacks_.push_back(std::move(callback)); host_->GetRenderWidgetHost()->ForwardMouseEvent(event); - // MouseUp/Down events don't create a round-trip to the renderer, so there's - // no point in blocking the response until an ack is received. Only wait for - // an ack if we're synthesizing a MouseMove event, which does make a - // round-trip to the renderer. - if (event_type != blink::WebInputEvent::kMouseMove || !input_queued_) { + if (!input_queued_) { pending_mouse_callbacks_.back()->sendSuccess(); pending_mouse_callbacks_.pop_back(); }
diff --git a/content/browser/devtools/protocol/schema_handler.cc b/content/browser/devtools/protocol/schema_handler.cc index 30b45e3..590f534 100644 --- a/content/browser/devtools/protocol/schema_handler.cc +++ b/content/browser/devtools/protocol/schema_handler.cc
@@ -30,7 +30,8 @@ "ServiceWorker", "Input", "LayerTree", "DeviceOrientation", "Tracing", "Animation", "Accessibility", "Storage", "Log", "Runtime", "Debugger", "Profiler", - "HeapProfiler", "Schema", "Target", "Overlay"}; + "HeapProfiler", "Schema", "Target", "Overlay", + "Performance"}; *domains = protocol::Array<Schema::Domain>::create(); for (size_t i = 0; i < arraysize(kDomains); ++i) { (*domains)->addItem(Schema::Domain::Create()
diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc index a57a3819..e37a480 100644 --- a/content/browser/download/download_request_core.cc +++ b/content/browser/download/download_request_core.cc
@@ -34,15 +34,11 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/resource_context.h" #include "content/public/browser/web_contents.h" -#include "net/base/elements_upload_data_stream.h" #include "net/base/io_buffer.h" -#include "net/base/load_flags.h" #include "net/base/net_errors.h" -#include "net/base/upload_bytes_element_reader.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" -#include "net/url_request/url_request_context.h" #include "services/device/public/interfaces/constants.mojom.h" #include "services/device/public/interfaces/wake_lock_provider.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -115,74 +111,15 @@ const int DownloadRequestCore::kDownloadByteStreamSize = 100 * 1024; // static -std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread( - uint32_t download_id, - DownloadUrlParameters* params) { +std::unique_ptr<net::URLRequest> +DownloadRequestCore::CreateRequestOnIOThread(uint32_t download_id, + DownloadUrlParameters* params) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(download_id == DownloadItem::kInvalidId || !params->content_initiated()) << "Content initiated downloads shouldn't specify a download ID"; - DCHECK(params->offset() >= 0); - // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and - // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so - // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. - std::unique_ptr<net::URLRequest> request( - params->url_request_context_getter() - ->GetURLRequestContext() - ->CreateRequest(params->url(), net::DEFAULT_PRIORITY, nullptr, - params->GetNetworkTrafficAnnotation())); - request->set_method(params->method()); - - if (!params->post_body().empty()) { - const std::string& body = params->post_body(); - std::unique_ptr<net::UploadElementReader> reader( - net::UploadOwnedBytesElementReader::CreateWithString(body)); - request->set_upload( - net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0)); - } - - if (params->post_id() >= 0) { - // The POST in this case does not have an actual body, and only works - // when retrieving data from cache. This is done because we don't want - // to do a re-POST without user consent, and currently don't have a good - // plan on how to display the UI for that. - DCHECK(params->prefer_cache()); - DCHECK_EQ("POST", params->method()); - std::vector<std::unique_ptr<net::UploadElementReader>> element_readers; - request->set_upload(base::MakeUnique<net::ElementsUploadDataStream>( - std::move(element_readers), params->post_id())); - } - - int load_flags = request->load_flags(); - if (params->prefer_cache()) { - // If there is upload data attached, only retrieve from cache because there - // is no current mechanism to prompt the user for their consent for a - // re-post. For GETs, try to retrieve data from the cache and skip - // validating the entry if present. - if (request->get_upload()) - load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION; - else - load_flags |= net::LOAD_SKIP_CACHE_VALIDATION; - } else { - load_flags |= net::LOAD_DISABLE_CACHE; - } - request->SetLoadFlags(load_flags); - - // Add partial requests headers. - AddPartialRequestHeaders(request.get(), params); - - // Downloads are treated as top level navigations. Hence the first-party - // origin for cookies is always based on the target URL and is updated on - // redirects. - request->set_site_for_cookies(params->url()); - request->set_first_party_url_policy( - net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); - request->set_initiator(params->initiator()); - - for (const auto& header : params->request_headers()) - request->SetExtraRequestHeaderByName(header.first, header.second, - false /*overwrite*/); + std::unique_ptr<net::URLRequest> request = CreateURLRequestOnIOThread(params); DownloadRequestData::Attach(request.get(), params, download_id); return request; @@ -626,63 +563,4 @@ return DOWNLOAD_INTERRUPT_REASON_NONE; } -// static -void DownloadRequestCore::AddPartialRequestHeaders( - net::URLRequest* request, - DownloadUrlParameters* params) { - if (params->offset() == 0 && - params->length() == DownloadSaveInfo::kLengthFullContent) - return; - - bool has_last_modified = !params->last_modified().empty(); - bool has_etag = !params->etag().empty(); - - // Strong validator(i.e. etag or last modified) is required in range requests - // for download resumption and parallel download. - DCHECK(has_etag || has_last_modified); - if (!has_etag && !has_last_modified) { - DVLOG(1) << "Creating partial request without strong validators."; - return; - } - - // Add "Range" header. - std::string range_header = - (params->length() == DownloadSaveInfo::kLengthFullContent) - ? base::StringPrintf("bytes=%" PRId64 "-", params->offset()) - : base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(), - params->offset() + params->length() - 1); - request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kRange, - range_header, true); - - // Add "If-Range" headers. - if (params->use_if_range()) { - // In accordance with RFC 7233 Section 3.2, use If-Range to specify that - // the server return the entire entity if the validator doesn't match. - // Last-Modified can be used in the absence of ETag as a validator if the - // response headers satisfied the HttpUtil::HasStrongValidators() - // predicate. - // - // This function assumes that HasStrongValidators() was true and that the - // ETag and Last-Modified header values supplied are valid. - request->SetExtraRequestHeaderByName( - net::HttpRequestHeaders::kIfRange, - has_etag ? params->etag() : params->last_modified(), true); - return; - } - - // Add "If-Match"/"If-Unmodified-Since" headers. - if (has_etag) { - request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kIfMatch, - params->etag(), true); - } - // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for - // old servers that didn't implement "If-Match" and must be ignored when - // "If-Match" presents. - if (has_last_modified) { - request->SetExtraRequestHeaderByName( - net::HttpRequestHeaders::kIfUnmodifiedSince, params->last_modified(), - true); - } -} - } // namespace content
diff --git a/content/browser/download/download_request_core.h b/content/browser/download/download_request_core.h index 85208c6..93c4315a 100644 --- a/content/browser/download/download_request_core.h +++ b/content/browser/download/download_request_core.h
@@ -119,9 +119,6 @@ const net::HttpResponseHeaders& http_headers, DownloadSaveInfo* save_info); - static void AddPartialRequestHeaders(net::URLRequest* request, - DownloadUrlParameters* params); - std::unique_ptr<DownloadCreateInfo> CreateDownloadCreateInfo( DownloadInterruptReason result);
diff --git a/content/browser/download/download_utils.cc b/content/browser/download/download_utils.cc index b36171f2..856a531 100644 --- a/content/browser/download/download_utils.cc +++ b/content/browser/download/download_utils.cc
@@ -4,11 +4,110 @@ #include "content/browser/download/download_utils.h" +#include "base/format_macros.h" +#include "base/memory/ptr_util.h" +#include "base/strings/stringprintf.h" #include "content/browser/download/download_interrupt_reasons_impl.h" #include "content/browser/download/download_stats.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_url_parameters.h" +#include "content/public/common/resource_request.h" +#include "net/base/elements_upload_data_stream.h" +#include "net/base/load_flags.h" +#include "net/base/upload_bytes_element_reader.h" +#include "net/http/http_request_headers.h" +#include "net/url_request/url_request_context.h" namespace content { +namespace { + +void AppendExtraHeaders(net::HttpRequestHeaders* headers, + DownloadUrlParameters* params) { + for (const auto& header : params->request_headers()) + headers->SetHeaderIfMissing(header.first, header.second); +} + +int GetLoadFlags(DownloadUrlParameters* params, bool has_upload_data) { + int load_flags = 0; + if (params->prefer_cache()) { + // If there is upload data attached, only retrieve from cache because there + // is no current mechanism to prompt the user for their consent for a + // re-post. For GETs, try to retrieve data from the cache and skip + // validating the entry if present. + if (has_upload_data) + load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION; + else + load_flags |= net::LOAD_SKIP_CACHE_VALIDATION; + } else { + load_flags |= net::LOAD_DISABLE_CACHE; + } + return load_flags; +} + +std::unique_ptr<net::HttpRequestHeaders> GetAdditionalRequestHeaders( + DownloadUrlParameters* params) { + auto headers = base::MakeUnique<net::HttpRequestHeaders>(); + if (params->offset() == 0 && + params->length() == DownloadSaveInfo::kLengthFullContent) { + AppendExtraHeaders(headers.get(), params); + return headers; + } + + bool has_last_modified = !params->last_modified().empty(); + bool has_etag = !params->etag().empty(); + + // Strong validator(i.e. etag or last modified) is required in range requests + // for download resumption and parallel download. + DCHECK(has_etag || has_last_modified); + if (!has_etag && !has_last_modified) { + DVLOG(1) << "Creating partial request without strong validators."; + AppendExtraHeaders(headers.get(), params); + return headers; + } + + // Add "Range" header. + std::string range_header = + (params->length() == DownloadSaveInfo::kLengthFullContent) + ? base::StringPrintf("bytes=%" PRId64 "-", params->offset()) + : base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(), + params->offset() + params->length() - 1); + headers->SetHeader(net::HttpRequestHeaders::kRange, range_header); + + // Add "If-Range" headers. + if (params->use_if_range()) { + // In accordance with RFC 7233 Section 3.2, use If-Range to specify that + // the server return the entire entity if the validator doesn't match. + // Last-Modified can be used in the absence of ETag as a validator if the + // response headers satisfied the HttpUtil::HasStrongValidators() + // predicate. + // + // This function assumes that HasStrongValidators() was true and that the + // ETag and Last-Modified header values supplied are valid. + headers->SetHeader(net::HttpRequestHeaders::kIfRange, + has_etag ? params->etag() : params->last_modified()); + AppendExtraHeaders(headers.get(), params); + return headers; + } + + // Add "If-Match"/"If-Unmodified-Since" headers. + if (has_etag) + headers->SetHeader(net::HttpRequestHeaders::kIfMatch, params->etag()); + + // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for + // old servers that didn't implement "If-Match" and must be ignored when + // "If-Match" presents. + if (has_last_modified) { + headers->SetHeader(net::HttpRequestHeaders::kIfUnmodifiedSince, + params->last_modified()); + } + + AppendExtraHeaders(headers.get(), params); + return headers; +} + +} // namespace + DownloadInterruptReason HandleRequestCompletionStatus( net::Error error_code, bool has_strong_validators, net::CertStatus cert_status, DownloadInterruptReason abort_reason) { @@ -53,4 +152,103 @@ error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK); } +std::unique_ptr<ResourceRequest> CreateResourceRequest( + DownloadUrlParameters* params) { + DCHECK(params->offset() >= 0); + + std::unique_ptr<ResourceRequest> request(new ResourceRequest); + request->method = params->method(); + request->url = params->url(); + request->request_initiator = params->initiator(); + request->do_not_prompt_for_login = params->do_not_prompt_for_login(); + request->site_for_cookies = params->url(); + request->referrer = params->referrer().url; + request->referrer_policy = params->referrer().policy; + request->download_to_file = true; + + bool has_upload_data = false; + if (!params->post_body().empty()) { + request->request_body = ResourceRequestBody::CreateFromBytes( + params->post_body().data(), params->post_body().size()); + has_upload_data = true; + } + + if (params->post_id() >= 0) { + // The POST in this case does not have an actual body, and only works + // when retrieving data from cache. This is done because we don't want + // to do a re-POST without user consent, and currently don't have a good + // plan on how to display the UI for that. + DCHECK(params->prefer_cache()); + DCHECK_EQ("POST", params->method()); + request->request_body = new ResourceRequestBody(); + request->request_body->set_identifier(params->post_id()); + has_upload_data = true; + } + + request->load_flags = GetLoadFlags(params, has_upload_data); + + // Add additional request headers. + std::unique_ptr<net::HttpRequestHeaders> headers = + GetAdditionalRequestHeaders(params); + if (!headers->IsEmpty()) + request->headers = headers->ToString(); + + return request; +} + +std::unique_ptr<net::URLRequest> +CreateURLRequestOnIOThread(DownloadUrlParameters* params) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(params->offset() >= 0); + + // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and + // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so + // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. + std::unique_ptr<net::URLRequest> request( + params->url_request_context_getter() + ->GetURLRequestContext() + ->CreateRequest(params->url(), net::DEFAULT_PRIORITY, nullptr, + params->GetNetworkTrafficAnnotation())); + request->set_method(params->method()); + + if (!params->post_body().empty()) { + const std::string& body = params->post_body(); + std::unique_ptr<net::UploadElementReader> reader( + net::UploadOwnedBytesElementReader::CreateWithString(body)); + request->set_upload( + net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0)); + } + + if (params->post_id() >= 0) { + // The POST in this case does not have an actual body, and only works + // when retrieving data from cache. This is done because we don't want + // to do a re-POST without user consent, and currently don't have a good + // plan on how to display the UI for that. + DCHECK(params->prefer_cache()); + DCHECK_EQ("POST", params->method()); + std::vector<std::unique_ptr<net::UploadElementReader>> element_readers; + request->set_upload(base::MakeUnique<net::ElementsUploadDataStream>( + std::move(element_readers), params->post_id())); + } + + request->SetLoadFlags(GetLoadFlags(params, request->get_upload())); + + // Add additional request headers. + std::unique_ptr<net::HttpRequestHeaders> headers = + GetAdditionalRequestHeaders(params); + if (!headers->IsEmpty()) + request->SetExtraRequestHeaders(*headers); + + // Downloads are treated as top level navigations. Hence the first-party + // origin for cookies is always based on the target URL and is updated on + // redirects. + request->set_site_for_cookies(params->url()); + request->set_first_party_url_policy( + net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); + request->set_initiator(params->initiator()); + + return request; +} + + } // namespace content
diff --git a/content/browser/download/download_utils.h b/content/browser/download/download_utils.h index e94f030..741218a 100644 --- a/content/browser/download/download_utils.h +++ b/content/browser/download/download_utils.h
@@ -9,14 +9,29 @@ #include "net/base/net_errors.h" #include "net/cert/cert_status_flags.h" +namespace net { +class URLRequest; +} + namespace content { +class DownloadUrlParameters; +struct ResourceRequest; + // Handle the url request completion status and return the interrupt reasons. // |cert_status| is ignored if error_code is not net::ERR_ABORTED. DownloadInterruptReason CONTENT_EXPORT HandleRequestCompletionStatus( net::Error error_code, bool has_strong_validators, net::CertStatus cert_status, DownloadInterruptReason abort_reason); +// Create a ResourceRequest from |params|. +std::unique_ptr<ResourceRequest> CONTENT_EXPORT CreateResourceRequest( + DownloadUrlParameters* params); + +// Create a URLRequest from |params|. +std::unique_ptr<net::URLRequest> CreateURLRequestOnIOThread( + DownloadUrlParameters* params); + } // namespace content #endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_UTILS_H_
diff --git a/content/browser/loader/mojo_async_resource_handler_unittest.cc b/content/browser/loader/mojo_async_resource_handler_unittest.cc index daa08ddd..27ccfad 100644 --- a/content/browser/loader/mojo_async_resource_handler_unittest.cc +++ b/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -309,12 +309,7 @@ mojom::URLLoaderClientPtr PassClientPtr() { return std::move(client_ptr_); } - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& url_request, - SyncLoadCallback callback) override { - NOTREACHED(); - } + void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); } private: mojom::URLLoaderRequest loader_request_;
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index f7b8607d..d03d366 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -888,7 +888,8 @@ const ResourceRequest& request_data, net::MutableNetworkTrafficAnnotationTag traffic_annotation) { OnRequestResourceInternal( - requester_info, routing_id, request_id, request_data, nullptr, nullptr, + requester_info, routing_id, request_id, false /* is_sync_load */, + request_data, nullptr, nullptr, net::NetworkTrafficAnnotationTag(traffic_annotation)); } @@ -896,6 +897,7 @@ ResourceRequesterInfo* requester_info, int routing_id, int request_id, + bool is_sync_load, const ResourceRequest& request_data, mojom::URLLoaderRequest mojo_request, mojom::URLLoaderClientPtr url_loader_client, @@ -917,7 +919,7 @@ request_data.render_frame_id, request_data.url); } - BeginRequest(requester_info, request_id, request_data, + BeginRequest(requester_info, request_id, request_data, is_sync_load, SyncLoadResultCallback(), routing_id, std::move(mojo_request), std::move(url_loader_client), traffic_annotation); } @@ -938,8 +940,9 @@ SyncLoadResultCallback callback = base::Bind(&HandleSyncLoadResult, requester_info->filter()->GetWeakPtr(), base::Passed(WrapUnique(sync_result))); - BeginRequest(requester_info, request_id, request_data, callback, - sync_result->routing_id(), nullptr, nullptr, kTrafficAnnotation); + BeginRequest(requester_info, request_id, request_data, + true /* is_sync_load */, callback, sync_result->routing_id(), + nullptr, nullptr, kTrafficAnnotation); } bool ResourceDispatcherHostImpl::IsRequestIDInUse( @@ -1098,6 +1101,7 @@ ResourceRequesterInfo* requester_info, int request_id, const ResourceRequest& request_data, + bool is_sync_load, const SyncLoadResultCallback& sync_result_handler, // only valid for sync int route_id, mojom::URLLoaderRequest mojo_request, @@ -1218,8 +1222,8 @@ base::Bind( &ResourceDispatcherHostImpl::ContinuePendingBeginRequest, base::Unretained(this), make_scoped_refptr(requester_info), - request_id, request_data, sync_result_handler, route_id, - headers, base::Passed(std::move(mojo_request)), + request_id, request_data, is_sync_load, sync_result_handler, + route_id, headers, base::Passed(std::move(mojo_request)), base::Passed(std::move(url_loader_client)), base::Passed(std::move(blob_handles)), traffic_annotation)); return; @@ -1228,9 +1232,9 @@ } } ContinuePendingBeginRequest( - requester_info, request_id, request_data, sync_result_handler, route_id, - headers, std::move(mojo_request), std::move(url_loader_client), - std::move(blob_handles), traffic_annotation, + requester_info, request_id, request_data, is_sync_load, + sync_result_handler, route_id, headers, std::move(mojo_request), + std::move(url_loader_client), std::move(blob_handles), traffic_annotation, HeaderInterceptorResult::CONTINUE); } @@ -1238,6 +1242,7 @@ scoped_refptr<ResourceRequesterInfo> requester_info, int request_id, const ResourceRequest& request_data, + bool is_sync_load, const SyncLoadResultCallback& sync_result_handler, // only valid for sync int route_id, const net::HttpRequestHeaders& headers, @@ -1247,6 +1252,7 @@ const net::NetworkTrafficAnnotationTag& traffic_annotation, HeaderInterceptorResult interceptor_result) { DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload()); + DCHECK(!sync_result_handler || is_sync_load); if (interceptor_result != HeaderInterceptorResult::CONTINUE) { if (requester_info->IsRenderer() && interceptor_result == HeaderInterceptorResult::KILL) { @@ -1265,7 +1271,6 @@ bool allow_download = false; bool do_not_prompt_for_login = false; bool report_raw_headers = false; - bool is_sync_load = !!sync_result_handler; int load_flags = BuildLoadFlagsForRequest(request_data, is_sync_load); bool is_navigation_stream_request = IsBrowserSideNavigationEnabled() && @@ -2266,27 +2271,21 @@ void ResourceDispatcherHostImpl::OnRequestResourceWithMojo( ResourceRequesterInfo* requester_info, - int routing_id, - int request_id, + int32_t routing_id, + int32_t request_id, + uint32_t options, const ResourceRequest& request, mojom::URLLoaderRequest mojo_request, mojom::URLLoaderClientPtr url_loader_client, const net::NetworkTrafficAnnotationTag& traffic_annotation) { - OnRequestResourceInternal(requester_info, routing_id, request_id, request, - std::move(mojo_request), + DCHECK_EQ(mojom::kURLLoadOptionNone, + options & ~mojom::kURLLoadOptionSynchronous); + bool is_sync_load = options & mojom::kURLLoadOptionSynchronous; + OnRequestResourceInternal(requester_info, routing_id, request_id, + is_sync_load, request, std::move(mojo_request), std::move(url_loader_client), traffic_annotation); } -void ResourceDispatcherHostImpl::OnSyncLoadWithMojo( - ResourceRequesterInfo* requester_info, - int routing_id, - int request_id, - const ResourceRequest& request_data, - const SyncLoadResultCallback& result_handler) { - BeginRequest(requester_info, request_id, request_data, result_handler, - routing_id, nullptr, nullptr, kTrafficAnnotation); -} - // static int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost( net::URLRequest* request) {
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index 8c6187c..3ef287d 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -285,19 +285,14 @@ // Called when loading a request with mojo. void OnRequestResourceWithMojo( ResourceRequesterInfo* requester_info, - int routing_id, - int request_id, + int32_t routing_id, + int32_t request_id, + uint32_t options, const ResourceRequest& request, mojom::URLLoaderRequest mojo_request, mojom::URLLoaderClientPtr url_loader_client, const net::NetworkTrafficAnnotationTag& traffic_annotation); - void OnSyncLoadWithMojo(ResourceRequesterInfo* requester_info, - int routing_id, - int request_id, - const ResourceRequest& request_data, - const SyncLoadResultCallback& result_handler); - // Helper function for initializing the |request| passed in. By initializing // we mean setting the |referrer| on the |request|, associating the // ResourceRequestInfoImpl structure with the |request|, etc. @@ -548,6 +543,7 @@ ResourceRequesterInfo* requester_info, int routing_id, int request_id, + bool is_sync_load, const ResourceRequest& request_data, mojom::URLLoaderRequest mojo_request, mojom::URLLoaderClientPtr url_loader_client, @@ -583,6 +579,7 @@ ResourceRequesterInfo* requester_info, int request_id, const ResourceRequest& request_data, + bool is_sync_load, const SyncLoadResultCallback& sync_result_handler, // only valid for sync int route_id, mojom::URLLoaderRequest mojo_request, @@ -601,6 +598,7 @@ scoped_refptr<ResourceRequesterInfo> requester_info, int request_id, const ResourceRequest& request_data, + bool is_sync_load, const SyncLoadResultCallback& sync_result_handler, // only valid for sync int route_id, const net::HttpRequestHeaders& headers,
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 0ba21d0..98c0c64 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -3840,72 +3840,6 @@ content::RunAllBlockingPoolTasksUntilIdle(); } -namespace { - -void StoreSyncLoadResult(bool* called, - bool* was_null, - SyncLoadResult* result_out, - const SyncLoadResult* result) { - *called = true; - *was_null = !result; - - if (result) - *result_out = *result; -} - -} // namespace - -TEST_F(ResourceDispatcherHostTest, SyncLoadWithMojoSuccess) { - ResourceRequest request = CreateResourceRequest( - "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_1()); - request.priority = net::MAXIMUM_PRIORITY; - - bool called = false; - bool was_null = false; - SyncLoadResult result; - host_.OnSyncLoadWithMojo( - GetResourceRequesterInfo(filter_.get()), 0, 1, request, - base::Bind(&StoreSyncLoadResult, &called, &was_null, &result)); - content::RunAllBlockingPoolTasksUntilIdle(); - EXPECT_TRUE(called); - EXPECT_FALSE(was_null); - EXPECT_EQ(net::OK, result.error_code); -} - -TEST_F(ResourceDispatcherHostTest, SyncLoadWithMojoError) { - ResourceRequest request = CreateResourceRequest( - "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_error()); - request.priority = net::MAXIMUM_PRIORITY; - - bool called = false; - bool was_null = false; - SyncLoadResult result; - host_.OnSyncLoadWithMojo( - GetResourceRequesterInfo(filter_.get()), 0, 1, request, - base::Bind(&StoreSyncLoadResult, &called, &was_null, &result)); - content::RunAllBlockingPoolTasksUntilIdle(); - EXPECT_TRUE(called); - EXPECT_FALSE(was_null); - EXPECT_EQ(net::ERR_INVALID_URL, result.error_code); -} - -TEST_F(ResourceDispatcherHostTest, SyncLoadWithMojoCancel) { - ResourceRequest request = CreateResourceRequest( - "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_error()); - request.priority = net::MAXIMUM_PRIORITY; - - bool called = false; - bool was_null = false; - SyncLoadResult result; - host_.OnSyncLoadWithMojo( - GetResourceRequesterInfo(filter_.get()), 0, 1, request, - base::Bind(&StoreSyncLoadResult, &called, &was_null, &result)); - host_.CancelRequestsForProcess(filter_->child_id()); - content::RunAllBlockingPoolTasksUntilIdle(); - EXPECT_TRUE(called); - EXPECT_TRUE(was_null); -} - // A URLRequestTestJob that sets a test certificate on the |ssl_info| // field of the response. class TestHTTPSURLRequestJob : public net::URLRequestTestJob {
diff --git a/content/browser/loader/resource_message_filter.cc b/content/browser/loader/resource_message_filter.cc index ca27217..5f4d3a7c 100644 --- a/content/browser/loader/resource_message_filter.cc +++ b/content/browser/loader/resource_message_filter.cc
@@ -52,6 +52,10 @@ void ResourceMessageFilter::OnChannelClosing() { DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); + // Close all additional Mojo connections opened to this object so that + // messages are not dispatched while it is being shut down. + bindings_.CloseAllBindings(); + // Unhook us from all pending network requests so they don't get sent to a // deleted object. ResourceDispatcherHostImpl::Get()->CancelRequestsForProcess( @@ -92,19 +96,14 @@ const ResourceRequest& url_request, mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { - DCHECK_EQ(options, mojom::kURLLoadOptionNone); URLLoaderFactoryImpl::CreateLoaderAndStart( requester_info_.get(), std::move(request), routing_id, request_id, - url_request, std::move(client), + options, url_request, std::move(client), net::NetworkTrafficAnnotationTag(traffic_annotation)); } -void ResourceMessageFilter::SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& url_request, - SyncLoadCallback callback) { - URLLoaderFactoryImpl::SyncLoad(requester_info_.get(), routing_id, request_id, - url_request, std::move(callback)); +void ResourceMessageFilter::Clone(mojom::URLLoaderFactoryRequest request) { + bindings_.AddBinding(this, std::move(request)); } int ResourceMessageFilter::child_id() const {
diff --git a/content/browser/loader/resource_message_filter.h b/content/browser/loader/resource_message_filter.h index f96d0c2..f00cb19 100644 --- a/content/browser/loader/resource_message_filter.h +++ b/content/browser/loader/resource_message_filter.h
@@ -79,11 +79,8 @@ mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override; + void Clone(mojom::URLLoaderFactoryRequest request) override; - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override; int child_id() const; ResourceRequesterInfo* requester_info_for_test() { @@ -104,6 +101,11 @@ bool is_channel_closed_; scoped_refptr<ResourceRequesterInfo> requester_info_; + // An additional set of non-associated bindings (beyond those held by the + // BrowserAssociatedInterface parent class) of pipes to this object's + // URLLoaderFactory interface. + mojo::BindingSet<mojom::URLLoaderFactory> bindings_; + // Task runner for the IO thead. scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
diff --git a/content/browser/loader/url_loader_factory_impl.cc b/content/browser/loader/url_loader_factory_impl.cc index f433732..544e82c 100644 --- a/content/browser/loader/url_loader_factory_impl.cc +++ b/content/browser/loader/url_loader_factory_impl.cc
@@ -14,25 +14,6 @@ namespace content { -namespace { - -void DispatchSyncLoadResult(URLLoaderFactoryImpl::SyncLoadCallback callback, - const SyncLoadResult* result) { - // |result| can be null when a loading task is aborted unexpectedly. Reply - // with a failure result on that case. - // TODO(tzik): Test null-result case. - if (!result) { - SyncLoadResult failure; - failure.error_code = net::ERR_FAILED; - std::move(callback).Run(failure); - return; - } - - std::move(callback).Run(*result); -} - -} // namespace - URLLoaderFactoryImpl::URLLoaderFactoryImpl( scoped_refptr<ResourceRequesterInfo> requester_info, const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner) @@ -41,6 +22,8 @@ DCHECK((requester_info_->IsRenderer() && requester_info_->filter()) || requester_info_->IsNavigationPreload()); DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); + bindings_.set_connection_error_handler(base::Bind( + &URLLoaderFactoryImpl::OnConnectionError, base::Unretained(this))); } URLLoaderFactoryImpl::~URLLoaderFactoryImpl() { @@ -55,19 +38,14 @@ const ResourceRequest& url_request, mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { - DCHECK_EQ(options, mojom::kURLLoadOptionNone); CreateLoaderAndStart( requester_info_.get(), std::move(request), routing_id, request_id, - url_request, std::move(client), + options, url_request, std::move(client), static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation)); } -void URLLoaderFactoryImpl::SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& url_request, - SyncLoadCallback callback) { - SyncLoad(requester_info_.get(), routing_id, request_id, url_request, - std::move(callback)); +void URLLoaderFactoryImpl::Clone(mojom::URLLoaderFactoryRequest request) { + bindings_.AddBinding(this, std::move(request)); } // static @@ -76,6 +54,7 @@ mojom::URLLoaderRequest request, int32_t routing_id, int32_t request_id, + uint32_t options, const ResourceRequest& url_request, mojom::URLLoaderClientPtr client, const net::NetworkTrafficAnnotationTag& traffic_annotation) { @@ -85,33 +64,26 @@ ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get(); rdh->OnRequestResourceWithMojo(requester_info, routing_id, request_id, - url_request, std::move(request), + options, url_request, std::move(request), std::move(client), traffic_annotation); } // static -void URLLoaderFactoryImpl::SyncLoad(ResourceRequesterInfo* requester_info, - int32_t routing_id, - int32_t request_id, - const ResourceRequest& url_request, - SyncLoadCallback callback) { - DCHECK(ResourceDispatcherHostImpl::Get() - ->io_thread_task_runner() - ->BelongsToCurrentThread()); - - ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get(); - rdh->OnSyncLoadWithMojo( - requester_info, routing_id, request_id, url_request, - base::Bind(&DispatchSyncLoadResult, base::Passed(&callback))); -} - void URLLoaderFactoryImpl::Create( scoped_refptr<ResourceRequesterInfo> requester_info, - mojo::InterfaceRequest<mojom::URLLoaderFactory> request, + mojom::URLLoaderFactoryRequest request, const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner) { - mojo::MakeStrongBinding(base::WrapUnique(new URLLoaderFactoryImpl( - std::move(requester_info), io_thread_runner)), - std::move(request)); + // This instance is effectively reference counted by the number of pipes open + // to it and will get deleted when all clients drop their connections. + // Please see OnConnectionError() for details. + auto* impl = + new URLLoaderFactoryImpl(std::move(requester_info), io_thread_runner); + impl->Clone(std::move(request)); +} + +void URLLoaderFactoryImpl::OnConnectionError() { + if (bindings_.empty()) + delete this; } } // namespace content
diff --git a/content/browser/loader/url_loader_factory_impl.h b/content/browser/loader/url_loader_factory_impl.h index 9bfa94d..caa72a3 100644 --- a/content/browser/loader/url_loader_factory_impl.h +++ b/content/browser/loader/url_loader_factory_impl.h
@@ -10,6 +10,7 @@ #include "base/single_thread_task_runner.h" #include "content/common/content_export.h" #include "content/public/common/url_loader_factory.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace content { @@ -31,26 +32,18 @@ mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override; - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override; + void Clone(mojom::URLLoaderFactoryRequest request) override; static void CreateLoaderAndStart( ResourceRequesterInfo* requester_info, mojom::URLLoaderRequest request, int32_t routing_id, int32_t request_id, + uint32_t options, const ResourceRequest& url_request, mojom::URLLoaderClientPtr client, const net::NetworkTrafficAnnotationTag& traffic_annotation); - static void SyncLoad(ResourceRequesterInfo* requester_info, - int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback); - // Creates a URLLoaderFactoryImpl instance. The instance is held by the // StrongBinding in it, so this function doesn't return the instance. CONTENT_EXPORT static void Create( @@ -63,6 +56,10 @@ scoped_refptr<ResourceRequesterInfo> requester_info, const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner); + void OnConnectionError(); + + mojo::BindingSet<mojom::URLLoaderFactory> bindings_; + scoped_refptr<ResourceRequesterInfo> requester_info_; // Task runner for the IO thead.
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h index df39d1b..4355a8cd 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.h +++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -38,7 +38,7 @@ // is visible. // - The RenderWidgetHostViewMac that is used to display these frames is // attached to the NSView hierarchy of an NSWindow. -class BrowserCompositorMac : public DelegatedFrameHostClient { +class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient { public: BrowserCompositorMac( ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view, @@ -51,6 +51,10 @@ // These will not return nullptr until Destroy is called. DelegatedFrameHost* GetDelegatedFrameHost(); + // Ensure that the currect compositor frame be cleared (even if it is + // potentially visible). + void ClearCompositorFrame(); + // This may return nullptr, if this has detached itself from its // ui::Compositor. ui::AcceleratedWidgetMac* GetAcceleratedWidgetMac(); @@ -105,6 +109,9 @@ void OnBeginFrame() override; bool IsAutoResizeEnabled() const override; + // Returns nullptr if no compositor is attached. + ui::Compositor* CompositorForTesting() const; + private: // The state of |delegated_frame_host_| and |recyclable_compositor_| to // manage being visible, hidden, or occluded.
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index 8a7eb98f..428bef1 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -216,6 +216,17 @@ return delegated_frame_host_.get(); } +void BrowserCompositorMac::ClearCompositorFrame() { + // Make sure that we no longer hold a compositor lock by un-suspending the + // compositor. This ensures that we are able to swap in a new blank frame to + // replace any old content. + // https://crbug.com/739621 + if (recyclable_compositor_) + recyclable_compositor_->Unsuspend(); + if (delegated_frame_host_) + delegated_frame_host_->ClearDelegatedFrame(); +} + void BrowserCompositorMac::CopyCompleted( base::WeakPtr<BrowserCompositorMac> browser_compositor, const ReadbackRequestCallback& callback, @@ -450,4 +461,10 @@ return false; } +ui::Compositor* BrowserCompositorMac::CompositorForTesting() const { + if (recyclable_compositor_) + return recyclable_compositor_->compositor(); + return nullptr; +} + } // namespace content
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 8c0c5a55..5aa3c3a3 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -488,6 +488,11 @@ } void DelegatedFrameHost::ClearDelegatedFrame() { + // Ensure that we are able to swap in a new blank frame to replace any old + // content. This will result in a white flash if we switch back to this + // content. + // https://crbug.com/739621 + released_front_lock_.reset(); EvictDelegatedFrame(); }
diff --git a/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc b/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc index e673446..7bfbef7 100644 --- a/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc +++ b/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
@@ -24,6 +24,8 @@ #include "media/audio/audio_thread_impl.h" #include "media/audio/fake_audio_log_factory.h" #include "media/audio/fake_audio_manager.h" +#include "media/base/bind_to_current_loop.h" +#include "media/base/gmock_callback_support.h" #include "media/base/media_switches.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -354,33 +356,41 @@ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done); } + void TrampolineToUI(base::Closure done, + std::unique_ptr<AudioOutputDelegateImpl> delegate) { + // Destruct and then sync since destruction will post some tasks. + delegate.reset(); + SyncWithAllThreads(); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done); + } + void ErrorTest(base::Closure done) { EXPECT_CALL(media_observer_, OnCreatingAudioStream(kRenderProcessId, kRenderFrameId)); EXPECT_CALL(event_handler_, GotOnStreamCreated()); - EXPECT_CALL(event_handler_, OnStreamError(kStreamId)); EXPECT_CALL(mirroring_manager_, AddDiverter(kRenderProcessId, kRenderFrameId, NotNull())); + EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())); - { - auto socket = base::MakeUnique<base::CancelableSyncSocket>(); - auto reader = AudioSyncReader::Create(Params(), socket.get()); - AudioOutputDelegateImpl delegate( - std::move(reader), std::move(socket), &event_handler_, - audio_manager_.get(), - log_factory_.CreateAudioLog( - media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER), - &mirroring_manager_, &media_observer_, kStreamId, kRenderFrameId, - kRenderProcessId, Params(), kDefaultDeviceId); + auto socket = base::MakeUnique<base::CancelableSyncSocket>(); + auto reader = AudioSyncReader::Create(Params(), socket.get()); + auto delegate = base::MakeUnique<AudioOutputDelegateImpl>( + std::move(reader), std::move(socket), &event_handler_, + audio_manager_.get(), + log_factory_.CreateAudioLog( + media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER), + &mirroring_manager_, &media_observer_, kStreamId, kRenderFrameId, + kRenderProcessId, Params(), kDefaultDeviceId); - delegate.GetControllerForTesting()->OnError(); + delegate->GetControllerForTesting()->OnError(); - SyncWithAllThreads(); - - EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())); - } - SyncWithAllThreads(); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done); + // Errors are deferred by AudioOutputController, so wait for the error; pass + // the delegate along since destructing it will close the stream and void + // the purpose of this test. + EXPECT_CALL(event_handler_, OnStreamError(kStreamId)) + .WillOnce(media::RunClosure(media::BindToCurrentLoop(base::Bind( + &AudioOutputDelegateTest::TrampolineToUI, base::Unretained(this), + done, base::Passed(&delegate))))); } void CreateAndDestroyTest(base::Closure done) {
diff --git a/content/browser/renderer_host/native_web_keyboard_event_android.cc b/content/browser/renderer_host/native_web_keyboard_event_android.cc index c2b9c2f..ece07f9 100644 --- a/content/browser/renderer_host/native_web_keyboard_event_android.cc +++ b/content/browser/renderer_host/native_web_keyboard_event_android.cc
@@ -9,20 +9,6 @@ #include "ui/events/base_event_utils.h" #include "ui/gfx/native_widget_types.h" -namespace { - -jobject NewGlobalRefForKeyEvent(jobject key_event) { - if (key_event == nullptr) return nullptr; - return base::android::AttachCurrentThread()->NewGlobalRef(key_event); -} - -void DeleteGlobalRefForKeyEvent(jobject key_event) { - if (key_event != nullptr) - base::android::AttachCurrentThread()->DeleteGlobalRef(key_event); -} - -} - namespace content { NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type, @@ -65,28 +51,25 @@ os_event(nullptr), skip_in_browser(false) { if (!android_key_event.is_null()) - os_event = NewGlobalRefForKeyEvent(android_key_event.obj()); + os_event.Reset(android_key_event); } NativeWebKeyboardEvent::NativeWebKeyboardEvent( const NativeWebKeyboardEvent& other) : WebKeyboardEvent(other), - os_event(NewGlobalRefForKeyEvent(other.os_event)), - skip_in_browser(other.skip_in_browser) { -} + os_event(other.os_event), + skip_in_browser(other.skip_in_browser) {} NativeWebKeyboardEvent& NativeWebKeyboardEvent::operator=( const NativeWebKeyboardEvent& other) { WebKeyboardEvent::operator=(other); - os_event = NewGlobalRefForKeyEvent(other.os_event); + os_event = other.os_event; skip_in_browser = other.skip_in_browser; return *this; } -NativeWebKeyboardEvent::~NativeWebKeyboardEvent() { - DeleteGlobalRefForKeyEvent(os_event); -} +NativeWebKeyboardEvent::~NativeWebKeyboardEvent() {} } // 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 1adfb73..503f889 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3632,6 +3632,8 @@ // request for FrameSinkProvider so make sure frame_sink_provider_ is ready // for that. frame_sink_provider_.Unbind(); + if (renderer_host_binding_.is_bound()) + renderer_host_binding_.Unbind(); shared_bitmap_allocation_notifier_impl_.ChildDied();
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 16fd8d08..9374bf3 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -447,6 +447,9 @@ // Delegated frame management and compositor interface. std::unique_ptr<BrowserCompositorMac> browser_compositor_; + BrowserCompositorMac* BrowserCompositorForTesting() const { + return browser_compositor_.get(); + } // Set when the currently-displayed frame is the minimum scale. Used to // determine if pinch gestures need to be thresholded.
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 4fe436b..db0fb3681 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1447,7 +1447,7 @@ } void RenderWidgetHostViewMac::ClearCompositorFrame() { - browser_compositor_->GetDelegatedFrameHost()->ClearDelegatedFrame(); + browser_compositor_->ClearCompositorFrame(); } gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() {
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index ae1dce9..f03c1410 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -2127,4 +2127,14 @@ rwhv_mac_->release_pepper_fullscreen_window_for_testing(); } +TEST_F(RenderWidgetHostViewMacTest, ClearCompositorFrame) { + BrowserCompositorMac* browser_compositor = + rwhv_mac_->BrowserCompositorForTesting(); + EXPECT_NE(browser_compositor->CompositorForTesting(), nullptr); + EXPECT_TRUE(browser_compositor->CompositorForTesting()->IsLocked()); + rwhv_mac_->ClearCompositorFrame(); + EXPECT_NE(browser_compositor->CompositorForTesting(), nullptr); + EXPECT_FALSE(browser_compositor->CompositorForTesting()->IsLocked()); +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc index 172566ba..cf0ec22 100644 --- a/content/browser/service_worker/service_worker_provider_host.cc +++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -241,10 +241,9 @@ std::move(request)); } - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override { + void Clone(mojom::URLLoaderFactoryRequest request) override { + // This method is required to support synchronous requests which are not + // performed during installation. NOTREACHED(); }
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index e40ac83..375c004 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -2685,10 +2685,8 @@ traffic_annotation) override { new FailingURLLoaderImpl(std::move(client)); } - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override {} + + void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); } }; }
diff --git a/content/browser/webui/web_ui_url_loader_factory.cc b/content/browser/webui/web_ui_url_loader_factory.cc index 40c59e115..3c49b85 100644 --- a/content/browser/webui/web_ui_url_loader_factory.cc +++ b/content/browser/webui/web_ui_url_loader_factory.cc
@@ -266,11 +266,8 @@ storage_partition_->browser_context()->GetResourceContext())); } - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override { - NOTREACHED(); + void Clone(mojom::URLLoaderFactoryRequest request) override { + loader_factory_bindings_.AddBinding(this, std::move(request)); } // FrameTreeNode::Observer implementation:
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn index d7ed326f..146b551 100644 --- a/content/child/BUILD.gn +++ b/content/child/BUILD.gn
@@ -174,6 +174,8 @@ "site_isolation_stats_gatherer.h", "storage_util.cc", "storage_util.h", + "sync_load_context.cc", + "sync_load_context.h", "sync_load_response.cc", "sync_load_response.h", "thread_safe_sender.cc",
diff --git a/content/child/loader/cors_url_loader_factory.cc b/content/child/loader/cors_url_loader_factory.cc index aef3667..8d5583cc 100644 --- a/content/child/loader/cors_url_loader_factory.cc +++ b/content/child/loader/cors_url_loader_factory.cc
@@ -45,12 +45,11 @@ std::move(request)); } -void CORSURLLoaderFactory::SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& resource_request, - SyncLoadCallback callback) { - network_loader_factory_->SyncLoad(routing_id, request_id, resource_request, - std::move(callback)); +void CORSURLLoaderFactory::Clone(mojom::URLLoaderFactoryRequest request) { + // Cloning a CORSURLLoaderFactory so that it can be used from a different + // thread is not useful because that thread will still be dependent on the + // current one to handle requests. + NOTREACHED(); } } // namespace content
diff --git a/content/child/loader/cors_url_loader_factory.h b/content/child/loader/cors_url_loader_factory.h index ae0db76..1e1972ef 100644 --- a/content/child/loader/cors_url_loader_factory.h +++ b/content/child/loader/cors_url_loader_factory.h
@@ -31,11 +31,7 @@ mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override; - - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& resource_request, - SyncLoadCallback callback) override; + void Clone(mojom::URLLoaderFactoryRequest request) override; private: PossiblyAssociatedInterfacePtr<mojom::URLLoaderFactory>
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc index 5df6e50..32eb20f 100644 --- a/content/child/resource_dispatcher.cc +++ b/content/child/resource_dispatcher.cc
@@ -585,26 +585,14 @@ SyncLoadResult result; - if (ipc_type == blink::WebURLRequest::LoadingIPCType::kMojo) { - // TODO(yzshen): There is no way to apply a throttle to sync loading. We - // could use async loading + sync handle watching to emulate this behavior. - // That may require to extend the bindings API to change the priority of - // messages. It would result in more messages during this blocking - // operation, but sync loading is discouraged anyway. - if (!url_loader_factory->SyncLoad( - routing_id, MakeRequestID(), *request, &result)) { - response->error_code = net::ERR_FAILED; - return; - } - } else { - IPC::SyncMessage* msg = new ResourceHostMsg_SyncLoad( - routing_id, MakeRequestID(), *request, &result); + DCHECK_NE(ipc_type, blink::WebURLRequest::LoadingIPCType::kMojo); + IPC::SyncMessage* msg = new ResourceHostMsg_SyncLoad( + routing_id, MakeRequestID(), *request, &result); - // NOTE: This may pump events (see RenderThread::Send). - if (!message_sender_->Send(msg)) { - response->error_code = net::ERR_FAILED; - return; - } + // NOTE: This may pump events (see RenderThread::Send). + if (!message_sender_->Send(msg)) { + response->error_code = net::ERR_FAILED; + return; } response->error_code = result.error_code; @@ -628,6 +616,7 @@ int routing_id, scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner, const url::Origin& frame_origin, + bool is_sync, std::unique_ptr<RequestPeer> peer, blink::WebURLRequest::LoadingIPCType ipc_type, mojom::URLLoaderFactory* url_loader_factory, @@ -699,6 +688,8 @@ // MIME sniffing should be disabled for a request initiated by fetch(). options |= mojom::kURLLoadOptionSniffMimeType; } + if (is_sync) + options |= mojom::kURLLoadOptionSynchronous; std::unique_ptr<ThrottlingURLLoader> url_loader = ThrottlingURLLoader::CreateLoaderAndStart(
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h index ccde1a4..558fd76 100644 --- a/content/child/resource_dispatcher.h +++ b/content/child/resource_dispatcher.h
@@ -110,6 +110,7 @@ int routing_id, scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner, const url::Origin& frame_origin, + bool is_sync, std::unique_ptr<RequestPeer> peer, blink::WebURLRequest::LoadingIPCType ipc_type, mojom::URLLoaderFactory* url_loader_factory,
diff --git a/content/child/resource_dispatcher_unittest.cc b/content/child/resource_dispatcher_unittest.cc index 25953ff..82510673 100644 --- a/content/child/resource_dispatcher_unittest.cc +++ b/content/child/resource_dispatcher_unittest.cc
@@ -228,7 +228,7 @@ std::unique_ptr<TestRequestPeer> peer( new TestRequestPeer(dispatcher(), peer_context)); int request_id = dispatcher()->StartAsync( - std::move(request), 0, nullptr, url::Origin(), std::move(peer), + std::move(request), 0, nullptr, url::Origin(), false, std::move(peer), blink::WebURLRequest::LoadingIPCType::kChromeIPC, nullptr, std::vector<std::unique_ptr<URLLoaderThrottle>>(), mojo::ScopedDataPipeConsumerHandle());
diff --git a/content/child/sync_load_context.cc b/content/child/sync_load_context.cc new file mode 100644 index 0000000..e7ee0fc --- /dev/null +++ b/content/child/sync_load_context.cc
@@ -0,0 +1,115 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/child/sync_load_context.h" + +#include <string> + +#include "base/logging.h" +#include "base/synchronization/waitable_event.h" +#include "content/child/sync_load_response.h" +#include "content/public/common/resource_request.h" +#include "content/public/common/resource_response_info.h" +#include "content/public/common/url_loader_throttle.h" +#include "net/url_request/redirect_info.h" + +namespace content { + +// static +void SyncLoadContext::StartAsyncWithWaitableEvent( + std::unique_ptr<ResourceRequest> request, + int routing_id, + const url::Origin& frame_origin, + mojom::URLLoaderFactoryPtrInfo url_loader_factory_pipe, + SyncLoadResponse* response, + base::WaitableEvent* event) { + auto* context = new SyncLoadContext( + request.get(), std::move(url_loader_factory_pipe), response, event); + // TODO(reillyg): Support throttles. + std::vector<std::unique_ptr<URLLoaderThrottle>> throttles; + + context->request_id_ = context->resource_dispatcher_->StartAsync( + std::move(request), routing_id, nullptr, frame_origin, true /* is_sync */, + base::WrapUnique(context), blink::WebURLRequest::LoadingIPCType::kMojo, + context->url_loader_factory_.get(), std::move(throttles), + mojo::ScopedDataPipeConsumerHandle()); +} + +SyncLoadContext::SyncLoadContext( + ResourceRequest* request, + mojom::URLLoaderFactoryPtrInfo url_loader_factory, + SyncLoadResponse* response, + base::WaitableEvent* event) + : response_(response), event_(event) { + url_loader_factory_.Bind(std::move(url_loader_factory)); + + // Constructs a new ResourceDispatcher specifically for this request. + resource_dispatcher_ = base::MakeUnique<ResourceDispatcher>( + nullptr, base::ThreadTaskRunnerHandle::Get()); + + // Initialize the final URL with the original request URL. It will be + // overwritten on redirects. + response_->url = request->url; +} + +SyncLoadContext::~SyncLoadContext() {} + +void SyncLoadContext::OnUploadProgress(uint64_t position, uint64_t size) {} + +bool SyncLoadContext::OnReceivedRedirect(const net::RedirectInfo& redirect_info, + const ResourceResponseInfo& info) { + if (redirect_info.new_url.GetOrigin() != response_->url.GetOrigin()) { + LOG(ERROR) << "Cross origin redirect denied"; + response_->error_code = net::ERR_ABORTED; + event_->Signal(); + + // Returning false here will cause the request to be cancelled and this + // object deleted. + return false; + } + + response_->url = redirect_info.new_url; + return true; +} + +void SyncLoadContext::OnReceivedResponse(const ResourceResponseInfo& info) { + response_->headers = info.headers; + response_->mime_type = info.mime_type; + response_->charset = info.charset; + response_->request_time = info.request_time; + response_->response_time = info.response_time; + response_->load_timing = info.load_timing; + response_->devtools_info = info.devtools_info; + response_->download_file_path = info.download_file_path; + response_->socket_address = info.socket_address; +} + +void SyncLoadContext::OnDownloadedData(int len, int encoded_data_length) { + // This method is only called when RequestInfo::download_to_file is true which + // is not allowed when processing a synchronous request. + NOTREACHED(); +} + +void SyncLoadContext::OnReceivedData(std::unique_ptr<ReceivedData> data) { + response_->data.append(data->payload(), data->length()); +} + +void SyncLoadContext::OnTransferSizeUpdated(int transfer_size_diff) {} + +void SyncLoadContext::OnCompletedRequest(int error_code, + bool stale_copy_in_cache, + const base::TimeTicks& completion_time, + int64_t total_transfer_size, + int64_t encoded_body_size, + int64_t decoded_body_size) { + response_->error_code = error_code; + response_->encoded_data_length = total_transfer_size; + response_->encoded_body_length = encoded_body_size; + event_->Signal(); + + // This will indirectly cause this object to be deleted. + resource_dispatcher_->RemovePendingRequest(request_id_); +} + +} // namespace content
diff --git a/content/child/sync_load_context.h b/content/child/sync_load_context.h new file mode 100644 index 0000000..5323023 --- /dev/null +++ b/content/child/sync_load_context.h
@@ -0,0 +1,81 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_CHILD_SYNC_LOAD_CONTEXT_H_ +#define CONTENT_CHILD_SYNC_LOAD_CONTEXT_H_ + +#include "base/macros.h" +#include "content/child/resource_dispatcher.h" +#include "content/public/child/request_peer.h" +#include "content/public/common/url_loader_factory.mojom.h" + +namespace base { +class WaitableEvent; +} + +namespace url { +class Origin; +} + +namespace content { + +struct ResourceRequest; +struct SyncLoadResponse; + +// This class owns the context necessary to perform an asynchronous request +// while the main thread is blocked so that it appears to be synchronous. +class SyncLoadContext : public RequestPeer { + public: + // Begins a new asynchronous request on whatever sequence this method is + // called on. |event| will be signalled when the request is complete and + // |response| will be populated with the response data. + static void StartAsyncWithWaitableEvent( + std::unique_ptr<ResourceRequest> request, + int routing_id, + const url::Origin& frame_origin, + mojom::URLLoaderFactoryPtrInfo url_loader_factory_pipe, + SyncLoadResponse* response, + base::WaitableEvent* event); + + SyncLoadContext(ResourceRequest* request, + mojom::URLLoaderFactoryPtrInfo url_loader_factory, + SyncLoadResponse* response, + base::WaitableEvent* event); + ~SyncLoadContext() override; + + private: + // RequestPeer implementation: + void OnUploadProgress(uint64_t position, uint64_t size) override; + bool OnReceivedRedirect(const net::RedirectInfo& redirect_info, + const ResourceResponseInfo& info) override; + void OnReceivedResponse(const ResourceResponseInfo& info) override; + void OnDownloadedData(int len, int encoded_data_length) override; + void OnReceivedData(std::unique_ptr<ReceivedData> data) override; + void OnTransferSizeUpdated(int transfer_size_diff) override; + void OnCompletedRequest(int error_code, + bool stale_copy_in_cache, + const base::TimeTicks& completion_time, + int64_t total_transfer_size, + int64_t encoded_body_size, + int64_t decoded_body_size) override; + + // This raw pointer will remain valid for the lifetime of this object because + // it remains on the stack until |event_| is signaled. + SyncLoadResponse* response_; + + // This event is signaled when the request is complete. + base::WaitableEvent* event_; + + // State necessary to run a request on an independent thread. + mojom::URLLoaderFactoryPtr url_loader_factory_; + std::unique_ptr<ResourceDispatcher> resource_dispatcher_; + + int request_id_; + + DISALLOW_COPY_AND_ASSIGN(SyncLoadContext); +}; + +} // namespace content + +#endif // CONTENT_CHILD_SYNC_LOAD_CONTEXT_H_
diff --git a/content/child/url_loader_client_impl_unittest.cc b/content/child/url_loader_client_impl_unittest.cc index edf0cd6..16b229b9 100644 --- a/content/child/url_loader_client_impl_unittest.cc +++ b/content/child/url_loader_client_impl_unittest.cc
@@ -30,7 +30,7 @@ mojo_binding_.Bind(mojo::MakeRequest(&url_loader_factory_proxy_)); request_id_ = dispatcher_->StartAsync( - base::MakeUnique<ResourceRequest>(), 0, nullptr, url::Origin(), + base::MakeUnique<ResourceRequest>(), 0, nullptr, url::Origin(), false, base::MakeUnique<TestRequestPeer>(dispatcher_.get(), &request_peer_context_), blink::WebURLRequest::LoadingIPCType::kMojo, @@ -64,12 +64,7 @@ url_loader_client_ = std::move(client); } - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override { - NOTREACHED(); - } + void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); } static MojoCreateDataPipeOptions DataPipeOptions() { MojoCreateDataPipeOptions options;
diff --git a/content/child/url_response_body_consumer_unittest.cc b/content/child/url_response_body_consumer_unittest.cc index 46a0e88..0bfadb86 100644 --- a/content/child/url_response_body_consumer_unittest.cc +++ b/content/child/url_response_body_consumer_unittest.cc
@@ -137,7 +137,7 @@ int SetUpRequestPeer(std::unique_ptr<ResourceRequest> request, TestRequestPeer::Context* context) { return dispatcher_->StartAsync( - std::move(request), 0, nullptr, url::Origin(), + std::move(request), 0, nullptr, url::Origin(), false, base::MakeUnique<TestRequestPeer>(context, message_loop_.task_runner()), blink::WebURLRequest::LoadingIPCType::kChromeIPC, nullptr, std::vector<std::unique_ptr<URLLoaderThrottle>>(),
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index fd674b2..6cd2b7d 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -22,6 +22,8 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "base/synchronization/waitable_event.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" @@ -30,6 +32,7 @@ #include "content/child/request_extra_data.h" #include "content/child/resource_dispatcher.h" #include "content/child/shared_memory_data_consumer_handle.h" +#include "content/child/sync_load_context.h" #include "content/child/sync_load_response.h" #include "content/child/web_url_request_util.h" #include "content/child/weburlresponse_extradata_impl.h" @@ -658,10 +661,37 @@ if (sync_load_response) { DCHECK(defers_loading_ == NOT_DEFERRING); - resource_dispatcher_->StartSync( - std::move(resource_request), request.RequestorID(), sync_load_response, - request.GetLoadingIPCType(), url_loader_factory_, - extra_data->TakeURLLoaderThrottles()); + + int routing_id = request.RequestorID(); + blink::WebURLRequest::LoadingIPCType ipc_type = request.GetLoadingIPCType(); + if (ipc_type == blink::WebURLRequest::LoadingIPCType::kMojo) { + mojom::URLLoaderFactoryPtrInfo url_loader_factory_copy; + url_loader_factory_->Clone(mojo::MakeRequest(&url_loader_factory_copy)); + base::WaitableEvent event( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + + // TODO(reillyg): Support passing URLLoaderThrottles to this task. + DCHECK_EQ(0u, extra_data->TakeURLLoaderThrottles().size()); + + // A task is posted to a separate thread to execute the request so that + // this thread may block on a waitable event. It is safe to pass raw + // pointers to |sync_load_response| and |event| as this stack frame will + // survive until the request is complete. + base::CreateSingleThreadTaskRunnerWithTraits({})->PostTask( + FROM_HERE, + base::BindOnce( + &SyncLoadContext::StartAsyncWithWaitableEvent, + std::move(resource_request), routing_id, + extra_data->frame_origin(), std::move(url_loader_factory_copy), + base::Unretained(sync_load_response), base::Unretained(&event))); + + event.Wait(); + } else { + resource_dispatcher_->StartSync( + std::move(resource_request), routing_id, sync_load_response, ipc_type, + url_loader_factory_, extra_data->TakeURLLoaderThrottles()); + } return; } @@ -669,7 +699,7 @@ TRACE_EVENT_FLAG_FLOW_OUT); request_id_ = resource_dispatcher_->StartAsync( std::move(resource_request), request.RequestorID(), task_runner_, - extra_data->frame_origin(), + extra_data->frame_origin(), false /* is_sync */, base::MakeUnique<WebURLLoaderImpl::RequestPeerImpl>(this), request.GetLoadingIPCType(), url_loader_factory_, extra_data->TakeURLLoaderThrottles(), std::move(consumer_handle));
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc index cc6c4e86..8e0da3b 100644 --- a/content/child/web_url_loader_impl_unittest.cc +++ b/content/child/web_url_loader_impl_unittest.cc
@@ -82,12 +82,15 @@ int routing_id, scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner, const url::Origin& frame_origin, + bool is_sync, std::unique_ptr<RequestPeer> peer, blink::WebURLRequest::LoadingIPCType ipc_type, mojom::URLLoaderFactory* url_loader_factory, std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, mojo::ScopedDataPipeConsumerHandle consumer_handle) override { EXPECT_FALSE(peer_); + if (sync_load_response_.encoded_body_length != -1) + EXPECT_TRUE(is_sync); peer_ = std::move(peer); url_ = request->url; stream_url_ = request->resource_body_stream_url;
diff --git a/content/common/throttling_url_loader_unittest.cc b/content/common/throttling_url_loader_unittest.cc index ea3d9759..8da6e74 100644 --- a/content/common/throttling_url_loader_unittest.cc +++ b/content/common/throttling_url_loader_unittest.cc
@@ -59,12 +59,7 @@ client_ptr_ = std::move(client); } - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override { - NOTREACHED(); - } + void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); } size_t create_loader_and_start_called_ = 0;
diff --git a/content/network/network_service_url_loader_factory_impl.cc b/content/network/network_service_url_loader_factory_impl.cc index 593ee780..7624b6c 100644 --- a/content/network/network_service_url_loader_factory_impl.cc +++ b/content/network/network_service_url_loader_factory_impl.cc
@@ -5,6 +5,7 @@ #include "content/network/network_service_url_loader_factory_impl.h" #include "base/logging.h" +#include "content/network/network_context.h" #include "content/network/url_loader_impl.h" #include "content/public/common/resource_request.h" @@ -33,16 +34,9 @@ static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation)); } -void NetworkServiceURLLoaderFactoryImpl::SyncLoad( - int32_t routing_id, - int32_t request_id, - const ResourceRequest& url_request, - SyncLoadCallback callback) { - NOTIMPLEMENTED(); - - SyncLoadResult result; - result.error_code = net::ERR_NOT_IMPLEMENTED; - std::move(callback).Run(result); +void NetworkServiceURLLoaderFactoryImpl::Clone( + mojom::URLLoaderFactoryRequest request) { + context_->CreateURLLoaderFactory(std::move(request), process_id_); } } // namespace content
diff --git a/content/network/network_service_url_loader_factory_impl.h b/content/network/network_service_url_loader_factory_impl.h index 571db36..e0b9316 100644 --- a/content/network/network_service_url_loader_factory_impl.h +++ b/content/network/network_service_url_loader_factory_impl.h
@@ -32,10 +32,7 @@ mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override; - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& request, - SyncLoadCallback callback) override; + void Clone(mojom::URLLoaderFactoryRequest request) override; private: // Not owned.
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index ec03f8c..c4254e37 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -71,12 +71,6 @@ const base::Feature kCompositorTouchAction{"CompositorTouchAction", base::FEATURE_DISABLED_BY_DEFAULT}; -// Controls whether PreferCompositingToLCDText is forced off, even for -// screens with high resolution. -const base::Feature kDisablePreferCompositingToLCDTextOnLowEndAndroid{ - "DisablePreferCompositingToLCDTextOnLowEndAndroid", - base::FEATURE_DISABLED_BY_DEFAULT}; - // Throttle tasks in Blink background timer queues based on CPU budgets // for the background tab. Bug: https://crbug.com/639852. const base::Feature kExpensiveBackgroundTimerThrottling{ @@ -285,7 +279,7 @@ // An experiment to reduce the soft tile memory limit on low-end android // devices. const base::Feature kReducedSoftTileMemoryLimitOnLowEndAndroid{ - "kReducedSoftTileMemoryLimitOnLowEndAndroid", + "ReducedSoftTileMemoryLimitOnLowEndAndroid", base::FEATURE_DISABLED_BY_DEFAULT}; // Paint invalidation based on slimming paint. See https://goo.gl/eQczQW
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 2d0cfbb..7c6d268a 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -30,8 +30,6 @@ CONTENT_EXPORT extern const base::Feature kCompositeOpaqueScrollers; CONTENT_EXPORT extern const base::Feature kCompositorTouchAction; CONTENT_EXPORT extern const base::Feature - kDisablePreferCompositingToLCDTextOnLowEndAndroid; -CONTENT_EXPORT extern const base::Feature kReducedSoftTileMemoryLimitOnLowEndAndroid; CONTENT_EXPORT extern const base::Feature kExpensiveBackgroundTimerThrottling; CONTENT_EXPORT extern const base::Feature kFeaturePolicy;
diff --git a/content/public/common/typemaps.gni b/content/public/common/typemaps.gni index a9cff966..db3e842 100644 --- a/content/public/common/typemaps.gni +++ b/content/public/common/typemaps.gni
@@ -12,5 +12,4 @@ "//content/public/common/url_request.typemap", "//content/public/common/url_request_redirect_info.typemap", "//content/public/common/url_response_head.typemap", - "//content/public/common/url_sync_load_result.typemap", ]
diff --git a/content/public/common/url_loader_factory.mojom b/content/public/common/url_loader_factory.mojom index 54b2fd4..1d69a7c 100644 --- a/content/public/common/url_loader_factory.mojom +++ b/content/public/common/url_loader_factory.mojom
@@ -7,14 +7,13 @@ import "mutable_network_traffic_annotation_tag.mojom"; import "url_loader.mojom"; -[Native] -struct URLSyncLoadResult; - const uint32 kURLLoadOptionNone = 0; // Sends the net::SSLInfo struct in OnReceiveResponse. const uint32 kURLLoadOptionSendSSLInfo = 1; // Enables mime sniffing. NOTE: this is only used with the network service. const uint32 kURLLoadOptionSniffMimeType = 2; +// Indicates that execution is blocking on the completion of the request. +const uint32 kURLLoadOptionSynchronous = 4; interface URLLoaderFactory { // Creats a URLLoader and starts loading with the given |request|. |client|'s @@ -29,10 +28,6 @@ URLLoaderClient client, MutableNetworkTrafficAnnotationTag traffic_annotation); - // Loads the resource for the given |request| synchronously. - // |request_id| is for compatibility with the existing Chrome IPC. - [Sync] SyncLoad(int32 routing_id, - int32 request_id, - URLRequest request) - => (URLSyncLoadResult result); + // Connects a new pipe to this instance of the URLLoaderFactory interface. + Clone(URLLoaderFactory& factory); };
diff --git a/content/public/common/url_sync_load_result.typemap b/content/public/common/url_sync_load_result.typemap deleted file mode 100644 index 4fd35f5..0000000 --- a/content/public/common/url_sync_load_result.typemap +++ /dev/null
@@ -1,8 +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. - -mojom = "//content/public/common/url_loader_factory.mojom" -public_headers = [ "//content/public/common/resource_response.h" ] -traits_headers = [ "//content/common/resource_messages.h" ] -type_mappings = [ "content.mojom.URLSyncLoadResult=content::SyncLoadResult" ]
diff --git a/content/renderer/media/android/media_player_renderer_client_factory.cc b/content/renderer/media/android/media_player_renderer_client_factory.cc index cbd3a3f..c9f1d5b 100644 --- a/content/renderer/media/android/media_player_renderer_client_factory.cc +++ b/content/renderer/media/android/media_player_renderer_client_factory.cc
@@ -26,11 +26,12 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, media::AudioRendererSink* audio_renderer_sink, media::VideoRendererSink* video_renderer_sink, - const media::RequestOverlayInfoCB& request_overlay_info_cb) { + const media::RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) { std::unique_ptr<media::Renderer> renderer = mojo_renderer_factory_->CreateRenderer( media_task_runner, worker_task_runner, audio_renderer_sink, - video_renderer_sink, request_overlay_info_cb); + video_renderer_sink, request_overlay_info_cb, target_color_space); media::MojoRenderer* mojo_renderer = static_cast<media::MojoRenderer*>(renderer.release());
diff --git a/content/renderer/media/android/media_player_renderer_client_factory.h b/content/renderer/media/android/media_player_renderer_client_factory.h index dd24f70..a85f45f 100644 --- a/content/renderer/media/android/media_player_renderer_client_factory.h +++ b/content/renderer/media/android/media_player_renderer_client_factory.h
@@ -35,7 +35,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, media::AudioRendererSink* audio_renderer_sink, media::VideoRendererSink* video_renderer_sink, - const media::RequestOverlayInfoCB& request_surface_cb) override; + const media::RequestOverlayInfoCB& request_surface_cb, + const gfx::ColorSpace& target_color_space) override; // The MediaPlayerRenderer uses a Type::URL. media::MediaResource::Type GetRequiredMediaResourceType() override;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index ed8de4c..39dea4cb 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -334,10 +334,6 @@ static bool PreferCompositingToLCDText(CompositorDependencies* compositor_deps, float device_scale_factor) { - if (base::FeatureList::IsEnabled( - features::kDisablePreferCompositingToLCDTextOnLowEndAndroid) && - base::SysInfo::AmountOfPhysicalMemoryMB() <= 512) - return false; const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(switches::kDisablePreferCompositingToLCDText))
diff --git a/extensions/browser/api/lock_screen_data/data_item.cc b/extensions/browser/api/lock_screen_data/data_item.cc index 4b0779a6..6fc04b9 100644 --- a/extensions/browser/api/lock_screen_data/data_item.cc +++ b/extensions/browser/api/lock_screen_data/data_item.cc
@@ -13,6 +13,7 @@ #include "base/files/file_util.h" #include "base/location.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/sequenced_task_runner.h" #include "base/task_scheduler/post_task.h" #include "base/values.h" @@ -180,6 +181,12 @@ } base::Base64Encode(encrypted, &encrypted); + UMA_HISTOGRAM_COUNTS_10M("Apps.LockScreen.DataItemStorage.ClearTextItemSize", + data.size()); + + UMA_HISTOGRAM_COUNTS_10M("Apps.LockScreen.DataItemStorage.EncryptedItemSize", + encrypted.size()); + ValueStore::WriteResult write = store->Set(ValueStore::DEFAULTS, item_id, base::Value(std::move(encrypted)));
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_data_api.cc b/extensions/browser/api/lock_screen_data/lock_screen_data_api.cc index ad4fd781..1ad64e0 100644 --- a/extensions/browser/api/lock_screen_data/lock_screen_data_api.cc +++ b/extensions/browser/api/lock_screen_data/lock_screen_data_api.cc
@@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "base/metrics/histogram_macros.h" #include "extensions/browser/api/lock_screen_data/data_item.h" #include "extensions/browser/api/lock_screen_data/lock_screen_item_storage.h" #include "extensions/browser/api/lock_screen_data/operation_result.h" @@ -20,6 +21,7 @@ std::string GetErrorString(lock_screen_data::OperationResult result) { switch (result) { case lock_screen_data::OperationResult::kSuccess: + case lock_screen_data::OperationResult::kCount: NOTREACHED() << "Expected a failure code."; return "Unknown"; case lock_screen_data::OperationResult::kFailed: @@ -60,6 +62,10 @@ void LockScreenDataCreateFunction::OnDone( lock_screen_data::OperationResult result, const lock_screen_data::DataItem* item) { + UMA_HISTOGRAM_ENUMERATION( + "Apps.LockScreen.DataItemStorage.OperationResult.RegisterItem", result, + lock_screen_data::OperationResult::kCount); + if (result != lock_screen_data::OperationResult::kSuccess) { Respond(Error(GetErrorString(result))); return; @@ -124,6 +130,10 @@ void LockScreenDataGetContentFunction::OnDone( lock_screen_data::OperationResult result, std::unique_ptr<std::vector<char>> data) { + UMA_HISTOGRAM_ENUMERATION( + "Apps.LockScreen.DataItemStorage.OperationResult.ReadItem", result, + lock_screen_data::OperationResult::kCount); + if (result == lock_screen_data::OperationResult::kSuccess) { Respond(ArgumentList( api::lock_screen_data::GetContent::Results::Create(*data))); @@ -154,6 +164,10 @@ void LockScreenDataSetContentFunction::OnDone( lock_screen_data::OperationResult result) { + UMA_HISTOGRAM_ENUMERATION( + "Apps.LockScreen.DataItemStorage.OperationResult.WriteItem", result, + lock_screen_data::OperationResult::kCount); + if (result == lock_screen_data::OperationResult::kSuccess) { Respond(NoArguments()); return; @@ -182,6 +196,10 @@ void LockScreenDataDeleteFunction::OnDone( lock_screen_data::OperationResult result) { + UMA_HISTOGRAM_ENUMERATION( + "Apps.LockScreen.DataItemStorage.OperationResult.DeleteItem", result, + lock_screen_data::OperationResult::kCount); + if (result == lock_screen_data::OperationResult::kSuccess) { Respond(NoArguments()); return;
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc b/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc index 542af03..172d93b93 100644 --- a/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc +++ b/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc
@@ -10,6 +10,8 @@ #include "base/bind.h" #include "base/guid.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" +#include "base/time/default_tick_clock.h" #include "base/values.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -111,6 +113,7 @@ crypto_key_(crypto_key), local_state_(local_state), storage_root_(storage_root.Append(user_id_)), + tick_clock_(base::MakeUnique<base::DefaultTickClock>()), extension_registry_observer_(this), value_store_cache_(base::MakeUnique<LocalValueStoreCache>( new ValueStoreFactoryImpl(storage_root))), @@ -252,9 +255,10 @@ CreateDataItem(base::GenerateGUID(), extension_id, context_, value_store_cache_.get(), task_runner_.get(), crypto_key_); DataItem* item_ptr = item.get(); - item_ptr->Register(base::Bind( - &LockScreenItemStorage::OnItemRegistered, weak_ptr_factory_.GetWeakPtr(), - base::Passed(std::move(item)), extension_id, callback)); + item_ptr->Register(base::Bind(&LockScreenItemStorage::OnItemRegistered, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(std::move(item)), extension_id, + tick_clock_->NowTicks(), callback)); } void LockScreenItemStorage::GetAllForExtensionImpl( @@ -288,7 +292,9 @@ return; } - item->Write(data, callback); + item->Write(data, base::Bind(&LockScreenItemStorage::OnItemWritten, + weak_ptr_factory_.GetWeakPtr(), + tick_clock_->NowTicks(), callback)); } void LockScreenItemStorage::GetItemContentImpl(const std::string& extension_id, @@ -300,7 +306,9 @@ return; } - item->Read(callback); + item->Read(base::Bind(&LockScreenItemStorage::OnItemRead, + weak_ptr_factory_.GetWeakPtr(), tick_clock_->NowTicks(), + callback)); } void LockScreenItemStorage::DeleteItemImpl(const std::string& extension_id, @@ -313,14 +321,25 @@ } item->Delete(base::Bind(&LockScreenItemStorage::OnItemDeleted, - base::Unretained(this), extension_id, item_id, - callback)); + weak_ptr_factory_.GetWeakPtr(), extension_id, item_id, + tick_clock_->NowTicks(), callback)); } void LockScreenItemStorage::OnItemRegistered(std::unique_ptr<DataItem> item, const std::string& extension_id, + const base::TimeTicks& start_time, const CreateCallback& callback, OperationResult result) { + if (result == OperationResult::kSuccess) { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.OperationDuration.RegisterItem", + tick_clock_->NowTicks() - start_time); + } else { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.FailedOperationDuration.RegisterItem", + tick_clock_->NowTicks() - start_time); + } + if (result != OperationResult::kSuccess) { callback.Run(result, nullptr); return; @@ -339,10 +358,55 @@ callback.Run(OperationResult::kSuccess, item_ptr); } -void LockScreenItemStorage::OnItemDeleted(const std::string& extension_id, - const std::string& item_id, +void LockScreenItemStorage::OnItemWritten(const base::TimeTicks& start_time, const WriteCallback& callback, OperationResult result) { + if (result == OperationResult::kSuccess) { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.OperationDuration.WriteItem", + tick_clock_->NowTicks() - start_time); + } else { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.FailedOperationDuration.WriteItem", + tick_clock_->NowTicks() - start_time); + } + + callback.Run(result); +} + +void LockScreenItemStorage::OnItemRead( + const base::TimeTicks& start_time, + const ReadCallback& callback, + OperationResult result, + std::unique_ptr<std::vector<char>> data) { + if (result == OperationResult::kSuccess) { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.OperationDuration.ReadItem", + tick_clock_->NowTicks() - start_time); + } else { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.FailedOperationDuration.ReadItem", + tick_clock_->NowTicks() - start_time); + } + + callback.Run(result, std::move(data)); +} + +void LockScreenItemStorage::OnItemDeleted(const std::string& extension_id, + const std::string& item_id, + const base::TimeTicks& start_time, + const WriteCallback& callback, + OperationResult result) { + if (result == OperationResult::kSuccess) { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.OperationDuration.DeleteItem", + tick_clock_->NowTicks() - start_time); + } else { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.FailedOperationDuration.DeleteItem", + tick_clock_->NowTicks() - start_time); + } + data_item_cache_[extension_id].data_items.erase(item_id); { DictionaryPrefUpdate update(local_state_, kLockScreenDataPrefKey); @@ -372,11 +436,13 @@ GetRegisteredItems(extension_id, context_, value_store_cache_.get(), task_runner_.get(), base::Bind(&LockScreenItemStorage::OnGotExtensionItems, - weak_ptr_factory_.GetWeakPtr(), extension_id)); + weak_ptr_factory_.GetWeakPtr(), extension_id, + tick_clock_->NowTicks())); } void LockScreenItemStorage::OnGotExtensionItems( const std::string& extension_id, + const base::TimeTicks& start_time, OperationResult result, std::unique_ptr<base::DictionaryValue> items) { ExtensionDataMap::iterator data = data_item_cache_.find(extension_id); @@ -385,6 +451,21 @@ return; } + UMA_HISTOGRAM_ENUMERATION( + "Apps.LockScreen.DataItemStorage.OperationResult.GetRegisteredItems", + result, OperationResult::kCount); + + if (result == OperationResult::kSuccess) { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.OperationDuration.GetRegisteredItems", + tick_clock_->NowTicks() - start_time); + } else { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.DataItemStorage.FailedOperationDuration." + "GetRegisteredItems", + tick_clock_->NowTicks() - start_time); + } + if (result == OperationResult::kSuccess) { for (base::DictionaryValue::Iterator item_iter(*items); !item_iter.IsAtEnd(); item_iter.Advance()) { @@ -393,6 +474,11 @@ task_runner_.get(), crypto_key_); data->second.data_items.emplace(item_iter.key(), std::move(item)); } + + // Record number of registered items. + UMA_HISTOGRAM_COUNTS_100( + "Apps.LockScreen.DataItemStorage.RegisteredItemsCount", + data->second.data_items.size()); } DictionaryPrefUpdate update(local_state_, kLockScreenDataPrefKey);
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_item_storage.h b/extensions/browser/api/lock_screen_data/lock_screen_item_storage.h index 88768e4..6337b49 100644 --- a/extensions/browser/api/lock_screen_data/lock_screen_item_storage.h +++ b/extensions/browser/api/lock_screen_data/lock_screen_item_storage.h
@@ -23,6 +23,10 @@ class PrefRegistrySimple; class PrefService; +namespace base { +class TickClock; +} + namespace content { class BrowserContext; } @@ -199,6 +203,7 @@ // Callback for loading initial set of known data items for an extension. void OnGotExtensionItems(const std::string& extension_id, + const base::TimeTicks& start_time, OperationResult result, std::unique_ptr<base::DictionaryValue> items); @@ -206,13 +211,28 @@ // the item to the cached data item state, and invoked the callback. void OnItemRegistered(std::unique_ptr<DataItem> item, const std::string& extension_id, + const base::TimeTicks& start_time, const CreateCallback& callback, OperationResult result); + // Callback for data item write operation - it invokes the callback with the + // operation result. + void OnItemWritten(const base::TimeTicks& start_time, + const WriteCallback& callback, + OperationResult result); + + // Callback for data item read operation - it invokes the callback with the + // operation result. + void OnItemRead(const base::TimeTicks& start_time, + const ReadCallback& callback, + OperationResult result, + std::unique_ptr<std::vector<char>> data); + // Callback for item deletion operation. It removes the item from the cached // state and invokes the callback with the operation result. void OnItemDeleted(const std::string& extension_id, const std::string& item_id, + const base::TimeTicks& start_time, const WriteCallback& callback, OperationResult result); @@ -245,6 +265,8 @@ PrefService* local_state_; const base::FilePath storage_root_; + std::unique_ptr<base::TickClock> tick_clock_; + SessionLockedState session_locked_state_ = SessionLockedState::kUnknown; ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
diff --git a/extensions/browser/api/lock_screen_data/operation_result.h b/extensions/browser/api/lock_screen_data/operation_result.h index ff53663f..6ec2ef5 100644 --- a/extensions/browser/api/lock_screen_data/operation_result.h +++ b/extensions/browser/api/lock_screen_data/operation_result.h
@@ -10,14 +10,18 @@ // Enum containing possible results of data item operations exposed by // ItemStorage and DataItem. +// IMPORTANT: Used to report metrics. Should be kept in sync with +// LockScreenDataItemOperationResult histogram enum. The assigned values should +// not be changed. enum class OperationResult { - kSuccess, - kFailed, - kNotFound, - kUnknownExtension, - kAlreadyRegistered, - kInvalidKey, - kWrongKey, + kSuccess = 0, + kFailed = 1, + kNotFound = 2, + kUnknownExtension = 3, + kAlreadyRegistered = 4, + kInvalidKey = 5, + kWrongKey = 6, + kCount, }; } // namespace lock_screen_data
diff --git a/extensions/common/api/app_runtime.idl b/extensions/common/api/app_runtime.idl index a69bd5f5..3614ae7 100644 --- a/extensions/common/api/app_runtime.idl +++ b/extensions/common/api/app_runtime.idl
@@ -78,6 +78,11 @@ // is set as the lock screen enabled action handler by the user. // </p> [nodoc] boolean? isLockScreenAction; + + // Currently, used only with lock screen actions. If set, indicates whether + // the app should attempt to restore state from when the action was last + // handled. + [nodoc] boolean? restoreLastActionState; }; // Optional data for the launch. Either <code>items</code>, or
diff --git a/extensions/common/features/feature_provider.cc b/extensions/common/features/feature_provider.cc index 5e5b1451..2d75f82 100644 --- a/extensions/common/features/feature_provider.cc +++ b/extensions/common/features/feature_provider.cc
@@ -135,13 +135,12 @@ return nullptr; } -Feature* FeatureProvider::GetParent(Feature* feature) const { - CHECK(feature); - if (feature->no_parent()) +const Feature* FeatureProvider::GetParent(const Feature& feature) const { + if (feature.no_parent()) return nullptr; std::vector<base::StringPiece> split = base::SplitStringPiece( - feature->name(), ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + feature.name(), ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); if (split.size() < 2) return nullptr; split.pop_back();
diff --git a/extensions/common/features/feature_provider.h b/extensions/common/features/feature_provider.h index a6944231..c5cde10 100644 --- a/extensions/common/features/feature_provider.h +++ b/extensions/common/features/feature_provider.h
@@ -48,8 +48,8 @@ // Returns the feature with the specified name. Feature* GetFeature(const std::string& name) const; - // Returns the parent feature of |feature|, or NULL if there isn't one. - Feature* GetParent(Feature* feature) const; + // Returns the parent feature of |feature|, or null if there isn't one. + const Feature* GetParent(const Feature& feature) const; // Returns the features inside the |parent| namespace, recursively. std::vector<Feature*> GetChildren(const Feature& parent) const;
diff --git a/extensions/renderer/api_definitions_natives.cc b/extensions/renderer/api_definitions_natives.cc index 1db01d04..2f2d553 100644 --- a/extensions/renderer/api_definitions_natives.cc +++ b/extensions/renderer/api_definitions_natives.cc
@@ -25,7 +25,7 @@ std::vector<std::string> apis; const FeatureProvider* feature_provider = FeatureProvider::GetAPIFeatures(); for (const auto& map_entry : feature_provider->GetAllFeatures()) { - if (!feature_provider->GetParent(map_entry.second.get()) && + if (!feature_provider->GetParent(*map_entry.second) && context()->GetAvailability(map_entry.first).is_available()) { apis.push_back(map_entry.first); }
diff --git a/extensions/renderer/feature_cache.cc b/extensions/renderer/feature_cache.cc index 22cff87..df10bd2 100644 --- a/extensions/renderer/feature_cache.cc +++ b/extensions/renderer/feature_cache.cc
@@ -70,7 +70,7 @@ // TODO(devlin): Optimize this - instead of skipping child features and then // checking IsAnyFeatureAvailableToContext() (which checks child features), // we should just check all features directly. - if (api_feature_provider->GetParent(feature) != nullptr) + if (api_feature_provider->GetParent(*feature) != nullptr) continue; // Skip chrome.test if this isn't a test.
diff --git a/extensions/renderer/js_extension_bindings_system.cc b/extensions/renderer/js_extension_bindings_system.cc index 2e3b575..6fb206c 100644 --- a/extensions/renderer/js_extension_bindings_system.cc +++ b/extensions/renderer/js_extension_bindings_system.cc
@@ -199,7 +199,7 @@ // If this API has a parent feature (and isn't marked 'noparent'), // then this must be a function or event, so we should not register. - if (api_feature_provider->GetParent(map_entry.second.get()) != nullptr) + if (api_feature_provider->GetParent(*map_entry.second) != nullptr) continue; // Skip chrome.test if this isn't a test.
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc index b1c5987..52d790d2 100644 --- a/extensions/renderer/native_extension_bindings_system.cc +++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -340,7 +340,7 @@ // If this API has a parent feature (and isn't marked 'noparent'), // then this must be a function or event, so we should not register. - if (api_feature_provider->GetParent(iter->second.get()) != nullptr) + if (api_feature_provider->GetParent(*iter->second) != nullptr) continue; base::StringPiece binding_name =
diff --git a/ios/chrome/browser/payments/BUILD.gn b/ios/chrome/browser/payments/BUILD.gn index 262cf06..5463f9a 100644 --- a/ios/chrome/browser/payments/BUILD.gn +++ b/ios/chrome/browser/payments/BUILD.gn
@@ -15,8 +15,6 @@ "ios_payment_instrument_finder.mm", "ios_payment_request_cache_factory.h", "ios_payment_request_cache_factory.mm", - "itunes_json_request.cc", - "itunes_json_request.h", "origin_security_checker.h", "origin_security_checker.mm", "payment_request.h",
diff --git a/ios/chrome/browser/payments/itunes_json_request.cc b/ios/chrome/browser/payments/itunes_json_request.cc deleted file mode 100644 index ef7904b..0000000 --- a/ios/chrome/browser/payments/itunes_json_request.cc +++ /dev/null
@@ -1,117 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ios/chrome/browser/payments/itunes_json_request.h" - -#include <utility> - -#include "base/bind.h" -#include "base/json/json_reader.h" -#include "base/memory/ptr_util.h" -#include "base/values.h" -#include "net/base/load_flags.h" -#include "net/http/http_status_code.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_request_status.h" -#include "url/gurl.h" - -namespace payment_request_util { - -const char kBadResponse[] = "Bad iTunes Store search response"; -const char kITunesStoreLookupPrefix[] = "https://itunes.apple.com/lookup?"; -const char kITunesStoreSearchPrefix[] = "https://itunes.apple.com/search?"; - -ITunesJsonRequest::ITunesJsonRequest( - const Callback& callback, - net::URLRequestContextGetter* context_getter) - : callback_(callback), - context_getter_(context_getter), - weak_factory_(this) { - DCHECK(!callback_.is_null()); -} - -ITunesJsonRequest::~ITunesJsonRequest() {} - -void ITunesJsonRequest::Start(ITunesStoreRequestType request_type, - const std::string& request_query) { - Stop(); - - std::string complete_query; - switch (request_type) { - case LOOKUP: - complete_query = kITunesStoreLookupPrefix + request_query; - case SEARCH: - complete_query = kITunesStoreSearchPrefix + request_query; - } - - fetcher_ = - net::URLFetcher::Create(GURL(complete_query), net::URLFetcher::GET, this); - fetcher_->SetRequestContext(context_getter_); - fetcher_->SetLoadFlags(net::LOAD_MAYBE_USER_GESTURE | - net::LOAD_DO_NOT_SAVE_COOKIES | - net::LOAD_VERIFY_EV_CERT); - fetcher_->Start(); -} - -void ITunesJsonRequest::Stop() { - fetcher_.reset(); - weak_factory_.InvalidateWeakPtrs(); -} - -void ITunesJsonRequest::ParseJson( - const std::string& json, - const payment_request_util::ITunesJsonRequest::SuccessCallback& - success_callback, - const payment_request_util::ITunesJsonRequest::ErrorCallback& - error_callback) { - DCHECK(!success_callback.is_null()); - DCHECK(!error_callback.is_null()); - - base::JSONReader json_reader; - std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); - if (value) { - success_callback.Run(std::move(value)); - } else { - error_callback.Run(json_reader.GetErrorMessage()); - } -} - -void ITunesJsonRequest::OnJsonParseSuccess( - std::unique_ptr<base::Value> parsed_json) { - if (!parsed_json->IsType(base::Value::Type::DICTIONARY)) { - OnJsonParseError(kBadResponse); - return; - } - - callback_.Run(base::WrapUnique( - static_cast<base::DictionaryValue*>(parsed_json.release()))); -} - -void ITunesJsonRequest::OnJsonParseError(const std::string& error) { - callback_.Run(std::unique_ptr<base::DictionaryValue>()); -} - -void ITunesJsonRequest::OnURLFetchComplete(const net::URLFetcher* source) { - CHECK_EQ(fetcher_.get(), source); - - std::unique_ptr<net::URLFetcher> fetcher(std::move(fetcher_)); - - if (!fetcher->GetStatus().is_success() || - fetcher->GetResponseCode() != net::HTTP_OK) { - OnJsonParseError(kBadResponse); - return; - } - - std::string json_data; - fetcher->GetResponseAsString(&json_data); - - // The parser will call us back via one of the callbacks. - ParseJson(json_data, - base::Bind(&ITunesJsonRequest::OnJsonParseSuccess, - weak_factory_.GetWeakPtr()), - base::Bind(&ITunesJsonRequest::OnJsonParseError, - weak_factory_.GetWeakPtr())); -} - -} // namespace payment_request_util
diff --git a/ios/chrome/browser/payments/itunes_json_request.h b/ios/chrome/browser/payments/itunes_json_request.h deleted file mode 100644 index fbae57f..0000000 --- a/ios/chrome/browser/payments/itunes_json_request.h +++ /dev/null
@@ -1,80 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_PAYMENTS_ITUNES_JSON_REQUEST_H_ -#define IOS_CHROME_BROWSER_PAYMENTS_ITUNES_JSON_REQUEST_H_ - -#include <memory> -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "net/url_request/url_fetcher_delegate.h" - -namespace base { -class DictionaryValue; -class Value; -} // namespace base - -namespace net { -class URLFetcher; -class URLRequestContextGetter; -} // namespace net - -namespace payment_request_util { - -// A class that fetches a JSON formatted response from the iTunes Store using -// the iTunes Search API and a basic JSON parser to parse the response as a -// DictionaryValue. -class ITunesJsonRequest : public net::URLFetcherDelegate { - public: - // Callback to pass back the parsed json dictionary returned from iTunes. - // Invoked with NULL if there is an error. - typedef base::Callback<void(std::unique_ptr<base::DictionaryValue>)> Callback; - - ITunesJsonRequest(const Callback& callback, - net::URLRequestContextGetter* context_getter); - ~ITunesJsonRequest() override; - - // Used to express the type of request. Please view the following for info: - // https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/ - enum ITunesStoreRequestType { - LOOKUP, - SEARCH, - }; - - // Starts to fetch results for the given |request_type| and |request_query|. - void Start(ITunesStoreRequestType request_type, - const std::string& request_query); - void Stop(); - - private: - // Callbacks for JSON parsing. - typedef base::Callback<void(std::unique_ptr<base::Value> result)> - SuccessCallback; - typedef base::Callback<void(const std::string& error)> ErrorCallback; - - void ParseJson(const std::string& raw_json_string, - const SuccessCallback& success_callback, - const ErrorCallback& error_callback); - - void OnJsonParseSuccess(std::unique_ptr<base::Value> parsed_json); - void OnJsonParseError(const std::string& error); - - // net::URLFetcherDelegate overrides: - void OnURLFetchComplete(const net::URLFetcher* source) override; - - Callback callback_; - net::URLRequestContextGetter* context_getter_; - - std::unique_ptr<net::URLFetcher> fetcher_; - base::WeakPtrFactory<ITunesJsonRequest> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ITunesJsonRequest); -}; - -} // namespace payment_request_util - -#endif // IOS_CHROME_BROWSER_PAYMENTS_ITUNES_JSON_REQUEST_H_
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn index b5f59f7..ff86093b 100644 --- a/ios/chrome/browser/web/BUILD.gn +++ b/ios/chrome/browser/web/BUILD.gn
@@ -84,6 +84,7 @@ "//ios/web/public/test", "//ios/web/public/test/fakes", "//testing/gtest", + "//third_party/ocmock", "//ui/base:base", "//url:url", ]
diff --git a/ios/chrome/browser/web/sad_tab_tab_helper_unittest.mm b/ios/chrome/browser/web/sad_tab_tab_helper_unittest.mm index 59b31e4..487e670 100644 --- a/ios/chrome/browser/web/sad_tab_tab_helper_unittest.mm +++ b/ios/chrome/browser/web/sad_tab_tab_helper_unittest.mm
@@ -9,6 +9,7 @@ #import "ios/web/public/web_state/ui/crw_generic_content_view.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -26,20 +27,19 @@ class SadTabTabHelperTest : public PlatformTest { protected: - SadTabTabHelperTest() { SadTabTabHelper::CreateForWebState(&web_state_); } + SadTabTabHelperTest() : application_(OCMClassMock([UIApplication class])) { + SadTabTabHelper::CreateForWebState(&web_state_); + OCMStub([application_ sharedApplication]).andReturn(application_); + } + ~SadTabTabHelperTest() override { [application_ stopMocking]; } web::TestWebState web_state_; + id application_; }; -// TODO(crbug.com/753327): those tests are consistently failing on devices on -// the bots. Remove once they have been fixed. -#if TARGET_OS_SIMULATOR -#define DISABLED_ON_DEVICE(NAME) NAME -#else -#define DISABLED_ON_DEVICE(NAME) DISABLED_##NAME -#endif - // Tests that SadTab is not presented for not shown web states. -TEST_F(SadTabTabHelperTest, DISABLED_ON_DEVICE(NotPresented)) { +TEST_F(SadTabTabHelperTest, NotPresented) { + OCMStub([application_ applicationState]).andReturn(UIApplicationStateActive); + // WebState should not have presented a transient content view. EXPECT_FALSE(web_state_.GetTransientContentView()); @@ -49,8 +49,40 @@ EXPECT_FALSE(web_state_.GetTransientContentView()); } +// Tests that SadTab is not presented if app is in background. +TEST_F(SadTabTabHelperTest, AppInBackground) { + OCMStub([application_ applicationState]) + .andReturn(UIApplicationStateBackground); + web_state_.WasShown(); + + // WebState should not have presented a transient content view. + EXPECT_FALSE(web_state_.GetTransientContentView()); + + // Helper should get notified of render process failure, + // but Sad Tab should not be presented, because application is backgrounded. + web_state_.OnRenderProcessGone(); + EXPECT_FALSE(web_state_.GetTransientContentView()); +} + +// Tests that SadTab is not presented if app is in inactive. +TEST_F(SadTabTabHelperTest, AppIsInactive) { + OCMStub([application_ applicationState]) + .andReturn(UIApplicationStateInactive); + web_state_.WasShown(); + + // WebState should not have presented a transient content view. + EXPECT_FALSE(web_state_.GetTransientContentView()); + + // Helper should get notified of render process failure, + // but Sad Tab should not be presented, because application is inactive. + web_state_.OnRenderProcessGone(); + EXPECT_FALSE(web_state_.GetTransientContentView()); +} + // Tests that SadTab is presented for shown web states. -TEST_F(SadTabTabHelperTest, DISABLED_ON_DEVICE(Presented)) { +TEST_F(SadTabTabHelperTest, Presented) { + OCMStub([application_ applicationState]).andReturn(UIApplicationStateActive); + web_state_.WasShown(); // WebState should not have presented a transient content view. @@ -62,7 +94,8 @@ } // Tests that repeated failures generate the correct UI. -TEST_F(SadTabTabHelperTest, DISABLED_ON_DEVICE(RepeatedFailuresShowCorrectUI)) { +TEST_F(SadTabTabHelperTest, RepeatedFailuresShowCorrectUI) { + OCMStub([application_ applicationState]).andReturn(UIApplicationStateActive); web_state_.WasShown(); // Helper should get notified of render process failure. @@ -85,7 +118,9 @@ } // Tests that repeated failures can time out, and return to the RELOAD UI. -TEST_F(SadTabTabHelperTest, DISABLED_ON_DEVICE(FailureInterval)) { +TEST_F(SadTabTabHelperTest, FailureInterval) { + OCMStub([application_ applicationState]).andReturn(UIApplicationStateActive); + // N.B. The test fixture web_state_ is not used for this test as a custom // |repeat_failure_interval| is required. web::TestWebState web_state;
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc index 90bd2cc..a905dc8 100644 --- a/media/audio/audio_output_controller.cc +++ b/media/audio/audio_output_controller.cc
@@ -48,11 +48,12 @@ params.sample_rate(), TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)), on_more_io_data_called_(0), - ignore_errors_during_stop_close_(false) { + weak_factory_for_errors_(this) { DCHECK(audio_manager); DCHECK(handler_); DCHECK(sync_reader_); DCHECK(message_loop_.get()); + weak_this_for_errors_ = weak_factory_for_errors_.GetWeakPtr(); } AudioOutputController::~AudioOutputController() { @@ -341,15 +342,14 @@ } void AudioOutputController::OnError() { - { - base::AutoLock auto_lock(error_lock_); - if (ignore_errors_during_stop_close_) - return; - } - - // Handle error on the audio controller thread. - message_loop_->PostTask( - FROM_HERE, base::BindOnce(&AudioOutputController::DoReportError, this)); + // Handle error on the audio controller thread. We defer errors for one + // second in case they are the result of a device change; delay chosen to + // exceed duration of device changes which take a few hundred milliseconds. + message_loop_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&AudioOutputController::DoReportError, + weak_this_for_errors_), + base::TimeDelta::FromSeconds(1)); } void AudioOutputController::DoStopCloseAndClearStream() { @@ -357,10 +357,9 @@ // Allow calling unconditionally and bail if we don't have a stream_ to close. if (stream_) { - { - base::AutoLock auto_lock(error_lock_); - ignore_errors_during_stop_close_ = true; - } + // Ensure no errors will be delivered while we cycle streams and any that + // occurred immediately prior to the device change are dropped. + weak_factory_for_errors_.InvalidateWeakPtrs(); // De-register from state change callbacks if stream_ was created via // AudioManager. @@ -374,8 +373,8 @@ diverting_to_stream_ = NULL; stream_ = NULL; - // Since the stream is no longer running, no lock is necessary. - ignore_errors_during_stop_close_ = false; + // Since the stream is stopped, we can now update |weak_this_for_errors_|. + weak_this_for_errors_ = weak_factory_for_errors_.GetWeakPtr(); } state_ = kEmpty;
diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h index 19fba1f..0b19326 100644 --- a/media/audio/audio_output_controller.h +++ b/media/audio/audio_output_controller.h
@@ -15,6 +15,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/timer/timer.h" #include "build/build_config.h" @@ -266,15 +267,16 @@ base::AtomicRefCount on_more_io_data_called_; std::unique_ptr<base::OneShotTimer> wedge_timer_; - // Flag which indicates errors received during Stop/Close should be ignored. - // These errors are generally harmless since a fresh stream is about to be - // recreated, but if forwarded, renderer side clients may consider them - // catastrophic and abort their operations. + // WeakPtrFactory and WeakPtr for ignoring errors which occur arround a + // Stop/Close cycle; e.g., device changes. These errors are generally harmless + // since a fresh stream is about to be recreated, but if forwarded, renderer + // side clients may consider them catastrophic and abort their operations. // - // If |stream_| is started then |ignore_errors_during_stop_close_| must only - // be accessed while |error_lock_| is held. - bool ignore_errors_during_stop_close_; - base::Lock error_lock_; + // |weak_this_for_errors_| must not be reassigned while a stream is active or + // we'll have concurrent access from different threads. Only the factory may + // be used to invalidate WeakPtrs while the stream is active. + base::WeakPtr<AudioOutputController> weak_this_for_errors_; + base::WeakPtrFactory<AudioOutputController> weak_factory_for_errors_; DISALLOW_COPY_AND_ASSIGN(AudioOutputController); };
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc index b61b48f..a2f03f31 100644 --- a/media/audio/audio_output_controller_unittest.cc +++ b/media/audio/audio_output_controller_unittest.cc
@@ -115,6 +115,7 @@ AudioOutputControllerTest() : audio_manager_(AudioManager::CreateForTesting( base::MakeUnique<TestAudioThread>())) { + EXPECT_CALL(mock_event_handler_, OnLog(_)).Times(testing::AnyNumber()); base::RunLoop().RunUntilIdle(); } @@ -256,6 +257,13 @@ run_loop.Run(); } + void SimulateErrorThenDeviceChange() { + audio_manager_->GetTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&AudioOutputControllerTest::TriggerErrorThenDeviceChange, + base::Unretained(this))); + } + // These help make test sequences more readable. void DivertNeverPlaying() { Divert(false, 0); } void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); } @@ -264,6 +272,18 @@ void RevertWhilePlaying() { Revert(true); } private: + void TriggerErrorThenDeviceChange() { + DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); + + // Errors should be deferred; the device change should ensure it's dropped. + EXPECT_CALL(mock_event_handler_, OnControllerError()).Times(0); + controller_->OnError(); + + EXPECT_CALL(mock_event_handler_, OnControllerPlaying()); + EXPECT_CALL(mock_event_handler_, OnControllerPaused()).Times(0); + controller_->OnDeviceChange(); + } + base::TestMessageLoop message_loop_; std::unique_ptr<AudioManager> audio_manager_; MockAudioOutputControllerEventHandler mock_event_handler_; @@ -308,6 +328,13 @@ Close(); } +TEST_F(AudioOutputControllerTest, PlayDeviceChangeError) { + Create(kSamplesPerPacket); + Play(); + SimulateErrorThenDeviceChange(); + Close(); +} + TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) { Create(kSamplesPerPacket); Play();
diff --git a/media/base/renderer_factory.h b/media/base/renderer_factory.h index f7475e27..d362347 100644 --- a/media/base/renderer_factory.h +++ b/media/base/renderer_factory.h
@@ -13,6 +13,7 @@ #include "media/base/media_resource.h" #include "media/base/overlay_info.h" #include "media/base/renderer.h" +#include "ui/gfx/color_space.h" namespace base { class SingleThreadTaskRunner; @@ -40,7 +41,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, AudioRendererSink* audio_renderer_sink, VideoRendererSink* video_renderer_sink, - const RequestOverlayInfoCB& request_overlay_info_cb) = 0; + const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) = 0; // Returns the MediaResource::Type that should be used with the renderers // created by this factory.
diff --git a/media/base/renderer_factory_selector_unittest.cc b/media/base/renderer_factory_selector_unittest.cc index e435fa0e..845b98a 100644 --- a/media/base/renderer_factory_selector_unittest.cc +++ b/media/base/renderer_factory_selector_unittest.cc
@@ -26,7 +26,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, AudioRendererSink* audio_renderer_sink, VideoRendererSink* video_renderer_sink, - const RequestOverlayInfoCB& request_overlay_info_cb) override { + const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) override { return std::unique_ptr<Renderer>(); }
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 0c94165..68b41bce 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -1969,7 +1969,7 @@ #endif return renderer_factory_selector_->GetCurrentFactory()->CreateRenderer( media_task_runner_, worker_task_runner_, audio_source_provider_.get(), - compositor_, request_overlay_info_cb); + compositor_, request_overlay_info_cb, client_->TargetColorSpace()); } void WebMediaPlayerImpl::StartPipeline() { @@ -2021,6 +2021,8 @@ chunk_demuxer_ = new ChunkDemuxer( BindToCurrentLoop( base::Bind(&WebMediaPlayerImpl::OnDemuxerOpened, AsWeakPtr())), + BindToCurrentLoop( + base::Bind(&WebMediaPlayerImpl::OnProgress, AsWeakPtr())), encrypted_media_init_data_cb, media_log_.get()); demuxer_.reset(chunk_demuxer_);
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index d6054dd..1d5ecc3 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -484,7 +484,8 @@ // handling a src= or MSE based playback. void RecordUnderflowDuration(base::TimeDelta duration); - // Called by the data source when loading progresses. + // Called by the data source (for src=) or demuxer (for mse) when loading + // progresses. // Can be called quite often. void OnProgress();
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index ad913a9..291e4b2 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc
@@ -424,12 +424,14 @@ ChunkDemuxer::ChunkDemuxer( const base::Closure& open_cb, + const base::Closure& progress_cb, const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, MediaLog* media_log) : state_(WAITING_FOR_INIT), cancel_next_seek_(false), host_(NULL), open_cb_(open_cb), + progress_cb_(progress_cb), encrypted_media_init_data_cb_(encrypted_media_init_data_cb), enable_text_(false), media_log_(media_log), @@ -884,6 +886,7 @@ } host_->OnBufferedTimeRangesChanged(ranges); + progress_cb_.Run(); return true; }
diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index 53f44d2..ab1af1d3 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h
@@ -176,11 +176,13 @@ }; // |open_cb| Run when Initialize() is called to signal that the demuxer - // is ready to receive media data via AppenData(). + // is ready to receive media data via AppendData(). + // |progress_cb| Run each time data is appended. // |encrypted_media_init_data_cb| Run when the demuxer determines that an // encryption key is needed to decrypt the content. // |media_log| Used to report content and engine debug messages. ChunkDemuxer(const base::Closure& open_cb, + const base::Closure& progress_cb, const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, MediaLog* media_log); ~ChunkDemuxer() override; @@ -409,6 +411,7 @@ DemuxerHost* host_; base::Closure open_cb_; + base::Closure progress_cb_; EncryptedMediaInitDataCB encrypted_media_init_data_cb_; bool enable_text_;
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc index 7da9c5c..6c056b02 100644 --- a/media/filters/chunk_demuxer_unittest.cc +++ b/media/filters/chunk_demuxer_unittest.cc
@@ -10,6 +10,7 @@ #include <utility> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/command_line.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" @@ -178,7 +179,9 @@ return GenerateCluster(46, 66, 5); } - ChunkDemuxerTest() : append_window_end_for_next_append_(kInfiniteDuration) { + ChunkDemuxerTest() + : did_progress_(false), + append_window_end_for_next_append_(kInfiniteDuration) { init_segment_received_cb_ = base::Bind( &ChunkDemuxerTest::InitSegmentReceived, base::Unretained(this)); CreateNewDemuxer(); @@ -187,10 +190,12 @@ void CreateNewDemuxer() { base::Closure open_cb = base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this)); + base::Closure progress_cb = + base::Bind(&ChunkDemuxerTest::OnProgress, base::Unretained(this)); Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind( &ChunkDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this)); - demuxer_.reset( - new ChunkDemuxer(open_cb, encrypted_media_init_data_cb, &media_log_)); + demuxer_.reset(new ChunkDemuxer(open_cb, progress_cb, + encrypted_media_init_data_cb, &media_log_)); } virtual ~ChunkDemuxerTest() { @@ -1279,6 +1284,14 @@ MOCK_METHOD1(InitSegmentReceivedMock, void(std::unique_ptr<MediaTracks>&)); MOCK_METHOD1(OnParseWarningMock, void(const SourceBufferParseWarning)); + void OnProgress() { did_progress_ = true; } + + bool DidProgress() { + bool result = did_progress_; + did_progress_ = false; + return result; + } + void Seek(base::TimeDelta seek_time) { demuxer_->StartWaitingForSeek(seek_time); demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK)); @@ -1307,6 +1320,8 @@ std::unique_ptr<ChunkDemuxer> demuxer_; Demuxer::MediaTracksUpdatedCB init_segment_received_cb_; + bool did_progress_; + base::TimeDelta append_window_start_for_next_append_; base::TimeDelta append_window_end_for_next_append_; @@ -2153,7 +2168,9 @@ ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO); EXPECT_CALL(*this, InitSegmentReceivedMock(_)); + EXPECT_FALSE(DidProgress()); ASSERT_TRUE(AppendDataInPieces(buffer.get(), buffer_size)); + EXPECT_TRUE(DidProgress()); GenerateExpectedReads(0, 9); }
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc index f3c920d..9f80c99 100644 --- a/media/filters/gpu_video_decoder.cc +++ b/media/filters/gpu_video_decoder.cc
@@ -106,10 +106,12 @@ GpuVideoDecoder::GpuVideoDecoder( GpuVideoAcceleratorFactories* factories, const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space, MediaLog* media_log) : needs_bitstream_conversion_(false), factories_(factories), request_overlay_info_cb_(request_overlay_info_cb), + target_color_space_(target_color_space), media_log_(media_log), vda_initialized_(false), state_(kNormal), @@ -360,7 +362,8 @@ vda_config.encryption_scheme = config_.encryption_scheme(); vda_config.is_deferred_initialization_allowed = true; vda_config.initial_expected_coded_size = config_.coded_size(); - vda_config.color_space = config_.color_space_info(); + vda_config.container_color_space = config_.color_space_info(); + vda_config.target_color_space = target_color_space_; #if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS) // We pass the SPS and PPS on Android because it lets us initialize
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h index 4bc69d5..d8f09c9 100644 --- a/media/filters/gpu_video_decoder.h +++ b/media/filters/gpu_video_decoder.h
@@ -51,6 +51,7 @@ public: GpuVideoDecoder(GpuVideoAcceleratorFactories* factories, const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space, MediaLog* media_log); ~GpuVideoDecoder() override; @@ -157,6 +158,8 @@ // normal video frames and not render them to a surface. RequestOverlayInfoCB request_overlay_info_cb_; + gfx::ColorSpace target_color_space_; + MediaLog* media_log_; // Populated during Initialize() (on success) and unchanged until an error
diff --git a/media/gpu/dxva_video_decode_accelerator_win.cc b/media/gpu/dxva_video_decode_accelerator_win.cc index 29f9d7a3..25853b4 100644 --- a/media/gpu/dxva_video_decode_accelerator_win.cc +++ b/media/gpu/dxva_video_decode_accelerator_win.cc
@@ -531,7 +531,7 @@ // Unfortunately, the profile is currently unreliable for // VP9 (crbug.com/592074) so also try to use fp16 if HDR is on. - if (base::FeatureList::IsEnabled(features::kHighDynamicRange)) { + if (config_.target_color_space.IsHDR()) { use_fp16_ = true; } @@ -2181,7 +2181,7 @@ // frame then we are done. VideoColorSpace color_space = config_change_detector_->current_color_space(); if (color_space == VideoColorSpace()) - color_space = config_.color_space; + color_space = config_.container_color_space; DoDecode(color_space.ToGfxColorSpace()); if (OutputSamplesPresent()) return; @@ -2233,7 +2233,7 @@ VideoColorSpace color_space = config_change_detector_->current_color_space(); if (color_space == VideoColorSpace()) - color_space = config_.color_space; + color_space = config_.container_color_space; if (!inputs_before_decode_) { TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding", @@ -2837,8 +2837,7 @@ base::win::ScopedComPtr<ID3D11VideoContext1> video_context1; HRESULT hr = video_context_.CopyTo(video_context1.GetAddressOf()); if (SUCCEEDED(hr)) { - if (use_fp16_ && - base::FeatureList::IsEnabled(features::kHighDynamicRange) && + if (use_fp16_ && config_.target_color_space.IsHDR() && color_space.IsHDR()) { // Note, we only use the SCRGBLinear output color space when // the input is PQ, because nvidia drivers will not convert
diff --git a/media/gpu/ipc/common/media_param_traits_macros.h b/media/gpu/ipc/common/media_param_traits_macros.h index 85e7211..5211cd9 100644 --- a/media/gpu/ipc/common/media_param_traits_macros.h +++ b/media/gpu/ipc/common/media_param_traits_macros.h
@@ -31,7 +31,8 @@ IPC_STRUCT_TRAITS_MEMBER(supported_output_formats) IPC_STRUCT_TRAITS_MEMBER(sps) IPC_STRUCT_TRAITS_MEMBER(pps) - IPC_STRUCT_TRAITS_MEMBER(color_space) + IPC_STRUCT_TRAITS_MEMBER(container_color_space) + IPC_STRUCT_TRAITS_MEMBER(target_color_space) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(media::CreateVideoEncoderParams)
diff --git a/media/mojo/clients/mojo_renderer_factory.cc b/media/mojo/clients/mojo_renderer_factory.cc index a9ae33b..321459c 100644 --- a/media/mojo/clients/mojo_renderer_factory.cc +++ b/media/mojo/clients/mojo_renderer_factory.cc
@@ -40,7 +40,8 @@ const scoped_refptr<base::TaskRunner>& /* worker_task_runner */, AudioRendererSink* /* audio_renderer_sink */, VideoRendererSink* video_renderer_sink, - const RequestOverlayInfoCB& /* request_overlay_info_cb */) { + const RequestOverlayInfoCB& /* request_overlay_info_cb */, + const gfx::ColorSpace& /* target_color_space */) { std::unique_ptr<VideoOverlayFactory> overlay_factory; // |get_gpu_factories_cb_| can be null in the HLS/MediaPlayerRenderer case,
diff --git a/media/mojo/clients/mojo_renderer_factory.h b/media/mojo/clients/mojo_renderer_factory.h index c4a4cd2..bf06a614 100644 --- a/media/mojo/clients/mojo_renderer_factory.h +++ b/media/mojo/clients/mojo_renderer_factory.h
@@ -43,7 +43,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, AudioRendererSink* audio_renderer_sink, VideoRendererSink* video_renderer_sink, - const RequestOverlayInfoCB& request_overlay_info_cb) final; + const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) final; private: mojom::RendererPtr GetRendererPtr();
diff --git a/media/mojo/services/interface_factory_impl.cc b/media/mojo/services/interface_factory_impl.cc index 5d08caae..426600a 100644 --- a/media/mojo/services/interface_factory_impl.cc +++ b/media/mojo/services/interface_factory_impl.cc
@@ -102,9 +102,11 @@ auto audio_sink = mojo_media_client_->CreateAudioRendererSink(audio_device_id); auto video_sink = mojo_media_client_->CreateVideoRendererSink(task_runner); + // TODO(hubbe): Find out if gfx::ColorSpace() is correct for the + // target_color_space. auto renderer = renderer_factory->CreateRenderer( task_runner, task_runner, audio_sink.get(), video_sink.get(), - RequestOverlayInfoCB()); + RequestOverlayInfoCB(), gfx::ColorSpace()); if (!renderer) { LOG(ERROR) << "Renderer creation failed."; return;
diff --git a/media/remoting/courier_renderer_factory.cc b/media/remoting/courier_renderer_factory.cc index 27453a1..0581fa2d 100644 --- a/media/remoting/courier_renderer_factory.cc +++ b/media/remoting/courier_renderer_factory.cc
@@ -28,7 +28,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, AudioRendererSink* audio_renderer_sink, VideoRendererSink* video_renderer_sink, - const RequestOverlayInfoCB& request_overlay_info_cb) { + const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) { DCHECK(IsRemotingActive()); #if !defined(ENABLE_MEDIA_REMOTING_RPC) return nullptr;
diff --git a/media/remoting/courier_renderer_factory.h b/media/remoting/courier_renderer_factory.h index b2fa59d..3c17b0a 100644 --- a/media/remoting/courier_renderer_factory.h +++ b/media/remoting/courier_renderer_factory.h
@@ -23,7 +23,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, AudioRendererSink* audio_renderer_sink, VideoRendererSink* video_renderer_sink, - const RequestOverlayInfoCB& request_overlay_info_cb) override; + const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) override; // Returns whether remote rendering has started, based off of |controller_|. // Called by RendererFactorySelector to determine when to create a
diff --git a/media/renderers/default_renderer_factory.cc b/media/renderers/default_renderer_factory.cc index 814c5fbd..32d5c23 100644 --- a/media/renderers/default_renderer_factory.cc +++ b/media/renderers/default_renderer_factory.cc
@@ -65,6 +65,7 @@ DefaultRendererFactory::CreateVideoDecoders( const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space, GpuVideoAcceleratorFactories* gpu_factories) { // Create our video decoders and renderer. std::vector<std::unique_ptr<VideoDecoder>> video_decoders; @@ -82,7 +83,8 @@ media_log_, &video_decoders); } video_decoders.push_back(base::MakeUnique<GpuVideoDecoder>( - gpu_factories, request_overlay_info_cb, media_log_)); + gpu_factories, request_overlay_info_cb, target_color_space, + media_log_)); } #if !defined(MEDIA_DISABLE_LIBVPX) @@ -101,7 +103,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, AudioRendererSink* audio_renderer_sink, VideoRendererSink* video_renderer_sink, - const RequestOverlayInfoCB& request_overlay_info_cb) { + const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) { DCHECK(audio_renderer_sink); std::unique_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl( @@ -130,7 +133,7 @@ // finishes. base::Bind(&DefaultRendererFactory::CreateVideoDecoders, base::Unretained(this), media_task_runner, - request_overlay_info_cb, gpu_factories), + request_overlay_info_cb, target_color_space, gpu_factories), true, gpu_factories, media_log_)); return base::MakeUnique<RendererImpl>(
diff --git a/media/renderers/default_renderer_factory.h b/media/renderers/default_renderer_factory.h index f146beb9..fb05edcb 100644 --- a/media/renderers/default_renderer_factory.h +++ b/media/renderers/default_renderer_factory.h
@@ -43,7 +43,8 @@ const scoped_refptr<base::TaskRunner>& worker_task_runner, AudioRendererSink* audio_renderer_sink, VideoRendererSink* video_renderer_sink, - const RequestOverlayInfoCB& request_overlay_info_cb) final; + const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space) final; private: std::vector<std::unique_ptr<AudioDecoder>> CreateAudioDecoders( @@ -51,6 +52,7 @@ std::vector<std::unique_ptr<VideoDecoder>> CreateVideoDecoders( const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, const RequestOverlayInfoCB& request_overlay_info_cb, + const gfx::ColorSpace& target_color_space, GpuVideoAcceleratorFactories* gpu_factories); MediaLog* media_log_;
diff --git a/media/test/mock_media_source.cc b/media/test/mock_media_source.cc index e3b1a289..c8d16c5a 100644 --- a/media/test/mock_media_source.cc +++ b/media/test/mock_media_source.cc
@@ -4,6 +4,8 @@ #include "media/test/mock_media_source.h" +#include "base/bind.h" +#include "base/bind_helpers.h" #include "base/threading/thread_task_runner_handle.h" #include "media/base/test_data_util.h" #include "media/base/timestamp_constants.h" @@ -20,6 +22,7 @@ mimetype_(mimetype), chunk_demuxer_(new ChunkDemuxer( base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)), + base::Bind(&base::DoNothing), base::Bind(&MockMediaSource::OnEncryptedMediaInitData, base::Unretained(this)), &media_log_)),
diff --git a/media/video/video_decode_accelerator.h b/media/video/video_decode_accelerator.h index b37a85e..173fe0d 100644 --- a/media/video/video_decode_accelerator.h +++ b/media/video/video_decode_accelerator.h
@@ -21,6 +21,7 @@ #include "media/base/surface_manager.h" #include "media/base/video_decoder_config.h" #include "media/video/picture.h" +#include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_memory_buffer.h" @@ -171,7 +172,12 @@ std::vector<uint8_t> pps; // Color space specified by the container. - VideoColorSpace color_space; + VideoColorSpace container_color_space; + + // Target color space. + // Used as a hint to the decoder. Outputting VideoFrames in this color space + // may avoid extra conversion steps. + gfx::ColorSpace target_color_space; }; // Interface for collaborating with picture interface to provide memory for
diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc index 2e7b678..cbbf3c35 100644 --- a/net/dns/dns_session.cc +++ b/net/dns/dns_session.cc
@@ -234,9 +234,15 @@ std::abs(current_error.ToInternalValue())); deviation += (abs_error - deviation) / 4; // * delta + // RTT values shouldn't be less than 0, but it shouldn't cause a crash if they + // are anyway, so clip to 0. See https://crbug.com/753568. + int32_t rtt_ms = rtt.InMilliseconds(); + if (rtt_ms < 0) + rtt_ms = 0; + // Histogram-based method. server_stats_[server_index]->rtt_histogram->Accumulate( - static_cast<base::HistogramBase::Sample>(rtt.InMilliseconds()), 1); + static_cast<base::HistogramBase::Sample>(rtt_ms), 1); } void DnsSession::RecordLostPacket(unsigned server_index, int attempt) {
diff --git a/net/dns/dns_session_unittest.cc b/net/dns/dns_session_unittest.cc index d228556..8c44440 100644 --- a/net/dns/dns_session_unittest.cc +++ b/net/dns/dns_session_unittest.cc
@@ -244,6 +244,13 @@ EXPECT_EQ(timeout.InMilliseconds(), config_.timeout.InMilliseconds()); } +// Ensures that reported negative RTT values don't cause a crash. Regression +// test for https://crbug.com/753568. +TEST_F(DnsSessionTest, NegativeRtt) { + Initialize(2); + session_->RecordRTT(0, base::TimeDelta::FromMilliseconds(-1)); +} + } // namespace } // namespace net
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index d18447d..7cf9329 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -203,6 +203,7 @@ params.quic_race_cert_verification, params.quic_estimate_initial_rtt, params.quic_connection_options, + params.quic_client_connection_options, params.enable_token_binding), spdy_session_pool_(context.host_resolver, context.ssl_config_service,
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 5cd08da9..906579d7 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -125,6 +125,9 @@ std::set<HostPortPair> origins_to_force_quic_on; // Set of QUIC tags to send in the handshake's connection options. QuicTagVector quic_connection_options; + // Set of QUIC tags to send in the handshake's connection options that only + // affect the client. + QuicTagVector quic_client_connection_options; // Active QUIC experiments
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc index d2a17ba..9b04b4fd 100644 --- a/net/quic/chromium/quic_chromium_client_session.cc +++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -1367,7 +1367,7 @@ int QuicChromiumClientSession::HandleWriteError( int error_code, - scoped_refptr<StringIOBuffer> packet) { + scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> packet) { if (stream_factory_ == nullptr || !stream_factory_->migrate_sessions_on_network_change()) { return error_code; @@ -1386,7 +1386,7 @@ // Store packet in the session since the actual migration and packet rewrite // can happen via this posted task or via an async network notification. - packet_ = packet; + packet_ = std::move(packet); migration_pending_ = true; // Cause the packet writer to return ERR_IO_PENDING and block so @@ -1446,18 +1446,13 @@ return; } - // Set packet_ to null first before calling WritePacketToSocket since - // that method may set packet_ if there is a write error. - scoped_refptr<StringIOBuffer> packet = packet_; - packet_ = nullptr; - // The connection is waiting for the original write to complete // asynchronously. The new writer will notify the connection if the // write below completes asynchronously, but a synchronous competion // must be propagated back to the connection here. WriteResult result = static_cast<QuicChromiumPacketWriter*>(connection()->writer()) - ->WritePacketToSocket(packet); + ->WritePacketToSocket(std::move(packet_)); if (result.error_code == ERR_IO_PENDING) return;
diff --git a/net/quic/chromium/quic_chromium_client_session.h b/net/quic/chromium/quic_chromium_client_session.h index 9a888bb..a443e4a09 100644 --- a/net/quic/chromium/quic_chromium_client_session.h +++ b/net/quic/chromium/quic_chromium_client_session.h
@@ -324,7 +324,8 @@ // QuicChromiumPacketWriter::Delegate override. int HandleWriteError(int error_code, - scoped_refptr<StringIOBuffer> last_packet) override; + scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> + last_packet) override; void OnWriteError(int error_code) override; void OnWriteUnblocked() override; @@ -549,7 +550,7 @@ uint64_t bytes_pushed_and_unclaimed_count_; // Stores packet that witnesses socket write error. This packet is // written to a new socket after migration completes. - scoped_refptr<StringIOBuffer> packet_; + scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> packet_; // TODO(jri): Replace use of migration_pending_ sockets_.size(). // When a task is posted for MigrateSessionOnError, pass in // sockets_.size(). Then in MigrateSessionOnError, check to see if
diff --git a/net/quic/chromium/quic_chromium_packet_writer.cc b/net/quic/chromium/quic_chromium_packet_writer.cc index 9f2a147..33736d11 100644 --- a/net/quic/chromium/quic_chromium_packet_writer.cc +++ b/net/quic/chromium/quic_chromium_packet_writer.cc
@@ -16,33 +16,84 @@ namespace net { +namespace { + +enum NotReusableReason { + NOT_REUSABLE_NULLPTR = 0, + NOT_REUSABLE_TOO_SMALL = 1, + NOT_REUSABLE_REF_COUNT = 2, + NUM_NOT_REUSABLE_REASONS = 3, +}; + +void RecordNotReusableReason(NotReusableReason reason) { + UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.WritePacketNotReusable", reason, + NUM_NOT_REUSABLE_REASONS); +} + +} // namespace + +QuicChromiumPacketWriter::ReusableIOBuffer::ReusableIOBuffer(size_t capacity) + : IOBuffer(capacity), capacity_(capacity), size_(0) {} + +QuicChromiumPacketWriter::ReusableIOBuffer::~ReusableIOBuffer() {} + +void QuicChromiumPacketWriter::ReusableIOBuffer::Set(const char* buffer, + size_t buf_len) { + CHECK_LE(buf_len, capacity_); + CHECK(HasOneRef()); + size_ = buf_len; + std::memcpy(data(), buffer, buf_len); +} + QuicChromiumPacketWriter::QuicChromiumPacketWriter() : weak_factory_(this) {} QuicChromiumPacketWriter::QuicChromiumPacketWriter(DatagramClientSocket* socket) : socket_(socket), delegate_(nullptr), - packet_(nullptr), + packet_(new ReusableIOBuffer(kMaxPacketSize)), write_blocked_(false), weak_factory_(this) {} QuicChromiumPacketWriter::~QuicChromiumPacketWriter() {} +void QuicChromiumPacketWriter::SetPacket(const char* buffer, size_t buf_len) { + if (UNLIKELY(!packet_)) { + packet_ = new ReusableIOBuffer( + std::max(buf_len, static_cast<size_t>(kMaxPacketSize))); + RecordNotReusableReason(NOT_REUSABLE_NULLPTR); + } + if (UNLIKELY(packet_->capacity() < buf_len)) { + packet_ = new ReusableIOBuffer(buf_len); + RecordNotReusableReason(NOT_REUSABLE_TOO_SMALL); + } + if (UNLIKELY(!packet_->HasOneRef())) { + packet_ = new ReusableIOBuffer( + std::max(buf_len, static_cast<size_t>(kMaxPacketSize))); + RecordNotReusableReason(NOT_REUSABLE_REF_COUNT); + } + packet_->Set(buffer, buf_len); +} + WriteResult QuicChromiumPacketWriter::WritePacket( const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* /*options*/) { - scoped_refptr<StringIOBuffer> buf( - new StringIOBuffer(std::string(buffer, buf_len))); DCHECK(!IsWriteBlocked()); - return WritePacketToSocket(buf); + SetPacket(buffer, buf_len); + return WritePacketToSocketImpl(); } WriteResult QuicChromiumPacketWriter::WritePacketToSocket( - scoped_refptr<StringIOBuffer> packet) { + scoped_refptr<ReusableIOBuffer> packet) { + packet_ = std::move(packet); + return QuicChromiumPacketWriter::WritePacketToSocketImpl(); +} + +WriteResult QuicChromiumPacketWriter::WritePacketToSocketImpl() { base::TimeTicks now = base::TimeTicks::Now(); - int rv = socket_->Write(packet.get(), packet.get()->size(), + int rv = socket_->Write(packet_.get(), packet_->size(), base::Bind(&QuicChromiumPacketWriter::OnWriteComplete, weak_factory_.GetWeakPtr())); @@ -50,7 +101,8 @@ // If write error, then call delegate's HandleWriteError, which // may be able to migrate and rewrite packet on a new socket. // HandleWriteError returns the outcome of that rewrite attempt. - rv = delegate_->HandleWriteError(rv, packet); + rv = delegate_->HandleWriteError(rv, std::move(packet_)); + DCHECK(packet_ == nullptr); } WriteStatus status = WRITE_STATUS_OK; @@ -61,7 +113,6 @@ } else { status = WRITE_STATUS_BLOCKED; write_blocked_ = true; - packet_ = std::move(packet); } } @@ -97,8 +148,8 @@ // If write error, then call delegate's HandleWriteError, which // may be able to migrate and rewrite packet on a new socket. // HandleWriteError returns the outcome of that rewrite attempt. - rv = delegate_->HandleWriteError(rv, packet_); - packet_ = nullptr; + rv = delegate_->HandleWriteError(rv, std::move(packet_)); + DCHECK(packet_ == nullptr); if (rv == ERR_IO_PENDING) return; }
diff --git a/net/quic/chromium/quic_chromium_packet_writer.h b/net/quic/chromium/quic_chromium_packet_writer.h index 9b522e5..6e4b71e 100644 --- a/net/quic/chromium/quic_chromium_packet_writer.h +++ b/net/quic/chromium/quic_chromium_packet_writer.h
@@ -22,6 +22,27 @@ // Chrome specific packet writer which uses a datagram Socket for writing data. class NET_EXPORT_PRIVATE QuicChromiumPacketWriter : public QuicPacketWriter { public: + // Define a specific IO buffer that can be allocated once, but be + // assigned new contents and reused, avoiding the alternative of + // repeated memory allocations. This packet writer only ever has a + // single write in flight, a constraint inherited from the interface + // of the underlying datagram Socket. + class NET_EXPORT_PRIVATE ReusableIOBuffer : public IOBuffer { + public: + explicit ReusableIOBuffer(size_t capacity); + + size_t capacity() const { return capacity_; } + size_t size() const { return size_; } + + // Does memcpy from |buffer| into this->data(). |buf_len <= + // capacity()| must be true, |HasOneRef()| must be true. + void Set(const char* buffer, size_t buf_len); + + private: + ~ReusableIOBuffer() override; + size_t capacity_; + size_t size_; + }; // Delegate interface which receives notifications on socket write events. class NET_EXPORT_PRIVATE Delegate { public: @@ -30,8 +51,9 @@ // packet to a different socket. An implementation must return the // return value from the rewrite attempt if there is one, and // |error_code| otherwise. - virtual int HandleWriteError(int error_code, - scoped_refptr<StringIOBuffer> last_packet) = 0; + virtual int HandleWriteError( + int error_code, + scoped_refptr<ReusableIOBuffer> last_packet) = 0; // Called to propagate the final write error to the delegate. virtual void OnWriteError(int error_code) = 0; @@ -51,7 +73,7 @@ void set_write_blocked(bool write_blocked) { write_blocked_ = write_blocked; } // Writes |packet| to the socket and returns the error code from the write. - WriteResult WritePacketToSocket(scoped_refptr<StringIOBuffer> packet); + WriteResult WritePacketToSocket(scoped_refptr<ReusableIOBuffer> packet); // QuicPacketWriter WriteResult WritePacket(const char* buffer, @@ -68,11 +90,13 @@ void OnWriteComplete(int rv); private: + void SetPacket(const char* buffer, size_t buf_len); + WriteResult WritePacketToSocketImpl(); DatagramClientSocket* socket_; // Unowned. Delegate* delegate_; // Unowned. - // When a write returns asynchronously, |packet_| stores the written - // packet until OnWriteComplete is called. - scoped_refptr<StringIOBuffer> packet_; + // Reused for every packet write for the lifetime of the writer. Is + // moved to the delegate in the case of a write error. + scoped_refptr<ReusableIOBuffer> packet_; // Whether a write is currently in flight. bool write_blocked_;
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc index 30ea8e1..cee86b8 100644 --- a/net/quic/chromium/quic_stream_factory.cc +++ b/net/quic/chromium/quic_stream_factory.cc
@@ -190,6 +190,7 @@ } QuicConfig InitializeQuicConfig(const QuicTagVector& connection_options, + const QuicTagVector& client_connection_options, int idle_connection_timeout_seconds) { DCHECK_GT(idle_connection_timeout_seconds, 0); QuicConfig config; @@ -197,6 +198,7 @@ QuicTime::Delta::FromSeconds(idle_connection_timeout_seconds), QuicTime::Delta::FromSeconds(idle_connection_timeout_seconds)); config.SetConnectionOptionsToSend(connection_options); + config.SetClientConnectionOptions(client_connection_options); return config; } @@ -671,6 +673,7 @@ bool race_cert_verification, bool estimate_initial_rtt, const QuicTagVector& connection_options, + const QuicTagVector& client_connection_options, bool enable_token_binding) : require_confirmation_(true), net_log_(net_log), @@ -687,6 +690,7 @@ clock_skew_detector_(base::TimeTicks::Now(), base::Time::Now()), socket_performance_watcher_factory_(socket_performance_watcher_factory), config_(InitializeQuicConfig(connection_options, + client_connection_options, idle_connection_timeout_seconds)), crypto_config_(base::WrapUnique( new ProofVerifierChromium(cert_verifier,
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h index 0d91062..038e0e7 100644 --- a/net/quic/chromium/quic_stream_factory.h +++ b/net/quic/chromium/quic_stream_factory.h
@@ -215,6 +215,7 @@ bool race_cert_verification, bool estimate_initial_rtt, const QuicTagVector& connection_options, + const QuicTagVector& client_connection_options, bool enable_token_binding); ~QuicStreamFactory() override;
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc index 459af54b..1f474bfb 100644 --- a/net/quic/chromium/quic_stream_factory_test.cc +++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -220,7 +220,7 @@ idle_connection_timeout_seconds_, reduced_ping_timeout_seconds_, migrate_sessions_on_network_change_, migrate_sessions_early_, allow_server_migration_, force_hol_blocking_, race_cert_verification_, - estimate_initial_rtt_, QuicTagVector(), + estimate_initial_rtt_, connection_options_, client_connection_options_, /*enable_token_binding*/ false)); factory_->set_require_confirmation(false); } @@ -732,6 +732,8 @@ bool force_hol_blocking_; bool race_cert_verification_; bool estimate_initial_rtt_; + QuicTagVector connection_options_; + QuicTagVector client_connection_options_; }; class QuicStreamFactoryTest : public QuicStreamFactoryTestBase, @@ -5076,5 +5078,25 @@ EXPECT_TRUE(test_cases[2].state->certs().empty()); } +// Passes connection options and client connection options to QuicStreamFactory, +// then checks that its internal QuicConfig is correct. +TEST_P(QuicStreamFactoryTest, ConfigConnectionOptions) { + connection_options_.push_back(net::kTIME); + connection_options_.push_back(net::kTBBR); + connection_options_.push_back(net::kREJ); + + client_connection_options_.push_back(net::kTBBR); + client_connection_options_.push_back(net::k1RTT); + + Initialize(); + + const QuicConfig* config = QuicStreamFactoryPeer::GetConfig(factory_.get()); + EXPECT_EQ(connection_options_, config->SendConnectionOptions()); + EXPECT_TRUE(config->HasClientRequestedIndependentOption( + net::kTBBR, Perspective::IS_CLIENT)); + EXPECT_TRUE(config->HasClientRequestedIndependentOption( + net::k1RTT, Perspective::IS_CLIENT)); +} + } // namespace test } // namespace net
diff --git a/remoting/ios/app/host_view_controller.mm b/remoting/ios/app/host_view_controller.mm index d2e1dc4..552e506 100644 --- a/remoting/ios/app/host_view_controller.mm +++ b/remoting/ios/app/host_view_controller.mm
@@ -53,6 +53,8 @@ BOOL _blocksKeyboard; BOOL _hasPhysicalKeyboard; NSLayoutConstraint* _keyboardHeightConstraint; + + // Identical to self.view. Just casted to EAGLView. EAGLView* _hostView; } @end @@ -83,20 +85,15 @@ #pragma mark - UIViewController +- (void)loadView { + _hostView = [[EAGLView alloc] initWithFrame:CGRectZero]; + self.view = _hostView; +} + - (void)viewDidLoad { [super viewDidLoad]; - _hostView = [[EAGLView alloc] initWithFrame:CGRectZero]; _hostView.displayTaskRunner = remoting::ChromotingClientRuntime::GetInstance()->display_task_runner(); - _hostView.translatesAutoresizingMaskIntoConstraints = NO; - [self.view addSubview:_hostView]; - - [NSLayoutConstraint activateConstraints:@[ - [_hostView.topAnchor constraintEqualToAnchor:self.view.topAnchor], - [_hostView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], - [_hostView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], - ]]; - [self setKeyboardSize:CGSizeZero needsLayout:NO]; _floatingButton = [MDCFloatingButton floatingButtonWithShape:MDCFloatingButtonShapeMini]; @@ -140,12 +137,7 @@ metrics:metrics views:views]; - [NSLayoutConstraint - activateConstraints:[NSLayoutConstraint - constraintsWithVisualFormat:@"V:[fab]-(inset)-|" - options:0 - metrics:metrics - views:views]]; + [self setKeyboardSize:CGSizeZero needsLayout:NO]; } - (void)viewDidUnload { @@ -208,7 +200,14 @@ - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; - [_client surfaceChanged:_hostView.bounds]; + // Pass the actual size of the view to the renderer. + [_client.displayHandler onSurfaceChanged:_hostView.bounds]; + + // Pass the size of the visible area to GestureInterpreter/DesktopViewport. + CGFloat visibleAreaHeight = + _hostView.bounds.size.height - _keyboardSize.height; + _client.gestureInterpreter->OnSurfaceSizeChanged(_hostView.bounds.size.width, + visibleAreaHeight); [self resizeHostToFitIfNeeded]; [self updateFABConstraintsAnimated:NO]; @@ -507,15 +506,16 @@ if (_keyboardHeightConstraint) { _keyboardHeightConstraint.active = NO; } - _keyboardHeightConstraint = - [_hostView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor - constant:-keyboardSize.height]; + // Change FAB bottom constraint to adjust for the keyboard size. + _keyboardHeightConstraint = [_floatingButton.bottomAnchor + constraintEqualToAnchor:_hostView.bottomAnchor + constant:-kFabInset - keyboardSize.height]; _keyboardHeightConstraint.active = YES; if (needsLayout) { [UIView animateWithDuration:kKeyboardAnimationTime animations:^{ - [self.view setNeedsLayout]; + [self.view layoutIfNeeded]; }]; } }
diff --git a/remoting/ios/client_keyboard.mm b/remoting/ios/client_keyboard.mm index 3a7132f01..66c17ccb 100644 --- a/remoting/ios/client_keyboard.mm +++ b/remoting/ios/client_keyboard.mm
@@ -66,7 +66,18 @@ } - (BOOL)resignFirstResponder { - return [self resignFirstResponderForced:NO]; + if (self.showsSoftKeyboard) { + // This translates the action of resigning first responder when the keyboard + // is showing into hiding the soft keyboard while keeping the view first + // responder. This is to allow the hide keyboard button on the soft keyboard + // to work properly with ClientKeyboard's soft keyboard logic, which calls + // resignFirstResponder. + // This may cause weird behavior if the superview has multiple responders + // (text views). + self.showsSoftKeyboard = NO; + return NO; + } + return [super resignFirstResponder]; } - (UIView*)inputAccessoryView { @@ -92,10 +103,7 @@ showsSoftKeyboard ? nil : [[UIView alloc] initWithFrame:CGRectZero]; if (self.isFirstResponder) { - // Cause the app to reload inputView. - - [self resignFirstResponderForced:YES]; - [self becomeFirstResponder]; + [self reloadInputViews]; } } @@ -103,21 +111,4 @@ return _inputView == nil; } -#pragma mark - Private - -- (BOOL)resignFirstResponderForced:(BOOL)forced { - if (!forced && self.showsSoftKeyboard) { - // This translates the action of resigning first responder when the keyboard - // is showing into hiding the soft keyboard while keeping the view first - // responder. This is to allow the hide keyboard button on the soft keyboard - // to work properly with ClientKeyboard's soft keyboard logic, which calls - // resignFirstResponder. - // This may cause weird behavior if the superview has multiple responders - // (text views). - self.showsSoftKeyboard = NO; - return NO; - } - return [super resignFirstResponder]; -} - @end
diff --git a/remoting/ios/session/remoting_client.h b/remoting/ios/session/remoting_client.h index 0591812..ce5fab2a 100644 --- a/remoting/ios/session/remoting_client.h +++ b/remoting/ios/session/remoting_client.h
@@ -72,9 +72,6 @@ - (void)handleExtensionMessageOfType:(NSString*)type message:(NSString*)message; -// Notifies all components that the frame of the surface has changed. -- (void)surfaceChanged:(const CGRect&)frame; - - (void)setHostResolution:(CGSize)dipsResolution scale:(int)scale; // The display handler tied to the remoting client used to display the host.
diff --git a/remoting/ios/session/remoting_client.mm b/remoting/ios/session/remoting_client.mm index 2030bbaf..1602366 100644 --- a/remoting/ios/session/remoting_client.mm +++ b/remoting/ios/session/remoting_client.mm
@@ -327,14 +327,6 @@ type, message); } -- (void)surfaceChanged:(const CGRect&)frame { - // Note that GLKView automatically sets the OpenGL viewport size to the size - // of the surface. - [_displayHandler onSurfaceChanged:frame]; - _gestureInterpreter->OnSurfaceSizeChanged(frame.size.width, - frame.size.height); -} - - (void)setHostResolution:(CGSize)dipsResolution scale:(int)scale { _session->SendClientResolution(dipsResolution.width, dipsResolution.height, scale);
diff --git a/services/resource_coordinator/public/cpp/BUILD.gn b/services/resource_coordinator/public/cpp/BUILD.gn index 5959cbd..4e76e805 100644 --- a/services/resource_coordinator/public/cpp/BUILD.gn +++ b/services/resource_coordinator/public/cpp/BUILD.gn
@@ -33,6 +33,10 @@ set_sources_assignment_filter(sources_assignment_filter) } + if (is_fuchsia) { + sources += [ "memory_instrumentation/os_metrics_fuchsia.cc" ] + } + defines = [ "SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_IMPLEMENTATION" ] deps = [
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc new file mode 100644 index 0000000..4a946b9 --- /dev/null +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc
@@ -0,0 +1,27 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" + +#include <vector> + +namespace memory_instrumentation { + +// static +bool OSMetrics::FillOSMemoryDump(base::ProcessId pid, + mojom::RawOSMemDump* dump) { + // TODO(fuchsia): Implement this. See crbug.com/750948 + NOTIMPLEMENTED(); + return false; +} + +// static +std::vector<mojom::VmRegionPtr> OSMetrics::GetProcessMemoryMaps( + base::ProcessId) { + // TODO(fuchsia): Implement this. See crbug.com/750948 + NOTIMPLEMENTED(); + return std::vector<mojom::VmRegionPtr>(); +} + +} // namespace memory_instrumentation
diff --git a/services/ui/public/cpp/input_devices/input_device_controller.cc b/services/ui/public/cpp/input_devices/input_device_controller.cc index d76604a2..cea7f9c 100644 --- a/services/ui/public/cpp/input_devices/input_device_controller.cc +++ b/services/ui/public/cpp/input_devices/input_device_controller.cc
@@ -21,8 +21,7 @@ InputDeviceController::~InputDeviceController() = default; void InputDeviceController::AddInterface( - service_manager::BinderRegistryWithArgs< - const service_manager::BindSourceInfo&>* registry) { + service_manager::BinderRegistry* registry) { // base::Unretained() is safe here as this class is tied to the life of // Service, so that no requests should come in after this class is deleted. registry->AddInterface<mojom::InputDeviceController>( @@ -162,8 +161,7 @@ } void InputDeviceController::BindInputDeviceControllerRequest( - mojom::InputDeviceControllerRequest request, - const service_manager::BindSourceInfo& source_info) { + mojom::InputDeviceControllerRequest request) { bindings_.AddBinding(this, std::move(request)); }
diff --git a/services/ui/public/cpp/input_devices/input_device_controller.h b/services/ui/public/cpp/input_devices/input_device_controller.h index 625912f..e812f4d 100644 --- a/services/ui/public/cpp/input_devices/input_device_controller.h +++ b/services/ui/public/cpp/input_devices/input_device_controller.h
@@ -8,7 +8,6 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" -#include "services/service_manager/public/cpp/bind_source_info.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/ui/public/interfaces/input_devices/input_device_controller.mojom.h" @@ -24,8 +23,7 @@ ~InputDeviceController() override; // Registers the interface provided by this class with |registry|. - void AddInterface(service_manager::BinderRegistryWithArgs< - const service_manager::BindSourceInfo&>* registry); + void AddInterface(service_manager::BinderRegistry* registry); // mojom::InputDeviceController:: void AddKeyboardDeviceObserver( @@ -67,8 +65,7 @@ void NotifyObserver(mojom::KeyboardDeviceObserver* observer); void BindInputDeviceControllerRequest( - mojom::InputDeviceControllerRequest request, - const service_manager::BindSourceInfo& source_info); + mojom::InputDeviceControllerRequest request); mojo::BindingSet<mojom::InputDeviceController> bindings_; mojo::InterfacePtrSet<mojom::KeyboardDeviceObserver> observers_;
diff --git a/services/ui/service.cc b/services/ui/service.cc index 7b2b52e..b779a8c1 100644 --- a/services/ui/service.cc +++ b/services/ui/service.cc
@@ -289,11 +289,12 @@ discardable_shared_memory_manager_ = owned_discardable_shared_memory_manager_.get(); } - registry_.AddInterface<mojom::AccessibilityManager>(base::Bind( - &Service::BindAccessibilityManagerRequest, base::Unretained(this))); - registry_.AddInterface<mojom::Clipboard>( + registry_with_source_info_.AddInterface<mojom::AccessibilityManager>( + base::Bind(&Service::BindAccessibilityManagerRequest, + base::Unretained(this))); + registry_with_source_info_.AddInterface<mojom::Clipboard>( base::Bind(&Service::BindClipboardRequest, base::Unretained(this))); - registry_.AddInterface<mojom::DisplayManager>( + registry_with_source_info_.AddInterface<mojom::DisplayManager>( base::Bind(&Service::BindDisplayManagerRequest, base::Unretained(this))); registry_.AddInterface<mojom::Gpu>( base::Bind(&Service::BindGpuRequest, base::Unretained(this))); @@ -303,16 +304,18 @@ base::Bind(&Service::BindIMEDriverRequest, base::Unretained(this))); registry_.AddInterface<mojom::UserAccessManager>(base::Bind( &Service::BindUserAccessManagerRequest, base::Unretained(this))); - registry_.AddInterface<mojom::UserActivityMonitor>(base::Bind( - &Service::BindUserActivityMonitorRequest, base::Unretained(this))); - registry_.AddInterface<WindowTreeHostFactory>(base::Bind( - &Service::BindWindowTreeHostFactoryRequest, base::Unretained(this))); - registry_.AddInterface<mojom::WindowManagerWindowTreeFactory>( - base::Bind(&Service::BindWindowManagerWindowTreeFactoryRequest, + registry_with_source_info_.AddInterface<mojom::UserActivityMonitor>( + base::Bind(&Service::BindUserActivityMonitorRequest, base::Unretained(this))); - registry_.AddInterface<mojom::WindowTreeFactory>(base::Bind( + registry_with_source_info_.AddInterface<WindowTreeHostFactory>(base::Bind( + &Service::BindWindowTreeHostFactoryRequest, base::Unretained(this))); + registry_with_source_info_ + .AddInterface<mojom::WindowManagerWindowTreeFactory>( + base::Bind(&Service::BindWindowManagerWindowTreeFactoryRequest, + base::Unretained(this))); + registry_with_source_info_.AddInterface<mojom::WindowTreeFactory>(base::Bind( &Service::BindWindowTreeFactoryRequest, base::Unretained(this))); - registry_ + registry_with_source_info_ .AddInterface<discardable_memory::mojom::DiscardableSharedMemoryManager>( base::Bind(&Service::BindDiscardableSharedMemoryManagerRequest, base::Unretained(this))); @@ -324,10 +327,10 @@ // On non-Linux platforms there will be no DeviceDataManager instance and no // purpose in adding the Mojo interface to connect to. if (input_device_server_.IsRegisteredAsObserver()) - input_device_server_.AddInterface(®istry_); + input_device_server_.AddInterface(®istry_with_source_info_); #if defined(USE_OZONE) - ui::OzonePlatform::GetInstance()->AddInterfaces(®istry_); + ui::OzonePlatform::GetInstance()->AddInterfaces(®istry_with_source_info_); #endif } @@ -335,8 +338,10 @@ const service_manager::BindSourceInfo& source_info, const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) { - registry_.BindInterface(interface_name, std::move(interface_pipe), - source_info); + if (!registry_with_source_info_.TryBindInterface( + interface_name, &interface_pipe, source_info)) { + registry_.BindInterface(interface_name, std::move(interface_pipe)); + } } void Service::StartDisplayInit() { @@ -400,7 +405,7 @@ } else { screen_manager_ = display::ScreenManager::Create(); } - screen_manager_->AddInterfaces(®istry_); + screen_manager_->AddInterfaces(®istry_with_source_info_); if (is_gpu_ready_) screen_manager_->Init(window_server_->display_manager()); } @@ -448,27 +453,20 @@ ->AddDisplayManagerBinding(std::move(request)); } -void Service::BindGpuRequest( - mojom::GpuRequest request, - const service_manager::BindSourceInfo& source_info) { +void Service::BindGpuRequest(mojom::GpuRequest request) { window_server_->gpu_host()->Add(std::move(request)); } -void Service::BindIMERegistrarRequest( - mojom::IMERegistrarRequest request, - const service_manager::BindSourceInfo& source_info) { +void Service::BindIMERegistrarRequest(mojom::IMERegistrarRequest request) { ime_registrar_.AddBinding(std::move(request)); } -void Service::BindIMEDriverRequest( - mojom::IMEDriverRequest request, - const service_manager::BindSourceInfo& source_info) { +void Service::BindIMEDriverRequest(mojom::IMEDriverRequest request) { ime_driver_.AddBinding(std::move(request)); } void Service::BindUserAccessManagerRequest( - mojom::UserAccessManagerRequest request, - const service_manager::BindSourceInfo& source_info) { + mojom::UserAccessManagerRequest request) { window_server_->user_id_tracker()->Bind(std::move(request)); } @@ -527,8 +525,7 @@ } void Service::BindWindowServerTestRequest( - mojom::WindowServerTestRequest request, - const service_manager::BindSourceInfo& source_info) { + mojom::WindowServerTestRequest request) { if (!test_config_) return; mojo::MakeStrongBinding(
diff --git a/services/ui/service.h b/services/ui/service.h index 7826b4a0..92cf63a 100644 --- a/services/ui/service.h +++ b/services/ui/service.h
@@ -140,19 +140,13 @@ mojom::DisplayManagerRequest request, const service_manager::BindSourceInfo& source_info); - void BindGpuRequest(mojom::GpuRequest request, - const service_manager::BindSourceInfo& source_info); + void BindGpuRequest(mojom::GpuRequest request); - void BindIMERegistrarRequest( - mojom::IMERegistrarRequest request, - const service_manager::BindSourceInfo& source_info); + void BindIMERegistrarRequest(mojom::IMERegistrarRequest request); - void BindIMEDriverRequest(mojom::IMEDriverRequest request, - const service_manager::BindSourceInfo& source_info); + void BindIMEDriverRequest(mojom::IMEDriverRequest request); - void BindUserAccessManagerRequest( - mojom::UserAccessManagerRequest request, - const service_manager::BindSourceInfo& source_info); + void BindUserAccessManagerRequest(mojom::UserAccessManagerRequest request); void BindUserActivityMonitorRequest( mojom::UserActivityMonitorRequest request, @@ -174,9 +168,7 @@ discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request, const service_manager::BindSourceInfo& source_info); - void BindWindowServerTestRequest( - mojom::WindowServerTestRequest request, - const service_manager::BindSourceInfo& source_info); + void BindWindowServerTestRequest(mojom::WindowServerTestRequest request); std::unique_ptr<ws::WindowServer> window_server_; std::unique_ptr<PlatformEventSource> event_source_; @@ -221,7 +213,8 @@ service_manager::BinderRegistryWithArgs< const service_manager::BindSourceInfo&> - registry_; + registry_with_source_info_; + service_manager::BinderRegistry registry_; // Set to true in StartDisplayInit(). bool is_gpu_ready_ = false;
diff --git a/services/ui/ws/event_dispatcher.cc b/services/ui/ws/event_dispatcher.cc index 02b5f3a5..d9dcc70 100644 --- a/services/ui/ws/event_dispatcher.cc +++ b/services/ui/ws/event_dispatcher.cc
@@ -48,7 +48,8 @@ event_targeter_(base::MakeUnique<EventTargeter>(this)), mouse_button_down_(false), mouse_cursor_source_window_(nullptr), - mouse_cursor_in_non_client_area_(false) {} + mouse_cursor_in_non_client_area_(false), + next_mouse_button_flags_(0) {} EventDispatcher::~EventDispatcher() { SetMouseCursorSourceWindow(nullptr); @@ -79,12 +80,17 @@ void EventDispatcher::SetMousePointerDisplayLocation( const gfx::Point& display_location, int64_t display_id) { - SetMousePointerLocation(display_location, display_id); - UpdateCursorProviderByLastKnownLocation(); - // Write our initial location back to our shared screen coordinate. This - // shouldn't cause problems because we already read the cursor before we - // process any events in views during window construction. - delegate_->OnMouseCursorLocationChanged(display_location, display_id); + // Create a synthetic mouse event and dispatch it directly to ourselves so we + // update internal caches and possibly send exit events in case the window + // the cursor is over changes. + ui::PointerEvent move_event( + ui::ET_POINTER_MOVED, display_location, display_location, + next_mouse_button_flags_, 0 /* changed_button_flags */, + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, + ui::MouseEvent::kMousePointerId), + base::TimeTicks::Now()); + ProcessEvent(move_event, display_id, + EventDispatcher::AcceleratorMatchPhase::ANY); } ui::CursorData EventDispatcher::GetCurrentMouseCursor() const { @@ -466,6 +472,12 @@ mouse_button_down_ = true; else if (is_pointer_going_up) mouse_button_down_ = false; + + if (event.type() == ui::ET_POINTER_UP) { + next_mouse_button_flags_ = event.flags() & ~event.changed_button_flags(); + } else { + next_mouse_button_flags_ = event.flags(); + } } if (drag_controller_) {
diff --git a/services/ui/ws/event_dispatcher.h b/services/ui/ws/event_dispatcher.h index d8936e3..85f3a16 100644 --- a/services/ui/ws/event_dispatcher.h +++ b/services/ui/ws/event_dispatcher.h
@@ -317,6 +317,12 @@ ServerWindow* mouse_cursor_source_window_; bool mouse_cursor_in_non_client_area_; + // We calculate out the button flags for any synthetic mouse events we need + // to create during SetMousePointerDisplayLocation(). We don't try to set + // this on a per-PointerTarget because modified PointerTargets aren't always + // committed back into |pointer_targets_|. + int next_mouse_button_flags_; + // The location of the mouse pointer in display coordinates. This can be // outside the bounds of |mouse_cursor_source_window_|, which can capture the // cursor.
diff --git a/services/ui/ws/event_dispatcher_unittest.cc b/services/ui/ws/event_dispatcher_unittest.cc index f571c0e..72fadfd 100644 --- a/services/ui/ws/event_dispatcher_unittest.cc +++ b/services/ui/ws/event_dispatcher_unittest.cc
@@ -994,6 +994,90 @@ EXPECT_EQ(child2.get(), details->window); } +TEST_P(EventDispatcherTest, SetMousePointerDisplayLocationWithFlags) { + std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3)); + + root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); + child->SetBounds(gfx::Rect(10, 10, 20, 20)); + + TestEventDispatcherDelegate* event_dispatcher_delegate = + test_event_dispatcher_delegate(); + EventDispatcher* dispatcher = event_dispatcher(); + + // Move to the child window with a mouse event which holds down the left + // mouse button. + const ui::PointerEvent move1( + ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11), + base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0)); + DispatchEvent(event_dispatcher(), move1, 0, + EventDispatcher::AcceleratorMatchPhase::ANY); + std::unique_ptr<DispatchedEventDetails> details = + event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); + EXPECT_EQ(child.get(), details->window); + + // Manually set the mouse pointer. + SetMousePointerDisplayLocation(dispatcher, gfx::Point(1, 1), 0); + + // The first dispatched event is a leave to the child. It should also + // maintain the button state from the first event above. + details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); + EXPECT_EQ(child.get(), details->window); + EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type()); + EXPECT_TRUE((details->event->flags() & EF_LEFT_MOUSE_BUTTON) != 0); + + // The second dispatched event is an enter to the root window. + details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); + EXPECT_EQ(root_window(), details->window); + EXPECT_EQ(ui::ET_POINTER_MOVED, details->event->type()); + EXPECT_TRUE((details->event->flags() & EF_LEFT_MOUSE_BUTTON) != 0); +} + +TEST_P(EventDispatcherTest, SetMousePointerDisplayLocationWithoutFlags) { + std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3)); + + root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); + child->SetBounds(gfx::Rect(10, 10, 20, 20)); + + TestEventDispatcherDelegate* event_dispatcher_delegate = + test_event_dispatcher_delegate(); + EventDispatcher* dispatcher = event_dispatcher(); + + // Move to the child window with a mouse event which holds down the left + // mouse button. + const ui::PointerEvent move1(ui::MouseEvent( + ui::ET_MOUSE_PRESSED, gfx::Point(11, 11), gfx::Point(11, 11), + base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0)); + DispatchEvent(event_dispatcher(), move1, 0, + EventDispatcher::AcceleratorMatchPhase::ANY); + std::unique_ptr<DispatchedEventDetails> details = + event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); + EXPECT_EQ(child.get(), details->window); + + // Release the mouse button. + const ui::PointerEvent release1(ui::MouseEvent( + ui::ET_MOUSE_RELEASED, gfx::Point(11, 11), gfx::Point(11, 11), + base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); + DispatchEvent(event_dispatcher(), release1, 0, + EventDispatcher::AcceleratorMatchPhase::ANY); + details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); + EXPECT_EQ(child.get(), details->window); + + // Manually set the mouse pointer. + SetMousePointerDisplayLocation(dispatcher, gfx::Point(1, 1), 0); + + // The first dispatched event is a leave to the child. + details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); + EXPECT_EQ(child.get(), details->window); + EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type()); + EXPECT_EQ(details->event->flags(), 0); + + // The second dispatched event is an enter to the root window. + details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); + EXPECT_EQ(root_window(), details->window); + EXPECT_EQ(ui::ET_POINTER_MOVED, details->event->type()); + EXPECT_EQ(details->event->flags(), 0); +} + TEST_P(EventDispatcherTest, DestroyWindowWhileGettingEvents) { std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 7fa0129..22b5e67 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2355,6 +2355,21 @@ ] } ], + "ReducedSoftTileMemoryLimitOnLowEndAndroid": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ReducedSoftTileMemoryLimitOnLowEndAndroid" + ] + } + ] + } + ], "RefreshTokenDeviceId": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index f773c2d..91ccd6c 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -66728,21 +66728,6 @@ {} ] ], - "IndexedDB/idbcursor_continue_index3-expected.txt": [ - [ - {} - ] - ], - "IndexedDB/idbcursor_iterating_objectstore2-expected.txt": [ - [ - {} - ] - ], - "IndexedDB/idbindex_count4-expected.txt": [ - [ - {} - ] - ], "IndexedDB/idbobjectstore_createIndex15-autoincrement-expected.txt": [ [ {} @@ -66758,26 +66743,11 @@ {} ] ], - "IndexedDB/interleaved-cursors-expected.txt": [ - [ - {} - ] - ], - "IndexedDB/key_valid-expected.txt": [ - [ - {} - ] - ], "IndexedDB/nested-cloning-common.js": [ [ {} ] ], - "IndexedDB/request_bubble-and-capture-expected.txt": [ - [ - {} - ] - ], "IndexedDB/support-promises.js": [ [ {} @@ -66788,11 +66758,6 @@ {} ] ], - "IndexedDB/transaction-abort-multiple-metadata-revert-expected.txt": [ - [ - {} - ] - ], "WebCryptoAPI/OWNERS": [ [ {} @@ -179874,10 +179839,6 @@ "cbec9b06016acc1af49b3e0a673b2905773114f6", "testharness" ], - "IndexedDB/idbcursor_continue_index3-expected.txt": [ - "1d69a1cffcd64c05bab8aa0ab0efa56b59568a79", - "support" - ], "IndexedDB/idbcursor_continue_index3.htm": [ "6d37c3e1996d0f54d87a29b2a65d3bb76736cba2", "testharness" @@ -179986,10 +179947,6 @@ "728242c9f1b72b7348c68c2723b25765bab64332", "testharness" ], - "IndexedDB/idbcursor_iterating_objectstore2-expected.txt": [ - "3ef1f02a86fe71c5096111ac2df33c734205da6d", - "support" - ], "IndexedDB/idbcursor_iterating_objectstore2.htm": [ "811427a853df6d79e671569b87a95e51b3e06070", "testharness" @@ -180322,10 +180279,6 @@ "e60732dbfc5de408f3ea32007ae22ee34b337ed8", "testharness" ], - "IndexedDB/idbindex_count4-expected.txt": [ - "9f7bdd476be5f8ae6c9b7692e338894d1b43eaa4", - "support" - ], "IndexedDB/idbindex_count4.htm": [ "9deabbce03168c216316a8eb8d317089fb26cd02", "testharness" @@ -180866,10 +180819,6 @@ "fdacaee0ed6b2a97b579495f5944df04e70b7deb", "testharness" ], - "IndexedDB/interleaved-cursors-expected.txt": [ - "37b79d510d79615902211fc629ccf76ccac8b390", - "support" - ], "IndexedDB/interleaved-cursors.html": [ "131b1965caae735de9ef8893e6ca55f24ce36f81", "testharness" @@ -180882,10 +180831,6 @@ "8c0257c4231c413dde10c6f541f17f57634bff1c", "testharness" ], - "IndexedDB/key_valid-expected.txt": [ - "f3b51f5baf287c6b05304501ab1f85042703d66b", - "support" - ], "IndexedDB/key_valid.html": [ "85d0f455f5116e0754bf29fe6ba5052e7a7563a7", "testharness" @@ -180982,10 +180927,6 @@ "44e8124ba121e64d82e47a99735e1a1df4f8ed44", "testharness" ], - "IndexedDB/request_bubble-and-capture-expected.txt": [ - "f14dd2c3e50689b38e5d2bb64153d6bd8ad077bc", - "support" - ], "IndexedDB/request_bubble-and-capture.htm": [ "9c486babd57c2d14bb251d5bba202b3dbd6c802d", "testharness" @@ -181010,10 +180951,6 @@ "07a6e888f303a42e66f2afaa98c9941e08ce2aa2", "testharness" ], - "IndexedDB/transaction-abort-multiple-metadata-revert-expected.txt": [ - "80751b784577c0ccc82e1e74b6bb51eeb821c972", - "support" - ], "IndexedDB/transaction-abort-multiple-metadata-revert.html": [ "204ed174a936fe4a91c36e00559845287ae31748", "testharness" @@ -224979,11 +224916,11 @@ "testharness" ], "dom/nodes/Node-cloneNode-expected.txt": [ - "ae2b6de915cea4a0a83fc5fbcb64c76842deb771", + "862708872f00abc7b0ba88374fbd43a3005da539", "support" ], "dom/nodes/Node-cloneNode.html": [ - "f35c88d16e9a3bfc47eb6965d13076f537a20c3c", + "f2f37f4ad272aef9f5ee46f8b44a668ff394d6c8", "testharness" ], "dom/nodes/Node-compareDocumentPosition.html": [ @@ -232375,7 +232312,7 @@ "testharness" ], "html/dom/documents/dom-tree-accessors/Document.currentScript.html": [ - "c7bbd7f042cf5b674217b4435be00b1dfd3af900", + "b8c28696c0974a392a9a62e079934641f57415b5", "testharness" ], "html/dom/documents/dom-tree-accessors/Document.getElementsByClassName-null-undef.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode-expected.txt index b7328f6..3c84289 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode-expected.txt
@@ -130,7 +130,7 @@ PASS createElementNS non-HTML PASS createProcessingInstruction PASS implementation.createDocumentType -FAIL implementation.createDocument assert_equals: expected "null" but got "http://web-platform.test:8001" +FAIL implementation.createDocument assert_equals: origin value expected "null" but got "http://web-platform.test:8001" PASS implementation.createHTMLDocument PASS node with children Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode.html index 9f4f8fc..5ed7b08c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode.html +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-cloneNode.html
@@ -11,27 +11,33 @@ assert_equals(nodeB.nodeName, nodeA.nodeName, "nodeName"); if (nodeA.nodeType === Node.ELEMENT_NODE) { - assert_equals(nodeB.prefix, nodeA.prefix); - assert_equals(nodeB.namespaceURI, nodeA.namespaceURI); - assert_equals(nodeB.localName, nodeA.localName); - assert_equals(nodeB.tagName, nodeA.tagName); - assert_not_equals(nodeB.attributes != nodeA.attributes); - assert_equals(nodeB.attributes.length, nodeA.attributes.length); + assert_equals(nodeB.prefix, nodeA.prefix, "prefix"); + assert_equals(nodeB.namespaceURI, nodeA.namespaceURI, "namespaceURI"); + assert_equals(nodeB.localName, nodeA.localName, "localName"); + assert_equals(nodeB.tagName, nodeA.tagName, "tagName"); + assert_not_equals(nodeB.attributes != nodeA.attributes, "attributes"); + assert_equals(nodeB.attributes.length, nodeA.attributes.length, + "attributes.length"); for (var i = 0, il = nodeA.attributes.length; i < il; ++i) { - assert_not_equals(nodeB.attributes[i], nodeA.attributes[i]); - assert_equals(nodeB.attributes[i].name, nodeA.attributes[i].name); - assert_equals(nodeB.attributes[i].prefix, nodeA.attributes[i].prefix); - assert_equals(nodeB.attributes[i].namespaceURI, nodeA.attributes[i].namespaceURI); - assert_equals(nodeB.attributes[i].value, nodeA.attributes[i].value); + assert_not_equals(nodeB.attributes[i], nodeA.attributes[i], + "attributes[" + i + "]"); + assert_equals(nodeB.attributes[i].name, nodeA.attributes[i].name, + "attributes[" + i + "].name"); + assert_equals(nodeB.attributes[i].prefix, nodeA.attributes[i].prefix, + "attributes[" + i + "].prefix"); + assert_equals(nodeB.attributes[i].namespaceURI, nodeA.attributes[i].namespaceURI, + "attributes[" + i + "].namespaceURI"); + assert_equals(nodeB.attributes[i].value, nodeA.attributes[i].value, + "attributes[" + i + "].value"); } } } function check_copy(orig, copy, type) { - assert_not_equals(orig, copy); - assert_equal_node(orig, copy); - assert_true(orig instanceof type, "Should be type"); - assert_true(copy instanceof type, "Should be type"); + assert_not_equals(orig, copy, "Object equality"); + assert_equal_node(orig, copy, "Node equality"); + assert_true(orig instanceof type, "original instanceof " + type); + assert_true(copy instanceof type, "copy instanceof " + type); } function create_element_and_check(localName, typeName) { @@ -212,40 +218,40 @@ var pi = document.createProcessingInstruction("target", "data"); var copy = pi.cloneNode(); check_copy(pi, copy, ProcessingInstruction); - assert_equals(pi.data, copy.data); - assert_equals(pi.target, pi.target); + assert_equals(pi.data, copy.data, "data"); + assert_equals(pi.target, pi.target, "target"); }, "createProcessingInstruction"); test(function() { var doctype = document.implementation.createDocumentType("html", "public", "system"); var copy = doctype.cloneNode(); check_copy(doctype, copy, DocumentType); - assert_equals(doctype.name, copy.name); - assert_equals(doctype.publicId, copy.publicId); - assert_equals(doctype.systemId, copy.systemId); + assert_equals(doctype.name, copy.name, "name"); + assert_equals(doctype.publicId, copy.publicId, "publicId"); + assert_equals(doctype.systemId, copy.systemId, "systemId"); }, "implementation.createDocumentType"); test(function() { var doc = document.implementation.createDocument(null, null); var copy = doc.cloneNode(); check_copy(doc, copy, Document); - assert_equals(doc.charset, "UTF-8"); - assert_equals(doc.charset, copy.charset); - assert_equals(doc.contentType, "application/xml"); - assert_equals(doc.contentType, copy.contentType); - assert_equals(doc.URL, "about:blank") - assert_equals(doc.URL, copy.URL); - assert_equals(doc.origin, "null") - assert_equals(doc.origin, copy.origin); - assert_equals(doc.compatMode, "CSS1Compat"); - assert_equals(doc.compatMode, copy.compatMode); + assert_equals(doc.charset, "UTF-8", "charset value"); + assert_equals(doc.charset, copy.charset, "charset equality"); + assert_equals(doc.contentType, "application/xml", "contentType value"); + assert_equals(doc.contentType, copy.contentType, "contentType equality"); + assert_equals(doc.URL, "about:blank", "URL value") + assert_equals(doc.URL, copy.URL, "URL equality"); + assert_equals(doc.origin, "null", "origin value") + assert_equals(doc.origin, copy.origin, "origin equality"); + assert_equals(doc.compatMode, "CSS1Compat", "compatMode value"); + assert_equals(doc.compatMode, copy.compatMode, "compatMode equality"); }, "implementation.createDocument"); test(function() { var html = document.implementation.createHTMLDocument("title"); var copy = html.cloneNode(); check_copy(html, copy, Document); - assert_equals(copy.title, ""); + assert_equals(copy.title, "", "title value"); }, "implementation.createHTMLDocument"); test(function() { @@ -262,19 +268,23 @@ var copy = parent.cloneNode(deep); check_copy(parent, copy, HTMLDivElement); - assert_equals(copy.childNodes.length, 2); + assert_equals(copy.childNodes.length, 2, + "copy.childNodes.length with deep copy"); check_copy(child1, copy.childNodes[0], HTMLDivElement); - assert_equals(copy.childNodes[0].childNodes.length, 0); + assert_equals(copy.childNodes[0].childNodes.length, 0, + "copy.childNodes[0].childNodes.length"); check_copy(child2, copy.childNodes[1], HTMLDivElement); - assert_equals(copy.childNodes[1].childNodes.length, 1); + assert_equals(copy.childNodes[1].childNodes.length, 1, + "copy.childNodes[1].childNodes.length"); check_copy(grandChild, copy.childNodes[1].childNodes[0], HTMLDivElement); deep = false; copy = parent.cloneNode(deep); check_copy(parent, copy, HTMLDivElement); - assert_equals(copy.childNodes.length, 0); + assert_equals(copy.childNodes.length, 0, + "copy.childNodes.length with non-deep copy"); }, "node with children"); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html b/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html index 76f1b64..34b3ec9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html
@@ -14,7 +14,6 @@ "dom-inline" : [], "dom-ext" : [], "nested" : ["nested-outer","nested-inner","nested-outer"], - "script-exec" : ["script-exec-before-after","script-exec-before-after"], "script-load-error" : [null], "script-window-error" : ["script-error-compile","script-error-runtime"], "timeout" : [null],
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-top-level-await-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-top-level-await-expected.txt new file mode 100644 index 0000000..c4d786a --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-top-level-await-expected.txt
@@ -0,0 +1,85 @@ +Tests that evaluation with top-level await may be perfomed in console. +await Promise.resolve(1) +1 +{a:await Promise.resolve(1)} +{a: 1} +$_ +{a: 1} +let {a,b} = await Promise.resolve({a: 1, b:2}), f = 5; +undefined +a +1 +b +2 +let c = await Promise.resolve(2) +undefined +c +2 +let d; +undefined +d +undefined +let [i,{abc:{k}}] = [0,{abc:{k:1}}]; +undefined +i +0 +k +1 +var l = await Promise.resolve(2); +undefined +l +2 +foo(await koo()); +4 +$_ +4 +const m = foo(await koo()); +undefined +m +4 +const n = foo(await +koo()); +undefined +n +4 +`status: ${(await Promise.resolve({status:200})).status}` +"status: 200" +for (let i = 0; i < 2; ++i) await i +undefined +for (let i = 0; i < 2; ++i) { await i } +undefined +await 0 +0 +await 0;function foo(){} +undefined +foo +ƒ foo(){} +class Foo{}; await 1; +1 +Foo +class Foo{} +await 0;function* gen(){} +undefined +for (var i = 0; i < 10; ++i) { await i; } +undefined +i +10 +for (let j = 0; j < 5; ++j) { await j; } +undefined +j +VM:1 Uncaught ReferenceError: j is not defined + at <anonymous>:1:1 +(anonymous) @ VM:1 +gen +ƒ* gen(){} +await 5; return 42; +VM:1 Uncaught SyntaxError: await is only valid in async function +let o = await 1, p +undefined +p +undefined +let q = 1, s = await 2 +undefined +s +2 +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-top-level-await.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-top-level-await.js new file mode 100644 index 0000000..e331c46 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-top-level-await.js
@@ -0,0 +1,65 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult('Tests that evaluation with top-level await may be perfomed in console.'); + + await TestRunner.loadModule('console_test_runner'); + await TestRunner.showPanel('console'); + + await TestRunner.evaluateInPagePromise(` + function foo(x) { + return x; + } + + function koo() { + return Promise.resolve(4); + } + `); + + var test = ConsoleTestRunner.evaluateInConsolePromise; + await test('await Promise.resolve(1)'); + await test('{a:await Promise.resolve(1)}'); + await test('$_'); + await test('let {a,b} = await Promise.resolve({a: 1, b:2}), f = 5;'); + await test('a'); + await test('b'); + await test('let c = await Promise.resolve(2)'); + await test('c'); + await test('let d;'); + await test('d'); + await test('let [i,{abc:{k}}] = [0,{abc:{k:1}}];'); + await test('i'); + await test('k'); + await test('var l = await Promise.resolve(2);'); + await test('l'); + await test('foo(await koo());'); + await test('$_'); + await test('const m = foo(await koo());'); + await test('m'); + await test('const n = foo(await\nkoo());'); + await test('n'); + await test('`status: ${(await Promise.resolve({status:200})).status}`'); + await test('for (let i = 0; i < 2; ++i) await i'); + await test('for (let i = 0; i < 2; ++i) { await i }'); + await test('await 0'); + await test('await 0;function foo(){}'); + await test('foo'); + await test('class Foo{}; await 1;'); + await test('Foo'); + await test('await 0;function* gen(){}'); + await test('for (var i = 0; i < 10; ++i) { await i; }') + await test('i'); + await test('for (let j = 0; j < 5; ++j) { await j; }') + await test('j'); + await test('gen'); + await test('await 5; return 42;'); + await test('let o = await 1, p'); + await test('p'); + await test('let q = 1, s = await 2'); + await test('s'); + await new Promise(resolve => ConsoleTestRunner.waitForRemoteObjectsConsoleMessages(resolve)); + ConsoleTestRunner.dumpConsoleMessages(); + TestRunner.completeTest(); +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys-expected.txt new file mode 100644 index 0000000..5da8cfb --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys-expected.txt
@@ -0,0 +1,38 @@ +Tests that styles sidebar can be navigated with arrow keys. + +Editing: true + + +Pressing escape to stop editing +Editing: false +element.style {} + +Navigating with arrow keys +Editing: false +<style>…</style>div#foo {} + +Editing: false +<style>…</style>#foo {} + +Editing: false +<style>…</style>div {} + +Editing: false +user agent stylesheetdiv {} + +Editing: false +<style>…</style>div {} + +Typing should start editing +Editing: true +t + +Pressing escape again should restore focus +Editing: false +<style>…</style>div {} + +Pressing enter should start editing selector +Editing: true +div + +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys.js b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys.js new file mode 100644 index 0000000..a2d42dd --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys.js
@@ -0,0 +1,86 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult('Tests that styles sidebar can be navigated with arrow keys.\n'); + + await TestRunner.showPanel('elements'); + await TestRunner.loadModule('elements_test_runner'); + + await TestRunner.loadHTML(` + <style> + #foo { + color: red; + } + div { + color: blue; + } + div#foo { + color: green; + } + </style> + <div id="foo"></div> + `); + ElementsTestRunner.selectNodeWithId('foo'); + + await waitForStylesRebuild(); + + let ssp = Elements.ElementsPanel.instance()._stylesWidget; + + // start editing + ssp._sectionBlocks[0].sections[0].element.focus(); + ssp._sectionBlocks[0].sections[0].addNewBlankProperty(0).startEditing(); + + dumpState(); + + TestRunner.addResult("Pressing escape to stop editing"); + eventSender.keyDown("Escape"); + dumpState() + + TestRunner.addResult("Navigating with arrow keys"); + eventSender.keyDown("ArrowDown"); + dumpState() + + eventSender.keyDown("ArrowDown"); + dumpState() + + eventSender.keyDown("ArrowDown"); + dumpState() + + eventSender.keyDown("ArrowDown"); + dumpState() + + eventSender.keyDown("ArrowUp"); + dumpState() + + TestRunner.addResult("Typing should start editing"); + eventSender.keyDown("t"); + dumpState() + + TestRunner.addResult("Pressing escape again should restore focus"); + eventSender.keyDown("Escape"); + dumpState() + + TestRunner.addResult("Pressing enter should start editing selector"); + eventSender.keyDown("Enter"); + dumpState() + + TestRunner.completeTest(); + + + function dumpState() { + TestRunner.addResult('Editing: ' + UI.isEditing()) + TestRunner.addResult(document.deepActiveElement().textContent); + TestRunner.addResult(''); + } + + function waitForStylesRebuild(node) { + if (node && node.getAttribute("id") === 'foo') + return; + return TestRunner.addSnifferPromise(Elements.StylesSidebarPane.prototype, "_nodeStylesUpdatedForTest").then(waitForStylesRebuild); + } + + + +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/preprocess-top-level-awaits-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/preprocess-top-level-awaits-expected.txt new file mode 100644 index 0000000..08d17d8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/preprocess-top-level-awaits-expected.txt
@@ -0,0 +1,82 @@ +CONSOLE ERROR: line 497: Walk order not defined for ArrayPattern +This tests preprocessTopLevelAwaitExpressions. +-------------- +0 +was ignored. +-------------- +await 0 +was processed: +(async () => {return (await 0)})() +-------------- +async function foo() { await 0; } +was ignored. +-------------- +async () => await 0 +was ignored. +-------------- +class A { async method() { await 0 } } +was ignored. +-------------- +await 0; return 0; +was ignored. +-------------- +var a = await 1 +was processed: +(async () => {void (a = await 1)})() +-------------- +let a = await 1 +was processed: +(async () => {void (a = await 1)})() +-------------- +const a = await 1 +was processed: +(async () => {void (a = await 1)})() +-------------- +for (var i = 0; i < 1; ++i) { await i } +was processed: +(async () => {for (void (i = 0); i < 1; ++i) { await i }})() +-------------- +for (let i = 0; i < 1; ++i) { await i } +was processed: +(async () => {for (let i = 0; i < 1; ++i) { await i }})() +-------------- +var {a} = {a:1}, [b] = [1], {c:{d}} = {c:{d: await 1}} +was processed: +(async () => {void ( ({a} = {a:1}), ([b] = [1]), ({c:{d}} = {c:{d: await 1}}))})() +-------------- +console.log(`${(await {a:1}).a}`) +was processed: +(async () => {return (console.log(`${(await {a:1}).a}`))})() +-------------- +await 0;function foo() {} +was processed: +(async () => {await 0;foo=function foo() {}})() +-------------- +await 0;class Foo {} +was processed: +(async () => {await 0;Foo=class Foo {}})() +-------------- +if (await true) { function foo() {} } +was processed: +(async () => {if (await true) { foo=function foo() {} }})() +-------------- +if (await true) { class Foo{} } +was processed: +(async () => {if (await true) { class Foo{} }})() +-------------- +if (await true) { var a = 1; } +was processed: +(async () => {if (await true) { void (a = 1); }})() +-------------- +if (await true) { let a = 1; } +was processed: +(async () => {if (await true) { let a = 1; }})() +-------------- +var a = await 1; let b = 2; const c = 3; +was processed: +(async () => {void (a = await 1); void (b = 2); void (c = 3);})() +-------------- +let o = await 1, p +was processed: +(async () => {void ( (o = await 1), (p=undefined))})() +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/preprocess-top-level-awaits.js b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/preprocess-top-level-awaits.js new file mode 100644 index 0000000..927f7e5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/preprocess-top-level-awaits.js
@@ -0,0 +1,40 @@ +var commands = [ + '0', + 'await 0', + 'async function foo() { await 0; }', + 'async () => await 0', + 'class A { async method() { await 0 } }', + 'await 0; return 0;', + 'var a = await 1', + 'let a = await 1', + 'const a = await 1', + 'for (var i = 0; i < 1; ++i) { await i }', + 'for (let i = 0; i < 1; ++i) { await i }', + 'var {a} = {a:1}, [b] = [1], {c:{d}} = {c:{d: await 1}}', + 'console.log(`${(await {a:1}).a}`)', + 'await 0;function foo() {}', + 'await 0;class Foo {}', + 'if (await true) { function foo() {} }', + 'if (await true) { class Foo{} }', + 'if (await true) { var a = 1; }', + 'if (await true) { let a = 1; }', + 'var a = await 1; let b = 2; const c = 3;', + 'let o = await 1, p' +]; + +(async function test() { + await TestRunner.loadModule("formatter"); + TestRunner.addResult("This tests preprocessTopLevelAwaitExpressions."); + for (var command of commands) { + TestRunner.addResult('--------------'); + TestRunner.addResult(command); + let processedText = await Formatter.formatterWorkerPool().preprocessTopLevelAwaitExpressions(command); + if (processedText) { + TestRunner.addResult('was processed:'); + TestRunner.addResult(processedText); + } else { + TestRunner.addResult('was ignored.'); + } + } + TestRunner.completeTest(); +})() \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/input/dispatchMouseEvent-ack-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/input/dispatchMouseEvent-ack-expected.txt new file mode 100644 index 0000000..c00c804 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/input/dispatchMouseEvent-ack-expected.txt
@@ -0,0 +1,20 @@ +Tests that Input.dispatchMouseEvent waits for JavaScript event handlers to finish. +-- mousePressed -- +Dispatching event +mouseEventPromise for mousePressed has not resolved yet +Paused on debugger statement +Resumed +Recieved ack for mousePressed +-- mouseReleased -- +Dispatching event +mouseEventPromise for mouseReleased has not resolved yet +Paused on debugger statement +Resumed +Recieved ack for mouseReleased +-- mouseMoved -- +Dispatching event +mouseEventPromise for mouseMoved has not resolved yet +Paused on debugger statement +Resumed +Recieved ack for mouseMoved +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/input/dispatchMouseEvent-ack.js b/third_party/WebKit/LayoutTests/inspector-protocol/input/dispatchMouseEvent-ack.js new file mode 100644 index 0000000..266db053 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/input/dispatchMouseEvent-ack.js
@@ -0,0 +1,50 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(`Tests that Input.dispatchMouseEvent waits for JavaScript event handlers to finish.`); + + await session.evaluate(` + window.got = 'nope'; + window.addEventListener('mousedown', pauseEvent); + window.addEventListener('mouseup', pauseEvent); + window.addEventListener('mousemove', pauseEvent); + + function pauseEvent(event) { + debugger; + event.preventDefault(); + } + `); + + function dumpError(message) { + if (message.error) + testRunner.log('Error: ' + message.error.message); + } + + + for (var event of ['mousePressed', 'mouseReleased', 'mouseMoved']) { + testRunner.log(`-- ${event} --`); + let resolved = false; + await dp.Debugger.enable(); + testRunner.log('Dispatching event'); + let mouseEventPromise = dp.Input.dispatchMouseEvent({ + type: event, + button: 'left', + clickCount: 1, + x: 100, + y: 200 + }); + mouseEventPromise.then(() => resolved = true); + await dp.Debugger.oncePaused(); + + await Promise.resolve(); // just in case + + testRunner.log(resolved ? `mouseEventPromise for ${event} was resolved too early` : `mouseEventPromise for ${event} has not resolved yet`) + testRunner.log('Paused on debugger statement'); + + await dp.Debugger.resume(); + testRunner.log('Resumed'); + dumpError(await mouseEventPromise); + testRunner.log(`Recieved ack for ${event}`); + } + + + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-counters-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-counters-expected.txt new file mode 100644 index 0000000..5672b8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-counters-expected.txt
@@ -0,0 +1,6 @@ +Test that page performance metrics are retrieved. +[] +["DocumentCount","JSEventListenerCount","NodeCount"] +["DocumentCount","JSEventListenerCount","NodeCount"] +[] +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-counters.js b/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-counters.js new file mode 100644 index 0000000..99218c22 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-counters.js
@@ -0,0 +1,18 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startBlank( + 'Test that page performance metrics are retrieved.'); + + await dumpMetrics(); + await dp.Performance.enable(); + await dumpMetrics(); + await dumpMetrics(); + await dp.Performance.disable(); + await dumpMetrics(); + + async function dumpMetrics() { + const {result:{metrics}} = await dp.Performance.getMetrics(); + testRunner.log(JSON.stringify(metrics.map(metric => metric.name))); + } + + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector/agents-enable-disable-expected.txt b/third_party/WebKit/LayoutTests/inspector/agents-enable-disable-expected.txt index c9fe4a65..484b7a3 100644 --- a/third_party/WebKit/LayoutTests/inspector/agents-enable-disable-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/agents-enable-disable-expected.txt
@@ -13,6 +13,7 @@ Network.disable finished successfully Overlay.disable finished successfully Page.disable finished successfully +Performance.disable finished successfully Profiler.disable finished successfully Runtime.disable finished successfully @@ -55,6 +56,9 @@ Page.enable finished successfully Page.disable finished successfully +Performance.enable finished successfully +Performance.disable finished successfully + Profiler.enable finished successfully Profiler.disable finished successfully
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/elements-tab-stops-expected.txt b/third_party/WebKit/LayoutTests/inspector/elements/elements-tab-stops-expected.txt index 960acc3..f0032b7 100644 --- a/third_party/WebKit/LayoutTests/inspector/elements/elements-tab-stops-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/elements/elements-tab-stops-expected.txt
@@ -5,6 +5,7 @@ BUTTON:Toggle Element State BUTTON:Element Classes BUTTON:New Style Rule +DIV:element.style {} BUTTON:Select an element in the page to inspect it DIV#tab-elements:Elements BUTTON:Customize and control DevTools @@ -17,6 +18,7 @@ BUTTON:Customize and control DevTools DIV#tab-elements:Elements BUTTON:Select an element in the page to inspect it +DIV:element.style {} BUTTON:New Style Rule BUTTON:Element Classes BUTTON:Toggle Element State
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-function-definition.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-function-definition.html index 227f32bd..68b4a15 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-function-definition.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-function-definition.html
@@ -40,7 +40,8 @@ function testDumpFunctionDefinition(next) { InspectorTest.addSniffer(ObjectUI.ObjectPropertiesSection, "formatObjectAsFunction", onConsoleMessagesReceived); - ConsoleModel.consoleModel.evaluateCommandInConsole(UI.context.flavor(SDK.ExecutionContext), "jumpToMe"); + var consoleView = Console.ConsoleView.instance(); + consoleView._prompt._appendCommand("jumpToMe", true); function onConsoleMessagesReceived() {
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 6bccac9..5befcc2 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -637,6 +637,8 @@ InitDNSPrefetch(); InstanceCounters::IncrementCounter(InstanceCounters::kDocumentCounter); + PerformanceMonitor::IncrementCounter(frame_, + PerformanceMonitor::kDocumentCount); lifecycle_.AdvanceTo(DocumentLifecycle::kInactive); @@ -2683,6 +2685,9 @@ // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes. CHECK(!View()->IsAttached()); + PerformanceMonitor::DecrementCounter(frame_, + PerformanceMonitor::kDocumentCount); + // This is required, as our LocalFrame might delete itself as soon as it // detaches us. However, this violates Node::detachLayoutTree() semantics, as // it's never possible to re-attach. Eventually Document::detachLayoutTree()
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn index 2a374b6..5434e49d 100644 --- a/third_party/WebKit/Source/core/editing/BUILD.gn +++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -240,6 +240,8 @@ "markers/SuggestionMarker.h", "markers/SuggestionMarkerListImpl.cpp", "markers/SuggestionMarkerListImpl.h", + "markers/SuggestionMarkerReplacementScope.cpp", + "markers/SuggestionMarkerReplacementScope.h", "markers/TextMatchMarker.cpp", "markers/TextMatchMarker.h", "markers/TextMatchMarkerListImpl.cpp",
diff --git a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.cpp b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.cpp index a73cb341..ae31e37 100644 --- a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.cpp +++ b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.cpp
@@ -5,9 +5,55 @@ #include "core/editing/markers/SuggestionMarkerListImpl.h" #include "core/editing/markers/DocumentMarkerListEditor.h" +#include "core/editing/markers/SuggestionMarker.h" +#include "core/editing/markers/SuggestionMarkerReplacementScope.h" namespace blink { +namespace { + +UChar32 GetCodePointAt(const String& text, size_t index) { + UChar32 c; + U16_GET(text, 0, index, text.length(), c); + return c; +} + +Optional<DocumentMarker::MarkerOffsets> +ComputeOffsetsAfterNonSuggestionEditingOperating(const DocumentMarker& marker, + const String& node_text, + unsigned offset, + unsigned old_length, + unsigned new_length) { + unsigned marker_start = marker.StartOffset(); + unsigned marker_end = marker.EndOffset(); + + // Marked text was modified + if (offset < marker_end && offset + old_length > marker_start) + return {}; + + // Text inserted/replaced immediately after the marker, remove marker if first + // character is a (Unicode) letter or digit + if (offset == marker_end && new_length > 0) { + if (WTF::Unicode::IsAlphanumeric(GetCodePointAt(node_text, offset))) + return {}; + return marker.ComputeOffsetsAfterShift(offset, old_length, new_length); + } + + // Text inserted/replaced immediately before the marker, remove marker if + // first character is a (Unicode) letter or digit + if (offset == marker_start && new_length > 0) { + if (WTF::Unicode::IsAlphanumeric( + GetCodePointAt(node_text, offset + new_length - 1))) + return {}; + return marker.ComputeOffsetsAfterShift(offset, old_length, new_length); + } + + // Don't care if text was deleted immediately before or after the marker + return marker.ComputeOffsetsAfterShift(offset, old_length, new_length); +} + +} // namespace + DocumentMarker::MarkerType SuggestionMarkerListImpl::MarkerType() const { return DocumentMarker::kSuggestion; } @@ -107,10 +153,67 @@ return did_remove_marker; } -bool SuggestionMarkerListImpl::ShiftMarkers(const String&, +bool SuggestionMarkerListImpl::ShiftMarkers(const String& node_text, unsigned offset, unsigned old_length, unsigned new_length) { + if (SuggestionMarkerReplacementScope::CurrentlyInScope()) + return ShiftMarkersForSuggestionReplacement(offset, old_length, new_length); + + return ShiftMarkersForNonSuggestionEditingOperation(node_text, offset, + old_length, new_length); +} + +bool SuggestionMarkerListImpl::ShiftMarkersForSuggestionReplacement( + unsigned offset, + unsigned old_length, + unsigned new_length) { + // Since suggestion markers are stored unsorted, the quickest way to perform + // this operation is to build a new list with the markers not removed by the + // shift. + bool did_shift_marker = false; + unsigned end_offset = offset + old_length; + HeapVector<Member<DocumentMarker>> unremoved_markers; + for (const Member<DocumentMarker>& marker : markers_) { + // Markers that intersect the replacement range, but do not fully contain + // it, should be removed. + const bool marker_intersects_replacement_range = + marker->StartOffset() < end_offset && marker->EndOffset() > offset; + const bool marker_contains_replacement_range = + marker->StartOffset() <= offset && marker->EndOffset() >= end_offset; + + if (marker_intersects_replacement_range && + !marker_contains_replacement_range) { + did_shift_marker = true; + continue; + } + + Optional<DocumentMarker::MarkerOffsets> result = + marker->ComputeOffsetsAfterShift(offset, old_length, new_length); + if (result == WTF::nullopt) { + did_shift_marker = true; + continue; + } + + if (marker->StartOffset() != result.value().start_offset || + marker->EndOffset() != result.value().end_offset) { + marker->SetStartOffset(result.value().start_offset); + marker->SetEndOffset(result.value().end_offset); + did_shift_marker = true; + } + + unremoved_markers.push_back(marker); + } + + markers_ = std::move(unremoved_markers); + return did_shift_marker; +} + +bool SuggestionMarkerListImpl::ShiftMarkersForNonSuggestionEditingOperation( + const String& node_text, + unsigned offset, + unsigned old_length, + unsigned new_length) { // Since suggestion markers are stored unsorted, the quickest way to perform // this operation is to build a new list with the markers not removed by the // shift. @@ -118,8 +221,9 @@ HeapVector<Member<DocumentMarker>> unremoved_markers; for (const Member<DocumentMarker>& marker : markers_) { Optional<DocumentMarker::MarkerOffsets> result = - marker->ComputeOffsetsAfterShift(offset, old_length, new_length); - if (result == WTF::nullopt) { + ComputeOffsetsAfterNonSuggestionEditingOperating( + *marker, node_text, offset, old_length, new_length); + if (!result) { did_shift_marker = true; continue; }
diff --git a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.h b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.h index 29d0e73..9477e29 100644 --- a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.h +++ b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.h
@@ -43,11 +43,25 @@ DECLARE_VIRTUAL_TRACE(); private: + bool ShiftMarkersForSuggestionReplacement(unsigned offset, + unsigned old_length, + unsigned new_length); + bool ShiftMarkersForNonSuggestionEditingOperation(const String& node_text, + unsigned offset, + unsigned old_length, + unsigned new_length); + HeapVector<Member<DocumentMarker>> markers_; DISALLOW_COPY_AND_ASSIGN(SuggestionMarkerListImpl); }; +DEFINE_TYPE_CASTS(SuggestionMarkerListImpl, + DocumentMarkerList, + list, + list->MarkerType() == DocumentMarker::kSuggestion, + list.MarkerType() == DocumentMarker::kSuggestion); + } // namespace blink #endif // SuggestionMarkerListImpl_h
diff --git a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImplTest.cpp b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImplTest.cpp index 212b46d78..6a01fd1 100644 --- a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImplTest.cpp +++ b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImplTest.cpp
@@ -5,6 +5,7 @@ #include "core/editing/markers/SuggestionMarkerListImpl.h" #include "core/editing/markers/SuggestionMarker.h" +#include "core/editing/markers/SuggestionMarkerReplacementScope.h" #include "platform/heap/Handle.h" #include "testing/gtest/include/gtest/gtest.h" @@ -254,14 +255,62 @@ EXPECT_EQ(50u, markers[1]->EndOffset()); } -TEST_F(SuggestionMarkerListImplTest, ShiftMarkers) { - marker_list_->Add(CreateMarker(30, 40)); - marker_list_->Add(CreateMarker(40, 50)); - marker_list_->Add(CreateMarker(10, 20)); +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForSuggestionReplacement_ReturnsFalseWhenNoShift) { marker_list_->Add(CreateMarker(0, 10)); + + { + SuggestionMarkerReplacementScope scope; + // Replace range 0 to 10 with a ten character string. + // Text is ignored for suggestion replacement, so we can just pass an empty + // string. + EXPECT_FALSE(marker_list_->ShiftMarkers("", 0, 10, 10)); + } + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(1u, markers.size()); + + EXPECT_EQ(0u, markers[0]->StartOffset()); + EXPECT_EQ(10u, markers[0]->EndOffset()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForSuggestionReplacement_MarkersUpdateProperly) { + // Marker with suggestion to apply. + // Should be kept (and shifted). + marker_list_->Add(CreateMarker(10, 20)); + + // Marker touching start of replacement range. + // Should be kept. + marker_list_->Add(CreateMarker(0, 10)); + + // Marker partially overlapping start of replacement range. + // Should be removed, + marker_list_->Add(CreateMarker(0, 11)); + + // Marker touching end of replacement range. + // Should be kept (and shifted). marker_list_->Add(CreateMarker(20, 30)); - EXPECT_TRUE(marker_list_->ShiftMarkers("", 15, 20, 0)); + // Marker partially overlapping end of replacement range + // Should be removed. + marker_list_->Add(CreateMarker(19, 30)); + + // Marker contained inside replacement range + // Should be removed. + marker_list_->Add(CreateMarker(11, 19)); + + // Marker containing replacement range + // Should be kept (and shifted). + marker_list_->Add(CreateMarker(9, 21)); + + { + SuggestionMarkerReplacementScope scope; + // Replace range 10 to 20 with a five character string. + // Text is ignored for suggestion replacement, so we can just pass an empty + // string. + EXPECT_TRUE(marker_list_->ShiftMarkers("", 10, 10, 5)); + } DocumentMarkerVector markers = marker_list_->GetMarkers(); std::sort(markers.begin(), markers.end(), compare_markers); @@ -271,14 +320,179 @@ EXPECT_EQ(0u, markers[0]->StartOffset()); EXPECT_EQ(10u, markers[0]->EndOffset()); - EXPECT_EQ(10u, markers[1]->StartOffset()); - EXPECT_EQ(15u, markers[1]->EndOffset()); + EXPECT_EQ(9u, markers[1]->StartOffset()); + EXPECT_EQ(16u, markers[1]->EndOffset()); - EXPECT_EQ(15u, markers[2]->StartOffset()); - EXPECT_EQ(20u, markers[2]->EndOffset()); + EXPECT_EQ(10u, markers[2]->StartOffset()); + EXPECT_EQ(15u, markers[2]->EndOffset()); - EXPECT_EQ(20u, markers[3]->StartOffset()); - EXPECT_EQ(30u, markers[3]->EndOffset()); + EXPECT_EQ(15u, markers[3]->StartOffset()); + EXPECT_EQ(25u, markers[3]->EndOffset()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_DeleteFromMiddle) { + marker_list_->Add(CreateMarker(0, 5)); + + EXPECT_TRUE(marker_list_->ShiftMarkers("hello", 2, 1, 0)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_InsertIntoMiddle) { + marker_list_->Add(CreateMarker(0, 5)); + + EXPECT_TRUE(marker_list_->ShiftMarkers("hello", 2, 0, 1)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_PrependLetter) { + marker_list_->Add(CreateMarker(0, 5)); + + EXPECT_TRUE(marker_list_->ShiftMarkers("ahello", 0, 0, 1)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F( + SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_PrependSurrogatePairLetter) { + marker_list_->Add(CreateMarker(0, 5)); + + // Prepending MATHEMATICAL SCRIPT CAPITAL C + EXPECT_TRUE(marker_list_->ShiftMarkers(u"\U0001d49ehello", 0, 0, 2)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_PrependDigit) { + marker_list_->Add(CreateMarker(0, 5)); + + EXPECT_TRUE(marker_list_->ShiftMarkers("0hello", 0, 0, 1)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_PrependSurrogatePairDigit) { + marker_list_->Add(CreateMarker(0, 5)); + + // Prepending MATHEMATICAL DOUBLE-STRUCK DIGIT ONE + EXPECT_TRUE(marker_list_->ShiftMarkers(u"\U0001d7d9hello", 0, 0, 2)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_PrependNonAlphanumeric) { + marker_list_->Add(CreateMarker(0, 5)); + + EXPECT_TRUE(marker_list_->ShiftMarkers(".hello", 0, 0, 1)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + + EXPECT_EQ(1u, markers.size()); + + EXPECT_EQ(1u, markers[0]->StartOffset()); + EXPECT_EQ(6u, markers[0]->EndOffset()); +} + +TEST_F( + SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_PrependSurrogatePairNonAlphanumeric) { + marker_list_->Add(CreateMarker(0, 5)); + + // Prepending FACE WITH TEARS OF JOY + EXPECT_TRUE(marker_list_->ShiftMarkers(u"\U0001f602hello", 0, 0, 2)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + + EXPECT_EQ(1u, markers.size()); + + EXPECT_EQ(2u, markers[0]->StartOffset()); + EXPECT_EQ(7u, markers[0]->EndOffset()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_AppendLetter) { + marker_list_->Add(CreateMarker(0, 5)); + + EXPECT_TRUE(marker_list_->ShiftMarkers("helloa", 5, 0, 1)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_AppendSurrogatePairLetter) { + marker_list_->Add(CreateMarker(0, 5)); + + // Appending MATHEMATICAL SCRIPT CAPITAL C + EXPECT_TRUE(marker_list_->ShiftMarkers(u"hello\U0001d49e", 5, 0, 2)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_AppendDigit) { + marker_list_->Add(CreateMarker(0, 5)); + + EXPECT_TRUE(marker_list_->ShiftMarkers("hello0", 5, 0, 1)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_AppendSurrogatePairDigit) { + marker_list_->Add(CreateMarker(0, 5)); + + // Appending MATHEMATICAL DOUBLE-STRUCK DIGIT ONE + EXPECT_TRUE(marker_list_->ShiftMarkers(u"hello\U0001d7d9", 5, 0, 2)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + EXPECT_EQ(0u, markers.size()); +} + +TEST_F(SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_AppendNonAlphanumeric) { + marker_list_->Add(CreateMarker(0, 5)); + + EXPECT_FALSE(marker_list_->ShiftMarkers("hello.", 5, 0, 1)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + + EXPECT_EQ(1u, markers.size()); + + EXPECT_EQ(0u, markers[0]->StartOffset()); + EXPECT_EQ(5u, markers[0]->EndOffset()); +} + +TEST_F( + SuggestionMarkerListImplTest, + ShiftMarkersForNonSuggestionEditingOperation_AppendSurrogatePairNonAlphanumeric) { + marker_list_->Add(CreateMarker(0, 5)); + + // Appending FACE WITH TEARS OF JOY + EXPECT_FALSE(marker_list_->ShiftMarkers(u"hello\U0001f602", 5, 0, 2)); + + DocumentMarkerVector markers = marker_list_->GetMarkers(); + + EXPECT_EQ(1u, markers.size()); + + EXPECT_EQ(0u, markers[0]->StartOffset()); + EXPECT_EQ(5u, markers[0]->EndOffset()); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerReplacementScope.cpp b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerReplacementScope.cpp new file mode 100644 index 0000000..37e07729 --- /dev/null +++ b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerReplacementScope.cpp
@@ -0,0 +1,25 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/editing/markers/SuggestionMarkerReplacementScope.h" + +namespace blink { + +bool SuggestionMarkerReplacementScope::currently_in_scope_ = false; + +SuggestionMarkerReplacementScope::SuggestionMarkerReplacementScope() { + DCHECK(!currently_in_scope_); + currently_in_scope_ = true; +} + +SuggestionMarkerReplacementScope::~SuggestionMarkerReplacementScope() { + currently_in_scope_ = false; +} + +// static +bool SuggestionMarkerReplacementScope::CurrentlyInScope() { + return currently_in_scope_; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerReplacementScope.h b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerReplacementScope.h new file mode 100644 index 0000000..335f6fe --- /dev/null +++ b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerReplacementScope.h
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SuggestionMarkerReplacementScope_h +#define SuggestionMarkerReplacementScope_h + +#include "core/CoreExport.h" +#include "platform/wtf/Allocator.h" +#include "platform/wtf/Noncopyable.h" + +namespace blink { + +class CORE_EXPORT SuggestionMarkerReplacementScope { + WTF_MAKE_NONCOPYABLE(SuggestionMarkerReplacementScope); + STACK_ALLOCATED(); + + public: + SuggestionMarkerReplacementScope(); + ~SuggestionMarkerReplacementScope(); + + static bool CurrentlyInScope(); + + private: + static bool currently_in_scope_; +}; + +} // namespace blink + +#endif
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp index 38068ab0..c21921b 100644 --- a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
@@ -61,6 +61,7 @@ #include "core/inspector/InspectorNetworkAgent.h" #include "core/inspector/InspectorOverlayAgent.h" #include "core/inspector/InspectorPageAgent.h" +#include "core/inspector/InspectorPerformanceAgent.h" #include "core/inspector/InspectorResourceContainer.h" #include "core/inspector/InspectorResourceContentLoader.h" #include "core/inspector/InspectorTaskRunner.h" @@ -334,6 +335,8 @@ session->Append(InspectorMemoryAgent::Create()); + session->Append(InspectorPerformanceAgent::Create(inspected_frames_.Get())); + session->Append( InspectorApplicationCacheAgent::Create(inspected_frames_.Get()));
diff --git a/third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp b/third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp index e61e0cac..87f5eb7 100644 --- a/third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp +++ b/third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "core/frame/PerformanceMonitor.h" + #include "bindings/core/v8/ScheduledAction.h" #include "bindings/core/v8/ScriptEventListener.h" #include "bindings/core/v8/SourceLocation.h"
diff --git a/third_party/WebKit/Source/core/frame/PerformanceMonitor.h b/third_party/WebKit/Source/core/frame/PerformanceMonitor.h index fdb0610..ca6ea852 100644 --- a/third_party/WebKit/Source/core/frame/PerformanceMonitor.h +++ b/third_party/WebKit/Source/core/frame/PerformanceMonitor.h
@@ -6,6 +6,7 @@ #define PerformanceMonitor_h #include "core/CoreExport.h" +#include "core/frame/LocalFrame.h" #include "platform/heap/Handle.h" #include "platform/scheduler/base/task_time_observer.h" #include "platform/wtf/text/AtomicString.h" @@ -26,11 +27,14 @@ class DOMWindow; class Document; class ExecutionContext; -class Frame; -class LocalFrame; class Performance; class SourceLocation; +#define PERF_METRICS_LIST(V) \ + V(DocumentCount) \ + V(JSEventListenerCount) \ + V(NodeCount) + // Performance monitor for Web Performance APIs and logging. // The monitor is maintained per local root. // Long task notifications are delivered to observing Performance* instances @@ -41,6 +45,13 @@ WTF_MAKE_NONCOPYABLE(PerformanceMonitor); public: + enum MetricsType { +#define DECLARE_PERF_METRIC_NAME(name) k##name, + PERF_METRICS_LIST(DECLARE_PERF_METRIC_NAME) +#undef DECLARE_PERF_METRIC_NAME + kMaxMetricType + }; + enum Violation : size_t { kLongTask, kLongLayout, @@ -94,6 +105,18 @@ void DocumentWriteFetchScript(Document*); + static inline void IncrementCounter(LocalFrame* frame, MetricsType type) { + if (frame) + ++frame->GetPerformanceMonitor()->metric_values_[type]; + } + + static inline void DecrementCounter(LocalFrame* frame, MetricsType type) { + if (frame) + --frame->GetPerformanceMonitor()->metric_values_[type]; + } + + int PerfMetricValue(int id) const { return metric_values_[id]; } + // Direct API for core. void Subscribe(Violation, double threshold, Client*); void UnsubscribeAll(Client*); @@ -148,6 +171,7 @@ typename DefaultHash<size_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<size_t>> subscriptions_; + int metric_values_[kMaxMetricType]{}; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index ab5533e..7f53496a 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -963,8 +963,9 @@ // here. } - auto surface = WTF::MakeUnique<UnacceleratedImageBufferSurface>( - Size(), opacity_mode, kInitializeImagePixels, GetCanvasColorParams()); + auto surface = WTF::MakeUnique<Canvas2DLayerBridge>( + Size(), 0, opacity_mode, Canvas2DLayerBridge::kDisableAcceleration, + GetCanvasColorParams()); if (surface->IsValid()) { CanvasMetrics::CountCanvasContextUsage( CanvasMetrics::kUnaccelerated2DCanvasImageBufferCreated);
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp index ae921cd..6a1ff4f7 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -70,6 +70,7 @@ #include "core/layout/LayoutMedia.h" #include "core/layout/api/LayoutViewItem.h" #include "core/page/ChromeClient.h" +#include "core/page/Page.h" #include "core/paint/compositing/PaintLayerCompositor.h" #include "platform/Histogram.h" #include "platform/LayoutTestSupport.h" @@ -96,6 +97,7 @@ #include "public/platform/WebMediaPlayer.h" #include "public/platform/WebMediaPlayerSource.h" #include "public/platform/WebMediaStream.h" +#include "public/platform/WebScreenInfo.h" #include "public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h" #include "public/platform/modules/remoteplayback/WebRemotePlaybackClient.h" #include "public/platform/modules/remoteplayback/WebRemotePlaybackState.h" @@ -4098,6 +4100,13 @@ : WebMediaPlayer::DisplayType::kInline; } +gfx::ColorSpace HTMLMediaElement::TargetColorSpace() { + const LocalFrame* frame = GetDocument().GetFrame(); + if (!frame) + return gfx::ColorSpace(); + return frame->GetPage()->GetChromeClient().GetScreenInfo().color_space; +} + void HTMLMediaElement::CheckViewportIntersectionTimerFired(TimerBase*) { bool should_report_root_bounds = true; IntersectionGeometry geometry(nullptr, *this, Vector<Length>(),
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h index 304c3ef6..740e18f2 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -419,6 +419,7 @@ WebRemotePlaybackClient* RemotePlaybackClient() final { return remote_playback_client_; } + gfx::ColorSpace TargetColorSpace() override; void LoadTimerFired(TimerBase*); void ProgressEventTimerFired(TimerBase*);
diff --git a/third_party/WebKit/Source/core/inspector/BUILD.gn b/third_party/WebKit/Source/core/inspector/BUILD.gn index f2e8785..9b87585 100644 --- a/third_party/WebKit/Source/core/inspector/BUILD.gn +++ b/third_party/WebKit/Source/core/inspector/BUILD.gn
@@ -68,6 +68,8 @@ "InspectorOverlayHost.h", "InspectorPageAgent.cpp", "InspectorPageAgent.h", + "InspectorPerformanceAgent.cpp", + "InspectorPerformanceAgent.h", "InspectorResourceContainer.cpp", "InspectorResourceContainer.h", "InspectorResourceContentLoader.cpp", @@ -175,6 +177,8 @@ "inspector/protocol/Overlay.h", "inspector/protocol/Page.cpp", "inspector/protocol/Page.h", + "inspector/protocol/Performance.cpp", + "inspector/protocol/Performance.h", "inspector/protocol/Protocol.cpp", "inspector/protocol/Protocol.h", "inspector/protocol/Runtime.h",
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPerformanceAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPerformanceAgent.cpp new file mode 100644 index 0000000..14de1f5 --- /dev/null +++ b/third_party/WebKit/Source/core/inspector/InspectorPerformanceAgent.cpp
@@ -0,0 +1,61 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/inspector/InspectorPerformanceAgent.h" + +#include "core/frame/LocalFrame.h" +#include "core/inspector/InspectedFrames.h" +#include "platform/wtf/dtoa/utils.h" + +namespace blink { + +using protocol::Response; + +const char* InspectorPerformanceAgent::metric_names_[] = { +#define DEFINE_PERF_METRIC_NAME(name) #name, + PERF_METRICS_LIST(DEFINE_PERF_METRIC_NAME) +#undef DEFINE_PERF_METRIC_NAME +}; + +InspectorPerformanceAgent::InspectorPerformanceAgent( + InspectedFrames* inspected_frames) + : performance_monitor_(inspected_frames->Root()->GetPerformanceMonitor()) {} + +InspectorPerformanceAgent::~InspectorPerformanceAgent() = default; + +protocol::Response InspectorPerformanceAgent::enable() { + enabled_ = true; + return Response::OK(); +} + +protocol::Response InspectorPerformanceAgent::disable() { + enabled_ = false; + return Response::OK(); +} + +Response InspectorPerformanceAgent::getMetrics( + std::unique_ptr<protocol::Array<protocol::Performance::Metric>>* + out_result) { + std::unique_ptr<protocol::Array<protocol::Performance::Metric>> result = + protocol::Array<protocol::Performance::Metric>::create(); + if (enabled_) { + for (size_t i = 0; i < ARRAY_SIZE(metric_names_); ++i) { + double value = performance_monitor_->PerfMetricValue( + static_cast<PerformanceMonitor::MetricsType>(i)); + result->addItem(protocol::Performance::Metric::create() + .setName(metric_names_[i]) + .setValue(value) + .build()); + } + } + *out_result = std::move(result); + return Response::OK(); +} + +DEFINE_TRACE(InspectorPerformanceAgent) { + visitor->Trace(performance_monitor_); + InspectorBaseAgent<protocol::Performance::Metainfo>::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPerformanceAgent.h b/third_party/WebKit/Source/core/inspector/InspectorPerformanceAgent.h new file mode 100644 index 0000000..38a0301 --- /dev/null +++ b/third_party/WebKit/Source/core/inspector/InspectorPerformanceAgent.h
@@ -0,0 +1,45 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef InspectorPerformanceAgent_h +#define InspectorPerformanceAgent_h + +#include "core/CoreExport.h" +#include "core/frame/PerformanceMonitor.h" +#include "core/inspector/InspectorBaseAgent.h" +#include "core/inspector/protocol/Performance.h" + +namespace blink { + +class InspectedFrames; + +class CORE_EXPORT InspectorPerformanceAgent final + : public InspectorBaseAgent<protocol::Performance::Metainfo> { + WTF_MAKE_NONCOPYABLE(InspectorPerformanceAgent); + + public: + DECLARE_VIRTUAL_TRACE(); + + static InspectorPerformanceAgent* Create(InspectedFrames* inspected_frames) { + return new InspectorPerformanceAgent(inspected_frames); + } + ~InspectorPerformanceAgent() override; + + protocol::Response enable() override; + protocol::Response disable() override; + protocol::Response getMetrics( + std::unique_ptr<protocol::Array<protocol::Performance::Metric>>* + out_result) override; + + private: + InspectorPerformanceAgent(InspectedFrames*); + + Member<PerformanceMonitor> performance_monitor_; + bool enabled_ = false; + static const char* metric_names_[]; +}; + +} // namespace blink + +#endif // !defined(InspectorPerformanceAgent_h)
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 1b42b79..b6ed8c1 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -65,6 +65,38 @@ ] }, { + "domain": "Performance", + "experimental": true, + "types": [ + { + "id": "Metric", + "type": "object", + "properties": [ + { "name": "name", "type": "string", "description": "Metric name." }, + { "name": "value", "type": "number", "description": "Metric value." } + ], + "description": "Run-time execution metric." + } + ], + "commands": [ + { + "name": "enable", + "description": "Enable collecting and reporting metrics." + }, + { + "name": "disable", + "description": "Disable collecting and reporting metrics." + }, + { + "name": "getMetrics", + "returns": [ + { "name": "metrics", "type": "array", "items": { "$ref": "Metric" }, "description": "Current values for run-time metrics." } + ], + "description": "Retrieve current values of run-time metrics." + } + ] + }, + { "domain": "Page", "description": "Actions and events related to the inspected page belong to the page domain.", "dependencies": ["Debugger", "DOM", "Network"],
diff --git a/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json b/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json index 17d24ed..e33b4d8 100644 --- a/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json +++ b/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json
@@ -85,6 +85,9 @@ "exclude_events": ["screencastFrame", "screencastVisibilityChanged", "colorPicked", "interstitialShown", "interstitialHidden", "javascriptDialogOpening", "javascriptDialogClosed", "navigationRequested"] }, { + "domain": "Performance" + }, + { "domain": "Emulation", "include": ["forceViewport", "resetViewport", "resetPageScaleFactor", "setPageScaleFactor", "setScriptExecutionDisabled", "setTouchEmulationEnabled", "setEmulatedMedia", "setCPUThrottlingRate", "setVirtualTimePolicy", "setDefaultBackgroundColorOverride"],
diff --git a/third_party/WebKit/Source/devtools/.gitignore b/third_party/WebKit/Source/devtools/.gitignore index 8fa55c0..5ec344e 100644 --- a/third_party/WebKit/Source/devtools/.gitignore +++ b/third_party/WebKit/Source/devtools/.gitignore
@@ -16,4 +16,5 @@ /release /scripts/local_node/runtimes /scripts/visualize_deps/out -/front_end/protocol_externs.js \ No newline at end of file +/front_end/protocol_externs.js +package-lock.json
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js b/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js index 2aa72e8..96629b5a 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
@@ -180,7 +180,7 @@ this._enterProcessedForTest(); return; } - this._appendCommand(str, true); + await this._appendCommand(str, true); this._enterProcessedForTest(); } @@ -188,11 +188,21 @@ * @param {string} text * @param {boolean} useCommandLineAPI */ - _appendCommand(text, useCommandLineAPI) { + async _appendCommand(text, useCommandLineAPI) { this.setText(''); var currentExecutionContext = UI.context.flavor(SDK.ExecutionContext); if (currentExecutionContext) { - ConsoleModel.consoleModel.evaluateCommandInConsole(currentExecutionContext, text, useCommandLineAPI); + var executionContext = currentExecutionContext; + var message = ConsoleModel.consoleModel.addCommandMessage(executionContext, text); + text = SDK.RuntimeModel.wrapObjectLiteralExpressionIfNeeded(text); + var preprocessed = false; + if (text.indexOf('await') !== -1) { + var preprocessedText = await Formatter.formatterWorkerPool().preprocessTopLevelAwaitExpressions(text); + preprocessed = !!preprocessedText; + text = preprocessedText || text; + } + ConsoleModel.consoleModel.evaluateCommandInConsole( + executionContext, message, text, useCommandLineAPI, /* awaitPromise */ preprocessed); if (Console.ConsolePanel.instance().isShowing()) Host.userMetrics.actionTaken(Host.UserMetrics.Action.CommandEvaluatedInConsolePanel); }
diff --git a/third_party/WebKit/Source/devtools/front_end/console/module.json b/third_party/WebKit/Source/devtools/front_end/console/module.json index ed35c62..a810d987 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/module.json +++ b/third_party/WebKit/Source/devtools/front_end/console/module.json
@@ -165,7 +165,8 @@ "data_grid", "object_ui", "console_model", - "product_registry" + "product_registry", + "formatter" ], "scripts": [ "ConsoleContextSelector.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js index 13e5fc0..12f2e08 100644 --- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js +++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -121,33 +121,43 @@ /** * @param {!SDK.ExecutionContext} executionContext - * @param {string} text + * @param {!ConsoleModel.ConsoleMessage} originatingMessage + * @param {string} expression * @param {boolean} useCommandLineAPI + * @param {boolean} awaitPromise */ - async evaluateCommandInConsole(executionContext, text, useCommandLineAPI) { - var commandMessage = new ConsoleModel.ConsoleMessage( - executionContext.runtimeModel, ConsoleModel.ConsoleMessage.MessageSource.JS, null, text, - ConsoleModel.ConsoleMessage.MessageType.Command); - commandMessage.setExecutionContextId(executionContext.id); - this.addMessage(commandMessage); - + async evaluateCommandInConsole(executionContext, originatingMessage, expression, useCommandLineAPI, awaitPromise) { var result = await executionContext.evaluate( { - expression: SDK.RuntimeModel.wrapObjectLiteralExpressionIfNeeded(text), + expression: expression, objectGroup: 'console', includeCommandLineAPI: useCommandLineAPI, silent: false, returnByValue: false, generatePreview: true }, - /* userGesture */ true, /* awaitPromise */ false); + /* userGesture */ true, awaitPromise); Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConsoleEvaluated); if (result.error) return; await Common.console.showPromise(); this.dispatchEventToListeners( ConsoleModel.ConsoleModel.Events.CommandEvaluated, - {result: result.object, commandMessage: commandMessage, exceptionDetails: result.exceptionDetails}); + {result: result.object, commandMessage: originatingMessage, exceptionDetails: result.exceptionDetails}); + } + + /** + * @param {!SDK.ExecutionContext} executionContext + * @param {string} text + * @return {!ConsoleModel.ConsoleMessage} + */ + addCommandMessage(executionContext, text) { + var commandMessage = new ConsoleModel.ConsoleMessage( + executionContext.runtimeModel, ConsoleModel.ConsoleMessage.MessageSource.JS, null, text, + ConsoleModel.ConsoleMessage.MessageType.Command); + commandMessage.setExecutionContextId(executionContext.id); + this.addMessage(commandMessage); + return commandMessage; } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js index 70f2bf7..fd8f9857 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -32,6 +32,7 @@ super(); this.setMinimumSize(96, 26); this.registerRequiredCSS('elements/stylesSidebarPane.css'); + this.element.tabIndex = -1; Common.moduleSetting('colorFormat').addChangeListener(this.update.bind(this)); Common.moduleSetting('textEditorIndent').addChangeListener(this.update.bind(this)); @@ -45,7 +46,12 @@ /** @type {?UI.ToolbarToggle} */ this._pendingWidgetToggle = null; this._toolbarPaneElement = this._createStylesSidebarToolbar(); + this._sectionsContainer = this.contentElement.createChild('div'); + this._sectionsContainer.addEventListener('keydown', this._sectionsContainerKeyDown.bind(this), false); + this._sectionsContainer.addEventListener('focusin', this._sectionsContainerFocusChanged.bind(this), false); + this._sectionsContainer.addEventListener('focusout', this._sectionsContainerFocusChanged.bind(this), false); + this._swatchPopoverHelper = new InlineEditor.SwatchPopoverHelper(); this._linkifier = new Components.Linkifier(Elements.StylesSidebarPane._maxLinkLength, /* useLinkDecorator */ true); /** @type {?Elements.StylePropertyHighlighter} */ @@ -186,6 +192,40 @@ /** * @param {!Event} event */ + _sectionsContainerKeyDown(event) { + var activeElement = this._sectionsContainer.ownerDocument.deepActiveElement(); + if (!activeElement) + return; + var section = activeElement._section; + if (!section) + return; + + switch (event.key) { + case 'ArrowUp': + case 'ArrowLeft': + var sectionToFocus = section.previousSibling() || section.lastSibling(); + sectionToFocus.element.focus(); + event.consume(true); + break; + case 'ArrowDown': + case 'ArrowRight': + var sectionToFocus = section.nextSibling() || section.firstSibling(); + sectionToFocus.element.focus(); + event.consume(true); + break; + } + } + + _sectionsContainerFocusChanged() { + // When a styles section is focused, shift+tab should leave the section. + // Leaving tabIndex = 0 on the first element would cause it to be focused instead. + if (this._sectionBlocks[0] && this._sectionBlocks[0].sections[0]) + this._sectionBlocks[0].sections[0].element.tabIndex = this._sectionsContainer.hasFocus() ? -1 : 0; + } + + /** + * @param {!Event} event + */ _onAddButtonLongClick(event) { var cssModel = this.cssModel(); if (!cssModel) @@ -337,9 +377,26 @@ } /** + * @return {number} + */ + _focusedSectionIndex() { + var index = 0; + for (var block of this._sectionBlocks) { + for (var section of block.sections) { + if (section.element.hasFocus()) + return index; + index++; + } + } + return -1; + } + + /** * @param {?SDK.CSSMatchedStyles} matchedStyles */ _innerRebuildUpdate(matchedStyles) { + var focusedIndex = this._focusedSectionIndex(); + this._linkifier.reset(); this._sectionsContainer.removeChildren(); this._sectionBlocks = []; @@ -371,14 +428,22 @@ block.sections.push(new Elements.KeyframePropertiesSection(this, matchedStyles, keyframe.style)); this._sectionBlocks.push(block); } - + var index = 0; for (var block of this._sectionBlocks) { var titleElement = block.titleElement(); if (titleElement) this._sectionsContainer.appendChild(titleElement); - for (var section of block.sections) + for (var section of block.sections) { this._sectionsContainer.appendChild(section.element); + if (index === focusedIndex) + section.element.focus(); + index++; + } } + if (focusedIndex >= index) + this._sectionBlocks[0].sections[0].element.focus(); + + this._sectionsContainerFocusChanged(); if (this._filterRegex) this._updateFilter(); @@ -695,12 +760,16 @@ var rule = style.parentRule; this.element = createElementWithClass('div', 'styles-section matched-styles monospace'); + this.element.tabIndex = -1; + this._editing = false; + this.element.addEventListener('keydown', this._onKeyDown.bind(this), false); this.element._section = this; this._innerElement = this.element.createChild('div'); this._titleElement = this._innerElement.createChild('div', 'styles-section-title ' + (rule ? 'styles-selector' : '')); this.propertiesTreeOutline = new UI.TreeOutlineInShadow(); + this.propertiesTreeOutline.setFocusable(false); this.propertiesTreeOutline.registerRequiredCSS('elements/stylesSectionTree.css'); this.propertiesTreeOutline.element.classList.add('style-properties', 'matched-styles', 'monospace'); this.propertiesTreeOutline.section = this; @@ -820,6 +889,26 @@ } /** + * @param {!Event} event + */ + _onKeyDown(event) { + if (this._editing || !this.editable || event.altKey || event.ctrlKey || event.metaKey) + return; + switch (event.key) { + case 'Enter': + case ' ': + this._startEditingAtFirstPosition(); + event.consume(true); + break; + default: + // Filter out non-printable key strokes. + if (event.key.length === 1) + this.addNewBlankProperty(0).startEditing(); + break; + } + } + + /** * @param {boolean} isHovered */ _setSectionHovered(isHovered) { @@ -850,25 +939,30 @@ var textShadowButton = new UI.ToolbarButton(Common.UIString('Add text-shadow'), 'largeicon-text-shadow'); textShadowButton.addEventListener( UI.ToolbarButton.Events.Click, this._onInsertShadowPropertyClick.bind(this, 'text-shadow')); + textShadowButton.element.tabIndex = -1; items.push(textShadowButton); var boxShadowButton = new UI.ToolbarButton(Common.UIString('Add box-shadow'), 'largeicon-box-shadow'); boxShadowButton.addEventListener( UI.ToolbarButton.Events.Click, this._onInsertShadowPropertyClick.bind(this, 'box-shadow')); + boxShadowButton.element.tabIndex = -1; items.push(boxShadowButton); var colorButton = new UI.ToolbarButton(Common.UIString('Add color'), 'largeicon-foreground-color'); colorButton.addEventListener(UI.ToolbarButton.Events.Click, this._onInsertColorPropertyClick, this); + colorButton.element.tabIndex = -1; items.push(colorButton); var backgroundButton = new UI.ToolbarButton(Common.UIString('Add background-color'), 'largeicon-background-color'); backgroundButton.addEventListener(UI.ToolbarButton.Events.Click, this._onInsertBackgroundColorPropertyClick, this); + backgroundButton.element.tabIndex = -1; items.push(backgroundButton); var newRuleButton = null; if (this._style.parentRule) { newRuleButton = new UI.ToolbarButton(Common.UIString('Insert Style Rule Below'), 'largeicon-add'); newRuleButton.addEventListener(UI.ToolbarButton.Events.Click, this._onNewRuleClick, this); + newRuleButton.element.tabIndex = -1; items.push(newRuleButton); } @@ -877,6 +971,7 @@ sectionToolbar.appendToolbarItem(items[i]); var menuButton = new UI.ToolbarButton(Common.UIString('More tools\u2026'), 'largeicon-menu'); + menuButton.element.tabIndex = -1; sectionToolbar.appendToolbarItem(menuButton); setItemsVisibility.call(this, items, false); sectionToolbar.element.addEventListener('mouseenter', setItemsVisibility.bind(this, items, true)); @@ -1486,7 +1581,7 @@ event.consume(true); return; } - this._startEditingOnMouseEvent(); + this._startEditingAtFirstPosition(); event.consume(true); } @@ -1506,19 +1601,15 @@ Common.Revealer.reveal(uiLocation, !focus); } - _startEditingOnMouseEvent() { + _startEditingAtFirstPosition() { if (!this.editable || this._isSASSStyle()) return; - var rule = this._style.parentRule; - if (!rule && !this.propertiesTreeOutline.rootElement().childCount()) { - this.addNewBlankProperty().startEditing(); + if (!this._style.parentRule) { + this._moveEditorFromSelector('forward'); return; } - if (!rule) - return; - this.startEditingSelector(); } @@ -1664,6 +1755,7 @@ _startEditing() { this._manuallySetHeight(); this.element.addEventListener('input', this._scheduleHeightUpdate, true); + this._editing = true; } /** @@ -1679,6 +1771,9 @@ this.element.style.removeProperty('height'); this.element.style.removeProperty('contain'); this.element.removeEventListener('input', this._scheduleHeightUpdate, true); + this._editing = false; + if (this._parentPane.element.hasFocus()) + this.element.focus(); } }; @@ -2674,6 +2769,7 @@ (isPropertySplitPaste || moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput)); var section = /** @type {!Elements.StylePropertiesSection} */ (this.section()); if (((userInput !== context.previousContent || isDirtyViaPaste) && !this._newProperty) || shouldCommitNewProperty) { + this._parentPane.element.focus(); section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, section); var propertyText; if (blankInput || (this._newProperty && this.valueElement.textContent.isWhitespace())) {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/stylesSidebarPane.css b/third_party/WebKit/Source/devtools/front_end/elements/stylesSidebarPane.css index 4675fca..536aefe6 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/stylesSidebarPane.css +++ b/third_party/WebKit/Source/devtools/front_end/elements/stylesSidebarPane.css
@@ -29,6 +29,13 @@ background-color: #eee; } +.styles-section[data-keyboard-focus="true"]:focus { + background-color: hsl(214, 67%, 95%); +} +.styles-section.read-only[data-keyboard-focus="true"]:focus { + background-color: hsl(215, 25%, 91%); +} + .styles-filter-engaged, .styles-section .simple-selector.filter-match { background-color: rgba(255, 255, 0, 0.5); @@ -203,6 +210,10 @@ z-index: 0; } +.styles-section[data-keyboard-focus="true"]:focus .sidebar-pane-section-toolbar { + background-color: hsla(214, 67%, 95%, 0.9); +} + .styles-pane:not(.is-editing-style) .styles-section.matched-styles:not(.read-only):hover .sidebar-pane-section-toolbar { visibility: visible; }
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter/FormatterWorkerPool.js b/third_party/WebKit/Source/devtools/front_end/formatter/FormatterWorkerPool.js index 3e80f73c..e24608522 100644 --- a/third_party/WebKit/Source/devtools/front_end/formatter/FormatterWorkerPool.js +++ b/third_party/WebKit/Source/devtools/front_end/formatter/FormatterWorkerPool.js
@@ -151,6 +151,14 @@ /** * @param {string} content + * @return {!Promise<string>} + */ + preprocessTopLevelAwaitExpressions(content) { + return this._runTask('preprocessTopLevelAwaitExpressions', {content: content}).then(text => text || ''); + } + + /** + * @param {string} content * @param {function(boolean, !Array<!Formatter.FormatterWorkerPool.CSSRule>)} callback */ parseCSS(content, callback) {
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormatterWorker.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormatterWorker.js index bfc5fe5..ada92b0 100644 --- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormatterWorker.js +++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormatterWorker.js
@@ -81,6 +81,9 @@ case 'parseJSONRelaxed': FormatterWorker.parseJSONRelaxed(params.content); break; + case 'preprocessTopLevelAwaitExpressions': + FormatterWorker.preprocessTopLevelAwaitExpressions(params.content); + break; default: console.error('Unsupport method name: ' + method); } @@ -138,6 +141,91 @@ /** * @param {string} content */ +FormatterWorker.preprocessTopLevelAwaitExpressions = function(content) { + var wrapped = '(async () => {' + content + '})()'; + var root = acorn.parse(wrapped, {ecmaVersion: 8}); + var body = root.body[0].expression.callee.body; + var changes = []; + var containsAwait = false; + var containsReturn = false; + class Visitor { + ClassDeclaration(node) { + if (node.parent === body) + changes.push({text: node.id.name + '=', start: node.start, end: node.start}); + } + FunctionDeclaration(node) { + changes.push({text: node.id.name + '=', start: node.start, end: node.start}); + return FormatterWorker.ESTreeWalker.SkipSubtree; + } + FunctionExpression(node) { + return FormatterWorker.ESTreeWalker.SkipSubtree; + } + ArrowFunctionExpression(node) { + return FormatterWorker.ESTreeWalker.SkipSubtree; + } + MethodDefinition(node) { + return FormatterWorker.ESTreeWalker.SkipSubtree; + } + AwaitExpression(node) { + containsAwait = true; + } + ReturnStatement(node) { + containsReturn = true; + } + VariableDeclaration(node) { + if (node.kind !== 'var' && node.parent !== body) + return; + var onlyOneDeclaration = node.declarations.length === 1; + changes.push( + {text: onlyOneDeclaration ? 'void' : 'void (', start: node.start, end: node.start + node.kind.length}); + for (var declaration of node.declarations) { + if (!declaration.init) { + changes.push({text: '(', start: declaration.start, end: declaration.start}); + changes.push({text: '=undefined)', start: declaration.end, end: declaration.end}); + continue; + } + changes.push({text: '(', start: declaration.start, end: declaration.start}); + changes.push({text: ')', start: declaration.end, end: declaration.end}); + } + if (!onlyOneDeclaration) { + var last = node.declarations.peekLast(); + changes.push({text: ')', start: last.end, end: last.end}); + } + } + } + var walker = new FormatterWorker.ESTreeWalker(visit.bind(new Visitor())); + walker.walk(body); + /** + * @param {!ESTree.Node} node + * @this {Object} + */ + function visit(node) { + if (node.type in this) + return this[node.type](node); + } + // Top-level return is not allowed. + if (!containsAwait || containsReturn) { + postMessage(''); + return; + } + var last = body.body[body.body.length - 1]; + if (last.type === 'ExpressionStatement') { + changes.push({text: 'return (', start: last.start, end: last.start}); + if (wrapped[last.end - 1] !== ';') + changes.push({text: ')', start: last.end, end: last.end}); + else + changes.push({text: ')', start: last.end - 1, end: last.end - 1}); + } + while (changes.length) { + var change = changes.pop(); + wrapped = wrapped.substr(0, change.start) + change.text + wrapped.substr(change.end); + } + postMessage(wrapped); +}; + +/** + * @param {string} content + */ FormatterWorker.javaScriptIdentifiers = function(content) { var root = acorn.parse(content, {ranges: false, ecmaVersion: 8});
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js index 338eab4..0b29943 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
@@ -60,13 +60,14 @@ if (!(/^\s*\{/.test(code) && /\}\s*$/.test(code))) return code; + var parse = (async () => 0).constructor; try { // Check if the code can be interpreted as an expression. - Function('return ' + code + ';'); + parse('return ' + code + ';'); // No syntax error! Does it work parenthesized? var wrappedCode = '(' + code + ')'; - Function(wrappedCode); + parse(wrappedCode); return wrappedCode; } catch (e) {
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js index c28927dc..1a9181e 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -918,10 +918,13 @@ if (callFunctionResult.wasThrown || !callFunctionResult.object || callFunctionResult.object.type !== 'string') { failedToSave(callFunctionResult.object || null); } else { + var executionContext = /** @type {!SDK.ExecutionContext} */ (currentExecutionContext); + var text = /** @type {string} */ (callFunctionResult.object.value); + var message = ConsoleModel.consoleModel.addCommandMessage(executionContext, text); + text = SDK.RuntimeModel.wrapObjectLiteralExpressionIfNeeded(text); ConsoleModel.consoleModel.evaluateCommandInConsole( - /** @type {!SDK.ExecutionContext} */ (currentExecutionContext), - /** @type {string} */ (callFunctionResult.object.value), - /* useCommandLineAPI */ false); + executionContext, message, text, + /* useCommandLineAPI */ false, /* awaitPromise */ false); } if (callFunctionResult.object) callFunctionResult.object.release(); @@ -1247,8 +1250,12 @@ if (frame) { var text = frame.textEditor.text(frame.textEditor.selection()); var executionContext = UI.context.flavor(SDK.ExecutionContext); - if (executionContext) - ConsoleModel.consoleModel.evaluateCommandInConsole(executionContext, text, /* useCommandLineAPI */ true); + if (executionContext) { + var message = ConsoleModel.consoleModel.addCommandMessage(executionContext, text); + text = SDK.RuntimeModel.wrapObjectLiteralExpressionIfNeeded(text); + ConsoleModel.consoleModel.evaluateCommandInConsole( + executionContext, message, text, /* useCommandLineAPI */ true, /* awaitPromise */ false); + } } return true; }
diff --git a/third_party/WebKit/Source/devtools/front_end/unit_test_runner.json b/third_party/WebKit/Source/devtools/front_end/unit_test_runner.json index b129e67..9034d72 100644 --- a/third_party/WebKit/Source/devtools/front_end/unit_test_runner.json +++ b/third_party/WebKit/Source/devtools/front_end/unit_test_runner.json
@@ -19,7 +19,8 @@ { "name": "protocol" }, { "name": "data_grid" }, { "name": "product_registry" }, - { "name": "product_registry_impl" } + { "name": "product_registry_impl" }, + { "name": "formatter" } ], "has_html": true }
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp index f1f0539..64dd7ee3 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -201,7 +201,6 @@ const CanvasColorParams& color_params, bool is_unit_test) : ImageBufferSurface(size, opacity_mode, color_params), - context_provider_wrapper_(SharedGpuContext::ContextProviderWrapper()), logger_(WTF::WrapUnique(new Logger)), weak_ptr_factory_(this), image_buffer_(0), @@ -219,8 +218,12 @@ opacity_mode_(opacity_mode), size_(size), color_params_(color_params) { - DCHECK(context_provider_wrapper_); - DCHECK(!context_provider_wrapper_->ContextProvider()->IsSoftwareRendering()); + if (acceleration_mode != kDisableAcceleration) { + context_provider_wrapper_ = SharedGpuContext::ContextProviderWrapper(); + DCHECK(context_provider_wrapper_); + DCHECK( + !context_provider_wrapper_->ContextProvider()->IsSoftwareRendering()); + } DCHECK(color_params_.GetGfxColorSpace().IsValid()); // Used by browser tests to detect the use of a Canvas2DLayerBridge. TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation",
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py index c786b93..ca47c43 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
@@ -31,8 +31,8 @@ This includes finding tests to run, reading the test expectations, starting the required helper servers, deciding the order and way to -run the tests, retrying fails tests and collecting the test results, -including crash logs, and mismatches with expectations. +run the tests, retrying failed tests, and collecting the test results, +including crash logs and mismatches with expectations. The Manager object has a constructor and one main method called run. """ @@ -72,12 +72,12 @@ ARCHIVED_RESULTS_LIMIT = 25 def __init__(self, port, options, printer): - """Initialize test runner data structures. + """Initializes test runner data structures. Args: - port: An object implementing platform-specific functionality. - options: An options argument which contains command line options. - printer: A Printer object to record updates to. + port: An object implementing platform-specific functionality. + options: An options argument which contains command line options. + printer: A Printer object to record updates to. """ self._port = port self._filesystem = port.host.filesystem @@ -95,7 +95,7 @@ self._runner = LayoutTestRunner(self._options, self._port, self._printer, self._results_directory, self._test_is_slow) def run(self, args): - """Run the tests and return a RunDetails object with the results.""" + """Runs the tests and return a RunDetails object with the results.""" start_time = time.time() self._printer.write_update('Collecting tests ...') running_all_tests = False @@ -273,7 +273,7 @@ self._test_requires_lock(test_file)) def _test_requires_lock(self, test_file): - """Return True if the test needs to be locked when running multiple + """Returns True if the test needs to be locked when running multiple instances of this test runner. Perf tests are locked because heavy load caused by running other @@ -414,9 +414,9 @@ under stress, do a second pass at the end of the test run. Args: - run_results: The results of the test run. - start_time: Time the tests started at. We're looking for crash - logs after that time. + run_results: The results of the test run. + start_time: Time the tests started at. We're looking for crash + logs after that time. """ crashed_processes = [] for test, result in run_results.unexpected_results_by_name.iteritems():
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py index b871fb76..f5449300 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -102,7 +102,7 @@ action='append', default=[], dest='adb_devices', - help='Run Android layout tests on these devices.'), + help='Run Android layout tests on these devices'), # FIXME: Flip this to be off by default once we can log the # device setup more cleanly. optparse.make_option( @@ -110,8 +110,8 @@ dest='android_logging', action='store_false', default=True, - help=('Do not log android-specific debug messages (default is to log as part ' - 'of --debug-rwt-logging')), + help=('Do not log android-specific debug messages (default ' + 'is to log as part of --debug-rwt-logging)')), ])) option_group_definitions.append( @@ -183,7 +183,7 @@ '--new-flag-specific-baseline', action='store_true', default=False, - help=('Together with --addtional-driver-flag, if actual results are ' + help=('Together with --additional-driver-flag, if actual results are ' 'different from expected, save actual results as new baselines ' 'into the flag-specific generic-platform directory.')), optparse.make_option( @@ -413,10 +413,10 @@ action='store', default=None, help=('control how tests marked SKIP are run. ' - "'default' == Skip tests unless explicitly listed on the command line, " - "'ignore' == Run them anyway, " - "'only' == only run the SKIP tests, " - "'always' == always skip, even if listed on the command line.")), + '"default" == Skip tests unless explicitly listed on the command line, ' + '"ignore" == Run them anyway, ' + '"only" == only run the SKIP tests, ' + '"always" == always skip, even if listed on the command line.')), optparse.make_option( '--fastest', action='store', @@ -433,9 +433,9 @@ optparse.make_option( '--wrapper', help=('wrapper command to insert before invocations of the driver; option ' - "is split on whitespace before running. (Example: --wrapper='valgrind " - "--smc-check=all')")), - # FIXME: Display default number of child processes that will run. + 'is split on whitespace before running. (Example: --wrapper="valgrind ' + '--smc-check=all")')), + # FIXME: Display the default number of child processes that will run. optparse.make_option( '-f', '--fully-parallel', action='store_true', @@ -502,11 +502,11 @@ options.batch_size = port.default_batch_size() if not options.child_processes: - options.child_processes = port.host.environ.get('WEBKIT_TEST_CHILD_PROCESSES', - str(port.default_child_processes())) + options.child_processes = port.host.environ.get( + 'WEBKIT_TEST_CHILD_PROCESSES', str(port.default_child_processes())) if not options.max_locked_shards: - options.max_locked_shards = int(port.host.environ.get('WEBKIT_TEST_MAX_LOCKED_SHARDS', - str(port.default_max_locked_shards()))) + options.max_locked_shards = int(port.host.environ.get( + 'WEBKIT_TEST_MAX_LOCKED_SHARDS', str(port.default_max_locked_shards()))) if not options.configuration: options.configuration = port.default_configuration() @@ -601,12 +601,12 @@ stdout.flush() _log.debug('') - _log.debug('Testing completed, Exit status: %d', run_details.exit_code) + _log.debug('Testing completed. Exit status: %d', run_details.exit_code) return run_details finally: printer.cleanup() + if __name__ == '__main__': - exit_code = main(sys.argv[1:], sys.stdout, sys.stderr) - sys.exit(exit_code) + sys.exit(main(sys.argv[1:], sys.stdout, sys.stderr))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/views/buildbot_results.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/views/buildbot_results.py index e45f283..d7a4078 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/views/buildbot_results.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/views/buildbot_results.py
@@ -34,9 +34,11 @@ class BuildBotPrinter(object): - # This output is parsed by buildbots and must only be changed in coordination with buildbot scripts (see webkit.org's - # Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg: RunWebKitTests._parseNewRunWebKitTestsOutput - # and chromium.org's buildbot/master.chromium/scripts/master/log_parser/webkit_test_command.py). + # This output was previously parsed on buildbot runs by + # build/scripts/master/log_parser/webkit_test_command.py, + # but this is no longer the case. + # TODO(qyearsley): Remove this module, and potentially + # move any useful printing to printing.py. def __init__(self, stream, debug_logging): self.stream = stream @@ -63,9 +65,6 @@ self._print_run_results_entry(run_results, test_expectations.NOW, 'Tests to be fixed') self._print('') - # FIXME: We should be skipping anything marked WONTFIX, so we shouldn't bother logging these stats. - self._print_run_results_entry(run_results, test_expectations.WONTFIX, - 'Tests that will only be fixed if they crash (WONTFIX)') self._print('') def _print_run_results_entry(self, run_results, timeline, heading):
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index e06a2d3..7799699 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -603,7 +603,6 @@ "web/WebTextCheckingResult.h", "web/WebTextDecorationType.h", "web/WebTextDirection.h", - "web/WebTextInputType.h", "web/WebTreeScopeType.h", "web/WebTriggeringEventInfo.h", "web/WebUserGestureIndicator.h",
diff --git a/third_party/WebKit/public/platform/WebMediaPlayerClient.h b/third_party/WebKit/public/platform/WebMediaPlayerClient.h index 880b58f..c05d4591 100644 --- a/third_party/WebKit/public/platform/WebMediaPlayerClient.h +++ b/third_party/WebKit/public/platform/WebMediaPlayerClient.h
@@ -33,6 +33,7 @@ #include "WebCommon.h" #include "WebMediaPlayer.h" +#include "ui/gfx/color_space.h" namespace blink { @@ -138,6 +139,10 @@ // any. virtual WebRemotePlaybackClient* RemotePlaybackClient() { return nullptr; }; + // Returns the color space to render media into if. + // Rendering media into this color space may avoid some conversions. + virtual gfx::ColorSpace TargetColorSpace() { return gfx::ColorSpace(); } + protected: ~WebMediaPlayerClient() = default; };
diff --git a/third_party/WebKit/public/web/WebInputMethodController.h b/third_party/WebKit/public/web/WebInputMethodController.h index 86a2e24..d95ee7e 100644 --- a/third_party/WebKit/public/web/WebInputMethodController.h +++ b/third_party/WebKit/public/web/WebInputMethodController.h
@@ -7,7 +7,6 @@ #include "public/platform/WebTextInputInfo.h" #include "WebCompositionUnderline.h" -#include "WebTextInputType.h" #include "WebWidget.h" namespace blink {
diff --git a/third_party/WebKit/public/web/WebTextInputType.h b/third_party/WebKit/public/web/WebTextInputType.h deleted file mode 100644 index 070d5814..0000000 --- a/third_party/WebKit/public/web/WebTextInputType.h +++ /dev/null
@@ -1,93 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebTextInputType_h -#define WebTextInputType_h - -namespace blink { - -enum WebTextInputType { - // Input caret is not in an editable node, no input method shall be used. - WebTextInputTypeNone, - - // Input caret is in a normal editable node, any input method can be used. - WebTextInputTypeText, - - // Input caret is in a specific input field, and input method may be used - // only if it's suitable for the specific input field. - WebTextInputTypePassword, - WebTextInputTypeSearch, - WebTextInputTypeEmail, - WebTextInputTypeNumber, - WebTextInputTypeTelephone, - WebTextInputTypeURL, - - // FIXME: Remove these types once Date like types are not - // seen as Text. For now they also exist in WebTextInputType - WebTextInputTypeDate, - WebTextInputTypeDateTime, - WebTextInputTypeDateTimeLocal, - WebTextInputTypeMonth, - WebTextInputTypeTime, - WebTextInputTypeWeek, - WebTextInputTypeTextArea, - - // Input caret is in a contenteditable node (not an INPUT field). - WebTextInputTypeContentEditable, - - // The focused node is date time field. The date time field does not have - // input caret but it is necessary to distinguish from WebTextInputTypeNone - // for on-screen keyboard. - WebTextInputTypeDateTimeField, -}; - -// Separate on/off flags are defined so that the input mechanism can choose -// an appropriate default based on other things (like InputType and direct -// knowledge of the actual input system) if there are no overrides. -// -// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web -// GENERATED_JAVA_PREFIX_TO_STRIP: WebTextInputFlag -enum WebTextInputFlags { - WebTextInputFlagNone = 0, - WebTextInputFlagAutocompleteOn = 1 << 0, - WebTextInputFlagAutocompleteOff = 1 << 1, - WebTextInputFlagAutocorrectOn = 1 << 2, - WebTextInputFlagAutocorrectOff = 1 << 3, - WebTextInputFlagSpellcheckOn = 1 << 4, - WebTextInputFlagSpellcheckOff = 1 << 5, - WebTextInputFlagAutocapitalizeNone = 1 << 6, - WebTextInputFlagAutocapitalizeCharacters = 1 << 7, - WebTextInputFlagAutocapitalizeWords = 1 << 8, - WebTextInputFlagAutocapitalizeSentences = 1 << 9 -}; - -} // namespace blink - -#endif
diff --git a/third_party/snappy/README.chromium b/third_party/snappy/README.chromium index f0a0ec3..9cf4e95 100644 --- a/third_party/snappy/README.chromium +++ b/third_party/snappy/README.chromium
@@ -1,7 +1,7 @@ Name: Snappy: A fast compressor/decompressor Short Name: snappy URL: http://google.github.io/snappy/ -Version: 1.1.5 +Version: 1.1.6.git.77c12adc192ac6620a0f0d340c99149ec56a97a3 License: New BSD License File: src/COPYING Security Critical: yes
diff --git a/third_party/snappy/linux/config.h b/third_party/snappy/linux/config.h index 80e39be9..6c51dba 100644 --- a/third_party/snappy/linux/config.h +++ b/third_party/snappy/linux/config.h
@@ -1,5 +1,5 @@ -#ifndef SNAPPY_CONFIG_H -#define SNAPPY_CONFIG_H 1 +#ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_ +#define THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_ /* Define to 1 if the compiler supports __builtin_ctz and friends. */ #define HAVE_BUILTIN_CTZ 1 @@ -10,48 +10,30 @@ /* Define to 1 if you have the <byteswap.h> header file. */ #define HAVE_BYTESWAP_H 1 -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 +/* Define to 1 if you have a definition for mmap() in <sys/mman.h>. */ +#define HAVE_FUNC_MMAP 1 -/* Use the gflags package for command-line parsing. */ +/* Define to 1 if you have a definition for sysconf() in <unistd.h>. */ +#define HAVE_FUNC_SYSCONF 1 + +/* Define to 1 to use the gflags package for command-line parsing. */ /* #undef HAVE_GFLAGS */ -/* Defined when Google Test is available. */ +/* Define to 1 if you have Google Test. */ /* #undef HAVE_GTEST */ -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - /* Define to 1 if you have the `lzo2' library (-llzo2). */ /* #undef HAVE_LIBLZO2 */ /* Define to 1 if you have the `z' library (-lz). */ #define HAVE_LIBZ 1 -/* Define to 1 if you have the <sys/uio.h> header file. */ -#define HAVE_SYS_UIO_H 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - /* Define to 1 if you have the <stddef.h> header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the <stdint.h> header file. */ #define HAVE_STDINT_H 1 -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the <sys/byteswap.h> header file. */ -/* #undef HAVE_SYS_BYTESWAP_H */ - /* Define to 1 if you have the <sys/endian.h> header file. */ /* #undef HAVE_SYS_ENDIAN_H */ @@ -61,14 +43,11 @@ /* Define to 1 if you have the <sys/resource.h> header file. */ #define HAVE_SYS_RESOURCE_H 1 -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - /* Define to 1 if you have the <sys/time.h> header file. */ #define HAVE_SYS_TIME_H 1 -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 +/* Define to 1 if you have the <sys/uio.h> header file. */ +#define HAVE_SYS_UIO_H 1 /* Define to 1 if you have the <unistd.h> header file. */ #define HAVE_UNISTD_H 1 @@ -76,15 +55,8 @@ /* Define to 1 if you have the <windows.h> header file. */ /* #undef HAVE_WINDOWS_H */ -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ /* #undef WORDS_BIGENDIAN */ -#if defined(_MSC_VER) && (_MSC_VER <= 1900) -typedef __int64 ssize_t; -#endif - -#endif +#endif // THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_
diff --git a/third_party/snappy/linux/snappy-stubs-public.h b/third_party/snappy/linux/snappy-stubs-public.h index b8a60c6..394d512 100644 --- a/third_party/snappy/linux/snappy-stubs-public.h +++ b/third_party/snappy/linux/snappy-stubs-public.h
@@ -36,21 +36,21 @@ #ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ #define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ -#if 1 +#if 1 // HAVE_STDINT_H #include <stdint.h> -#endif +#endif // HAVE_STDDEF_H -#if 1 +#if 1 // HAVE_STDDEF_H #include <stddef.h> -#endif +#endif // HAVE_STDDEF_H -#if 1 +#if 1 // HAVE_SYS_UIO_H #include <sys/uio.h> -#endif +#endif // HAVE_SYS_UIO_H #define SNAPPY_MAJOR 1 #define SNAPPY_MINOR 1 -#define SNAPPY_PATCHLEVEL 5 +#define SNAPPY_PATCHLEVEL 6 #define SNAPPY_VERSION \ ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL) @@ -58,7 +58,7 @@ namespace snappy { -#if 1 +#if 1 // HAVE_STDINT_H typedef int8_t int8; typedef uint8_t uint8; typedef int16_t int16; @@ -76,24 +76,18 @@ typedef unsigned int uint32; typedef long long int64; typedef unsigned long long uint64; -#endif +#endif // HAVE_STDINT_H typedef std::string string; -#ifndef DISALLOW_COPY_AND_ASSIGN -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) -#endif - -#if !1 +#if !1 // !HAVE_SYS_UIO_H // Windows does not have an iovec type, yet the concept is universally useful. // It is simple to define it ourselves, so we put it inside our own namespace. struct iovec { void* iov_base; size_t iov_len; }; -#endif +#endif // !HAVE_SYS_UIO_H } // namespace snappy
diff --git a/third_party/snappy/mac/config.h b/third_party/snappy/mac/config.h index 4b29b41..bedcfb7a 100644 --- a/third_party/snappy/mac/config.h +++ b/third_party/snappy/mac/config.h
@@ -1,5 +1,5 @@ -#ifndef SNAPPY_CONFIG_H -#define SNAPPY_CONFIG_H 1 +#ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_ +#define THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_ /* Define to 1 if the compiler supports __builtin_ctz and friends. */ #define HAVE_BUILTIN_CTZ 1 @@ -10,48 +10,30 @@ /* Define to 1 if you have the <byteswap.h> header file. */ /* #undef HAVE_BYTESWAP_H */ -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 +/* Define to 1 if you have a definition for mmap() in <sys/mman.h>. */ +#define HAVE_FUNC_MMAP 1 -/* Use the gflags package for command-line parsing. */ +/* Define to 1 if you have a definition for sysconf() in <unistd.h>. */ +#define HAVE_FUNC_SYSCONF 1 + +/* Define to 1 to use the gflags package for command-line parsing. */ /* #undef HAVE_GFLAGS */ -/* Defined when Google Test is available. */ +/* Define to 1 if you have Google Test. */ /* #undef HAVE_GTEST */ -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - /* Define to 1 if you have the `lzo2' library (-llzo2). */ /* #undef HAVE_LIBLZO2 */ /* Define to 1 if you have the `z' library (-lz). */ #define HAVE_LIBZ 1 -/* Define to 1 if you have the <sys/uio.h> header file. */ -#define HAVE_SYS_UIO_H 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - /* Define to 1 if you have the <stddef.h> header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the <stdint.h> header file. */ #define HAVE_STDINT_H 1 -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the <sys/byteswap.h> header file. */ -/* #undef HAVE_SYS_BYTESWAP_H */ - /* Define to 1 if you have the <sys/endian.h> header file. */ /* #undef HAVE_SYS_ENDIAN_H */ @@ -61,14 +43,11 @@ /* Define to 1 if you have the <sys/resource.h> header file. */ #define HAVE_SYS_RESOURCE_H 1 -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - /* Define to 1 if you have the <sys/time.h> header file. */ #define HAVE_SYS_TIME_H 1 -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 +/* Define to 1 if you have the <sys/uio.h> header file. */ +#define HAVE_SYS_UIO_H 1 /* Define to 1 if you have the <unistd.h> header file. */ #define HAVE_UNISTD_H 1 @@ -76,15 +55,8 @@ /* Define to 1 if you have the <windows.h> header file. */ /* #undef HAVE_WINDOWS_H */ -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ /* #undef WORDS_BIGENDIAN */ -#if defined(_MSC_VER) && (_MSC_VER <= 1900) -typedef __int64 ssize_t; -#endif - -#endif +#endif // THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_
diff --git a/third_party/snappy/mac/snappy-stubs-public.h b/third_party/snappy/mac/snappy-stubs-public.h index b8a60c6..91c3de97 100644 --- a/third_party/snappy/mac/snappy-stubs-public.h +++ b/third_party/snappy/mac/snappy-stubs-public.h
@@ -50,7 +50,7 @@ #define SNAPPY_MAJOR 1 #define SNAPPY_MINOR 1 -#define SNAPPY_PATCHLEVEL 5 +#define SNAPPY_PATCHLEVEL 6 #define SNAPPY_VERSION \ ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL)
diff --git a/third_party/snappy/win32/config.h b/third_party/snappy/win32/config.h index 71fd1d8..75fcea87 100644 --- a/third_party/snappy/win32/config.h +++ b/third_party/snappy/win32/config.h
@@ -1,5 +1,5 @@ -#ifndef SNAPPY_CONFIG_H -#define SNAPPY_CONFIG_H 1 +#ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_ +#define THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_ /* Define to 1 if the compiler supports __builtin_ctz and friends. */ /* #undef HAVE_BUILTIN_CTZ */ @@ -10,48 +10,30 @@ /* Define to 1 if you have the <byteswap.h> header file. */ /* #undef HAVE_BYTESWAP_H */ -/* Define to 1 if you have the <dlfcn.h> header file. */ -/* #undef HAVE_DLFCN_H */ +/* Define to 1 if you have a definition for mmap() in <sys/mman.h>. */ +/* #undef HAVE_FUNC_MMAP */ -/* Use the gflags package for command-line parsing. */ +/* Define to 1 if you have a definition for sysconf() in <unistd.h>. */ +/* #undef HAVE_FUNC_SYSCONF */ + +/* Define to 1 to use the gflags package for command-line parsing. */ /* #undef HAVE_GFLAGS */ -/* Defined when Google Test is available. */ +/* Define to 1 if you have Google Test. */ /* #undef HAVE_GTEST */ -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - /* Define to 1 if you have the `lzo2' library (-llzo2). */ /* #undef HAVE_LIBLZO2 */ /* Define to 1 if you have the `z' library (-lz). */ /* #undef HAVE_LIBZ */ -/* Define to 1 if you have the <sys/uio.h> header file. */ -/* #undef HAVE_SYS_UIO_H */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - /* Define to 1 if you have the <stddef.h> header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the <stdint.h> header file. */ #define HAVE_STDINT_H 1 -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -/* #undef HAVE_STRINGS_H */ - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the <sys/byteswap.h> header file. */ -/* #undef HAVE_SYS_BYTESWAP_H */ - /* Define to 1 if you have the <sys/endian.h> header file. */ /* #undef HAVE_SYS_ENDIAN_H */ @@ -61,14 +43,11 @@ /* Define to 1 if you have the <sys/resource.h> header file. */ /* #undef HAVE_SYS_RESOURCE_H */ -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - /* Define to 1 if you have the <sys/time.h> header file. */ /* #undef HAVE_SYS_TIME_H */ -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H +/* Define to 1 if you have the <sys/uio.h> header file. */ +/* #undef HAVE_SYS_UIO_H */ /* Define to 1 if you have the <unistd.h> header file. */ /* #undef HAVE_UNISTD_H */ @@ -76,15 +55,8 @@ /* Define to 1 if you have the <windows.h> header file. */ #define HAVE_WINDOWS_H 1 -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ /* #undef WORDS_BIGENDIAN */ -#if defined(_MSC_VER) && (_MSC_VER <= 1900) -typedef __int64 ssize_t; -#endif - -#endif +#endif // THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_
diff --git a/third_party/snappy/win32/snappy-stubs-public.h b/third_party/snappy/win32/snappy-stubs-public.h index 7c71efb..afe3c84 100644 --- a/third_party/snappy/win32/snappy-stubs-public.h +++ b/third_party/snappy/win32/snappy-stubs-public.h
@@ -36,21 +36,21 @@ #ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ #define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ -#if 1 +#if 1 // HAVE_STDINT_H #include <stdint.h> -#endif +#endif // HAVE_STDDEF_H -#if 1 +#if 1 // HAVE_STDDEF_H #include <stddef.h> -#endif +#endif // HAVE_STDDEF_H -#if 0 +#if 0 // HAVE_SYS_UIO_H #include <sys/uio.h> -#endif +#endif // HAVE_SYS_UIO_H #define SNAPPY_MAJOR 1 #define SNAPPY_MINOR 1 -#define SNAPPY_PATCHLEVEL 5 +#define SNAPPY_PATCHLEVEL 6 #define SNAPPY_VERSION \ ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL) @@ -58,7 +58,7 @@ namespace snappy { -#if 1 +#if 1 // HAVE_STDINT_H typedef int8_t int8; typedef uint8_t uint8; typedef int16_t int16; @@ -76,24 +76,18 @@ typedef unsigned int uint32; typedef long long int64; typedef unsigned long long uint64; -#endif +#endif // HAVE_STDINT_H typedef std::string string; -#ifndef DISALLOW_COPY_AND_ASSIGN -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) -#endif - -#if !0 +#if !0 // !HAVE_SYS_UIO_H // Windows does not have an iovec type, yet the concept is universally useful. // It is simple to define it ourselves, so we put it inside our own namespace. struct iovec { void* iov_base; size_t iov_len; }; -#endif +#endif // !HAVE_SYS_UIO_H } // namespace snappy
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a2250a4..507809d 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -22634,6 +22634,16 @@ <int value="4" label="Success"/> </enum> +<enum name="LockScreenDataItemOperationResult"> + <int value="0" label="Success"/> + <int value="1" label="Operation failed"/> + <int value="2" label="Data item not found"/> + <int value="3" label="Unknown app"/> + <int value="4" label="Item already registered"/> + <int value="5" label="Invalid encryption key"/> + <int value="6" label="Wrong encryption key"/> +</enum> + <enum name="LockScreenProgress"> <int value="0" label="Start screen lock"/> <int value="1" label="Enter password correctly"/> @@ -31923,6 +31933,12 @@ <int value="12" label="csv"/> </enum> +<enum name="QuicNotReusableReason"> + <int value="0" label="NULLPTR"/> + <int value="1" label="TOO_SMALL"/> + <int value="2" label="REF_COUNT"/> +</enum> + <enum name="QuicRejectReasons"> <int value="1" label="CLIENT_NONCE_UNKNOWN_FAILURE"/> <int value="2" label="CLIENT_NONCE_INVALID_FAILURE"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index f42bdddd..d086ac2 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -1748,6 +1748,61 @@ </summary> </histogram> +<histogram name="Apps.LockScreen.DataItemStorage.ClearTextItemSize" + units="bytes"> + <owner>tbarzic@chromium.org</owner> + <summary> + The size of a data item stored in the lock screen data item storage using + chrome.lockScreen.data API as sent from the app - the item will be encrypted + before getting stored in the storage. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.DataItemStorage.EncryptedItemSize" + units="bytes"> + <owner>tbarzic@chromium.org</owner> + <summary> + The size of an encrypted data item stored in the lock screen data item + storage using chrome.lockScreen.data API. + </summary> +</histogram> + +<histogram base="true" + name="Apps.LockScreen.DataItemStorage.FailedOperationDuration" units="ms"> + <owner>tbarzic@chromium.org</owner> + <summary> + The amount of time it took to complete a lock screen data item storage + operation. Reported only on the operation failure. + </summary> +</histogram> + +<histogram base="true" name="Apps.LockScreen.DataItemStorage.OperationDuration" + units="ms"> + <owner>tbarzic@chromium.org</owner> + <summary> + The amount of time it took to complete a lock screen data item storage + operation. Reported only on the operation success. + </summary> +</histogram> + +<histogram base="true" name="Apps.LockScreen.DataItemStorage.OperationResult" + enum="LockScreenDataItemOperationResult"> + <owner>tbarzic@chromium.org</owner> + <summary> + The result of a lock screen data item storage operation returned through + chrome.lockScreen.data extension API. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.DataItemStorage.RegisteredItemsCount"> + <owner>tbarzic@chromium.org</owner> + <summary> + The number of data items saved in the lock screen data item storage per app. + This is recorded on startup, when the app attempts to use the + chrome.lockScreen.data API. + </summary> +</histogram> + <histogram name="Apps.NoteTakingApp.DefaultLaunchResult" enum="NoteTakingAppLaunchResult"> <owner>derat@chromium.org</owner> @@ -41469,6 +41524,15 @@ </summary> </histogram> +<histogram name="Net.QuicSession.WritePacketNotReusableReason" + enum="QuicNotReusableReason"> + <owner>ckrasic@chromium.org</owner> + <summary> + The reason QUIC packet writer needed to allocate a new buffer, rather than + the expected case of reusing its existing one. + </summary> +</histogram> + <histogram name="Net.QuicStreamFactory.BadPacketLossEvents5" enum="QuicBadPacketLossEvents"> <owner>rch@chromium.org</owner> @@ -94129,6 +94193,18 @@ <affected-histogram name="Renderer4.LockExistingCachedImage"/> </histogram_suffixes> +<histogram_suffixes name="LockScreenAppDataItemOperation" separator="."> + <suffix name="GetRegisteredItems"/> + <suffix name="RegisterItem"/> + <suffix name="WriteItem"/> + <suffix name="ReadItem"/> + <suffix name="DeleteItem"/> + <affected-histogram + name="Apps.LockScreen.DataItemStorage.FailedOperationDuration"/> + <affected-histogram name="Apps.LockScreen.DataItemStorage.OperationDuration"/> + <affected-histogram name="Apps.LockScreen.DataItemStorage.OperationResult"/> +</histogram_suffixes> + <histogram_suffixes name="LowMemoryMargin" separator="_"> <suffix name="default" label="Low memory margin set to the system default"/> <suffix name="off" label="Low memory notification disabled"/>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index f2e2232..0de1fd6 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -24,6 +24,7 @@ from telemetry import benchmark as benchmark_module from telemetry import decorators +from telemetry.story import expectations from py_utils import discover @@ -1012,7 +1013,11 @@ benchmark_list = current_benchmarks() for benchmark in benchmark_list: - disabled = 'all' in decorators.GetDisabledAttributes(benchmark) + exp = benchmark().GetExpectations() + disabled = 'all' in decorators.GetDisabledAttributes(benchmark) or any( + any(isinstance(condition, expectations.ALL.__class__) + for condition in conditions) + for (conditions, _) in exp.disabled_platforms) emails = decorators.GetEmails(benchmark) if emails:
diff --git a/ui/gfx/native_widget_types.h b/ui/gfx/native_widget_types.h index 517bd40..ca40bc68 100644 --- a/ui/gfx/native_widget_types.h +++ b/ui/gfx/native_widget_types.h
@@ -11,7 +11,7 @@ #include "build/build_config.h" #if defined(OS_ANDROID) -#include <jni.h> +#include "base/android/scoped_java_ref.h" #elif defined(OS_MACOSX) #include <objc/objc.h> #endif @@ -132,7 +132,7 @@ typedef void* NativeCursor; typedef ui::ViewAndroid* NativeView; typedef ui::WindowAndroid* NativeWindow; -typedef jobject NativeEvent; +typedef base::android::ScopedJavaGlobalRef<jobject> NativeEvent; #else #error Unknown build environment. #endif
diff --git a/ui/login/account_picker/md_screen_account_picker.css b/ui/login/account_picker/md_screen_account_picker.css index 6e69f2b..81b4625f 100644 --- a/ui/login/account_picker/md_screen_account_picker.css +++ b/ui/login/account_picker/md_screen_account_picker.css
@@ -74,10 +74,6 @@ position: absolute; } -.small-pod-container.scroll { - background-color: rgba(0, 0, 0, 0.3); -} - .small-pod-container.images-loading { visibility: hidden; } @@ -105,7 +101,6 @@ } .small-pod-container-mask { - background: linear-gradient(#000, transparent); height: 112px; position: absolute; width: 100%;
diff --git a/ui/resources/BUILD.gn b/ui/resources/BUILD.gn index e81141e..cee10c4 100644 --- a/ui/resources/BUILD.gn +++ b/ui/resources/BUILD.gn
@@ -238,7 +238,7 @@ } # Repack just the strings for the framework locales on Mac and iOS. This -# emulates repack_locales.py, but just for en-US. Note ui_test.pak is not simply +# emulates repack_locales(), but just for en-US. Note ui_test.pak is not simply # copied, because it causes leaks from allocations within system libraries when # trying to load non-string resources. http://crbug.com/413034. repack("repack_ui_test_mac_locale_pack") {