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(&registry_);
+#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(&registry_);
+    input_device_server_.AddInterface(&registry_with_source_info_);
 
 #if defined(USE_OZONE)
-  ui::OzonePlatform::GetInstance()->AddInterfaces(&registry_);
+  ui::OzonePlatform::GetInstance()->AddInterfaces(&registry_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(&registry_);
+  screen_manager_->AddInterfaces(&registry_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") {