diff --git a/tools/android/roll/android_deps/build.gradle b/tools/android/roll/android_deps/build.gradle
index b5a6f30e..74bae36 100644
--- a/tools/android/roll/android_deps/build.gradle
+++ b/tools/android/roll/android_deps/build.gradle
@@ -39,7 +39,7 @@
     compile "com.google.android.gms:play-services-vision:${gmsVersion}"
     compile "com.google.android.gms:play-services-fido:${gmsVersion}"
 
-    compile "com.google.android.play:core:1.3.0"
+    compile "com.google.android.play:core:1.3.5"
 
     // Support v4 libraries
     def supportLibVersion = '27.0.0'
diff --git a/tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy b/tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
index af6e50c..955e62f 100644
--- a/tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
+++ b/tools/android/roll/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
@@ -155,11 +155,15 @@
     private customizeDep(DependencyDescription dep) {
         if (dep.id?.startsWith("com_google_android_")) {
             dep.licenseUrl = ""
-            // This should match fetch_all._ANDROID_SDK_LICENSE_PATH
+            // This should match fetch_all._ANDROID_SDK_LICENSE_PATH.
             dep.licensePath = "licenses/Android_SDK_License-December_9_2016.txt"
             if (dep.url?.isEmpty()) {
                 dep.url = "https://developers.google.com/android/guides/setup"
             }
+        } else if (dep.licenseUrl?.equals("http://openjdk.java.net/legal/gplv2+ce.html")) {
+            // This avoids using html in a LICENSE file.
+            dep.licenseUrl = ""
+            dep.licensePath = "licenses/GNU_v2_with_Classpath_Exception_1991.txt"
         } else if (dep.licenseName?.isEmpty()) {
             def fallbackProperties = FALLBACK_PROPERTIES.get(dep.id)
             if (fallbackProperties != null) {
diff --git a/tools/android/ui/generate_spline_constants.py b/tools/android/ui/generate_spline_constants.py
new file mode 100755
index 0000000..3642d42
--- /dev/null
+++ b/tools/android/ui/generate_spline_constants.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Generates Java code to declare SPLINE_POSITION and SPLINE_TIME as precomputed
+array.
+
+Run this and paste the output into //chrome/android/java/src/org/chromium/
+chrome/browser/compositor/layouts/phone/stack/StackScroller.java
+"""
+
+import math
+import sys
+
+def Main():
+    # Keep these in sync with the values in //chrome/android/java/src/org/
+    # chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java
+    NB_SAMPLES = 100
+    INFLEXION = 0.35  # Tension lines cross at (INFLEXION, 1)
+
+    START_TENSION = 0.5
+    END_TENSION = 1.0
+    P1 = START_TENSION * INFLEXION
+    P2 = 1.0 - END_TENSION * (1.0 - INFLEXION)
+
+    spline_time = []
+    spline_position = []
+
+    xMin = 0.0
+    yMin = 0.0
+    for i in range(NB_SAMPLES):
+        alpha = float(i) / NB_SAMPLES
+
+        xMax = 1.0
+        while 1:
+            x = xMin + (xMax - xMin) / 2.0
+            coef = 3.0 * x * (1.0 - x)
+            tx = coef * ((1.0 - x) * P1 + x * P2) + x * x * x
+            if math.fabs(tx - alpha) < 1E-5:
+                break
+            if tx > alpha:
+                xMax = x
+            else:
+                xMin = x
+
+        spline_position.append(coef * ((1.0 - x) * START_TENSION + x)
+                               + x * x * x)
+
+        yMax = 1.0
+        while 1:
+            y = yMin + (yMax - yMin) / 2.0
+            coef = 3.0 * y * (1.0 - y)
+            dy = coef * ((1.0 - y) * START_TENSION + y) + y * y * y
+            if math.fabs(dy - alpha) < 1E-5:
+                break
+            if dy > alpha:
+                yMax = y
+            else:
+                yMin = y
+
+        spline_time.append(coef * ((1.0 - y) * P1 + y * P2) + y * y * y)
+
+    spline_position.append(1.0)
+    spline_time.append(1.0)
+
+    print WriteJavaArrayDeclaration('SPLINE_POSITION', spline_position)
+    print WriteJavaArrayDeclaration('SPLINE_TIME', spline_time)
+
+    return 0
+
+def WriteJavaArrayDeclaration(name, float_list):
+    MAX_CHARS_PER_LINE = 100
+    INDENT_LEVELS = 2
+    SPACES_PER_INDENT_LEVEL = 4
+    DECLARATION_PREAMBLE = ' ' * SPACES_PER_INDENT_LEVEL * INDENT_LEVELS
+    VALUES_PREAMBLE = ' ' * SPACES_PER_INDENT_LEVEL * (INDENT_LEVELS + 2)
+
+    # Default precision is 6 decimal plates.
+    FLOAT_LENGTH = len('0.123456, ')
+
+    # +1 accounts for the trimmed space at the end.
+    FLOATS_PER_LINE = ((MAX_CHARS_PER_LINE - len(VALUES_PREAMBLE) + 1)
+                       / FLOAT_LENGTH)
+
+    chunks = []
+    for i in xrange(0, len(float_list), FLOATS_PER_LINE):
+        float_chunk = float_list[i : i + FLOATS_PER_LINE]
+        values = ', '.join(['%ff' % f for f in float_chunk])
+        chunks.append(VALUES_PREAMBLE + values)
+
+    s = DECLARATION_PREAMBLE + 'private static final float[] %s = {\n' % name
+    s += ',\n'.join(chunks)
+    s += '\n'
+    s += DECLARATION_PREAMBLE + '};'
+    return s
+
+if __name__ == '__main__':
+    sys.exit(Main())
diff --git a/tools/binary_size/README.md b/tools/binary_size/README.md
index 901fbaa6..d3c71e1 100644
--- a/tools/binary_size/README.md
+++ b/tools/binary_size/README.md
@@ -167,6 +167,11 @@
      * `template_name`: Name without argument parameters.
      * `full_name`: Name with all parameters.
 
+1. Special cases:
+   * LLVM function outlining creates many OUTLINED_FUNCTION_* symbols. These
+     renamed to '** outlined functions' or '** outlined functions * (count)',
+     and are deduped so an address can have at most one such symbol.
+
 1. Clustering:
    * Compiler & linker optimizations can cause symbols to be broken into
      multiple parts to become candidates for inlining ("partial inlining").
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
index e12d606..0b879f4 100644
--- a/tools/binary_size/libsupersize/archive.py
+++ b/tools/binary_size/libsupersize/archive.py
@@ -641,6 +641,22 @@
       symbol.component = _FindComponentRoot(folder_path, seen_paths, knobs)
 
 
+def _UpdateSymbolNamesFromNm(raw_symbols, names_by_address):
+  """Updates raw_symbols names with extra information from nm."""
+  logging.debug('Update symbol names')
+  # linker_map_parser extracts '** outlined function' without knowing how many
+  # such symbols exist at each address. nm has this information, and stores the
+  # value as, e.g., '** outlined function * 5'. Copy the information over.
+  for s in raw_symbols:
+    if s.full_name.startswith('** outlined function'):
+      name_list = names_by_address.get(s.address)
+      if name_list:
+        for name in name_list:
+          if name.startswith('** outlined function'):
+            s.full_name = name
+            break
+
+
 def _AddNmAliases(raw_symbols, names_by_address):
   """Adds symbols that were removed by identical code folding."""
   # Step 1: Create list of (index_of_symbol, name_list).
@@ -845,6 +861,8 @@
         'Adding symbols removed by identical code folding (as reported by nm)')
     # This normally does not block (it's finished by this time).
     names_by_address = elf_nm_result.get()
+    _UpdateSymbolNamesFromNm(raw_symbols, names_by_address)
+
     raw_symbols = _AddNmAliases(raw_symbols, names_by_address)
 
     if outdir_context:
@@ -853,7 +871,6 @@
           'Fetched path information for %d symbols from %d files',
           len(object_paths_by_name),
           len(outdir_context.elf_object_paths) + len(missed_object_paths))
-
       # For aliases, this provides path information where there wasn't any.
       logging.info('Creating aliases for symbols shared by multiple paths')
       raw_symbols = _AssignNmAliasPathsAndCreatePathAliases(
diff --git a/tools/binary_size/libsupersize/demangle.py b/tools/binary_size/libsupersize/demangle.py
index 748bf7b3..40ba487 100644
--- a/tools/binary_size/libsupersize/demangle.py
+++ b/tools/binary_size/libsupersize/demangle.py
@@ -6,17 +6,39 @@
 
 import collections
 import logging
+import re
 import subprocess
 
 import path_util
 
+_PROMOTED_GLOBAL_NAME_DEMANGLED_PATTERN = re.compile(
+    r' \((\.\d+)?\.llvm\.\d+\)$')
+_PROMOTED_GLOBAL_NAME_RAW_PATTERN = re.compile(r'(\.\d+)?\.llvm\.\d+$')
+
+def StripLlvmPromotedGlobalNames(name):
+  """Strips LLVM promoted global names suffix, and returns the result.
+
+  LLVM can promote global names by adding the suffix '.llvm.1234', or
+  '.1.llvm.1234', where the last numeric suffix is a hash. If demangle is
+  sucessful, the suffix transforms into, e.g., ' (.llvm.1234)' or
+  ' (.1.llvm.1234)'. Otherwise the suffix is left as is. This function strips
+  the suffix to prevent it from intefering with name comparison.
+  """
+  llvm_pos = name.find('.llvm.')
+  if llvm_pos < 0:
+    return name  # Handles most cases.
+  if name.endswith(')'):
+    return _PROMOTED_GLOBAL_NAME_DEMANGLED_PATTERN.sub('', name)
+  return _PROMOTED_GLOBAL_NAME_RAW_PATTERN.sub('', name)
+
+
 def _DemangleNames(names, tool_prefix):
   """Uses c++filt to demangle a list of names."""
   proc = subprocess.Popen([path_util.GetCppFiltPath(tool_prefix)],
                           stdin=subprocess.PIPE, stdout=subprocess.PIPE)
   stdout = proc.communicate('\n'.join(names))[0]
   assert proc.returncode == 0
-  ret = stdout.splitlines()
+  ret = [StripLlvmPromotedGlobalNames(line) for line in stdout.splitlines()]
   if logging.getLogger().isEnabledFor(logging.INFO):
     fail_count = sum(1 for s in ret if s.startswith('_Z'))
     if fail_count:
diff --git a/tools/binary_size/libsupersize/linker_map_parser.py b/tools/binary_size/libsupersize/linker_map_parser.py
index 679b901..8f4f070 100644
--- a/tools/binary_size/libsupersize/linker_map_parser.py
+++ b/tools/binary_size/libsupersize/linker_map_parser.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import demangle
 import logging
 import os
 import re
@@ -98,21 +99,23 @@
 #                 0x00290711                base::AutoLock::~AutoLock()
 #                 0x00290711                base::AutoLock::~AutoLock()
 # .text._ZNK5blink15LayoutBlockFlow31mustSeparateMarginAfterForChildERK...
-#                0xffffffffffffffff       0x46 obj/...
-#                0x006808e1                blink::LayoutBlockFlow::...
+#                 0xffffffffffffffff       0x46 obj/...
+#                 0x006808e1                blink::LayoutBlockFlow::...
+# .text.OUTLINED_FUNCTION_0
+#                 0x002a2000       0x20 obj/net/net/tag.o
 # .bss
 #  .bss._ZGVZN11GrProcessor11initClassIDI10LightingFPEEvvE8kClassID
-#                0x02d4b294        0x4 obj/skia/skia/SkLightingShader.o
-#                0x02d4b294   guard variable for void GrProcessor::initClassID
+#                 0x02d4b294        0x4 obj/skia/skia/SkLightingShader.o
+#                 0x02d4b294   guard variable for void GrProcessor::initClassID
 # .data           0x0028c600  0x22d3468
 #  .data.rel.ro._ZTVN3gvr7android19ScopedJavaGlobalRefIP12_jfloatArrayEE
-#                0x02d1e668       0x10 ../../third_party/.../libfoo.a(bar.o)
-#                0x02d1e668   vtable for gvr::android::GlobalRef<_jfloatArray*>
+#                 0x02d1e668       0x10 ../../third_party/.../libfoo.a(bar.o)
+#                 0x02d1e668   vtable for gvr::android::GlobalRef<_jfloatArray*>
 #  ** merge strings
 #                 0x0255fb00   0x1f2424
 #  ** merge constants
 #                 0x0255fb00   0x8
-# ** common      0x02db5700   0x13ab48
+# ** common       0x02db5700   0x13ab48
     syms = self._symbols
     while True:
       line = self._SkipToLineWithPrefix('.')
@@ -242,6 +245,10 @@
               if mangled_name and (not name or mangled_name.startswith('_Z') or
                                    '._Z' in mangled_name):
                 full_name = mangled_name
+              # Handle outlined functions. These are actual LLD features, but we
+              # handle them here for Gold to facilitate testing.
+              if full_name and full_name.startswith('OUTLINED_FUNCTION_'):
+                full_name = '** outlined function'
 
               sym = models.Symbol(section_name, size, address=address,
                                   full_name=full_name, object_path=path)
@@ -310,6 +317,15 @@
 #     194      194       13     1         <internal>:(.interp)
 #     1a8      1a8     22d8     4 .ARM.exidx
 #     1b0      1b0        8     4         obj/sandbox/syscall.o:(.ARM.exidx)
+#     400      400   123400    64 .text
+#     600      600       14     4         obj/...:(.text.OUTLINED_FUNCTION_0)
+#     600      600        0     1                 $x.3
+#     600      600       14     1                 OUTLINED_FUNCTION_0
+#  123800   123800    20000   256 .rodata
+#  123800   123800       4      4         ...:o:(.rodata._ZN3fooE.llvm.1234)
+#  123800   123800       4      1                 foo (.llvm.1234)
+#  123804   123804       4      4         ...:o:(.rodata.bar.llvm.1234)
+#  123804   123804       4      1                 bar.llvm.1234
 # Older format:
 # Address          Size             Align Out     In      Symbol
 # 00000000002002a8 000000000000001c     1 .interp
@@ -333,6 +349,7 @@
     sym_maker = _SymbolMaker()
     cur_section = None
     cur_section_is_useful = None
+    promoted_name_count = 0
 
     for line in lines:
       m = pattern.match(line)
@@ -383,12 +400,23 @@
           # If multiple entries exist, take the first on that reports a size.
           # Zero-length symbols look like "$t.4", "$d.5".
           if size and not sym_maker.cur_sym.full_name:
+            # Outlined functions have names like OUTLINED_FUNCTION_0, which can
+            # appear 1000+ time that can cause false aliasing. We treat these as
+            # special cases by designating them as a placeholder symbols and
+            # renaming them to '** outlined function'.
+            if tok.startswith('OUTLINED_FUNCTION_'):
+              tok = '** outlined function'
+            stripped_tok = demangle.StripLlvmPromotedGlobalNames(tok)
+            if len(tok) != len(stripped_tok):
+              promoted_name_count += 1
+              tok = stripped_tok
             sym_maker.cur_sym.full_name = tok
-
         else:
           logging.error('Problem line: %r', line)
 
     sym_maker.Flush()
+    if promoted_name_count:
+      logging.info('Found %d promoted global names', promoted_name_count)
     return self._section_sizes, sym_maker.syms
 
 
diff --git a/tools/binary_size/libsupersize/nm.py b/tools/binary_size/libsupersize/nm.py
index 978f174..3c71c53 100644
--- a/tools/binary_size/libsupersize/nm.py
+++ b/tools/binary_size/libsupersize/nm.py
@@ -76,6 +76,19 @@
   # Constructors often show up twice, so use sets to ensure no duplicates.
   names_by_address = collections.defaultdict(set)
 
+  # Many OUTLINED_FUNCTION_* entries can coexist on a single address, possibly
+  # mixed with regular symbols. However, naively keeping these is bad because:
+  # * OUTLINED_FUNCTION_* can have many duplicates. Keeping them would cause
+  #   false associations downstream, when looking up object_paths from names.
+  # * For addresses with multiple OUTLINED_FUNCTION_* entries, we can't get the
+  #   associated object_path (exception: the one entry in the .map file, for LLD
+  #   without ThinLTO). So keeping copies around is rather useless.
+  # Our solution is to merge OUTLINED_FUNCTION_* entries at the same address
+  # into a single symbol. We'd also like to keep track of the number of copies
+  # (although it will not be used to compute PSS computation). This is done by
+  # writing the count in the name, e.g., '** outlined function * 5'.
+  num_outlined_functions_at_address = collections.Counter()
+
   # About 60mb of output, but piping takes ~30s, and loading it into RAM
   # directly takes 3s.
   args = [path_util.GetNmPath(tool_prefix), '--no-sort', '--defined-only',
@@ -100,7 +113,15 @@
     address = int(address_str, 16)
     if not address:
       continue
-    names_by_address[address].add(mangled_name)
+    if mangled_name.startswith('OUTLINED_FUNCTION_'):
+      num_outlined_functions_at_address[address] += 1
+    else:
+      names_by_address[address].add(mangled_name)
+
+  # Need to add before demangling because |names_by_address| changes type.
+  for address, count in num_outlined_functions_at_address.iteritems():
+    name = '** outlined function' + (' * %d' % count if count > 1 else '')
+    names_by_address[address].add(name)
 
   # Demangle all names.
   names_by_address = demangle.DemangleSetsInDicts(names_by_address, tool_prefix)
@@ -108,7 +129,12 @@
   # Since this is run in a separate process, minimize data passing by returning
   # only aliased symbols.
   # Also: Sort to ensure stable ordering.
-  return {k: sorted(v) for k, v in names_by_address.iteritems() if len(v) > 1}
+  return {
+      addr: sorted(names)
+      for addr, names in names_by_address.iteritems()
+      if len(names) > 1 or num_outlined_functions_at_address.get(addr, 0) > 1
+  }
+
 
 
 def _CollectAliasesByAddressAsyncHelper(elf_path, tool_prefix):
diff --git a/tools/binary_size/libsupersize/static/infocard-ui.js b/tools/binary_size/libsupersize/static/infocard-ui.js
index fd2f1ec..98deefa 100644
--- a/tools/binary_size/libsupersize/static/infocard-ui.js
+++ b/tools/binary_size/libsupersize/static/infocard-ui.js
@@ -74,21 +74,32 @@
     }
 
     /**
-     * Updates the path text, which shows the idPath of the node but highlights
-     * the symbol name portion using bold text.
+     * Updates the path text, which shows the idPath for directory nodes, and
+     * srcPath / component for symbol nodes.
      * @param {TreeNode} node
      */
-    _updatePath(node) {
-      const path = node.idPath.slice(0, node.shortNameIndex);
-      const boldShortName = dom.textElement(
-        'span',
-        shortName(node),
-        'symbol-name-info'
-      );
-      const pathFragment = dom.createFragment([
-        document.createTextNode(path),
-        boldShortName,
-      ]);
+    _updatePaths(node) {
+      let pathFragment;
+      if (node.srcPath) {
+        pathFragment = dom.createFragment([
+            dom.textElement('span', 'Path: ', 'symbol-name-info'),
+            document.createTextNode(node.srcPath),
+            document.createElement('br'),
+            dom.textElement('span', 'Component: ', 'symbol-name-info'),
+            document.createTextNode(node.componet || '(No component)'),
+        ]);
+      } else {
+        const path = node.idPath.slice(0, node.shortNameIndex);
+        const boldShortName = dom.textElement(
+          'span',
+          shortName(node),
+          'symbol-name-info'
+        );
+        pathFragment = dom.createFragment([
+          document.createTextNode(path),
+          boldShortName,
+        ]);
+      }
 
       // Update DOM
       dom.replace(this._pathInfo, pathFragment);
@@ -145,7 +156,7 @@
 
       // Update DOM
       this._updateSize(node);
-      this._updatePath(node);
+      this._updatePaths(node);
       if (type !== this._lastType) {
         // No need to create a new icon if it is identical.
         const icon = getIconTemplate(type);
diff --git a/tools/binary_size/libsupersize/static/infocard.css b/tools/binary_size/libsupersize/static/infocard.css
index 2c7a84a2..385cdf4 100644
--- a/tools/binary_size/libsupersize/static/infocard.css
+++ b/tools/binary_size/libsupersize/static/infocard.css
@@ -9,7 +9,7 @@
   left: 8px;
   right: 8px;
   margin: 0 auto;
-  max-width: 512px;
+  max-width: 720px;
   max-height: 50vh;
   overflow-y: auto;
   background: white;
@@ -94,6 +94,7 @@
   border-top: 1px solid #dadce0;
   padding-top: 8px;
   clear: right;
+  text-align: left;
 }
 .canvas-overlay {
   position: absolute;
@@ -108,9 +109,6 @@
   min-width: 100%;
   font-size: 14px;
 }
-.type-breakdown-info th {
-  text-align: left;
-}
 .type-breakdown-info th[scope='row'] {
   font-weight: normal;
 }
diff --git a/tools/binary_size/libsupersize/static/options.css b/tools/binary_size/libsupersize/static/options.css
index d0fc6375..184d57ff 100644
--- a/tools/binary_size/libsupersize/static/options.css
+++ b/tools/binary_size/libsupersize/static/options.css
@@ -4,7 +4,7 @@
 
 /** Body modifier class, indicates when options should be visible. */
 .show-options {
-  grid-template-columns: auto 256px;
+  grid-template-columns: auto 306px;
 }
 
 .show-options .options {
diff --git a/tools/binary_size/libsupersize/static/shared.js b/tools/binary_size/libsupersize/static/shared.js
index b0c084d7..53ea8d5 100644
--- a/tools/binary_size/libsupersize/static/shared.js
+++ b/tools/binary_size/libsupersize/static/shared.js
@@ -18,6 +18,8 @@
  * arrays indicate this is a leaf node.
  * @prop {TreeNode | null} parent Parent tree node. null if this is a root node.
  * @prop {string} idPath Full path to this node.
+ * @prop {string} srcPath Path to the source containing this symbol.
+ * @prop {string} component OWNERS Component for this symbol.
  * @prop {number} shortNameIndex The name of the node is include in the idPath.
  * This index indicates where to start to slice the idPath to read the name.
  * @prop {number} size Byte size of this node and its children.
diff --git a/tools/binary_size/libsupersize/static/tree-worker.js b/tools/binary_size/libsupersize/static/tree-worker.js
index efc101f..db7af6a 100644
--- a/tools/binary_size/libsupersize/static/tree-worker.js
+++ b/tools/binary_size/libsupersize/static/tree-worker.js
@@ -50,6 +50,14 @@
 }
 
 /**
+ * @param {Meta} meta
+ * @param {FileEntry} fileEntry
+ */
+function getComponent(meta, fileEntry) {
+  return meta.components[fileEntry[_KEYS.COMPONENT_INDEX]];
+}
+
+/**
  * Find the last index of either '/' or `sep` in the given path.
  * @param {string} path
  * @param {string} sep
@@ -91,6 +99,8 @@
 function createNode(options) {
   const {
     idPath,
+    srcPath,
+    component,
     type,
     shortNameIndex,
     size = 0,
@@ -102,6 +112,8 @@
     children: [],
     parent: null,
     idPath,
+    srcPath,
+    component,
     type,
     shortNameIndex,
     size,
@@ -128,13 +140,16 @@
    * @param {(symbolNode: TreeNode) => boolean} options.highlightTest Called to
    * see if a symbol should be highlighted.
    * @param {string} options.sep Path seperator used to find parent names.
+   * @param {Meta} options.meta Metadata associated with this tree.
    */
   constructor(options) {
     this._getPath = options.getPath;
     this._filterTest = options.filterTest;
     this._highlightTest = options.highlightTest;
     this._sep = options.sep || _PATH_SEP;
+    this._meta = options.meta;
 
+    // srcPath and component don't make sense for the root node.
     this.rootNode = createNode({
       idPath: this._sep,
       shortNameIndex: 0,
@@ -234,6 +249,8 @@
           if (classNode == null) {
             classNode = createNode({
               idPath: classIdPath,
+              srcPath: node.srcPath,
+              component: node.component,
               shortNameIndex: childNode.shortNameIndex,
               type: _CONTAINER_TYPES.JAVA_CLASS,
             });
@@ -341,6 +358,9 @@
       // get parent from cache if it exists, otherwise create it
       parentNode = this._parents.get(parentPath);
       if (parentNode == null) {
+        // srcPath and component are not available for parent nodes, since they
+        // are stored alongside FileEntry. We could extract srcPath from idPath,
+        // but it doesn't really add enough value to warrent doing so.
         parentNode = createNode({
           idPath: parentPath,
           shortNameIndex: lastIndexOf(parentPath, this._sep) + 1,
@@ -365,9 +385,13 @@
    */
   addFileEntry(fileEntry, diffMode) {
     const idPath = this._getPath(fileEntry);
+    const srcPath = getSourcePath(fileEntry);
+    const component = getComponent(this._meta, fileEntry);
     // make node for this
     const fileNode = createNode({
       idPath,
+      srcPath,
+      component,
       shortNameIndex: lastIndexOf(idPath, this._sep) + 1,
       type: _CONTAINER_TYPES.FILE,
     });
@@ -384,6 +408,8 @@
       const symbolNode = createNode({
         // Join file path to symbol name with a ":"
         idPath: `${idPath}:${symbol[_KEYS.SYMBOL_NAME]}`,
+        srcPath,
+        component,
         shortNameIndex: idPath.length + 1,
         size,
         type,
@@ -707,20 +733,13 @@
   /** @type {{ [gropyBy: string]: (fileEntry: FileEntry) => string }} */
   const getPathMap = {
     component(fileEntry) {
-      const component = meta.components[fileEntry[_KEYS.COMPONENT_INDEX]];
+      const component = getComponent(meta, fileEntry);
       const path = getSourcePath(fileEntry);
       return `${component || '(No component)'}>${path}`;
     },
     source_path: getSourcePath,
   };
 
-  builder = new TreeBuilder({
-    sep: groupBy === 'component' ? '>' : _PATH_SEP,
-    getPath: getPathMap[groupBy],
-    filterTest,
-    highlightTest,
-  });
-
   /**
    * Creates data to post to the UI thread. Defaults will be used for the root
    * and percent values if not specified.
@@ -767,6 +786,15 @@
         // First line of data is used to store meta information.
         meta = /** @type {Meta} */ (dataObj);
         diffMode = meta.diff_mode;
+
+        builder = new TreeBuilder({
+          getPath: getPathMap[groupBy],
+          filterTest,
+          highlightTest,
+          sep: groupBy === 'component' ? '>' : _PATH_SEP,
+          meta,
+        });
+
         postToUi();
       } else {
         builder.addFileEntry(/** @type {FileEntry} */ (dataObj), diffMode);
diff --git a/tools/binary_size/libsupersize/testdata/Archive.golden b/tools/binary_size/libsupersize/testdata/Archive.golden
index d7762ad..f8164fd 100644
--- a/tools/binary_size/libsupersize/testdata/Archive.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive.golden
@@ -1,7 +1,7 @@
-Section .text: has 100.0% of 35900712 bytes accounted for from 15 symbols. 0 bytes are unaccounted for.
+Section .text: has 100.0% of 35900712 bytes accounted for from 17 symbols. 0 bytes are unaccounted for.
 * 0 have source paths assigned (0.0%)
 * Padding accounts for 48 bytes (0.0%)
-* 3 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
+* 5 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
 * Contains 0 aliases
 * 0 symbols have shared ownership
 Section .rodata: has 100.0% of 5927652 bytes accounted for from 10 symbols. 0 bytes are unaccounted for.
@@ -67,7 +67,9 @@
 .text@2a0020(size_without_padding=24,padding=4,full_name=blink::ContiguousContainerBase::ContiguousContainerBase(blink::ContiguousContainerBase&&),object_path=third_party/WebKit.a/sub/ContiguousContainer.o,source_path=,flags={},num_aliases=1,component=)
 .text@2a1000(size_without_padding=0,padding=4040,full_name=** symbol gap 1,object_path=,source_path=,flags={},num_aliases=1,component=)
 .text@2a1000(size_without_padding=94,padding=0,full_name=blink::PaintChunker::releasePaintChunks(),object_path=third_party/WebKit.a/sub/ContiguousContainer.o,source_path=,flags={anon,clone},num_aliases=1,component=)
-.text@24ca628(size_without_padding=0,padding=35821002,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
+.text@2a2000(size_without_padding=32,padding=4002,full_name=** outlined function,object_path=third_party/WebKit.a/sub/ContiguousContainer.o,source_path=,flags={},num_aliases=1,component=)
+.text@2a2020(size_without_padding=48,padding=0,full_name=** outlined function,object_path=third_party/WebKit.a/sub/ContiguousContainer.o,source_path=,flags={},num_aliases=1,component=)
+.text@24ca628(size_without_padding=0,padding=35816920,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
 .bss@0(size_without_padding=262144,padding=0,full_name=ff_cos_131072,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=,flags={},num_aliases=1,component=)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_131072_fixed,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o,source_path=,flags={},num_aliases=1,component=)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_65536,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
index bc41e34..1e892bff 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
@@ -9,11 +9,11 @@
 linker_name=gold
 map_file_name=../../../test.map
 tool_prefix=tools/binary_size/libsupersize/testdata/mock_toolchain/
-Section .text: has 100.0% of 35900712 bytes accounted for from 19 symbols. 0 bytes are unaccounted for.
-* 15 have source paths assigned (78.9%)
+Section .text: has 100.0% of 35900712 bytes accounted for from 22 symbols. 0 bytes are unaccounted for.
+* 16 have source paths assigned (72.7%)
 * Padding accounts for 48 bytes (0.0%)
-* 3 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
-* Contains 6 aliases, mapped to 2 unique addresses (52 bytes saved)
+* 5 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
+* Contains 8 aliases, mapped to 3 unique addresses (100 bytes saved)
 * 0 symbols have shared ownership
 Section .rodata: has 100.0% of 5927652 bytes accounted for from 12 symbols. 0 bytes are unaccounted for.
 * 8 have source paths assigned (66.7%)
@@ -303,7 +303,10 @@
 .text@2a0020(size_without_padding=24,padding=4,full_name=blink::ContiguousContainerBase::ContiguousContainerBase(blink::ContiguousContainerBase&&),object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
 .text@2a1000(size_without_padding=0,padding=4040,full_name=** symbol gap 1,object_path=,source_path=,flags={},num_aliases=1,component=)
 .text@2a1000(size_without_padding=94,padding=0,full_name=blink::PaintChunker::releasePaintChunks(),object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={anon,clone},num_aliases=1,component=UI>Browser)
-.text@24ca628(size_without_padding=0,padding=35821002,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
+.text@2a2000(size_without_padding=32,padding=4002,full_name=** outlined function,object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
+.text@2a2020(size_without_padding=48,padding=0,full_name=** outlined function * 2,object_path=,source_path=,flags={},num_aliases=2,component=)
+.text@2a2020(size_without_padding=48,padding=0,full_name=aliasedWithOutlinedFunction(),object_path=,source_path=,flags={},num_aliases=2,component=)
+.text@24ca628(size_without_padding=0,padding=35816920,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
 .bss@0(size_without_padding=262144,padding=0,full_name=ff_cos_131072,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=third_party/fft_float.cc,flags={},num_aliases=1,component=Internal>Android)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_131072_fixed,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o,source_path=third_party/fft_fixed.cc,flags={},num_aliases=1,component=Internal>Android)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_65536,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=third_party/fft_float.cc,flags={},num_aliases=1,component=Internal>Android)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Elf.golden b/tools/binary_size/libsupersize/testdata/Archive_Elf.golden
index 75dd1f3b..22dea2fc 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_Elf.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_Elf.golden
@@ -7,11 +7,11 @@
 linker_name=gold
 map_file_name=../../../test.map
 tool_prefix=tools/binary_size/libsupersize/testdata/mock_toolchain/
-Section .text: has 100.0% of 35900712 bytes accounted for from 19 symbols. 0 bytes are unaccounted for.
-* 15 have source paths assigned (78.9%)
+Section .text: has 100.0% of 35900712 bytes accounted for from 22 symbols. 0 bytes are unaccounted for.
+* 16 have source paths assigned (72.7%)
 * Padding accounts for 48 bytes (0.0%)
-* 3 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
-* Contains 6 aliases, mapped to 2 unique addresses (52 bytes saved)
+* 5 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
+* Contains 8 aliases, mapped to 3 unique addresses (100 bytes saved)
 * 0 symbols have shared ownership
 Section .rodata: has 100.0% of 5927652 bytes accounted for from 12 symbols. 0 bytes are unaccounted for.
 * 8 have source paths assigned (66.7%)
@@ -88,7 +88,10 @@
 .text@2a0020(size_without_padding=24,padding=4,full_name=blink::ContiguousContainerBase::ContiguousContainerBase(blink::ContiguousContainerBase&&),object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
 .text@2a1000(size_without_padding=0,padding=4040,full_name=** symbol gap 1,object_path=,source_path=,flags={},num_aliases=1,component=)
 .text@2a1000(size_without_padding=94,padding=0,full_name=blink::PaintChunker::releasePaintChunks(),object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={anon,clone},num_aliases=1,component=UI>Browser)
-.text@24ca628(size_without_padding=0,padding=35821002,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
+.text@2a2000(size_without_padding=32,padding=4002,full_name=** outlined function,object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
+.text@2a2020(size_without_padding=48,padding=0,full_name=** outlined function * 2,object_path=,source_path=,flags={},num_aliases=2,component=)
+.text@2a2020(size_without_padding=48,padding=0,full_name=aliasedWithOutlinedFunction(),object_path=,source_path=,flags={},num_aliases=2,component=)
+.text@24ca628(size_without_padding=0,padding=35816920,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
 .bss@0(size_without_padding=262144,padding=0,full_name=ff_cos_131072,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=third_party/fft_float.cc,flags={},num_aliases=1,component=Internal>Android)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_131072_fixed,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o,source_path=third_party/fft_fixed.cc,flags={},num_aliases=1,component=Internal>Android)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_65536,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=third_party/fft_float.cc,flags={},num_aliases=1,component=Internal>Android)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_OutputDirectory.golden b/tools/binary_size/libsupersize/testdata/Archive_OutputDirectory.golden
index d7a5660..c9d365f 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_OutputDirectory.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_OutputDirectory.golden
@@ -1,7 +1,7 @@
-Section .text: has 100.0% of 35900712 bytes accounted for from 15 symbols. 0 bytes are unaccounted for.
-* 12 have source paths assigned (80.0%)
+Section .text: has 100.0% of 35900712 bytes accounted for from 17 symbols. 0 bytes are unaccounted for.
+* 14 have source paths assigned (82.4%)
 * Padding accounts for 48 bytes (0.0%)
-* 3 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
+* 5 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
 * Contains 0 aliases
 * 0 symbols have shared ownership
 Section .rodata: has 100.0% of 5927652 bytes accounted for from 10 symbols. 0 bytes are unaccounted for.
@@ -67,7 +67,9 @@
 .text@2a0020(size_without_padding=24,padding=4,full_name=blink::ContiguousContainerBase::ContiguousContainerBase(blink::ContiguousContainerBase&&),object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
 .text@2a1000(size_without_padding=0,padding=4040,full_name=** symbol gap 1,object_path=,source_path=,flags={},num_aliases=1,component=)
 .text@2a1000(size_without_padding=94,padding=0,full_name=blink::PaintChunker::releasePaintChunks(),object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={anon,clone},num_aliases=1,component=UI>Browser)
-.text@24ca628(size_without_padding=0,padding=35821002,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
+.text@2a2000(size_without_padding=32,padding=4002,full_name=** outlined function,object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
+.text@2a2020(size_without_padding=48,padding=0,full_name=** outlined function,object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
+.text@24ca628(size_without_padding=0,padding=35816920,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
 .bss@0(size_without_padding=262144,padding=0,full_name=ff_cos_131072,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=third_party/fft_float.cc,flags={},num_aliases=1,component=Internal>Android)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_131072_fixed,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o,source_path=third_party/fft_fixed.cc,flags={},num_aliases=1,component=Internal>Android)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_65536,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=third_party/fft_float.cc,flags={},num_aliases=1,component=Internal>Android)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Pak_Files.golden b/tools/binary_size/libsupersize/testdata/Archive_Pak_Files.golden
index 0eb93c64..ded3734 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_Pak_Files.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_Pak_Files.golden
@@ -7,11 +7,11 @@
 linker_name=gold
 map_file_name=../../../test.map
 tool_prefix=tools/binary_size/libsupersize/testdata/mock_toolchain/
-Section .text: has 100.0% of 35900712 bytes accounted for from 19 symbols. 0 bytes are unaccounted for.
-* 15 have source paths assigned (78.9%)
+Section .text: has 100.0% of 35900712 bytes accounted for from 22 symbols. 0 bytes are unaccounted for.
+* 16 have source paths assigned (72.7%)
 * Padding accounts for 48 bytes (0.0%)
-* 3 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
-* Contains 6 aliases, mapped to 2 unique addresses (52 bytes saved)
+* 5 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
+* Contains 8 aliases, mapped to 3 unique addresses (100 bytes saved)
 * 0 symbols have shared ownership
 Section .rodata: has 100.0% of 5927652 bytes accounted for from 12 symbols. 0 bytes are unaccounted for.
 * 8 have source paths assigned (66.7%)
@@ -98,7 +98,10 @@
 .text@2a0020(size_without_padding=24,padding=4,full_name=blink::ContiguousContainerBase::ContiguousContainerBase(blink::ContiguousContainerBase&&),object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
 .text@2a1000(size_without_padding=0,padding=4040,full_name=** symbol gap 1,object_path=,source_path=,flags={},num_aliases=1,component=)
 .text@2a1000(size_without_padding=94,padding=0,full_name=blink::PaintChunker::releasePaintChunks(),object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={anon,clone},num_aliases=1,component=UI>Browser)
-.text@24ca628(size_without_padding=0,padding=35821002,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
+.text@2a2000(size_without_padding=32,padding=4002,full_name=** outlined function,object_path=third_party/sub/ContiguousContainer.o,source_path=third_party/container/container.c,flags={},num_aliases=1,component=UI>Browser)
+.text@2a2020(size_without_padding=48,padding=0,full_name=** outlined function * 2,object_path=,source_path=,flags={},num_aliases=2,component=)
+.text@2a2020(size_without_padding=48,padding=0,full_name=aliasedWithOutlinedFunction(),object_path=,source_path=,flags={},num_aliases=2,component=)
+.text@24ca628(size_without_padding=0,padding=35816920,full_name=** symbol gap 2 (end of section),object_path=,source_path=,flags={},num_aliases=1,component=)
 .bss@0(size_without_padding=262144,padding=0,full_name=ff_cos_131072,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=third_party/fft_float.cc,flags={},num_aliases=1,component=Internal>Android)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_131072_fixed,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o,source_path=third_party/fft_fixed.cc,flags={},num_aliases=1,component=Internal>Android)
 .bss@0(size_without_padding=131072,padding=0,full_name=ff_cos_65536,object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o,source_path=third_party/fft_float.cc,flags={},num_aliases=1,component=Internal>Android)
diff --git a/tools/binary_size/libsupersize/testdata/Console.golden b/tools/binary_size/libsupersize/testdata/Console.golden
index 2538830..0c1f79a9 100644
--- a/tools/binary_size/libsupersize/testdata/Console.golden
+++ b/tools/binary_size/libsupersize/testdata/Console.golden
@@ -81,13 +81,13 @@
     .symtab: 16.4mb (17166112 bytes) (12.8%)
     .text: 34.2mb (35900712 bytes) (26.7%)
 
-Showing 50 symbols (45 unique) with total pss: 77769551 bytes
+Showing 53 symbols (47 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-     [2,4): 6    [16,32): 10        [128,256): 2    [131072,262144): 2     [1048576,2097152): 2
-     [4,8): 6    [32,64): 9         [256,512): 1    [262144,524288): 1     [2097152,4194304): 1
-    [8,16): 3   [64,128): 1    [65536,131072): 2   [524288,1048576): 2   [33554432,67108864): 2
+     [2,4): 6    [16,32): 12     [128,256): 2    [65536,131072): 2    [524288,1048576): 2   [33554432,67108864): 2
+     [4,8): 6    [32,64): 9      [256,512): 1   [131072,262144): 2   [1048576,2097152): 2
+    [8,16): 3   [64,128): 1    [2048,4096): 1   [262144,524288): 1   [2097152,4194304): 1
 Sizes: .text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
-Counts: .text=19 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
+Counts: .text=22 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
@@ -156,39 +156,45 @@
              extFromUUseMapping
 31)  41869009 (53.8%) t@0x28d98a   32             base/page_allocator.cc
              extFromUUseMapping
-32)  77699769 (99.9%) t@Group      35830760       {no path}
+32)  77695687 (99.9%) t@Group      35826678       {no path}
              ** symbol gaps (count=3)
-33)  77700217 (99.9%) t@0x28f000   448            $root_gen_dir/third_party/icu/ucnv_ext.c
+33)  77696135 (99.9%) t@0x28f000   448            $root_gen_dir/third_party/icu/ucnv_ext.c
              ucnv_extMatchFromU
-34)  77700245 (99.9%) t@0x28f1c8   28             $root_gen_dir/third_party/icu/ucnv_ext.c
+34)  77696163 (99.9%) t@0x28f1c8   28             $root_gen_dir/third_party/icu/ucnv_ext.c
              _GLOBAL__sub_I_SkDeviceProfile.cpp
-35)  77769369 (100.0%) t@0x28f1e0   69124          $root_gen_dir/third_party/icu/ucnv_ext.c
+35)  77765287 (100.0%) t@0x28f1e0   69124          $root_gen_dir/third_party/icu/ucnv_ext.c
              foo_bar
-36)  77769393 (100.0%) t@0x2a0000   24 (size=48)   $root_gen_dir/third_party/icu/ucnv_ext.c
+36)  77765311 (100.0%) t@0x2a0000   24 (size=48)   $root_gen_dir/third_party/icu/ucnv_ext.c
              BazAlias (num_aliases=2)
-37)  77769417 (100.0%) t@0x2a0000   24 (size=48)   {no path}
+37)  77765335 (100.0%) t@0x2a0000   24 (size=48)   {no path}
              blink::ContiguousContainerBase::shrinkToFit (num_aliases=2)
-38)  77769420 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
+38)  77765338 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
              BarAlias (num_aliases=4)
-39)  77769423 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
+39)  77765341 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
              FooAlias (num_aliases=4)
-40)  77769426 (100.0%) t@0x2a0010   3 (size=12)    $root_gen_dir/third_party/icu/ucnv_ext.c
+40)  77765344 (100.0%) t@0x2a0010   3 (size=12)    $root_gen_dir/third_party/icu/ucnv_ext.c
              blink::ContiguousContainerBase::shrinkToFit (num_aliases=4)
-41)  77769429 (100.0%) t@0x2a0010   3 (size=12)    third_party/paint.cc
+41)  77765347 (100.0%) t@0x2a0010   3 (size=12)    third_party/paint.cc
              blink::ContiguousContainerBase::shrinkToFit (num_aliases=4)
-42)  77769457 (100.0%) t@0x2a0020   28             third_party/container/container.c
+42)  77765375 (100.0%) t@0x2a0020   28             third_party/container/container.c
              blink::ContiguousContainerBase::ContiguousContainerBase
-43)  77769551 (100.0%) t@0x2a1000   94             third_party/container/container.c
+43)  77765469 (100.0%) t@0x2a1000   94             third_party/container/container.c
              blink::PaintChunker::releasePaintChunks
-44)  77769551 (100.0%) b@0x0        262144         third_party/fft_float.cc
+44)  77769503 (100.0%) t@0x2a2000   4034           third_party/container/container.c
+             ** outlined function
+45)  77769527 (100.0%) t@0x2a2020   24 (size=48)   {no path}
+             ** outlined function * 2 (num_aliases=2)
+46)  77769551 (100.0%) t@0x2a2020   24 (size=48)   {no path}
+             aliasedWithOutlinedFunction (num_aliases=2)
+47)  77769551 (100.0%) b@0x0        262144         third_party/fft_float.cc
              ff_cos_131072
-45)  77769551 (100.0%) b@0x0        131072         third_party/fft_fixed.cc
+48)  77769551 (100.0%) b@0x0        131072         third_party/fft_fixed.cc
              ff_cos_131072_fixed
-46)  77769551 (100.0%) b@0x0        131072         third_party/fft_float.cc
+49)  77769551 (100.0%) b@0x0        131072         third_party/fft_float.cc
              ff_cos_65536
-47)  77769551 (100.0%) b@0x2dffda0  28             $root_gen_dir/third_party/icu/ucnv_ext.c
+50)  77769551 (100.0%) b@0x2dffda0  28             $root_gen_dir/third_party/icu/ucnv_ext.c
              g_chrome_content_browser_client
-48)  77769551 (100.0%) b@0x2dffe80  200            $root_gen_dir/third_party/icu/ucnv_ext.c
+51)  77769551 (100.0%) b@0x2dffe80  200            $root_gen_dir/third_party/icu/ucnv_ext.c
              SaveHistogram::atomic_histogram_pointer
-49)  77769551 (100.0%) b@0x2dffe84  4              $root_gen_dir/third_party/icu/ucnv_ext.c
+52)  77769551 (100.0%) b@0x2dffe84  4              $root_gen_dir/third_party/icu/ucnv_ext.c
              g_AnimationFrameTimeHistogram_clazz
diff --git a/tools/binary_size/libsupersize/testdata/Csv.golden b/tools/binary_size/libsupersize/testdata/Csv.golden
index 3dac1cf2..74253bb 100644
--- a/tools/binary_size/libsupersize/testdata/Csv.golden
+++ b/tools/binary_size/libsupersize/testdata/Csv.golden
@@ -43,7 +43,7 @@
 ,0x28d948,28,0,1,28.0,t,_GLOBAL__sub_I_pacing_sender.cc
 ,0x28d964,38,0,1,38.0,t,extFromUUseMapping
 ,0x28d98a,32,0,1,32.0,t,extFromUUseMapping
-3,,0,35830760,1,35830760.0,t,** symbol gaps
+3,,0,35826678,1,35826678.0,t,** symbol gaps
 ,0x28f000,448,0,1,448.0,t,ucnv_extMatchFromU
 ,0x28f1c8,20,8,1,28.0,t,_GLOBAL__sub_I_SkDeviceProfile.cpp
 ,0x28f1e0,69120,4,1,69124.0,t,foo_bar
@@ -55,6 +55,9 @@
 ,0x2a0010,12,0,4,3.0,t,blink::ContiguousContainerBase::shrinkToFit
 ,0x2a0020,24,4,1,28.0,t,blink::ContiguousContainerBase::ContiguousContainerBase
 ,0x2a1000,94,0,1,94.0,t,blink::PaintChunker::releasePaintChunks
+,0x2a2000,32,4002,1,4034.0,t,** outlined function
+,0x2a2020,48,0,2,24.0,t,** outlined function * 2
+,0x2a2020,48,0,2,24.0,t,aliasedWithOutlinedFunction
 ,0x0,262144,0,1,262144.0,b,ff_cos_131072
 ,0x0,131072,0,1,131072.0,b,ff_cos_131072_fixed
 ,0x0,131072,0,1,131072.0,b,ff_cos_65536
diff --git a/tools/binary_size/libsupersize/testdata/Diff_Basic.golden b/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
index a2b24ee..0ed0012 100644
--- a/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
+++ b/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
@@ -40,10 +40,10 @@
     .strtab: 0 bytes (0 bytes)
     .symtab: 0 bytes (0 bytes)
 
-2 symbols added (+), 2 changed (~), 3 removed (-), 244 unchanged (not shown)
+2 symbols added (+), 2 changed (~), 3 removed (-), 245 unchanged (not shown)
 Added/Removed by section: .data: +2 .pak.translations: -3
 Of changed symbols, 3 grew, 4 shrank
-Number of unique symbols 254 -> 253 (-1)
+Number of unique symbols 256 -> 255 (-1)
 0 paths added, 0 removed, 2 changed
 Changed files:
   
diff --git a/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden b/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
index 122ffe20..f2f07c83 100644
--- a/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
+++ b/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
@@ -20,10 +20,10 @@
     .rodata: 0 bytes (0 bytes) (0.0%)
     .text: 0 bytes (0 bytes) (0.0%)
 
-0 symbols added (+), 0 changed (~), 0 removed (-), 50 unchanged (not shown)
+0 symbols added (+), 0 changed (~), 0 removed (-), 53 unchanged (not shown)
 Added/Removed by section: 
 Of changed symbols, 0 grew, 0 shrank
-Number of unique symbols 48 -> 48 (+0)
+Number of unique symbols 50 -> 50 (+0)
 0 paths added, 0 removed, 0 changed
 
 Showing 0 symbols (0 -> 0 unique) with total pss: 0 bytes
diff --git a/tools/binary_size/libsupersize/testdata/FullDescription.golden b/tools/binary_size/libsupersize/testdata/FullDescription.golden
index 5954343..5ce4c80 100644
--- a/tools/binary_size/libsupersize/testdata/FullDescription.golden
+++ b/tools/binary_size/libsupersize/testdata/FullDescription.golden
@@ -42,11 +42,11 @@
     .rel.plt: 2.75kb (2816 bytes)
     .shstrtab: 436 bytes (436 bytes)
 
-Section .text: has 100.0% of 35900712 bytes accounted for from 19 symbols. 0 bytes are unaccounted for.
-* 15 have source paths assigned (78.9%)
+Section .text: has 100.0% of 35900712 bytes accounted for from 22 symbols. 0 bytes are unaccounted for.
+* 16 have source paths assigned (72.7%)
 * Padding accounts for 48 bytes (0.0%)
-* 3 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
-* Contains 6 aliases, mapped to 2 unique addresses (52 bytes saved)
+* 5 placeholders (symbols that start with **) account for 35830760 bytes (99.8%)
+* Contains 8 aliases, mapped to 3 unique addresses (100 bytes saved)
 * 0 symbols have shared ownership
 Section .rodata: has 100.0% of 5927652 bytes accounted for from 12 symbols. 0 bytes are unaccounted for.
 * 8 have source paths assigned (66.7%)
@@ -78,13 +78,13 @@
 * Contains 0 aliases
 * 0 symbols have shared ownership
 
-Showing 53 symbols (48 unique) with total pss: 77769551 bytes
+Showing 56 symbols (50 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-     [2,4): 7    [16,32): 10     [128,256): 2       [4096,8192): 1     [262144,524288): 1     [2097152,4194304): 1
+     [2,4): 7    [16,32): 12     [128,256): 2       [4096,8192): 1     [262144,524288): 1     [2097152,4194304): 1
      [4,8): 6    [32,64): 9      [256,512): 1    [65536,131072): 2    [524288,1048576): 2   [33554432,67108864): 2
-    [8,16): 3   [64,128): 1    [2048,4096): 1   [131072,262144): 2   [1048576,2097152): 2
+    [8,16): 3   [64,128): 1    [2048,4096): 2   [131072,262144): 2   [1048576,2097152): 2
 Sizes: .text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
-Counts: .text=19 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
+Counts: .text=22 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
@@ -239,35 +239,45 @@
              source_path=third_party/container/container.c 	object_path=third_party/sub/ContiguousContainer.o
              flags={anon,clone}  name=blink::PaintChunker::releasePaintChunks
                   full_name=blink::PaintChunker::releasePaintChunks()
-46)  77769551 (100.0%) t@0x24ca628  pss=35821002  padding=35821002  num_aliases=1
+46)  41952583 (53.9%) t@0x2a2000   pss=4034  padding=4002  num_aliases=1
+             source_path=third_party/container/container.c 	object_path=third_party/sub/ContiguousContainer.o
+             flags={}  name=** outlined function
+47)  41952607 (53.9%) t@0x2a2020   pss=24 (size=48)  padding=0  num_aliases=2
+             source_path= 	object_path=
+             flags={}  name=** outlined function * 2
+48)  41952631 (53.9%) t@0x2a2020   pss=24 (size=48)  padding=0  num_aliases=2
+             source_path= 	object_path=
+             flags={}  name=aliasedWithOutlinedFunction
+                  full_name=aliasedWithOutlinedFunction()
+49)  77769551 (100.0%) t@0x24ca628  pss=35816920  padding=35816920  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 2 (end of section)
-47)  77769551 (100.0%) b@0x0        pss=262144  padding=0  num_aliases=1
+50)  77769551 (100.0%) b@0x0        pss=262144  padding=0  num_aliases=1
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=ff_cos_131072
-48)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
+51)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
              source_path=third_party/fft_fixed.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o
              flags={}  name=ff_cos_131072_fixed
-49)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
+52)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=ff_cos_65536
-50)  77769551 (100.0%) b@0x2dffda0  pss=28  padding=0  num_aliases=1
+53)  77769551 (100.0%) b@0x2dffda0  pss=28  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=g_chrome_content_browser_client
-51)  77769551 (100.0%) b@0x2dffe80  pss=200  padding=196  num_aliases=1
+54)  77769551 (100.0%) b@0x2dffe80  pss=200  padding=196  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=SaveHistogram::atomic_histogram_pointer
                   full_name=SaveHistogram(_JNIEnv*, base::android::JavaParamRef<_jobject*> const&, base::android::JavaParamRef<_jstring*> const&, base::android::JavaParamRef<_jlongArray*> const&, int)::atomic_histogram_pointer
-52)  77769551 (100.0%) b@0x2dffe84  pss=4  padding=0  num_aliases=1
+55)  77769551 (100.0%) b@0x2dffe84  pss=4  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={anon,gen}  name=g_AnimationFrameTimeHistogram_clazz
-Showing 50 symbols (45 unique) with total pss: 77769551 bytes
+Showing 53 symbols (47 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-     [2,4): 6    [16,32): 10        [128,256): 2    [131072,262144): 2     [1048576,2097152): 2
-     [4,8): 6    [32,64): 9         [256,512): 1    [262144,524288): 1     [2097152,4194304): 1
-    [8,16): 3   [64,128): 1    [65536,131072): 2   [524288,1048576): 2   [33554432,67108864): 2
+     [2,4): 6    [16,32): 12     [128,256): 2    [65536,131072): 2    [524288,1048576): 2   [33554432,67108864): 2
+     [4,8): 6    [32,64): 9      [256,512): 1   [131072,262144): 2   [1048576,2097152): 2
+    [8,16): 3   [64,128): 1    [2048,4096): 1   [262144,524288): 1   [2097152,4194304): 1
 Sizes: .text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
-Counts: .text=19 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
+Counts: .text=22 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
@@ -377,7 +387,7 @@
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=extFromUUseMapping
                   full_name=extFromUUseMapping(aj, int)
-32)  77699769 (99.9%) t@Group      pss=35830760  padding=35830760  count=3
+32)  77695687 (99.9%) t@Group      pss=35826678  padding=35826678  count=3
              source_path= 	object_path=
              flags={}  name=** symbol gaps
 > 0)       5718 (0.0%)  t@0x28f000   pss=5718  padding=5718  num_aliases=1
@@ -386,67 +396,77 @@
 > 1)       9758 (0.0%)  t@0x2a1000   pss=4040  padding=4040  num_aliases=1
                source_path= 	object_path=
                flags={}  name=** symbol gap 1
-> 2)   35830760 (100.0%) t@0x24ca628  pss=35821002  padding=35821002  num_aliases=1
+> 2)   35826678 (100.0%) t@0x24ca628  pss=35816920  padding=35816920  num_aliases=1
                source_path= 	object_path=
                flags={}  name=** symbol gap 2 (end of section)
-33)  77700217 (99.9%) t@0x28f000   pss=448  padding=0  num_aliases=1
+33)  77696135 (99.9%) t@0x28f000   pss=448  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=ucnv_extMatchFromU
                   full_name=ucnv_extMatchFromU(int const*, int, unsigned short const*, int, unsigned short const*, int, unsigned int*, signed char, signed char)
-34)  77700245 (99.9%) t@0x28f1c8   pss=28  padding=8  num_aliases=1
+34)  77696163 (99.9%) t@0x28f1c8   pss=28  padding=8  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={startup,gen}  name=_GLOBAL__sub_I_SkDeviceProfile.cpp
-35)  77769369 (100.0%) t@0x28f1e0   pss=69124  padding=4  num_aliases=1
+35)  77765287 (100.0%) t@0x28f1e0   pss=69124  padding=4  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={unlikely,gen}  name=foo_bar
-36)  77769393 (100.0%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
+36)  77765311 (100.0%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=BazAlias
                   full_name=BazAlias(bool)
-37)  77769417 (100.0%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
+37)  77765335 (100.0%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
              source_path= 	object_path=
              flags={}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-38)  77769420 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+38)  77765338 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=BarAlias
                   full_name=BarAlias()
-39)  77769423 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+39)  77765341 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=FooAlias
                   full_name=FooAlias()
-40)  77769426 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+40)  77765344 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen,clone}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-41)  77769429 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+41)  77765347 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/paint.cc 	object_path=third_party/sub/PaintChunker.o
              flags={clone}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-42)  77769457 (100.0%) t@0x2a0020   pss=28  padding=4  num_aliases=1
+42)  77765375 (100.0%) t@0x2a0020   pss=28  padding=4  num_aliases=1
              source_path=third_party/container/container.c 	object_path=third_party/sub/ContiguousContainer.o
              flags={}  name=blink::ContiguousContainerBase::ContiguousContainerBase
                   full_name=blink::ContiguousContainerBase::ContiguousContainerBase(blink::ContiguousContainerBase&&)
-43)  77769551 (100.0%) t@0x2a1000   pss=94  padding=0  num_aliases=1
+43)  77765469 (100.0%) t@0x2a1000   pss=94  padding=0  num_aliases=1
              source_path=third_party/container/container.c 	object_path=third_party/sub/ContiguousContainer.o
              flags={anon,clone}  name=blink::PaintChunker::releasePaintChunks
                   full_name=blink::PaintChunker::releasePaintChunks()
-44)  77769551 (100.0%) b@0x0        pss=262144  padding=0  num_aliases=1
+44)  77769503 (100.0%) t@0x2a2000   pss=4034  padding=4002  num_aliases=1
+             source_path=third_party/container/container.c 	object_path=third_party/sub/ContiguousContainer.o
+             flags={}  name=** outlined function
+45)  77769527 (100.0%) t@0x2a2020   pss=24 (size=48)  padding=0  num_aliases=2
+             source_path= 	object_path=
+             flags={}  name=** outlined function * 2
+46)  77769551 (100.0%) t@0x2a2020   pss=24 (size=48)  padding=0  num_aliases=2
+             source_path= 	object_path=
+             flags={}  name=aliasedWithOutlinedFunction
+                  full_name=aliasedWithOutlinedFunction()
+47)  77769551 (100.0%) b@0x0        pss=262144  padding=0  num_aliases=1
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=ff_cos_131072
-45)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
+48)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
              source_path=third_party/fft_fixed.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o
              flags={}  name=ff_cos_131072_fixed
-46)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
+49)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=ff_cos_65536
-47)  77769551 (100.0%) b@0x2dffda0  pss=28  padding=0  num_aliases=1
+50)  77769551 (100.0%) b@0x2dffda0  pss=28  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=g_chrome_content_browser_client
-48)  77769551 (100.0%) b@0x2dffe80  pss=200  padding=196  num_aliases=1
+51)  77769551 (100.0%) b@0x2dffe80  pss=200  padding=196  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=SaveHistogram::atomic_histogram_pointer
                   full_name=SaveHistogram(_JNIEnv*, base::android::JavaParamRef<_jobject*> const&, base::android::JavaParamRef<_jstring*> const&, base::android::JavaParamRef<_jlongArray*> const&, int)::atomic_histogram_pointer
-49)  77769551 (100.0%) b@0x2dffe84  pss=4  padding=0  num_aliases=1
+52)  77769551 (100.0%) b@0x2dffe84  pss=4  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={anon,gen}  name=g_AnimationFrameTimeHistogram_clazz
diff --git a/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden b/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
index 83469a0..0753836 100644
--- a/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
+++ b/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
@@ -1,11 +1,11 @@
 GroupedByName()
-Showing 43 symbols (43 unique) with total pss: 77769551 bytes
+Showing 46 symbols (46 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-      {0}: 6    [8,16): 3    [64,128): 2      [65536,131072): 1   [33554432,67108864): 2
-    [2,4): 2   [16,32): 9   [128,256): 1    [524288,1048576): 2
-    [4,8): 5   [32,64): 7   [256,512): 1   [1048576,2097152): 2
+      {0}: 6    [8,16): 3     [64,128): 2        [2048,4096): 1     [1048576,2097152): 2
+    [2,4): 2   [16,32): 11   [128,256): 1     [65536,131072): 1   [33554432,67108864): 2
+    [4,8): 5   [32,64): 7    [256,512): 1   [524288,1048576): 2
 Sizes: .text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
-Counts: .text=19 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
+Counts: .text=22 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
@@ -29,38 +29,42 @@
 15)  35941208 (46.2%) *@Group      21              string literal (count=3)
 16)  35941251 (46.2%) *@Group      43              ** merge strings (count=1)
 17)  37906596 (48.7%) *@Group      1965345         ** merge constants (count=1)
-18)  77023471 (99.0%) *@Group      39116875        ** symbol gaps (count=2)
-19)  77023479 (99.0%) *@Group      8                (count=1)
-20)  77023523 (99.0%) *@Group      44              Name (count=1)
-21)  77023555 (99.0%) *@Group      32              chrome::mojom::FilePatcher::Name_ (count=1)
-22)  77699595 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
-23)  77699599 (99.9%) *@Group      4               blink::CSSValueKeywordsHash::findValueImpl::value_word_list (count=1)
-24)  77699615 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
-25)  77699671 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
-26)  77699699 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
-27)  77699769 (99.9%) *@Group      70              extFromUUseMapping (count=2)
-28)  77700217 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
-29)  77700245 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
-30)  77769369 (100.0%) *@Group      69124           foo_bar (count=1)
-31)  77769393 (100.0%) *@Group      24              BazAlias (count=1)
-32)  77769423 (100.0%) *@Group      30              blink::ContiguousContainerBase::shrinkToFit (count=3)
-33)  77769426 (100.0%) *@Group      3               BarAlias (count=1)
-34)  77769429 (100.0%) *@Group      3               FooAlias (count=1)
-35)  77769457 (100.0%) *@Group      28              blink::ContiguousContainerBase::ContiguousContainerBase (count=1)
-36)  77769551 (100.0%) *@Group      94              blink::PaintChunker::releasePaintChunks (count=1)
-37)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
-38)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
-39)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
-40)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
-41)  77769551 (100.0%) *@Group      0               SaveHistogram::atomic_histogram_pointer (count=1)
-42)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
+18)  77019389 (99.0%) *@Group      39112793        ** symbol gaps (count=2)
+19)  77019397 (99.0%) *@Group      8                (count=1)
+20)  77019441 (99.0%) *@Group      44              Name (count=1)
+21)  77019473 (99.0%) *@Group      32              chrome::mojom::FilePatcher::Name_ (count=1)
+22)  77695513 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
+23)  77695517 (99.9%) *@Group      4               blink::CSSValueKeywordsHash::findValueImpl::value_word_list (count=1)
+24)  77695533 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
+25)  77695589 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
+26)  77695617 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
+27)  77695687 (99.9%) *@Group      70              extFromUUseMapping (count=2)
+28)  77696135 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
+29)  77696163 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
+30)  77765287 (100.0%) *@Group      69124           foo_bar (count=1)
+31)  77765311 (100.0%) *@Group      24              BazAlias (count=1)
+32)  77765341 (100.0%) *@Group      30              blink::ContiguousContainerBase::shrinkToFit (count=3)
+33)  77765344 (100.0%) *@Group      3               BarAlias (count=1)
+34)  77765347 (100.0%) *@Group      3               FooAlias (count=1)
+35)  77765375 (100.0%) *@Group      28              blink::ContiguousContainerBase::ContiguousContainerBase (count=1)
+36)  77765469 (100.0%) *@Group      94              blink::PaintChunker::releasePaintChunks (count=1)
+37)  77769503 (100.0%) *@Group      4034            ** outlined function (count=1)
+38)  77769527 (100.0%) *@Group      24              ** outlined function * 2 (count=1)
+39)  77769551 (100.0%) *@Group      24              aliasedWithOutlinedFunction (count=1)
+40)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
+41)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
+42)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
+43)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
+44)  77769551 (100.0%) *@Group      0               SaveHistogram::atomic_histogram_pointer (count=1)
+45)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=1)
-Showing 35 symbols (35 unique) with total pss: 77769551 bytes
+Showing 38 symbols (38 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-      {0}: 6    [8,16): 4    [32,64): 6   [128,256): 2     [65536,131072): 1     [1048576,2097152): 2
-    [2,4): 2   [16,32): 6   [64,128): 1   [256,512): 1   [524288,1048576): 2   [33554432,67108864): 2
+       {0}: 6    [16,32): 8     [128,256): 2      [65536,131072): 1   [33554432,67108864): 2
+     [2,4): 2    [32,64): 6     [256,512): 1    [524288,1048576): 2
+    [8,16): 4   [64,128): 1   [2048,4096): 1   [1048576,2097152): 2
 Sizes: .text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
-Counts: .text=19 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
+Counts: .text=22 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
@@ -80,35 +84,38 @@
 11)  35941240 (46.2%) *@Group      21              string literal (count=3)
 12)  35941283 (46.2%) *@Group      43              ** merge strings (count=1)
 13)  37906628 (48.7%) *@Group      1965345         ** merge constants (count=1)
-14)  77023503 (99.0%) *@Group      39116875        ** symbol gaps (count=2)
-15)  77023511 (99.0%) *@Group      8                (count=1)
-16)  77023555 (99.0%) *@Group      44              Name (count=1)
-17)  77699595 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
-18)  77699751 (99.9%) *@Group      156             blink (count=6)
-19)  77699767 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
-20)  77699823 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
-21)  77699851 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
-22)  77699921 (99.9%) *@Group      70              extFromUUseMapping (count=2)
-23)  77700369 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
-24)  77700397 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
-25)  77769521 (100.0%) *@Group      69124           foo_bar (count=1)
-26)  77769545 (100.0%) *@Group      24              BazAlias (count=1)
-27)  77769548 (100.0%) *@Group      3               BarAlias (count=1)
-28)  77769551 (100.0%) *@Group      3               FooAlias (count=1)
-29)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
-30)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
-31)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
-32)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
-33)  77769551 (100.0%) *@Group      0               SaveHistogram (count=1)
-34)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
+14)  77019421 (99.0%) *@Group      39112793        ** symbol gaps (count=2)
+15)  77019429 (99.0%) *@Group      8                (count=1)
+16)  77019473 (99.0%) *@Group      44              Name (count=1)
+17)  77695513 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
+18)  77695669 (99.9%) *@Group      156             blink (count=6)
+19)  77695685 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
+20)  77695741 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
+21)  77695769 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
+22)  77695839 (99.9%) *@Group      70              extFromUUseMapping (count=2)
+23)  77696287 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
+24)  77696315 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
+25)  77765439 (100.0%) *@Group      69124           foo_bar (count=1)
+26)  77765463 (100.0%) *@Group      24              BazAlias (count=1)
+27)  77765466 (100.0%) *@Group      3               BarAlias (count=1)
+28)  77765469 (100.0%) *@Group      3               FooAlias (count=1)
+29)  77769503 (100.0%) *@Group      4034            ** outlined function (count=1)
+30)  77769527 (100.0%) *@Group      24              ** outlined function * 2 (count=1)
+31)  77769551 (100.0%) *@Group      24              aliasedWithOutlinedFunction (count=1)
+32)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
+33)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
+34)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
+35)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
+36)  77769551 (100.0%) *@Group      0               SaveHistogram (count=1)
+37)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=-1)
-Showing 38 symbols (38 unique) with total pss: 77769551 bytes
+Showing 41 symbols (41 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-      {0}: 6    [8,16): 4    [64,128): 2      [65536,131072): 1   [33554432,67108864): 2
-    [2,4): 2   [16,32): 6   [128,256): 1    [524288,1048576): 2
-    [4,8): 1   [32,64): 8   [256,512): 1   [1048576,2097152): 2
+      {0}: 6    [8,16): 4    [64,128): 2        [2048,4096): 1     [1048576,2097152): 2
+    [2,4): 2   [16,32): 8   [128,256): 1     [65536,131072): 1   [33554432,67108864): 2
+    [4,8): 1   [32,64): 8   [256,512): 1   [524288,1048576): 2
 Sizes: .text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
-Counts: .text=19 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
+Counts: .text=22 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
@@ -128,38 +135,41 @@
 11)  35941208 (46.2%) *@Group      21              string literal (count=3)
 12)  35941251 (46.2%) *@Group      43              ** merge strings (count=1)
 13)  37906596 (48.7%) *@Group      1965345         ** merge constants (count=1)
-14)  77023471 (99.0%) *@Group      39116875        ** symbol gaps (count=2)
-15)  77023479 (99.0%) *@Group      8                (count=1)
-16)  77023523 (99.0%) *@Group      44              Name (count=1)
-17)  77023555 (99.0%) *@Group      32              chrome::mojom::FilePatcher (count=1)
-18)  77699595 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
-19)  77699599 (99.9%) *@Group      4               blink::CSSValueKeywordsHash::findValueImpl (count=1)
-20)  77699615 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
-21)  77699671 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
-22)  77699699 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
-23)  77699769 (99.9%) *@Group      70              extFromUUseMapping (count=2)
-24)  77700217 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
-25)  77700245 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
-26)  77769369 (100.0%) *@Group      69124           foo_bar (count=1)
-27)  77769393 (100.0%) *@Group      24              BazAlias (count=1)
-28)  77769451 (100.0%) *@Group      58              blink::ContiguousContainerBase (count=4)
-29)  77769454 (100.0%) *@Group      3               BarAlias (count=1)
-30)  77769457 (100.0%) *@Group      3               FooAlias (count=1)
-31)  77769551 (100.0%) *@Group      94              blink::PaintChunker (count=1)
-32)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
-33)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
-34)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
-35)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
-36)  77769551 (100.0%) *@Group      0               SaveHistogram (count=1)
-37)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
+14)  77019389 (99.0%) *@Group      39112793        ** symbol gaps (count=2)
+15)  77019397 (99.0%) *@Group      8                (count=1)
+16)  77019441 (99.0%) *@Group      44              Name (count=1)
+17)  77019473 (99.0%) *@Group      32              chrome::mojom::FilePatcher (count=1)
+18)  77695513 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
+19)  77695517 (99.9%) *@Group      4               blink::CSSValueKeywordsHash::findValueImpl (count=1)
+20)  77695533 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
+21)  77695589 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
+22)  77695617 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
+23)  77695687 (99.9%) *@Group      70              extFromUUseMapping (count=2)
+24)  77696135 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
+25)  77696163 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
+26)  77765287 (100.0%) *@Group      69124           foo_bar (count=1)
+27)  77765311 (100.0%) *@Group      24              BazAlias (count=1)
+28)  77765369 (100.0%) *@Group      58              blink::ContiguousContainerBase (count=4)
+29)  77765372 (100.0%) *@Group      3               BarAlias (count=1)
+30)  77765375 (100.0%) *@Group      3               FooAlias (count=1)
+31)  77765469 (100.0%) *@Group      94              blink::PaintChunker (count=1)
+32)  77769503 (100.0%) *@Group      4034            ** outlined function (count=1)
+33)  77769527 (100.0%) *@Group      24              ** outlined function * 2 (count=1)
+34)  77769551 (100.0%) *@Group      24              aliasedWithOutlinedFunction (count=1)
+35)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
+36)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
+37)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
+38)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
+39)  77769551 (100.0%) *@Group      0               SaveHistogram (count=1)
+40)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=1, min_count=2)
-Showing 35 symbols (34 unique) with total pss: 77769551 bytes
+Showing 38 symbols (36 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-     [2,4): 2    [16,32): 7        [128,256): 3    [131072,262144): 2     [1048576,2097152): 2
-     [4,8): 1    [32,64): 6        [256,512): 1    [262144,524288): 1   [33554432,67108864): 2
-    [8,16): 4   [64,128): 1   [65536,131072): 1   [524288,1048576): 2
+     [2,4): 2    [16,32): 9     [128,256): 3    [65536,131072): 1      [524288,1048576): 2
+     [4,8): 1    [32,64): 6     [256,512): 1   [131072,262144): 2     [1048576,2097152): 2
+    [8,16): 4   [64,128): 1   [2048,4096): 1   [262144,524288): 1   [33554432,67108864): 2
 Sizes: .text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
-Counts: .text=19 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
+Counts: .text=22 .rodata=12 .data.rel.ro=4 .data=6 .bss=6 .other=1
 Number of unique paths: 9
 
 Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
@@ -193,44 +203,50 @@
              ** merge strings
 13)  37906628 (48.7%) r@0x284d600  1965345        {no path}
              ** merge constants
-14)  77023503 (99.0%) *@Group      39116875       {no path}
+14)  77019421 (99.0%) *@Group      39112793       {no path}
              ** symbol gaps (count=2)
-15)  77023511 (99.0%) r@0x284e364  8              base/page_allocator.cc
-16)  77023555 (99.0%) r@0x284e370  44             base/page_allocator.cc
+15)  77019429 (99.0%) r@0x284e364  8              base/page_allocator.cc
+16)  77019473 (99.0%) r@0x284e370  44             base/page_allocator.cc
              Name
-17)  77699595 (99.9%) r@0x28f3450  676040         third_party/paint.cc
+17)  77695513 (99.9%) r@0x28f3450  676040         third_party/paint.cc
              kAnimationFrameTimeHistogramClassPath
-18)  77699751 (99.9%) *@Group      156            {no path}
+18)  77695669 (99.9%) *@Group      156            {no path}
              blink (count=6)
-19)  77699767 (99.9%) t@0x28d900   16             base/page_allocator.cc
+19)  77695685 (99.9%) t@0x28d900   16             base/page_allocator.cc
              _GLOBAL__sub_I_page_allocator.cc
-20)  77699823 (99.9%) t@0x28d910   56             base/page_allocator.cc
+20)  77695741 (99.9%) t@0x28d910   56             base/page_allocator.cc
              _GLOBAL__sub_I_bbr_sender.cc
-21)  77699851 (99.9%) t@0x28d948   28             base/page_allocator.cc
+21)  77695769 (99.9%) t@0x28d948   28             base/page_allocator.cc
              _GLOBAL__sub_I_pacing_sender.cc
-22)  77699921 (99.9%) *@Group      70             base/page_allocator.cc
+22)  77695839 (99.9%) *@Group      70             base/page_allocator.cc
              extFromUUseMapping (count=2)
-23)  77700369 (99.9%) t@0x28f000   448            $root_gen_dir/third_party/icu/ucnv_ext.c
+23)  77696287 (99.9%) t@0x28f000   448            $root_gen_dir/third_party/icu/ucnv_ext.c
              ucnv_extMatchFromU
-24)  77700397 (99.9%) t@0x28f1c8   28             $root_gen_dir/third_party/icu/ucnv_ext.c
+24)  77696315 (99.9%) t@0x28f1c8   28             $root_gen_dir/third_party/icu/ucnv_ext.c
              _GLOBAL__sub_I_SkDeviceProfile.cpp
-25)  77769521 (100.0%) t@0x28f1e0   69124          $root_gen_dir/third_party/icu/ucnv_ext.c
+25)  77765439 (100.0%) t@0x28f1e0   69124          $root_gen_dir/third_party/icu/ucnv_ext.c
              foo_bar
-26)  77769545 (100.0%) t@0x2a0000   24 (size=48)   $root_gen_dir/third_party/icu/ucnv_ext.c
+26)  77765463 (100.0%) t@0x2a0000   24 (size=48)   $root_gen_dir/third_party/icu/ucnv_ext.c
              BazAlias (num_aliases=2)
-27)  77769548 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
+27)  77765466 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
              BarAlias (num_aliases=4)
-28)  77769551 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
+28)  77765469 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
              FooAlias (num_aliases=4)
-29)  77769551 (100.0%) b@0x0        262144         third_party/fft_float.cc
+29)  77769503 (100.0%) t@0x2a2000   4034           third_party/container/container.c
+             ** outlined function
+30)  77769527 (100.0%) t@0x2a2020   24 (size=48)   {no path}
+             ** outlined function * 2 (num_aliases=2)
+31)  77769551 (100.0%) t@0x2a2020   24 (size=48)   {no path}
+             aliasedWithOutlinedFunction (num_aliases=2)
+32)  77769551 (100.0%) b@0x0        262144         third_party/fft_float.cc
              ff_cos_131072
-30)  77769551 (100.0%) b@0x0        131072         third_party/fft_fixed.cc
+33)  77769551 (100.0%) b@0x0        131072         third_party/fft_fixed.cc
              ff_cos_131072_fixed
-31)  77769551 (100.0%) b@0x0        131072         third_party/fft_float.cc
+34)  77769551 (100.0%) b@0x0        131072         third_party/fft_float.cc
              ff_cos_65536
-32)  77769551 (100.0%) b@0x2dffda0  28             $root_gen_dir/third_party/icu/ucnv_ext.c
+35)  77769551 (100.0%) b@0x2dffda0  28             $root_gen_dir/third_party/icu/ucnv_ext.c
              g_chrome_content_browser_client
-33)  77769551 (100.0%) b@0x2dffe80  200            $root_gen_dir/third_party/icu/ucnv_ext.c
+36)  77769551 (100.0%) b@0x2dffe80  200            $root_gen_dir/third_party/icu/ucnv_ext.c
              SaveHistogram::atomic_histogram_pointer
-34)  77769551 (100.0%) b@0x2dffe84  4              $root_gen_dir/third_party/icu/ucnv_ext.c
+37)  77769551 (100.0%) b@0x2dffe84  4              $root_gen_dir/third_party/icu/ucnv_ext.c
              g_AnimationFrameTimeHistogram_clazz
diff --git a/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_nm.py b/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_nm.py
index 517e211f..aa2abda 100644
--- a/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_nm.py
+++ b/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_nm.py
@@ -18,6 +18,10 @@
 002a0010 t BarAlias()
 002a0000 t blink::ContiguousContainerBase::shrinkToFit()
 002a0000 t BazAlias(bool)
+002a2000 t OUTLINED_FUNCTION_0
+002a2020 t OUTLINED_FUNCTION_1
+002a2020 t OUTLINED_FUNCTION_2
+002a2020 t aliasedWithOutlinedFunction()
 002b6bb8 t $t.22
 """.format(_SHRINK_TO_FIT_CLONE)
 
@@ -62,6 +66,9 @@
          'ink::ContiguousContainerBase&&)'),
         ('01010101 t (anonymous namespace)::blink::PaintChunker::releasePaintCh'
          'unks() [clone .part.1]'),
+        ('01010101 t OUTLINED_FUNCTION_0'),
+        ('01010101 t OUTLINED_FUNCTION_1'),
+        ('01010101 t OUTLINED_FUNCTION_2'),
     ],
     'obj/base/base/page_allocator.o': [
         '01010101 t _GLOBAL__sub_I_page_allocator.cc',
@@ -73,14 +80,14 @@
         '01010101 t extFromUUseMapping(signed char, unsigned int, int)',
         '01010101 t Name',
         '01010101 v vtable for mojo::MessageReceiver',
-        '01010101 r kMethodsAnimationFrameTimeHistogram',
+        '01010101 r kMethodsAnimationFrameTimeHistogram (.llvm.12341234)',
         '01010101 r google::protobuf::internal::pLinuxKernelCmpxchg',
     ],
     'obj/third_party/ffmpeg/libffmpeg_internal.a': [
         '',
         'fft_float.o:',
         '01010101 b ff_cos_65536',
-        '01010101 b ff_cos_131072',
+        '01010101 b ff_cos_131072.1.llvm.43214321',
         '002a0010 t FooAlias()',
         '002b6bb8 t $t',
         '002a0010 t BarAlias()',
diff --git a/tools/binary_size/libsupersize/testdata/test.map b/tools/binary_size/libsupersize/testdata/test.map
index 25be0b3b..e9a9c2c 100644
--- a/tools/binary_size/libsupersize/testdata/test.map
+++ b/tools/binary_size/libsupersize/testdata/test.map
@@ -102,6 +102,10 @@
  .text._ZN10_GLOBAL__N5blink12PaintChunker18releasePaintChunksEv.part.1
                 0x002a1000       0x5e obj/third_party/WebKit.a(sub/ContiguousContainer.o)
                 0x002a1001                (anonymous namespace)::blink::PaintChunker::releasePaintChunks() [clone .part.1]
+ .text.OUTLINED_FUNCTION_0
+                0x002a2000       0x20 obj/third_party/WebKit.a(sub/ContiguousContainer.o)
+ .text.OUTLINED_FUNCTION_1
+                0x002a2020       0x30 obj/third_party/WebKit.a(sub/ContiguousContainer.o)
 
 .ARM.exidx      0x024ca628   0x1771c8
  .ARM.exidx.text.startup._GLOBAL__sub_I_page_allocator.cc
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py b/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
index 78a663a..3049c4c 100644
--- a/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
+++ b/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
@@ -9,7 +9,6 @@
 from common import chrome_proxy_measurements as measurements
 from common.chrome_proxy_measurements import ChromeProxyValidation
 from integration_tests import chrome_proxy_metrics as metrics
-from metrics import loading
 from telemetry.core import exceptions, util
 from telemetry.page import legacy_page_test
 
diff --git a/tools/chrome_proxy/webdriver/lite_page.py b/tools/chrome_proxy/webdriver/lite_page.py
index 655abe7..8dcc3a6d 100644
--- a/tools/chrome_proxy/webdriver/lite_page.py
+++ b/tools/chrome_proxy/webdriver/lite_page.py
@@ -195,6 +195,47 @@
       self.assertEqual(1, btf_response)
       self.assertGreater(1, image_responses)
 
+  # Tests that the stale previews UI is shown on a stale Lite page.
+  @AndroidOnly
+  @ChromeVersionEqualOrAfterM(65)
+  def testStaleLitePageNano(self):
+    # If it was attempted to run with another experiment, skip this test.
+    if common.ParseFlags().browser_args and ('--data-reduction-proxy-experiment'
+        in common.ParseFlags().browser_args):
+      self.skipTest('This test cannot be run with other experiments.')
+    with TestDriver() as test_driver:
+      test_driver.AddChromeArg('--enable-spdy-proxy-auth')
+      test_driver.AddChromeArg('--enable-features='
+                               'Previews,DataReductionProxyDecidesTransform')
+      test_driver.AddChromeArg('--force-effective-connection-type=2G')
+      # Set exp=client_test_nano to force Lite page response.
+      test_driver.AddChromeArg(
+        '--data-reduction-proxy-experiment=client_test_nano')
+      # LoadURL waits for onLoadFinish so the Previews UI will be showing by
+      # then since it's triggered on commit.
+      test_driver.LoadURL(
+        'http://check.googlezip.net/cacheable/test.html?age_seconds=360')
+
+      histogram = test_driver.GetHistogram(
+        'Previews.StalePreviewTimestampShown')
+      self.assertEqual(1, histogram['count'])
+      # Check that there is a single entry in the 'Timestamp Shown' bucket.
+      self.assertEqual(
+        {'count': 1, 'high': 1, 'low': 0},
+        histogram['buckets'][0])
+
+      # Go to a non stale page and check that the stale timestamp is not shown.
+      test_driver.LoadURL(
+        'http://check.googlezip.net/cacheable/test.html?age_seconds=0')
+
+      histogram = test_driver.GetHistogram(
+        'Previews.StalePreviewTimestampShown')
+      # Check that there is still a single entry in the 'Timestamp Shown'
+      # bucket.
+      self.assertEqual(
+        {'count': 1, 'high': 1, 'low': 0},
+        histogram['buckets'][0])
+
   # Lo-Fi fallback is not supported without the
   # DataReductionProxyDecidesTransform feature. Check that no Lo-Fi response
   # is received if a Lite Page is not served.
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py
index 745362c..b6d718cd 100755
--- a/tools/clang/scripts/package.py
+++ b/tools/clang/scripts/package.py
@@ -269,7 +269,7 @@
     # lib/clang/*/lib/linux/libclang_rt.{[atm]san,san,ubsan,fuzzer,profile}-*.a,
     # but not dfsan.
     want.extend(['lib/clang/*/lib/linux/*[atm]san*',
-                 'lib/clang/*/lib/linux/*ubsan*',
+                 'lib/clang/*/lib/linux/*ubsan_standalone*',
                  'lib/clang/*/lib/linux/*libclang_rt.fuzzer_no_main*',
                  'lib/clang/*/lib/linux/*libclang_rt.san*',
                  'lib/clang/*/lib/linux/*profile*',
@@ -280,7 +280,7 @@
                  'lib/clang/*/lib/windows/clang_rt.asan*.lib',
                  'lib/clang/*/lib/windows/clang_rt.fuzzer_no_main*.lib',
                  'lib/clang/*/lib/windows/clang_rt.profile*.lib',
-                 'lib/clang/*/lib/windows/clang_rt.ubsan*.lib',
+                 'lib/clang/*/lib/windows/clang_rt.ubsan_standalone*.lib',
                  ])
 
   if sys.platform in ('linux2', 'darwin'):
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 5aa6520..60215e9f 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -27,7 +27,7 @@
 # Do NOT CHANGE this if you don't know what you're doing -- see
 # https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
 # Reverting problematic clang rolls is safe, though.
-CLANG_REVISION = '344066'
+CLANG_REVISION = '346388'
 
 use_head_revision = bool(os.environ.get('LLVM_FORCE_HEAD_REVISION', '0')
                          in ('1', 'YES'))
@@ -781,6 +781,14 @@
               'i686': 'x86',
           }[target_arch]])
 
+      # NDK r16 "helpfully" installs libc++ as libstdc++ "so the compiler will
+      # pick it up by default". Only these days, the compiler tries to find
+      # libc++ instead. See https://crbug.com/902270.
+      shutil.copy(os.path.join(toolchain_dir, 'sysroot/usr/lib/libstdc++.a'),
+                  os.path.join(toolchain_dir, 'sysroot/usr/lib/libc++.a'))
+      shutil.copy(os.path.join(toolchain_dir, 'sysroot/usr/lib/libstdc++.so'),
+                  os.path.join(toolchain_dir, 'sysroot/usr/lib/libc++.so'))
+
       # Build compiler-rt runtimes needed for Android in a separate build tree.
       build_dir = os.path.join(LLVM_BUILD_DIR, 'android-' + target_arch)
       if not os.path.exists(build_dir):
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py
index d4645a5..e0ca15e 100755
--- a/tools/code_coverage/coverage.py
+++ b/tools/code_coverage/coverage.py
@@ -661,7 +661,7 @@
   if _IsIOSCommand(command):
     # For a given application bundle, the binary resides in the bundle and has
     # the same name with the application without the .app extension.
-    app_path = command_parts[-1].rstrip(os.path.sep)
+    app_path = command_parts[1].rstrip(os.path.sep)
     app_name = os.path.splitext(os.path.basename(app_path))[0]
     return os.path.join(app_path, app_name)
 
diff --git a/tools/cygprofile/cygprofile_utils.py b/tools/cygprofile/cygprofile_utils.py
index 4169c6b..6d83d8f5 100644
--- a/tools/cygprofile/cygprofile_utils.py
+++ b/tools/cygprofile/cygprofile_utils.py
@@ -9,6 +9,10 @@
 import os
 import re
 
+
+START_OF_TEXT_SYMBOL = 'linker_script_start_of_text'
+
+
 class WarningCollector(object):
   """Collects warnings, but limits the number printed to a set value."""
   def __init__(self, max_warnings, level=logging.WARNING):
diff --git a/tools/cygprofile/process_profiles.py b/tools/cygprofile/process_profiles.py
index 592cce9..ecc41c9 100755
--- a/tools/cygprofile/process_profiles.py
+++ b/tools/cygprofile/process_profiles.py
@@ -15,6 +15,7 @@
     os.path.dirname(__file__), os.pardir, os.pardir))
 path = os.path.join(_SRC_PATH, 'tools', 'cygprofile')
 sys.path.append(path)
+import cygprofile_utils
 import symbol_extractor
 
 
@@ -147,7 +148,8 @@
         symbols.append(self.OffsetToPrimaryMap()[o - 1].name)
       else:
         not_found += 1
-    logging.warning('%d offsets do not have matching symbol', not_found)
+    if not_found:
+      logging.warning('%d offsets do not have matching symbol', not_found)
     return symbols
 
   def OffsetsPrimarySize(self, offsets):
@@ -234,7 +236,7 @@
     for i in items:
       dump_offset = get(i)
       idx = dump_offset / 4
-      assert idx < len(dump_offset_to_symbol_info), (
+      assert dump_offset >= 0 and idx < len(dump_offset_to_symbol_info), (
           'Dump offset out of binary range')
       symbol_info = dump_offset_to_symbol_info[idx]
       if symbol_info is None:
@@ -254,12 +256,17 @@
         section, maps it to a symbol, or None.
     """
     if self._offset_to_symbol_info is None:
-      min_offset = min(s.offset for s in self.SymbolInfos())
+      start_syms = [s for s in self.SymbolInfos()
+                    if s.name == cygprofile_utils.START_OF_TEXT_SYMBOL]
+      assert len(start_syms) == 1, 'Can\'t find unique start of text symbol'
+      start_of_text = start_syms[0].offset
       max_offset = max(s.offset + s.size for s in self.SymbolInfos())
-      text_length_words = (max_offset - min_offset) / 4
+      text_length_words = (max_offset - start_of_text) / 4
       self._offset_to_symbol_info = [None for _ in xrange(text_length_words)]
       for s in self.SymbolInfos():
-        offset = s.offset - min_offset
+        offset = s.offset - start_of_text
+        if offset < 0:
+          continue
         for i in range(offset / 4, (offset + s.size) / 4):
           self._offset_to_symbol_info[i] = s
     return self._offset_to_symbol_info
diff --git a/tools/cygprofile/process_profiles_unittest.py b/tools/cygprofile/process_profiles_unittest.py
index 3bda20d..0f03955 100755
--- a/tools/cygprofile/process_profiles_unittest.py
+++ b/tools/cygprofile/process_profiles_unittest.py
@@ -16,9 +16,10 @@
                         TestProfileManager)
 
 class ProcessProfilesTestCase(unittest.TestCase):
+  START_SYMBOL = 'linker_script_start_of_text'
 
   def setUp(self):
-    self.symbol_0 = SimpleTestSymbol('0', 0, 0)
+    self.symbol_0 = SimpleTestSymbol(self.START_SYMBOL, 0, 0)
     self.symbol_1 = SimpleTestSymbol('1', 8, 16)
     self.symbol_2 = SimpleTestSymbol('2', 32, 8)
     self.symbol_3 = SimpleTestSymbol('3', 40, 12)
@@ -39,6 +40,18 @@
     offset_to_symbol_info = processor._GetDumpOffsetToSymbolInfo()
     self.assertListEqual(self.offset_to_symbol_info, offset_to_symbol_info)
 
+  def testSymbolsBeforeStart(self):
+    self.symbol_infos = [SimpleTestSymbol(s.name, s.offset + 8, s.size)
+                         for s in self.symbol_infos]
+    self.symbol_infos.append(SimpleTestSymbol('early', 0, 4))
+    processor = TestSymbolOffsetProcessor(self.symbol_infos)
+    offset_to_symbol_info = processor._GetDumpOffsetToSymbolInfo()
+    # The 'early' symbol should be omitted.
+    self.assertEqual(([None, None] + [self.symbol_infos[1]] * 4 +
+                      [None] * 2 + [self.symbol_infos[2]] * 2 +
+                      [self.symbol_infos[3]] * 3),
+                     offset_to_symbol_info)
+
   def testGetReachedOffsetsFromDump(self):
     processor = TestSymbolOffsetProcessor(self.symbol_infos)
     # 2 hits for symbol_1, 0 for symbol_2, 1 for symbol_3
@@ -60,7 +73,7 @@
 
   def testGetOrderedSymbols(self):
     processor = TestSymbolOffsetProcessor(self.symbol_infos)
-    self.assertListEqual(['1', '3', '0'],
+    self.assertListEqual(['1', '3', self.START_SYMBOL],
                          processor.GetOrderedSymbols([8, 41, 6, 0]))
 
   def testOffsetToSymbolsMap(self):
diff --git a/tools/cygprofile/profile_android_startup.py b/tools/cygprofile/profile_android_startup.py
index fc75e81..b13b2aad 100755
--- a/tools/cygprofile/profile_android_startup.py
+++ b/tools/cygprofile/profile_android_startup.py
@@ -186,7 +186,7 @@
   # order to keep devices tidy.
   _LEGACY_PROFILE_DIRS = ['/data/local/tmp/chrome/cyglog']
 
-  TEST_URL = 'https://www.google.com/#hl=en&q=science'
+  TEST_URL = 'http://en.m.wikipedia.org/wiki/Science'
   _WPR_ARCHIVE = os.path.join(
       os.path.dirname(__file__), 'memory_top_10_mobile_000.wprgo')
 
@@ -264,6 +264,7 @@
       logging.info('Using pregenerated profiles instead of running profile')
       logging.info('Profile files: %s', '\n'.join(self._pregenerated_profiles))
       return self._pregenerated_profiles
+    self._device.adb.Logcat(clear=True)
     self._Install(apk)
     try:
       changer = self._SetChromeFlags(package_info)
@@ -274,6 +275,11 @@
           self._RunProfileCollection(package_info, self._simulate_user)
       else:
         self._RunProfileCollection(package_info, self._simulate_user)
+    except device_errors.CommandFailedError as exc:
+      logging.error('Exception %s; dumping logcat', exc)
+      for logcat_line in self._device.adb.Logcat(dump=True):
+        logging.error(logcat_line)
+      raise
     finally:
       self._RestoreChromeFlags(changer)
 
diff --git a/tools/cygprofile/symbol_extractor.py b/tools/cygprofile/symbol_extractor.py
index 4b9e808..3b1408c4 100644
--- a/tools/cygprofile/symbol_extractor.py
+++ b/tools/cygprofile/symbol_extractor.py
@@ -35,6 +35,56 @@
   _arch = arch
 
 
+# Regular expression to match lines printed by 'objdump -t -w'. An example of
+# such line looks like this:
+# 018db2de l     F .text  00000060              .hidden _ZN8SkBitmapC2ERKS_
+#
+# The regex intentionally allows matching more than valid inputs. This gives
+# more protection against potentially incorrectly silently ignoring unmatched
+# input lines. Instead a few assertions early in _FromObjdumpLine() check the
+# validity of a few parts matched as groups.
+_OBJDUMP_LINE_RE = re.compile(r'''
+  # The offset of the function, as hex.
+  (?P<offset>^[0-9a-f]+)
+
+  # The space character.
+  [ ]
+
+  # The 7 groups of flag characters, one character each.
+  (
+    (?P<assert_scope>.)           # Global, local, unique local, etc.
+    (?P<assert_weak_or_strong>.)
+    (?P<assert_4spaces>.{4})      # Constructor, warning, indirect ref,
+                                  # debugger symbol.
+    (?P<symbol_type>.)            # Function, object, file or normal.
+  )
+
+  [ ]
+
+  # The section name should start with ".text", can be ".text.foo". With LLD,
+  # and especially LTO the traces of input sections are not preserved. Support
+  # ".text.foo" for a little longer time because it is easy.
+  (?P<section>.text[^0-9a-f]*)
+
+  (?P<assert_tab> \s+)
+
+  # The size of the symbol, as hex.
+  (?P<size>[0-9a-f]+)
+
+  # Normally separated out by 14 spaces, but some bits in ELF may theoretically
+  # affect this length.
+  (?P<assert_14spaces>[ ]+)
+
+  # Hidden symbols should be treated as usual.
+  (.hidden [ ])?
+
+  # The symbol name.
+  (?P<name>.*)
+
+  $
+  ''', re.VERBOSE)
+
+
 def _FromObjdumpLine(line):
   """Create a SymbolInfo by parsing a properly formatted objdump output line.
 
@@ -44,29 +94,57 @@
   Returns:
     An instance of SymbolInfo if the line represents a symbol, None otherwise.
   """
-  # All of the symbol lines we care about are in the form
-  # 0000000000  g    F   .text.foo     000000000 [.hidden] foo
-  # where g (global) might also be l (local) or w (weak).
-  parts = line.split()
-  if len(parts) < 6 or parts[2] != 'F':
+  m = _OBJDUMP_LINE_RE.match(line)
+  if not m:
     return None
 
-  assert len(parts) == 6 or (len(parts) == 7 and parts[5] == '.hidden')
-  accepted_scopes = set(['g', 'l', 'w'])
-  assert parts[1] in accepted_scopes
+  assert m.group('assert_scope') in set(['g', 'l']), line
+  assert m.group('assert_weak_or_strong') in set(['w', ' ']), line
+  assert m.group('assert_tab') == '\t', line
+  assert m.group('assert_4spaces') == ' ' * 4, line
+  assert m.group('assert_14spaces') == ' ' * 14, line
+  name = m.group('name')
+  offset = int(m.group('offset'), 16)
 
-  offset = int(parts[0], 16)
-  section = parts[3]
-  size = int(parts[4], 16)
-  name = parts[-1].rstrip('\n')
+  # Output the label that contains the earliest offset. It is needed later for
+  # translating offsets from the profile dumps.
+  if name == cygprofile_utils.START_OF_TEXT_SYMBOL:
+    return SymbolInfo(name=name, offset=offset, section='.text', size=0)
+
+  # Check symbol type for validity and ignore some types.
+  # From objdump manual page: The symbol is the name of a function (F) or a file
+  # (f) or an object (O) or just a normal symbol (a space). The 'normal' symbols
+  # seens so far has been function-local labels.
+  symbol_type = m.group('symbol_type')
+  if symbol_type == ' ':
+    # Ignore local goto labels. Unfortunately, v8 builtins (like 'Builtins_.*')
+    # are indistinguishable from labels of size 0 other than by name.
+    return None
+  # Guard against file symbols, since they are normally not seen in the
+  # binaries we parse.
+  assert symbol_type != 'f', line
+
+  # Extract the size from the ELF field. This value sometimes does not reflect
+  # the real size of the function. One reason for that is the '.size' directive
+  # in the assembler. As a result, a few functions in .S files have the size 0.
+  # They are not instrumented (yet), but maintaining their order in the
+  # orderfile may be important in some cases.
+  size = int(m.group('size'), 16)
+
   # Forbid ARM mapping symbols and other unexpected symbol names, but allow $
   # characters in a non-initial position, which can appear as a component of a
   # mangled name, e.g. Clang can mangle a lambda function to:
   # 02cd61e0 l     F .text  000000c0 _ZZL11get_globalsvENK3$_1clEv
   # The equivalent objdump line from GCC is:
   # 0325c58c l     F .text  000000d0 _ZZL11get_globalsvENKUlvE_clEv
-  assert re.match('^[a-zA-Z0-9_.][a-zA-Z0-9_.$]*$', name)
-  return SymbolInfo(name=name, offset=offset, section=section, size=size)
+  #
+  # Also disallow .internal and .protected symbols (as well as other flags),
+  # those have not appeared in the binaries we parse. Rejecting these extra
+  # prefixes is done by disallowing spaces in symbol names.
+  assert re.match('^[a-zA-Z0-9_.][a-zA-Z0-9_.$]*$', name), name
+
+  return SymbolInfo(name=name, offset=offset, section=m.group('section'),
+      size=size)
 
 
 def _SymbolInfosFromStream(objdump_lines):
@@ -81,7 +159,7 @@
   name_to_offsets = collections.defaultdict(list)
   symbol_infos = []
   for line in objdump_lines:
-    symbol_info = _FromObjdumpLine(line)
+    symbol_info = _FromObjdumpLine(line.rstrip('\n'))
     if symbol_info is not None:
       name_to_offsets[symbol_info.name].append(symbol_info.offset)
       symbol_infos.append(symbol_info)
diff --git a/tools/cygprofile/symbol_extractor_unittest.py b/tools/cygprofile/symbol_extractor_unittest.py
index f852401..32e43164 100755
--- a/tools/cygprofile/symbol_extractor_unittest.py
+++ b/tools/cygprofile/symbol_extractor_unittest.py
@@ -6,37 +6,67 @@
 import symbol_extractor
 import unittest
 
+
+# The number of spaces that objdump prefixes each symbol with.
+SPACES = ' ' * 14
+
+
 class TestSymbolInfo(unittest.TestCase):
   def testIgnoresBlankLine(self):
     symbol_info = symbol_extractor._FromObjdumpLine('')
     self.assertIsNone(symbol_info)
 
   def testIgnoresMalformedLine(self):
-    # This line is too short.
-    line = ('00c1b228      F .text  00000060 _ZN20trace_event')
+    # This line is too short: only 6 flags.
+    line = ('00c1b228      F .text\t00000060' + SPACES + '_ZN20trace_event')
     symbol_info = symbol_extractor._FromObjdumpLine(line)
     self.assertIsNone(symbol_info)
-    # This line has the wrong marker.
-    line = '00c1b228 l     f .text  00000060 _ZN20trace_event'
-    symbol_info = symbol_extractor._FromObjdumpLine(line)
-    self.assertIsNone(symbol_info)
+
+  def testWrongSymbolType(self):
+    # This line has unsupported 'f' as symbol type.
+    line = '00c1b228 l     f .text\t00000060' + SPACES + '_ZN20trace_event'
+    self.assertRaises(AssertionError, symbol_extractor._FromObjdumpLine, line)
 
   def testAssertionErrorOnInvalidLines(self):
     # This line has an invalid scope.
-    line = ('00c1b228 z     F .text  00000060 _ZN20trace_event')
+    line = ('00c1b228 z     F .text\t00000060' + SPACES + '_ZN20trace_event')
     self.assertRaises(AssertionError, symbol_extractor._FromObjdumpLine, line)
-    # This line has too many fields.
-    line = ('00c1b228 l     F .text  00000060 _ZN20trace_event too many')
+    # This line has the symbol name with spaces in it.
+    line = ('00c1b228 l     F .text\t00000060' + SPACES +
+        '_ZN20trace_event too many')
     self.assertRaises(AssertionError, symbol_extractor._FromObjdumpLine, line)
-    # This line has invalid characters in the symbol.
-    line = ('00c1b228 l     F .text  00000060 _ZN20trace_?bad')
+    # This line has invalid characters in the symbol name.
+    line = ('00c1b228 l     F .text\t00000060' + SPACES + '_ZN20trace_?bad')
     self.assertRaises(AssertionError, symbol_extractor._FromObjdumpLine, line)
     # This line has an invalid character at the start of the symbol name.
-    line = ('00c1b228 l     F .text  00000060 $_ZN20trace_bad')
+    line = ('00c1b228 l     F .text\t00000060' + SPACES + '$_ZN20trace_bad')
     self.assertRaises(AssertionError, symbol_extractor._FromObjdumpLine, line)
 
+  def testSymbolTypeObject(self):
+    # Builds with ThinLTO produce symbols of type 'O'.
+    line = ('009faf60 l     O .text\t00000500' + SPACES + 'AES_Td')
+    symbol_info = symbol_extractor._FromObjdumpLine(line)
+    self.assertIsNotNone(symbol_info)
+    self.assertEquals(0x009faf60, symbol_info.offset)
+    self.assertEquals('.text', symbol_info.section)
+    self.assertEquals(0x500, symbol_info.size)
+    self.assertEquals('AES_Td', symbol_info.name)
+
+  def testSymbolFromLocalLabel(self):
+    line = ('00f64b80 l       .text\t00000000' + SPACES + 'Builtins_Abort')
+    symbol_info = symbol_extractor._FromObjdumpLine(line)
+    self.assertIsNone(symbol_info)
+
+  def testStartOfText(self):
+    line = ('00918000 l       .text\t00000000' + SPACES +
+        '.hidden linker_script_start_of_text')
+    symbol_info = symbol_extractor._FromObjdumpLine(line)
+    self.assertIsNotNone(symbol_info)
+    self.assertEquals(0x00918000, symbol_info.offset)
+    self.assertEquals('linker_script_start_of_text', symbol_info.name)
+
   def testSymbolInfo(self):
-    line = ('00c1c05c l     F .text  0000002c '
+    line = ('00c1c05c l     F .text\t0000002c' + SPACES +
             '_GLOBAL__sub_I_chrome_main_delegate.cc')
     test_name = '_GLOBAL__sub_I_chrome_main_delegate.cc'
     test_offset = 0x00c1c05c
@@ -50,7 +80,7 @@
     self.assertEquals(test_section, symbol_info.section)
 
   def testHiddenSymbol(self):
-    line = ('00c1c05c l     F .text  0000002c '
+    line = ('00c1c05c l     F .text\t0000002c' + SPACES +
             '.hidden _GLOBAL__sub_I_chrome_main_delegate.cc')
     test_name = '_GLOBAL__sub_I_chrome_main_delegate.cc'
     test_offset = 0x00c1c05c
@@ -66,7 +96,8 @@
   def testDollarInSymbolName(self):
     # A $ character elsewhere in the symbol name is fine.
     # This is an example of a lambda function name from Clang.
-    line = ('00c1b228 l     F .text  00000060 _ZZL11get_globalsvENK3$_1clEv')
+    line = ('00c1b228 l     F .text\t00000060' + SPACES +
+       '_ZZL11get_globalsvENK3$_1clEv')
     symbol_info = symbol_extractor._FromObjdumpLine(line)
     self.assertIsNotNone(symbol_info)
     self.assertEquals(0xc1b228, symbol_info.offset)
@@ -79,10 +110,10 @@
   def testSymbolInfosFromStream(self):
     lines = ['Garbage',
              '',
-             '00c1c05c l     F .text  0000002c first',
+             '00c1c05c l     F .text\t0000002c' + SPACES + 'first',
              ''
              'more garbage',
-             '00155 g     F .text  00000012 second']
+             '00155 g     F .text\t00000012' + SPACES + 'second']
     symbol_infos = symbol_extractor._SymbolInfosFromStream(lines)
     self.assertEquals(len(symbol_infos), 2)
     first = symbol_extractor.SymbolInfo('first', 0x00c1c05c, 0x2c, '.text')
diff --git a/tools/determinism/deterministic_build_whitelist.pyl b/tools/determinism/deterministic_build_whitelist.pyl
index 30a24416..4227a83 100644
--- a/tools/determinism/deterministic_build_whitelist.pyl
+++ b/tools/determinism/deterministic_build_whitelist.pyl
@@ -33,6 +33,12 @@
     'mr_extension/release',
   ],
 
+  'linux_component': [
+    # https://crbug.com/900696
+    'browser_tests.isolated',
+    'remoting-webapp.v2.zip',
+  ],
+
   # https://crbug.com/330262
   'mac': [
     # ld64 in current Xcode versions is not deterministic. Most smaller binaries
diff --git a/tools/gdb/gdb_chrome.py b/tools/gdb/gdb_chrome.py
index fdbf6ff..c8e2594 100644
--- a/tools/gdb/gdb_chrome.py
+++ b/tools/gdb/gdb_chrome.py
@@ -30,6 +30,11 @@
 
 sys.path.insert(0, os.path.join(
     os.path.dirname(os.path.abspath(__file__)),
+    'util'))
+import class_methods
+
+sys.path.insert(0, os.path.join(
+    os.path.dirname(os.path.abspath(__file__)),
     '..', '..', 'third_party', 'blink', 'tools', 'gdb'))
 try:
   import blink
@@ -375,3 +380,29 @@
 
 
 gdb.printing.register_pretty_printer(gdb, pp_set, replace=_DEBUGGING)
+
+
+"""Implementations of inlined libc++ std container functions."""
+@class_methods.Class('std::__1::vector', template_types=['T'])
+class LibcppVector(object):
+    @class_methods.member_function('T&', 'operator[]', ['int'])
+    def element(obj, i):
+        return obj['__begin_'][i]
+
+    @class_methods.member_function('size_t', 'size', [])
+    def size(obj):
+        return obj['__end_'] - obj['__begin_']
+
+@class_methods.Class('std::__1::unique_ptr', template_types=['T'])
+class LibcppUniquePtr(object):
+    @class_methods.member_function('T*', 'get', [])
+    def get(obj):
+        return obj['__ptr_']['__value_']
+
+    @class_methods.member_function('T*', 'operator->', [])
+    def arrow(obj):
+        return obj['__ptr_']['__value_']
+
+    @class_methods.member_function('T&', 'operator*', [])
+    def dereference(obj):
+        return obj['__ptr_']['__value_'].dereference()
diff --git a/tools/gdb/util/class_methods.py b/tools/gdb/util/class_methods.py
new file mode 100644
index 0000000..2cb7e25
--- /dev/null
+++ b/tools/gdb/util/class_methods.py
@@ -0,0 +1,185 @@
+# Copyright (c) 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Helper library for defining XMethod implementations on C++ classes.
+
+Include this library and then define python implementations of C++ methods
+using the Class and member_function decorator functions.
+"""
+
+import gdb
+import gdb.xmethod
+import operator
+import re
+
+
+class MemberFunction(object):
+  def __init__(self, return_type, name, arguments, wrapped_function):
+    self.return_type = return_type
+    self.name = name
+    self.arguments = arguments
+    self.function_ = wrapped_function
+
+  def __call__(self, *args):
+    self.function_(*args)
+
+
+def member_function(return_type, name, arguments):
+  """Decorate a member function.
+
+  See Class decorator for example usage within a class.
+
+  Args:
+    return_type: The return type of the function (e.g. 'int')
+    name: The function name (e.g. 'sum')
+    arguments: The argument types for this function (e.g. ['int', 'int'])
+
+    Each type can be a string (e.g. 'int', 'std::string', 'T*') or a
+    function which constructs the return type. See CreateTypeResolver
+    for details about type resolution.
+  """
+  def DefineMember(fn):
+    return MemberFunction(return_type, name, arguments, fn)
+  return DefineMember
+
+
+def Class(class_name, template_types):
+  """Decorate a python class with its corresponding C++ type.
+  Args:
+    class_name: The canonical string identifier for the class (e.g. base::Foo)
+    template_types: An array of names for each templated type (e.g. ['K',
+    'V'])
+
+  Example:
+    As an example, the following is an implementation of size() and operator[]
+    on std::__1::vector, functions which are normally inlined and not
+    normally callable from gdb.
+
+    @class_methods.Class('std::__1::vector', template_types=['T'])
+    class LibcppVector(object):
+      @class_methods.member_function('T&', 'operator[]', ['int'])
+      def element(obj, i):
+        return obj['__begin_'][i]
+
+      @class_methods.member_function('size_t', 'size', [])
+      def size(obj):
+        return obj['__end_'] - obj['__begin_']
+
+  Note:
+    Note that functions are looked up by the function name, which means that
+    functions cannot currently have overloaded implementations for different
+    arguments.
+  """
+
+  class MethodWorkerWrapper(gdb.xmethod.XMethod):
+    """Wrapper of an XMethodWorker class as an XMethod."""
+    def __init__(self, name, worker_class):
+      super(MethodWorkerWrapper, self).__init__(name)
+      self.name = name
+      self.worker_class = worker_class
+
+
+  class ClassMatcher(gdb.xmethod.XMethodMatcher):
+    """Matches member functions of one class template."""
+    def __init__(self, obj):
+      super(ClassMatcher, self).__init__(class_name)
+
+      # Constructs a regular expression to match this type.
+      self._class_regex = re.compile(
+          '^' + re.escape(class_name) +
+          ('<.*>' if template_types > 0 else '') + '$')
+
+      # Construct a dictionary and array of methods
+      self.dict = {}
+      self.methods = []
+      for name in dir(obj):
+        attr = getattr(obj, name)
+        if not isinstance(attr, MemberFunction):
+          continue
+
+        name = attr.name
+        return_type = CreateTypeResolver(attr.return_type)
+        arguments = [CreateTypeResolver(arg) for arg in
+                     attr.arguments]
+        method = MethodWorkerWrapper(
+            attr.name,
+            CreateTemplatedMethodWorker(return_type,
+                                        arguments, attr.function_))
+        self.methods.append(method)
+
+    def match(self, class_type, method_name):
+      if not re.match(self._class_regex, class_type.tag):
+        return None
+      templates = [class_type.template_argument(i) for i in
+                   range(len(template_types))]
+      return [method.worker_class(templates) for method in self.methods
+              if method.name == method_name and method.enabled]
+
+
+  def CreateTypeResolver(type_desc):
+    """Creates a callback which resolves to the appropriate type when
+    invoked.
+
+    This is a helper to allow specifying simple types as strings when
+    writing function descriptions. For complex cases, a callback can be
+    passed which will be invoked when template instantiation is known.
+
+    Args:
+      type_desc: A callback generating the type or a string description of
+          the type to lookup. Supported types are classes in the
+          template_classes array (e.g. T) which will be looked up when those
+          templated classes are known, or globally visible type names (e.g.
+          int, base::Foo).
+
+          Types can be modified by appending a '*' or '&' to denote a
+          pointer or reference.
+
+          If a callback is used, the callback will be passed an array of the
+          instantiated template types.
+
+    Note:
+      This does not parse complex types such as std::vector<T>::iterator,
+      to refer to types like these you must currently write a callback
+      which constructs the appropriate type.
+    """
+    if callable(type_desc):
+      return type_desc
+    if type_desc == 'void':
+      return lambda T: None
+    if type_desc[-1] == '&':
+      inner_resolver = CreateTypeResolver(type_desc[:-1])
+      return lambda template_types: inner_resolver(template_types).reference()
+    if type_desc[-1] == '*':
+      inner_resolver = CreateTypeResolver(type_desc[:-1])
+      return lambda template_types: inner_resolver(template_types).pointer()
+    try:
+      template_index = template_types.index(type_desc)
+      return operator.itemgetter(template_index)
+    except ValueError:
+      return lambda template_types: gdb.lookup_type(type_desc)
+
+
+  def CreateTemplatedMethodWorker(return_callback, args_callbacks,
+                                  method_callback):
+    class TemplatedMethodWorker(gdb.xmethod.XMethodWorker):
+      def __init__(self, templates):
+        super(TemplatedMethodWorker, self).__init__()
+        self._templates = templates
+
+      def get_arg_types(self):
+        return [cb(self._templates) for cb in args_callbacks]
+
+      def get_result_type(self, obj):
+        return return_callback(self._templates)
+
+      def __call__(self, *args):
+        return method_callback(*args)
+    return TemplatedMethodWorker
+
+  def DefineClass(obj):
+    matcher = ClassMatcher(obj)
+    gdb.xmethod.register_xmethod_matcher(None, matcher)
+    return matcher
+
+  return DefineClass
diff --git a/tools/generate_stubs/generate_stubs.py b/tools/generate_stubs/generate_stubs.py
index 7d2f91b8..47fe033a 100755
--- a/tools/generate_stubs/generate_stubs.py
+++ b/tools/generate_stubs/generate_stubs.py
@@ -3,30 +3,20 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-"""Creates windows and posix stub files for a given set of signatures.
+"""Creates Windows and POSIX stub files for a given set of signatures.
 
 For libraries that need to be loaded outside of the standard executable startup
 path mechanism, stub files need to be generated for the wanted functions.  In
-windows, this is done via "def" files and the delay load mechanism.  On a posix
+Windows, this is done via "def" files and the delay load mechanism.  On a POSIX
 system, a set of stub functions need to be generated that dispatch to functions
 found via dlsym.
 
 This script takes a set of files, where each file is a list of C-style
-signatures (one signature per line).  The output is either a windows def file,
-or a header + implementation file of stubs suitable for use in a posix system.
+signatures (one signature per line).  The output is either a Windows def file,
+or a header + implementation file of stubs suitable for use in a POSIX system.
 
-This script also handles varidiac functions, e.g.
+This script also handles variadic functions, e.g.
 void printf(const char* s, ...);
-
-TODO(hclam): Fix the situation for varidiac functions.
-Stub for the above function will be generated and inside the stub function it
-is translated to:
-void printf(const char* s, ...) {
-  printf_ptr(s, (void*)arg1);
-}
-
-Only one argument from the varidiac arguments is used and it will be used as
-type void*.
 """
 
 __author__ = 'ajwong@chromium.org (Albert J. Wong)'
@@ -63,9 +53,9 @@
 #
 #   1) Starts with [_a-ZA-Z] (C++ spec 2.10).
 #   2) Continues with [_a-ZA-Z0-9] (C++ spec 2.10).
-#   3) Preceeds an opening parenthesis by 0 or more whitespace chars.
+#   3) Precedes an opening parenthesis by 0 or more whitespace chars.
 #
-# From that, all preceeding characters are considered the return value.
+# From that, all preceding characters are considered the return value.
 # Trailing characters should have a substring matching the form (.*).  That
 # is considered the arguments.
 SIGNATURE_REGEX = re.compile('(?P<return_type>.+?)'
@@ -75,7 +65,7 @@
 # Used for generating C++ identifiers.
 INVALID_C_IDENT_CHARS = re.compile('[^_a-zA-Z0-9]')
 
-# Constants defning the supported file types options.
+# Constants defining the supported file types options.
 FILE_TYPE_WIN_X86 = 'windows_lib'
 FILE_TYPE_WIN_X64 = 'windows_lib_x64'
 FILE_TYPE_POSIX_STUB = 'posix_stubs'
@@ -111,11 +101,9 @@
 VARIADIC_STUB_FUNCTION_DEFINITION = (
     """extern %(return_type)s %(name)s(%(params)s) __attribute__((weak));
 %(return_type)s %(export)s %(name)s(%(params)s) {
-  va_list args___;
-  va_start(args___, %(last_named_arg)s);
-  %(return_type)s ret___ = %(name)s_ptr(%(arg_list)s, va_arg(args___, void*));
-  va_end(args___);
-  return ret___;
+#define %(name)s_ptr_variadic(%(arg_list)s, ...) \
+%(name)s_ptr(%(arg_list)s, ##__VA_ARGS__)
+  return %(name)s_ptr_variadic(%(arg_list)s);
 }""")
 
 # Template for generating a variadic stub function definition without
@@ -132,10 +120,9 @@
 VOID_VARIADIC_STUB_FUNCTION_DEFINITION = (
     """extern void %(name)s(%(params)s) __attribute__((weak));
 void %(export)s %(name)s(%(params)s) {
-  va_list args___;
-  va_start(args___, %(last_named_arg)s);
-  %(name)s_ptr(%(arg_list)s, va_arg(args___, void*));
-  va_end(args___);
+#define %(name)s_ptr_variadic(%(arg_list)s, ...) \
+%(name)s_ptr(%(arg_list)s, ##__VA_ARGS__)
+  %(name)s_ptr_variadic(%(arg_list)s);
 }""")
 
 # Template for the preamble for the stub header file with the header guards,
@@ -143,6 +130,7 @@
 # following named parameters:
 #   guard_name: The macro to use as the header guard.
 #   namespace: The namespace for the stub functions.
+#   logging_include: Header file where the logging function is defined.
 STUB_HEADER_PREAMBLE = """// This is generated file. Do not modify directly.
 
 #ifndef %(guard_name)s
@@ -153,7 +141,7 @@
 #include <string>
 #include <vector>
 
-#include "base/logging.h"
+#include "%(logging_include)s"
 
 namespace %(namespace)s {
 """
@@ -168,7 +156,7 @@
 """
 
 # The standard includes needed for the stub implementation file.  Takes one
-# string substition with the path to the associated stub header file.
+# string substitution with the path to the associated stub header file.
 IMPLEMENTATION_PREAMBLE = """// This is generated file. Do not modify directly.
 
 #include "%s"
@@ -217,7 +205,7 @@
 """)
 
 # Template for the module initialization check function.  This template
-# takes two parameteres: the function name, and the conditional used to
+# takes two parameters: the function name, and the conditional used to
 # verify the module's initialization.
 MODULE_INITIALIZATION_CHECK_FUNCTION = (
     """// Returns true if all stubs have been properly initialized.
@@ -236,11 +224,14 @@
 #   name: The name of the function.
 #   return_type: The return type.
 #   params: The parameters to the function.
+#   logging_function: Function call for error logging.
 STUB_POINTER_INITIALIZER = """  %(name)s_ptr =
     reinterpret_cast<%(return_type)s (*)(%(parameters)s)>(
       dlsym(module, "%(name)s"));
-    VLOG_IF(1, !%(name)s_ptr) << "Couldn't load %(name)s, dlerror() says:\\n"
-        << dlerror();
+  if (!%(name)s_ptr) {
+    %(logging_function)s << "Couldn't load %(name)s, dlerror() says:\\n"
+      << dlerror();
+  }
 """
 
 # Template for module initializer function start and end.  This template takes
@@ -283,6 +274,7 @@
 """)
 
 # Function to initialize each DSO for the given paths.
+#   logging_function: Function call that will be used for error logging.
 UMBRELLA_INITIALIZER_INITIALIZE_FUNCTION_START = (
     """bool InitializeStubs(const StubPathMap& path_map) {
   StubHandleMap opened_libraries;
@@ -306,7 +298,7 @@
         module_opened = true;
         opened_libraries[cur_module] = handle;
       } else {
-        VLOG(1) << "dlopen(" << dso_path->c_str() << ") failed, "
+        %(logging_function)s << "dlopen(" << dso_path->c_str() << ") failed, "
                 << "dlerror() says:\\n" << dlerror();
       }
     }
@@ -360,7 +352,7 @@
   """Infers the module name from the input file path.
 
   The input filename is supposed to be in the form "ModuleName.sigs".
-  This function splits the filename from the extention on that basename of
+  This function splits the filename from the extension on that basename of
   the path and returns that as the module name.
 
   Args:
@@ -427,11 +419,11 @@
 
 
 def WriteWindowsDefFile(module_name, signatures, outfile):
-  """Writes a windows def file to the given output file object.
+  """Writes a Windows def file to the given output file object.
 
     The def file format is basically a list of function names.  Generation is
     simple.  After outputting the LIBRARY and EXPORTS lines, print out each
-    function name, one to a line, preceeded by 2 spaces.
+    function name, one to a line, preceded by 2 spaces.
 
   Args:
     module_name: The name of the module we are writing a stub for.
@@ -459,7 +451,7 @@
 
 def CreateWindowsLib(module_name, signatures, intermediate_dir, outdir_path,
                      machine):
-  """Creates a windows library file.
+  """Creates a Windows library file.
 
   Calling this function will create a lib file in the outdir_path that exports
   the signatures passed into the object.  A temporary def file will be created
@@ -474,7 +466,7 @@
     machine: String holding the machine type, 'X86' or 'X64'.
 
   Raises:
-    SubprocessError: If invoking the windows "lib" tool fails, this is raised
+    SubprocessError: If invoking the Windows "lib" tool fails, this is raised
                      with the error code.
   """
   def_file_path = os.path.join(intermediate_dir,
@@ -489,7 +481,7 @@
 
   # Invoke the "lib" program on Windows to create stub .lib files for the
   # generated definitions.  These .lib files can then be used during
-  # delayloading of the dynamic libraries.
+  # delay loading of the dynamic libraries.
   ret = QuietRun(['lib', '/nologo',
                   '/machine:' + machine,
                   '/def:' + def_file_path,
@@ -509,11 +501,11 @@
   delays loading of the dynamic library/resolution of the symbols until one of
   the needed functions are accessed.
 
-  In posix, RTLD_LAZY does something similar with DSOs.  This is the default
+  In POSIX, RTLD_LAZY does something similar with DSOs.  This is the default
   link mode for DSOs.  However, even though the symbol is not resolved until
   first usage, the DSO must be present at load time of the main binary.
 
-  To simulate the windows delay load procedure, we need to create a set of
+  To simulate the Windows delay load procedure, we need to create a set of
   stub functions that allow for correct linkage of the main binary, but
   dispatch to the dynamically resolved symbol when the module is initialized.
 
@@ -521,7 +513,8 @@
   functions plus initialization code for them.
   """
 
-  def __init__(self, module_name, export_macro, signatures):
+  def __init__(self, module_name, export_macro, signatures, logging_function,
+               logging_include):
     """Initializes PosixStubWriter for this set of signatures and module_name.
 
     Args:
@@ -530,10 +523,14 @@
                     an EXPORT marking, to control visibility.
       signatures: The list of signature hashes, as produced by ParseSignatures,
                   to create stubs for.
+      logging_function: Function call that will be used for error logging.
+      logging_include: Header file where the logging function is defined.
     """
     self.signatures = signatures
     self.module_name = module_name
     self.export_macro = export_macro
+    self.logging_function = logging_function
+    self.logging_include = logging_include
 
   @classmethod
   def CStyleIdentifier(cls, identifier):
@@ -618,7 +615,7 @@
 
     Args:
       signature: A signature hash, as produced by ParseSignatures,
-                 representating the function signature.
+                 representing the function signature.
 
     Returns:
       A string with the declaration of the function pointer for the signature.
@@ -637,7 +634,7 @@
 
     Args:
       signature: A signature hash, as produced by ParseSignatures,
-                 representating the function signature.
+                 representing the function signature.
 
     Returns:
       A string with the stub function definition.
@@ -649,12 +646,18 @@
     # Generate the argument list.
     arguments = [re.split('[\*& ]', arg)[-1].strip() for arg in
                  signature['params']]
+    # Remove square brackets from arrays, otherwise we will end with a
+    # compilation failure.
+    for i in range(0, len(arguments)):
+      if arguments[i].endswith('[]'):
+        arguments[i] = arguments[i][0:-2]
+
     arg_list = ', '.join(arguments)
     if arg_list == 'void':
       arg_list = ''
 
     if arg_list != '' and len(arguments) > 1 and arguments[-1] == '...':
-      # If the last argment is ... then this is a variadic function.
+      # If the last argument is ... then this is a variadic function.
       if return_prefix != '':
         return VARIADIC_STUB_FUNCTION_DEFINITION % {
             'return_type': signature['return_type'],
@@ -691,7 +694,8 @@
     outfile.write(IMPLEMENTATION_PREAMBLE % header_path)
 
   @classmethod
-  def WriteUmbrellaInitializer(cls, module_names, namespace, outfile):
+  def WriteUmbrellaInitializer(cls, module_names, namespace, outfile,
+                               logging_function):
     """Writes a single function that will open + initialize each module.
 
     This intializer will take in an stl map of that lists the correct
@@ -711,9 +715,10 @@
     outfile.write(UMBRELLA_INITIALIZER_START % namespace)
     outfile.write(UMBRELLA_INITIALIZER_CLEANUP_FUNCTION)
 
-    # Create the initializaiton function that calls all module initializers,
+    # Create the initialization function that calls all module initializers,
     # checks if they succeeded, and backs out module loads on an error.
-    outfile.write(UMBRELLA_INITIALIZER_INITIALIZE_FUNCTION_START)
+    outfile.write(UMBRELLA_INITIALIZER_INITIALIZE_FUNCTION_START % {
+        'logging_function': logging_function})
     outfile.write(
         '\n  // Initialize each module if we have not already failed.\n')
     for module in module_names:
@@ -733,7 +738,8 @@
     outfile.write('\n}  // namespace %s\n' % namespace)
 
   @classmethod
-  def WriteHeaderContents(cls, module_names, namespace, header_guard, outfile):
+  def WriteHeaderContents(cls, module_names, namespace, header_guard, outfile,
+                          logging_include):
     """Writes a header file for the stub file generated for module_names.
 
     The header file exposes the following:
@@ -748,11 +754,13 @@
       namespace: The namespace these functions should be in.
       header_guard: The macro to use as our header guard.
       outfile: The output handle to populate.
+      logging_include: Header file where the logging function is defined.
     """
     outfile.write(STUB_HEADER_PREAMBLE %
-                  {'guard_name': header_guard, 'namespace': namespace})
+                  {'guard_name': header_guard, 'namespace': namespace,
+                   'logging_include': logging_include})
 
-    # Generate the Initializer protoypes for each module.
+    # Generate the Initializer prototypes for each module.
     outfile.write('// Individual module initializer functions.\n')
     for name in module_names:
       outfile.write(MODULE_FUNCTION_PROTOTYPES % {
@@ -847,7 +855,7 @@
     ptr_names = ['%s_ptr' % sig['name'] for sig in self.signatures]
 
     # Construct the conditional expression to check the initialization of
-    # all the function pointers above.  It should generate a conjuntion
+    # all the function pointers above.  It should generate a conjunction
     # with each pointer on its own line, indented by six spaces to match
     # the indentation level of MODULE_INITIALIZATION_CHECK_FUNCTION.
     initialization_conditional = ' &&\n      '.join(ptr_names)
@@ -863,7 +871,8 @@
       outfile.write(STUB_POINTER_INITIALIZER % {
           'name': sig['name'],
           'return_type': sig['return_type'],
-          'parameters': ', '.join(sig['params'])})
+          'parameters': ', '.join(sig['params']),
+          'logging_function': self.logging_function})
     outfile.write(MODULE_INITIALIZE_END)
 
     # Create function that uninitializes the module (sets all pointers to
@@ -924,7 +933,7 @@
                     dest='extra_stub_header',
                     default=None,
                     help=('File to insert after the system includes in the '
-                          'generated stub implemenation file. Ignored for '
+                          'generated stub implementation file. Ignored for '
                           '%s and %s types.' %
                           (FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64)))
   parser.add_option('-m',
@@ -939,7 +948,17 @@
                     default='',
                     help=('A macro to place between the return type and '
                           'function name, e.g. MODULE_EXPORT, to control the '
-                          'visbility of the stub functions.'))
+                          'visibility of the stub functions.'))
+  parser.add_option('-l',
+                    '--logging-function',
+                    dest='logging_function',
+                    default='VLOG(1)',
+                    help=('Function call that will be used for error logging.'))
+  parser.add_option('-n',
+                    '--logging-include',
+                    dest='logging_include',
+                    default='base/logging.h',
+                    help=('Header file where the logging function is defined.'))
 
   return parser
 
@@ -1016,12 +1035,12 @@
 
 def CreateWindowsLibForSigFiles(sig_files, out_dir, intermediate_dir, machine,
                                 export_macro):
-  """For each signature file, create a windows lib.
+  """For each signature file, create a Windows lib.
 
   Args:
     sig_files: Array of strings with the paths to each signature file.
     out_dir: String holding path to directory where the generated libs go.
-    intermediate_dir: String holding path to directory generated intermdiate
+    intermediate_dir: String holding path to directory generated intermediate
                       artifacts.
     machine: String holding the machine type, 'X86' or 'X64'.
     export_macro: A preprocessor macro used to annotate stub symbols with
@@ -1041,7 +1060,7 @@
 
 
 def CreateWindowsDefForSigFiles(sig_files, out_dir, module_name):
-  """For all signature files, create a single windows def file.
+  """For all signature files, create a single Windows def file.
 
   Args:
     sig_files: Array of strings with the paths to each signature file.
@@ -1068,8 +1087,9 @@
 
 def CreatePosixStubsForSigFiles(sig_files, stub_name, out_dir,
                                 intermediate_dir, path_from_source,
-                                extra_stub_header, export_macro):
-  """Create a posix stub library with a module for each signature file.
+                                extra_stub_header, export_macro,
+                                logging_function, logging_include):
+  """Create a POSIX stub library with a module for each signature file.
 
   Args:
     sig_files: Array of strings with the paths to each signature file.
@@ -1082,6 +1102,8 @@
                        into the generated header for the stub library.
     export_macro: A preprocessor macro used to annotate stub symbols with
                   an EXPORT marking, to control visibility.
+    logging_function: Function call that will be used for error logging.
+    logging_include: Header file where the logging function is defined.
   """
   header_base_name = stub_name + '.h'
   header_path = os.path.join(out_dir, header_base_name)
@@ -1118,12 +1140,13 @@
         signatures = ParseSignatures(infile)
       finally:
         infile.close()
-      writer = PosixStubWriter(name, export_macro, signatures)
+      writer = PosixStubWriter(name, export_macro, signatures, logging_function,
+                               logging_include)
       writer.WriteImplementationContents(namespace, impl_file)
 
     # Lastly, output the umbrella function for the file.
     PosixStubWriter.WriteUmbrellaInitializer(module_names, namespace,
-                                             impl_file)
+                                             impl_file, logging_function)
   finally:
     impl_file.close()
 
@@ -1131,7 +1154,8 @@
   header_file = open(header_path, 'w')
   try:
     PosixStubWriter.WriteHeaderContents(module_names, namespace,
-                                        header_guard, header_file)
+                                        header_guard, header_file,
+                                        logging_include)
   finally:
     header_file.close()
 
@@ -1149,7 +1173,9 @@
   elif options.type == FILE_TYPE_POSIX_STUB:
     CreatePosixStubsForSigFiles(args, options.stubfile_name, out_dir,
                                 intermediate_dir, options.path_from_source,
-                                options.extra_stub_header, options.export_macro)
+                                options.extra_stub_header, options.export_macro,
+                                options.logging_function,
+                                options.logging_include)
   elif options.type == FILE_TYPE_WIN_DEF:
     CreateWindowsDefForSigFiles(args, out_dir, options.module_name)
 
diff --git a/tools/generate_stubs/generate_stubs_unittest.py b/tools/generate_stubs/generate_stubs_unittest.py
index 85a74c0..29a9af7 100755
--- a/tools/generate_stubs/generate_stubs_unittest.py
+++ b/tools/generate_stubs/generate_stubs_unittest.py
@@ -6,7 +6,7 @@
 """Unittest for the generate_stubs.py.
 
 Since generate_stubs.py is a code generator, it is hard to do a very good
-test.  Instead of creating a golden-file test, which might be flakey, this
+test.  Instead of creating a golden-file test, which might be flaky, this
 test elects instead to verify that various components "exist" within the
 generated file as a sanity check.  In particular, there is a simple hit
 test to make sure that umbrella functions, etc., do try and include every
@@ -40,6 +40,10 @@
     ('void quux(void)', _MakeSignature('void', 'quux', ['void'])),
     ('void waldo(void);', _MakeSignature('void', 'waldo', ['void'])),
     ('int corge(void);', _MakeSignature('int', 'corge', ['void'])),
+    ('int ferda(char **argv[]);',
+     _MakeSignature('int', 'ferda', ['char **argv[]'])),
+    ('void brouk(char *pytlik, ...);',
+     _MakeSignature('void', 'brouk', ['char *pytlik', '...'])),
     ]
 
 TRICKY_SIGNATURES = [
@@ -165,7 +169,8 @@
     self.module_name = 'my_module-1'
     self.signatures = [sig[1] for sig in SIMPLE_SIGNATURES]
     self.out_dir = 'out_dir'
-    self.writer = gs.PosixStubWriter(self.module_name, '', self.signatures)
+    self.writer = gs.PosixStubWriter(self.module_name, '', self.signatures,
+                                     'VLOG(1)', 'base/logging.h')
 
   def testEnumName(self):
     self.assertEqual('kModuleMy_module1',
@@ -211,6 +216,21 @@
   return foo_ptr(b);
 }""", gs.PosixStubWriter.StubFunction(sig))
 
+    # Test for a signature where an array is passed. It should be passed without
+    # square brackets otherwise the compilation failure will occur..
+    self.assertEqual("""extern int ferda(char **argv[]) __attribute__((weak));
+int  ferda(char **argv[]) {
+  return ferda_ptr(argv);
+}""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[6][1]))
+
+    # Test variadic argument
+    self.assertEqual("""extern void brouk(char *pytlik, ...) \
+__attribute__((weak));
+void  brouk(char *pytlik, ...) {
+#define brouk_ptr_variadic(pytlik, ...) brouk_ptr(pytlik, ##__VA_ARGS__)
+  brouk_ptr_variadic(pytlik);
+}""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[7][1]))
+
   def testWriteImplemenationContents(self):
     outfile = StringIO.StringIO()
     self.writer.WriteImplementationContents('my_namespace', outfile)
@@ -250,7 +270,7 @@
     # Make the header.
     outfile = StringIO.StringIO()
     self.writer.WriteHeaderContents(module_names, 'my_namespace', 'GUARD_',
-                                    outfile)
+                                    outfile, 'base/logging.h')
     contents = outfile.getvalue()
 
     # Check for namespace and header guard.
@@ -284,7 +304,8 @@
 
     # Make the header.
     outfile = StringIO.StringIO()
-    self.writer.WriteUmbrellaInitializer(module_names, 'my_namespace', outfile)
+    self.writer.WriteUmbrellaInitializer(module_names, 'my_namespace', outfile,
+                                         'VLOG(1)')
     contents = outfile.getvalue()
 
     # Check for umbrella initializer declaration.
diff --git a/tools/grit/grit.py b/tools/grit/grit.py
index 2813b93..d8074e4 100755
--- a/tools/grit/grit.py
+++ b/tools/grit/grit.py
@@ -12,4 +12,4 @@
 
 
 if __name__ == '__main__':
-  grit.grit_runner.Main(sys.argv[1:])
+  sys.exit(grit.grit_runner.Main(sys.argv[1:]))
diff --git a/tools/grit/grit/__init__.py b/tools/grit/grit/__init__.py
old mode 100755
new mode 100644
index a1eeaca..766fd349
--- a/tools/grit/grit/__init__.py
+++ b/tools/grit/grit/__init__.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/clique.py b/tools/grit/grit/clique.py
old mode 100755
new mode 100644
index 7607e5d..f5549d8
--- a/tools/grit/grit/clique.py
+++ b/tools/grit/grit/clique.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/constants.py b/tools/grit/grit/constants.py
old mode 100755
new mode 100644
index 77faf2a..02f2928
--- a/tools/grit/grit/constants.py
+++ b/tools/grit/grit/constants.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/exception.py b/tools/grit/grit/exception.py
old mode 100755
new mode 100644
index d30d782..23aff82
--- a/tools/grit/grit/exception.py
+++ b/tools/grit/grit/exception.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/extern/BogoFP.py b/tools/grit/grit/extern/BogoFP.py
old mode 100755
new mode 100644
index 3d9cad3..5af21fd
--- a/tools/grit/grit/extern/BogoFP.py
+++ b/tools/grit/grit/extern/BogoFP.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/extern/FP.py b/tools/grit/grit/extern/FP.py
old mode 100755
new mode 100644
index 3bde18dc..69892ca
--- a/tools/grit/grit/extern/FP.py
+++ b/tools/grit/grit/extern/FP.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/extern/tclib.py b/tools/grit/grit/extern/tclib.py
old mode 100755
new mode 100644
index a9b1a39f..d7294731
--- a/tools/grit/grit/extern/tclib.py
+++ b/tools/grit/grit/extern/tclib.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/format/__init__.py b/tools/grit/grit/format/__init__.py
old mode 100755
new mode 100644
index 28a4dc7..55d56b8
--- a/tools/grit/grit/format/__init__.py
+++ b/tools/grit/grit/format/__init__.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/format/android_xml.py b/tools/grit/grit/format/android_xml.py
old mode 100755
new mode 100644
index 42ba6bc..2d878673
--- a/tools/grit/grit/format/android_xml.py
+++ b/tools/grit/grit/format/android_xml.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/format/c_format.py b/tools/grit/grit/format/c_format.py
old mode 100755
new mode 100644
index 5e10b98..6d5d9e6
--- a/tools/grit/grit/format/c_format.py
+++ b/tools/grit/grit/format/c_format.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/format/js_map_format.py b/tools/grit/grit/format/js_map_format.py
old mode 100755
new mode 100644
index 8cc8eb2..c789fb42e
--- a/tools/grit/grit/format/js_map_format.py
+++ b/tools/grit/grit/format/js_map_format.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/format/policy_templates_json.py b/tools/grit/grit/format/policy_templates_json.py
old mode 100755
new mode 100644
index 13f680e..f4531f5
--- a/tools/grit/grit/format/policy_templates_json.py
+++ b/tools/grit/grit/format/policy_templates_json.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # 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.
diff --git a/tools/grit/grit/format/rc.py b/tools/grit/grit/format/rc.py
old mode 100755
new mode 100644
index 47ad5a03..e7d716d3
--- a/tools/grit/grit/format/rc.py
+++ b/tools/grit/grit/format/rc.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/format/rc_header.py b/tools/grit/grit/format/rc_header.py
old mode 100755
new mode 100644
index 825ef1e..da2f156
--- a/tools/grit/grit/format/rc_header.py
+++ b/tools/grit/grit/format/rc_header.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/format/resource_map.py b/tools/grit/grit/format/resource_map.py
old mode 100755
new mode 100644
index d245ca6..b28141b
--- a/tools/grit/grit/format/resource_map.py
+++ b/tools/grit/grit/format/resource_map.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/__init__.py b/tools/grit/grit/gather/__init__.py
old mode 100755
new mode 100644
index e52734a5..2d578f5
--- a/tools/grit/grit/gather/__init__.py
+++ b/tools/grit/grit/gather/__init__.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/admin_template.py b/tools/grit/grit/gather/admin_template.py
old mode 100755
new mode 100644
index edf783b..1b8340a
--- a/tools/grit/grit/gather/admin_template.py
+++ b/tools/grit/grit/gather/admin_template.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/chrome_html.py b/tools/grit/grit/gather/chrome_html.py
old mode 100755
new mode 100644
index a0bd999..12f570c
--- a/tools/grit/grit/gather/chrome_html.py
+++ b/tools/grit/grit/gather/chrome_html.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/chrome_scaled_image.py b/tools/grit/grit/gather/chrome_scaled_image.py
old mode 100755
new mode 100644
index a0663edf..b7bcf2d
--- a/tools/grit/grit/gather/chrome_scaled_image.py
+++ b/tools/grit/grit/gather/chrome_scaled_image.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/interface.py b/tools/grit/grit/gather/interface.py
old mode 100755
new mode 100644
index c277d37..5d3ef1d
--- a/tools/grit/grit/gather/interface.py
+++ b/tools/grit/grit/gather/interface.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/json_loader.py b/tools/grit/grit/gather/json_loader.py
old mode 100755
new mode 100644
index 6370b10..ca1f435
--- a/tools/grit/grit/gather/json_loader.py
+++ b/tools/grit/grit/gather/json_loader.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/policy_json.py b/tools/grit/grit/gather/policy_json.py
old mode 100755
new mode 100644
index d11de75..d0a7d67
--- a/tools/grit/grit/gather/policy_json.py
+++ b/tools/grit/grit/gather/policy_json.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/rc.py b/tools/grit/grit/gather/rc.py
old mode 100755
new mode 100644
index f1e8982..a332758
--- a/tools/grit/grit/gather/rc.py
+++ b/tools/grit/grit/gather/rc.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/regexp.py b/tools/grit/grit/gather/regexp.py
old mode 100755
new mode 100644
index 16bc323a..de64c17
--- a/tools/grit/grit/gather/regexp.py
+++ b/tools/grit/grit/gather/regexp.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/skeleton_gatherer.py b/tools/grit/grit/gather/skeleton_gatherer.py
old mode 100755
new mode 100644
index 38b504c..564ccce
--- a/tools/grit/grit/gather/skeleton_gatherer.py
+++ b/tools/grit/grit/gather/skeleton_gatherer.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/tr_html.py b/tools/grit/grit/gather/tr_html.py
old mode 100755
new mode 100644
index d5122f6e..f0bd132
--- a/tools/grit/grit/gather/tr_html.py
+++ b/tools/grit/grit/gather/tr_html.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/gather/txt.py b/tools/grit/grit/gather/txt.py
old mode 100755
new mode 100644
index e8c20de..a2a6cfc
--- a/tools/grit/grit/gather/txt.py
+++ b/tools/grit/grit/gather/txt.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/grit_runner.py b/tools/grit/grit/grit_runner.py
index 58160e4..cc094661 100755
--- a/tools/grit/grit/grit_runner.py
+++ b/tools/grit/grit/grit_runner.py
@@ -196,57 +196,65 @@
   """Parses arguments and does the appropriate thing."""
   util.ChangeStdoutEncoding()
 
-  if sys.version_info < (2, 6):
-    print "GRIT requires Python 2.6 or later."
-    return 2
-  elif not args or (len(args) == 1 and args[0] == 'help'):
-    PrintUsage()
-    return 0
-  elif len(args) == 2 and args[0] == 'help':
-    tool = args[1].lower()
-    if not _GetToolInfo(tool):
-      print "No such tool.  Try running 'grit help' for a list of tools."
-      return 2
-
-    print ("Help for 'grit %s' (for general help, run 'grit help'):\n"
-           % (tool))
-    print _GetToolInfo(tool)[_FACTORY]().__doc__
-    return 0
-  else:
-    options = Options()
+  options = Options()
+  try:
     args = options.ReadOptions(args)  # args may be shorter after this
-    if not args:
-      print "No tool provided.  Try running 'grit help' for a list of tools."
-      return 2
-    tool = args[0]
-    if not _GetToolInfo(tool):
-      print "No such tool.  Try running 'grit help' for a list of tools."
-      return 2
+  except getopt.GetoptError as e:
+    print "grit:", str(e)
+    print "Try running 'grit help' for valid options."
+    return 1
+  if not args:
+    print "No tool provided.  Try running 'grit help' for a list of tools."
+    return 2
 
-    try:
-      if _GetToolInfo(tool)[_REQUIRES_INPUT]:
-        os.stat(options.input)
-    except OSError:
-      print ('Input file %s not found.\n'
-             'To specify a different input file:\n'
-             '  1. Use the GRIT_INPUT environment variable.\n'
-             '  2. Use the -i command-line option.  This overrides '
-             'GRIT_INPUT.\n'
-             '  3. Specify neither GRIT_INPUT or -i and GRIT will try to load '
-             "'resource.grd'\n"
-             '     from the current directory.' % options.input)
-      return 2
+  tool = args[0]
+  if tool == 'help':
+    if len(args) == 1:
+      PrintUsage()
+      return 0
+    else:
+      tool = args[1]
+      if not _GetToolInfo(tool):
+        print "No such tool.  Try running 'grit help' for a list of tools."
+        return 2
 
-    if options.hash:
-      grit.extern.FP.UseUnsignedFingerPrintFromModule(options.hash)
+      print ("Help for 'grit %s' (for general help, run 'grit help'):\n"
+             % (tool))
+      print _GetToolInfo(tool)[_FACTORY]().__doc__
+      return 0
+  if not _GetToolInfo(tool):
+    print "No such tool.  Try running 'grit help' for a list of tools."
+    return 2
 
+  try:
+    if _GetToolInfo(tool)[_REQUIRES_INPUT]:
+      os.stat(options.input)
+  except OSError:
+    print ('Input file %s not found.\n'
+           'To specify a different input file:\n'
+           '  1. Use the GRIT_INPUT environment variable.\n'
+           '  2. Use the -i command-line option.  This overrides '
+           'GRIT_INPUT.\n'
+           '  3. Specify neither GRIT_INPUT or -i and GRIT will try to load '
+           "'resource.grd'\n"
+           '     from the current directory.' % options.input)
+    return 2
+
+  if options.hash:
+    grit.extern.FP.UseUnsignedFingerPrintFromModule(options.hash)
+
+  try:
     toolobject = _GetToolInfo(tool)[_FACTORY]()
     if options.profile_dest:
       import hotshot
       prof = hotshot.Profile(options.profile_dest)
-      prof.runcall(toolobject.Run, options, args[1:])
+      return prof.runcall(toolobject.Run, options, args[1:])
     else:
-      toolobject.Run(options, args[1:])
+      return toolobject.Run(options, args[1:])
+  except getopt.GetoptError as e:
+    print "grit: %s: %s" % (tool, str(e))
+    print "Try running 'grit help %s' for valid options." % (tool,)
+    return 1
 
 
 if __name__ == '__main__':
diff --git a/tools/grit/grit/lazy_re.py b/tools/grit/grit/lazy_re.py
old mode 100755
new mode 100644
index a532cd0..ae67d048
--- a/tools/grit/grit/lazy_re.py
+++ b/tools/grit/grit/lazy_re.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/__init__.py b/tools/grit/grit/node/__init__.py
old mode 100755
new mode 100644
index f285e2d..2fc0d33
--- a/tools/grit/grit/node/__init__.py
+++ b/tools/grit/grit/node/__init__.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/base.py b/tools/grit/grit/node/base.py
old mode 100755
new mode 100644
index 76fbb31e..bd6b207
--- a/tools/grit/grit/node/base.py
+++ b/tools/grit/grit/node/base.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/custom/__init__.py b/tools/grit/grit/node/custom/__init__.py
old mode 100755
new mode 100644
index 3e13ca13..e179cf7
--- a/tools/grit/grit/node/custom/__init__.py
+++ b/tools/grit/grit/node/custom/__init__.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/custom/filename.py b/tools/grit/grit/node/custom/filename.py
old mode 100755
new mode 100644
index 79a7744f..416eac5
--- a/tools/grit/grit/node/custom/filename.py
+++ b/tools/grit/grit/node/custom/filename.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/empty.py b/tools/grit/grit/node/empty.py
old mode 100755
new mode 100644
index b3759a2..f2a1a1e
--- a/tools/grit/grit/node/empty.py
+++ b/tools/grit/grit/node/empty.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/include.py b/tools/grit/grit/node/include.py
old mode 100755
new mode 100644
index f7a51ed..2971ae3
--- a/tools/grit/grit/node/include.py
+++ b/tools/grit/grit/node/include.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/io.py b/tools/grit/grit/node/io.py
old mode 100755
new mode 100644
index 83e14b1f..0e17717e
--- a/tools/grit/grit/node/io.py
+++ b/tools/grit/grit/node/io.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/mapping.py b/tools/grit/grit/node/mapping.py
old mode 100755
new mode 100644
index 71b250b2..659f0e0
--- a/tools/grit/grit/node/mapping.py
+++ b/tools/grit/grit/node/mapping.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/message.py b/tools/grit/grit/node/message.py
old mode 100755
new mode 100644
index 1b887c2..da34af2
--- a/tools/grit/grit/node/message.py
+++ b/tools/grit/grit/node/message.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/misc.py b/tools/grit/grit/node/misc.py
old mode 100755
new mode 100644
index 91c9913f..2d561aa
--- a/tools/grit/grit/node/misc.py
+++ b/tools/grit/grit/node/misc.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/structure.py b/tools/grit/grit/node/structure.py
old mode 100755
new mode 100644
index 3d2012a..48304b72
--- a/tools/grit/grit/node/structure.py
+++ b/tools/grit/grit/node/structure.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/node/variant.py b/tools/grit/grit/node/variant.py
old mode 100755
new mode 100644
index 487f7f9..7d3a526
--- a/tools/grit/grit/node/variant.py
+++ b/tools/grit/grit/node/variant.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/pseudo.py b/tools/grit/grit/pseudo.py
old mode 100755
new mode 100644
index cb57daab..23b784d
--- a/tools/grit/grit/pseudo.py
+++ b/tools/grit/grit/pseudo.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/pseudo_rtl.py b/tools/grit/grit/pseudo_rtl.py
old mode 100755
new mode 100644
index dee4483..f307ea049
--- a/tools/grit/grit/pseudo_rtl.py
+++ b/tools/grit/grit/pseudo_rtl.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/scons.py b/tools/grit/grit/scons.py
old mode 100755
new mode 100644
index 8545767..71d45fc
--- a/tools/grit/grit/scons.py
+++ b/tools/grit/grit/scons.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/shortcuts.py b/tools/grit/grit/shortcuts.py
old mode 100755
new mode 100644
index 30bdbf7..bae61cc
--- a/tools/grit/grit/shortcuts.py
+++ b/tools/grit/grit/shortcuts.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tclib.py b/tools/grit/grit/tclib.py
old mode 100755
new mode 100644
index 509c3aa..4101824
--- a/tools/grit/grit/tclib.py
+++ b/tools/grit/grit/tclib.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/__init__.py b/tools/grit/grit/tool/__init__.py
old mode 100755
new mode 100644
index 4f769f2a..cc455b3
--- a/tools/grit/grit/tool/__init__.py
+++ b/tools/grit/grit/tool/__init__.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/android2grd.py b/tools/grit/grit/tool/android2grd.py
old mode 100755
new mode 100644
index e9e0ed1..1c7f5d7
--- a/tools/grit/grit/tool/android2grd.py
+++ b/tools/grit/grit/tool/android2grd.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py
old mode 100755
new mode 100644
index d23d72b..cbb9b3b
--- a/tools/grit/grit/tool/build.py
+++ b/tools/grit/grit/tool/build.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/buildinfo.py b/tools/grit/grit/tool/buildinfo.py
old mode 100755
new mode 100644
index f21d54c22..84075a7
--- a/tools/grit/grit/tool/buildinfo.py
+++ b/tools/grit/grit/tool/buildinfo.py
@@ -1,4 +1,3 @@
-#!/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.
@@ -14,7 +13,13 @@
 from grit.tool import interface
 
 class DetermineBuildInfo(interface.Tool):
-  """Determine what files will be read and output by GRIT."""
+  """Determine what files will be read and output by GRIT.
+Outputs the list of generated files and inputs used to stdout.
+
+Usage: grit buildinfo [-o DIR]
+
+The output directory is used for display only.
+"""
 
   def __init__(self):
     pass
@@ -25,8 +30,7 @@
             'output by GRIT with a given input.')
 
   def Run(self, opts, args):
-    """Main method for the buildinfo tool.  Outputs the list
-       of generated files and inputs used to stdout."""
+    """Main method for the buildinfo tool."""
     self.output_directory = '.'
     (own_opts, args) = getopt.getopt(args, 'o:')
     for (key, val) in own_opts:
diff --git a/tools/grit/grit/tool/count.py b/tools/grit/grit/tool/count.py
old mode 100755
new mode 100644
index 1517b16..7921523
--- a/tools/grit/grit/tool/count.py
+++ b/tools/grit/grit/tool/count.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/diff_structures.py b/tools/grit/grit/tool/diff_structures.py
old mode 100755
new mode 100644
index e2b10b9..719abd27
--- a/tools/grit/grit/tool/diff_structures.py
+++ b/tools/grit/grit/tool/diff_structures.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/interface.py b/tools/grit/grit/tool/interface.py
old mode 100755
new mode 100644
index bec4e1cc..74e8aaa
--- a/tools/grit/grit/tool/interface.py
+++ b/tools/grit/grit/tool/interface.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/menu_from_parts.py b/tools/grit/grit/tool/menu_from_parts.py
old mode 100755
new mode 100644
index c7be7bd9..c8c3619c
--- a/tools/grit/grit/tool/menu_from_parts.py
+++ b/tools/grit/grit/tool/menu_from_parts.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/newgrd.py b/tools/grit/grit/tool/newgrd.py
old mode 100755
new mode 100644
index 1dc7a7d..38a0f752
--- a/tools/grit/grit/tool/newgrd.py
+++ b/tools/grit/grit/tool/newgrd.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/postprocess_interface.py b/tools/grit/grit/tool/postprocess_interface.py
old mode 100755
new mode 100644
index c870b932..08566eb
--- a/tools/grit/grit/tool/postprocess_interface.py
+++ b/tools/grit/grit/tool/postprocess_interface.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/preprocess_interface.py b/tools/grit/grit/tool/preprocess_interface.py
old mode 100755
new mode 100644
index eea10b2..97404e9f
--- a/tools/grit/grit/tool/preprocess_interface.py
+++ b/tools/grit/grit/tool/preprocess_interface.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/rc2grd.py b/tools/grit/grit/tool/rc2grd.py
old mode 100755
new mode 100644
index a0ef77fc..c50a11e2
--- a/tools/grit/grit/tool/rc2grd.py
+++ b/tools/grit/grit/tool/rc2grd.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/resize.py b/tools/grit/grit/tool/resize.py
old mode 100755
new mode 100644
index 3daffa43..e5df449
--- a/tools/grit/grit/tool/resize.py
+++ b/tools/grit/grit/tool/resize.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/test.py b/tools/grit/grit/tool/test.py
old mode 100755
new mode 100644
index 8f4cdd9..1fcf23c
--- a/tools/grit/grit/tool/test.py
+++ b/tools/grit/grit/tool/test.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/transl2tc.py b/tools/grit/grit/tool/transl2tc.py
old mode 100755
new mode 100644
index a8af6ed1..10a893f
--- a/tools/grit/grit/tool/transl2tc.py
+++ b/tools/grit/grit/tool/transl2tc.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/unit.py b/tools/grit/grit/tool/unit.py
old mode 100755
new mode 100644
index 00ffcb1..b3da7c1b7
--- a/tools/grit/grit/tool/unit.py
+++ b/tools/grit/grit/tool/unit.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/tool/xmb.py b/tools/grit/grit/tool/xmb.py
old mode 100755
new mode 100644
index eb10e71..3f6eb10
--- a/tools/grit/grit/tool/xmb.py
+++ b/tools/grit/grit/tool/xmb.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/util.py b/tools/grit/grit/util.py
old mode 100755
new mode 100644
index aac2dd91..c3e004b
--- a/tools/grit/grit/util.py
+++ b/tools/grit/grit/util.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit/xtb_reader.py b/tools/grit/grit/xtb_reader.py
old mode 100755
new mode 100644
index df6d9f8..8d5f58f
--- a/tools/grit/grit/xtb_reader.py
+++ b/tools/grit/grit/xtb_reader.py
@@ -1,4 +1,3 @@
-#!/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.
diff --git a/tools/grit/grit_info.py b/tools/grit/grit_info.py
index 3b85dab..7c57aff 100755
--- a/tools/grit/grit_info.py
+++ b/tools/grit/grit_info.py
@@ -171,10 +171,6 @@
 
 
 def main(argv):
-  if sys.version_info < (2, 6):
-    print "GRIT requires Python 2.6 or later."
-    return 1
-
   try:
     result = DoMain(argv[1:])
   except WrongNumberOfArguments, e:
diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni
index c50895a..63c84c0 100644
--- a/tools/grit/grit_rule.gni
+++ b/tools/grit/grit_rule.gni
@@ -329,6 +329,7 @@
 
     inputs = [
       invoker.source,
+      asserted_list_file,
     ]
     if (resource_ids != "") {
       # The script depends on the ID file. Only add this dependency if the ID
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index 54561dc6..5280058f 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -131,20 +131,21 @@
     "includes": [13320],
   },
   "chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd": {
-    "structures": [13330],
+    "includes": [13330],
+    "structures": [13380],
   },
   "chrome/browser/vr/testapp/vr_testapp_resources.grd": {
-    "includes": [13370],
+    "includes": [13420],
   },
   # END chrome/browser section.
 
   # START chrome/ miscellaneous section.
   "chrome/common/common_resources.grd": {
-    "includes": [13380],
+    "includes": [13430],
   },
   "chrome/credential_provider/gaiacp/gaia_resources.grd": {
-    "includes": [13400],
-    "messages": [13410],
+    "includes": [13450],
+    "messages": [13460],
   },
   "chrome/renderer/resources/renderer_resources.grd": {
     "includes": [13500],
@@ -165,10 +166,6 @@
   # END chromeos/ section.
 
   # START components/ section.
-  "components/autofill/android/autofill_strings.grd": {
-    "messages": [15000],
-  },
-
   "components/chrome_apps/chrome_apps_resources.grd": {
     "includes": [15020],
   },
@@ -421,9 +418,6 @@
   "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd": {
     "includes": [28850],
   },
-  "devtools_resources.grd": {
-    "includes": [28850],
-  },
 
   # END "everything else" section.
   # Everything but chrome/, components/, content/, and ios/
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index c8f4278..169ebb007 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -1047,6 +1047,17 @@
     # the last instance of each arg is listed.
     gn_args = gn_helpers.ToGNString(gn_helpers.FromGNArgs(gn_args))
 
+    # If we're using the Simple Chrome SDK, add a comment at the top that
+    # points to the doc. This must happen after the gn_helpers.ToGNString()
+    # call above since gn_helpers strips comments.
+    if vals['cros_passthrough']:
+      simplechrome_comment = [
+          '# These args are generated via the Simple Chrome SDK. See the link',
+          '# below for more details:',
+          '# https://chromium.googlesource.com/chromiumos/docs/+/master/simple_chrome_workflow.md',  # pylint: disable=line-too-long
+      ]
+      gn_args = '%s\n%s' % ('\n'.join(simplechrome_comment), gn_args)
+
     args_file = vals.get('args_file', None)
     if args_file:
       gn_args = ('import("%s")\n' % vals['args_file']) + gn_args
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 12878da..1fb7e05 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -612,6 +612,7 @@
       'linux-blink-gen-property-trees': 'release_trybot',
       'linux-blink-heap-incremental-marking': 'debug_trybot_enable_blink_heap_incremental_marking',
       'linux-blink-heap-verification-try': 'release_trybot_enable_blink_heap_verification',
+      'linux-coverage-rel': 'clang_code_coverage_trybot',
       'linux-dcheck-off-rel': 'release_trybot_dcheck_off',
       'linux-goma-rbe-staging-rel': 'gpu_tests_release_trybot_no_symbols',
       'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11',
@@ -1090,6 +1091,11 @@
       'release_bot', 'clang', 'use_clang_coverage', 'no_symbols',
     ],
 
+    'clang_code_coverage_trybot': [
+      'gpu_tests', 'use_dummy_lastchange', 'release_trybot', 'clang', 'use_clang_coverage', 'no_symbols',
+      'partial_clang_instrumentation'
+    ],
+
     'clang_release_bot_minimal_symbols_x86': [
       'clang', 'release_bot', 'minimal_symbols', 'x86',
     ],
@@ -2057,6 +2063,15 @@
       'gn_args': 'ozone_platform_headless=true',
     },
 
+    # Used to pass the list of files to instrument for coverage to the compile
+    # wrapper. See:
+    # https://cs.chromium.org/chromium/build/scripts/slave/recipe_modules/clang_coverage/api.py
+    # and
+    # https://cs.chromium.org/chromium/src/docs/clang_code_coverage_wrapper.md
+    'partial_clang_instrumentation': {
+      'gn_args': 'coverage_instrumentation_input_file="//.clang-coverage/files_to_instrument.txt"'
+    },
+
     'pdf_xfa': {
       'gn_args': 'pdf_enable_xfa=true',
     },
diff --git a/tools/mb/mb_unittest.py b/tools/mb/mb_unittest.py
index bf6a771..3367ffe 100755
--- a/tools/mb/mb_unittest.py
+++ b/tools/mb/mb_unittest.py
@@ -6,6 +6,7 @@
 """Tests for mb.py."""
 
 import json
+import os
 import StringIO
 import sys
 import unittest
@@ -110,6 +111,7 @@
     'fake_master': {
       'fake_builder': 'rel_bot',
       'fake_debug_builder': 'debug_goma',
+      'fake_simplechrome_builder': 'cros_chrome_sdk',
       'fake_args_bot': '//build/args/bots/fake_master/fake_args_bot.gn',
       'fake_multi_phase': { 'phase_1': 'phase_1', 'phase_2': 'phase_2'},
       'fake_args_file': 'args_file_goma',
@@ -119,12 +121,16 @@
   'configs': {
     'args_file_goma': ['args_file', 'goma'],
     'args_file_twice': ['args_file', 'args_file'],
+    'cros_chrome_sdk': ['cros_chrome_sdk'],
     'rel_bot': ['rel', 'goma', 'fake_feature1'],
     'debug_goma': ['debug', 'goma'],
     'phase_1': ['phase_1'],
     'phase_2': ['phase_2'],
   },
   'mixins': {
+    'cros_chrome_sdk': {
+      'cros_passthrough': True,
+    },
     'fake_feature1': {
       'gn_args': 'enable_doom_melon=true',
     },
@@ -217,11 +223,17 @@
         mbw.files[path] = contents
     return mbw
 
-  def check(self, args, mbw=None, files=None, out=None, err=None, ret=None):
+  def check(self, args, mbw=None, files=None, out=None, err=None, ret=None,
+            env=None):
     if not mbw:
       mbw = self.fake_mbw(files)
 
-    actual_ret = mbw.Main(args)
+    try:
+      prev_env = os.environ.copy()
+      os.environ = env if env else prev_env
+      actual_ret = mbw.Main(args)
+    finally:
+      os.environ = prev_env
 
     self.assertEqual(actual_ret, ret)
     if out is not None:
@@ -583,6 +595,12 @@
                     '""" to _path_/args.gn.\n\n'
                     '/fake_src/buildtools/linux64/gn gen _path_\n'))
 
+  def test_lookup_simplechrome(self):
+    simplechrome_env = {
+        'GN_ARGS': 'is_chromeos=1 target_os="chromeos"',
+    }
+    self.check(['lookup', '-c', 'cros_chrome_sdk'], ret=0, env=simplechrome_env)
+
   def test_help(self):
     orig_stdout = sys.stdout
     try:
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 45fae30..eafe22a 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -10033,6 +10033,66 @@
   <description>The chrome://management page was viewed.</description>
 </action>
 
+<action name="ManualFallback_Close">
+  <owner>javierrobles@chromium.org</owner>
+  <description>
+    The user closed the Manual Fallback view by tapping the keyboard icon.
+  </description>
+</action>
+
+<action name="ManualFallback_ClosePopover">
+  <owner>javierrobles@chromium.org</owner>
+  <description>
+    The user closed the Manual Fallback Popover view. This happens when the user
+    taps outside the popover.
+  </description>
+</action>
+
+<action name="ManualFallback_OpenCreditCard">
+  <owner>javierrobles@chromium.org</owner>
+  <description>The user opened Credit Card Manual Fallback view.</description>
+</action>
+
+<action name="ManualFallback_OpenPassword">
+  <owner>javierrobles@chromium.org</owner>
+  <description>The user opened the Password Manual Fallback view.</description>
+</action>
+
+<action name="ManualFallback_OpenProfile">
+  <owner>javierrobles@chromium.org</owner>
+  <description>The user opened the Profile Manual Fallback view.</description>
+</action>
+
+<action name="ManualFallback_Password_OpenManagePassword">
+  <owner>javierrobles@chromium.org</owner>
+  <description>
+    The user tapped on &quot;Manage passwords&quot; on the Password Manual
+    Fallback view.
+  </description>
+</action>
+
+<action name="ManualFallback_Password_OpenOtherPassword">
+  <owner>javierrobles@chromium.org</owner>
+  <description>
+    The user tapped on &quot;Use other password&quot; on the Password Manual
+    Fallback view.
+  </description>
+</action>
+
+<action name="ManualFallback_Password_SelectPassword">
+  <owner>javierrobles@chromium.org</owner>
+  <description>
+    The user tapped on a password in the Password Manual Fallback view.
+  </description>
+</action>
+
+<action name="ManualFallback_Password_SelectUsername">
+  <owner>javierrobles@chromium.org</owner>
+  <description>
+    The user tapped on a username in the Password Manual Fallback view.
+  </description>
+</action>
+
 <action name="MaxButton_Clk_ExitFS">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
@@ -10135,6 +10195,20 @@
   <description>The user clicked on the cast overlay button.</description>
 </action>
 
+<action name="Media.Controls.ClickAnywhereToPause">
+  <owner>jazzhsu@chromium.org</owner>
+  <description>
+    The user clicked anywhere in the video frame to pause.
+  </description>
+</action>
+
+<action name="Media.Controls.ClickAnywhereToPlay">
+  <owner>jazzhsu@chromium.org</owner>
+  <description>
+    The user clicked anywhere in the video frame to play.
+  </description>
+</action>
+
 <action name="Media.Controls.ClosedCaptionHide">
   <owner>mlamouri@chromium.org</owner>
   <description>The user hid the closed caption from the controls.</description>
@@ -20581,6 +20655,7 @@
   <suffix name="PreviewsOmniboxUI"
       label="For the Previews UI in the Android Omnibox feature."/>
   <suffix name="ReopenTab" label="For ReopenTab feature."/>
+  <suffix name="TranslateMenuButton" label="For translate menu button."/>
   <affected-action name="InProductHelp.NotifyEvent.IPH"/>
   <affected-action name="InProductHelp.NotifyUsedEvent.IPH"/>
   <affected-action name="InProductHelp.ShouldTriggerHelpUI.IPH"/>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 1a143ffa..d1bcdd5 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -1126,6 +1126,13 @@
   <int value="18" label="All utility process crashes"/>
 </enum>
 
+<enum name="AndroidProcessedMinidumps">
+  <int value="0" label="Other"/>
+  <int value="1" label="Browser"/>
+  <int value="2" label="Renderer"/>
+  <int value="3" label="Gpu"/>
+</enum>
+
 <enum name="AndroidResourceExtractionStatus">
   <int value="0" label="No extraction performed"/>
   <int value="1" label="Extraction success"/>
@@ -3236,6 +3243,11 @@
   <int value="2" label="dual source"/>
 </enum>
 
+<enum name="AutoScreenBrightnessUserAdjustment">
+  <int value="0" label="NoPriorModelAdjustment"/>
+  <int value="1" label="WithPriorModelAdjustment"/>
+</enum>
+
 <enum name="AutoSigninFirstRun">
   <int value="0" label="No action"/>
   <int value="1" label="Turn off"/>
@@ -3383,7 +3395,7 @@
   <int value="4" label="RFH_NO_PROXY_TO_PARENT"/>
   <int value="5" label="RPH_DESERIALIZATION_FAILED"/>
   <int value="6" label="OBSOLETE_RVH_CAN_ACCESS_FILES_OF_PAGE_STATE"/>
-  <int value="7" label="RFH_FILE_CHOOSER_PATH"/>
+  <int value="7" label="OBSOLETE_RFH_FILE_CHOOSER_PATH"/>
   <int value="8" label="OBSOLETE_RWH_SYNTHETIC_GESTURE"/>
   <int value="9" label="OBSOLETE_RWH_FOCUS"/>
   <int value="10" label="OBSOLETE_RWH_BLUR"/>
@@ -4234,6 +4246,11 @@
   <int value="1" label="Allowed"/>
 </enum>
 
+<enum name="BooleanAnchorElementSameHost">
+  <int value="0" label="Anchor element has different host than document host"/>
+  <int value="1" label="Anchor element has same host as document host"/>
+</enum>
+
 <enum name="BooleanAttached">
   <int value="0" label="Detached"/>
   <int value="1" label="Attached"/>
@@ -4839,6 +4856,11 @@
   <int value="1" label="Generated by Chrome"/>
 </enum>
 
+<enum name="BooleanNil">
+  <int value="0" label="NSObject is not nil"/>
+  <int value="1" label="NSObject is nil"/>
+</enum>
+
 <enum name="BooleanNull">
   <int value="0" label="Is not a nullptr"/>
   <int value="1" label="Is a nullptr"/>
@@ -4982,6 +5004,11 @@
   <int value="1" label="Registration is a duplicate"/>
 </enum>
 
+<enum name="BooleanRemoved">
+  <int value="0" label="Not removed"/>
+  <int value="1" label="Removed"/>
+</enum>
+
 <enum name="BooleanRenamed">
   <int value="0" label="Not Renamed"/>
   <int value="1" label="Renamed"/>
@@ -5465,14 +5492,14 @@
 </enum>
 
 <enum name="CanvasCreateImageBitmapSource">
-  <int value="0" label="CreateImageBitmapFromBlob"/>
-  <int value="1" label="CreateImageBitmapFromImageBitmap"/>
-  <int value="2" label="CreateImageBitmapFromImageData"/>
-  <int value="3" label="CreateImageBitmapFromHTMLCanvasElement"/>
-  <int value="4" label="CreateImageBitmapFromHTMLImageElement"/>
-  <int value="5" label="CreateImageBitmapFromHTMLVideoElement"/>
-  <int value="6" label="CreateImageBitmapFromOffscreenCanvas"/>
-  <int value="7" label="CreateImageBitmapFromSVGImageElement"/>
+  <int value="0" label="Blob"/>
+  <int value="1" label="ImageBitmap"/>
+  <int value="2" label="ImageData"/>
+  <int value="3" label="HTML Canvas Element"/>
+  <int value="4" label="HTML Image Element"/>
+  <int value="5" label="HTML Video Element"/>
+  <int value="6" label="OffscreenCanvas"/>
+  <int value="7" label="SVG Image Element"/>
 </enum>
 
 <enum name="CanvasDisplayListFallbackReason">
@@ -5519,31 +5546,30 @@
 </enum>
 
 <enum name="CanvasGPUAccelerated2DCanvasDisableDeferralReason">
-  <int value="0" label="Unknown (Should not be seen in production)."/>
-  <int value="1" label="Canvas not cleared between consecutive frames."/>
-  <int value="2"
-      label="Canvas state stack too large (unbalanced save/restore?)."/>
-  <int value="3" label="Direct pixel write."/>
-  <int value="4" label="Draw image of animated 2d canvas"/>
-  <int value="5" label="Sub-pixel text anti-aliasing support (expect 0)"/>
+  <int value="0" label="Unknown (Should not be seen in production)"/>
+  <int value="1" label="Expensive overdraw heuristic"/>
+  <int value="2" label="Using texture backed pattern"/>
+  <int value="3" label="Draw image of video"/>
+  <int value="4" label="Draw image of animated 2D canvas"/>
+  <int value="5" label="Sub-pixel text anti-aliasing support"/>
   <int value="6" label="drawImage called with a texture backed source image"/>
   <int value="7" label="Running on low-end device"/>
 </enum>
 
 <enum name="CanvasHibernationEvent">
-  <int value="0" label="HibernationScheduled"/>
+  <int value="0" label="Scheduled"/>
   <int value="1"
-      label="HibernationAbortedDueToDestructionWhileHibernatePending"/>
-  <int value="2" label="HibernationAbortedDueToPendingDestruction (obsolete)"/>
-  <int value="3" label="HibernationAbortedDueToVisibilityChange"/>
-  <int value="4" label="HibernationAbortedDueGpuContextLoss"/>
-  <int value="5" label="HibernationAbortedDueToSwitchToUnacceleratedRendering"/>
-  <int value="6" label="HibernationAbortedDueToAllocationFailure"/>
-  <int value="7" label="HibernationEndedNormally"/>
-  <int value="8" label="HibernationEndedWithSwitchToBackgroundRendering"/>
-  <int value="9" label="HibernationEndedWithFallbackToSW"/>
-  <int value="10" label="HibernationEndedWithTeardown"/>
-  <int value="11" label="HibernationAbortedBecauseNoSurface"/>
+      label="Aborted due to destruction while hibernate was pending"/>
+  <int value="2" label="Aborted due to pending destruction (obsolete)"/>
+  <int value="3" label="Aborted due to visibility change"/>
+  <int value="4" label="Aborted due to GPU Context loss"/>
+  <int value="5" label="Aborted due to switch to unaccelerated rendering"/>
+  <int value="6" label="Aborted due to allocation failure"/>
+  <int value="7" label="Ended normally"/>
+  <int value="8" label="Ended with switch to background rendering"/>
+  <int value="9" label="Ended with fallback to software"/>
+  <int value="10" label="Ended with teardown"/>
+  <int value="11" label="Aborted because there was no surface"/>
 </enum>
 
 <enum name="CanvasResourceProviderType">
@@ -7885,6 +7911,13 @@
   <int value="37" label="Client hints setting"/>
   <int value="38" label="Sensors setting"/>
   <int value="39" label="Accessibility events setting"/>
+  <int value="40" label="Clipboard read"/>
+  <int value="41" label="Clipboard write"/>
+  <int value="42" label="Plugins data"/>
+  <int value="43" label="Payment handler"/>
+  <int value="44" label="USB guard"/>
+  <int value="45" label="Background fetch"/>
+  <int value="46" label="Intent picker display"/>
 </enum>
 
 <enum name="ContentTypeParseableResult">
@@ -9252,6 +9285,10 @@
   <int value="1" label="Click"/>
 </enum>
 
+<enum name="CrosSystemTrayManagedType">
+  <int value="0" label="Enterprise"/>
+</enum>
+
 <enum name="CrosSystemTrayToggleExpanded">
   <int value="0" label="Toggled by button"/>
   <int value="1" label="Toggled by gesture"/>
@@ -10574,6 +10611,11 @@
   <int value="18" label="YouTube"/>
 </enum>
 
+<enum name="DemoModeIdleLogoutWarningEvent">
+  <int value="0" label="Shown"/>
+  <int value="1" label="Canceled"/>
+</enum>
+
 <enum name="DemoModeResourcesRemovalReason">
   <int value="0" label="Low available disk space"/>
   <int value="1" label="Device enterprise enrolled"/>
@@ -10612,6 +10654,9 @@
 </enum>
 
 <enum name="DesktopIOSPromotionDismissalReason">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <int value="0" label="Focus lost."/>
   <int value="1" label="No thanks clicked."/>
   <int value="2" label="Close button clicked."/>
@@ -10620,6 +10665,9 @@
 </enum>
 
 <enum name="DesktopIOSPromotionEntryPoint">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <int value="1" label="Save Passwords new bubble."/>
   <int value="2" label="Bookmarks new bubble."/>
   <int value="3" label="Bookmarks footnote."/>
@@ -11828,6 +11876,9 @@
 </enum>
 
 <enum name="DownloadFrameGesture">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <summary>
     The type of frame in which a download occurs and whether the download
     involves a transient user gesture. It is only recorded for downloads
@@ -12231,6 +12282,8 @@
   <int value="315" label="osax"/>
   <int value="316" label="settingcontent-ms"/>
   <int value="317" label="oxt"/>
+  <int value="318" label="pyd"/>
+  <int value="319" label="pyo"/>
 </enum>
 
 <enum name="DownloadItem.DangerType">
@@ -14264,6 +14317,9 @@
   <int value="58" label="Consumer account with packaged license">
     Can't enroll a device with a packaged license to a consumer account.
   </int>
+  <int value="59" label="Device not pre-provisioned">
+    The device is not pre-provisioned for Zero-Touch.
+  </int>
 </enum>
 
 <enum name="EnterpriseExistingInstallAttributesLockType">
@@ -14801,6 +14857,8 @@
   <int value="496" label="BrowserSwitcherUrlList"/>
   <int value="497" label="BrowserSwitcherUrlGreylist"/>
   <int value="498" label="BrowserSwitcherUseIeSitelist"/>
+  <int value="499" label="ReportExtensionsAndPluginsData"/>
+  <int value="500" label="ReportSafeBrowsingData"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
@@ -15469,8 +15527,8 @@
   <int value="84" label="DOWNLOADS_ON_CREATED"/>
   <int value="85" label="DOWNLOADS_ON_DETERMINING_FILENAME"/>
   <int value="86" label="DOWNLOADS_ON_ERASED"/>
-  <int value="87" label="EASY_UNLOCK_PRIVATE_ON_START_AUTO_PAIRING"/>
-  <int value="88" label="EASY_UNLOCK_PRIVATE_ON_USER_INFO_UPDATED"/>
+  <int value="87" label="DELETED_EASY_UNLOCK_PRIVATE_ON_START_AUTO_PAIRING"/>
+  <int value="88" label="DELETED_EASY_UNLOCK_PRIVATE_ON_USER_INFO_UPDATED"/>
   <int value="89" label="DELETED_EXPERIENCE_SAMPLING_PRIVATE_ON_DECISION"/>
   <int value="90" label="DELETED_EXPERIENCE_SAMPLING_PRIVATE_ON_DISPLAYED"/>
   <int value="91" label="EXPERIMENTAL_DEVTOOLS_CONSOLE_ON_MESSAGE_ADDED"/>
@@ -15726,7 +15784,7 @@
   <int value="338" label="CAST_CHANNEL_ON_MESSAGE"/>
   <int value="339" label="CAST_CHANNEL_ON_ERROR"/>
   <int value="340" label="SCREENLOCK_PRIVATE_ON_CHANGED"/>
-  <int value="341" label="SCREENLOCK_PRIVATE_ON_AUTH_ATTEMPTED"/>
+  <int value="341" label="DELETED_SCREENLOCK_PRIVATE_ON_AUTH_ATTEMPTED"/>
   <int value="342" label="TYPES_CHROME_SETTING_ON_CHANGE"/>
   <int value="343"
       label="DELETED_TYPES_PRIVATE_CHROME_DIRECT_SETTING_ON_CHANGE"/>
@@ -15777,9 +15835,10 @@
   <int value="386" label="WEB_VIEW_INTERNAL_ON_BEFORE_REDIRECT"/>
   <int value="387" label="WEB_VIEW_INTERNAL_ON_ERROR_OCCURRED"/>
   <int value="388" label="WEB_VIEW_INTERNAL_ON_SEND_HEADERS"/>
-  <int value="389" label="EASY_UNLOCK_PRIVATE_ON_CONNECTION_STATUS_CHANGED"/>
-  <int value="390" label="EASY_UNLOCK_PRIVATE_ON_DATA_RECEIVED"/>
-  <int value="391" label="EASY_UNLOCK_PRIVATE_ON_SEND_COMPLETED"/>
+  <int value="389"
+      label="DELETED_EASY_UNLOCK_PRIVATE_ON_CONNECTION_STATUS_CHANGED"/>
+  <int value="390" label="DELETED_EASY_UNLOCK_PRIVATE_ON_DATA_RECEIVED"/>
+  <int value="391" label="DELETED_EASY_UNLOCK_PRIVATE_ON_SEND_COMPLETED"/>
   <int value="392" label="DISPLAY_SOURCE_ON_SINKS_UPDATED"/>
   <int value="393" label="INPUT_IME_ON_COMPOSITION_BOUNDS_CHANGED"/>
   <int value="394" label="INPUT_METHOD_PRIVATE_ON_IME_MENU_ACTIVATION_CHANGED"/>
@@ -16701,18 +16760,19 @@
   <int value="839" label="APPVIEWINTERNAL_ATTACHFRAME"/>
   <int value="840" label="APPVIEWINTERNAL_DENYREQUEST"/>
   <int value="841" label="FILEMANAGERPRIVATEINTERNAL_GETDOWNLOADURL"/>
-  <int value="842" label="EASYUNLOCKPRIVATE_PERFORMECDHKEYAGREEMENT"/>
-  <int value="843" label="EASYUNLOCKPRIVATE_GENERATEECP256KEYPAIR"/>
-  <int value="844" label="EASYUNLOCKPRIVATE_CREATESECUREMESSAGE"/>
-  <int value="845" label="EASYUNLOCKPRIVATE_UNWRAPSECUREMESSAGE"/>
+  <int value="842" label="DELETED_EASYUNLOCKPRIVATE_PERFORMECDHKEYAGREEMENT"/>
+  <int value="843" label="DELETED_EASYUNLOCKPRIVATE_GENERATEECP256KEYPAIR"/>
+  <int value="844" label="DELETED_EASYUNLOCKPRIVATE_CREATESECUREMESSAGE"/>
+  <int value="845" label="DELETED_EASYUNLOCKPRIVATE_UNWRAPSECUREMESSAGE"/>
   <int value="846" label="DELETED_LOGPRIVATE_STARTEVENTRECODER"/>
   <int value="847" label="DELETED_LOGPRIVATE_STOPEVENTRECODER"/>
   <int value="848" label="DELETED_LOGPRIVATE_DUMPLOGS"/>
   <int value="849" label="SOCKET_SECURE"/>
   <int value="850" label="SOCKETS_TCP_SECURE"/>
   <int value="851" label="DELETED_EXPERIENCESAMPLINGPRIVATE_GETBROWSERINFO"/>
-  <int value="852" label="EASYUNLOCKPRIVATE_SEEKBLUETOOTHDEVICEBYADDRESS"/>
-  <int value="853" label="EASYUNLOCKPRIVATE_GETSTRINGS"/>
+  <int value="852"
+      label="DELETED_EASYUNLOCKPRIVATE_SEEKBLUETOOTHDEVICEBYADDRESS"/>
+  <int value="853" label="DELETED_EASYUNLOCKPRIVATE_GETSTRINGS"/>
   <int value="854" label="NOTIFICATIONPROVIDER_SENDONCLEAR"/>
   <int value="855" label="NOTIFICATIONPROVIDER_NOTIFYONCLEARED"/>
   <int value="856" label="NOTIFICATIONPROVIDER_NOTIFYONCLICKED"/>
@@ -16735,28 +16795,28 @@
   <int value="873" label="BROWSINGDATA_REMOVESERVICEWORKERS"/>
   <int value="874" label="USBPRIVATE_GETDEVICES"/>
   <int value="875" label="USBPRIVATE_GETDEVICEINFO"/>
-  <int value="876" label="EASYUNLOCKPRIVATE_UPDATESCREENLOCKSTATE"/>
+  <int value="876" label="DELETED_EASYUNLOCKPRIVATE_UPDATESCREENLOCKSTATE"/>
   <int value="877" label="CAST_CHANNEL_GETLOGS"/>
-  <int value="878" label="EASYUNLOCKPRIVATE_SETPERMITACCESS"/>
-  <int value="879" label="EASYUNLOCKPRIVATE_GETPERMITACCESS"/>
-  <int value="880" label="EASYUNLOCKPRIVATE_CLEARPERMITACCESS"/>
-  <int value="881" label="EASYUNLOCKPRIVATE_SETREMOTEDEVICES"/>
-  <int value="882" label="EASYUNLOCKPRIVATE_GETREMOTEDEVICES"/>
+  <int value="878" label="DELETED_EASYUNLOCKPRIVATE_SETPERMITACCESS"/>
+  <int value="879" label="DELETED_EASYUNLOCKPRIVATE_GETPERMITACCESS"/>
+  <int value="880" label="DELETED_EASYUNLOCKPRIVATE_CLEARPERMITACCESS"/>
+  <int value="881" label="DELETED_EASYUNLOCKPRIVATE_SETREMOTEDEVICES"/>
+  <int value="882" label="DELETED_EASYUNLOCKPRIVATE_GETREMOTEDEVICES"/>
   <int value="883" label="FILESYSTEMPROVIDER_GETALL"/>
   <int value="884"
-      label="EASYUNLOCKPRIVATE_CONNECTTOBLUETOOTHSERVICEINSECURELY"/>
+      label="DELETED_EASYUNLOCKPRIVATE_CONNECTTOBLUETOOTHSERVICEINSECURELY"/>
   <int value="885" label="MEDIAGALLERIES_ADDGALLERYWATCH"/>
   <int value="886" label="MEDIAGALLERIES_REMOVEGALLERYWATCH"/>
   <int value="887" label="DELETED_MEDIAGALLERIES_GETALLGALLERYWATCH"/>
   <int value="888" label="DELETED_MEDIAGALLERIES_REMOVEALLGALLERYWATCH"/>
   <int value="889" label="MANAGEMENT_GETSELF"/>
   <int value="890" label="APP_CURRENTWINDOWINTERNAL_SETVISIBLEONALLWORKSPACES"/>
-  <int value="891" label="EASYUNLOCKPRIVATE_GETSIGNINCHALLENGE"/>
-  <int value="892" label="EASYUNLOCKPRIVATE_TRYSIGNINSECRET"/>
+  <int value="891" label="DELETED_EASYUNLOCKPRIVATE_GETSIGNINCHALLENGE"/>
+  <int value="892" label="DELETED_EASYUNLOCKPRIVATE_TRYSIGNINSECRET"/>
   <int value="893" label="ACCESSIBILITY_PRIVATE_SETFOCUSRING"/>
   <int value="894" label="USB_GETCONFIGURATION"/>
   <int value="895" label="WEBVIEWINTERNAL_SETALLOWTRANSPARENCY"/>
-  <int value="896" label="EASYUNLOCKPRIVATE_GETUSERINFO"/>
+  <int value="896" label="DELETED_EASYUNLOCKPRIVATE_GETUSERINFO"/>
   <int value="897" label="HOTWORDPRIVATE_GETLAUNCHSTATE"/>
   <int value="898" label="HOTWORDPRIVATE_SETHOTWORDALWAYSONSEARCHENABLED"/>
   <int value="899" label="WEBVIEWINTERNAL_LOADDATAWITHBASEURL"/>
@@ -16807,20 +16867,20 @@
   <int value="943" label="BLUETOOTHPRIVATE_DISCONNECTALL"/>
   <int value="944" label="FILEMANAGERPRIVATEINTERNAL_GETMIMETYPE"/>
   <int value="945" label="USB_SETCONFIGURATION"/>
-  <int value="946" label="EASYUNLOCKPRIVATE_GETCONNECTIONINFO"/>
+  <int value="946" label="DELETED_EASYUNLOCKPRIVATE_GETCONNECTIONINFO"/>
   <int value="947" label="FILEMANAGERPRIVATEINTERNAL_COMPUTECHECKSUM"/>
   <int value="948" label="PRINTERPROVIDERINTERNAL_REPORTPRINTRESULT"/>
   <int value="949" label="PRINTERPROVIDERINTERNAL_REPORTPRINTERCAPABILITY"/>
   <int value="950" label="PRINTERPROVIDERINTERNAL_REPORTPRINTERS"/>
   <int value="951" label="FILESYSTEMPROVIDER_GET"/>
   <int value="952" label="FILEMANAGERPRIVATE_SEARCHFILESBYHASHES"/>
-  <int value="953" label="EASYUNLOCKPRIVATE_SHOWERRORBUBBLE"/>
+  <int value="953" label="DELETED_EASYUNLOCKPRIVATE_SHOWERRORBUBBLE"/>
   <int value="954" label="EXTENSIONVIEWINTERNAL_NAVIGATE"/>
   <int value="955" label="NETWORKING_CONFIG_SETNETWORKFILTER"/>
   <int value="956" label="NETWORKING_CONFIG_FINISHAUTHENTICATION"/>
   <int value="957" label="PLATFORMKEYSINTERNAL_SELECTCLIENTCERTIFICATES"/>
   <int value="958" label="CRYPTOTOKENPRIVATE_CANORIGINASSERTAPPID"/>
-  <int value="959" label="EASYUNLOCKPRIVATE_SETAUTOPAIRINGRESULT"/>
+  <int value="959" label="DELETED_EASYUNLOCKPRIVATE_SETAUTOPAIRINGRESULT"/>
   <int value="960" label="FILEMANAGERPRIVATE_ISUMAENABLED"/>
   <int value="961" label="WEBVIEWINTERNAL_SETALLOWSCALING"/>
   <int value="962" label="PLATFORMKEYSINTERNAL_GETPUBLICKEY"/>
@@ -16854,7 +16914,7 @@
   <int value="989" label="SETTINGSPRIVATE_GETALLPREFS"/>
   <int value="990" label="SETTINGSPRIVATE_GETPREF"/>
   <int value="991" label="NETWORKINGPRIVATE_FORGETNETWORK"/>
-  <int value="992" label="EASYUNLOCKPRIVATE_HIDEERRORBUBBLE"/>
+  <int value="992" label="DELETED_EASYUNLOCKPRIVATE_HIDEERRORBUBBLE"/>
   <int value="993" label="WEBVIEWINTERNAL_SETZOOMMODE"/>
   <int value="994" label="WEBVIEWINTERNAL_GETZOOMMODE"/>
   <int value="995" label="LAUNCHERSEARCHPROVIDER_SETSEARCHRESULTS"/>
@@ -16951,14 +17011,16 @@
   <int value="1080" label="CERTIFICATEPROVIDERINTERNAL_REPORTSIGNATURE"/>
   <int value="1081" label="CERTIFICATEPROVIDERINTERNAL_REPORTCERTIFICATES"/>
   <int value="1082" label="BLUETOOTHPRIVATE_PAIR"/>
-  <int value="1083" label="EASYUNLOCKPRIVATE_FINDSETUPCONNECTION"/>
+  <int value="1083" label="DELETED_EASYUNLOCKPRIVATE_FINDSETUPCONNECTION"/>
   <int value="1084" label="RESOURCESPRIVATE_GETSTRINGS"/>
   <int value="1085" label="USB_GETCONFIGURATIONS"/>
-  <int value="1086" label="EASYUNLOCKPRIVATE_SETUPCONNECTIONSTATUS"/>
-  <int value="1087" label="EASYUNLOCKPRIVATE_SETUPCONNECTIONDISCONNECT"/>
-  <int value="1088" label="EASYUNLOCKPRIVATE_SETUPCONNECTIONSEND"/>
+  <int value="1086" label="DELETED_EASYUNLOCKPRIVATE_SETUPCONNECTIONSTATUS"/>
+  <int value="1087"
+      label="DELETED_EASYUNLOCKPRIVATE_SETUPCONNECTIONDISCONNECT"/>
+  <int value="1088" label="DELETED_EASYUNLOCKPRIVATE_SETUPCONNECTIONSEND"/>
   <int value="1089" label="DATAREDUCTIONPROXY_GETDATAUSAGE"/>
-  <int value="1090" label="EASYUNLOCKPRIVATE_SETUPCONNECTIONGETDEVICEADDRESS"/>
+  <int value="1090"
+      label="DELETED_EASYUNLOCKPRIVATE_SETUPCONNECTIONGETDEVICEADDRESS"/>
   <int value="1091" label="TABCAPTURE_CAPTUREOFFSCREENTAB"/>
   <int value="1092" label="LANGUAGESETTINGSPRIVATE_ADDSPELLCHECKWORD"/>
   <int value="1093" label="LANGUAGESETTINGSPRIVATE_REMOVESPELLCHECKWORD"/>
@@ -17164,6 +17226,10 @@
   <int value="1286" label="ACCESSIBILITY_PRIVATE_SENDSYNTHETICMOUSEEVENT"/>
   <int value="1287" label="FILEMANAGERPRIVATE_DETECTCHARACTERENCODING"/>
   <int value="1288" label="FILEMANAGERPRIVATEINTERNAL_GETLINUXPACKAGEINFO"/>
+  <int value="1289" label="TABS_GOFORWARD"/>
+  <int value="1290" label="TABS_GOBACK"/>
+  <int value="1291"
+      label="BRAILLEDISPLAYPRIVATE_UPDATEBLUETOOTHBRAILLEDISPLAYADDRESS"/>
 </enum>
 
 <enum name="ExtensionIconState">
@@ -17470,7 +17536,7 @@
   <int value="52" label="kDownloadsInternal"/>
   <int value="53" label="kDownloadsOpen"/>
   <int value="54" label="kDownloadsShelf"/>
-  <int value="55" label="kEasyUnlockPrivate"/>
+  <int value="55" label="kDeleted_EasyUnlockPrivate"/>
   <int value="56" label="kEchoPrivate"/>
   <int value="57" label="kEmbeddedExtensionOptions"/>
   <int value="58" label="kEnterprisePlatformKeys"/>
@@ -20619,6 +20685,17 @@
   <int value="2612" label="V8OptimizedFunctionWithOneShotBytecode"/>
   <int value="2613" label="SVGGeometryPropertyHasNonZeroUnitlessValue"/>
   <int value="2614" label="CSSValueAppearanceNoImplementationSkipBorder"/>
+  <int value="2615" label="InstantiateModuleScript"/>
+  <int value="2616" label="DynamicImportModuleScript"/>
+  <int value="2617" label="HistoryPushState"/>
+  <int value="2618" label="HistoryReplaceState"/>
+  <int value="2619" label="GetDisplayMedia"/>
+  <int value="2620" label="CursorImageGT64x64"/>
+  <int value="2621" label="AdClick"/>
+  <int value="2622" label="UpdateWithoutShippingOptionOnShippingAddressChange"/>
+  <int value="2623" label="UpdateWithoutShippingOptionOnShippingOptionChange"/>
+  <int value="2624" label="CSSSelectorEmptyWhitespaceOnlyFail"/>
+  <int value="2625" label="ActivatedImplicitRootScroller"/>
 </enum>
 
 <enum name="FeaturePolicyFeature">
@@ -20647,9 +20724,9 @@
   <int value="20" label="kMagnetometer"/>
   <int value="21" label="kUnsizedMedia"/>
   <int value="22" label="kLegacyImageFormats"/>
-  <int value="23" label="kImageCompression"/>
+  <int value="23" label="kUnoptimizedImages"/>
   <int value="24" label="kAnimations"/>
-  <int value="25" label="kMaxDownscalingImage"/>
+  <int value="25" label="kOversizedImages"/>
   <int value="26" label="kPictureInPicture"/>
   <int value="27" label="kVerticalScroll"/>
   <int value="28" label="kDocumentWrite"/>
@@ -25612,11 +25689,11 @@
 
 <enum name="IMEExtensionMojoEvent">
   <int value="0" label="Unknown"/>
-  <int value="1" label="Init Sucess"/>
+  <int value="1" label="Init Success"/>
   <int value="2" label="Init Failed"/>
   <int value="3" label="Activate IME Success"/>
   <int value="4" label="Activate IME Failed"/>
-  <int value="5" label="Rulebased Process Failed"/>
+  <int value="5" label="Service disconnected"/>
 </enum>
 
 <enum name="IMEGestureTypingEvent">
@@ -29113,6 +29190,7 @@
   <int value="-1710772665" label="disable-my-files-navigation"/>
   <int value="-1703709912" label="enable-new-ntp"/>
   <int value="-1703308540" label="disable-webaudio"/>
+  <int value="-1701123067" label="ShowManagedUi:enabled"/>
   <int value="-1696366449" label="disable-permissions-bubbles"/>
   <int value="-1695774453" label="skip-extra-ash-window-positioning"/>
   <int value="-1694353093" label="ArcVpn:disabled"/>
@@ -29205,8 +29283,10 @@
   <int value="-1536293422" label="SharedArrayBuffer:enabled"/>
   <int value="-1536242739" label="security-chip"/>
   <int value="-1535758690" label="AutoplayIgnoreWebAudio:disabled"/>
+  <int value="-1533258008" label="CalculateNativeWinOcclusion:enabled"/>
   <int value="-1532035450" label="DragTabsInTabletMode:disabled"/>
   <int value="-1532014193" label="disable-encryption-migration"/>
+  <int value="-1529907580" label="ImeServiceConnectable:disabled"/>
   <int value="-1528455406" label="OmniboxPedalSuggestions:enabled"/>
   <int value="-1520855274" label="PWAFullCodeCache:disabled"/>
   <int value="-1517518406" label="force-update-menu-type"/>
@@ -29427,6 +29507,7 @@
   <int value="-1174267639" label="ClientLoFi:disabled"/>
   <int value="-1172572865" label="NTPShowGoogleGInOmnibox:enabled"/>
   <int value="-1172204005" label="enable-offline-auto-reload-visible-only"/>
+  <int value="-1167992523" label="DesktopPWAsCustomTabUI:disabled"/>
   <int value="-1166715563" label="ChromeOSAssistant:disabled"/>
   <int value="-1162944097" label="enable-color-correct-rendering"/>
   <int value="-1161409696" label="MediaRemotingEncrypted:enabled"/>
@@ -29614,6 +29695,7 @@
   <int value="-823165021" label="MaterialDesignUserMenu:enabled"/>
   <int value="-820041355" label="enable-transition-compositing"/>
   <int value="-816984237" label="OfflinePagesAsyncDownload:enabled"/>
+  <int value="-816895294" label="DiscoverApp:disabled"/>
   <int value="-814097014" label="disable-session-crashed-bubble"/>
   <int value="-813753274" label="VrBrowsing:disabled"/>
   <int value="-813474479" label="site-per-process"/>
@@ -29639,6 +29721,7 @@
   <int value="-775321548" label="UseNewDoodleApi:disabled"/>
   <int value="-773238824" label="AutoplayWhitelistSettings:disabled"/>
   <int value="-772679248" label="MojoVideoEncodeAccelerator:enabled"/>
+  <int value="-772608284" label="MyFilesVolume:enabled"/>
   <int value="-771080109" label="GrantNotificationsToDSE:disabled"/>
   <int value="-770319039" label="enable-touch-editing"/>
   <int value="-769865314" label="AutofillCacheQueryResponses:disabled"/>
@@ -29792,6 +29875,8 @@
   <int value="-471405972" label="ViewsProfileChooser:disabled"/>
   <int value="-471085510" label="MultiDeviceApi:enabled"/>
   <int value="-470948890" label="OfflinePagesDescriptivePendingStatus:enabled"/>
+  <int value="-470247915"
+      label="AutofillUpstreamEditableExpirationDate:enabled"/>
   <int value="-468697885" label="ArcInputMethod:enabled"/>
   <int value="-462205750" label="enable-service-worker-sync"/>
   <int value="-461292699" label="ContentSuggestionsCategoryOrder:enabled"/>
@@ -29929,6 +30014,8 @@
   <int value="-181590721"
       label="AutofillEnforceMinRequiredFieldsForHeuristics:enabled"/>
   <int value="-181093956" label="ScrollAnchoring:enabled"/>
+  <int value="-174706795"
+      label="WebPaymentsPerMethodCanMakePaymentQuota:enabled"/>
   <int value="-174564579"
       label="ServiceWorkerImportedScriptUpdateCheck:enabled"/>
   <int value="-174319545" label="BulkPrinters:enabled"/>
@@ -29992,6 +30079,7 @@
   <int value="-59401847" label="ContentSuggestionsLargeThumbnail:disabled"/>
   <int value="-58242474" label="ash-disable-swipe-to-close-in-overview-mode"/>
   <int value="-57986995" label="DisablePostScriptPrinting:enabled"/>
+  <int value="-56235502" label="WebRtcHideLocalIpsWithMdns:enabled"/>
   <int value="-55944747" label="disable-child-account-detection"/>
   <int value="-52483823" label="disable-new-video-renderer"/>
   <int value="-52241456" label="enable-single-click-autofill"/>
@@ -30050,6 +30138,7 @@
   <int value="37045987" label="AutofillPreviewStyleExperiment:disabled"/>
   <int value="42098736" label="TranslateAndroidManualTrigger:disabled"/>
   <int value="42844603" label="AndroidSurfaceControl:disabled"/>
+  <int value="43951968" label="DesktopPWAsCustomTabUI:enabled"/>
   <int value="44088203" label="ExpensiveBackgroundTimerThrottling:enabled"/>
   <int value="48159177" label="reduced-referrer-granularity"/>
   <int value="48223610" label="SiteSettings:disabled"/>
@@ -30281,6 +30370,7 @@
   <int value="513356954" label="InstantTethering:disabled"/>
   <int value="513372959" label="ViewsProfileChooser:enabled"/>
   <int value="517568645" label="AnimatedAppMenuIcon:disabled"/>
+  <int value="533064367" label="WebRtcHideLocalIpsWithMdns:disabled"/>
   <int value="535131384" label="OmniboxTailSuggestions:enabled"/>
   <int value="535976218" label="enable-plugin-power-saver"/>
   <int value="538468149" label="OfflinePagesCT:enabled"/>
@@ -30307,6 +30397,7 @@
   <int value="588333474" label="OfflineIndicator:disabled"/>
   <int value="592050831" label="disable-slimming-paint"/>
   <int value="593707592" label="disable-network-portal-notification"/>
+  <int value="594756372" label="MyFilesVolume:disabled"/>
   <int value="595168244" label="NotificationExpansionAnimation:enabled"/>
   <int value="595371145" label="OmniboxRichEntitySuggestions:disabled"/>
   <int value="596106994" label="CustomFeedbackUi:enabled"/>
@@ -30321,6 +30412,7 @@
   <int value="606288133" label="enable-print-preview-register-promos"/>
   <int value="606512202" label="AutofillCreditCardPopupLayout:enabled"/>
   <int value="606834606" label="force-color-profile"/>
+  <int value="606969417" label="DiscoverApp:enabled"/>
   <int value="609112512" label="touch-selection-strategy"/>
   <int value="609580715" label="ArcCupsApi:disabled"/>
   <int value="610545308" label="enable-potentially-annoying-security-features"/>
@@ -30406,6 +30498,9 @@
   <int value="736911267" label="ExperimentalCrostiniUI:disabled"/>
   <int value="737421745" label="enable-accessibility-object-model"/>
   <int value="738868972" label="GdiTextPrinting:disabled"/>
+  <int value="739938466"
+      label="WebPaymentsPerMethodCanMakePaymentQuota:disabled"/>
+  <int value="740056959" label="ImeServiceConnectable:enabled"/>
   <int value="745783589" label="translate-force-trigger-on-english"/>
   <int value="745868416" label="disable-system-timezone-automatic-detection"/>
   <int value="746944193" label="enable-automatic-password-saving:disabled"/>
@@ -30600,6 +30695,7 @@
   <int value="1111871757" label="ForceUnifiedConsentBump:enabled"/>
   <int value="1112051724" label="DetectingHeavyPages:enabled"/>
   <int value="1112885300" label="VizHitTestDrawQuad:disabled"/>
+  <int value="1113196543" label="ShowManagedUi:disabled"/>
   <int value="1113365156" label="tab-management-experiment-type-chive"/>
   <int value="1114629582" label="enable-floating-virtual-keyboard"/>
   <int value="1115476442" label="PolicyTool:disabled"/>
@@ -31054,6 +31150,8 @@
   <int value="1955677113" label="trace-export-events-to-etw"/>
   <int value="1957273171" label="PageAlmostIdle:disabled"/>
   <int value="1957358530" label="ContextualSearchSecondTap:enabled"/>
+  <int value="1957472162"
+      label="AutofillUpstreamEditableExpirationDate:disabled"/>
   <int value="1958387645" label="ScanCardsInWebPayments:enabled"/>
   <int value="1959148757" label="OffMainThreadFetch:enabled"/>
   <int value="1960169775" label="NewPhotoPicker:disabled"/>
@@ -31105,6 +31203,7 @@
   <int value="2043321329" label="OfflinePagesPrefetchingUI:disabled"/>
   <int value="2056572020" label="EnableUsernameCorrection:disabled"/>
   <int value="2058283872" label="CCTModuleCache:disabled"/>
+  <int value="2058439723" label="CalculateNativeWinOcclusion:disabled"/>
   <int value="2059322877" label="new-avatar-menu"/>
   <int value="2063091429" label="OfflinePagesSharing:enabled"/>
   <int value="2067634730" label="LsdPermissionPrompt:disabled"/>
@@ -33237,6 +33336,15 @@
   <int value="1" label="Http Live Stream Type"/>
 </enum>
 
+<enum name="MediaVideoHeight">
+  <int value="0" label="~360 or lower"/>
+  <int value="1" label="~480"/>
+  <int value="2" label="~720"/>
+  <int value="3" label="~1080"/>
+  <int value="4" label="~1440"/>
+  <int value="5" label="~2160 or higher"/>
+</enum>
+
 <enum name="MemCacheWriteResult">
   <int value="0" label="Success"/>
   <int value="1" label="Invalid Argument"/>
@@ -33445,6 +33553,14 @@
   <int value="2" label="ResponseReceived"/>
 </enum>
 
+<enum name="MixedContentType">
+  <int value="0" label="Display Mixed Content"/>
+  <int value="1" label="Display Content with Certificate Errors"/>
+  <int value="2" label="Mixed Content Form"/>
+  <int value="3" label="Scripting Mixed Content"/>
+  <int value="4" label="Scripting Content with Certificate Errors"/>
+</enum>
+
 <enum name="MobileDefaultBrowserState">
   <int value="0" label="No default"/>
   <int value="1" label="Chrome: System default"/>
@@ -33746,6 +33862,33 @@
   <int value="2" label="SUCCESS">All operations succeeded.</int>
 </enum>
 
+<enum name="MultiDevice_DeviceSyncService_DeviceSyncRequestFailureReason">
+  <int value="0" label="Requested succeeded but unexpected result"/>
+  <int value="1" label="Service not yet initialized"/>
+  <int value="2" label="Device offline"/>
+  <int value="3" label="Server endpoint not found"/>
+  <int value="4" label="Authentication error"/>
+  <int value="5" label="Bad request"/>
+  <int value="6" label="Response malformed"/>
+  <int value="7" label="Internal server error"/>
+  <int value="8" label="Unknown network error"/>
+  <int value="9" label="Unknown error"/>
+</enum>
+
+<enum name="MultiDevice_DeviceSyncService_Features">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="Better Together Suite"/>
+  <int value="2" label="Smart Lock"/>
+  <int value="3" label="Instant Tethering"/>
+  <int value="4" label="Messages"/>
+  <int value="5" label="Unexpected Client Feature"/>
+</enum>
+
+<enum name="MultiDevice_DeviceSyncService_ForceCryptAuthOperationResult">
+  <int value="0" label="Success"/>
+  <int value="1" label="Service not ready"/>
+</enum>
+
 <enum name="MultiDevice_PostOOBESetupFlow_Page">
   <int value="0" label="Unknown page"/>
   <int value="1" label="Start page"/>
@@ -33753,6 +33896,14 @@
   <int value="3" label="Success page"/>
 </enum>
 
+<enum name="MultiDevice_Setup_HostStatus">
+  <int value="0" label="No eligible hosts"/>
+  <int value="1" label="Eligible host exists but no host set"/>
+  <int value="2" label="Host set locally but waiting for backend confirmation"/>
+  <int value="3" label="Host set but not yet verified"/>
+  <int value="4" label="Host verified"/>
+</enum>
+
 <enum name="MultiDeviceSetupNotification">
   <int value="0" label="New user, potential host exists"/>
   <int value="1" label="Existing user, host switched"/>
@@ -34074,6 +34225,13 @@
   <int value="2" label="Back">Scrolled back</int>
 </enum>
 
+<enum name="NavigationDownloadPolicy">
+  <int value="0" label="Allowed"/>
+  <int value="1" label="Disallowed (view-source)"/>
+  <int value="2" label="Disallowed (interstitial)"/>
+  <int value="3" label="Allowed (opener)"/>
+</enum>
+
 <enum name="NavigationInterceptResult">
   <int value="0" label="Created external intent"/>
   <int value="1" label="Created external intent with tab clobbering"/>
@@ -34086,6 +34244,12 @@
   <int value="1" label="Same process navigation"/>
 </enum>
 
+<enum name="NavigationNeedsReloadType">
+  <int value="0" label="kRequestedByClient"/>
+  <int value="1" label="kRestoreSession"/>
+  <int value="2" label="kCopyStateFrom"/>
+</enum>
+
 <enum name="NavigationScheme">
   <int value="0" label="(Unknown)"/>
   <int value="1" label="http"/>
@@ -36372,6 +36536,7 @@
   <int value="1" label="Arc++"/>
   <int value="2" label="Web Page"/>
   <int value="3" label="System Component"/>
+  <int value="4" label="Crostini"/>
 </enum>
 
 <enum name="NotifyResult">
@@ -44413,6 +44578,8 @@
   <int value="315" label="OSAX"/>
   <int value="316" label="SETTINGCONTENT-MS"/>
   <int value="317" label="OXT"/>
+  <int value="318" label="PYD"/>
+  <int value="319" label="PYO"/>
 </enum>
 
 <enum name="SBClientDownloadIsSignedBinary">
@@ -45024,6 +45191,9 @@
 </enum>
 
 <enum name="ServiceWorkerMainResourceRequestDestination">
+  <obsolete>
+    Not used since November 2018
+  </obsolete>
   <summary>
     Describes whether a main resource request went to service worker or network
     or errored.
@@ -46494,6 +46664,25 @@
   <int value="3" label="User-initiated with logs enabled"/>
 </enum>
 
+<enum name="SourceForRefreshTokenOperation">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="TokenService::LoadCredentials"/>
+  <int value="2" label="SupervisedUser::InitSync"/>
+  <int value="3" label="InlineLoginHandler::Signin"/>
+  <int value="4" label="SigninManager::ClearPrimaryAccount"/>
+  <int value="5" label="SigninManager::LegacyPreDiceSigninFlow"/>
+  <int value="6" label="UserMenu:RemoveAccount"/>
+  <int value="7" label="UserMenu::SignOutAllAccounts"/>
+  <int value="8" label="Settings::Signout"/>
+  <int value="9" label="Settings::PauseSync"/>
+  <int value="10" label="AccountReconcilor::GaiaCookiesDeletedByUser"/>
+  <int value="11" label="AccountReconcilor::GaiaCookiesUpdated"/>
+  <int value="12" label="AccountReconcilor::Reconcile"/>
+  <int value="13" label="DiceResponseHandler::Signin"/>
+  <int value="14" label="DiceResponseHandler::Signout"/>
+  <int value="15" label="DiceTurnOnSyncHelper::Abort"/>
+</enum>
+
 <enum name="SpareProcessMaybeTakeAction">
   <int value="0" label="NoSparePresent"/>
   <int value="1" label="MismatchedBrowserContext"/>
@@ -47742,6 +47931,32 @@
   <int value="2" label="MemoryCached StyleSheetContents was reused"/>
 </enum>
 
+<enum name="SubframeDownloadSandboxOriginAdGesture">
+  <summary>
+    For a download that occurs in subframe, record whether the frame is
+    sandboxed, whether the origin is same to the top frame, whether it's an ad
+    subframe, and whether the download involves a transient user gesture. It is
+    only recorded for downloads originated from navigations or from HTML anchor
+    download attributes.
+  </summary>
+  <int value="0" label="NotSandboxed_SameOrigin_NonAd_NoGesture"/>
+  <int value="1" label="NotSandboxed_SameOrigin_NonAd_Gesture"/>
+  <int value="2" label="NotSandboxed_SameOrigin_Ad_NoGesture"/>
+  <int value="3" label="NotSandboxed_SameOrigin_Ad_Gesture"/>
+  <int value="4" label="NotSandboxed_CrossOrigin_NonAd_NoGesture"/>
+  <int value="5" label="NotSandboxed_CrossOrigin_NonAd_Gesture"/>
+  <int value="6" label="NotSandboxed_CrossOrigin_Ad_NoGesture"/>
+  <int value="7" label="NotSandboxed_CrossOrigin_Ad_Gesture"/>
+  <int value="8" label="Sandboxed_SameOrigin_NonAd_NoGesture"/>
+  <int value="9" label="Sandboxed_SameOrigin_NonAd_Gesture"/>
+  <int value="10" label="Sandboxed_SameOrigin_Ad_NoGesture"/>
+  <int value="11" label="Sandboxed_SameOrigin_Ad_Gesture"/>
+  <int value="12" label="Sandboxed_CrossOrigin_NonAd_NoGesture"/>
+  <int value="13" label="Sandboxed_CrossOrigin_NonAd_Gesture"/>
+  <int value="14" label="Sandboxed_CrossOrigin_Ad_NoGesture"/>
+  <int value="15" label="Sandboxed_CrossOrigin_Ad_Gesture"/>
+</enum>
+
 <enum name="SubmissionIndicatorEvent">
   <int value="0" label="No submission"/>
   <int value="1" label="HTML form submission"/>
@@ -48302,6 +48517,17 @@
   <int value="3" label="Local version is ahead"/>
 </enum>
 
+<enum name="SyncClientToServerMessageContents">
+  <summary>
+    Type of a network message sent from the client to the sync server.
+  </summary>
+  <int value="1" label="COMMIT"/>
+  <int value="2" label="GET_UPDATES"/>
+  <int value="3" label="AUTHENTICATE"/>
+  <int value="4" label="DEPRECATED_4"/>
+  <int value="5" label="CLEAR_SERVER_DATA"/>
+</enum>
+
 <enum name="SyncConfigureResult">
   <summary>
     Sync data type configure results. The codes are listed in
@@ -52190,6 +52416,15 @@
   <int value="4" label="Fullscreen"/>
 </enum>
 
+<enum name="WebAppInstallResultCode">
+  <int value="0" label="Success"/>
+  <int value="1" label="AlreadyInstalled"/>
+  <int value="2" label="FailedUnknownReason"/>
+  <int value="3" label="GetWebApplicationInfoFailed"/>
+  <int value="4" label="PreviouslyUninstalled"/>
+  <int value="5" label="WebContentsDestroyed"/>
+</enum>
+
 <enum name="WebAppInstallSource">
   <obsolete>
     Removed from code Jan 2018.
@@ -52455,6 +52690,16 @@
   <int value="3" label="Both"/>
 </enum>
 
+<enum name="WebRequestSpecialRequestHeaderModification">
+  <int value="0" label="None"/>
+  <int value="1" label="AcceptLanguage"/>
+  <int value="2" label="AcceptEncoding"/>
+  <int value="3" label="UserAgent"/>
+  <int value="4" label="Cookie"/>
+  <int value="5" label="Referer"/>
+  <int value="6" label="Multiple"/>
+</enum>
+
 <enum name="WebRequestWSRequestHeadersModification">
   <int value="0" label="None"/>
   <int value="1" label="Setting User-Agent only"/>
@@ -52945,6 +53190,11 @@
   <int value="1" label="Revoked ephemeral permission"/>
 </enum>
 
+<enum name="WebViewClientTypeEnum">
+  <int value="0" label="Regular WebViewClient"/>
+  <int value="1" label="WebViewClientCompat (via AndroidX)"/>
+</enum>
+
 <enum name="WelcomeSignInPromptOutcome">
   <int value="0" label="User navigated away from page"/>
   <int value="1" label="User clicked the No Thanks button"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 101f8de..3a777cb 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -313,7 +313,7 @@
 </histogram>
 
 <histogram name="Accessibility.Mac.DifferentiateWithoutColor"
-    enum="BooleanEnabled">
+    enum="BooleanEnabled" expires_after="2019-11-02">
   <owner>ellyjones@chromium.org</owner>
   <summary>
     Whether the &quot;differentiate without color&quot; Mac system setting is
@@ -322,7 +322,7 @@
 </histogram>
 
 <histogram name="Accessibility.Mac.FullKeyboardAccessEnabled"
-    enum="BooleanEnabled">
+    enum="BooleanEnabled" expires_after="2019-11-02">
   <owner>ellyjones@chromium.org</owner>
   <summary>
     Whether the &quot;full keyboard access&quot; Mac system setting is enabled.
@@ -330,7 +330,8 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.Mac.IncreaseContrast" enum="BooleanEnabled">
+<histogram name="Accessibility.Mac.IncreaseContrast" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>ellyjones@chromium.org</owner>
   <summary>
     Whether the &quot;increase contrast&quot; Mac system setting is enabled.
@@ -338,7 +339,19 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.Mac.ReduceTransparency" enum="BooleanEnabled">
+<histogram name="Accessibility.Mac.ReduceMotion" enum="BooleanEnabled">
+  <owner>dmazzoni@chromium.org</owner>
+  <owner>smcgruer@chromium.org</owner>
+  <summary>
+    Tracks whether the accessibilityDisplayShouldReduceMotion system property is
+    enabled. The purpose is to inform the design of the prefers-reduced-motion
+    media feature; see http://crbug.com/722548. This is checked once, 45 seconds
+    after startup.
+  </summary>
+</histogram>
+
+<histogram name="Accessibility.Mac.ReduceTransparency" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>ellyjones@chromium.org</owner>
   <summary>
     Whether the &quot;reduce transparency&quot; Mac system setting is enabled.
@@ -391,13 +404,26 @@
   </summary>
 </histogram>
 
+<histogram name="Accessibility.Win.AnimationsEnabled" enum="BooleanEnabled"
+    expires_after="2019-11-02">
+  <owner>dmazzoni@chromium.org</owner>
+  <owner>smcgruer@chromium.org</owner>
+  <summary>
+    Tracks whether the SPI_GETCLIENTAREAANIMATION system property is enabled.
+    The purpose is to inform the design of the prefers-reduced-motion media
+    feature; see http://crbug.com/722548. This is checked once, 45 seconds after
+    startup.
+  </summary>
+</histogram>
+
 <histogram name="Accessibility.WinAPIs" enum="AccessibilityWinAPIEnum">
   <owner>dmazzoni@chromium.org</owner>
   <owner>nektar@chromium.org</owner>
   <summary>Tracks usage of all public Windows accessibility APIs.</summary>
 </histogram>
 
-<histogram name="Accessibility.WinAudioDescription" enum="BooleanEnabled">
+<histogram name="Accessibility.WinAudioDescription" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <summary>
@@ -406,7 +432,8 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.WinJAWS" enum="BooleanEnabled">
+<histogram name="Accessibility.WinJAWS" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <summary>
@@ -415,7 +442,8 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.WinNVDA" enum="BooleanEnabled">
+<histogram name="Accessibility.WinNVDA" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <summary>
@@ -424,7 +452,8 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.WinSAToGo" enum="BooleanEnabled">
+<histogram name="Accessibility.WinSAToGo" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <summary>
@@ -433,7 +462,8 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.WinScreenReader" enum="BooleanEnabled">
+<histogram name="Accessibility.WinScreenReader" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <summary>
@@ -444,7 +474,8 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.WinStickyKeys" enum="BooleanEnabled">
+<histogram name="Accessibility.WinStickyKeys" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <summary>
@@ -452,7 +483,8 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.WinZoomText" enum="BooleanEnabled">
+<histogram name="Accessibility.WinZoomText" enum="BooleanEnabled"
+    expires_after="2019-11-02">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <summary>
@@ -843,6 +875,25 @@
   </summary>
 </histogram>
 
+<histogram name="AnchorElementMetrics.Clicked.OnDSE.SameHost"
+    enum="BooleanAnchorElementSameHost">
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    True if the target link of the anchor element has the same host as the root
+    document. Recorded only on default search engine pages.
+  </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.OnNonDSE.SameHost"
+    enum="BooleanAnchorElementSameHost">
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    True if the target link of the anchor element has the same host as the root
+    document. Recorded only on pages whose URL do not match the default search
+    engine.
+  </summary>
+</histogram>
+
 <histogram name="AnchorElementMetrics.Clicked.RatioContainsImage_ContainsImage"
     units="%">
   <owner>chelu@chromium.org</owner>
@@ -983,6 +1034,13 @@
   </summary>
 </histogram>
 
+<histogram name="AnchorElementMetrics.IsAdFrameElement" units="Boolean">
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    True if the anchor element was inside an iframe tagged as an ad iframe.
+  </summary>
+</histogram>
+
 <histogram base="true" name="AnchorElementMetrics.IsInIFrame" enum="Boolean">
   <owner>chelu@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
@@ -2698,6 +2756,18 @@
   </summary>
 </histogram>
 
+<histogram name="Android.WebView.SupportLibrary.ClientIsCompat"
+    enum="WebViewClientTypeEnum" expires_after="2019-05-05">
+  <owner>ntfschr@chromium.org</owner>
+  <owner>changwan@chromium.org</owner>
+  <summary>
+    Records whether the WebViewClient provided by the app is an instance of
+    WebViewClientCompat (and therefore exposes AndroidX callbacks). This is
+    recorded each time the app sets a new WebViewClient via
+    WebView#setWebViewClient().
+  </summary>
+</histogram>
+
 <histogram name="Android.WebView.TargetSdkVersion" enum="AndroidApiLevel">
   <owner>changwan@chromium.org</owner>
   <summary>
@@ -2719,6 +2789,32 @@
   </summary>
 </histogram>
 
+<histogram name="AndroidSms.PWAInstallationResult"
+    enum="WebAppInstallResultCode">
+  <owner>azeemarshad@chromium.org</owner>
+  <summary>
+    Records installation result code when Android Messages for Web PWA is
+    installed through Multidevice setup or settings.
+  </summary>
+</histogram>
+
+<histogram name="AndroidSms.ServiceWorkerLifetime" units="ms">
+  <owner>azeemarshad@chromium.org</owner>
+  <summary>
+    Tracks the duration of time for which the Android Messages for Web Service-
+    Worker is handling background connection.
+  </summary>
+</histogram>
+
+<histogram name="AndroidSms.ServiceWorkerMessageDispatchStatus"
+    enum="BooleanSuccess">
+  <owner>azeemarshad@chromium.org</owner>
+  <summary>
+    Tracks dispatch success/failure status of the start streaming message sent
+    to the Android Messages for Web Service-Worker.
+  </summary>
+</histogram>
+
 <histogram name="AndroidTabCloseUndo.Toast"
     enum="AndroidTabCloseUndoToastEvent">
   <owner>dtrainor@chromium.org</owner>
@@ -3963,7 +4059,17 @@
   <owner>khmel@google.com</owner>
   <summary>
     Arc Silent Auth Code status. This status is set during the ARC
-    reauthorization flow.
+    Device/Primary Account reauthorization flow.
+  </summary>
+</histogram>
+
+<histogram name="Arc.OptInSilentAuthCode.SecondaryAccount"
+    enum="ArcOptInSilentAuthCode">
+  <owner>khmel@google.com</owner>
+  <summary>
+    Arc Silent Auth Code status. This status is set during the minting of an
+    auth code for a Secondary Account. It can be set for Secondary Account
+    signin or reauthorization.
   </summary>
 </histogram>
 
@@ -4058,6 +4164,14 @@
   </summary>
 </histogram>
 
+<histogram name="Arc.Secondary.Signin.Result" enum="ArcProvisioningResult">
+  <owner>khmel@google.com</owner>
+  <summary>
+    The result (success or the type of failure) of ARC Secondary Account signin/
+    reauthorization.
+  </summary>
+</histogram>
+
 <histogram name="Arc.ShareFilesOnExit" enum="ArcShareFilesOnExit">
   <owner>weifangsun@google.com</owner>
   <owner>djacobo@google.com</owner>
@@ -5351,6 +5465,15 @@
   </summary>
 </histogram>
 
+<histogram name="Assistant.EntryPoint" enum="AssistantSource"
+    expires_after="2019-11-01">
+  <owner>xiaohuic@chromium.org</owner>
+  <owner>meilinw@chromium.org</owner>
+  <summary>
+    Record the Assistant entry point where Assistant UI becomes visible.
+  </summary>
+</histogram>
+
 <histogram name="Assistant.HotwordEnableNotification" enum="BooleanHit">
   <owner>updowndota@chromium.org</owner>
   <summary>
@@ -7566,6 +7689,18 @@
   </summary>
 </histogram>
 
+<histogram name="Autofill.SaveCardReachedPersonalDataManager" enum="Boolean"
+    expires_after="2019-06-30">
+  <owner>jsaul@google.com</owner>
+  <owner>sebsg@chromium.org</owner>
+  <owner>mahmadi@chromium.org</owner>
+<!-- Name completed by histogram_suffixes name="AutofillCreditCardType" -->
+
+  <summary>
+    Records if the PersonalDataManager was notified to attempt saving of a card.
+  </summary>
+</histogram>
+
 <histogram name="Autofill.SaveCardWithFirstAndLastNameComplete" enum="Boolean">
   <owner>sebsg@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="AutofillCreditCardType" -->
@@ -8124,6 +8259,12 @@
   <summary>Whether the user changed autofilled field.</summary>
 </histogram>
 
+<histogram name="AutoScreenBrightness.UserAdjustment"
+    enum="AutoScreenBrightnessUserAdjustment">
+  <owner>jiameng@chromium.org</owner>
+  <summary>Type of user manual screen brightness adjustment.</summary>
+</histogram>
+
 <histogram base="true" name="BackgroundFetch.EventDispatchFailure.Dispatch"
     enum="ServiceWorkerStatusCode">
 <!-- Name completed by histogram_suffixes name="BackgroundFetchEvents" -->
@@ -8209,6 +8350,9 @@
 
 <histogram name="BackgroundFetch.RegistrationCreatedError"
     enum="BackgroundFetchError">
+  <obsolete>
+    Deprecated 10/2018 since DB tasks record this more accurately.
+  </obsolete>
   <owner>peter@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -8219,6 +8363,9 @@
 
 <histogram name="BackgroundFetch.RegistrationDeletedError"
     enum="BackgroundFetchError">
+  <obsolete>
+    Deprecated 10/2018 since DB tasks record this more accurately.
+  </obsolete>
   <owner>peter@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -8229,6 +8376,9 @@
 
 <histogram name="BackgroundFetch.SchedulerFinishedError"
     enum="BackgroundFetchError">
+  <obsolete>
+    Deprecated 10/2018 since DB tasks record this more accurately.
+  </obsolete>
   <owner>peter@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -8749,7 +8899,7 @@
 </histogram>
 
 <histogram name="Blink.Canvas.2DLayerBridgeIsDeferred" enum="BooleanSuccess"
-    expires_after="2018-12-31">
+    expires_after="2019-12-31">
   <owner>aaronhk@chromium.org</owner>
   <owner>fserb@chromium.org</owner>
   <summary>
@@ -8766,6 +8916,15 @@
   </summary>
 </histogram>
 
+<histogram name="Blink.Canvas.CreateImageBitmapSource"
+    enum="CanvasCreateImageBitmapSource" expires_after="2019-12-31">
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
+  <summary>
+    The source from which an ImageBitmap is created by a createImageBitmap call.
+  </summary>
+</histogram>
+
 <histogram name="Blink.Canvas.DrawImage" units="microseconds">
   <obsolete>
     Replaced with Blink.Canvas.DrawImage.Duration in 10/2018.
@@ -8795,6 +8954,16 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Blink.Canvas.DrawImage.SqrtNumberOfPixels"
+    units="sqrt(pixels)" expires_after="2019-12-31">
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
+  <summary>
+    Stores the square root of the number of pixels drawn into a Canvas.
+    Different histograms per CanvasImageSource.
+  </summary>
+</histogram>
+
 <histogram name="Blink.Canvas.GetImageData" units="microseconds">
   <obsolete>
     Replaced with Blink.Canvas.GetImageDataScaledDuration in 10/2018.
@@ -8826,6 +8995,26 @@
   </summary>
 </histogram>
 
+<histogram name="Blink.Canvas.GPUAccelerated2DCanvasDisableDeferralReason"
+    enum="CanvasGPUAccelerated2DCanvasDisableDeferralReason"
+    expires_after="2019-12-31">
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
+  <summary>
+    The reasons why a GPU accelerated canvas stopped deferring its rendering
+    operations.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Canvas.HibernationEvents" enum="CanvasHibernationEvent"
+    expires_after="2019-12-31">
+  <owner/>
+  <summary>
+    Records the occurrence of events related to 2D canvas GPU resource
+    hibernation.
+  </summary>
+</histogram>
+
 <histogram name="Blink.Canvas.IsComposited" enum="BooleanSuccess"
     expires_after="2020-10-24">
   <owner>aaronhk@chromium.org</owner>
@@ -8846,6 +9035,9 @@
 </histogram>
 
 <histogram name="Blink.Canvas.OffscreenCommitTimer" units="microseconds">
+  <obsolete>
+    Deprecated in 10/2018. Offscreen Canvas no longer needs commits.
+  </obsolete>
   <owner>junov@chromium.org</owner>
   <owner>xidachen@chromium.org</owner>
   <summary>
@@ -8890,6 +9082,16 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Blink.Canvas.RequestedImageMimeTypes"
+    enum="RequestedImageMimeType" expires_after="2019-12-31">
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
+  <summary>
+    Records the occurence of image file formats passed into toDataURL and toBlob
+    functions in canvas.
+  </summary>
+</histogram>
+
 <histogram name="Blink.Canvas.ResourceProviderIsAccelerated"
     enum="BooleanEnabled">
   <owner>aaronhk@chromium.org</owner>
@@ -9040,6 +9242,9 @@
 </histogram>
 
 <histogram name="Blink.Canvas.ToDataURL" units="microseconds">
+  <obsolete>
+    Replaced with Blink.Canvas.ToDataURLScaledDuration in 10/2018.
+  </obsolete>
   <owner>junov@chromium.org</owner>
   <summary>
     Time spent on 2D canvas toDataURL API call.
@@ -9052,6 +9257,20 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Blink.Canvas.ToDataURLScaledDuration"
+    units="microseconds/sqrt(pixels)" expires_after="2019-12-31">
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
+  <summary>
+    Time spent on 2D canvas toDataURL API call divided by the square root of the
+    total number of pixels of the image. Smaller is faster.
+
+    The idea behind this unit is that the bigger the area of a canvas the longer
+    the operation ToDataURL takes, so we want a way to measure the overall
+    performance regardless of the size of the canvas.
+  </summary>
+</histogram>
+
 <histogram name="Blink.CheckerableImageCount" enum="CheckerableImageType">
   <obsolete>
     Deprecated on 2018-05-04.
@@ -11497,6 +11716,10 @@
     number of these intervals that were &quot;janky&quot;. See
     https://docs.google.com/document/d/1vDSGFvJblh7yJ3U3RVB_7qZLubyfTbQdQjuN1GoUNkc/edit
     for more details.
+
+    On desktop platforms, this metric measures native events, as well as tasks
+    posted to the UI and IO threads of the browser process. On Android, this
+    metric only measures tasks posted to the UI and IO threads.
   </summary>
 </histogram>
 
@@ -11882,6 +12105,9 @@
 
 <histogram name="Canvas.CreateImageBitmapSource"
     enum="CanvasCreateImageBitmapSource">
+  <obsolete>
+    Replaced with Blink.Canvas.CreateImageBitmapSource in 10/2018.
+  </obsolete>
   <owner>junov@chromium.org</owner>
   <owner>zakerinasab@chromium.org</owner>
   <summary>
@@ -11903,6 +12129,10 @@
 
 <histogram name="Canvas.GPUAccelerated2DCanvasDisableDeferralReason"
     enum="CanvasGPUAccelerated2DCanvasDisableDeferralReason">
+  <obsolete>
+    Replaced with Blink.Canvas.GPUAccelerated2DCanvasDisableDeferralReason in
+    10/2018.
+  </obsolete>
   <owner>junov@chromium.org</owner>
   <summary>
     The reasons why a GPU accelerated canvas stopped deferring its rendering
@@ -11911,6 +12141,9 @@
 </histogram>
 
 <histogram name="Canvas.HibernationEvents" enum="CanvasHibernationEvent">
+  <obsolete>
+    Replaced with Blink.Canvas.HibernationEvents in 10/2018.
+  </obsolete>
   <owner>junov@chromium.org</owner>
   <summary>
     Records the occurrence of events related to 2D canvas GPU resource
@@ -11930,6 +12163,9 @@
 </histogram>
 
 <histogram name="Canvas.RequestedImageMimeTypes" enum="RequestedImageMimeType">
+  <obsolete>
+    Replaced with Blink.Canvas.RequestedImageMimeTypes in 10/2018.
+  </obsolete>
   <owner>xlai@chromium.org</owner>
   <summary>
     Records the occurence of image file formats passed into toDataURL and toBlob
@@ -13149,6 +13385,15 @@
   </summary>
 </histogram>
 
+<histogram name="ChromeOS.SystemTray.OpenHelpPageForManaged"
+    enum="CrosSystemTrayManagedType">
+  <owner>yamaguchi@chromium.org</owner>
+  <summary>
+    Type of the support page which user opened by clicking the indicator of
+    managed device type in the unified system tray bubble.
+  </summary>
+</histogram>
+
 <histogram name="ChromeOS.SystemTray.TimeToClick" units="ms">
   <owner>tetsui@chromium.org</owner>
   <summary>
@@ -16689,6 +16934,10 @@
 </histogram>
 
 <histogram name="CrashReport.CrashBackgroundUploadDelay" units="ms">
+  <obsolete>
+    Deprecated as of 03/2018 when Chrome for iOS stopped uploading crash dumps
+    in the background.
+  </obsolete>
   <owner>olivierrobin@chromium.org</owner>
   <owner>pkl@chromium.org</owner>
   <summary>
@@ -16698,6 +16947,10 @@
 </histogram>
 
 <histogram name="CrashReport.PendingReportsOnBackgroundWakeUp">
+  <obsolete>
+    Deprecated as of 03/2018 when Chrome for iOS stopped uploading crash dumps
+    in the background.
+  </obsolete>
   <owner>olivierrobin@chromium.org</owner>
   <owner>pkl@chromium.org</owner>
   <summary>
@@ -16937,6 +17190,11 @@
   </summary>
 </histogram>
 
+<histogram name="CryptAuth.DeviceSync.Result" enum="BooleanSuccess">
+  <owner>hansberry@chromium.org</owner>
+  <summary>Indicates success of performing a DeviceSync.</summary>
+</histogram>
+
 <histogram name="CryptAuth.DeviceSyncSoftwareFeaturesResult"
     enum="BooleanSuccess">
   <owner>hansberry@chromium.org</owner>
@@ -19609,6 +19867,19 @@
   </summary>
 </histogram>
 
+<histogram name="DemoMode.IdleLogoutWarningEvent"
+    enum="DemoModeIdleLogoutWarningEvent" expires_after="M73">
+  <owner>michaelpg@chromium.org</owner>
+  <owner>ovanieva@chromium.org</owner>
+  <owner>wzang@chromium.org</owner>
+  <summary>
+    Tracks whether the idle logout warning was canceled or proceeded to logout.
+    Note: the count of &quot;shown&quot; includes both cases, so the count of
+    &quot;shown and proceeded&quot; is equal to &quot;shown&quot; minus
+    &quot;canceled&quot;.
+  </summary>
+</histogram>
+
 <histogram name="DemoMode.ResourcesRemoval.Reason"
     enum="DemoModeResourcesRemovalReason" expires_after="M73">
   <owner>michaelpg@chromium.org</owner>
@@ -19666,6 +19937,9 @@
 
 <histogram name="DesktopIOSPromotion.DismissalReason"
     enum="DesktopIOSPromotionDismissalReason">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>mrefaat@chromium.org</owner>
   <summary>
     The dimissal reason of the desktop to iOS promotion entry point.
@@ -19676,6 +19950,9 @@
 
 <histogram name="DesktopIOSPromotion.ImpressionFromEntryPoint"
     enum="DesktopIOSPromotionEntryPoint">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>mrefaat@chromium.org</owner>
   <summary>
     The type of the desktop to iOS promotion that was shown to the user. This
@@ -19685,6 +19962,9 @@
 
 <histogram name="DesktopIOSPromotion.IOSSigninReason"
     enum="DesktopIOSPromotionEntryPoint">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>mrefaat@chromium.org</owner>
   <summary>
     [IOS] For users who sign-in on Chrome for iOS, log the type of the desktop
@@ -19699,6 +19979,9 @@
 
 <histogram name="DesktopIOSPromotion.OAuthTokenCompletion"
     enum="BooleanSuccess">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>justincohen@chromium.org</owner>
   <summary>
     Whether getting the OAuth token was successful for a desktop to iOS
@@ -19708,6 +19991,9 @@
 
 <histogram name="DesktopIOSPromotion.OAuthTokenResponseCode"
     enum="CombinedHttpResponseAndNetErrorCode">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>justincohen@chromium.org</owner>
   <summary>
     HTTP Response code returned by the server when trying to fetch the OAuth
@@ -19717,6 +20003,9 @@
 
 <histogram name="DesktopIOSPromotion.QueryPhoneNumberSucceeded"
     enum="BooleanSuccess">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>mrefaat@chromium.org</owner>
   <summary>
     Whether the SMS service api called from the desktop to iOS promotion
@@ -19726,6 +20015,9 @@
 </histogram>
 
 <histogram name="DesktopIOSPromotion.SendSMSSucceeded" enum="BooleanSuccess">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>mrefaat@chromium.org</owner>
   <summary>
     Whether the SMS service api initiated SMS sending successfully from the
@@ -19734,6 +20026,9 @@
 </histogram>
 
 <histogram name="DesktopIOSPromotion.SMSToSigninTime" units="hours">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>mrefaat@chromium.org</owner>
   <summary>
     [IOS] The difference between the client time of triggering the SMS action on
@@ -19748,6 +20043,9 @@
 </histogram>
 
 <histogram base="true" name="DesktopIOSPromotion.VariationSigninReason">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <owner>mrefaat@chromium.org</owner>
   <summary>
     [IOS] For users who sign-in on Chrome for iOS, log which variation of the
@@ -20771,6 +21069,9 @@
 </histogram>
 
 <histogram name="DNS.AttemptDiscarded">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -20781,6 +21082,9 @@
 </histogram>
 
 <histogram name="DNS.AttemptFailDuration" units="ms">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -20792,12 +21096,18 @@
 </histogram>
 
 <histogram name="DNS.AttemptFailure">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>The attempt that has not resolved the host successfully.</summary>
 </histogram>
 
 <histogram name="DNS.AttemptFirstFailure">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -20807,6 +21117,9 @@
 </histogram>
 
 <histogram name="DNS.AttemptFirstSuccess">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -20815,12 +21128,18 @@
 </histogram>
 
 <histogram name="DNS.AttemptSuccess">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>The attempt that has resolved the host successfully.</summary>
 </histogram>
 
 <histogram name="DNS.AttemptSuccessDuration" units="ms">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -23054,6 +23373,9 @@
 </histogram>
 
 <histogram name="Download.FrameGesture" enum="DownloadFrameGesture">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>yaoxia@chromium.org</owner>
   <summary>
     The type of frame in which a download occurs and whether the download
@@ -23176,15 +23498,18 @@
   </summary>
 </histogram>
 
-<histogram name="Download.IOSDownloadedFileAction" enum="DownloadedFileAction">
-  <owner>bdibello@chromium.org</owner>
+<histogram name="Download.IOSDownloadedFileAction" enum="DownloadedFileAction"
+    expires_after="2020-01-15">
+  <owner>eugenebut@chromium.org</owner>
   <summary>
     The action that a user takes on a file after it has been successfully
     downloaded on iOS.
   </summary>
 </histogram>
 
-<histogram name="Download.IOSDownloadedFileNetError" enum="NetErrorCodes">
+<histogram name="Download.IOSDownloadedFileNetError" enum="NetErrorCodes"
+    expires_after="2020-01-15">
+  <owner>eugenebut@chromium.org</owner>
   <owner>mrefaat@chromium.org</owner>
   <summary>
     Positive net error codes that happens in the case of download content fetch
@@ -23192,17 +23517,17 @@
   </summary>
 </histogram>
 
-<histogram name="Download.IOSDownloadedFileStatusCode">
-  <owner>stkhapugin@chromium.org</owner>
+<histogram name="Download.IOSDownloadedFileStatusCode"
+    expires_after="2020-01-15">
   <owner>eugenebut@chromium.org</owner>
-  <owner>stuartmorgan@chromium.org</owner>
+  <owner>stkhapugin@chromium.org</owner>
   <summary>
     HTTP status code returned when file download completes on iOS.
   </summary>
 </histogram>
 
 <histogram name="Download.IOSDownloadFileInBackground"
-    enum="DownloadFileInBackground">
+    enum="DownloadFileInBackground" expires_after="2020-01-15">
   <owner>eugenebut@chromium.org</owner>
   <summary>
     Logged when the download is completed (successfully or not) or in-progress
@@ -23212,13 +23537,16 @@
   </summary>
 </histogram>
 
-<histogram name="Download.IOSDownloadFileResult" enum="DownloadFileResult">
-  <owner>bdibello@chromium.org</owner>
+<histogram name="Download.IOSDownloadFileResult" enum="DownloadFileResult"
+    expires_after="2020-01-15">
+  <owner>eugenebut@chromium.org</owner>
   <summary>Result when a user attempts to download a file on iOS.</summary>
 </histogram>
 
-<histogram name="Download.IOSDownloadInstallDrivePromoShown" enum="Boolean">
+<histogram name="Download.IOSDownloadInstallDrivePromoShown" enum="Boolean"
+    expires_after="2020-01-15">
   <owner>eugenebut@chromium.org</owner>
+  <owner>pkl@chromium.org</owner>
   <summary>
     Logged when the download was successfully completed. Bool value indicates
     whether or not Install Google Drive promo was shown to the user.
@@ -23234,8 +23562,8 @@
 </histogram>
 
 <histogram name="Download.IOSDownloadPassKitResult"
-    enum="DownloadPassKitResult">
-  <owner>gchatz@chromium.org</owner>
+    enum="DownloadPassKitResult" expires_after="2020-01-15">
+  <owner>eugenebut@chromium.org</owner>
   <summary>
     Result when a user attempts to download a PassKit file on iOS.
   </summary>
@@ -23257,6 +23585,15 @@
   <summary>Result of an attempt to present Add Passes dialog on iOS.</summary>
 </histogram>
 
+<histogram name="Download.MainFrame.HasGesture" enum="Boolean">
+  <owner>yaoxia@chromium.org</owner>
+  <summary>
+    Whether the main frame download involves a transient user gesture. It is
+    only recorded for downloads originated from navigations or from HTML anchor
+    download attributes.
+  </summary>
+</histogram>
+
 <histogram name="Download.MaliciousDownloadClassified"
     enum="DownloadItem.DangerType">
   <owner>dtrainor@chromium.org</owner>
@@ -23940,6 +24277,18 @@
   </summary>
 </histogram>
 
+<histogram name="Download.Subframe.SandboxOriginAdGesture"
+    enum="SubframeDownloadSandboxOriginAdGesture">
+  <owner>yaoxia@chromium.org</owner>
+  <summary>
+    For a download that occurs in subframe, record whether the frame is
+    sandboxed, whether the origin is same to the top frame, whether it's an ad
+    subframe, and whether the download involves a transient user gesture. It is
+    only recorded for downloads originated from navigations or from HTML anchor
+    download attributes.
+  </summary>
+</histogram>
+
 <histogram name="Download.TargetConnectionSecurity"
     enum="DownloadConnectionSecurity">
   <owner>jialiul@chromium.org</owner>
@@ -25212,6 +25561,15 @@
   </summary>
 </histogram>
 
+<histogram name="Enterprise.EnrollmentAttestationBased"
+    enum="EnterpriseEnrollmentType">
+  <owner>drcrash@chromium.org</owner>
+  <summary>
+    Events related to attestation-based enrollment (Zero-Touch) of Chrome OS
+    devices.
+  </summary>
+</histogram>
+
 <histogram name="Enterprise.EnrollmentForced" enum="EnterpriseEnrollmentType">
   <owner>tnagel@chromium.org</owner>
   <summary>
@@ -25219,6 +25577,24 @@
   </summary>
 </histogram>
 
+<histogram name="Enterprise.EnrollmentForcedAttestationBased"
+    enum="EnterpriseEnrollmentType">
+  <owner>drcrash@chromium.org</owner>
+  <summary>
+    Events related to attestation-based re-enrollment (Auto RE) of Chrome OS
+    devices.
+  </summary>
+</histogram>
+
+<histogram name="Enterprise.EnrollmentForcedManualFallback"
+    enum="EnterpriseEnrollmentType">
+  <owner>drcrash@chromium.org</owner>
+  <summary>
+    Events related to manual fallback from attestation-based re-enrollment (Auto
+    RE) of Chrome OS devices.
+  </summary>
+</histogram>
+
 <histogram name="Enterprise.EnrollmentRecovery" enum="EnterpriseEnrollmentType">
   <owner>tnagel@chromium.org</owner>
   <summary>
@@ -25497,6 +25873,11 @@
   </summary>
 </histogram>
 
+<histogram name="Enterprise.ResourceCacheTiming" units="ms">
+  <owner>nikitapodguzov@chromium.org</owner>
+  <summary>The time to perform operations on the ResourceCache object.</summary>
+</histogram>
+
 <histogram base="true" name="Enterprise.RetrievePolicyResponse"
     enum="EnterpriseRetrievePolicyResponseType">
 <!-- Name completed by histogram_suffixes name="EnterpriseRetrievePolicyResponse" -->
@@ -33083,6 +33464,9 @@
 
 <histogram name="Extensions.WebRequest.ModifiedResponseHeaders"
     enum="WebRequestResponseHeaderType">
+  <obsolete>
+    Removed 11/2018 as this is no longer needed.
+  </obsolete>
   <owner>rockot@chromium.org</owner>
   <summary>
     Tracks whether any interesting response header modifications were made for
@@ -33121,8 +33505,41 @@
   </summary>
 </histogram>
 
+<histogram name="Extensions.WebRequest.SetCookieResponseHeaderChanged"
+    enum="BooleanChanged" expires_after="M72">
+  <owner>cduvall@chromium.org</owner>
+  <owner>karandeepb@chromium.org</owner>
+  <summary>
+    Whether the set-cookie response header was changed by an extension using the
+    Web Request API. Logged for every network request as long as one or more
+    enabled extensions is using a declarative or blocking filter to process
+    onHeadersReceived events.
+
+    This histogram is temporary, for investigating https://crbug.com/827582. It
+    can probably be removed by M72.
+  </summary>
+</histogram>
+
+<histogram name="Extensions.WebRequest.SetCookieResponseHeaderRemoved"
+    enum="BooleanRemoved" expires_after="M72">
+  <owner>cduvall@chromium.org</owner>
+  <owner>karandeepb@chromium.org</owner>
+  <summary>
+    Whether the set-cookie response header was removed by an extension using the
+    Web Request API. Logged for every network request as long as one or more
+    enabled extensions is using a declarative or blocking filter to process
+    onHeadersReceived events.
+
+    This histogram is temporary, for investigating https://crbug.com/827582. It
+    can probably be removed by M72.
+  </summary>
+</histogram>
+
 <histogram name="Extensions.WebRequest.SpecialHeadersRemoved"
     enum="WebRequestSpecialHeaderRemoval">
+  <obsolete>
+    Removed 11/2018 as this is no longer needed.
+  </obsolete>
   <owner>rockot@chromiumorg</owner>
   <summary>
     Whether either or both of the special Accept-Language or User-Agent request
@@ -33135,6 +33552,38 @@
   </summary>
 </histogram>
 
+<histogram name="Extensions.WebRequest.SpecialRequestHeadersChanged"
+    enum="WebRequestSpecialRequestHeaderModification" expires_after="M72">
+  <owner>cduvall@chromium.org</owner>
+  <owner>karandeepb@chromium.org</owner>
+  <summary>
+    Whether Accept-Language, Accept-Encoding, User-Agent, Cookie, Referer, or
+    mulitple of these request headers were changed by an extension using the Web
+    Request API. Logged for every network request as long as one or more enabled
+    extensions is using a declarative or blocking filter to process
+    onBeforeSendHeaders events.
+
+    This histogram is temporary, for investigating https://crbug.com/827582. It
+    can probably be removed by M72.
+  </summary>
+</histogram>
+
+<histogram name="Extensions.WebRequest.SpecialRequestHeadersRemoved"
+    enum="WebRequestSpecialRequestHeaderModification" expires_after="M72">
+  <owner>cduvall@chromium.org</owner>
+  <owner>karandeepb@chromium.org</owner>
+  <summary>
+    Whether Accept-Language, Accept-Encoding, User-Agent, Cookie, Referer, or
+    mulitple of these request headers were removed by an extension using the Web
+    Request API. Logged for every network request as long as one or more enabled
+    extensions is using a declarative or blocking filter to process
+    onBeforeSendHeaders events.
+
+    This histogram is temporary, for investigating https://crbug.com/827582. It
+    can probably be removed by M72.
+  </summary>
+</histogram>
+
 <histogram
     name="Extensions.WebRequest.WS_CookiesAreModifiedOnBeforeSendHeaders"
     units="boolean">
@@ -33197,8 +33646,7 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.WebRequestBlockingCount"
-    units="Number of extensions">
+<histogram name="Extensions.WebRequestBlockingCount" units="extensions">
   <owner>karandeepb@chromium.org</owner>
   <summary>
     Number of enabled extensions which have requested the
@@ -33208,6 +33656,16 @@
   </summary>
 </histogram>
 
+<histogram name="Extensions.WebRequestCount" units="extensions">
+  <owner>karandeepb@chromium.org</owner>
+  <owner>rdevlin.cronin@chromium.org</owner>
+  <summary>
+    Number of enabled extensions which have requested the &quot;webRequest&quot;
+    permission. Includes all kinds of extensions, including component and
+    unpacked extensions. Recorded during profile initialization.
+  </summary>
+</histogram>
+
 <histogram name="Extensions.WebRequestEventFoundFrame" units="boolean">
   <obsolete>
     Deprecated as of 11/2017. No longer relevant after refactoring.
@@ -35666,6 +36124,9 @@
 </histogram>
 
 <histogram name="GPU.AtExitMBytesAllocated" units="MB">
+  <obsolete>
+    Removed sometime around M55.
+  </obsolete>
   <owner>vmiura@chromium.org</owner>
   <summary>
     The amount of GPU memory that was currently allocated as of just before the
@@ -35674,6 +36135,9 @@
 </histogram>
 
 <histogram name="GPU.AtExitMBytesAllocatedMax" units="MB">
+  <obsolete>
+    Removed sometime around M55.
+  </obsolete>
   <owner>vmiura@chromium.org</owner>
   <summary>
     The maximum amount of GPU memory that had ever been allocated during the GPU
@@ -35682,6 +36146,9 @@
 </histogram>
 
 <histogram name="GPU.AtExitMBytesLimit" units="MB">
+  <obsolete>
+    Removed sometime around M55.
+  </obsolete>
   <owner>vmiura@chromium.org</owner>
   <summary>
     The GPU memory manager's limit on the amount of GPU memory that can be
@@ -35699,6 +36166,9 @@
 </histogram>
 
 <histogram name="GPU.AtExitWindowCount">
+  <obsolete>
+    Removed sometime around M55.
+  </obsolete>
   <owner>vmiura@chromium.org</owner>
   <summary>
     The number of windows that the GPU memory manager believed to exist as of
@@ -36086,6 +36556,15 @@
   <summary>The error states generated by OpenGL calls.</summary>
 </histogram>
 
+<histogram base="true" name="GPU.EstablishGpuChannelDuration" units="ms"
+    expires_after="M73">
+  <owner>kylechar@chromium.org</owner>
+  <summary>
+    The duration from when a request to establish a GPU channel arrives in
+    viz::GpuClient and to when the response for the request is sent.
+  </summary>
+</histogram>
+
 <histogram name="GPU.FenceSupport" enum="BooleanAvailable">
   <owner>reveman@chromium.org</owner>
   <summary>
@@ -37660,6 +38139,9 @@
 </histogram>
 
 <histogram name="History.TopHostsVisitsByRank" units="rank">
+  <obsolete>
+    Deprecated as of 11/2018, not used in production since 2/2018.
+  </obsolete>
   <owner>twifkak@chromium.org</owner>
   <owner>bengr@chromium.org</owner>
   <summary>
@@ -40844,6 +41326,21 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.TabGridMediator.DidDetachNilWebStateList"
+    enum="BooleanNil" expires_after="2019-05-01">
+  <owner>edchin@chromium.org</owner>
+  <owner>marq@chromium.org</owner>
+  <summary>
+    WebStateList should be guaranteed to be non-nil during a
+    WebStateListObserver callback. This histogram counts the frequency of this
+    invariant holding when webStateList:DidDetachWebState: is invoked in
+    TabGridMediator. Violations of this invariant is the cause of real-world
+    crashes (https://crbug.com/877792), which were not currently reproducible in
+    testing. This histogram is used to retain visibility of the severity of this
+    issue, while preventing the crashes with a no-op.
+  </summary>
+</histogram>
+
 <histogram name="IOS.TabSwitcher.PageChangeInteraction"
     enum="IOSTabSwitcherPageChangeInteraction">
   <owner>marq@chromium.org</owner>
@@ -45522,6 +46019,17 @@
   <summary>Counts of video decode errors reported to plugin.</summary>
 </histogram>
 
+<histogram base="true" name="Media.PepperVideoDecoderOutputPictureCount"
+    enum="MediaVideoHeight" expires_after="2019-11-01">
+  <owner>sandersd@chromium.org</owner>
+  <owner>dalecurtis@chromium.org</owner>
+  <summary>
+    Counts every output picture emitted to a PPAPI client, categorized by size
+    and decoder type. Flash will only use platform decoders, but NaCl clients
+    can use either decoder type.
+  </summary>
+</histogram>
+
 <histogram name="Media.PepperVideoDecoderPictureCount">
   <owner>ihf@chromium.org</owner>
   <owner>posciak@chromium.org</owner>
@@ -46354,6 +46862,9 @@
 </histogram>
 
 <histogram name="Media.Video.KeyFrameDistance" units="ms">
+  <obsolete>
+    Deprecated as of 11/2018 -- no longer used and expensive to monitor.
+  </obsolete>
   <owner>avayvod@chromium.org</owner>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
@@ -46919,6 +47430,9 @@
 </histogram>
 
 <histogram name="Media.VpxVideoDecoder.Vp9DecodeTime" units="ms">
+  <obsolete>
+    Deprecated 11/2018 -- shows nothing interesting; it's been static for years.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>Amount of time taken to decode one VP9 frame.</summary>
 </histogram>
@@ -47546,6 +48060,18 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.AudioService.ResidentSet" units="MiB"
+    expires_after="2019-01-31">
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The size of the resident memory in a audio service process. This is
+    influenced by factors we control (e.g. memory that is not accessed can be
+    swapped) and factors we don't control (e.g. an unrelated process using a lot
+    of memory can force memory in our process to be swapped). Recorded once per
+    UMA ping on Windows/Linux/ChromeOS/Android.
+  </summary>
+</histogram>
+
 <histogram name="Memory.AudioService.SharedMemoryFootprint" units="MB">
   <owner>marinaciocea@chromium.org</owner>
   <owner>maxmorin@chromium.org</owner>
@@ -47631,6 +48157,18 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.Browser.ResidentSet" units="MiB"
+    expires_after="2019-01-31">
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The size of the resident memory in the browser process. This is influenced
+    by factors we control (e.g. memory that is not accessed can be swapped) and
+    factors we don't control (e.g. an unrelated process using a lot of memory
+    can force memory in our process to be swapped). Recorded once per UMA ping
+    on Windows/Linux/ChromeOS/Android.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Browser.SharedMemoryFootprint" units="MB">
   <owner>erikchen@chromium.org</owner>
   <summary>
@@ -48303,6 +48841,18 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.Extension.ResidentSet" units="MiB"
+    expires_after="2019-01-31">
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The size of the resident memory in an extension process. This is influenced
+    by factors we control (e.g. memory that is not accessed can be swapped) and
+    factors we don't control (e.g. an unrelated process using a lot of memory
+    can force memory in our process to be swapped). Recorded once per UMA ping
+    on Windows/Linux/ChromeOS/Android.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Extension.SharedMemoryFootprint" units="MB">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
@@ -48371,6 +48921,17 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.Gpu.ResidentSet" units="MiB" expires_after="2019-01-31">
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The size of the resident memory in the GPU process. This is influenced by
+    factors we control (e.g. memory that is not accessed can be swapped) and
+    factors we don't control (e.g. an unrelated process using a lot of memory
+    can force memory in our process to be swapped). Recorded once per UMA ping
+    on Windows/Linux/ChromeOS/Android.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Gpu.SharedMemoryFootprint" units="MB">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
@@ -48561,6 +49122,83 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.ParkableString.CompressedSizeKb" units="KB">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Total size of compressed ParkableStrings, in KB. Recorded at the same time
+    as &quot;Memory.ParkableString.TotalSizeKb&quot;.
+  </summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.Compression.Latency"
+    units="microseconds">
+  <owner>lizeb@chromium.org</owner>
+  <summary>Time to compress a parkable string, in ms.</summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.Compression.SizeKb" units="KB">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Size of a compressed parkable string, recorded at compression time.
+  </summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.Compression.ThroughputMBps" units="MBps">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Size of a compressed parkable string, recorded at compression time.
+  </summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.CompressionRatio" units="KB">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Average compression ratio, 100 * compressed_size / initial_size, for all
+    compressed ParkableStrings. Recorded at the same time as
+    &quot;Memory.ParkableString.TotalSizeKb&quot;.
+  </summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.Decompression.Latency"
+    units="microseconds">
+  <owner>lizeb@chromium.org</owner>
+  <summary>Time to decompress a parkable string, in ms.</summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.Decompression.SizeKb" units="KB">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Original size of a compressed parkable string, recorded at decompression
+    time.
+  </summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.Decompression.ThroughputMBps"
+    units="MBps">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Original size of a compressed parkable string, recorded at decompression
+    time.
+  </summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.SavingsKb" units="KB">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Sum of memory saved by compression, in KB. Recorded at the same time as
+    &quot;Memory.ParkableString.TotalSizeKb&quot;.
+  </summary>
+</histogram>
+
+<histogram name="Memory.ParkableString.TotalSizeKb" units="KB">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Total size of ParkableStrings assuming no compression, in KB. Recorded 30s
+    after compression was triggered, provided that the renderer stayed
+    backgrounded.
+  </summary>
+</histogram>
+
 <histogram name="Memory.PepperFlashPlugin" units="KB">
   <obsolete>
     Deprecated 11/2017. No direct replacement.
@@ -48740,6 +49378,18 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.Renderer.ResidentSet" units="MiB"
+    expires_after="2019-01-31">
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The size of the resident memory in a renderer process. This is influenced by
+    factors we control (e.g. memory that is not accessed can be swapped) and
+    factors we don't control (e.g. an unrelated process using a lot of memory
+    can force memory in our process to be swapped). Recorded once per UMA ping
+    on Windows/Linux/ChromeOS/Android.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Renderer.SharedMemoryFootprint" units="MB">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
@@ -49363,6 +50013,18 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.Total.ResidentSet" units="MiB"
+    expires_after="2019-01-31">
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The size of the resident memory in all processes. This is influenced by
+    factors we control (e.g. memory that is not accessed can be swapped) and
+    factors we don't control (e.g. an unrelated process using a lot of memory
+    can force memory in our process to be swapped). Recorded once per UMA ping
+    on Windows/Linux/ChromeOS/Android.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Total.SharedMemoryFootprint" units="MB">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
@@ -49415,6 +50077,18 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.Utility.ResidentSet" units="MiB"
+    expires_after="2019-01-31">
+  <owner>fdoray@chromium.org</owner>
+  <summary>
+    The size of the resident memory in a utility process. This is influenced by
+    factors we control (e.g. memory that is not accessed can be swapped) and
+    factors we don't control (e.g. an unrelated process using a lot of memory
+    can force memory in our process to be swapped). Recorded once per UMA ping
+    on Windows/Linux/ChromeOS/Android.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Utility.SharedMemoryFootprint" units="MB">
   <owner>jam@chromium.org</owner>
   <summary>
@@ -50782,12 +51456,66 @@
   </summary>
 </histogram>
 
+<histogram name="MultiDevice.DeviceSyncService.FindEligibleDevices.Result"
+    enum="BooleanSuccess">
+  <owner>hansberry@chromium.org</owner>
+  <summary>Result of trying to find eligible devices.</summary>
+</histogram>
+
+<histogram
+    name="MultiDevice.DeviceSyncService.FindEligibleDevices.Result.FailureReason"
+    enum="MultiDevice_DeviceSyncService_DeviceSyncRequestFailureReason">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Breaks down the percentages of reasons when failure occurs on
+    FindEligibleDevices.
+  </summary>
+</histogram>
+
+<histogram name="MultiDevice.DeviceSyncService.ForceEnrollmentNow.Result"
+    enum="MultiDevice_DeviceSyncService_ForceCryptAuthOperationResult">
+  <owner>hansberry@chromium.org</owner>
+  <summary>Result for when ForceEnrollmentNow is called.</summary>
+</histogram>
+
+<histogram name="MultiDevice.DeviceSyncService.ForceSyncNow.Result"
+    enum="MultiDevice_DeviceSyncService_ForceCryptAuthOperationResult">
+  <owner>hansberry@chromium.org</owner>
+  <summary>Result for when ForceSyncNow is called.</summary>
+</histogram>
+
+<histogram
+    name="MultiDevice.DeviceSyncService.SetSoftwareFeatureState.Disable.FailedFeature"
+    enum="MultiDevice_DeviceSyncService_Features">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Breaks down which features failed when attempted to disable.
+  </summary>
+</histogram>
+
+<histogram
+    name="MultiDevice.DeviceSyncService.SetSoftwareFeatureState.Enable.FailedFeature"
+    enum="MultiDevice_DeviceSyncService_Features">
+  <owner>hansberry@chromium.org</owner>
+  <summary>Breaks down which features failed when attempted to enable.</summary>
+</histogram>
+
 <histogram name="MultiDevice.DeviceSyncService.SetSoftwareFeatureState.Result"
     enum="BooleanSuccess">
   <owner>hansberry@chromium.org</owner>
   <summary>Result of enabling and disabling features for devices.</summary>
 </histogram>
 
+<histogram
+    name="MultiDevice.DeviceSyncService.SetSoftwareFeatureState.Result.FailureReason"
+    enum="MultiDevice_DeviceSyncService_DeviceSyncRequestFailureReason">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Breaks down the percentages of reasons when failure occurs on
+    SetSoftwareFeatureState.
+  </summary>
+</histogram>
+
 <histogram name="MultiDevice.PostOOBESetupFlow.PageShown"
     enum="MultiDevice_PostOOBESetupFlow_Page">
   <owner>hansberry@chromium.org</owner>
@@ -50803,6 +51531,15 @@
   </summary>
 </histogram>
 
+<histogram name="MultiDevice.Setup.HostStatus"
+    enum="MultiDevice_Setup_HostStatus">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Breaks down percentages of host statuses. This metric is emitted to at the
+    creation of the user session, when the user logs in
+  </summary>
+</histogram>
+
 <histogram name="MultiDeviceSetup.OOBE.UserChoice"
     enum="MultiDeviceSetupOOBEUserChoice">
   <owner>hansberry@chromium.org</owner>
@@ -50819,6 +51556,17 @@
   <owner>jordynass@chromium.org</owner>
   <summary>
     Counts the number of each MultiDevice setup notification clicked by a user.
+    This metric should be compared with MultiDeviceSetup_NotificationShown.
+  </summary>
+</histogram>
+
+<histogram name="MultiDeviceSetup_NotificationDismissed"
+    enum="MultiDeviceSetupNotification">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Counts the number of each MultiDevice setup notification dismissed by a
+    user. This metric should be compared with
+    MultiDeviceSetup_NotificationShown.
   </summary>
 </histogram>
 
@@ -51586,6 +52334,16 @@
   </summary>
 </histogram>
 
+<histogram name="Navigation.DownloadPolicy" enum="NavigationDownloadPolicy"
+    expires_after="2019-11-01">
+  <owner>csharrison@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <summary>
+    When a navigation results in a download, logs the download policy applied to
+    that navigation.
+  </summary>
+</histogram>
+
 <histogram name="Navigation.EngagementTime.HTTP" units="ms">
   <owner>felt@chromium.org</owner>
   <summary>
@@ -51670,6 +52428,18 @@
   <summary>Whether the navigation led to a change of process or not.</summary>
 </histogram>
 
+<histogram name="Navigation.LoadIfNecessaryType"
+    enum="NavigationNeedsReloadType">
+  <owner>boliu@chromium.org</owner>
+  <owner>alexmos@chromium.org</owner>
+  <summary>
+    The type of the source of a load from LoadIfNecessary. Recorded when
+    LoadIfNecessary starts a page load. For example, on Android,
+    kRequestedByClient is recorded when user switch back to a tab with a dead
+    renderer, which causes the tab to reload.
+  </summary>
+</histogram>
+
 <histogram name="Navigation.MainFrameHasEmbeddedCredentials" enum="Boolean">
   <obsolete>
     Deprecated 03/2017 in Issue 703460.
@@ -54831,6 +55601,33 @@
   </summary>
 </histogram>
 
+<histogram name="Net.DNS.Android.AutoDohPrivate" enum="Boolean">
+  <owner>pauljensen@chromium.org</owner>
+  <summary>
+    For devices using Android private DNS, are their DNS servers known to
+    support DNS-over-HTTPS.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.Android.AutoDohPublic" enum="Boolean">
+  <owner>pauljensen@chromium.org</owner>
+  <summary>
+    For devices not using Android private DNS, are their DNS servers known to
+    support DNS-over-HTTPS, thus potential candidates for automatic upgrading
+    from regular DNS to DNS-over-HTTPS.
+  </summary>
+</histogram>
+
+<histogram name="Net.DNS.Android.DotExplicit" enum="Boolean">
+  <owner>pauljensen@chromium.org</owner>
+  <summary>
+    For devices using Android private DNS, was their DNS-over-TLS server
+    specified explicitly in their Android settings. When false, they were
+    automatically upgraded from the standard DNS protocol to DNS-over-TLS via
+    auto-detection.
+  </summary>
+</histogram>
+
 <histogram name="Net.DNS.DnsTask.ErrorBeforeFallback.Fast" enum="NetErrorCodes">
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
@@ -54877,6 +55674,9 @@
 </histogram>
 
 <histogram name="Net.DNS.JobQueueTime" units="ms">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -54886,6 +55686,9 @@
 </histogram>
 
 <histogram name="Net.DNS.JobQueueTimeAfterChange" units="ms">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -54896,6 +55699,9 @@
 </histogram>
 
 <histogram name="Net.DNS.ProcTask.FailureTime" units="ms">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -54904,6 +55710,9 @@
 </histogram>
 
 <histogram name="Net.DNS.ProcTask.SuccessTime" units="ms">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -54994,6 +55803,18 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Net.DNS.TotalTimeTyped" units="ms">
+<!-- Name completed by histogram_suffixes
+     name="DnsTotalTimeType" -->
+
+  <owner>pauljensen@chromium.org</owner>
+  <summary>
+    Duration of time since a HostResolverImpl::Resolve request to the time a
+    result is posted. Excludes canceled, evicted, and aborted requests. Includes
+    cache hits (recorded as 0). Excludes speculative requests.
+  </summary>
+</histogram>
+
 <histogram name="Net.DNS_Resolution_And_TCP_Connection_Latency">
   <obsolete>
     Deprecated- see Net.DNS_Resolution_And_TCP_Connection_Latency2
@@ -55637,9 +56458,9 @@
   </summary>
 </histogram>
 
-<histogram name="Net.FoundSystemTrustRootsAndroid" enum="Boolean"
-    expires_after="2018-08-30">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+<histogram name="Net.FoundSystemTrustRootsAndroid" enum="BooleanFound">
+  <owner>davidben@chromium.org</owner>
+  <owner>rsleevi@chromium.org</owner>
   <summary>
     Whether or not system installed trust anchors could be distinguished from
     user installed trust anchors. Recorded on first certificate verification on
@@ -56841,6 +57662,9 @@
 </histogram>
 
 <histogram name="Net.OSErrorsForGetAddrinfo" enum="ErrorCodesGetaddrinfo_All">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Positive error code that was returned by the system library
@@ -56851,6 +57675,9 @@
 
 <histogram name="Net.OSErrorsForGetAddrinfo_Linux"
     enum="ErrorCodesGetaddrinfo_Linux">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Positive error code that was returned by the system library
@@ -56860,6 +57687,9 @@
 
 <histogram name="Net.OSErrorsForGetAddrinfo_Mac"
     enum="ErrorCodesGetaddrinfo_Mac">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Positive error code that was returned by the system library
@@ -56869,6 +57699,9 @@
 
 <histogram name="Net.OSErrorsForGetAddrinfo_Win"
     enum="ErrorCodesGetaddrinfo_Win">
+  <obsolete>
+    Deprecated 11/2018.
+  </obsolete>
   <owner>mgersh@chromium.org</owner>
   <summary>
     Positive error code that was returned by the system library
@@ -58121,6 +58954,14 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.ClosedByPublicReset" enum="Boolean">
+  <owner>wub@chromium.org</owner>
+  <summary>
+    For a QUIC session that is closed by a public reset, this boolean shows
+    whether it is a public reset sent from a Google server or not.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.ClosedDuringInitializeSession" enum="Boolean"
     expires_after="2018-08-30">
   <owner>rch@chromium.org</owner>
@@ -59097,6 +59938,15 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicStreamFactory.AttemptMigrationBeforeHandshake"
+    enum="BooleanAttempted" expires_after="2020-11-01">
+  <owner>zhongyi@chromium.org</owner>
+  <summary>
+    Records if a new connection on the alternate network is attempted when a
+    connection fails before handshake is confirmed.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicStreamFactory.BadPacketLossEvents5"
     enum="QuicBadPacketLossEvents">
   <owner>rch@chromium.org</owner>
@@ -59127,6 +59977,15 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicStreamFactory.MigrationBeforeHandshake"
+    enum="BooleanSuccess" expires_after="2020-11-01">
+  <owner>zhongyi@chromium.org</owner>
+  <summary>
+    Status of the connection which is created for migration before handshake is
+    confirmed.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicStreamFactory.PublicResetsPostHandshake"
     units="resets">
   <owner>ckrasic@chromium.org</owner>
@@ -66745,6 +67604,15 @@
   </summary>
 </histogram>
 
+<histogram name="Notifications.NotifierType" enum="NotifierType">
+  <owner>tetsui@chromium.org</owner>
+  <owner>toshikikikuchi@google.com</owner>
+  <summary>
+    The number of times a notification was added for the various types of
+    sources.
+  </summary>
+</histogram>
+
 <histogram name="Notifications.PerNotificationActions"
     enum="NotificationActionType">
   <owner>dewittj@chromium.org</owner>
@@ -71899,6 +72767,24 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.CompressionRatio"
     units="%">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    100 times the ratio of network bytes received to network bytes the user
+    would have seen without data reduction proxy (not including headers) in a
+    page load that had its main resource loaded through data reduction proxy.
+    Recorded as a percent if the data reduction proxy saved the user data.
+    Recorded per page load when the user navigates away, hides the tab, or
+    backgrounds the app.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.CompressionRatio2"
+    units="%">
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -71914,6 +72800,22 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.Inflation"
     units="KB">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    The number of network kilobytes (not including headers) that the data
+    reduction proxy inflated for the user in a page load that had its main
+    resource was loaded through data reduction proxy. Recorded per page load
+    when the user navigates away, hides the tab, or backgrounds the app.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.Inflation2"
+    units="KB">
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -71927,6 +72829,23 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.InflationPercent"
     units="%">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    The inflation in network kilobytes (not including headers) the user saw due
+    to using data reduction proxy in a page load that had its main resource was
+    loaded through data reduction proxy. Recorded as a percent when the user saw
+    inflated data. Recorded per page load when the user navigates away, hides
+    the tab, or backgrounds the app.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.InflationPercent2"
+    units="%">
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -71941,6 +72860,22 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.NonProxied"
     units="KB">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    The number of network kilobytes that were not fetched through the data
+    reduction proxy (not including headers) in a page load that had its main
+    resource was loaded through data reduction proxy. Recorded per page load
+    when the user navigates away, hides the tab, or backgrounds the app.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.NonProxied2"
+    units="KB">
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -71954,6 +72889,22 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.Original"
     units="KB">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    The number of network kilobytes (not including headers) that the user would
+    have seen without using data reduction proxy in a page load that had its
+    main resource was loaded through data reduction proxy. Recorded per page
+    load when the user navigates away, hides the tab, or backgrounds the app.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.Original2"
+    units="KB">
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -71967,6 +72918,22 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.PercentProxied"
     units="%">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    The percent of network kilobytes (not including headers) in a page load that
+    went through data reduction proxy when the main resource was loaded through
+    data reduction proxy. Recorded per page load when the user navigates away,
+    hides the tab, or backgrounds the app.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.PercentProxied2"
+    units="%">
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -71980,6 +72947,22 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.Proxied"
     units="KB">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    The number of network kilobytes that were fetched through the data reduction
+    proxy (not including headers) in a page load that had its main resource was
+    loaded through data reduction proxy. Recorded per page load when the user
+    navigates away, hides the tab, or backgrounds the app.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.Proxied2"
+    units="KB">
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -71993,6 +72976,22 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.Savings"
     units="KB">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    The number of network kilobytes (not including headers) that the data
+    reduction proxy saved the user in a page load that had its main resource was
+    loaded through data reduction proxy. Recorded per page load when the user
+    navigates away, hides the tab, or backgrounds the app.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.Bytes.Network.Savings2"
+    units="KB">
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -72006,6 +73005,9 @@
 <histogram
     name="PageLoad.Clients.DataReductionProxy.Experimental.CompletedResources.Network.PercentProxied"
     units="%">
+  <obsolete>
+    Deprecated 10/2018
+  </obsolete>
   <owner>bengr@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <summary>
@@ -72016,6 +73018,20 @@
   </summary>
 </histogram>
 
+<histogram
+    name="PageLoad.Clients.DataReductionProxy.Experimental.CompletedResources.Network2"
+    units="%">
+  <owner>bengr@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <summary>
+    Records info about the completed resources loaded from network in a page
+    load that use data reduction proxy when the main resource was loaded through
+    data reduction proxy. Recorded per page load when the user navigates away,
+    hides the tab, or backgrounds the app. The number of proxies, non-proxied,
+    percent of proxied are recorded as suffixes.
+  </summary>
+</histogram>
+
 <histogram name="PageLoad.Clients.DelayNavigation.Delay.Actual" units="ms">
   <obsolete>
     Deprecated March 2018
@@ -73184,6 +74200,33 @@
   </summary>
 </histogram>
 
+<histogram name="PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime"
+    units="ms">
+  <owner>sadrul@chromium.org</owner>
+  <summary>
+    'Swap time' is the timestamp of the renderer submitting a CompositorFrame,
+    and 'Presentation time' is the timestamp of the frame becoming visible on
+    screen. This metric measures the duration between the swap-time and the
+    presentation-time. This is recorded only if a valid presentation-timestamp
+    is available. See PageLoad.Internal.Renderer.PresentationTime.Valid for how
+    often the presentation-timestamp is valid. This is reported only for
+    compositor-frames that report a paint-timing metric (e.g.
+    FirstContentfulPaint etc.), and after that frame has been displayed on
+    screen.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Internal.Renderer.PresentationTime.Valid"
+    enum="Boolean">
+  <owner>sadrul@chromium.org</owner>
+  <summary>
+    This boolean keeps track of whether a valid presentation-timestamp was
+    received or not. This is reported only for compositor-frames that report a
+    paint-timing metric (e.g. FirstContentfulPaint etc.), and after that frame
+    has been displayed on screen.
+  </summary>
+</histogram>
+
 <histogram name="PageLoad.Navigation.RedirectChainLength" units="urls">
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -74567,6 +75610,18 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.DynamicFormChanges" expires_after="M75">
+  <owner>dvadym@chromium.org</owner>
+  <owner>vabr@chromium.org</owner>
+  <summary>
+    Records a bitmask of password form changes after the first time this form is
+    seen by Password Manager. Recorded once per a form when the form is removed
+    from DOM. Bit 0 - changes in number of fields, bit 1 - changes in fields
+    renderer ids, bit 2 - changes in autocomplete attributes, bit 3 - changes in
+    form control types.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.EditsInSaveBubble"
     enum="PasswordManagerEditsInSaveBubbleEnum">
   <owner>battre@chromium.org</owner>
@@ -75975,6 +77030,14 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordProtection.PageZoomFactor">
+  <owner>drubery@chromium.org</owner>
+  <summary>
+    Reports the zoom factor for a login page, when the protected password is
+    entered.
+  </summary>
+</histogram>
+
 <histogram base="true" name="PasswordProtection.PasswordAlertModeOutcome"
     enum="PasswordProtectionRequestOutcome">
   <owner>jialiul@chromium.org</owner>
@@ -83101,7 +84164,9 @@
     reports the reason for disallowing it. If the preview is allowed, then this
     generally reports &quot;Previews Allowed&quot;. It may instead report
     &quot;Previews Allowed without server rule check&quot; for a preview that
-    expects to check server rules but they are not enabled.
+    expects to check server rules but they are not enabled. Recorded throughout
+    navigation at the beginning of each navigation, after each redirect, and
+    during commit.
   </summary>
 </histogram>
 
@@ -83232,6 +84297,11 @@
   </summary>
 </histogram>
 
+<histogram name="Previews.PageEndReason" enum="PageEndReason">
+  <owner>robertogden@chromium.org</owner>
+  <summary>Records why the page load ended on a given preview type.</summary>
+</histogram>
+
 <histogram name="Previews.ProcessHintsResult" enum="PreviewsProcessHintsResult">
   <owner>dougarnett@chromium.org</owner>
   <summary>
@@ -84549,6 +85619,62 @@
   </summary>
 </histogram>
 
+<histogram name="ProtoDB.DestroySuccess" enum="BooleanSuccess">
+  <owner>thildebr@chromium.org</owner>
+  <summary>Whether a ProtoDB Destroy call was successful or not.</summary>
+</histogram>
+
+<histogram name="ProtoDB.GetErrorStatus" enum="LevelDBStatus">
+  <owner>thildebr@chromium.org</owner>
+  <summary>
+    The LevelDB Status returned from a failed ProtoDatabase Get call.
+  </summary>
+</histogram>
+
+<histogram name="ProtoDB.GetFound" enum="Boolean">
+  <owner>thildebr@chromium.org</owner>
+  <summary>Whether a ProtoDB Get call found what was requested.</summary>
+</histogram>
+
+<histogram name="ProtoDB.GetSuccess" enum="BooleanSuccess">
+  <owner>thildebr@chromium.org</owner>
+  <summary>Whether a ProtoDB Get call was successful or not.</summary>
+</histogram>
+
+<histogram name="ProtoDB.InitStatus" enum="LevelDBStatus">
+  <owner>thildebr@chromium.org</owner>
+  <summary>The LevelDB Status from a ProtoDatabase Init call.</summary>
+</histogram>
+
+<histogram name="ProtoDB.LoadEntriesSuccess" enum="BooleanSuccess">
+  <owner>thildebr@chromium.org</owner>
+  <summary>Whether a ProtoDB LoadEntries call was successful or not.</summary>
+</histogram>
+
+<histogram name="ProtoDB.LoadKeysAndEntriesSuccess" enum="BooleanSuccess">
+  <owner>thildebr@chromium.org</owner>
+  <summary>
+    Whether a ProtoDB LoadKeysAndEntries call was successful or not.
+  </summary>
+</histogram>
+
+<histogram name="ProtoDB.LoadKeysSuccess" enum="BooleanSuccess">
+  <owner>thildebr@chromium.org</owner>
+  <summary>Whether a ProtoDB LoadKeys call was successful or not.</summary>
+</histogram>
+
+<histogram name="ProtoDB.UpdateErrorStatus" enum="LevelDBStatus">
+  <owner>thildebr@chromium.org</owner>
+  <summary>
+    The LevelDB Status returned from a failed Protodatabase UpdateEntries call.
+  </summary>
+</histogram>
+
+<histogram name="ProtoDB.UpdateSuccess" enum="BooleanSuccess">
+  <owner>thildebr@chromium.org</owner>
+  <summary>Whether a ProtoDB UpdateEntries call was successful or not.</summary>
+</histogram>
+
 <histogram name="ProximityAuth.BleWeaveConnectionResult"
     enum="ProximityAuth_BleWeaveConnectionResult">
   <owner>hansberry@chromium.org</owner>
@@ -89343,7 +90469,7 @@
 
 <histogram name="SafeBrowsing.ContentsSize.Height" units="DIPs"
     expires_after="M73">
-  <owner>jialiul@chrormium.org</owner>
+  <owner>jialiul@chromium.org</owner>
   <owner>nparker@chromium.org</owner>
   <summary>
     Records the height of content area when the user opens a new browser window
@@ -89353,7 +90479,7 @@
 
 <histogram name="SafeBrowsing.ContentsSize.Width" units="DIPs"
     expires_after="M73">
-  <owner>jialiul@chrormium.org</owner>
+  <owner>jialiul@chromium.org</owner>
   <owner>nparker@chromium.org</owner>
   <summary>
     Records the width of content area when the user opens a new browser window
@@ -89447,6 +90573,32 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.FontSize.Default" units="pts" expires_after="M73">
+  <owner>drubery@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>Records the default font size on user startup.</summary>
+</histogram>
+
+<histogram name="SafeBrowsing.FontSize.DefaultFixed" units="pts"
+    expires_after="M73">
+  <owner>drubery@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>Records the default fixed font size on user startup.</summary>
+</histogram>
+
+<histogram name="SafeBrowsing.FontSize.Minimum" units="pts" expires_after="M73">
+  <owner>drubery@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>Records the minimum font size on user startup.</summary>
+</histogram>
+
+<histogram name="SafeBrowsing.FontSize.MinimumLogical" units="pts"
+    expires_after="M73">
+  <owner>drubery@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>Records the minimum logical font size on user startup.</summary>
+</histogram>
+
 <histogram name="SafeBrowsing.GetV4HashHttpResponseOrErrorCode"
     enum="CombinedHttpResponseAndNetErrorCode">
   <obsolete>
@@ -96926,7 +98078,7 @@
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.FetchHandlerEndToFallbackNetwork"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) renderer process sends an IPC message to notify that
     a resource loading request needs to be fall back to network, to (b) browser
@@ -96943,7 +98095,7 @@
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.FetchHandlerEndToResponseReceived"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) renderer process sends an IPC message to notify that
     a promise of respondWith() is settled, to (b) browser process received the
@@ -96960,7 +98112,7 @@
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.FetchHandlerStartToFetchHandlerEnd"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) a fetch event is dispatched, to (b) respondWith() is
     settled for the fetch event, or fetch event dispatch is finished without
@@ -96976,7 +98128,7 @@
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.ForwardServiceWorkerToWorkerReady"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) a resource loading request is routed to service
     worker path, to (b) a service worker is ready to handle the request.
@@ -96991,7 +98143,7 @@
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.ResponseReceivedToCompleted"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) response headers from service worker are received,
     to (b) reading response body is completed. Recorded when a fetch event
@@ -97007,7 +98159,7 @@
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.StartToForwardServiceWorker"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) the start of a navigation request, to (b) the
     request is forwarded to a service worker code path. This includes looking up
@@ -97023,7 +98175,7 @@
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.WorkerReadyToFetchHandlerStart"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) browser process sends an IPC message to dispatch a
     fetch event, to (b) a renderer process received the IPC message and is about
@@ -97039,7 +98191,7 @@
     name="ServiceWorker.LoadTiming.Subresource.FetchHandlerEndToFallbackNetwork"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) service worker sends a mojo message to notify that a
     resource loading request needs to be fall back to network, to (b) the mojo
@@ -97056,7 +98208,7 @@
     name="ServiceWorker.LoadTiming.Subresource.FetchHandlerEndToResponseReceived"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) service worker sends a mojo message to notify that a
     promise of respondWith() is settled, to (b) the mojo message is received on
@@ -97073,7 +98225,7 @@
     name="ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) a subresource request is routed to the URLLoader (on
     a background thread) for service worker controlled loads starts handling a
@@ -97088,7 +98240,7 @@
     name="ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) response headers from service worker are received,
     to (b) reading response body is completed. Only recorded when a fetch event
@@ -97103,7 +98255,7 @@
     name="ServiceWorker.LoadTiming.Subresource.WorkerReadyToFetchHandlerEnd"
     units="ms" expires_after="2021-10-31">
   <owner>bashi@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     The time taken from (a) a fetch event is dispatched, to (b) respondWith() is
     settled for the fetch event, or fetch event dispatch is finished without
@@ -97149,8 +98301,11 @@
 <histogram name="ServiceWorker.MainResourceRequestDestination"
     enum="ServiceWorkerMainResourceRequestDestination"
     expires_after="2018-12-01">
+  <obsolete>
+    Removed 2018-11, see https://crbug.com/902100
+  </obsolete>
   <owner>falken@chromium.org</owner>
-  <owner>worker-dev@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
   <summary>
     Describes whether a main resource request (i.e., a request for a main frame,
     subframe, or shared worker) was routed to service worker or network and why.
@@ -100430,6 +101585,43 @@
   </summary>
 </histogram>
 
+<histogram name="Signin.LoadedIdentities.Count" units="identities"
+    expires_after="2019-11-01">
+  <owner>jlebel@chromium.org</owner>
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Counts the number of identities loaded by SSO library using the keychain
+    API. The metric is recorded every time SSO updates the identity list (either
+    on the first run, or when the cache is staled). See:
+    https://crbug.com/897470.
+  </summary>
+</histogram>
+
+<histogram name="Signin.LoadedIdentities.Duration" units="ms"
+    expires_after="2019-11-01">
+  <owner>jlebel@chromium.org</owner>
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Tracks the time it takes to load identities by SSO library using the
+    keychain API. The metric is recorded every time SSO updates the identity
+    list (either on the first run, or when the cache is staled). See:
+    https://crbug.com/897470.
+  </summary>
+</histogram>
+
+<histogram name="Signin.LoadedIdentities.DurationPerIdentity" units="ms"
+    expires_after="2019-11-01">
+  <owner>jlebel@chromium.org</owner>
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Tracks the time it takes to load one identity in average by SSO library
+    using the keychain API. This value is the total time taken by the keychain
+    API to finish, divided by the number of identities returned. The metrics is
+    recorded every time SSO updates the identity list (either on the first run,
+    or when the cache is staled). See: crbug.com/897470.
+  </summary>
+</histogram>
+
 <histogram name="Signin.LoadTokenFromDB" enum="SigninLoadTokenFromDB">
   <owner>droger@chromium.org</owner>
   <summary>
@@ -100597,6 +101789,41 @@
   </summary>
 </histogram>
 
+<histogram name="Signin.RefreshTokenRevoked.Source"
+    enum="SourceForRefreshTokenOperation">
+  <owner>droger@chromium.org</owner>
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Source for refresh token revocation. This is used to track the sources for
+    signing out of Google accounts and is required to validate that the browser
+    is not revoking tokens for large parts of the user population.
+  </summary>
+</histogram>
+
+<histogram name="Signin.RefreshTokenUpdated.ToInvalidToken.Source"
+    enum="SourceForRefreshTokenOperation">
+  <owner>droger@chromium.org</owner>
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Source for refresh token updated to invalid tokens. The refresh token is
+    updated to an permanently invalid token when the user attempts to sign out
+    of the primary account without turning off sync. This histogram is used to
+    track the sources for invalidating the token of the primary account and is
+    required to validate that the browser is not invalidating the token of the
+    primary account for large parts of the user population.
+  </summary>
+</histogram>
+
+<histogram name="Signin.RefreshTokenUpdated.ToValidToken.Source"
+    enum="SourceForRefreshTokenOperation">
+  <owner>droger@chromium.org</owner>
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Source for refresh token updated to valid tokens. This is used to track the
+    sources for adding Google accounts to the browser.
+  </summary>
+</histogram>
+
 <histogram name="Signin.RequestHeaderOperation.Dice"
     enum="SigninRequestHeaderOperation">
   <owner>msarda@chromium.org</owner>
@@ -103723,6 +104950,11 @@
   </summary>
 </histogram>
 
+<histogram name="SSL.MixedContentShown" enum="MixedContentType">
+  <owner>carlosil@chromium.org</owner>
+  <summary>Tracks when mixed content is displayed or run.</summary>
+</histogram>
+
 <histogram name="SSORecallPromo.AccountsAvailable">
   <owner>msarda@chromium.org</owner>
   <summary>
@@ -103792,6 +105024,19 @@
   </summary>
 </histogram>
 
+<histogram name="Stability.Android.ProcessedMinidumps"
+    enum="AndroidProcessedMinidumps" expires_after="M74">
+  <owner>mheikal@chromium.org</owner>
+  <owner>smaier@chromium.org</owner>
+  <owner>wnwen@chromium.org</owner>
+  <summary>
+    Records the number of minidumps processed by Crashpad, split by process
+    type. This metric is similar to one that could be computed server-side based
+    on received crash uploads; but the client-side metric also includes any
+    minidumps that were not successfully uploaded.
+  </summary>
+</histogram>
+
 <histogram name="Stability.Android.RendererCrash" enum="Boolean">
   <owner>wnwen@chromium.org</owner>
   <summary>
@@ -107993,6 +109238,15 @@
   </summary>
 </histogram>
 
+<histogram name="Sync.PostedClientToServerMessage"
+    enum="SyncClientToServerMessageContents">
+  <owner>mastiz@chromium.org</owner>
+  <summary>
+    Number of network requests issued by sync to the sync server, grouped by
+    content type.
+  </summary>
+</histogram>
+
 <histogram name="Sync.PreferenceAssociationTime" units="ms">
   <obsolete>
     Deprecated in M53.
@@ -109010,8 +110264,10 @@
   </summary>
 </histogram>
 
-<histogram name="Tab.PullDownGesture" enum="PullDownGestureAction">
-  <owner>jbbegue@google.com</owner>
+<histogram name="Tab.PullDownGesture" enum="PullDownGestureAction"
+    expires_after="2020-01-15">
+  <owner>gambard@chromium.org</owner>
+  <owner>kkhorimoto@chromium.org</owner>
   <summary>
     Record the action executed when the user performs a pull down gesture. This
     feature is currently iOS only.
@@ -109161,8 +110417,10 @@
   </summary>
 </histogram>
 
-<histogram name="Tab.StateAtRendererTermination" enum="TabForegroundState">
-  <owner>stuartmorgan@chromium.org</owner>
+<histogram name="Tab.StateAtRendererTermination" enum="TabForegroundState"
+    expires_after="2019-08-07">
+  <owner>olivierrobin@chromium.org</owner>
+  <owner>pkl@chromium.org</owner>
   <summary>
     The state (foreground/background) of a tab when its renderer is terminated.
   </summary>
@@ -124012,6 +125270,7 @@
   <suffix name="Local" label="Local"/>
   <suffix name="Server" label="Server (Google Payments)"/>
   <affected-histogram name="Autofill.DaysSinceLastUse.StoredCreditCard"/>
+  <affected-histogram name="Autofill.SaveCardReachedPersonalDataManager"/>
   <affected-histogram name="Autofill.SaveCardWithFirstAndLastNameComplete"/>
   <affected-histogram name="Autofill.SaveCardWithFirstAndLastNameOffered"/>
   <affected-histogram name="Autofill.StoredCreditCardCount"/>
@@ -124138,6 +125397,14 @@
   <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.Reshows"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="AutofillSaveCreditCardPromptRequestingExpirationDate"
+    separator=".">
+  <suffix name="RequestingExpirationDate"
+      label="Expiration date was explicitly requested in prompt"/>
+  <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.FirstShow"/>
+  <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.Reshows"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="AutofillSaveCreditCardPromptShow" separator=".">
   <suffix name="FirstShow"
       label="first time prompt is shown for a single credit card submit"/>
@@ -124245,7 +125512,7 @@
   <suffix name="ClickEvent" label="BackgroundFetchClickEvent"/>
   <suffix name="FailEvent" label="BackgroundFetchFailEvent"/>
   <suffix name="FetchedEvent" label="BackgroundFetchedEvent"/>
-  <suffix name="FetchSuccessEvent" label="BackgroundFetchSuccessEvent"/>
+  <suffix name="SuccessEvent" label="BackgroundFetchSuccessEvent"/>
   <affected-histogram name="BackgroundFetch.EventDispatchFailure.Dispatch"/>
   <affected-histogram name="BackgroundFetch.EventDispatchFailure.FindWorker"/>
   <affected-histogram name="BackgroundFetch.EventDispatchFailure.StartWorker"/>
@@ -124302,6 +125569,20 @@
   <affected-histogram name="WebRTC.Stun.BatchSuccessPercent.UnknownNAT"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="BlinkCanvasDrawImageSizeType" separator=".">
+  <suffix name="Canvas.CPU"/>
+  <suffix name="Canvas.GPU"/>
+  <suffix name="CssImage"/>
+  <suffix name="ImageBitmap"/>
+  <suffix name="ImageElement"/>
+  <suffix name="OffscreenCanvas.CPU"/>
+  <suffix name="OffscreenCanvas.GPU"/>
+  <suffix name="SVG"/>
+  <suffix name="Unknown"/>
+  <suffix name="Video"/>
+  <affected-histogram name="Blink.Canvas.DrawImage.SqrtNumberOfPixels"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="BlinkCanvasDrawImageType" separator=".">
   <suffix base="true" name="Canvas"/>
   <suffix base="true" name="CssImage"/>
@@ -124370,7 +125651,7 @@
   <affected-histogram name="Blink.Canvas.ToBlob.ScaledDuration"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="BlinkCanvasToDataURLTime" separator=".">
+<histogram_suffixes name="BlinkCanvasToDataURLMimeType" separator=".">
   <suffix name="BMP">
     <obsolete>
       Removed in Oct 2016
@@ -124399,7 +125680,7 @@
     </obsolete>
   </suffix>
   <suffix name="WEBP"/>
-  <affected-histogram name="Blink.Canvas.ToDataURL"/>
+  <affected-histogram name="Blink.Canvas.ToDataURLScaledDuration"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="BlinkCompositingLayerCount" separator=".">
@@ -125093,6 +126374,7 @@
   <suffix name="images" label="Images exceptions"/>
   <suffix name="javascript" label="JavaScript exceptions"/>
   <suffix name="keygen" label="Keygen exceptions"/>
+  <suffix name="media-engagement" label="Media engagement exceptions"/>
   <suffix name="media-stream-camera" label="Camera exceptions"/>
   <suffix name="media-stream-mic" label="Microphone exceptions"/>
   <suffix name="midi-sysex" label="Midi exceptions"/>
@@ -126208,6 +127490,9 @@
 
 <histogram_suffixes name="DesktopIOSEntryPoints" separator="."
     ordering="prefix">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <suffix name="BookmarksFootNote"/>
   <suffix name="BookmarksNewBubble"/>
   <suffix name="HistoryPage"/>
@@ -126218,6 +127503,9 @@
 
 <histogram_suffixes name="DesktopIOSPromotionSMSSent" separator="."
     ordering="prefix">
+  <obsolete>
+    Deprecated 11/2018 in issue 894963.
+  </obsolete>
   <suffix name="NoSMS" label="No SMS was sent from the promotion."/>
   <suffix name="SMSSent" label="SMS sent from the promotion."/>
   <affected-histogram name="DesktopIOSPromotion.IOSSigninReason"/>
@@ -126366,6 +127654,24 @@
   <affected-histogram name="DNS.ResolveSuccess"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="DnsTotalTimeType" separator=".">
+  <suffix name="Async" label="using Chromium's resolver"/>
+  <suffix name="AsyncPrivateSupportsDoh"
+      label="using Chromium's resolver, with a DNS server that supports
+             DNS-over-HTTPS"/>
+  <suffix name="System" label="using the system resolver"/>
+  <suffix name="SystemPrivate"
+      label="using the system resolver using private DNS"/>
+  <suffix name="SystemSupportsDoh"
+      label="using the system resolver, with a DNS server that supports
+             DNS-over-HTTPS. Note that on Android the DNS servers are not
+             passed to native code when private DNS is used so we cannot
+             detect when private DNS is used with servers that support
+             DNS-over-HTTPS, so this bucket will fall into the SystemPrivate
+             bucket."/>
+  <affected-histogram name="Net.DNS.TotalTimeTyped"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="DocsSpecific" separator=".">
   <suffix name="Docs" label="Only for docs.google.com"/>
   <affected-histogram name="appcache.MainResourceResponseRetrieval"/>
@@ -126622,6 +127928,37 @@
   <affected-histogram name="SiteEngagementService.EngagementScoreBucket"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="Enterprise.ResourceCacheTiming" separator=".">
+  <suffix name="Clear"
+      label="The time to perform the 'clear' operation on a ResourceCache,
+             which deletes all subkeys of given key."/>
+  <suffix name="Delete"
+      label="The time to perform the 'delete' operation on a ResourceCache,
+             which deletes given subkey."/>
+  <suffix name="FilterSubkeys"
+      label="The time to perform the 'filterSubkeys' operation on a
+             ResourceCache, which deletes filtered subkeys of given key."/>
+  <suffix name="Init"
+      label="The time to perform the initialization of a ResourceCache."/>
+  <suffix name="Load"
+      label="The time to perform the 'load' operation on a ResourceCache,
+             which loads the content of given key."/>
+  <suffix name="LoadAllSubkeys"
+      label="The time to perform the 'loadAllSubkeys' operation on a
+             ResourceCache, which loads the content of all subkeys of given
+             key."/>
+  <suffix name="PurgeOtherKeys"
+      label="The time to perform the 'purgeOtherKeys' operation on a
+             ResourceCache, which deletes all keys except given."/>
+  <suffix name="PurgeOtherSubkeys"
+      label="The time to perform the 'purgeOtherSubkeys' operation on a
+             ResourceCache, which deletes all subkeys except given."/>
+  <suffix name="Store"
+      label="The time to perform the 'store' operation on a ResourceCache,
+             which stores data under given key."/>
+  <affected-histogram name="Enterprise.ResourceCacheTiming"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="EnterpriseAutoEnrollmentType" separator=".">
   <suffix name="ForcedReenrollment" label="Forced Re-Enrollment"/>
   <suffix name="InitialEnrollment" label="Initial Enrollment Exchange"/>
@@ -127115,6 +128452,12 @@
   <affected-histogram name="GPU.BlacklistFeatureTestResultsWindows2"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="GpuChannelResponse" separator=".">
+  <suffix name="Failure" label="Failed Request"/>
+  <suffix name="Success" label="Successful Request"/>
+  <affected-histogram name="GPU.EstablishGpuChannelDuration"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="GraphicsPipeline" separator="." ordering="prefix">
   <suffix name="Browser" label="for browser process."/>
   <suffix name="Exo" label="for Exo clients."/>
@@ -127285,6 +128628,7 @@
 
 <histogram_suffixes name="HandshakeConfirmed" separator=".">
   <suffix name="HandshakeConfirmed" label="the handshake was confirmed"/>
+  <affected-histogram name="Net.QuicSession.ClosedByPublicReset"/>
   <affected-histogram name="Net.QuicSession.ConnectionCloseErrorCodeClient"/>
   <affected-histogram name="Net.QuicSession.ConnectionCloseErrorCodeServer"/>
 </histogram_suffixes>
@@ -127726,6 +129070,8 @@
       label="In product help for the Previews UI in the Android Omnibox."/>
   <suffix name="IPH_ReopenTab"
       label="In product help for reopening closed tabs."/>
+  <suffix name="IPH_TranslateMenuButton"
+      label="In product help translate menu button."/>
   <affected-histogram name="InProductHelp.NotifyEventReadyState"/>
   <affected-histogram name="InProductHelp.ShouldTriggerHelpUI"/>
 </histogram_suffixes>
@@ -127926,6 +129272,16 @@
   <affected-histogram name="LevelDB.ApproximateMemoryUse"/>
   <affected-histogram name="LevelDB.ApproximateMemTableMemoryUse"/>
   <affected-histogram name="LevelDB.Open"/>
+  <affected-histogram name="ProtoDB.DestroySuccess"/>
+  <affected-histogram name="ProtoDB.GetErrorStatus"/>
+  <affected-histogram name="ProtoDB.GetFound"/>
+  <affected-histogram name="ProtoDB.GetSuccess"/>
+  <affected-histogram name="ProtoDB.InitStatus"/>
+  <affected-histogram name="ProtoDB.LoadEntriesSuccess"/>
+  <affected-histogram name="ProtoDB.LoadKeysAndEntriesSuccess"/>
+  <affected-histogram name="ProtoDB.LoadKeysSuccess"/>
+  <affected-histogram name="ProtoDB.UpdateErrorStatus"/>
+  <affected-histogram name="ProtoDB.UpdateSuccess"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="LevelDBEnvBackupRestore" separator="">
@@ -128314,6 +129670,12 @@
   <affected-histogram name="Media.Controls.CTR"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="MediaDecoderType" separator=".">
+  <suffix name="HW" label="Platform decoder"/>
+  <suffix name="SW" label="Software decoder"/>
+  <affected-histogram name="Media.PepperVideoDecoderOutputPictureCount"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="MediaElementConfigurations" separator=".">
   <suffix name="FullscreenLandscape"/>
   <suffix name="FullscreenPortrait"/>
@@ -131351,10 +132713,18 @@
     separator=".">
   <suffix name="NonProxied"
       label="Resources not loaded through data reduction proxy."/>
+  <suffix name="PercentProxied"
+      label="Percent of resources loaded through data reduction proxy."/>
   <suffix name="Proxied"
       label="Resources loaded through data reduction proxy."/>
   <affected-histogram
-      name="PageLoad.Clients.DataReductionProxy.Experimental.CompletedResources.Network"/>
+      name="PageLoad.Clients.DataReductionProxy.Experimental.CompletedResources.Network">
+    <obsolete>
+      Deprecated 10/2018
+    </obsolete>
+  </affected-histogram>
+  <affected-histogram
+      name="PageLoad.Clients.DataReductionProxy.Experimental.CompletedResources.Network2"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="PageLoadMetricsClientsDocWrite" separator="."
@@ -132895,6 +134265,7 @@
   <suffix name="LitePage" label="Lite page previews"/>
   <suffix name="LitePageRedirect" label="Lite page redirection previews"/>
   <suffix name="LoFi" label="LoFi previews"/>
+  <suffix name="None" label="No preview was served"/>
   <suffix name="NoScript" label="NoScript previews"/>
   <suffix name="Offline" label="Offline previews"/>
   <suffix name="ResourceLoadingHints"
@@ -132904,6 +134275,7 @@
   <affected-histogram name="Previews.OmniboxAction"/>
   <affected-histogram name="Previews.OptimizationFilterStatus"/>
   <affected-histogram name="Previews.OptOut.UserOptedOut"/>
+  <affected-histogram name="Previews.PageEndReason"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="ProcessMemoryAllocator2" separator=".">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 957fa18..38fb63c 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -603,6 +603,14 @@
       The average time taken by the compositing phase in microseconds in the
       event period.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="Compositing.AverageRatio">
     <summary>
@@ -628,6 +636,14 @@
       The average time taken by the compositing commit at the end of the blink
       lifecycle, in microseconds in the event period.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="CompositingCommit.AverageRatio">
     <summary>
@@ -654,6 +670,14 @@
       The average time taken by all forced style recalcs and layouts in
       microseconds in the event period.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="ForcedStyleAndLayout.AverageRatio">
     <summary>
@@ -680,6 +704,14 @@
       The average time taken to compute IntersectionObserver observations in
       microseconds in the event period.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="IntersectionObservation.AverageRatio">
     <summary>
@@ -706,6 +738,14 @@
       The average time between a BeginMainFrame and the commit of paint results,
       in microseconds.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="MainFrame.WorstCase">
     <summary>
@@ -718,6 +758,14 @@
       The average time taken by the paint phase in microseconds in the event
       period.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="Paint.AverageRatio">
     <summary>
@@ -743,6 +791,14 @@
       The average time taken by the pre-paint phase in microseconds in the event
       period.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="PrePaint.AverageRatio">
     <summary>
@@ -768,6 +824,14 @@
       The average time taken by the style and layout phases in microseconds in
       the event period.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="StyleAndLayout.AverageRatio">
     <summary>
@@ -1426,6 +1490,13 @@
       the event, no recording is made. The first GSU of every scrolling sequence
       is excluded from this metric.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
 </event>
 
@@ -1456,6 +1527,13 @@
       a given scroll gesture event sequence. If no swap was induced by the
       event, no recording is made.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
 </event>
 
@@ -2782,6 +2860,13 @@
       render process used by other tabs. If this is undefined, TabPMF will be
       undefined.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="SubFrameProcessPMF.Excluded">
     <summary>
@@ -2790,11 +2875,25 @@
       the process has responsiblities outside the scope of the relevant tab. If
       this is non-zero, TabPMF will be undefined.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="SubFrameProcessPMF.Included">
     <summary>
       Number of render processes that contributed to SubFrameProcessPMF.Total.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="SubFrameProcessPMF.Total">
     <summary>
@@ -2803,6 +2902,13 @@
       hosts frames of other tabs, it isn't considered to be 'dedicated' and so
       it doesn't contribute to this total.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="TabPMF">
     <summary>
@@ -2811,6 +2917,13 @@
       responsible for hosting parts of this tab while hosting parts of other
       tabs.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
 </event>
 
@@ -3003,12 +3116,26 @@
       start to the time the DOMContentLoaded event is fired, for main frame
       documents.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="DocumentTiming.NavigationToLoadEventFired">
     <summary>
       Measures the time in milliseconds from navigation timing's navigation
       start to the time the load event is fired, for main frame documents.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="Experimental.InputToNavigationStart">
     <summary>
@@ -3031,6 +3158,13 @@
       start to the first meaningful paint (http://bit.ly/ttfmp-doc), for main
       frame documents.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="Experimental.PaintTiming.NavigationToLargestImagePaint">
     <summary>
@@ -3071,6 +3205,13 @@
       meaningful input per navigation. See https://goo.gl/tr1oTZ for a detailed
       explanation. In ms.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="InteractiveTiming.FirstInputTimestamp">
     <summary>
@@ -3222,12 +3363,26 @@
       start to the time when the page first paints content. A contentful paint
       includes a paint of text, image, SVG, or canvas.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="PaintTiming.NavigationToFirstPaint">
     <summary>
       Measures the time in milliseconds from navigation timing's navigation
       start to the time the first paint is performed.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="ParseTiming.NavigationToParseStart">
     <summary>
@@ -3660,7 +3815,7 @@
   <owner>ryansturm@chromium.org</owner>
   <summary>
     Previews related metrics associated with a page load. See
-    //componenets/previews/.
+    //components/previews/.
   </summary>
   <metric name="client_lofi">
     <summary>
@@ -3712,6 +3867,58 @@
   </metric>
 </event>
 
+<event name="PreviewsResourceLoadingHints" singular="True">
+  <owner>jegray@chromium.org</owner>
+  <summary>
+    Metrics associated with loading a resource loading hints based preview. This
+    is recorded when the URL's document finishes loading. See
+    //components/previews/.
+  </summary>
+  <metric name="blocked_high_priority">
+    <summary>
+      The number of high priority resource requests that were blocked by the
+      resource loading hints based preview while the URL's document was loading.
+    </summary>
+  </metric>
+  <metric name="blocked_low_priority">
+    <summary>
+      The number of low priority resource requests that were blocked by the
+      resource loading hints based preview while the URL's document was loading.
+    </summary>
+  </metric>
+  <metric name="blocked_medium_priority">
+    <summary>
+      The number of medium priority resource requests that were blocked by the
+      resource loading hints based preview while the URL's document was loading.
+    </summary>
+  </metric>
+  <metric name="blocked_very_high_priority">
+    <summary>
+      The number of very high priority resource requests that were blocked by
+      the resource loading hints based preview while the URL's document was
+      loading.
+    </summary>
+  </metric>
+  <metric name="blocked_very_low_priority">
+    <summary>
+      The number of very low priority resource requests that were blocked by the
+      resource loading hints based preview while the URL's document was loading.
+    </summary>
+  </metric>
+  <metric name="patterns_to_block_total">
+    <summary>
+      The total number of patterns to block included in the resource loading
+      hints based preview.
+    </summary>
+  </metric>
+  <metric name="patterns_to_block_used">
+    <summary>
+      The number of patterns that blocked at least one resource request in the
+      resource loading hints based preview while the URL's document was loading.
+    </summary>
+  </metric>
+</event>
+
 <event name="ResponsivenessMeasurement">
   <owner>npm@chromium.org</owner>
   <owner>tdresser@chromium.org</owner>
@@ -4038,12 +4245,28 @@
       The final SecurityLevel of the page before it is closed or another
       navigation occurs. Based on the enum security_state::SecurityLevel.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <enumeration/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="InitialSecurityLevel">
     <summary>
       The initial SecurityLevel of the page when the navigation commits. Based
       on the enum security_state::SecurityLevel.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <enumeration/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="ScoreDelta">
     <summary>
@@ -5308,4 +5531,36 @@
   </metric>
 </event>
 
+<event name="MixedContentAutoupgrade.ResourceRequest">
+  <owner>carlosil@chromium.org</owner>
+  <summary>
+    Status and Network error or HTTP response code for a resource request that
+    was autoupgraded to HTTPS as part of the mixed content autoupgrade
+    experiment.
+  </summary>
+  <metric name="Code">
+    <summary>
+      The HTTP response or network error code for an autoupgraded request.
+    </summary>
+  </metric>
+  <metric name="Status">
+    <summary>
+      An enum with 0 representing started, 1 failed, and 2 response received.
+    </summary>
+  </metric>
+</event>
+
+<event name="SSL.MixedContentShown">
+  <owner>carlosil@chromium.org</owner>
+  <summary>
+    Logged when mixed content is displayed on a site.
+  </summary>
+  <metric name="Type">
+    <summary>
+      A value of the MixedContentType enum, detailing the type of mixed content
+      included on the site.
+    </summary>
+  </metric>
+</event>
+
 </ukm-configuration>
diff --git a/tools/metrics/ukm/ukm_model.py b/tools/metrics/ukm/ukm_model.py
index 1149dc7..5bf4bec6 100644
--- a/tools/metrics/ukm/ukm_model.py
+++ b/tools/metrics/ukm/ukm_model.py
@@ -16,6 +16,48 @@
 
 _LOWERCASE_NAME_FN = lambda n: n.attributes['name'].value.lower()
 
+_ENUMERATION_TYPE = models.ObjectNodeType(
+    'enumeration',
+    attributes=[],
+    single_line=True)
+
+_QUANTILES_TYPE = models.ObjectNodeType(
+    'quantiles',
+    attributes=[
+      ('type', unicode),
+    ],
+    single_line=True)
+
+_INDEX_TYPE = models.ObjectNodeType(
+    'index',
+    attributes=[
+      ('fields', unicode),
+    ],
+    single_line=True)
+
+_STATISTICS_TYPE =  models.ObjectNodeType(
+    'statistics',
+    attributes=[],
+    children=[
+        models.ChildType('quantiles', _QUANTILES_TYPE, False),
+        models.ChildType('enumeration', _ENUMERATION_TYPE, False),
+    ])
+
+_HISTORY_TYPE =  models.ObjectNodeType(
+    'history',
+    attributes=[],
+    children=[
+        models.ChildType('index', _INDEX_TYPE, False),
+        models.ChildType('statistics', _STATISTICS_TYPE, True),
+    ])
+
+_AGGREGATION_TYPE =  models.ObjectNodeType(
+    'aggregation',
+    attributes=[],
+    children=[
+        models.ChildType('history', _HISTORY_TYPE, False),
+    ])
+
 _METRIC_TYPE =  models.ObjectNodeType(
     'metric',
     attributes=[
@@ -26,6 +68,7 @@
         models.ChildType('obsolete', _OBSOLETE_TYPE, False),
         models.ChildType('owners', _OWNER_TYPE, True),
         models.ChildType('summary', _SUMMARY_TYPE, False),
+        models.ChildType('aggregation', _AGGREGATION_TYPE, True),
     ])
 
 _EVENT_TYPE =  models.ObjectNodeType(
diff --git a/tools/perf/OWNERS b/tools/perf/OWNERS
index e89141fb..21aa6c8 100644
--- a/tools/perf/OWNERS
+++ b/tools/perf/OWNERS
@@ -1,16 +1,12 @@
 charliea@chromium.org
-nednguyen@google.com
+crouleau@chromium.org
+eyaich@chromium.org
 sullivan@chromium.org
+nednguyen@google.com
 
 # For changes related to ChromeOS.
 achuith@chromium.org
 
-# For changes related to generate_perf_json.
-eyaich@chromium.org
-
-# Simple rubberstamp-only oilpan-related changes.
-peria@chromium.org
-
 # For system health memory benchmarks & memory-infra related changes.
 perezju@chromium.org
 
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 7ead40f..29c7762c 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -2,7 +2,8 @@
 See https://bit.ly/update-benchmarks-info to make changes
 Benchmark name,Individual owners,Component,Documentation,Tags
 angle_perftests,"jmadill@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU>ANGLE,,
-blink_perf.accessibility,dmazzoni@chromium.org,['Blink>Accessibility'],https://bit.ly/blink-perf-benchmarks,
+base_perftests,"skyostil@chromium.org, gab@chromium.org",Internals>SequenceManager,https://chromium.googlesource.com/chromium/src/+/HEAD/base/README.md#performance-testing,
+blink_perf.accessibility,dmazzoni@chromium.org,Blink>Accessibility,https://bit.ly/blink-perf-benchmarks,
 blink_perf.bindings,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org",Blink>Bindings,https://bit.ly/blink-perf-benchmarks,
 blink_perf.canvas,fserb@chromium.org,Blink>Canvas,https://bit.ly/blink-perf-benchmarks,
 blink_perf.css,"futhark@chromium.org, andruud@chromium.org",Blink>CSS,https://bit.ly/blink-perf-benchmarks,
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index e7fe7f9f..57bbe3d 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -354,7 +354,7 @@
 
 
 @benchmark.Info(emails=['dmazzoni@chromium.org'],
-                component=['Blink>Accessibility'],
+                component='Blink>Accessibility',
                 documentation_url='https://bit.ly/blink-perf-benchmarks')
 class BlinkPerfAccessibility(_BlinkPerfBenchmark):
   tag = 'accessibility'
diff --git a/tools/perf/benchmarks/dromaeo.py b/tools/perf/benchmarks/dromaeo.py
index 59590fc..f178ed0 100644
--- a/tools/perf/benchmarks/dromaeo.py
+++ b/tools/perf/benchmarks/dromaeo.py
@@ -2,109 +2,23 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import json
-import math
-import os
-
-from core import perf_benchmark
+from benchmarks import press
 
 from telemetry import benchmark
-from telemetry import page as page_module
-from telemetry.page import legacy_page_test
-from telemetry import story
-from telemetry.value import scalar
 
-
-class _DromaeoMeasurement(legacy_page_test.LegacyPageTest):
-
-  def __init__(self):
-    super(_DromaeoMeasurement, self).__init__()
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    tab.WaitForJavaScriptCondition(
-        'window.document.getElementById("pause") &&' +
-        'window.document.getElementById("pause").value == "Run"',
-        timeout=120)
-
-    # Start spying on POST request that will report benchmark results, and
-    # intercept result data.
-    tab.ExecuteJavaScript("""
-        (function() {
-          var real_jquery_ajax_ = window.jQuery;
-          window.results_ = "";
-          window.jQuery.ajax = function(request) {
-            if (request.url == "store.php") {
-              window.results_ = decodeURIComponent(request.data);
-              window.results_ = window.results_.substring(
-                window.results_.indexOf("=") + 1,
-                window.results_.lastIndexOf("&"));
-              real_jquery_ajax_(request);
-            }
-          };
-        })();""")
-    # Starts benchmark.
-    tab.ExecuteJavaScript('window.document.getElementById("pause").click();')
-
-    tab.WaitForJavaScriptCondition('!!window.results_', timeout=600)
-
-    score = json.loads(tab.EvaluateJavaScript('window.results_ || "[]"'))
-
-    def Escape(k):
-      chars = [' ', '.', '-', '/', '(', ')', '*']
-      for c in chars:
-        k = k.replace(c, '_')
-      return k
-
-    def AggregateData(container, key, value):
-      if key not in container:
-        container[key] = {'count': 0, 'sum': 0}
-      container[key]['count'] += 1
-      container[key]['sum'] += math.log(value)
-
-    suffix = page.url[page.url.index('?') + 1:]
-
-    def AddResult(name, value):
-      important = False
-      if name == suffix:
-        important = True
-      results.AddValue(scalar.ScalarValue(
-          results.current_page, Escape(name), 'runs/s', value, important))
-
-    aggregated = {}
-    for data in score:
-      AddResult('%s/%s' % (data['collection'], data['name']),
-                data['mean'])
-
-      top_name = data['collection'].split('-', 1)[0]
-      AggregateData(aggregated, top_name, data['mean'])
-
-      collection_name = data['collection']
-      AggregateData(aggregated, collection_name, data['mean'])
-
-    for key, value in aggregated.iteritems():
-      AddResult(key, math.exp(value['sum'] / value['count']))
+from page_sets import dromaeo_pages
 
 
 @benchmark.Info(component='Blink>Bindings',
                 emails=['jbroman@chromium.org',
                          'yukishiino@chromium.org',
                          'haraken@chromium.org'])
-class DromaeoBenchmark(perf_benchmark.PerfBenchmark):
-
-  test = _DromaeoMeasurement
+# pylint: disable=protected-access
+class DromaeoBenchmark(press._PressBenchmark):
 
   @classmethod
   def Name(cls):
     return 'dromaeo'
 
   def CreateStorySet(self, options):
-    archive_data_file = '../page_sets/data/dromaeo.json'
-    ps = story.StorySet(
-        archive_data_file=archive_data_file,
-        base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.PUBLIC_BUCKET)
-    for query_param in ['dom-attr', 'dom-modify', 'dom-query', 'dom-traverse']:
-      url = 'http://dromaeo.com?%s' % query_param
-      ps.AddStory(page_module.Page(
-          url, ps, ps.base_dir, make_javascript_deterministic=False, name=url))
-    return ps
+    return dromaeo_pages.DromaeoStorySet()
diff --git a/tools/perf/benchmarks/jetstream.py b/tools/perf/benchmarks/jetstream.py
index 46aa5c8..4a7d5dc 100644
--- a/tools/perf/benchmarks/jetstream.py
+++ b/tools/perf/benchmarks/jetstream.py
@@ -17,80 +17,18 @@
 specialized optimization for one benchmark might make another benchmark slower.
 """
 
-import json
-import os
-
-from core import perf_benchmark
-
 from telemetry import benchmark
-from telemetry import page as page_module
-from telemetry.page import legacy_page_test
-from telemetry import story
-from telemetry.util import statistics
-from telemetry.value import list_of_scalar_values
 
+import page_sets
+from benchmarks import press
 
-class _JetstreamMeasurement(legacy_page_test.LegacyPageTest):
-
-  def __init__(self):
-    super(_JetstreamMeasurement, self).__init__()
-
-  def WillNavigateToPage(self, page, tab):
-    page.script_to_evaluate_on_commit = """
-        var __results = [];
-        var __real_log = window.console.log;
-        window.console.log = function() {
-          __results.push(Array.prototype.join.call(arguments, ' '));
-          __real_log.apply(this, arguments);
-        }
-        """
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    del page  # unused
-    tab.WaitForDocumentReadyStateToBeComplete()
-    tab.EvaluateJavaScript('JetStream.start()')
-    result = tab.WaitForJavaScriptCondition("""
-        (function() {
-          for (var i = 0; i < __results.length; i++) {
-            if (!__results[i].indexOf('Raw results: ')) return __results[i];
-          }
-          return null;
-        })();
-        """, timeout=60*20)
-    result = json.loads(result.partition(': ')[2])
-
-    all_score_lists = []
-    for k, v in result.iteritems():
-      results.AddValue(list_of_scalar_values.ListOfScalarValues(
-          results.current_page, k.replace('.', '_'), 'score', v['result'],
-          important=False))
-      # Collect all test scores to compute geometric mean.
-      for i, score in enumerate(v['result']):
-        if len(all_score_lists) <= i:
-          all_score_lists.append([])
-        all_score_lists[i].append(score)
-    all_scores = []
-    for score_list in all_score_lists:
-      all_scores.append(statistics.GeometricMean(score_list))
-    results.AddSummaryValue(list_of_scalar_values.ListOfScalarValues(
-        None, 'Score', 'score', all_scores))
 
 @benchmark.Info(emails=['hablich@chromium.org'],
                 component='Blink>JavaScript')
-class Jetstream(perf_benchmark.PerfBenchmark):
-  test = _JetstreamMeasurement
-
+class Jetstream(press._PressBenchmark): # pylint: disable=protected-access
   @classmethod
   def Name(cls):
     return 'jetstream'
 
   def CreateStorySet(self, options):
-    ps = story.StorySet(
-        archive_data_file='../page_sets/data/jetstream.json',
-        base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.INTERNAL_BUCKET)
-    ps.AddStory(page_module.Page(
-        'http://browserbench.org/JetStream/', ps, ps.base_dir,
-        make_javascript_deterministic=False,
-        name='http://browserbench.org/JetStream/'))
-    return ps
+    return page_sets.JetstreamStorySet()
diff --git a/tools/perf/benchmarks/kraken.py b/tools/perf/benchmarks/kraken.py
index e42317a..86b91d2 100644
--- a/tools/perf/benchmarks/kraken.py
+++ b/tools/perf/benchmarks/kraken.py
@@ -4,124 +4,22 @@
 
 """Runs Mozilla's Kraken JavaScript benchmark."""
 
-import json
-import os
-
-from core import perf_benchmark
-
 from telemetry import benchmark
-from telemetry import page as page_module
-from telemetry.page import legacy_page_test
-from telemetry import story
-from telemetry.value import list_of_scalar_values
-from telemetry.value import scalar
 
-
-DESCRIPTIONS = {
-    'ai-astar':
-        'This benchmark uses the [A* search algorithm]'
-        '(http://en.wikipedia.org/wiki/A*_search_algorithm) to automatically '
-        'plot an efficient path between two points, in the presence of '
-        'obstacles. Adapted from code by [Brian Gringstead]'
-        '(http://www.briangrinstead.com/blog/astar-search-algorithm-in-'
-        'javascript).',
-    'audio-beat-detection':
-        'This benchmark performs [beat detection]'
-        '(http://en.wikipedia.org/wiki/Beat_detection) on an Audio sample '
-        'using [code](http://beatdetektor.svn.sourceforge.net/viewvc'
-        '/beatdetektor/trunk/core/js/beatdetektor.js?revision=18&view=markup) '
-        'from [BeatDetektor](http://www.cubicproductions.com/index.php'
-        '?option=com_content&view=article&id=67&Itemid=82) and '
-        '[DSP.js](http://github.com/corbanbrook/dsp.js/).',
-    'audio-dft':
-        'This benchmark performs a [Discrete Fourier Transform]'
-        '(http://en.wikipedia.org/wiki/Discrete_Fourier_transform) on an '
-        'Audio sample using code from [DSP.js]'
-        '(http://github.com/corbanbrook/dsp.js).',
-    'audio-fft':
-        'This benchmark performs a [Fast Fourier Transform]'
-        '(http://en.wikipedia.org/wiki/Fast_Fourier_transform) on an Audio '
-        'sample using code from [DSP.js]'
-        '(http://github.com/corbanbrook/dsp.js/).',
-    'audio-oscillator':
-        'This benchmark generates a soundwave using code from [DSP.js]'
-        '(http://github.com/corbanbrook/dsp.js/).',
-    'imaging-darkroom':
-        'This benchmark performs a variety of photo manipulations such as '
-        'Fill, Brightness, Contrast, Saturation, and Temperature.',
-    'imaging-desaturate':
-        'This benchmark [desaturates]'
-        '(http://en.wikipedia.org/wiki/Colorfulness) a photo using code from '
-        '[Pixastic](http://www.pixastic.com/).',
-    'imaging-gaussian-blur':
-        'This benchmark performs a [Gaussian blur]'
-        '(http://en.wikipedia.org/wiki/Gaussian_blur) on a photo.',
-    'json-parse-financial':
-        'This benchmark parses [JSON](http://www.json.org) records.',
-    'json-stringify-tinderbox':
-        'This benchmark serializes [Tinderbox]'
-        '(http://tests.themasta.com/tinderboxpushlog/?tree=Firefox) build '
-        'data to [JSON](http://www.json.org).',
-}
-
-
-def _Mean(l):
-  return float(sum(l)) / len(l) if len(l) > 0 else 0.0
-
-
-class _KrakenMeasurement(legacy_page_test.LegacyPageTest):
-
-  def __init__(self):
-    super(_KrakenMeasurement, self).__init__()
-
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    tab.WaitForJavaScriptCondition(
-        'document.title.indexOf("Results") != -1', timeout=700)
-    tab.WaitForDocumentReadyStateToBeComplete()
-
-    result_dict = json.loads(tab.EvaluateJavaScript("""
-        var formElement = document.getElementsByTagName("input")[0];
-        decodeURIComponent(formElement.value.split("?")[1]);
-        """))
-    total = 0
-    for key in result_dict:
-      if key == 'v':
-        continue
-      results.AddValue(list_of_scalar_values.ListOfScalarValues(
-          results.current_page, key, 'ms', result_dict[key], important=False,
-          description=DESCRIPTIONS.get(key)))
-      total += _Mean(result_dict[key])
-
-    # TODO(tonyg/nednguyen): This measurement shouldn't calculate Total. The
-    # results system should do that for us.
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'Total', 'ms', total,
-        description='Total of the means of the results for each type '
-                    'of benchmark in [Mozilla\'s Kraken JavaScript benchmark]'
-                    '(http://krakenbenchmark.mozilla.org/)'))
+import page_sets
+from benchmarks import press
 
 
 @benchmark.Info(emails=['hablich@chromium.org'],
                 component='Blink>JavaScript')
-class Kraken(perf_benchmark.PerfBenchmark):
+class Kraken(press._PressBenchmark): # pylint: disable=protected-access
   """Mozilla's Kraken JavaScript benchmark.
 
   http://krakenbenchmark.mozilla.org/
   """
-  test = _KrakenMeasurement
-
   @classmethod
   def Name(cls):
     return 'kraken'
 
   def CreateStorySet(self, options):
-    ps = story.StorySet(
-        archive_data_file='../page_sets/data/kraken.json',
-        base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.PARTNER_BUCKET)
-    ps.AddStory(page_module.Page(
-        'http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html',
-        ps, ps.base_dir,
-        name='http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html'))
-    return ps
+    return page_sets.KrakenStorySet()
diff --git a/tools/perf/benchmarks/octane.py b/tools/perf/benchmarks/octane.py
index f0318d2..b0ecc9b 100644
--- a/tools/perf/benchmarks/octane.py
+++ b/tools/perf/benchmarks/octane.py
@@ -11,132 +11,21 @@
 Octane 2.0 consists of 17 tests, four more than Octane v1.
 """
 
-import os
-
-from core import perf_benchmark
-
 from telemetry import benchmark
-from telemetry import page as page_module
-from telemetry.page import legacy_page_test
-from telemetry import story
-from telemetry.util import statistics
-from telemetry.value import scalar
-
-_GB = 1024 * 1024 * 1024
-
-DESCRIPTIONS = {
-    'CodeLoad':
-        'Measures how quickly a JavaScript engine can start executing code '
-        'after loading a large JavaScript program, social widget being a '
-        'common example. The source for test is derived from open source '
-        'libraries (Closure, jQuery) (1,530 lines).',
-    'Crypto':
-        'Encryption and decryption benchmark based on code by Tom Wu '
-        '(1698 lines).',
-    'DeltaBlue':
-        'One-way constraint solver, originally written in Smalltalk by John '
-        'Maloney and Mario Wolczko (880 lines).',
-    'EarleyBoyer':
-        'Classic Scheme benchmarks, translated to JavaScript by Florian '
-        'Loitsch\'s Scheme2Js compiler (4684 lines).',
-    'Gameboy':
-        'Emulate the portable console\'s architecture and runs a demanding 3D '
-        'simulation, all in JavaScript (11,097 lines).',
-    'Mandreel':
-        'Runs the 3D Bullet Physics Engine ported from C++ to JavaScript via '
-        'Mandreel (277,377 lines).',
-    'NavierStokes':
-        '2D NavierStokes equations solver, heavily manipulates double '
-        'precision arrays. Based on Oliver Hunt\'s code (387 lines).',
-    'PdfJS':
-        'Mozilla\'s PDF Reader implemented in JavaScript. It measures decoding '
-        'and interpretation time (33,056 lines).',
-    'RayTrace':
-        'Ray tracer benchmark based on code by Adam Burmister (904 lines).',
-    'RegExp':
-        'Regular expression benchmark generated by extracting regular '
-        'expression operations from 50 of the most popular web pages '
-        '(1761 lines).',
-    'Richards':
-        'OS kernel simulation benchmark, originally written in BCPL by Martin '
-        'Richards (539 lines).',
-    'Splay':
-        'Data manipulation benchmark that deals with splay trees and exercises '
-        'the automatic memory management subsystem (394 lines).',
-}
-
-
-class _OctaneMeasurement(legacy_page_test.LegacyPageTest):
-
-  def __init__(self):
-    super(_OctaneMeasurement, self).__init__()
-
-  def WillNavigateToPage(self, page, tab):
-    total_memory = tab.browser.platform.GetSystemTotalPhysicalMemory()
-    if total_memory is not None and total_memory < 1 * _GB:
-      skipBenchmarks = '"zlib"'
-    else:
-      skipBenchmarks = ''
-    page.script_to_evaluate_on_commit = """
-        var __results = [];
-        var __real_log = window.console.log;
-        window.console.log = function(msg) {
-          __results.push(msg);
-          __real_log.apply(this, [msg]);
-        }
-        skipBenchmarks = [%s]
-        """ % (skipBenchmarks)
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    tab.WaitForJavaScriptCondition('window.completed', timeout=10)
-    tab.WaitForJavaScriptCondition(
-        '!document.getElementById("progress-bar-container")', timeout=1200)
-
-    results_log = tab.EvaluateJavaScript('__results')
-    all_scores = []
-    for output in results_log:
-      # Split the results into score and test name.
-      # results log e.g., "Richards: 18343"
-      score_and_name = output.split(': ', 2)
-      assert len(score_and_name) == 2, \
-        'Unexpected result format "%s"' % score_and_name
-      if 'Skipped' not in score_and_name[1]:
-        name = score_and_name[0]
-        score = float(score_and_name[1])
-        results.AddValue(scalar.ScalarValue(
-            results.current_page, name, 'score', score, important=False,
-            description=DESCRIPTIONS.get(name)))
-
-        # Collect all test scores to compute geometric mean.
-        all_scores.append(score)
-    total = statistics.GeometricMean(all_scores)
-    results.AddSummaryValue(
-        scalar.ScalarValue(None, 'Total.Score', 'score', total,
-                           description='Geometric mean of the scores of each '
-                           'individual benchmark in the Octane '
-                           'benchmark collection.'))
+import page_sets
+from benchmarks import press
 
 
 @benchmark.Info(emails=['hablich@chromium.org'],
                 component='Blink>JavaScript')
-class Octane(perf_benchmark.PerfBenchmark):
+class Octane(press._PressBenchmark): # pylint: disable=protected-access
   """Google's Octane JavaScript benchmark.
 
   http://chromium.github.io/octane/index.html?auto=1
   """
-  test = _OctaneMeasurement
-
   @classmethod
   def Name(cls):
     return 'octane'
 
   def CreateStorySet(self, options):
-    ps = story.StorySet(
-        archive_data_file='../page_sets/data/octane.json',
-        base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.PUBLIC_BUCKET)
-    ps.AddStory(page_module.Page(
-        'http://chromium.github.io/octane/index.html?auto=1',
-        ps, ps.base_dir, make_javascript_deterministic=False,
-        name='http://chromium.github.io/octane/index.html?auto=1'))
-    return ps
+    return page_sets.OctaneStorySet()
diff --git a/tools/perf/benchmarks/press.py b/tools/perf/benchmarks/press.py
new file mode 100644
index 0000000..87825a06
--- /dev/null
+++ b/tools/perf/benchmarks/press.py
@@ -0,0 +1,31 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Base class for a PressBenchmark.
+
+This benchmark manages both PressStory objects that
+implement javascript based metrics as well as can
+compute TMBv2 metrics.
+
+Example implementation:
+
+  FooPressBenchmark(press._PressBenchmark):
+    @classmethod
+    def Name(clas):
+      return Foo;
+
+    def CreateStorySet():
+      // Return a set of stories inheriting from
+      // page_sets.PressStory
+
+    def CreateCoreTimelineBasedMeasurementOptions()
+      // Implement to define tracing metrics you
+      // want on top of any javascript metrics
+      // implemented in your stories
+"""
+from core import perf_benchmark
+
+from measurements import dual_metric_measurement
+
+class _PressBenchmark(perf_benchmark.PerfBenchmark):
+  test = dual_metric_measurement.DualMetricMeasurement
diff --git a/tools/perf/benchmarks/rendering.py b/tools/perf/benchmarks/rendering.py
index e2951f2..ad026b9 100644
--- a/tools/perf/benchmarks/rendering.py
+++ b/tools/perf/benchmarks/rendering.py
@@ -4,17 +4,16 @@
 from core import perf_benchmark
 
 import page_sets
-from measurements import rendering
 from telemetry import benchmark
 from telemetry import story as story_module
-
+from telemetry.timeline import chrome_trace_category_filter
+from telemetry.web_perf import timeline_based_measurement
 
 @benchmark.Info(emails=['sadrul@chromium.org', 'vmiura@chromium.org'],
                 documentation_url='https://bit.ly/rendering-benchmarks',
                 component='Internals>GPU>Metrics')
 class RenderingDesktop(perf_benchmark.PerfBenchmark):
 
-  test = rendering.Rendering
   SUPPORTED_PLATFORMS = [story_module.expectations.ALL_DESKTOP]
 
   @classmethod
@@ -31,13 +30,18 @@
   def CreateStorySet(self, options):
     return page_sets.RenderingStorySet(platform='desktop')
 
+  def CreateCoreTimelineBasedMeasurementOptions(self):
+    category_filter = chrome_trace_category_filter.CreateLowOverheadFilter()
+    options = timeline_based_measurement.Options(category_filter)
+    options.SetTimelineBasedMetrics(['renderingMetric'])
+    return options
+
 
 @benchmark.Info(emails=['sadrul@chromium.org', 'vmiura@chromium.org'],
                 documentation_url='https://bit.ly/rendering-benchmarks',
                 component='Internals>GPU>Metrics')
 class RenderingMobile(perf_benchmark.PerfBenchmark):
 
-  test = rendering.Rendering
   SUPPORTED_PLATFORMS = [story_module.expectations.ALL_MOBILE]
 
   @classmethod
@@ -53,3 +57,10 @@
 
   def CreateStorySet(self, options):
     return page_sets.RenderingStorySet(platform='mobile')
+
+  def CreateCoreTimelineBasedMeasurementOptions(self):
+    category_filter = chrome_trace_category_filter.CreateLowOverheadFilter()
+    options = timeline_based_measurement.Options(category_filter)
+    options.config.enable_platform_display_trace = True
+    options.SetTimelineBasedMetrics(['renderingMetric'])
+    return options
diff --git a/tools/perf/benchmarks/speedometer.py b/tools/perf/benchmarks/speedometer.py
index da2a604..df2549f 100644
--- a/tools/perf/benchmarks/speedometer.py
+++ b/tools/perf/benchmarks/speedometer.py
@@ -15,106 +15,20 @@
 these types of operations depends on the speed of the DOM APIs, the JavaScript
 engine, CSS style resolution, layout, and other technologies.
 """
-
-import os
-
-from core import perf_benchmark
-
 from telemetry import benchmark
-from telemetry import page as page_module
-from telemetry.page import legacy_page_test
-from telemetry import story
-from telemetry.value import list_of_scalar_values
 
-from metrics import keychain_metric
-
-
-class SpeedometerMeasurement(legacy_page_test.LegacyPageTest):
-  enabled_suites = [
-      'VanillaJS-TodoMVC',
-      'EmberJS-TodoMVC',
-      'BackboneJS-TodoMVC',
-      'jQuery-TodoMVC',
-      'AngularJS-TodoMVC',
-      'React-TodoMVC',
-      'FlightJS-TodoMVC'
-  ]
-
-  def __init__(self):
-    super(SpeedometerMeasurement, self).__init__()
-
-  def CustomizeBrowserOptions(self, options):
-    keychain_metric.KeychainMetric.CustomizeBrowserOptions(options)
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    tab.WaitForDocumentReadyStateToBeComplete()
-    iterationCount = 10
-    # A single iteration on android takes ~75 seconds, the benchmark times out
-    # when running for 10 iterations.
-    if tab.browser.platform.GetOSName() == 'android':
-      iterationCount = 3
-
-    tab.ExecuteJavaScript("""
-        // Store all the results in the benchmarkClient
-        benchmarkClient._measuredValues = []
-        benchmarkClient.didRunSuites = function(measuredValues) {
-          benchmarkClient._measuredValues.push(measuredValues);
-          benchmarkClient._timeValues.push(measuredValues.total);
-        };
-        benchmarkClient.iterationCount = {{ count }};
-        startTest();
-        """,
-        count=iterationCount)
-    tab.WaitForJavaScriptCondition(
-        'benchmarkClient._finishedTestCount == benchmarkClient.testsCount',
-        timeout=600)
-    results.AddValue(list_of_scalar_values.ListOfScalarValues(
-        page, 'Total', 'ms',
-        tab.EvaluateJavaScript('benchmarkClient._timeValues'),
-        important=True))
-    results.AddValue(list_of_scalar_values.ListOfScalarValues(
-        page, 'RunsPerMinute', 'score',
-        tab.EvaluateJavaScript(
-            '[parseFloat(document.getElementById("result-number").innerText)];'
-        ),
-        important=True))
-
-    # Extract the timings for each suite
-    for suite_name in self.enabled_suites:
-      results.AddValue(list_of_scalar_values.ListOfScalarValues(
-          page, suite_name, 'ms',
-          tab.EvaluateJavaScript("""
-              var suite_times = [];
-              for(var i = 0; i < benchmarkClient.iterationCount; i++) {
-                suite_times.push(
-                    benchmarkClient._measuredValues[i].tests[{{ key }}].total);
-              };
-              suite_times;
-              """,
-              key=suite_name), important=False))
-    keychain_metric.KeychainMetric().AddResults(tab, results)
-
+import page_sets
+from benchmarks import press
 
 @benchmark.Info(emails=['hablich@chromium.org'],
                 component='Blink')
-class Speedometer(perf_benchmark.PerfBenchmark):
-  test = SpeedometerMeasurement
-
+class Speedometer(press._PressBenchmark): # pylint: disable=protected-access
   @classmethod
   def Name(cls):
     return 'speedometer'
 
   def CreateStorySet(self, options):
-    ps = story.StorySet(
-        base_dir=os.path.dirname(os.path.abspath(__file__)),
-        archive_data_file='../page_sets/data/speedometer.json',
-        cloud_storage_bucket=story.PUBLIC_BUCKET)
-    ps.AddStory(page_module.Page(
-        'http://browserbench.org/Speedometer/', ps, ps.base_dir,
-        make_javascript_deterministic=False,
-        name='http://browserbench.org/Speedometer/'))
-    return ps
-
+    return page_sets.SpeedometerStorySet()
 
 @benchmark.Info(emails=['hablich@chromium.org'],
                 component='Blink')
@@ -129,4 +43,5 @@
     return 'speedometer-future'
 
   def SetExtraBrowserOptions(self, options):
+    super(V8SpeedometerFuture, self).SetExtraBrowserOptions(options)
     options.AppendExtraBrowserArgs('--enable-features=V8VmFuture')
diff --git a/tools/perf/benchmarks/speedometer2.py b/tools/perf/benchmarks/speedometer2.py
index 5e32bda8..64e27ab 100644
--- a/tools/perf/benchmarks/speedometer2.py
+++ b/tools/perf/benchmarks/speedometer2.py
@@ -8,121 +8,21 @@
 import os
 import re
 
+from benchmarks import press
+
 from core import path_util
-from core import perf_benchmark
 
 from telemetry import benchmark
-from telemetry import page as page_module
-from telemetry.page import legacy_page_test
 from telemetry import story
-from telemetry.value import list_of_scalar_values
 
+from page_sets import speedometer2_pages
 
 _SPEEDOMETER_DIR = os.path.join(path_util.GetChromiumSrcDir(),
     'third_party', 'blink', 'perf_tests', 'speedometer')
-_SPEEDOMETER_SUITE_NAME_BASE = '{0}-TodoMVC'
-_SPEEDOMETER_SUITES = [
-  'VanillaJS',
-  'Vanilla-ES2015',
-  'Vanilla-ES2015-Babel-Webpack',
-  'React',
-  'React-Redux',
-  'EmberJS',
-  'EmberJS-Debug',
-  'BackboneJS',
-  'AngularJS',
-  'Angular2-TypeScript',
-  'VueJS',
-  'jQuery',
-  'Preact',
-  'Inferno',
-  'Elm',
-  'Flight'
-]
-
-
-class Speedometer2Measurement(legacy_page_test.LegacyPageTest):
-  def __init__(self, should_filter_suites, filtered_suite_names=None,
-               enable_smoke_test_mode=False):
-    super(Speedometer2Measurement, self).__init__()
-    self.should_filter_suites_ = should_filter_suites
-    self.filtered_suites_ = filtered_suite_names
-    self.enable_smoke_test_mode = enable_smoke_test_mode
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    tab.WaitForDocumentReadyStateToBeComplete()
-    iterationCount = 10
-    # A single iteration on android takes ~75 seconds, the benchmark times out
-    # when running for 10 iterations.
-    if tab.browser.platform.GetOSName() == 'android':
-      iterationCount = 3
-    # For a smoke test one iteration is sufficient
-    if self.enable_smoke_test_mode:
-      iterationCount = 1
-
-    if self.should_filter_suites_:
-      tab.ExecuteJavaScript("""
-        Suites.forEach(function(suite) {
-          suite.disabled = {{ filtered_suites }}.indexOf(suite.name) < 0;
-        });
-      """, filtered_suites=self.filtered_suites_)
-
-    enabled_suites = tab.EvaluateJavaScript("""
-      (function() {
-        var suitesNames = [];
-        Suites.forEach(function(s) {
-          if (!s.disabled)
-            suitesNames.push(s.name);
-        });
-        return suitesNames;
-       })();""")
-
-    tab.ExecuteJavaScript("""
-        // Store all the results in the benchmarkClient
-        var testDone = false;
-        var iterationCount = {{ count }};
-        var benchmarkClient = {};
-        var suiteValues = [];
-        benchmarkClient.didRunSuites = function(measuredValues) {
-          suiteValues.push(measuredValues);
-        };
-        benchmarkClient.didFinishLastIteration = function () {
-          testDone = true;
-        };
-        var runner = new BenchmarkRunner(Suites, benchmarkClient);
-        runner.runMultipleIterations(iterationCount);
-        """,
-        count=iterationCount)
-    tab.WaitForJavaScriptCondition('testDone', timeout=600)
-
-    if not self.should_filter_suites_:
-      results.AddValue(list_of_scalar_values.ListOfScalarValues(
-          page, 'Total', 'ms',
-          tab.EvaluateJavaScript('suiteValues.map(each => each.total)'),
-          important=True))
-      results.AddValue(list_of_scalar_values.ListOfScalarValues(
-          page, 'RunsPerMinute', 'score',
-          tab.EvaluateJavaScript('suiteValues.map(each => each.score)'),
-          important=True))
-
-    # Extract the timings for each suite
-    for suite_name in enabled_suites:
-      results.AddValue(list_of_scalar_values.ListOfScalarValues(
-          page, suite_name, 'ms',
-          tab.EvaluateJavaScript("""
-              var suite_times = [];
-              for(var i = 0; i < iterationCount; i++) {
-                suite_times.push(
-                    suiteValues[i].tests[{{ key }}].total);
-              };
-              suite_times;
-              """,
-              key=suite_name), important=False))
-
 
 @benchmark.Info(emails=['hablich@chromium.org'],
                 component='Blink')
-class Speedometer2(perf_benchmark.PerfBenchmark):
+class Speedometer2(press._PressBenchmark): # pylint: disable=protected-access
   """Speedometer2 Benchmark.
 
   Runs all the speedometer 2 suites by default. Add --suite=<regex> to filter
@@ -136,29 +36,15 @@
   def Name(cls):
     return 'speedometer2'
 
-  @staticmethod
-  def GetFullSuiteName(name):
-    return _SPEEDOMETER_SUITE_NAME_BASE.format(name)
-
-  @staticmethod
-  def GetSuites(suite_regex):
-    if not suite_regex:
-      return []
-    exp = re.compile(suite_regex)
-    return [name for name in _SPEEDOMETER_SUITES
-            if exp.search(Speedometer2.GetFullSuiteName(name))]
-
-  def CreatePageTest(self, options):
-      should_filter_suites = bool(options.suite)
-      filtered_suite_names = map(Speedometer2.GetFullSuiteName,
-          Speedometer2.GetSuites(options.suite))
-      return Speedometer2Measurement(should_filter_suites, filtered_suite_names,
-                                     self.enable_smoke_test_mode)
-
   def CreateStorySet(self, options):
+    should_filter_suites = bool(options.suite)
+    filtered_suite_names = map(
+        speedometer2_pages.Speedometer2Story.GetFullSuiteName,
+            speedometer2_pages.Speedometer2Story.GetSuites(options.suite))
+
     ps = story.StorySet(base_dir=_SPEEDOMETER_DIR)
-    ps.AddStory(page_module.Page(
-       'file://InteractiveRunner.html', ps, ps.base_dir, name='Speedometer2'))
+    ps.AddStory(speedometer2_pages.Speedometer2Story(ps, should_filter_suites,
+        filtered_suite_names, self.enable_smoke_test_mode))
     return ps
 
   @classmethod
@@ -170,7 +56,7 @@
   def ProcessCommandLineArgs(cls, parser, args):
     if args.suite:
       try:
-        if not Speedometer2.GetSuites(args.suite):
+        if not speedometer2_pages.Speedometer2Story.GetSuites(args.suite):
           raise parser.error('--suite: No matches.')
       except re.error:
         raise parser.error('--suite: Invalid regex.')
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index 406ddd1..5f954561 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -80,10 +80,12 @@
   # crbug.com/696824
   'system_health.memory_desktop/load:news:qq',
   # crbug.com/893615
+  'system_health.memory_desktop/browse:media:pinterest',
+  'system_health.memory_desktop/browse:media:youtube',
+  'system_health.memory_desktop/browse:search:google_india',
+  'system_health.memory_desktop/load:games:alphabetty',
   'system_health.memory_desktop/load:news:cnn',
   'system_health.memory_desktop/load:tools:stackoverflow',
-  'system_health.memory_desktop/load:games:alphabetty',
-  'system_health.memory_desktop/browse:search:google_india',
 
   # crbug.com/698006
   'system_health.memory_desktop/load:tools:drive',
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn
index 712c02f..fc1c43b 100644
--- a/tools/perf/chrome_telemetry_build/BUILD.gn
+++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -4,7 +4,8 @@
 
 import("//build/config/compiler/compiler.gni")
 if (is_android) {
-  import("//build/config/android/config.gni")  # For public_android_sdk
+  # Pull in enable_chrome_android_internal and public_android_sdk
+  import("//build/config/android/config.gni")
 }
 if (is_chromeos) {
   import("//build/config/chromeos/rules.gni")
@@ -19,14 +20,18 @@
   data = []
 
   if (is_android) {
-    data_deps += [ "//chrome/android:chrome_public_apk" ]
+    if (enable_chrome_android_internal) {
+      data_deps += [ "//clank:telemetry_clank_test" ]
+    } else {
+      data_deps += [ "//chrome/android:chrome_public_apk" ]
 
-    if (public_android_sdk) {
-      data_deps += [
-        "//android_webview:system_webview_apk",
-        "//android_webview/tools/system_webview_shell:system_webview_shell_apk",
-        "//chrome/android:monochrome_public_apk",
-      ]
+      if (public_android_sdk) {
+        data_deps += [
+          "//android_webview:system_webview_apk",
+          "//android_webview/tools/system_webview_shell:system_webview_shell_apk",
+          "//chrome/android:monochrome_public_apk",
+        ]
+      }
     }
   } else {
     data_deps += [ "//chrome" ]
@@ -83,9 +88,7 @@
     "//third_party/catapult:telemetry_chrome_test_support",
   ]
   if (!is_android) {
-    data_deps += [
-      "//third_party/catapult/telemetry:bitmaptools",
-    ]
+    data_deps += [ "//third_party/catapult/telemetry:bitmaptools" ]
   }
 
   data = [
diff --git a/tools/perf/contrib/cluster_telemetry/rendering_ct.py b/tools/perf/contrib/cluster_telemetry/rendering_ct.py
index eee6d16..35c33ba 100644
--- a/tools/perf/contrib/cluster_telemetry/rendering_ct.py
+++ b/tools/perf/contrib/cluster_telemetry/rendering_ct.py
@@ -4,9 +4,10 @@
 
 from contrib.cluster_telemetry import ct_benchmarks_util
 from contrib.cluster_telemetry import page_set
+from telemetry.timeline import chrome_trace_category_filter
+from telemetry.web_perf import timeline_based_measurement
 
 from core import perf_benchmark
-from measurements import rendering
 
 def ScrollToEndOfPage(action_runner):
   action_runner.Wait(1)
@@ -19,8 +20,6 @@
 
   options = {'upload_results': True}
 
-  test = rendering.Rendering
-
   @classmethod
   def Name(cls):
     return 'rendering.cluster_telemetry'
@@ -37,3 +36,9 @@
     return page_set.CTPageSet(
         options.urls_list, options.user_agent, options.archive_data_file,
         run_page_interaction_callback=ScrollToEndOfPage)
+
+  def CreateCoreTimelineBasedMeasurementOptions(self):
+    category_filter = chrome_trace_category_filter.CreateLowOverheadFilter()
+    options = timeline_based_measurement.Options(category_filter)
+    options.SetTimelineBasedMetrics(['renderingMetric'])
+    return options
diff --git a/tools/perf/contrib/cluster_telemetry/repaint.py b/tools/perf/contrib/cluster_telemetry/repaint.py
index e7d0fd8..ed88aa6 100644
--- a/tools/perf/contrib/cluster_telemetry/repaint.py
+++ b/tools/perf/contrib/cluster_telemetry/repaint.py
@@ -5,16 +5,15 @@
 from contrib.cluster_telemetry import ct_benchmarks_util
 from contrib.cluster_telemetry import page_set
 from contrib.cluster_telemetry import repaint_helpers
+from telemetry.timeline import chrome_trace_category_filter
+from telemetry.web_perf import timeline_based_measurement
 
 from core import perf_benchmark
-from measurements import rendering
 
 
 class RepaintCT(perf_benchmark.PerfBenchmark):
   """Measures repaint performance for Cluster Telemetry."""
 
-  test = rendering.Rendering
-
   @classmethod
   def Name(cls):
     return 'repaint_ct'
@@ -41,3 +40,9 @@
     return page_set.CTPageSet(
         options.urls_list, options.user_agent, options.archive_data_file,
         run_page_interaction_callback=repaint_helpers.WaitThenRepaint)
+
+  def CreateCoreTimelineBasedMeasurementOptions(self):
+    category_filter = chrome_trace_category_filter.CreateLowOverheadFilter()
+    options = timeline_based_measurement.Options(category_filter)
+    options.SetTimelineBasedMetrics(['renderingMetric'])
+    return options
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index ddb8b30a..d70b573 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -218,6 +218,11 @@
           'extra_args': [
               '--shard-timeout=300'
           ],
+        },
+        {
+          'isolate': 'base_perftests',
+          'num_shards': 1,
+          'telemetry': False,
         }
       ],
       'platform': 'android',
@@ -338,6 +343,11 @@
           'isolate': 'views_perftests',
           'num_shards': 1,
           'telemetry': False,
+        },
+        {
+          'isolate': 'base_perftests',
+          'num_shards': 1,
+          'telemetry': False,
         }
       ],
       'platform': 'win',
@@ -500,6 +510,11 @@
           'isolate': 'media_perftests',
           'num_shards': 1,
           'telemetry': False,
+        },
+        {
+          'isolate': 'base_perftests',
+          'num_shards': 1,
+          'telemetry': False,
         }
       ],
       'platform': 'linux',
@@ -534,6 +549,11 @@
           'isolate': 'media_perftests',
           'num_shards': 1,
           'telemetry': False,
+        },
+        {
+          'isolate': 'base_perftests',
+          'num_shards': 1,
+          'telemetry': False,
         }
       ],
       'platform': 'mac',
@@ -616,6 +636,11 @@
     'angle_perftests': BenchmarkMetadata(
         'jmadill@chromium.org, chrome-gpu-perf-owners@chromium.org',
         'Internals>GPU>ANGLE'),
+    'base_perftests': BenchmarkMetadata(
+        'skyostil@chromium.org, gab@chromium.org',
+        'Internals>SequenceManager',
+        ('https://chromium.googlesource.com/chromium/src/+/HEAD/base/' +
+         'README.md#performance-testing')),
     'validating_command_buffer_perftests': BenchmarkMetadata(
         'piman@chromium.org, chrome-gpu-perf-owners@chromium.org',
         'Internals>GPU'),
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 32fd89a..7cccc80 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -42,6 +42,7 @@
 crbug.com/574483 [ Android_Svelte ] blink_perf.paint/* [ Skip ]
 crbug.com/799540 [ Nexus_5 ] blink_perf.paint/* [ Skip ]
 crbug.com/859979 [ Android_Webview ] blink_perf.paint/paint-offset-changes.html [ Skip ]
+crbug.com/901493 [ Nexus6_Webview ] blink_perf.paint/* [ Skip ]
 
 # Benchmark: blink_perf.shadow_dom
 crbug.com/702319 [ Nexus_5X ] blink_perf.shadow_dom/* [ Skip ]
@@ -135,6 +136,11 @@
 
 # Benchmark: memory.long_running_idle_gmail_tbmv2
 crbug.com/611167 [ Android_Svelte ] memory.long_running_idle_gmail_tbmv2/* [ Skip ]
+crbug.com/901510 [ Nexus6_Webview ] memory.long_running_idle_gmail_tbmv2/* [ Skip ]
+crbug.com/901510 [ Nexus_5 ] memory.long_running_idle_gmail_tbmv2/* [ Skip ]
+crbug.com/901510 [ Nexus5X_Webview ] memory.long_running_idle_gmail_tbmv2/* [ Skip ]
+crbug.com/901510 [ Nexus_5X ] memory.long_running_idle_gmail_tbmv2/* [ Skip ]
+crbug.com/902064 [ Nexus_5 ] memory.long_running_idle_gmail_background_tbmv2/* [ Skip ]
 
 # Benchmark: memory.long_running_idle_gmail_background_tbmv2
 crbug.com/611167 [ Android_Svelte ] memory.long_running_idle_gmail_background_tbmv2/* [ Skip ]
@@ -198,6 +204,7 @@
 crbug.com/893197 [ Nexus_5X ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ]
 crbug.com/865400 [ Pixel_2 ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ]
 crbug.com/874935 [ Nexus_5 ] rendering.mobile/yahoo_news_2018 [ Skip ]
+crbug.com/901526 [ All ] rendering.mobile/microsoft_fireflies [ Skip ]
 
 # Benchmark: rasterize_and_record_micro.top_25
 crbug.com/764543 [ All ] rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html [ Skip ]
@@ -217,10 +224,9 @@
 crbug.com/773084 [ Mac ] system_health.common_desktop/browse:tools:maps [ Skip ]
 crbug.com/839411 [ Win ] system_health.common_desktop/browse:social:twitter_infinite_scroll [ Skip ]
 crbug.com/846022 [ Linux ] system_health.common_desktop/browse:social:twitter_infinite_scroll [ Skip ]
+crbug.com/903417 [ Mac ] system_health.common_desktop/long_running:tools:gmail-foreground [ Skip ]
 
 # Benchmark: system_health.common_mobile
-crbug.com/900909 [ Android ] system_health.common_mobile/browse:chrome:omnibox [ Skip ]
-crbug.com/900909 [ Android ] system_health.common_mobile/browse:chrome:newtab [ Skip ]
 crbug.com/714650 [ Android ] system_health.common_mobile/browse:news:globo [ Skip ]
 crbug.com/787001 [ Android_Webview ] system_health.common_mobile/load:media:soundcloud [ Skip ]
 crbug.com/708300 [ Android ] system_health.common_mobile/browse:shopping:flipkart [ Skip ]
@@ -251,10 +257,9 @@
 crbug.com/869118 [ Linux ] system_health.memory_desktop/long_running:tools:gmail-background [ Skip ]
 crbug.com/836447 [ ChromeOS ] system_health.memory_desktop/multitab:misc:typical24 [ Skip ]
 crbug.com/799734 [ Win ] system_health.memory_desktop/browse:media:tumblr [ Skip ]
+crbug.com/899887 [ Linux ] system_health.memory_desktop/browse:social:facebook_infinite_scroll:2018 [ Skip ]
 
 # Benchmark: system_health.memory_mobile
-crbug.com/900909 [ Android ] system_health.memory_mobile/browse:chrome:omnibox [ Skip ]
-crbug.com/900909 [ Android ] system_health.memory_mobile/browse:chrome:newtab [ Skip ]
 crbug.com/787001 [ Android_Webview ] system_health.memory_mobile/load:media:soundcloud [ Skip ]
 [ Android_Webview ] system_health.memory_mobile/browse:chrome:newtab [ Skip ]
 crbug.com/847786 [ Android_One ] system_health.memory_mobile/browse:chrome:newtab [ Skip ]
@@ -335,8 +340,6 @@
 crbug.com/773084 [ Mac ] v8.browsing_desktop-future/browse:tools:maps [ Skip ]
 
 # Benchmark: v8.browsing_mobile
-crbug.com/900909 [ Android ] v8.browsing_mobile/browse:chrome:omnibox [ Skip ]
-crbug.com/900909 [ Android ] v8.browsing_mobile/browse:chrome:newtab [ Skip ]
 crbug.com/714650 [ Android ] v8.browsing_mobile/browse:news:globo [ Skip ]
 crbug.com/767970 [ Android ] v8.browsing_mobile/browse:shopping:flipkart [ Skip ]
 crbug.com/708300 [ Android ] v8.browsing_mobile/browse:shopping:flipkart [ Skip ]
@@ -347,10 +350,9 @@
 crbug.com/853212 [ Android_Webview ] v8.browsing_mobile/browse:news:cnn [ Skip ]
 crbug.com/877648 [ Android_Go ] v8.browsing_mobile/browse:news:toi [ Skip ]
 crbug.com/877648 [ Android_Go ] v8.browsing_mobile/browse:news:cnn [ Skip ]
+crbug.com/901967 [ Nexus6_Webview ] v8.browsing_mobile/browse:news:toi [ Skip ]
 
 # Benchmark: v8.browsing_mobile-future
-crbug.com/900909 [ Android ] v8.browsing_mobile-future/browse:chrome:omnibox [ Skip ]
-crbug.com/900909 [ Android ] v8.browsing_mobile-future/browse:chrome:newtab [ Skip ]
 crbug.com/714650 [ Android ] v8.browsing_mobile-future/browse:news:globo [ Skip ]
 crbug.com/767970 [ Android ] v8.browsing_mobile-future/browse:shopping:flipkart [ Skip ]
 crbug.com/708300 [ Android ] v8.browsing_mobile-future/browse:shopping:flipkart [ Skip ]
@@ -360,6 +362,8 @@
 crbug.com/799080 [ Nexus_5X Android_Webview ] v8.browsing_mobile-future/browse:social:facebook [ Skip ]
 crbug.com/799080 [ Nexus_5X Android_Webview ] v8.browsing_mobile-future/browse:social:facebook [ Skip ]
 crbug.com/875159 [ Win_10 ] v8.browsing_desktop-future/browse:social:facebook_infinite_scroll [ Skip ]
+crbug.com/901534 [ Nexus6_Webview ] v8.browsing_mobile-future/browse:news:toi [ Skip ]
+crbug.com/902064 [ Nexus_5 ] v8.browsing_mobile-future/browse:news:toi [ Skip ]
 
 # Benchmark: v8.detached_context_age_in_gc
 crbug.com/770982 [ Win ] v8.detached_context_age_in_gc/Docs_(1_open_document_tab) [ Skip ]
diff --git a/tools/perf/flakiness_cli b/tools/perf/flakiness_cli
index 29b2f12..5d3c479 100755
--- a/tools/perf/flakiness_cli
+++ b/tools/perf/flakiness_cli
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env vpython
 # Copyright 2018 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -60,5 +60,4 @@
 
 
 if __name__ == '__main__':
-  core.CheckDependencies()
   sys.exit(main())
diff --git a/tools/perf/measurements/dual_metric_measurement.py b/tools/perf/measurements/dual_metric_measurement.py
new file mode 100644
index 0000000..041ef1e
--- /dev/null
+++ b/tools/perf/measurements/dual_metric_measurement.py
@@ -0,0 +1,49 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.web_perf import story_test
+from telemetry.web_perf import timeline_based_measurement
+
+
+class DualMetricMeasurement(story_test.StoryTest):
+  """Test class for a benchmark that aggregates all metrics.
+
+    Assumes both javascript as well as tracing metrics might be defined.
+
+    All pages associated with this measurement must implement
+    GetJavascriptMetricValues() and GetJavascriptMetricSummaryValues()
+  """
+  def __init__(self, tbm_options):
+    super(DualMetricMeasurement, self).__init__()
+    # Only enable tracing if metrics have been specified.
+    if tbm_options.GetTimelineBasedMetrics():
+      self._tbm_test = timeline_based_measurement.TimelineBasedMeasurement(
+          tbm_options)
+      self._enable_tracing = True
+    else:
+      self._enable_tracing = False
+
+  def WillRunStory(self, platform):
+    if self._enable_tracing:
+      self._tbm_test.WillRunStory(platform)
+
+  def Measure(self, platform, results):
+    for value in results.current_page.GetJavascriptMetricValues():
+      results.AddValue(value)
+    for value in results.current_page.GetJavascriptMetricSummaryValues():
+      results.AddSummaryValue(value)
+    # This call is necessary to convert the current ScalarValues to
+    # histograms before more histograms are added.  If we don't,
+    # when histograms get added by TBM2 page_test_results will see those and
+    # not convert any existing values because it assumes they are already
+    # converted.  Therefore, so the javascript metrics don't get dropped, we
+    # have to convert them first.
+    results.PopulateHistogramSet()
+    if self._enable_tracing:
+      self._tbm_test.Measure(platform, results)
+
+  def DidRunStory(self, platform, results):
+    if self._enable_tracing:
+      self._tbm_test.DidRunStory(platform, results)
+
diff --git a/tools/perf/measurements/rendering.py b/tools/perf/measurements/rendering.py
deleted file mode 100644
index 36481f0..0000000
--- a/tools/perf/measurements/rendering.py
+++ /dev/null
@@ -1,106 +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.
-
-from telemetry.page import legacy_page_test
-from telemetry.timeline import model as model_module
-from telemetry.value import trace
-from telemetry.web_perf import smooth_gesture_util
-from telemetry.web_perf import timeline_interaction_record as tir_module
-from telemetry.timeline import tracing_config
-
-from metrics import timeline
-from measurements import rendering_util
-
-
-def _CollectRecordsFromRendererThreads(model, renderer_thread):
-  records = []
-  for event in renderer_thread.async_slices:
-    if tir_module.IsTimelineInteractionRecord(event.name):
-      interaction = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
-      # Adjust the interaction record to match the synthetic gesture
-      # controller if needed.
-      interaction = (
-          smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
-              model, interaction))
-      records.append(interaction)
-  return records
-
-
-class Rendering(legacy_page_test.LegacyPageTest):
-
-  def __init__(self):
-    super(Rendering, self).__init__()
-    self._results = None
-
-  @classmethod
-  def CustomizeBrowserOptions(cls, options):
-    options.AppendExtraBrowserArgs('--enable-gpu-benchmarking')
-    options.AppendExtraBrowserArgs('--touch-events=enabled')
-
-  def WillNavigateToPage(self, page, tab):
-    config = tracing_config.TracingConfig()
-    config.enable_chrome_trace = True
-    config.enable_platform_display_trace = True
-
-    # Basic categories for smoothness.
-    config.chrome_trace_config.SetLowOverheadFilter()
-
-    # Extra categories from commandline flag.
-    if self.options and self.options.extra_chrome_categories:
-      config.chrome_trace_config.category_filter.AddFilterString(
-          self.options.extra_chrome_categories)
-
-    tab.browser.platform.tracing_controller.StartTracing(config)
-
-  def ValidateAndMeasurePage(self, _, tab, results):
-    self._results = results
-    tab.browser.platform.tracing_controller.telemetry_info = (
-        results.telemetry_info)
-    trace_result = tab.browser.platform.tracing_controller.StopTracing()
-
-    # TODO(charliea): This is part of a three-sided Chromium/Telemetry patch
-    # where we're changing the return type of StopTracing from a TraceValue to a
-    # (TraceValue, nonfatal_exception_list) tuple. Once the tuple return value
-    # lands in Chromium, the non-tuple logic should be deleted.
-    if isinstance(trace_result, tuple):
-      trace_result = trace_result[0]
-
-    trace_value = trace.TraceValue(
-        results.current_page, trace_result,
-        file_path=results.telemetry_info.trace_local_path,
-        remote_path=results.telemetry_info.trace_remote_path,
-        upload_bucket=results.telemetry_info.upload_bucket,
-        cloud_url=results.telemetry_info.trace_remote_url)
-    results.AddValue(trace_value)
-
-    model = model_module.TimelineModel(trace_result)
-    renderer_thread = model.GetFirstRendererThread(tab.id)
-    records = _CollectRecordsFromRendererThreads(model, renderer_thread)
-
-    thread_times_metric = timeline.ThreadTimesTimelineMetric()
-    thread_times_metric.AddResults(model, renderer_thread, records, results)
-
-    rendering_util.AddTBMv2RenderingMetrics(
-        trace_value, results, import_experimental_metrics=True)
-
-  def DidRunPage(self, platform):
-    if platform.tracing_controller.is_tracing_running:
-      trace_result = platform.tracing_controller.StopTracing()
-      if self._results:
-
-        # TODO(charliea): This is part of a three-sided Chromium/Telemetry patch
-        # where we're changing the return type of StopTracing from a TraceValue
-        # to a (TraceValue, nonfatal_exception_list) tuple. Once the tuple
-        # return value lands in Chromium, the non-tuple logic should be deleted.
-        if isinstance(trace_result, tuple):
-          trace_result = trace_result[0]
-
-        trace_value = trace.TraceValue(
-            self._results.current_page, trace_result,
-            file_path=self._results.telemetry_info.trace_local_path,
-            remote_path=self._results.telemetry_info.trace_remote_path,
-            upload_bucket=self._results.telemetry_info.upload_bucket,
-            cloud_url=self._results.telemetry_info.trace_remote_url)
-
-        self._results.AddValue(trace_value)
diff --git a/tools/perf/measurements/rendering_unittest.py b/tools/perf/measurements/rendering_unittest.py
deleted file mode 100644
index f2db811..0000000
--- a/tools/perf/measurements/rendering_unittest.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from telemetry.testing import options_for_unittests
-from telemetry.testing import page_test_test_case
-from telemetry.util import wpr_modes
-
-from measurements import rendering
-from measurements import rendering_util
-
-RENDERING_THREAD_GROUPS = ['GPU', 'IO', 'browser', 'display_compositor',
-                           'other', 'raster', 'renderer_compositor',
-                           'renderer_main', 'total_all', 'total_fast_path']
-
-class RenderingUnitTest(page_test_test_case.PageTestTestCase):
-  """Test for rendering measurement
-
-     Runs rendering measurement on a simple page and verifies the existence of
-     all metrics in the results. The correctness of metrics is not tested here.
-  """
-
-  def setUp(self):
-    self._options = options_for_unittests.GetCopy()
-    self._options.browser_options.wpr_mode = wpr_modes.WPR_OFF
-    self._options.pageset_repeat = 2
-
-  def testRendering(self):
-    ps = self.CreateStorySetFromFileInUnittestDataDir('scrollable_page.html')
-    results = self.RunMeasurement(
-        rendering.Rendering(), ps, options=self._options)
-    self.assertFalse(results.had_failures)
-    stat = rendering_util.ExtractStat(results)
-
-    self.assertGreater(stat['frame_times'].count, 1)
-    self.assertGreater(stat['percentage_smooth'].count, 1)
-    for thread_group in RENDERING_THREAD_GROUPS:
-      # We should have at least two sample values for each metric, since
-      # pageset_repeat is 2.
-      histogram_name = 'thread_%s_cpu_time_per_frame' % thread_group
-      self.assertGreater(stat[histogram_name].count, 1)
diff --git a/tools/perf/measurements/rendering_util.py b/tools/perf/measurements/rendering_util.py
deleted file mode 100644
index 09d07ed75..0000000
--- a/tools/perf/measurements/rendering_util.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from tracing.metrics import metric_runner
-from tracing.value import histogram as histogram_module
-
-def AddTBMv2RenderingMetrics(trace_value, results, import_experimental_metrics):
-  mre_result = metric_runner.RunMetric(
-      trace_value.filename, metrics=['renderingMetric'],
-      extra_import_options={'trackDetailedModelStats': True},
-      report_progress=False, canonical_url=results.telemetry_info.trace_url)
-
-  for f in mre_result.failures:
-    results.Fail(f.stack)
-
-  histograms = []
-  for histogram in mre_result.pairs.get('histograms', []):
-    if (import_experimental_metrics or
-        histogram.get('name', '').find('_tbmv2') < 0):
-      histograms.append(histogram)
-  results.ImportHistogramDicts(histograms, import_immediately=False)
-
-def ExtractStat(results):
-  stat = {}
-  for histogram_dict in results.AsHistogramDicts():
-    # It would be nicer if instead of converting results._histograms to dicts
-    # and then parsing them back in the following line, results had a getter
-    # returning results._histograms. But, since this is a temporary code that
-    # will be deleted after transitioning Smoothness to TBMv2, we don't change
-    # page_test_results.py for a temporary usecase.
-    if 'name' in histogram_dict:
-      histogram = histogram_module.Histogram.FromDict(histogram_dict)
-      if histogram.running is None:
-        continue
-      if histogram.name in stat:
-        stat[histogram.name] = stat[histogram.name].Merge(histogram.running)
-      else:
-        stat[histogram.name] = histogram.running
-  return stat
diff --git a/tools/perf/metrics/cpu.py b/tools/perf/metrics/cpu.py
deleted file mode 100644
index 8975853..0000000
--- a/tools/perf/metrics/cpu.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import logging
-
-from telemetry.value import scalar
-
-from metrics import Metric
-
-
-class CpuMetric(Metric):
-  """Calculates CPU load over a span of time."""
-
-  def __init__(self, browser):
-    super(CpuMetric, self).__init__()
-    self._browser = browser
-    self._start_cpu = None
-    self._stop_cpu = None
-
-  def DidStartBrowser(self, browser):
-    # Save the browser object so that cpu_stats can be accessed later.
-    self._browser = browser
-
-  def Start(self, page, tab):
-    if not self._browser.supports_cpu_metrics:
-      logging.warning('CPU metrics not supported.')
-      return
-
-    self._start_cpu = self._browser.cpu_stats
-
-  def Stop(self, page, tab):
-    if not self._browser.supports_cpu_metrics:
-      return
-
-    assert self._start_cpu, 'Must call Start() first'
-    self._stop_cpu = self._browser.cpu_stats
-
-  # Optional argument trace_name is not in base class Metric.
-  # pylint: disable=arguments-differ
-  def AddResults(self, tab, results, trace_name='cpu_utilization'):
-    if not self._browser.supports_cpu_metrics:
-      return
-
-    assert self._stop_cpu, 'Must call Stop() first'
-    cpu_stats = _SubtractCpuStats(self._stop_cpu, self._start_cpu)
-
-    # FIXME: Renderer process CPU times are impossible to compare correctly.
-    # http://crbug.com/419786#c11
-    if 'Renderer' in cpu_stats:
-      del cpu_stats['Renderer']
-
-    # Add a result for each process type.
-    for process_type in cpu_stats:
-      trace_name_for_process = '%s_%s' % (trace_name, process_type.lower())
-      cpu_percent = 100 * cpu_stats[process_type]
-      results.AddValue(scalar.ScalarValue(
-          results.current_page, 'cpu_utilization.%s' % trace_name_for_process,
-          '%', cpu_percent, important=False))
-
-
-def _SubtractCpuStats(cpu_stats, start_cpu_stats):
-  """Computes average cpu usage over a time period for different process types.
-
-  Each of the two cpu_stats arguments is a dict with the following format:
-      {'Browser': {'CpuProcessTime': ..., 'TotalTime': ...},
-       'Renderer': {'CpuProcessTime': ..., 'TotalTime': ...}
-       'Gpu': {'CpuProcessTime': ..., 'TotalTime': ...}}
-
-  The 'CpuProcessTime' fields represent the number of seconds of CPU time
-  spent in each process, and total time is the number of real seconds
-  that have passed (this may be a Unix timestamp).
-
-  Returns:
-    A dict of process type names (Browser, Renderer, etc.) to ratios of cpu
-    time used to total time elapsed.
-  """
-  cpu_usage = {}
-  for process_type in cpu_stats:
-    assert process_type in start_cpu_stats, 'Mismatching process types'
-    # Skip any process_types that are empty.
-    if (not cpu_stats[process_type]) or (not start_cpu_stats[process_type]):
-      continue
-    cpu_process_time = (cpu_stats[process_type]['CpuProcessTime'] -
-                        start_cpu_stats[process_type]['CpuProcessTime'])
-    total_time = (cpu_stats[process_type]['TotalTime'] -
-                  start_cpu_stats[process_type]['TotalTime'])
-    # Fix overflow for 32-bit jiffie counter, 64-bit counter will not overflow.
-    # Linux kernel starts with a value close to an overflow, so correction is
-    # necessary. Assume jiffie counter is at 100 Hz.
-    if total_time < 0:
-      total_time += 2 ** 32 / 100.
-    # Assert that the arguments were given in the correct order.
-    assert total_time > 0 and total_time < 2 ** 31 / 100., (
-        'Expected total_time > 0, was: %d' % total_time)
-    cpu_usage[process_type] = float(cpu_process_time) / total_time
-  return cpu_usage
diff --git a/tools/perf/metrics/cpu_unittest.py b/tools/perf/metrics/cpu_unittest.py
deleted file mode 100644
index 7749bc4..0000000
--- a/tools/perf/metrics/cpu_unittest.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import unittest
-
-from metrics import cpu
-
-# Testing private method.
-# pylint: disable=protected-access
-
-
-class CpuMetricTest(unittest.TestCase):
-
-  def testSubtractCpuStats(self):
-    # The result computed is a ratio of cpu time used to time elapsed.
-    start = {'Browser': {'CpuProcessTime': 0, 'TotalTime': 0}}
-    end = {'Browser': {'CpuProcessTime': 5, 'TotalTime': 20}}
-    self.assertEqual({'Browser': 0.25}, cpu._SubtractCpuStats(end, start))
-
-    # An error is thrown if the args are called in the wrong order.
-    self.assertRaises(AssertionError, cpu._SubtractCpuStats, start, end)
-
-    # An error is thrown if there's a process type in end that's not in start.
-    end['Renderer'] = {'CpuProcessTime': 2, 'TotalTime': 20}
-    self.assertRaises(AssertionError, cpu._SubtractCpuStats, end, start)
-
-    # A process type will be ignored if there's an empty dict for start or end.
-    start['Renderer'] = {}
-    self.assertEqual({'Browser': 0.25}, cpu._SubtractCpuStats(end, start))
-
-    # Results for multiple process types can be computed.
-    start['Renderer'] = {'CpuProcessTime': 0, 'TotalTime': 0}
-    self.assertEqual({'Browser': 0.25, 'Renderer': 0.1},
-                     cpu._SubtractCpuStats(end, start))
-
-    # Test 32-bit overflow.
-    start = {'Browser': {'CpuProcessTime': 0, 'TotalTime': 2 ** 32 / 100. - 20}}
-    end = {'Browser': {'CpuProcessTime': 5, 'TotalTime': 20}}
-    self.assertEqual({'Browser': 0.125}, cpu._SubtractCpuStats(end, start))
-    self.assertRaises(AssertionError, cpu._SubtractCpuStats, start, end)
diff --git a/tools/perf/metrics/keychain_metric.py b/tools/perf/metrics/keychain_metric.py
deleted file mode 100644
index 37cb1fff..0000000
--- a/tools/perf/metrics/keychain_metric.py
+++ /dev/null
@@ -1,78 +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.
-
-import logging
-import sys
-
-from telemetry.util.mac import keychain_helper
-from telemetry.value import histogram_util
-from telemetry.value import scalar
-
-from metrics import Metric
-
-
-class KeychainMetric(Metric):
-  """KeychainMetric gathers keychain statistics from the browser object.
-
-  This includes the number of times that the keychain was accessed.
-  """
-
-  DISPLAY_NAME = 'OSX_Keychain_Access'
-  HISTOGRAM_NAME = 'OSX.Keychain.Access'
-
-  @staticmethod
-  def _CheckKeychainConfiguration():
-    """On OSX, it is possible for a misconfigured keychain to cause the
-    Telemetry tests to stall.
-
-    This method confirms that the keychain is in a sane state that will
-    not cause this behavior. Three conditions are checked:
-      - The keychain is unlocked.
-      - The keychain will not auto-lock after a period of time.
-      - The ACLs are correctly configured on the relevant keychain items.
-    """
-    warning_suffix = ('which will cause some Telemetry tests to stall when run'
-                      ' on a headless machine (e.g. perf bot).')
-    if keychain_helper.IsKeychainLocked():
-      logging.warning('The default keychain is locked, %s', warning_suffix)
-
-    if keychain_helper.DoesKeychainHaveTimeout():
-      logging.warning('The default keychain is configured to automatically'
-                      ' lock itself have a period of time, %s', warning_suffix)
-
-    chrome_acl_configured = (keychain_helper.
-                             IsKeychainConfiguredForBotsWithChrome())
-    chromium_acl_configured = (keychain_helper.
-                               IsKeychainConfiguredForBotsWithChromium())
-    acl_warning = ('A commonly used %s key stored in the default keychain does'
-                   ' not give decryption access to all applications, %s')
-    if not chrome_acl_configured:
-      logging.warning(acl_warning, 'Chrome', warning_suffix)
-    if not chromium_acl_configured:
-      logging.warning(acl_warning, 'Chromium', warning_suffix)
-
-  @classmethod
-  def CustomizeBrowserOptions(cls, options):
-    """Adds a browser argument that allows for the collection of keychain
-    metrics. Has no effect on non-Mac platforms.
-    """
-    if sys.platform != 'darwin':
-      return
-
-    KeychainMetric._CheckKeychainConfiguration()
-
-    options.AppendExtraBrowserArgs(['--enable-stats-collection-bindings'])
-
-  def AddResults(self, tab, results):
-    """Adds the number of times that the keychain was accessed to |results|.
-    Has no effect on non-Mac platforms.
-    """
-    if sys.platform != 'darwin':
-      return
-
-    access_count = histogram_util.GetHistogramSum(
-        histogram_util.BROWSER_HISTOGRAM, KeychainMetric.HISTOGRAM_NAME, tab)
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, KeychainMetric.DISPLAY_NAME, 'count',
-        access_count))
diff --git a/tools/perf/metrics/loading.py b/tools/perf/metrics/loading.py
deleted file mode 100644
index fa1ee3b..0000000
--- a/tools/perf/metrics/loading.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright 2013 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.
-
-from telemetry.value import scalar
-
-from metrics import Metric
-
-
-class LoadingMetric(Metric):
-
-  """A metric for page loading time based entirely on window.performance"""
-
-  def Start(self, page, tab):
-    raise NotImplementedError()
-
-  def Stop(self, page, tab):
-    raise NotImplementedError()
-
-  def AddResults(self, tab, results):
-    load_timings = tab.EvaluateJavaScript('window.performance.timing')
-
-    # NavigationStart relative markers in milliseconds.
-    load_start = (
-        float(load_timings['loadEventStart']) - load_timings['navigationStart'])
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'load_start', 'ms', load_start))
-
-    dom_content_loaded_start = (
-        float(load_timings['domContentLoadedEventStart']) -
-        load_timings['navigationStart'])
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'dom_content_loaded_start', 'ms',
-        dom_content_loaded_start))
-
-    fetch_start = (
-        float(load_timings['fetchStart']) - load_timings['navigationStart'])
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'fetch_start', 'ms', fetch_start,
-        important=False))
-
-    request_start = (
-        float(load_timings['requestStart']) - load_timings['navigationStart'])
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'request_start', 'ms', request_start,
-        important=False))
-
-    # Phase measurements in milliseconds.
-    domain_lookup_duration = (
-        float(load_timings['domainLookupEnd']) -
-        load_timings['domainLookupStart'])
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'domain_lookup_duration', 'ms',
-        domain_lookup_duration, important=False))
-
-    connect_duration = (
-        float(load_timings['connectEnd']) - load_timings['connectStart'])
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'connect_duration', 'ms', connect_duration,
-        important=False))
-
-    request_duration = (
-        float(load_timings['responseStart']) - load_timings['requestStart'])
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'request_duration', 'ms', request_duration,
-        important=False))
-
-    response_duration = (
-        float(load_timings['responseEnd']) - load_timings['responseStart'])
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'response_duration', 'ms', response_duration,
-        important=False))
diff --git a/tools/perf/metrics/timeline.py b/tools/perf/metrics/timeline.py
deleted file mode 100644
index 6693bbe..0000000
--- a/tools/perf/metrics/timeline.py
+++ /dev/null
@@ -1,239 +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.
-import collections
-
-from telemetry.util.statistics import DivideIfPossibleOrZero
-from telemetry.value import scalar
-from telemetry.web_perf.metrics import timeline_based_metric
-
-
-# We want to generate a consistent picture of our thread usage, despite
-# having several process configurations (in-proc-gpu/single-proc).
-# Since we can't isolate renderer threads in single-process mode, we
-# always sum renderer-process threads' times. We also sum all io-threads
-# for simplicity.
-TimelineThreadCategories = {
-    "Chrome_InProcGpuThread": "GPU",
-    "CrGpuMain": "GPU",
-    "VizCompositorThread": "display_compositor",
-    "CrBrowserMain": "browser",
-    "Browser Compositor": "browser",
-    "CrRendererMain": "renderer_main",
-    "Compositor": "renderer_compositor",
-    "IOThread": "IO",
-    "CompositorTileWorker": "raster",
-    "DummyThreadName1": "other",
-    "DummyThreadName2": "total_fast_path",
-    "DummyThreadName3": "total_all"
-}
-
-_MatchBySubString = ["IOThread", "CompositorTileWorker"]
-
-AllThreads = TimelineThreadCategories.values()
-NoThreads = []
-FastPathThreads = [
-  "GPU", "display_compositor", "renderer_compositor", "browser", "IO"]
-
-ReportMainThreadOnly = ["renderer_main"]
-ReportSilkDetails = ["renderer_main"]
-
-# TODO(epenner): Thread names above are likely fairly stable but trace names
-# could change. We should formalize these traces to keep this robust.
-OverheadTraceCategory = "trace_event_overhead"
-OverheadTraceName = "overhead"
-FrameTraceName = "Graphics.Pipeline"
-FrameTraceStepName = "GenerateCompositorFrame"
-FrameTraceThreadName = "renderer_compositor"
-
-
-def Rate(numerator, denominator):
-  return DivideIfPossibleOrZero(numerator, denominator)
-
-
-def ClockOverheadForEvent(event):
-  if (event.category == OverheadTraceCategory and
-      event.name == OverheadTraceName):
-    return event.duration
-  else:
-    return 0
-
-
-def CpuOverheadForEvent(event):
-  if (event.category == OverheadTraceCategory and
-      event.thread_duration):
-    return event.thread_duration
-  else:
-    return 0
-
-
-def ThreadCategoryName(thread_name):
-  thread_category = "other"
-  for substring, category in TimelineThreadCategories.iteritems():
-    if substring in _MatchBySubString and substring in thread_name:
-      thread_category = category
-  if thread_name in TimelineThreadCategories:
-    thread_category = TimelineThreadCategories[thread_name]
-  return thread_category
-
-
-def ThreadCpuTimeResultName(thread_category):
-  # This isn't a good name, but I don't want to change it and lose continuity.
-  return "thread_" + thread_category + "_cpu_time_per_frame"
-
-
-def ThreadTasksResultName(thread_category):
-  return "tasks_per_frame_" + thread_category
-
-
-def ThreadMeanFrameTimeResultName(thread_category):
-  return "mean_frame_time_" + thread_category
-
-
-def ThreadDetailResultName(thread_category, detail):
-  detail_sanitized = detail.replace(".", "_")
-  return "thread_" + thread_category + "|" + detail_sanitized
-
-
-class ResultsForThread(object):
-
-  def __init__(self, model, record_ranges, name):
-    self.model = model
-    self.toplevel_slices = []
-    self.all_slices = []
-    self.name = name
-    self.record_ranges = record_ranges
-    self.all_action_time = \
-        sum([record_range.bounds for record_range in self.record_ranges])
-
-  @property
-  def clock_time(self):
-    clock_duration = sum([x.duration for x in self.toplevel_slices])
-    clock_overhead = sum([ClockOverheadForEvent(x) for x in self.all_slices])
-    return clock_duration - clock_overhead
-
-  @property
-  def cpu_time(self):
-    cpu_duration = 0
-    cpu_overhead = sum([CpuOverheadForEvent(x) for x in self.all_slices])
-    for x in self.toplevel_slices:
-      # Only report thread-duration if we have it for all events.
-      #
-      # A thread_duration of 0 is valid, so this only returns 0 if it is None.
-      if x.thread_duration is None:
-        if not x.duration:
-          continue
-        else:
-          return 0
-      else:
-        cpu_duration += x.thread_duration
-    return cpu_duration - cpu_overhead
-
-  def SlicesInActions(self, slices):
-    slices_in_actions = []
-    for event in slices:
-      for record_range in self.record_ranges:
-        if record_range.ContainsInterval(event.start, event.end):
-          slices_in_actions.append(event)
-          break
-    return slices_in_actions
-
-  def AppendThreadSlices(self, thread):
-    self.all_slices.extend(self.SlicesInActions(thread.all_slices))
-    self.toplevel_slices.extend(self.SlicesInActions(thread.toplevel_slices))
-
-  # Reports cpu-time per interval and tasks per interval.
-  def AddResults(self, num_intervals, results):
-    cpu_per_interval = Rate(self.cpu_time, num_intervals)
-    tasks_per_interval = Rate(len(self.toplevel_slices), num_intervals)
-    results.AddValue(scalar.ScalarValue(
-        results.current_page,
-        ThreadCpuTimeResultName(self.name),
-        "ms",
-        cpu_per_interval))
-    results.AddValue(scalar.ScalarValue(
-        results.current_page,
-        ThreadTasksResultName(self.name),
-        "tasks", tasks_per_interval))
-
-  def AddDetailedResults(self, num_intervals, results):
-    slices_by_category = collections.defaultdict(list)
-    for s in self.all_slices:
-      slices_by_category[s.category].append(s)
-    all_self_times = []
-    for category, slices_in_category in slices_by_category.iteritems():
-      self_time = sum([x.self_time for x in slices_in_category])
-      all_self_times.append(self_time)
-      self_time_per_interval = Rate(self_time, num_intervals)
-      results.AddValue(scalar.ScalarValue(
-          results.current_page,
-          ThreadDetailResultName(self.name, category),
-          "ms",
-          self_time_per_interval))
-    all_measured_time = sum(all_self_times)
-    idle_time = max(0, self.all_action_time - all_measured_time)
-    idle_time_per_interval = Rate(idle_time, num_intervals)
-    results.AddValue(scalar.ScalarValue(
-        results.current_page,
-        ThreadDetailResultName(self.name, "idle"),
-        "ms",
-        idle_time_per_interval))
-
-  def CountTracesWithNameAndArg(self, trace_name, step):
-    count = 0
-    for event in self.all_slices:
-      if trace_name in event.name and event.args and event.args["step"] == step:
-        count += 1
-    return count
-
-
-class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric):
-
-  def __init__(self):
-    super(ThreadTimesTimelineMetric, self).__init__()
-    # Minimal traces, for minimum noise in CPU-time measurements.
-    self.results_to_report = AllThreads
-    self.details_to_report = NoThreads
-
-  def AddResults(self, model, _, interaction_records, results):
-    # Set up each thread category for consistent results.
-    thread_category_results = {}
-    for name in TimelineThreadCategories.values():
-      thread_category_results[name] = ResultsForThread(
-          model, [r.GetBounds() for r in interaction_records], name)
-
-    # Group the slices by their thread category.
-    for thread in model.GetAllThreads():
-      thread_category = ThreadCategoryName(thread.name)
-      thread_category_results[thread_category].AppendThreadSlices(thread)
-
-    # Group all threads.
-    for thread in model.GetAllThreads():
-      thread_category_results["total_all"].AppendThreadSlices(thread)
-
-    # Also group fast-path threads.
-    for thread in model.GetAllThreads():
-      if ThreadCategoryName(thread.name) in FastPathThreads:
-        thread_category_results["total_fast_path"].AppendThreadSlices(thread)
-
-    # Calculate the interaction's number of frames.
-    frame_rate_thread = thread_category_results[FrameTraceThreadName]
-    num_frames = frame_rate_thread.CountTracesWithNameAndArg(FrameTraceName,
-        FrameTraceStepName)
-
-    # Report the desired results and details for each interval type.
-    for thread_results in thread_category_results.values():
-      if thread_results.name in self.results_to_report:
-        thread_results.AddResults(num_frames, results)
-      # TODO(nduca): When generic results objects are done, this special case
-      # can be replaced with a generic UI feature.
-      if thread_results.name in self.details_to_report:
-        thread_results.AddDetailedResults(num_frames, results)
-
-    # Report mean frame time for the frame rate thread. We could report other
-    # frame rates (e.g. renderer_main) but this might get confusing.
-    mean_frame_time = Rate(frame_rate_thread.all_action_time, num_frames)
-    results.AddValue(scalar.ScalarValue(
-        results.current_page,
-        ThreadMeanFrameTimeResultName(FrameTraceThreadName),
-        "ms", mean_frame_time))
diff --git a/tools/perf/metrics/timeline_unittest.py b/tools/perf/metrics/timeline_unittest.py
deleted file mode 100644
index d385fc0..0000000
--- a/tools/perf/metrics/timeline_unittest.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import unittest
-
-from telemetry.testing import test_page_test_results
-from telemetry.timeline import model as model_module
-from telemetry.web_perf import timeline_interaction_record as tir_module
-
-from metrics import timeline
-
-
-def _GetInteractionRecord(start, end):
-  return tir_module.TimelineInteractionRecord('test-record', start, end)
-
-
-class ThreadTimesTimelineMetricUnittest(unittest.TestCase):
-
-  def GetResults(self, metric, model, renderer_thread, interaction_record):
-    results = test_page_test_results.TestPageTestResults(self)
-    metric.AddResults(model, renderer_thread, interaction_record,
-                      results)
-    return results
-
-  def testResults(self):
-    model = model_module.TimelineModel()
-    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
-    renderer_main.name = 'CrRendererMain'
-
-    metric = timeline.ThreadTimesTimelineMetric()
-    metric.details_to_report = timeline.ReportMainThreadOnly
-    results = self.GetResults(metric, model, renderer_main.parent,
-                              [_GetInteractionRecord(1, 2)])
-
-    # Test that all result thread categories exist
-    for name in timeline.TimelineThreadCategories.values():
-      results.GetPageSpecificValueNamed(
-          timeline.ThreadCpuTimeResultName(name))
-
-  def testBasic(self):
-    model = model_module.TimelineModel()
-    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
-    renderer_main.name = 'CrRendererMain'
-
-    # Create two frame swaps (Results times should be divided by two) for
-    # an interaction that lasts 20 milliseconds.
-    cc_main = model.GetOrCreateProcess(1).GetOrCreateThread(3)
-    cc_main.name = 'Compositor'
-    cc_main.BeginSlice('cc_cat', timeline.FrameTraceName, 10, 10,
-        args={'step': 'GenerateCompositorFrame'})
-    cc_main.EndSlice(11, 11)
-    cc_main.BeginSlice('cc_cat', timeline.FrameTraceName, 12, 12,
-        args={'step': 'GenerateCompositorFrame'})
-    cc_main.EndSlice(13, 13)
-
-    # [      X       ]   [ Z ]
-    #      [  Y  ]
-    renderer_main.BeginSlice('cat1', 'X', 10, 0)
-    renderer_main.BeginSlice('cat2', 'Y', 15, 5)
-    renderer_main.EndSlice(16, 5.5)
-    renderer_main.EndSlice(30, 19.5)
-    renderer_main.BeginSlice('cat1', 'Z', 31, 20)
-    renderer_main.BeginSlice('cat1', 'Z', 33, 21)
-    model.FinalizeImport()
-
-    # Exclude 'Z' using an action-range.
-    metric = timeline.ThreadTimesTimelineMetric()
-    metric.details_to_report = timeline.ReportMainThreadOnly
-    results = self.GetResults(metric, model, renderer_main.parent,
-                              [_GetInteractionRecord(10, 30)])
-
-    # Test for the results we expect.
-    main_thread = 'renderer_main'
-    cc_thread = 'renderer_compositor'
-    assert_results = [
-        (timeline.ThreadMeanFrameTimeResultName(cc_thread), 'ms', 10.0),
-        (timeline.ThreadTasksResultName(main_thread), 'tasks', 0.5),
-        (timeline.ThreadTasksResultName(cc_thread), 'tasks', 1.0),
-        (timeline.ThreadCpuTimeResultName(main_thread), 'ms', 9.75),
-        (timeline.ThreadCpuTimeResultName(cc_thread), 'ms', 1.0),
-        (timeline.ThreadDetailResultName(main_thread, 'cat1'), 'ms', 9.5),
-        (timeline.ThreadDetailResultName(main_thread, 'cat2'), 'ms', 0.5),
-        (timeline.ThreadDetailResultName(main_thread, 'idle'), 'ms', 0),
-    ]
-    for name, unit, value in assert_results:
-      results.AssertHasPageSpecificScalarValue(name, unit, value)
-
-  def testOverheadIsRemoved(self):
-    model = model_module.TimelineModel()
-    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
-    renderer_main.name = 'CrRendererMain'
-
-    # Create one frame swap.
-    cc_main = model.GetOrCreateProcess(1).GetOrCreateThread(3)
-    cc_main.name = 'Compositor'
-    cc_main.BeginSlice('cc_cat', timeline.FrameTraceName, 10, 10,
-        args={'step': 'GenerateCompositorFrame'})
-    cc_main.EndSlice(11, 11)
-
-    # [      X       ]
-    #    [Overhead]
-    overhead_category = timeline.OverheadTraceCategory
-    overhead_name = timeline.OverheadTraceName
-    renderer_main.BeginSlice('cat1', 'X', 10, 0)
-    renderer_main.BeginSlice(overhead_category, overhead_name, 15, 5)
-    renderer_main.EndSlice(16, 6)
-    renderer_main.EndSlice(30, 10)
-    model.FinalizeImport()
-
-    # Include everything in an action-range.
-    metric = timeline.ThreadTimesTimelineMetric()
-    metric.details_to_report = timeline.ReportMainThreadOnly
-    results = self.GetResults(metric, model, renderer_main.parent,
-                              [_GetInteractionRecord(10, 30)])
-
-    # Test a couple specific results.
-    assert_results = [
-        (timeline.ThreadCpuTimeResultName('renderer_main'), 'ms', 9.0),
-    ]
-    for name, unit, value in assert_results:
-      results.AssertHasPageSpecificScalarValue(name, unit, value)
diff --git a/tools/perf/page_sets/data/system_health_desktop.json b/tools/perf/page_sets/data/system_health_desktop.json
index d4a8eea..37130706 100644
--- a/tools/perf/page_sets/data/system_health_desktop.json
+++ b/tools/perf/page_sets/data/system_health_desktop.json
@@ -9,6 +9,9 @@
         "browse:media:pinterest": {
             "DEFAULT": "system_health_desktop_035.wprgo"
         },
+        "browse:media:pinterest:2018": {
+            "DEFAULT": "system_health_desktop_939ec7010c.wprgo"
+        },
         "browse:media:tumblr": {
             "DEFAULT": "system_health_desktop_036.wprgo"
         },
@@ -21,6 +24,9 @@
             "mac": "system_health_desktop_040.wprgo",
             "win": "system_health_desktop_047.wprgo"
         },
+        "browse:media:youtube:2018": {
+            "DEFAULT": "system_health_desktop_6b6bdda708.wprgo"
+        },
         "browse:news:cnn": {
             "DEFAULT": "system_health_desktop_013.wprgo"
         },
@@ -309,4 +315,4 @@
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
     "platform_specific": true
-}
\ No newline at end of file
+}
diff --git a/tools/perf/page_sets/data/system_health_desktop_37bd086ce0.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_37bd086ce0.wprgo.sha1
index 8fa8bb3..55edc26 100644
--- a/tools/perf/page_sets/data/system_health_desktop_37bd086ce0.wprgo.sha1
+++ b/tools/perf/page_sets/data/system_health_desktop_37bd086ce0.wprgo.sha1
@@ -1 +1 @@
-37bd086ce08318237ccbea5e7b64bbb0a9d3657e
\ No newline at end of file
+b83a60fe468810e74523ee95c7b8c7f59c410ae9
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_3c603ac582.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_3c603ac582.wprgo.sha1
index 00bced9..a4f0096 100644
--- a/tools/perf/page_sets/data/system_health_desktop_3c603ac582.wprgo.sha1
+++ b/tools/perf/page_sets/data/system_health_desktop_3c603ac582.wprgo.sha1
@@ -1 +1 @@
-3c603ac582f0c1c91a418af4f6cc5db4752d42d1
\ No newline at end of file
+6b2d23b5b155bcd941ecb5e3c19aa7115a190282
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_57d9c71c88.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_57d9c71c88.wprgo.sha1
index 1eeff224..78712ef 100644
--- a/tools/perf/page_sets/data/system_health_desktop_57d9c71c88.wprgo.sha1
+++ b/tools/perf/page_sets/data/system_health_desktop_57d9c71c88.wprgo.sha1
@@ -1 +1 @@
-57d9c71c88accb07a365fd975c3c8054eeb19880
\ No newline at end of file
+2ef65d18177b311bed426fc214488c3d21e349ac
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_6b6bdda708.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_6b6bdda708.wprgo.sha1
new file mode 100644
index 0000000..8bcb2f9
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_desktop_6b6bdda708.wprgo.sha1
@@ -0,0 +1 @@
+c83b5e397217ef1328e495aad61a2cca2bfd8474
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_907087980d.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_907087980d.wprgo.sha1
index 0ce0ee73..0b6c88e 100644
--- a/tools/perf/page_sets/data/system_health_desktop_907087980d.wprgo.sha1
+++ b/tools/perf/page_sets/data/system_health_desktop_907087980d.wprgo.sha1
@@ -1 +1 @@
-907087980d52d972104ce9b71ab50d7a8b6a52e0
\ No newline at end of file
+cb76e36f5b96bc26d8c51c20c2ce7ae67477ea2c
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_939ec7010c.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_939ec7010c.wprgo.sha1
new file mode 100644
index 0000000..60d3735
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_desktop_939ec7010c.wprgo.sha1
@@ -0,0 +1 @@
+d482ccd65a176db9ca862272f4ba268f3db7d6d2
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_d312e21b98.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_d312e21b98.wprgo.sha1
index 24abe44..3f0b6638 100644
--- a/tools/perf/page_sets/data/system_health_desktop_d312e21b98.wprgo.sha1
+++ b/tools/perf/page_sets/data/system_health_desktop_d312e21b98.wprgo.sha1
@@ -1 +1 @@
-d312e21b98ee88ea54a91146cff0a8f6836fd291
\ No newline at end of file
+6818c510b394aad8934a73da1ba0ab84e255dfa3
\ No newline at end of file
diff --git a/tools/perf/page_sets/dromaeo_pages.py b/tools/perf/page_sets/dromaeo_pages.py
new file mode 100644
index 0000000..84d4cda
--- /dev/null
+++ b/tools/perf/page_sets/dromaeo_pages.py
@@ -0,0 +1,96 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import math
+
+from telemetry import story
+from telemetry.value import scalar
+
+from page_sets import press_story
+
+class DromaeoStory(press_story.PressStory):
+
+  def __init__(self, url, ps):
+    self.URL = url
+    super(DromaeoStory, self).__init__(ps)
+
+
+  def ExecuteTest(self, action_runner):
+    action_runner.WaitForJavaScriptCondition(
+        'window.document.getElementById("pause") &&' +
+        'window.document.getElementById("pause").value == "Run"',
+        timeout=120)
+
+    # Start spying on POST request that will report benchmark results, and
+    # intercept result data.
+    action_runner.ExecuteJavaScript("""
+        (function() {
+          var real_jquery_ajax_ = window.jQuery;
+          window.results_ = "";
+          window.jQuery.ajax = function(request) {
+            if (request.url == "store.php") {
+              window.results_ = decodeURIComponent(request.data);
+              window.results_ = window.results_.substring(
+                window.results_.indexOf("=") + 1,
+                window.results_.lastIndexOf("&"));
+              real_jquery_ajax_(request);
+            }
+          };
+        })();""")
+    # Starts benchmark.
+    action_runner.ExecuteJavaScript(
+        'window.document.getElementById("pause").click();')
+
+    action_runner.WaitForJavaScriptCondition('!!window.results_', timeout=600)
+
+
+  def ParseTestResults(self, action_runner):
+    score = json.loads(
+        action_runner.EvaluateJavaScript('window.results_ || "[]"'))
+
+    def Escape(k):
+      chars = [' ', '.', '-', '/', '(', ')', '*']
+      for c in chars:
+        k = k.replace(c, '_')
+      return k
+
+    def AggregateData(container, key, value):
+      if key not in container:
+        container[key] = {'count': 0, 'sum': 0}
+      container[key]['count'] += 1
+      container[key]['sum'] += math.log(value)
+
+    suffix = self.url[self.url.index('?') + 1:]
+
+    def AddResult(name, value):
+      important = False
+      if name == suffix:
+        important = True
+      self.AddJavascriptMetricValue(scalar.ScalarValue(
+          self, Escape(name), 'runs/s', value, important))
+
+    aggregated = {}
+    for data in score:
+      AddResult('%s/%s' % (data['collection'], data['name']),
+                data['mean'])
+
+      top_name = data['collection'].split('-', 1)[0]
+      AggregateData(aggregated, top_name, data['mean'])
+
+      collection_name = data['collection']
+      AggregateData(aggregated, collection_name, data['mean'])
+
+    for key, value in aggregated.iteritems():
+      AddResult(key, math.exp(value['sum'] / value['count']))
+
+
+class DromaeoStorySet(story.StorySet):
+  def __init__(self):
+    super(DromaeoStorySet, self).__init__(
+        archive_data_file='../page_sets/data/dromaeo.json',
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
+
+    for query_param in ['dom-attr', 'dom-modify', 'dom-query', 'dom-traverse']:
+      url = 'http://dromaeo.com?%s' % query_param
+      self.AddStory(DromaeoStory(url, self))
diff --git a/tools/perf/page_sets/jetstream_pages.py b/tools/perf/page_sets/jetstream_pages.py
new file mode 100644
index 0000000..98206ae
--- /dev/null
+++ b/tools/perf/page_sets/jetstream_pages.py
@@ -0,0 +1,64 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+
+from page_sets import press_story
+from telemetry import story
+from telemetry.util import statistics
+from telemetry.value import list_of_scalar_values
+
+class JetstreamStory(press_story.PressStory):
+  URL='http://browserbench.org/JetStream/'
+
+  def __init__(self, ps):
+    super(JetstreamStory, self).__init__(ps)
+    self.script_to_evaluate_on_commit = """
+        var __results = [];
+        var __real_log = window.console.log;
+        window.console.log = function() {
+          __results.push(Array.prototype.join.call(arguments, ' '));
+          __real_log.apply(this, arguments);
+        }
+        """
+
+  def ExecuteTest(self, action_runner):
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
+    action_runner.EvaluateJavaScript('JetStream.start()')
+
+  def ParseTestResults(self, action_runner):
+    result = action_runner.WaitForJavaScriptCondition("""
+        (function() {
+          for (var i = 0; i < __results.length; i++) {
+            if (!__results[i].indexOf('Raw results: ')) return __results[i];
+          }
+          return null;
+        })();
+        """, timeout=60*20)
+    result = json.loads(result.partition(': ')[2])
+
+    all_score_lists = []
+    for k, v in result.iteritems():
+      self.AddJavascriptMetricValue(list_of_scalar_values.ListOfScalarValues(
+          self, k.replace('.', '_'), 'score', v['result'],
+          important=False))
+      # Collect all test scores to compute geometric mean.
+      for i, score in enumerate(v['result']):
+        if len(all_score_lists) <= i:
+          all_score_lists.append([])
+        all_score_lists[i].append(score)
+    all_scores = []
+    for score_list in all_score_lists:
+      all_scores.append(statistics.GeometricMean(score_list))
+    self.AddJavascriptMetricSummaryValue(
+        list_of_scalar_values.ListOfScalarValues(
+        None, 'Score', 'score', all_scores))
+
+
+class JetstreamStorySet(story.StorySet):
+  def __init__(self):
+    super(JetstreamStorySet, self).__init__(
+        archive_data_file='data/jetstream.json',
+        cloud_storage_bucket=story.INTERNAL_BUCKET)
+
+    self.AddStory(JetstreamStory(self))
diff --git a/tools/perf/page_sets/kraken_pages.py b/tools/perf/page_sets/kraken_pages.py
new file mode 100644
index 0000000..b62adf79
--- /dev/null
+++ b/tools/perf/page_sets/kraken_pages.py
@@ -0,0 +1,101 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+
+from page_sets import press_story
+from telemetry import story
+
+from telemetry.value import list_of_scalar_values
+from telemetry.value import scalar
+
+
+DESCRIPTIONS = {
+    'ai-astar':
+        'This benchmark uses the [A* search algorithm]'
+        '(http://en.wikipedia.org/wiki/A*_search_algorithm) to automatically '
+        'plot an efficient path between two points, in the presence of '
+        'obstacles. Adapted from code by [Brian Gringstead]'
+        '(http://www.briangrinstead.com/blog/astar-search-algorithm-in-'
+        'javascript).',
+    'audio-beat-detection':
+        'This benchmark performs [beat detection]'
+        '(http://en.wikipedia.org/wiki/Beat_detection) on an Audio sample '
+        'using [code](http://beatdetektor.svn.sourceforge.net/viewvc'
+        '/beatdetektor/trunk/core/js/beatdetektor.js?revision=18&view=markup) '
+        'from [BeatDetektor](http://www.cubicproductions.com/index.php'
+        '?option=com_content&view=article&id=67&Itemid=82) and '
+        '[DSP.js](http://github.com/corbanbrook/dsp.js/).',
+    'audio-dft':
+        'This benchmark performs a [Discrete Fourier Transform]'
+        '(http://en.wikipedia.org/wiki/Discrete_Fourier_transform) on an '
+        'Audio sample using code from [DSP.js]'
+        '(http://github.com/corbanbrook/dsp.js).',
+    'audio-fft':
+        'This benchmark performs a [Fast Fourier Transform]'
+        '(http://en.wikipedia.org/wiki/Fast_Fourier_transform) on an Audio '
+        'sample using code from [DSP.js]'
+        '(http://github.com/corbanbrook/dsp.js/).',
+    'audio-oscillator':
+        'This benchmark generates a soundwave using code from [DSP.js]'
+        '(http://github.com/corbanbrook/dsp.js/).',
+    'imaging-darkroom':
+        'This benchmark performs a variety of photo manipulations such as '
+        'Fill, Brightness, Contrast, Saturation, and Temperature.',
+    'imaging-desaturate':
+        'This benchmark [desaturates]'
+        '(http://en.wikipedia.org/wiki/Colorfulness) a photo using code from '
+        '[Pixastic](http://www.pixastic.com/).',
+    'imaging-gaussian-blur':
+        'This benchmark performs a [Gaussian blur]'
+        '(http://en.wikipedia.org/wiki/Gaussian_blur) on a photo.',
+    'json-parse-financial':
+        'This benchmark parses [JSON](http://www.json.org) records.',
+    'json-stringify-tinderbox':
+        'This benchmark serializes [Tinderbox]'
+        '(http://tests.themasta.com/tinderboxpushlog/?tree=Firefox) build '
+        'data to [JSON](http://www.json.org).',
+}
+
+def _Mean(l):
+  return float(sum(l)) / len(l) if len(l) > 0 else 0.0
+
+
+class KrakenStory(press_story.PressStory):
+  URL='http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html'
+
+  def ExecuteTest(self, action_runner):
+    action_runner.WaitForJavaScriptCondition(
+        'document.title.indexOf("Results") != -1', timeout=700)
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
+
+  def ParseTestResults(self, action_runner):
+    result_dict = json.loads(action_runner.EvaluateJavaScript("""
+        var formElement = document.getElementsByTagName("input")[0];
+        decodeURIComponent(formElement.value.split("?")[1]);
+        """))
+    total = 0
+    for key in result_dict:
+      if key == 'v':
+        continue
+      self.AddJavascriptMetricValue(list_of_scalar_values.ListOfScalarValues(
+          self, key, 'ms', result_dict[key], important=False,
+          description=DESCRIPTIONS.get(key)))
+      total += _Mean(result_dict[key])
+
+    # TODO(tonyg/nednguyen): This measurement shouldn't calculate Total. The
+    # results system should do that for us.
+    self.AddJavascriptMetricValue(scalar.ScalarValue(
+        self, 'Total', 'ms', total,
+        description='Total of the means of the results for each type '
+                    'of benchmark in [Mozilla\'s Kraken JavaScript benchmark]'
+                    '(http://krakenbenchmark.mozilla.org/)'))
+
+
+class KrakenStorySet(story.StorySet):
+  def __init__(self):
+    super(KrakenStorySet, self).__init__(
+        archive_data_file='data/kraken.json',
+        cloud_storage_bucket=story.PARTNER_BUCKET)
+
+    self.AddStory(KrakenStory(self))
diff --git a/tools/perf/page_sets/login_helpers/pinterest_login.py b/tools/perf/page_sets/login_helpers/pinterest_login.py
index ceddcdd..8962a36 100644
--- a/tools/perf/page_sets/login_helpers/pinterest_login.py
+++ b/tools/perf/page_sets/login_helpers/pinterest_login.py
@@ -26,17 +26,14 @@
 
   action_runner.Navigate('https://www.pinterest.com/login/')
   action_runner.Wait(1) # Error page happens if this wait is not here.
+  action_runner.WaitForElement(selector='button[type=submit]')
+
   login_utils.InputWithSelector(
       action_runner, '%s@gmail.com' % account_name, 'input[type=email]')
+
   login_utils.InputWithSelector(
       action_runner, password, 'input[type=password]')
 
-  login_button_function = (
-      'document.getElementsByClassName("Button Module btn hasText large '
-      'primary continueButton rounded")[0]')
-  action_runner.WaitForElement(element_function=login_button_function)
-  action_runner.ClickElement(element_function=login_button_function)
+  action_runner.ClickElement(selector='button[type=submit]')
 
-  search_bar_function = (
-      'document.getElementsByClassName("Input Module field")[0]')
-  action_runner.WaitForElement(element_function=search_bar_function)
+  action_runner.WaitForElement(selector='input[name=searchBoxInput]')
diff --git a/tools/perf/page_sets/octane_pages.py b/tools/perf/page_sets/octane_pages.py
new file mode 100644
index 0000000..e3f8a32
--- /dev/null
+++ b/tools/perf/page_sets/octane_pages.py
@@ -0,0 +1,113 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import story
+
+from telemetry.util import statistics
+from telemetry.value import scalar
+
+from page_sets import press_story
+
+_GB = 1024 * 1024 * 1024
+
+DESCRIPTIONS = {
+    'CodeLoad':
+        'Measures how quickly a JavaScript engine can start executing code '
+        'after loading a large JavaScript program, social widget being a '
+        'common example. The source for test is derived from open source '
+        'libraries (Closure, jQuery) (1,530 lines).',
+    'Crypto':
+        'Encryption and decryption benchmark based on code by Tom Wu '
+        '(1698 lines).',
+    'DeltaBlue':
+        'One-way constraint solver, originally written in Smalltalk by John '
+        'Maloney and Mario Wolczko (880 lines).',
+    'EarleyBoyer':
+        'Classic Scheme benchmarks, translated to JavaScript by Florian '
+        'Loitsch\'s Scheme2Js compiler (4684 lines).',
+    'Gameboy':
+        'Emulate the portable console\'s architecture and runs a demanding 3D '
+        'simulation, all in JavaScript (11,097 lines).',
+    'Mandreel':
+        'Runs the 3D Bullet Physics Engine ported from C++ to JavaScript via '
+        'Mandreel (277,377 lines).',
+    'NavierStokes':
+        '2D NavierStokes equations solver, heavily manipulates double '
+        'precision arrays. Based on Oliver Hunt\'s code (387 lines).',
+    'PdfJS':
+        'Mozilla\'s PDF Reader implemented in JavaScript. It measures decoding '
+        'and interpretation time (33,056 lines).',
+    'RayTrace':
+        'Ray tracer benchmark based on code by Adam Burmister (904 lines).',
+    'RegExp':
+        'Regular expression benchmark generated by extracting regular '
+        'expression operations from 50 of the most popular web pages '
+        '(1761 lines).',
+    'Richards':
+        'OS kernel simulation benchmark, originally written in BCPL by Martin '
+        'Richards (539 lines).',
+    'Splay':
+        'Data manipulation benchmark that deals with splay trees and exercises '
+        'the automatic memory management subsystem (394 lines).',
+}
+
+
+class OctaneStory(press_story.PressStory):
+  URL='http://chromium.github.io/octane/index.html?auto=1'
+
+  def RunNavigateSteps(self, action_runner):
+    total_memory = (
+        action_runner.tab.browser.platform.GetSystemTotalPhysicalMemory())
+    if total_memory is not None and total_memory < 1 * _GB:
+      skipBenchmarks = '"zlib"'
+    else:
+      skipBenchmarks = ''
+    self.script_to_evaluate_on_commit = """
+        var __results = [];
+        var __real_log = window.console.log;
+        window.console.log = function(msg) {
+          __results.push(msg);
+          __real_log.apply(this, [msg]);
+        }
+        skipBenchmarks = [%s]
+        """ % (skipBenchmarks)
+    super(OctaneStory, self).RunNavigateSteps(action_runner)
+
+  def ExecuteTest(self, action_runner):
+    action_runner.WaitForJavaScriptCondition('window.completed', timeout=10)
+    action_runner.WaitForJavaScriptCondition(
+        '!document.getElementById("progress-bar-container")', timeout=1200)
+
+  def ParseTestResults(self, action_runner):
+    results_log = action_runner.EvaluateJavaScript('__results')
+    all_scores = []
+    for output in results_log:
+      # Split the results into score and test name.
+      # results log e.g., "Richards: 18343"
+      score_and_name = output.split(': ', 2)
+      assert len(score_and_name) == 2, \
+        'Unexpected result format "%s"' % score_and_name
+      if 'Skipped' not in score_and_name[1]:
+        name = score_and_name[0]
+        score = float(score_and_name[1])
+        self.AddJavascriptMetricValue(scalar.ScalarValue(
+            self, name, 'score', score, important=False,
+            description=DESCRIPTIONS.get(name)))
+
+        # Collect all test scores to compute geometric mean.
+        all_scores.append(score)
+    total = statistics.GeometricMean(all_scores)
+    self.AddJavascriptMetricSummaryValue(
+        scalar.ScalarValue(None, 'Total.Score', 'score', total,
+                           description='Geometric mean of the scores of each '
+                           'individual benchmark in the Octane '
+                           'benchmark collection.'))
+
+
+class OctaneStorySet(story.StorySet):
+  def __init__(self):
+    super(OctaneStorySet, self).__init__(
+        archive_data_file='data/octane.json',
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
+
+    self.AddStory(OctaneStory(self))
diff --git a/tools/perf/page_sets/press_story.py b/tools/perf/page_sets/press_story.py
new file mode 100644
index 0000000..ceabf4e
--- /dev/null
+++ b/tools/perf/page_sets/press_story.py
@@ -0,0 +1,59 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page import page as page_module
+
+
+class PressStory(page_module.Page):
+  """Base class for Press stories.
+
+    Override ExecuteTest to execute javascript on the page and
+    ParseTestResults to obtain javascript metrics from page.
+
+    Example Implementation:
+
+    class FooPressStory:
+      URL = 'http://foo'
+
+      def ExecuteTest(self, action_runner):
+        //Execute some javascript
+
+      def ParseTestResults(self, action_runner):
+        some_value = action_runner.EvaluateJavascript("some javascript")
+        self.AddJavascriptMetricValue(some_value)
+  """
+  URL = None
+  DETERMINISTIC_JS = False
+  NAME = None
+
+  def __init__(self, ps):
+    super(PressStory, self).__init__(
+        self.URL, ps,
+        base_dir=ps.base_dir,
+        make_javascript_deterministic=self.DETERMINISTIC_JS,
+        name=self.NAME if self.NAME else self.URL)
+    self._values = []
+    self._summary_values = []
+
+  def GetJavascriptMetricValues(self):
+    return self._values
+
+  def AddJavascriptMetricValue(self, value):
+    self._values.append(value)
+
+  def GetJavascriptMetricSummaryValues(self):
+    return self._summary_values
+
+  def AddJavascriptMetricSummaryValue(self, value):
+    self._summary_values.append(value)
+
+  def ExecuteTest(self, action_runner):
+    pass
+
+  def ParseTestResults(self, action_runner):
+    pass
+
+  def RunPageInteractions(self, action_runner):
+    self.ExecuteTest(action_runner)
+    self.ParseTestResults(action_runner)
diff --git a/tools/perf/page_sets/speedometer2_pages.py b/tools/perf/page_sets/speedometer2_pages.py
new file mode 100644
index 0000000..2264c241
--- /dev/null
+++ b/tools/perf/page_sets/speedometer2_pages.py
@@ -0,0 +1,130 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Apple's Speedometer 2 performance benchmark pages
+"""
+import re
+
+from telemetry.value import list_of_scalar_values
+
+from page_sets import press_story
+
+_SPEEDOMETER_SUITE_NAME_BASE = '{0}-TodoMVC'
+_SPEEDOMETER_SUITES = [
+  'VanillaJS',
+  'Vanilla-ES2015',
+  'Vanilla-ES2015-Babel-Webpack',
+  'React',
+  'React-Redux',
+  'EmberJS',
+  'EmberJS-Debug',
+  'BackboneJS',
+  'AngularJS',
+  'Angular2-TypeScript',
+  'VueJS',
+  'jQuery',
+  'Preact',
+  'Inferno',
+  'Elm',
+  'Flight'
+]
+
+class Speedometer2Story(press_story.PressStory):
+  URL = 'file://InteractiveRunner.html'
+  NAME = 'Speedometer2'
+
+  def __init__(self, ps, should_filter_suites, filtered_suite_names=None,
+               enable_smoke_test_mode=False):
+    super(Speedometer2Story, self).__init__(ps)
+    self._should_filter_suites = should_filter_suites
+    self._filtered_suite_names = filtered_suite_names
+    self._enable_smoke_test_mode = enable_smoke_test_mode
+    self._enabled_suites = []
+
+  @staticmethod
+  def GetFullSuiteName(name):
+    return _SPEEDOMETER_SUITE_NAME_BASE.format(name)
+
+  @staticmethod
+  def GetSuites(suite_regex):
+    if not suite_regex:
+      return []
+    exp = re.compile(suite_regex)
+    return [name for name in _SPEEDOMETER_SUITES
+            if exp.search(Speedometer2Story.GetFullSuiteName(name))]
+
+  def ExecuteTest(self, action_runner):
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
+    iterationCount = 10
+    # A single iteration on android takes ~75 seconds, the benchmark times out
+    # when running for 10 iterations.
+    if action_runner.tab.browser.platform.GetOSName() == 'android':
+      iterationCount = 3
+    # For a smoke test one iteration is sufficient
+    if self._enable_smoke_test_mode:
+      iterationCount = 1
+
+    if self._should_filter_suites:
+      action_runner.ExecuteJavaScript("""
+        Suites.forEach(function(suite) {
+          suite.disabled = {{ filtered_suites }}.indexOf(suite.name) < 0;
+        });
+      """, filtered_suites=self._filtered_suites)
+
+    self._enabled_suites = action_runner.EvaluateJavaScript("""
+      (function() {
+        var suitesNames = [];
+        Suites.forEach(function(s) {
+          if (!s.disabled)
+            suitesNames.push(s.name);
+        });
+        return suitesNames;
+       })();""")
+
+    action_runner.ExecuteJavaScript("""
+        // Store all the results in the benchmarkClient
+        var testDone = false;
+        var iterationCount = {{ count }};
+        var benchmarkClient = {};
+        var suiteValues = [];
+        benchmarkClient.didRunSuites = function(measuredValues) {
+          suiteValues.push(measuredValues);
+        };
+        benchmarkClient.didFinishLastIteration = function () {
+          testDone = true;
+        };
+        var runner = new BenchmarkRunner(Suites, benchmarkClient);
+        runner.runMultipleIterations(iterationCount);
+        """,
+        count=iterationCount)
+    action_runner.WaitForJavaScriptCondition('testDone', timeout=600)
+
+
+  def ParseTestResults(self, action_runner):
+    if not self._should_filter_suites:
+      self.AddJavascriptMetricValue(list_of_scalar_values.ListOfScalarValues(
+          self, 'Total', 'ms',
+          action_runner.EvaluateJavaScript(
+              'suiteValues.map(each => each.total)'),
+          important=True))
+      self.AddJavascriptMetricValue(list_of_scalar_values.ListOfScalarValues(
+          self, 'RunsPerMinute', 'score',
+          action_runner.EvaluateJavaScript(
+              'suiteValues.map(each => each.score)'),
+          important=True))
+
+    # Extract the timings for each suite
+    for suite_name in self._enabled_suites:
+      self.AddJavascriptMetricValue(list_of_scalar_values.ListOfScalarValues(
+          self, suite_name, 'ms',
+          action_runner.EvaluateJavaScript("""
+              var suite_times = [];
+              for(var i = 0; i < iterationCount; i++) {
+                suite_times.push(
+                    suiteValues[i].tests[{{ key }}].total);
+              };
+              suite_times;
+              """,
+              key=suite_name), important=False))
+
diff --git a/tools/perf/page_sets/speedometer_pages.py b/tools/perf/page_sets/speedometer_pages.py
new file mode 100644
index 0000000..564d1bc
--- /dev/null
+++ b/tools/perf/page_sets/speedometer_pages.py
@@ -0,0 +1,79 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import story
+
+from telemetry.value import list_of_scalar_values
+
+from page_sets import press_story
+
+class SpeedometerStory(press_story.PressStory):
+  URL='http://browserbench.org/Speedometer/'
+
+  enabled_suites = [
+      'VanillaJS-TodoMVC',
+      'EmberJS-TodoMVC',
+      'BackboneJS-TodoMVC',
+      'jQuery-TodoMVC',
+      'AngularJS-TodoMVC',
+      'React-TodoMVC',
+      'FlightJS-TodoMVC'
+  ]
+
+  def ExecuteTest(self, action_runner):
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
+    iterationCount = 10
+    # A single iteration on android takes ~75 seconds, the benchmark times out
+    # when running for 10 iterations.
+    if action_runner.tab.browser.platform.GetOSName() == 'android':
+      iterationCount = 3
+
+    action_runner.ExecuteJavaScript("""
+        // Store all the results in the benchmarkClient
+        benchmarkClient._measuredValues = []
+        benchmarkClient.didRunSuites = function(measuredValues) {
+          benchmarkClient._measuredValues.push(measuredValues);
+          benchmarkClient._timeValues.push(measuredValues.total);
+        };
+        benchmarkClient.iterationCount = {{ count }};
+        startTest();
+        """,
+        count=iterationCount)
+    action_runner.WaitForJavaScriptCondition(
+        'benchmarkClient._finishedTestCount == benchmarkClient.testsCount',
+        timeout=600)
+
+  def ParseTestResults(self, action_runner):
+    self.AddJavascriptMetricValue(list_of_scalar_values.ListOfScalarValues(
+        self, 'Total', 'ms',
+        action_runner.EvaluateJavaScript('benchmarkClient._timeValues'),
+        important=True))
+    self.AddJavascriptMetricValue(list_of_scalar_values.ListOfScalarValues(
+        self, 'RunsPerMinute', 'score',
+        action_runner.EvaluateJavaScript(
+            '[parseFloat(document.getElementById("result-number").innerText)];'
+        ),
+        important=True))
+
+    # Extract the timings for each suite
+    for suite_name in self.enabled_suites:
+      self.AddJavascriptMetricValue(list_of_scalar_values.ListOfScalarValues(
+          self, suite_name, 'ms',
+          action_runner.EvaluateJavaScript("""
+              var suite_times = [];
+              for(var i = 0; i < benchmarkClient.iterationCount; i++) {
+                suite_times.push(
+                    benchmarkClient._measuredValues[i].tests[{{ key }}].total);
+              };
+              suite_times;
+              """,
+              key=suite_name), important=False))
+
+
+class SpeedometerStorySet(story.StorySet):
+  def __init__(self):
+    super(SpeedometerStorySet, self).__init__(
+        archive_data_file='data/speedometer.json',
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
+
+    self.AddStory(SpeedometerStory(self))
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index 384687a..0eb8288 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -596,6 +596,23 @@
   TAGS = [story_tags.JAVASCRIPT_HEAVY, story_tags.YEAR_2016]
 
 
+class YouTubeDesktopStory2018(_MediaBrowsingStory):
+  """Load a typical YouTube video then navigate to a next few videos. Stop and
+  watch each video for a few seconds.
+  """
+  NAME = 'browse:media:youtube:2018'
+  URL = 'https://www.youtube.com/watch?v=QGfhS1hfTWw&autoplay=0'
+  ITEM_SELECTOR = 'ytd-compact-video-renderer.ytd-watch-next-secondary-results-renderer a'
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+  IS_SINGLE_PAGE_APP = True
+  # A longer view time allows videos to load and play.
+  ITEM_VIEW_TIME_IN_SECONDS = 5
+  ITEMS_TO_VISIT = 8
+  ITEM_SELECTOR_INDEX = 3
+  PLATFORM_SPECIFIC = True
+  TAGS = [story_tags.JAVASCRIPT_HEAVY, story_tags.YEAR_2018]
+
+
 class FacebookPhotosMobileStory(_MediaBrowsingStory):
   """Load a photo page from Rihanna's facebook page then navigate a few next
   photos.
@@ -663,6 +680,7 @@
     action_runner.Wait(1)  # To make browsing more realistic.
 
 
+
 class PinterestDesktopStory(_MediaBrowsingStory):
   NAME = 'browse:media:pinterest'
   URL = 'https://pinterest.com'
@@ -701,6 +719,51 @@
     action_runner.Wait(1)  # Wait to make navigation realistic.
 
 
+class PinterestDesktopStory2018(_MediaBrowsingStory):
+  NAME = 'browse:media:pinterest:2018'
+  URL = 'https://pinterest.com'
+  ITEM_SELECTOR = '.pinWrapper a[data-force-refresh="1"]'
+  ITEM_VIEW_TIME = 5
+  IS_SINGLE_PAGE_APP = True
+  ITEMS_TO_VISIT = 8
+  INCREMENT_INDEX_AFTER_EACH_ITEM = True
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+  TAGS = [story_tags.YEAR_2018]
+  # SKIP_LOGIN = False
+
+  def _Login(self, action_runner):
+    pinterest_login.LoginDesktopAccount(action_runner, 'googletest')
+
+  def _ViewMediaItem(self, action_runner, index):
+    super(PinterestDesktopStory2018, self)._ViewMediaItem(action_runner, index)
+    # 1. click on item
+    # 2. pin every other item
+    # 3. go back to the main page
+    action_runner.Wait(1)  # Wait to make navigation realistic.
+    if index % 2 == 0:
+      if not self.SKIP_LOGIN:
+        action_runner.Wait(2)
+      action_runner.WaitForElement(selector='.SaveButton')
+      action_runner.ClickElement(selector='.SaveButton')
+      if not self.SKIP_LOGIN:
+        action_runner.Wait(2)
+      action_runner.Wait(2.5)
+      action_runner.WaitForElement(
+                  selector='div[data-test-id=BoardPickerSaveButton]')
+      action_runner.ClickElement(
+                  selector='div[data-test-id=BoardPickerSaveButton]')
+      action_runner.Wait(1.5)
+    action_runner.Wait(1)
+    if not self.SKIP_LOGIN:
+      action_runner.Wait(2)
+    action_runner.NavigateBack()
+
+    action_runner.WaitForElement(selector='input[name=searchBoxInput]')
+    action_runner.Wait(1)
+    if not self.SKIP_LOGIN:
+      action_runner.Wait(2)
+
+
 ##############################################################################
 # Emerging market browsing stories.
 ##############################################################################
diff --git a/tools/perf/test_results/analysis.py b/tools/perf/test_results/analysis.py
index 6f319d6..b082044 100644
--- a/tools/perf/test_results/analysis.py
+++ b/tools/perf/test_results/analysis.py
@@ -4,12 +4,8 @@
 
 import fnmatch
 
-try:
-  import numpy
-  import pandas
-except ImportError:
-  numpy = None
-  pandas = None
+import numpy  # pylint: disable=import-error
+import pandas  # pylint: disable=import-error
 
 
 SECONDS_IN_A_DAY = 60 * 60 * 24
diff --git a/tools/perf/test_results/analysis_unittest.py b/tools/perf/test_results/analysis_unittest.py
index 80bb14f..7ab2515 100644
--- a/tools/perf/test_results/analysis_unittest.py
+++ b/tools/perf/test_results/analysis_unittest.py
@@ -8,7 +8,6 @@
 from test_results import frames
 
 
-@unittest.skipIf(frames.pandas is None, 'pandas module not available')
 class TestAnalysis(unittest.TestCase):
   def testFilterBy(self):
     builders = frames.pandas.DataFrame.from_records([
diff --git a/tools/perf/test_results/core.py b/tools/perf/test_results/core.py
index ef5f320..55b0a84b 100644
--- a/tools/perf/test_results/core.py
+++ b/tools/perf/test_results/core.py
@@ -4,18 +4,11 @@
 
 import datetime
 import hashlib
-import sys
 
 from test_results import api
 from test_results import frames
 
 
-def CheckDependencies():
-  """Check that module dependencies are satisfied, otherwise exit with error."""
-  if frames.pandas is None:
-    sys.exit('ERROR: This tool requires pandas to run, try: pip install pandas')
-
-
 def GetBuilders():
   """Get the builders data frame and keep a cached copy."""
   def make_frame():
diff --git a/tools/perf/test_results/frames.py b/tools/perf/test_results/frames.py
index 38d4a3d8..04631d4 100644
--- a/tools/perf/test_results/frames.py
+++ b/tools/perf/test_results/frames.py
@@ -7,10 +7,7 @@
 import datetime
 import os
 
-try:
-  import pandas
-except ImportError:
-  pandas = None
+import pandas  # pylint: disable=import-error
 
 
 CACHE_DIR = os.path.normpath(
diff --git a/tools/perf/test_results/frames_unittest.py b/tools/perf/test_results/frames_unittest.py
index a47c7ef..6f66c5d 100644
--- a/tools/perf/test_results/frames_unittest.py
+++ b/tools/perf/test_results/frames_unittest.py
@@ -13,7 +13,6 @@
 from test_results import frames
 
 
-@unittest.skipIf(frames.pandas is None, 'pandas module not available')
 class TestDataFrames(unittest.TestCase):
   def testBuildersDataFrame(self):
     sample_data = {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index dab5eb2..7803b0f 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -70,7 +70,7 @@
  <item id="data_reduction_proxy_pingback" hash_code="68561428" type="0" content_hash_code="78407792" os_list="linux,windows" file_path="components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc"/>
  <item id="data_reduction_proxy_secure_proxy_check" hash_code="131236802" type="0" content_hash_code="122297136" os_list="linux,windows" file_path="components/data_reduction_proxy/core/browser/secure_proxy_checker.cc"/>
  <item id="data_reduction_proxy_warmup" hash_code="8250451" type="0" content_hash_code="6321249" os_list="linux,windows" file_path="components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc"/>
- <item id="desktop_ios_promotion" hash_code="13694792" type="0" content_hash_code="19776951" os_list="windows" file_path="chrome/browser/ui/desktop_ios_promotion/sms_service.cc"/>
+ <item id="desktop_ios_promotion" hash_code="13694792" type="0" deprecated="2018-11-04" content_hash_code="19776951" file_path=""/>
  <item id="device_geolocation_request" hash_code="77673751" type="0" deprecated="2017-10-20" content_hash_code="97181773" file_path=""/>
  <item id="device_management_service" hash_code="117782019" type="0" content_hash_code="127535409" os_list="linux,windows" file_path="components/policy/core/common/cloud/device_management_service.cc"/>
  <item id="devtools_free_data_source" hash_code="22774132" type="0" content_hash_code="35733000" os_list="linux,windows" file_path="chrome/browser/ui/webui/devtools_ui.cc"/>
@@ -271,6 +271,7 @@
  <item id="url_fetcher_downloader" hash_code="113231892" type="0" content_hash_code="61085066" os_list="linux,windows" file_path="components/update_client/url_fetcher_downloader.cc"/>
  <item id="url_prevision_fetcher" hash_code="118389509" type="0" content_hash_code="66145513" os_list="linux,windows" file_path="content/browser/media/url_provision_fetcher.cc"/>
  <item id="user_info_fetcher" hash_code="22265491" type="0" content_hash_code="72016232" os_list="linux,windows" file_path="components/policy/core/common/cloud/user_info_fetcher.cc"/>
+ <item id="viz_devtools_server" hash_code="16292315" type="0" content_hash_code="70061664" os_list="linux,windows" file_path="components/ui_devtools/devtools_server.cc"/>
  <item id="web_history_counter" hash_code="137457845" type="1" second_id="110307337" content_hash_code="49663381" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/counters/history_counter.cc"/>
  <item id="web_history_expire" hash_code="60946824" type="1" second_id="110307337" content_hash_code="92626030" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/history/core/browser/browsing_history_service.cc"/>
  <item id="web_history_expire_between_dates" hash_code="126122632" type="1" second_id="110307337" content_hash_code="34304787" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/history/core/browser/history_service.cc"/>